difftreelog
perf O(1) std.reverse, std.range
in: master
3 files changed
crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth11};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}143144144#[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) => x151 .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}172173173#[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}183186184#[jrsonnet_macros::builtin]187#[jrsonnet_macros::builtin]432}435}433436434#[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}445444446#[jrsonnet_macros::builtin]445#[jrsonnet_macros::builtin]crates/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)))
}
}
crates/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> {