difftreelog
perf O(1) std.reverse, std.range
in: master
3 files changed
crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -11,6 +11,7 @@
};
use crate::{Either, ObjValue};
use format::{format_arr, format_obj};
+use gcmodule::Cc;
use jrsonnet_interner::IStr;
use serde::Deserialize;
use serde_yaml::DeserializingQuirks;
@@ -142,11 +143,11 @@
}
#[jrsonnet_macros::builtin]
-fn builtin_length(x: Either![IStr, VecVal, ObjValue, FuncVal]) -> Result<usize> {
+fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> Result<usize> {
use Either4::*;
Ok(match x {
A(x) => x.chars().count(),
- B(x) => x.0.len(),
+ B(x) => x.len(),
C(x) => x
.fields_visibility()
.into_iter()
@@ -167,7 +168,7 @@
for i in 0..sz {
out.push(func.evaluate_simple(&[i as f64].as_slice())?)
}
- Ok(VecVal(out))
+ Ok(VecVal(Cc::new(out)))
}
#[jrsonnet_macros::builtin]
@@ -178,7 +179,9 @@
#[jrsonnet_macros::builtin]
fn builtin_object_fields_ex(obj: ObjValue, inc_hidden: bool) -> Result<VecVal> {
let out = obj.fields_ex(inc_hidden);
- Ok(VecVal(out.into_iter().map(Val::Str).collect::<Vec<_>>()))
+ Ok(VecVal(Cc::new(
+ out.into_iter().map(Val::Str).collect::<Vec<_>>(),
+ )))
}
#[jrsonnet_macros::builtin]
@@ -432,15 +435,11 @@
}
#[jrsonnet_macros::builtin]
-fn builtin_range(from: i32, to: i32) -> Result<VecVal> {
+fn builtin_range(from: i32, to: i32) -> Result<ArrValue> {
if to < from {
- return Ok(VecVal(Vec::new()));
+ return Ok(ArrValue::new_eager());
}
- let mut out = Vec::with_capacity((1 + to as usize - from as usize).max(0));
- for i in from as usize..=to as usize {
- out.push(Val::Num(i as f64));
- }
- Ok(VecVal(out))
+ Ok(ArrValue::new_range(from, to))
}
#[jrsonnet_macros::builtin]
crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth285}285}286286287/// Specialization, provides faster TryFrom<VecVal> for Val287/// Specialization, provides faster TryFrom<VecVal> for Val288pub struct VecVal(pub Vec<Val>);288pub struct VecVal(pub Cc<Vec<Val>>);289289290impl Typed for VecVal {290impl Typed for VecVal {291 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);291 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);296 fn try_from(value: Val) -> Result<Self> {296 fn try_from(value: Val) -> Result<Self> {297 <Self as Typed>::TYPE.check(&value)?;297 <Self as Typed>::TYPE.check(&value)?;298 match value {298 match value {299 Val::Arr(a) => Ok(Self(a.evaluated()?.to_vec())),299 Val::Arr(a) => Ok(Self(a.evaluated()?)),300 _ => unreachable!(),300 _ => unreachable!(),301 }301 }302 }302 }305 type Error = LocError;305 type Error = LocError;306306307 fn try_from(value: VecVal) -> Result<Self> {307 fn try_from(value: VecVal) -> Result<Self> {308 Ok(Self::Arr(value.0.into()))308 Ok(Self::Arr(ArrValue::Eager(value.0)))309 }309 }310}310}311311crates/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> {