difftreelog
refactor move arrays to use dyn ArrayLike
in: master
8 files changed
crates/jrsonnet-evaluator/src/arr/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/arr/mod.rs
+++ b/crates/jrsonnet-evaluator/src/arr/mod.rs
@@ -1,44 +1,20 @@
-use std::rc::Rc;
+use std::any::Any;
use jrsonnet_gcmodule::{Cc, Trace};
use jrsonnet_interner::IBytes;
use jrsonnet_parser::LocExpr;
-use crate::{function::FuncVal, Context, Result, Thunk, Val};
+use crate::{function::FuncVal, gc::TraceBox, tb, Context, Result, Thunk, Val};
mod spec;
-use spec::*;
+pub use spec::ArrayLike;
+pub(crate) use spec::*;
/// Represents a Jsonnet array value.
#[derive(Debug, Clone, Trace)]
// may contrain other ArrValue
#[trace(tracking(force))]
-pub enum ArrValue {
- /// Layout optimized byte array.
- Bytes(BytesArray),
- /// Layout optimized char array.
- Chars(CharArray),
- /// Every element is lazy evaluated.
- Lazy(LazyArray),
- /// Every element is defined somewhere in source code
- Expr(ExprArray),
- /// Every field is already evaluated.
- Eager(EagerArray),
- /// Concatenation of two arrays of any kind.
- Extended(Cc<ExtendedArray>),
- /// Represents a integer array in form `[start, start + 1, ... end - 1, end]`.
- /// This kind of arrays is generated by `std.range(start, end)` call, and used for loops.
- Range(RangeArray),
- /// Sliced array view.
- Slice(Cc<SliceArray>),
- /// Reversed array view.
- /// Returned by `std.reverse(other)` call
- Reverse(Cc<ReverseArray>),
- /// Returned by `std.map` call
- Mapped(MappedArray),
- /// Returned by `std.repeat` call
- Repeated(RepeatedArray),
-}
+pub struct ArrValue(Cc<TraceBox<dyn ArrayLike>>);
pub trait ArrayLikeIter<T>: Iterator<Item = T> + DoubleEndedIterator + ExactSizeIterator {}
impl<I, T> ArrayLikeIter<T> for I where
@@ -47,36 +23,39 @@
}
impl ArrValue {
+ pub fn new(v: impl ArrayLike) -> Self {
+ Self(Cc::new(tb!(v)))
+ }
pub fn empty() -> Self {
- Self::Range(RangeArray::empty())
+ Self::new(RangeArray::empty())
}
pub fn expr(ctx: Context, exprs: impl IntoIterator<Item = LocExpr>) -> Self {
- Self::Expr(ExprArray::new(ctx, exprs))
+ Self::new(ExprArray::new(ctx, exprs))
}
- pub fn lazy(thunks: Cc<Vec<Thunk<Val>>>) -> Self {
- Self::Lazy(LazyArray(thunks))
+ pub fn lazy(thunks: Vec<Thunk<Val>>) -> Self {
+ Self::new(LazyArray(thunks))
}
pub fn eager(values: Vec<Val>) -> Self {
- Self::Eager(EagerArray(Cc::new(values)))
+ Self::new(EagerArray(values))
}
pub fn repeated(data: ArrValue, repeats: usize) -> Option<Self> {
- Some(Self::Repeated(RepeatedArray::new(data, repeats)?))
+ Some(Self::new(RepeatedArray::new(data, repeats)?))
}
pub fn bytes(bytes: IBytes) -> Self {
- Self::Bytes(BytesArray(bytes))
+ Self::new(BytesArray(bytes))
}
pub fn chars(chars: impl Iterator<Item = char>) -> Self {
- Self::Chars(CharArray(Rc::new(chars.collect())))
+ Self::new(CharArray(chars.collect()))
}
#[must_use]
pub fn map(self, mapper: FuncVal) -> Self {
- Self::Mapped(MappedArray::new(self, mapper))
+ Self::new(MappedArray::new(self, mapper))
}
pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {
@@ -100,7 +79,7 @@
} else if b.is_empty() {
a
} else if a.len() + b.len() > ARR_EXTEND_THRESHOLD {
- Self::Extended(Cc::new(ExtendedArray::new(a, b)))
+ Self::new(ExtendedArray::new(a, b))
} else if let (Some(a), Some(b)) = (a.iter_cheap(), b.iter_cheap()) {
let mut out = Vec::with_capacity(a.len() + b.len());
out.extend(a);
@@ -110,15 +89,15 @@
let mut out = Vec::with_capacity(a.len() + b.len());
out.extend(a.iter_lazy());
out.extend(b.iter_lazy());
- Self::lazy(Cc::new(out))
+ Self::lazy(out)
}
}
pub fn range_exclusive(a: i32, b: i32) -> Self {
- Self::Range(RangeArray::new_exclusive(a, b))
+ Self::new(RangeArray::new_exclusive(a, b))
}
pub fn range_inclusive(a: i32, b: i32) -> Self {
- Self::Range(RangeArray::new_inclusive(a, b))
+ Self::new(RangeArray::new_inclusive(a, b))
}
#[must_use]
@@ -136,53 +115,42 @@
if from >= to || step == 0 {
return None;
}
- // match self {
- // ArrValue::Slice(slice) => {
- // return Some(Self::Slice(Cc::new(SliceArray {
- // inner: slice.inner.clone(),
- // from: slice.from + slice.step * (from as u32),
- // to: slice.from + (to as u32) * slice.step,
- // step: slice.step * step as u32,
- // })))
- // }
- // _ => {}
- // }
- Some(Self::Slice(Cc::new(SliceArray {
+ Some(Self::new(SliceArray {
inner: self,
from: from as u32,
to: to as u32,
step: step as u32,
- })))
+ }))
}
/// Array length.
pub fn len(&self) -> usize {
- pass!(self.len())
+ self.0.len()
}
/// Is array contains no elements?
pub fn is_empty(&self) -> bool {
- pass!(self.is_empty())
+ self.0.is_empty()
}
/// Get array element by index, evaluating it, if it is lazy.
///
/// Returns `None` on out-of-bounds condition.
pub fn get(&self, index: usize) -> Result<Option<Val>> {
- pass!(self.get(index))
+ self.0.get(index)
}
/// Returns None if get is either non cheap, or out of bounds
fn get_cheap(&self, index: usize) -> Option<Val> {
- pass!(self.get_cheap(index))
+ self.0.get_cheap(index)
}
/// Get array element by index, without evaluation.
///
/// Returns `None` on out-of-bounds condition.
pub fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
- pass!(self.get_lazy(index))
+ self.0.get_lazy(index)
}
pub fn iter(&self) -> impl ArrayLikeIter<Result<Val>> + '_ {
@@ -205,33 +173,20 @@
/// Return a reversed view on current array.
#[must_use]
pub fn reversed(self) -> Self {
- Self::Reverse(Cc::new(ReverseArray(self)))
+ Self::new(ReverseArray(self))
}
pub fn ptr_eq(a: &Self, b: &Self) -> bool {
- match (a, b) {
- (ArrValue::Bytes(a), ArrValue::Bytes(b)) => a.0 == b.0,
- (ArrValue::Lazy(a), ArrValue::Lazy(b)) => Cc::ptr_eq(&a.0, &b.0),
- (ArrValue::Expr(a), ArrValue::Expr(b)) => Cc::ptr_eq(&a.0, &b.0),
- (ArrValue::Eager(a), ArrValue::Eager(b)) => Cc::ptr_eq(&a.0, &b.0),
- (ArrValue::Extended(a), ArrValue::Extended(b)) => Cc::ptr_eq(a, b),
- (ArrValue::Range(a), ArrValue::Range(b)) => a == b,
- _ => false,
- }
+ Cc::ptr_eq(&a.0, &b.0)
}
/// Is this vec supports `.get_cheap()?`
pub fn is_cheap(&self) -> bool {
- match self {
- ArrValue::Eager(_) | ArrValue::Range(..) | ArrValue::Bytes(_) | ArrValue::Chars(_) => {
- true
- }
- ArrValue::Extended(v) => v.a.is_cheap() && v.b.is_cheap(),
- ArrValue::Slice(r) => r.inner.is_cheap(),
- ArrValue::Reverse(i) => i.0.is_cheap(),
- ArrValue::Repeated(v) => v.is_cheap(),
- ArrValue::Expr(_) | ArrValue::Lazy(_) | ArrValue::Mapped(_) => false,
- }
+ self.0.is_cheap()
+ }
+
+ pub fn as_any(&self) -> &dyn Any {
+ &self.0
}
}
impl From<Vec<Val>> for ArrValue {
@@ -241,7 +196,7 @@
}
impl From<Vec<Thunk<Val>>> for ArrValue {
fn from(value: Vec<Thunk<Val>>) -> Self {
- Self::lazy(Cc::new(value))
+ Self::lazy(value)
}
}
impl FromIterator<Val> for ArrValue {
@@ -249,6 +204,27 @@
Self::eager(iter.into_iter().collect())
}
}
+impl ArrayLike for ArrValue {
+ fn len(&self) -> usize {
+ self.0.len()
+ }
+ fn get(&self, index: usize) -> Result<Option<Val>> {
+ self.0.get(index)
+ }
+
+ fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
+ self.0.get_lazy(index)
+ }
+
+ fn get_cheap(&self, index: usize) -> Option<Val> {
+ self.0.get_cheap(index)
+ }
+
+ fn is_cheap(&self) -> bool {
+ self.0.is_cheap()
+ }
+}
+
#[cfg(target_pointer_width = "64")]
-static_assertions::assert_eq_size!(ArrValue, [u8; 16]);
+static_assertions::assert_eq_size!(ArrValue, [u8; 8]);
crates/jrsonnet-evaluator/src/arr/spec.rsdiffbeforeafterboth1use std::{cell::RefCell, iter, mem::replace, rc::Rc};23use jrsonnet_gcmodule::{Cc, Trace};4use jrsonnet_interner::{IBytes, IStr};5use jrsonnet_parser::LocExpr;67use super::ArrValue;8use crate::{9 error::ErrorKind::InfiniteRecursionDetected,10 evaluate,11 function::FuncVal,12 val::{StrValue, ThunkValue},13 Context, Error, Result, Thunk, Val,14};1516pub trait ArrayLike: Sized + Into<ArrValue> {17 fn len(&self) -> usize;18 fn is_empty(&self) -> bool {19 self.len() == 020 }21 fn get(&self, index: usize) -> Result<Option<Val>>;22 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>>;23 fn get_cheap(&self, index: usize) -> Option<Val>;2425 fn reverse(self) -> ArrValue {26 ArrValue::Reverse(Cc::new(ReverseArray(self.into())))27 }28}2930#[derive(Debug, Clone, Trace)]31pub struct SliceArray {32 pub(crate) inner: ArrValue,33 pub(crate) from: u32,34 pub(crate) to: u32,35 pub(crate) step: u32,36}3738impl SliceArray {39 fn iter(&self) -> impl Iterator<Item = Result<Val>> + '_ {40 self.inner41 .iter()42 .skip(self.from as usize)43 .take((self.to - self.from) as usize)44 .step_by(self.step as usize)45 }4647 fn iter_lazy(&self) -> impl Iterator<Item = Thunk<Val>> + '_ {48 self.inner49 .iter_lazy()50 .skip(self.from as usize)51 .take((self.to - self.from) as usize)52 .step_by(self.step as usize)53 }5455 fn iter_cheap(&self) -> Option<impl crate::arr::ArrayLikeIter<Val> + '_> {56 Some(57 self.inner58 .iter_cheap()?59 .skip(self.from as usize)60 .take((self.to - self.from) as usize)61 .step_by(self.step as usize),62 )63 }64}65impl ArrayLike for SliceArray {66 fn len(&self) -> usize {67 iter::repeat(())68 .take((self.to - self.from) as usize)69 .step_by(self.step as usize)70 .count()71 }7273 fn get(&self, index: usize) -> Result<Option<Val>> {74 self.iter().nth(index).transpose()75 }7677 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {78 self.iter_lazy().nth(index)79 }8081 fn get_cheap(&self, index: usize) -> Option<Val> {82 self.iter_cheap()?.nth(index)83 }84}85impl From<SliceArray> for ArrValue {86 fn from(value: SliceArray) -> Self {87 Self::Slice(Cc::new(value))88 }89}9091#[derive(Trace, Debug, Clone)]92pub struct CharArray(pub Rc<Vec<char>>);93impl ArrayLike for CharArray {94 fn len(&self) -> usize {95 self.0.len()96 }9798 fn get(&self, index: usize) -> Result<Option<Val>> {99 Ok(self.get_cheap(index))100 }101102 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {103 self.get_cheap(index).map(Thunk::evaluated)104 }105106 fn get_cheap(&self, index: usize) -> Option<Val> {107 self.0108 .get(index)109 .map(|v| Val::Str(StrValue::Flat(IStr::from(*v))))110 }111}112impl From<CharArray> for ArrValue {113 fn from(value: CharArray) -> Self {114 ArrValue::Chars(value)115 }116}117118#[derive(Trace, Debug, Clone)]119pub struct BytesArray(pub IBytes);120impl ArrayLike for BytesArray {121 fn len(&self) -> usize {122 self.0.len()123 }124125 fn get(&self, index: usize) -> Result<Option<Val>> {126 Ok(self.get_cheap(index))127 }128129 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {130 self.get_cheap(index).map(Thunk::evaluated)131 }132133 fn get_cheap(&self, index: usize) -> Option<Val> {134 self.0.get(index).map(|v| Val::Num(f64::from(*v)))135 }136}137impl From<BytesArray> for ArrValue {138 fn from(value: BytesArray) -> Self {139 ArrValue::Bytes(value)140 }141}142143#[derive(Debug, Trace, Clone)]144enum ArrayThunk<T: 'static + Trace> {145 Computed(Val),146 Errored(Error),147 Waiting(T),148 Pending,149}150151#[derive(Debug, Trace)]152pub struct ExprArrayInner {153 ctx: Context,154 cached: RefCell<Vec<ArrayThunk<LocExpr>>>,155}156#[derive(Debug, Trace, Clone)]157pub struct ExprArray(pub Cc<ExprArrayInner>);158impl ExprArray {159 pub fn new(ctx: Context, items: impl IntoIterator<Item = LocExpr>) -> Self {160 Self(Cc::new(ExprArrayInner {161 ctx,162 cached: RefCell::new(items.into_iter().map(ArrayThunk::Waiting).collect()),163 }))164 }165}166impl ArrayLike for ExprArray {167 fn len(&self) -> usize {168 self.0.cached.borrow().len()169 }170 fn get(&self, index: usize) -> Result<Option<Val>> {171 if index >= self.len() {172 return Ok(None);173 }174 match &self.0.cached.borrow()[index] {175 ArrayThunk::Computed(c) => return Ok(Some(c.clone())),176 ArrayThunk::Errored(e) => return Err(e.clone()),177 ArrayThunk::Pending => return Err(InfiniteRecursionDetected.into()),178 ArrayThunk::Waiting(..) => {}179 };180181 let ArrayThunk::Waiting(expr) =182 replace(&mut self.0.cached.borrow_mut()[index], ArrayThunk::Pending)183 else {184 unreachable!()185 };186187 let new_value = match evaluate(self.0.ctx.clone(), &expr) {188 Ok(v) => v,189 Err(e) => {190 self.0.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone());191 return Err(e);192 }193 };194 self.0.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone());195 Ok(Some(new_value))196 }197 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {198 #[derive(Trace)]199 struct ArrayElement {200 arr_thunk: ExprArray,201 index: usize,202 }203204 impl ThunkValue for ArrayElement {205 type Output = Val;206207 fn get(self: Box<Self>) -> Result<Self::Output> {208 self.arr_thunk209 .get(self.index)210 .transpose()211 .expect("index checked")212 }213 }214215 if index >= self.len() {216 return None;217 }218 match &self.0.cached.borrow()[index] {219 ArrayThunk::Computed(c) => return Some(Thunk::evaluated(c.clone())),220 ArrayThunk::Errored(e) => return Some(Thunk::errored(e.clone())),221 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}222 };223224 Some(Thunk::new(ArrayElement {225 arr_thunk: self.clone(),226 index,227 }))228 }229 fn get_cheap(&self, _index: usize) -> Option<Val> {230 None231 }232}233impl From<ExprArray> for ArrValue {234 fn from(value: ExprArray) -> Self {235 Self::Expr(value)236 }237}238239#[derive(Trace, Debug, Clone)]240pub struct ExtendedArray {241 pub a: ArrValue,242 pub b: ArrValue,243 split: usize,244 len: usize,245}246impl ExtendedArray {247 pub fn new(a: ArrValue, b: ArrValue) -> Self {248 let a_len = a.len();249 let b_len = b.len();250 Self {251 a,252 b,253 split: a_len,254 len: a_len.checked_add(b_len).expect("too large array value"),255 }256 }257}258259struct WithExactSize<I>(I, usize);260impl<I, T> Iterator for WithExactSize<I>261where262 I: Iterator<Item = T>,263{264 type Item = T;265266 fn next(&mut self) -> Option<Self::Item> {267 self.0.next()268 }269 fn nth(&mut self, n: usize) -> Option<Self::Item> {270 self.0.nth(n)271 }272 fn size_hint(&self) -> (usize, Option<usize>) {273 (self.1, Some(self.1))274 }275}276impl<I> DoubleEndedIterator for WithExactSize<I>277where278 I: DoubleEndedIterator,279{280 fn next_back(&mut self) -> Option<Self::Item> {281 self.0.next_back()282 }283 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {284 self.0.nth_back(n)285 }286}287impl<I> ExactSizeIterator for WithExactSize<I>288where289 I: Iterator,290{291 fn len(&self) -> usize {292 self.1293 }294}295impl ArrayLike for ExtendedArray {296 fn get(&self, index: usize) -> Result<Option<Val>> {297 if self.split > index {298 self.a.get(index)299 } else {300 self.b.get(index - self.split)301 }302 }303 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {304 if self.split > index {305 self.a.get_lazy(index)306 } else {307 self.b.get_lazy(index - self.split)308 }309 }310311 fn len(&self) -> usize {312 self.len313 }314315 fn get_cheap(&self, index: usize) -> Option<Val> {316 if self.split > index {317 self.a.get_cheap(index)318 } else {319 self.b.get_cheap(index - self.split)320 }321 }322}323impl From<ExtendedArray> for ArrValue {324 fn from(value: ExtendedArray) -> Self {325 Self::Extended(Cc::new(value))326 }327}328329#[derive(Trace, Debug, Clone)]330pub struct LazyArray(pub Cc<Vec<Thunk<Val>>>);331impl ArrayLike for LazyArray {332 fn len(&self) -> usize {333 self.0.len()334 }335 fn get(&self, index: usize) -> Result<Option<Val>> {336 let Some(v) = self.0.get(index) else {337 return Ok(None);338 };339 v.evaluate().map(Some)340 }341 fn get_cheap(&self, _index: usize) -> Option<Val> {342 None343 }344 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {345 self.0.get(index).cloned()346 }347}348impl From<LazyArray> for ArrValue {349 fn from(value: LazyArray) -> Self {350 Self::Lazy(value)351 }352}353354#[derive(Trace, Debug, Clone)]355pub struct EagerArray(pub Cc<Vec<Val>>);356impl ArrayLike for EagerArray {357 fn len(&self) -> usize {358 self.0.len()359 }360361 fn get(&self, index: usize) -> Result<Option<Val>> {362 Ok(self.0.get(index).cloned())363 }364365 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {366 self.0.get(index).cloned().map(Thunk::evaluated)367 }368369 fn get_cheap(&self, index: usize) -> Option<Val> {370 self.0.get(index).cloned()371 }372}373impl From<EagerArray> for ArrValue {374 fn from(value: EagerArray) -> Self {375 Self::Eager(value)376 }377}378379/// Inclusive range type380#[derive(Debug, Trace, Clone, PartialEq, Eq)]381pub struct RangeArray {382 start: i32,383 end: i32,384}385impl RangeArray {386 pub fn empty() -> Self {387 Self::new_exclusive(0, 0)388 }389 pub fn new_exclusive(start: i32, end: i32) -> Self {390 end.checked_sub(1)391 .map_or_else(Self::empty, |end| Self { start, end })392 }393 pub fn new_inclusive(start: i32, end: i32) -> Self {394 Self { start, end }395 }396 fn range(&self) -> impl Iterator<Item = i32> + ExactSizeIterator + DoubleEndedIterator {397 WithExactSize(398 self.start..=self.end,399 (self.end as usize)400 .wrapping_sub(self.start as usize)401 .wrapping_add(1),402 )403 }404}405406impl ArrayLike for RangeArray {407 fn len(&self) -> usize {408 self.range().len()409 }410 fn is_empty(&self) -> bool {411 self.range().len() == 0412 }413414 fn get(&self, index: usize) -> Result<Option<Val>> {415 Ok(self.get_cheap(index))416 }417418 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {419 self.get_cheap(index).map(Thunk::evaluated)420 }421422 fn get_cheap(&self, index: usize) -> Option<Val> {423 self.range().nth(index).map(|i| Val::Num(f64::from(i)))424 }425}426impl From<RangeArray> for ArrValue {427 fn from(value: RangeArray) -> Self {428 Self::Range(value)429 }430}431432#[derive(Debug, Trace, Clone)]433pub struct ReverseArray(pub ArrValue);434impl ArrayLike for ReverseArray {435 fn len(&self) -> usize {436 self.0.len()437 }438439 fn get(&self, index: usize) -> Result<Option<Val>> {440 self.0.get(self.0.len() - index - 1)441 }442443 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {444 self.0.get_lazy(self.0.len() - index - 1)445 }446447 fn get_cheap(&self, index: usize) -> Option<Val> {448 self.0.get_cheap(self.0.len() - index - 1)449 }450 fn reverse(self) -> ArrValue {451 self.0452 }453}454impl From<ReverseArray> for ArrValue {455 fn from(value: ReverseArray) -> Self {456 Self::Reverse(Cc::new(value))457 }458}459460#[derive(Trace, Debug)]461pub struct MappedArrayInner {462 inner: ArrValue,463 cached: RefCell<Vec<ArrayThunk<()>>>,464 mapper: FuncVal,465}466#[derive(Trace, Debug, Clone)]467pub struct MappedArray(Cc<MappedArrayInner>);468impl MappedArray {469 pub fn new(inner: ArrValue, mapper: FuncVal) -> Self {470 let len = inner.len();471 Self(Cc::new(MappedArrayInner {472 inner,473 cached: RefCell::new(vec![ArrayThunk::Waiting(()); len]),474 mapper,475 }))476 }477}478impl ArrayLike for MappedArray {479 fn len(&self) -> usize {480 self.0.cached.borrow().len()481 }482483 fn get(&self, index: usize) -> Result<Option<Val>> {484 if index >= self.len() {485 return Ok(None);486 }487 match &self.0.cached.borrow()[index] {488 ArrayThunk::Computed(c) => return Ok(Some(c.clone())),489 ArrayThunk::Errored(e) => return Err(e.clone()),490 ArrayThunk::Pending => return Err(InfiniteRecursionDetected.into()),491 ArrayThunk::Waiting(..) => {}492 };493494 let ArrayThunk::Waiting(_) =495 replace(&mut self.0.cached.borrow_mut()[index], ArrayThunk::Pending)496 else {497 unreachable!()498 };499500 let val = self501 .0502 .inner503 .get(index)504 .transpose()505 .expect("index checked")506 .and_then(|r| self.0.mapper.evaluate_simple(&(r,), false));507508 let new_value = match val {509 Ok(v) => v,510 Err(e) => {511 self.0.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone());512 return Err(e);513 }514 };515 self.0.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone());516 Ok(Some(new_value))517 }518 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {519 #[derive(Trace)]520 struct ArrayElement {521 arr_thunk: MappedArray,522 index: usize,523 }524525 impl ThunkValue for ArrayElement {526 type Output = Val;527528 fn get(self: Box<Self>) -> Result<Self::Output> {529 self.arr_thunk530 .get(self.index)531 .transpose()532 .expect("index checked")533 }534 }535536 if index >= self.len() {537 return None;538 }539 match &self.0.cached.borrow()[index] {540 ArrayThunk::Computed(c) => return Some(Thunk::evaluated(c.clone())),541 ArrayThunk::Errored(e) => return Some(Thunk::errored(e.clone())),542 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}543 };544545 Some(Thunk::new(ArrayElement {546 arr_thunk: self.clone(),547 index,548 }))549 }550551 fn get_cheap(&self, _index: usize) -> Option<Val> {552 None553 }554}555impl From<MappedArray> for ArrValue {556 fn from(value: MappedArray) -> Self {557 Self::Mapped(value)558 }559}560561#[derive(Trace, Debug)]562pub struct RepeatedArrayInner {563 data: ArrValue,564 repeats: usize,565 total_len: usize,566}567#[derive(Trace, Debug, Clone)]568pub struct RepeatedArray(Cc<RepeatedArrayInner>);569impl RepeatedArray {570 pub fn new(data: ArrValue, repeats: usize) -> Option<Self> {571 let total_len = data.len().checked_mul(repeats)?;572 Some(Self(Cc::new(RepeatedArrayInner {573 data,574 repeats,575 total_len,576 })))577 }578 pub fn is_cheap(&self) -> bool {579 self.0.data.is_cheap()580 }581}582583impl ArrayLike for RepeatedArray {584 fn len(&self) -> usize {585 self.0.total_len586 }587588 fn get(&self, index: usize) -> Result<Option<Val>> {589 if index > self.0.total_len {590 return Ok(None);591 }592 self.0.data.get(index % self.0.data.len())593 }594595 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {596 if index > self.0.total_len {597 return None;598 }599 self.0.data.get_lazy(index % self.0.data.len())600 }601602 fn get_cheap(&self, index: usize) -> Option<Val> {603 if index > self.0.total_len {604 return None;605 }606 self.0.data.get_cheap(index % self.0.data.len())607 }608}609impl From<RepeatedArray> for ArrValue {610 fn from(value: RepeatedArray) -> Self {611 Self::Repeated(value)612 }613}614615macro_rules! pass {616 ($t:ident.$m:ident($($ident:ident),*)) => {617 match $t {618 Self::Bytes(e) => e.$m($($ident)*),619 Self::Chars(e) => e.$m($($ident)*),620 Self::Expr(e) => e.$m($($ident)*),621 Self::Lazy(e) => e.$m($($ident)*),622 Self::Eager(e) => e.$m($($ident)*),623 Self::Range(e) => e.$m($($ident)*),624 Self::Slice(e) => e.$m($($ident)*),625 Self::Extended(e) => e.$m($($ident)*),626 Self::Reverse(e) => e.$m($($ident)*),627 Self::Mapped(e) => e.$m($($ident)*),628 Self::Repeated(e) => e.$m($($ident)*),629 }630 };631}632pub(super) use pass;crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -573,10 +573,10 @@
evaluate(self.ctx, &self.item)
}
}
- Val::Arr(ArrValue::lazy(Cc::new(vec![Thunk::new(ArrayElement {
+ Val::Arr(ArrValue::lazy(vec![Thunk::new(ArrayElement {
ctx,
item: items[0].clone(),
- })])))
+ })]))
} else {
Val::Arr(ArrValue::expr(ctx, items.iter().cloned()))
}
crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj.rs
+++ b/crates/jrsonnet-evaluator/src/obj.rs
@@ -17,7 +17,7 @@
operator::evaluate_add_op,
tb, throw,
val::ThunkValue,
- MaybeUnbound, Result, ResultExt, State, Thunk, Unbound, Val,
+ MaybeUnbound, Result, State, Thunk, Unbound, Val,
};
#[cfg(not(feature = "exp-preserve-order"))]
crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/typed/conversions.rs
+++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs
@@ -6,7 +6,7 @@
use jrsonnet_types::{ComplexValType, ValType};
use crate::{
- arr::ArrValue,
+ arr::{ArrValue, BytesArray},
error::Result,
function::{native::NativeDesc, FuncDesc, FuncVal},
throw,
@@ -434,12 +434,13 @@
}
fn from_untyped(value: Val) -> Result<Self> {
- if let Val::Arr(ArrValue::Bytes(bytes)) = value {
- return Ok(bytes.0);
- }
- <Self as Typed>::TYPE.check(&value)?;
- match value {
+ match &value {
Val::Arr(a) => {
+ if let Some(bytes) = a.as_any().downcast_ref::<BytesArray>() {
+ return Ok(bytes.0.as_slice().into());
+ };
+ <Self as Typed>::TYPE.check(&value)?;
+ // Any::downcast_ref::<ByteArray>(&a);
let mut out = Vec::with_capacity(a.len());
for e in a.iter() {
let r = e?;
@@ -447,7 +448,10 @@
}
Ok(out.as_slice().into())
}
- _ => unreachable!(),
+ _ => {
+ <Self as Typed>::TYPE.check(&value)?;
+ unreachable!()
+ }
}
}
}
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -9,7 +9,7 @@
use jrsonnet_interner::IStr;
use jrsonnet_types::ValType;
-pub use crate::arr::ArrValue;
+pub use crate::arr::{ArrValue, ArrayLike};
use crate::{
error::{Error, ErrorKind::*},
function::FuncVal,
crates/jrsonnet-stdlib/src/sets.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/sets.rs
+++ b/crates/jrsonnet-stdlib/src/sets.rs
@@ -7,7 +7,6 @@
val::ArrValue,
Thunk, Val,
};
-use jrsonnet_gcmodule::Cc;
use jrsonnet_parser::BinaryOpType;
#[builtin]
@@ -70,5 +69,5 @@
}
};
}
- Ok(ArrValue::lazy(Cc::new(out)))
+ Ok(ArrValue::lazy(out))
}
crates/jrsonnet-stdlib/src/sort.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/sort.rs
+++ b/crates/jrsonnet-stdlib/src/sort.rs
@@ -10,7 +10,6 @@
val::{equals, ArrValue},
Thunk, Val,
};
-use jrsonnet_gcmodule::Cc;
use jrsonnet_parser::BinaryOpType;
use crate::eval_on_empty;
@@ -136,7 +135,7 @@
values.iter().collect::<Result<Vec<Val>>>()?,
)?))
} else {
- Ok(ArrValue::lazy(Cc::new(sort_keyf(values, key_getter)?)))
+ Ok(ArrValue::lazy(sort_keyf(values, key_getter)?))
}
}
@@ -186,7 +185,7 @@
arr.iter().collect::<Result<Vec<Val>>>()?,
)?))
} else {
- Ok(ArrValue::lazy(Cc::new(uniq_keyf(arr, keyF)?)))
+ Ok(ArrValue::lazy(uniq_keyf(arr, keyF)?))
}
}
@@ -204,8 +203,8 @@
Ok(ArrValue::eager(arr))
} else {
let arr = sort_keyf(arr, keyF.clone())?;
- let arr = uniq_keyf(ArrValue::lazy(Cc::new(arr)), keyF)?;
- Ok(ArrValue::lazy(Cc::new(arr)))
+ let arr = uniq_keyf(ArrValue::lazy(arr), keyF)?;
+ Ok(ArrValue::lazy(arr))
}
}