git.delta.rocks / jrsonnet / refs/commits / 69d179bf913a

difftreelog

perf O(1) std.reverse, std.range

Yaroslav Bolyukin2022-04-20parent: #629c80c.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
11};11};
12use crate::{Either, ObjValue};12use crate::{Either, ObjValue};
13use format::{format_arr, format_obj};13use format::{format_arr, format_obj};
14use gcmodule::Cc;
14use jrsonnet_interner::IStr;15use jrsonnet_interner::IStr;
15use serde::Deserialize;16use serde::Deserialize;
16use serde_yaml::DeserializingQuirks;17use serde_yaml::DeserializingQuirks;
142}143}
143144
144#[jrsonnet_macros::builtin]145#[jrsonnet_macros::builtin]
145fn builtin_length(x: Either![IStr, VecVal, ObjValue, FuncVal]) -> Result<usize> {146fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> Result<usize> {
146 use Either4::*;147 use Either4::*;
147 Ok(match x {148 Ok(match x {
148 A(x) => x.chars().count(),149 A(x) => x.chars().count(),
149 B(x) => x.0.len(),150 B(x) => x.len(),
150 C(x) => x151 C(x) => x
151 .fields_visibility()152 .fields_visibility()
152 .into_iter()153 .into_iter()
167 for i in 0..sz {168 for i in 0..sz {
168 out.push(func.evaluate_simple(&[i as f64].as_slice())?)169 out.push(func.evaluate_simple(&[i as f64].as_slice())?)
169 }170 }
170 Ok(VecVal(out))171 Ok(VecVal(Cc::new(out)))
171}172}
172173
173#[jrsonnet_macros::builtin]174#[jrsonnet_macros::builtin]
178#[jrsonnet_macros::builtin]179#[jrsonnet_macros::builtin]
179fn builtin_object_fields_ex(obj: ObjValue, inc_hidden: bool) -> Result<VecVal> {180fn builtin_object_fields_ex(obj: ObjValue, inc_hidden: bool) -> Result<VecVal> {
180 let out = obj.fields_ex(inc_hidden);181 let out = obj.fields_ex(inc_hidden);
181 Ok(VecVal(out.into_iter().map(Val::Str).collect::<Vec<_>>()))182 Ok(VecVal(Cc::new(
183 out.into_iter().map(Val::Str).collect::<Vec<_>>(),
184 )))
182}185}
183186
184#[jrsonnet_macros::builtin]187#[jrsonnet_macros::builtin]
432}435}
433436
434#[jrsonnet_macros::builtin]437#[jrsonnet_macros::builtin]
435fn builtin_range(from: i32, to: i32) -> Result<VecVal> {438fn builtin_range(from: i32, to: i32) -> Result<ArrValue> {
436 if to < from {439 if to < from {
437 return Ok(VecVal(Vec::new()));440 return Ok(ArrValue::new_eager());
438 }441 }
439 let mut out = Vec::with_capacity((1 + to as usize - from as usize).max(0));442 Ok(ArrValue::new_range(from, to))
440 for i in from as usize..=to as usize {
441 out.push(Val::Num(i as f64));
442 }
443 Ok(VecVal(out))
444}443}
445444
446#[jrsonnet_macros::builtin]445#[jrsonnet_macros::builtin]
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/typed/conversions.rs
+++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs
@@ -285,7 +285,7 @@
 }
 
 /// Specialization, provides faster TryFrom<VecVal> for Val
-pub struct VecVal(pub Vec<Val>);
+pub struct VecVal(pub Cc<Vec<Val>>);
 
 impl Typed for VecVal {
 	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);
@@ -296,7 +296,7 @@
 	fn try_from(value: Val) -> Result<Self> {
 		<Self as Typed>::TYPE.check(&value)?;
 		match value {
-			Val::Arr(a) => Ok(Self(a.evaluated()?.to_vec())),
+			Val::Arr(a) => Ok(Self(a.evaluated()?)),
 			_ => unreachable!(),
 		}
 	}
@@ -305,7 +305,7 @@
 	type Error = LocError;
 
 	fn try_from(value: VecVal) -> Result<Self> {
-		Ok(Self::Arr(value.0.into()))
+		Ok(Self::Arr(ArrValue::Eager(value.0)))
 	}
 }
 
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -178,11 +178,17 @@
 	Lazy(Cc<Vec<LazyVal>>),
 	Eager(Cc<Vec<Val>>),
 	Extended(Box<(Self, Self)>),
+	Range(i32, i32),
+	Reversed(Box<Self>),
 }
 impl ArrValue {
 	pub fn new_eager() -> Self {
 		Self::Eager(Cc::new(Vec::new()))
 	}
+	pub fn new_range(a: i32, b: i32) -> Self {
+		assert!(a <= b);
+		Self::Range(a, b)
+	}
 
 	pub fn len(&self) -> usize {
 		match self {
@@ -190,6 +196,8 @@
 			Self::Lazy(l) => l.len(),
 			Self::Eager(e) => e.len(),
 			Self::Extended(v) => v.0.len() + v.1.len(),
+			Self::Range(a, b) => a.abs_diff(*b) as usize,
+			Self::Reversed(i) => i.len(),
 		}
 	}
 
@@ -218,6 +226,19 @@
 					v.1.get(index - a_len)
 				}
 			}
+			Self::Range(a, _) => {
+				if index >= self.len() {
+					return Ok(None);
+				}
+				Ok(Some(Val::Num(((*a as isize) + index as isize) as f64)))
+			}
+			Self::Reversed(v) => {
+				let len = v.len();
+				if index >= len {
+					return Ok(None);
+				}
+				v.get(len - index - 1)
+			}
 		}
 	}
 
@@ -236,6 +257,21 @@
 					v.1.get_lazy(index - a_len)
 				}
 			}
+			Self::Range(a, _) => {
+				if index >= self.len() {
+					return None;
+				}
+				Some(LazyVal::new_resolved(Val::Num(
+					((*a as isize) + index as isize) as f64,
+				)))
+			}
+			Self::Reversed(v) => {
+				let len = v.len();
+				if index >= len {
+					return None;
+				}
+				v.get_lazy(len - index - 1)
+			}
 		}
 	}
 
@@ -263,46 +299,50 @@
 				}
 				Cc::new(out)
 			}
+			Self::Range(a, b) => {
+				let mut out = Vec::with_capacity(self.len());
+				for i in *a..*b {
+					out.push(Val::Num(i as f64));
+				}
+				Cc::new(out)
+			}
+			Self::Reversed(r) => {
+				let mut r = r.evaluated()?;
+				Cc::update_with(&mut r, |v| v.reverse());
+				r
+			}
 		})
 	}
 
 	pub fn iter(&self) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {
-		(0..self.len()).map(move |idx| match self {
+		// if let Self::Reversed(v) = self {
+		// 	return v.iter().rev();
+		// }
+		let len = self.len();
+		(0..len).map(move |idx| match self {
 			Self::Bytes(b) => Ok(Val::Num(b[idx] as f64)),
 			Self::Lazy(l) => l[idx].evaluate(),
 			Self::Eager(e) => Ok(e[idx].clone()),
 			Self::Extended(_) => self.get(idx).map(|e| e.unwrap()),
+			Self::Range(..) => self.get(idx).map(|e| e.unwrap()),
+			Self::Reversed(..) => self.get(len - idx - 1).map(|e| e.unwrap()),
 		})
 	}
 
 	pub fn iter_lazy(&self) -> impl DoubleEndedIterator<Item = LazyVal> + '_ {
-		(0..self.len()).map(move |idx| match self {
+		let len = self.len();
+		(0..len).map(move |idx| match self {
 			Self::Bytes(b) => LazyVal::new_resolved(Val::Num(b[idx] as f64)),
 			Self::Lazy(l) => l[idx].clone(),
 			Self::Eager(e) => LazyVal::new_resolved(e[idx].clone()),
 			Self::Extended(_) => self.get_lazy(idx).unwrap(),
+			Self::Range(..) => self.get_lazy(idx).unwrap(),
+			Self::Reversed(..) => self.get_lazy(len - idx - 1).unwrap(),
 		})
 	}
 
 	pub fn reversed(self) -> Self {
-		match self {
-			Self::Bytes(b) => {
-				let mut out = b.to_vec();
-				out.reverse();
-				Self::Bytes(out.into())
-			}
-			Self::Lazy(vec) => {
-				let mut out = (&vec as &Vec<_>).clone();
-				out.reverse();
-				Self::Lazy(Cc::new(out))
-			}
-			Self::Eager(vec) => {
-				let mut out = (&vec as &Vec<_>).clone();
-				out.reverse();
-				Self::Eager(Cc::new(out))
-			}
-			Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),
-		}
+		Self::Reversed(Box::new(self))
 	}
 
 	pub fn map(self, mapper: impl Fn(Val) -> Result<Val>) -> Result<Self> {