git.delta.rocks / jrsonnet / refs/commits / 23d571a0df03

difftreelog

refactor move arrays to use dyn ArrayLike

Yaroslav Bolyukin2023-08-06parent: #09dae32.patch.diff
in: master

8 files changed

modifiedcrates/jrsonnet-evaluator/src/arr/mod.rsdiffbeforeafterboth
1use std::rc::Rc;1use std::any::Any;
22
3use jrsonnet_gcmodule::{Cc, Trace};3use jrsonnet_gcmodule::{Cc, Trace};
4use jrsonnet_interner::IBytes;4use jrsonnet_interner::IBytes;
5use jrsonnet_parser::LocExpr;5use jrsonnet_parser::LocExpr;
66
7use crate::{function::FuncVal, Context, Result, Thunk, Val};7use crate::{function::FuncVal, gc::TraceBox, tb, Context, Result, Thunk, Val};
88
9mod spec;9mod spec;
10pub use spec::ArrayLike;
10use spec::*;11pub(crate) use spec::*;
1112
12/// Represents a Jsonnet array value.13/// Represents a Jsonnet array value.
13#[derive(Debug, Clone, Trace)]14#[derive(Debug, Clone, Trace)]
14// may contrain other ArrValue15// may contrain other ArrValue
15#[trace(tracking(force))]16#[trace(tracking(force))]
16pub enum ArrValue {17pub struct ArrValue(Cc<TraceBox<dyn ArrayLike>>);
17 /// Layout optimized byte array.
18 Bytes(BytesArray),
19 /// Layout optimized char array.
20 Chars(CharArray),
21 /// Every element is lazy evaluated.
22 Lazy(LazyArray),
23 /// Every element is defined somewhere in source code
24 Expr(ExprArray),
25 /// Every field is already evaluated.
26 Eager(EagerArray),
27 /// Concatenation of two arrays of any kind.
28 Extended(Cc<ExtendedArray>),
29 /// Represents a integer array in form `[start, start + 1, ... end - 1, end]`.
30 /// This kind of arrays is generated by `std.range(start, end)` call, and used for loops.
31 Range(RangeArray),
32 /// Sliced array view.
33 Slice(Cc<SliceArray>),
34 /// Reversed array view.
35 /// Returned by `std.reverse(other)` call
36 Reverse(Cc<ReverseArray>),
37 /// Returned by `std.map` call
38 Mapped(MappedArray),
39 /// Returned by `std.repeat` call
40 Repeated(RepeatedArray),
41}
4218
43pub trait ArrayLikeIter<T>: Iterator<Item = T> + DoubleEndedIterator + ExactSizeIterator {}19pub trait ArrayLikeIter<T>: Iterator<Item = T> + DoubleEndedIterator + ExactSizeIterator {}
44impl<I, T> ArrayLikeIter<T> for I where20impl<I, T> ArrayLikeIter<T> for I where
47}23}
4824
49impl ArrValue {25impl ArrValue {
26 pub fn new(v: impl ArrayLike) -> Self {
27 Self(Cc::new(tb!(v)))
28 }
50 pub fn empty() -> Self {29 pub fn empty() -> Self {
51 Self::Range(RangeArray::empty())30 Self::new(RangeArray::empty())
52 }31 }
5332
54 pub fn expr(ctx: Context, exprs: impl IntoIterator<Item = LocExpr>) -> Self {33 pub fn expr(ctx: Context, exprs: impl IntoIterator<Item = LocExpr>) -> Self {
55 Self::Expr(ExprArray::new(ctx, exprs))34 Self::new(ExprArray::new(ctx, exprs))
56 }35 }
5736
58 pub fn lazy(thunks: Cc<Vec<Thunk<Val>>>) -> Self {37 pub fn lazy(thunks: Vec<Thunk<Val>>) -> Self {
59 Self::Lazy(LazyArray(thunks))38 Self::new(LazyArray(thunks))
60 }39 }
6140
62 pub fn eager(values: Vec<Val>) -> Self {41 pub fn eager(values: Vec<Val>) -> Self {
63 Self::Eager(EagerArray(Cc::new(values)))42 Self::new(EagerArray(values))
64 }43 }
6544
66 pub fn repeated(data: ArrValue, repeats: usize) -> Option<Self> {45 pub fn repeated(data: ArrValue, repeats: usize) -> Option<Self> {
67 Some(Self::Repeated(RepeatedArray::new(data, repeats)?))46 Some(Self::new(RepeatedArray::new(data, repeats)?))
68 }47 }
6948
70 pub fn bytes(bytes: IBytes) -> Self {49 pub fn bytes(bytes: IBytes) -> Self {
71 Self::Bytes(BytesArray(bytes))50 Self::new(BytesArray(bytes))
72 }51 }
73 pub fn chars(chars: impl Iterator<Item = char>) -> Self {52 pub fn chars(chars: impl Iterator<Item = char>) -> Self {
74 Self::Chars(CharArray(Rc::new(chars.collect())))53 Self::new(CharArray(chars.collect()))
75 }54 }
7655
77 #[must_use]56 #[must_use]
78 pub fn map(self, mapper: FuncVal) -> Self {57 pub fn map(self, mapper: FuncVal) -> Self {
79 Self::Mapped(MappedArray::new(self, mapper))58 Self::new(MappedArray::new(self, mapper))
80 }59 }
8160
82 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {61 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {
100 } else if b.is_empty() {79 } else if b.is_empty() {
101 a80 a
102 } else if a.len() + b.len() > ARR_EXTEND_THRESHOLD {81 } else if a.len() + b.len() > ARR_EXTEND_THRESHOLD {
103 Self::Extended(Cc::new(ExtendedArray::new(a, b)))82 Self::new(ExtendedArray::new(a, b))
104 } else if let (Some(a), Some(b)) = (a.iter_cheap(), b.iter_cheap()) {83 } else if let (Some(a), Some(b)) = (a.iter_cheap(), b.iter_cheap()) {
105 let mut out = Vec::with_capacity(a.len() + b.len());84 let mut out = Vec::with_capacity(a.len() + b.len());
106 out.extend(a);85 out.extend(a);
110 let mut out = Vec::with_capacity(a.len() + b.len());89 let mut out = Vec::with_capacity(a.len() + b.len());
111 out.extend(a.iter_lazy());90 out.extend(a.iter_lazy());
112 out.extend(b.iter_lazy());91 out.extend(b.iter_lazy());
113 Self::lazy(Cc::new(out))92 Self::lazy(out)
114 }93 }
115 }94 }
11695
117 pub fn range_exclusive(a: i32, b: i32) -> Self {96 pub fn range_exclusive(a: i32, b: i32) -> Self {
118 Self::Range(RangeArray::new_exclusive(a, b))97 Self::new(RangeArray::new_exclusive(a, b))
119 }98 }
120 pub fn range_inclusive(a: i32, b: i32) -> Self {99 pub fn range_inclusive(a: i32, b: i32) -> Self {
121 Self::Range(RangeArray::new_inclusive(a, b))100 Self::new(RangeArray::new_inclusive(a, b))
122 }101 }
123102
124 #[must_use]103 #[must_use]
136 if from >= to || step == 0 {115 if from >= to || step == 0 {
137 return None;116 return None;
138 }117 }
139 // match self {
140 // ArrValue::Slice(slice) => {
141 // return Some(Self::Slice(Cc::new(SliceArray {
142 // inner: slice.inner.clone(),
143 // from: slice.from + slice.step * (from as u32),
144 // to: slice.from + (to as u32) * slice.step,
145 // step: slice.step * step as u32,
146 // })))
147 // }
148 // _ => {}
149 // }
150118
151 Some(Self::Slice(Cc::new(SliceArray {119 Some(Self::new(SliceArray {
152 inner: self,120 inner: self,
153 from: from as u32,121 from: from as u32,
154 to: to as u32,122 to: to as u32,
155 step: step as u32,123 step: step as u32,
156 })))124 }))
157 }125 }
158126
159 /// Array length.127 /// Array length.
160 pub fn len(&self) -> usize {128 pub fn len(&self) -> usize {
161 pass!(self.len())129 self.0.len()
162 }130 }
163131
164 /// Is array contains no elements?132 /// Is array contains no elements?
165 pub fn is_empty(&self) -> bool {133 pub fn is_empty(&self) -> bool {
166 pass!(self.is_empty())134 self.0.is_empty()
167 }135 }
168136
169 /// Get array element by index, evaluating it, if it is lazy.137 /// Get array element by index, evaluating it, if it is lazy.
170 ///138 ///
171 /// Returns `None` on out-of-bounds condition.139 /// Returns `None` on out-of-bounds condition.
172 pub fn get(&self, index: usize) -> Result<Option<Val>> {140 pub fn get(&self, index: usize) -> Result<Option<Val>> {
173 pass!(self.get(index))141 self.0.get(index)
174 }142 }
175143
176 /// Returns None if get is either non cheap, or out of bounds144 /// Returns None if get is either non cheap, or out of bounds
177 fn get_cheap(&self, index: usize) -> Option<Val> {145 fn get_cheap(&self, index: usize) -> Option<Val> {
178 pass!(self.get_cheap(index))146 self.0.get_cheap(index)
179 }147 }
180148
181 /// Get array element by index, without evaluation.149 /// Get array element by index, without evaluation.
182 ///150 ///
183 /// Returns `None` on out-of-bounds condition.151 /// Returns `None` on out-of-bounds condition.
184 pub fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {152 pub fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
185 pass!(self.get_lazy(index))153 self.0.get_lazy(index)
186 }154 }
187155
188 pub fn iter(&self) -> impl ArrayLikeIter<Result<Val>> + '_ {156 pub fn iter(&self) -> impl ArrayLikeIter<Result<Val>> + '_ {
205 /// Return a reversed view on current array.173 /// Return a reversed view on current array.
206 #[must_use]174 #[must_use]
207 pub fn reversed(self) -> Self {175 pub fn reversed(self) -> Self {
208 Self::Reverse(Cc::new(ReverseArray(self)))176 Self::new(ReverseArray(self))
209 }177 }
210178
211 pub fn ptr_eq(a: &Self, b: &Self) -> bool {179 pub fn ptr_eq(a: &Self, b: &Self) -> bool {
212 match (a, b) {
213 (ArrValue::Bytes(a), ArrValue::Bytes(b)) => a.0 == b.0,
214 (ArrValue::Lazy(a), ArrValue::Lazy(b)) => Cc::ptr_eq(&a.0, &b.0),
215 (ArrValue::Expr(a), ArrValue::Expr(b)) => Cc::ptr_eq(&a.0, &b.0),180 Cc::ptr_eq(&a.0, &b.0)
216 (ArrValue::Eager(a), ArrValue::Eager(b)) => Cc::ptr_eq(&a.0, &b.0),
217 (ArrValue::Extended(a), ArrValue::Extended(b)) => Cc::ptr_eq(a, b),
218 (ArrValue::Range(a), ArrValue::Range(b)) => a == b,
219 _ => false,
220 }
221 }181 }
222182
223 /// Is this vec supports `.get_cheap()?`183 /// Is this vec supports `.get_cheap()?`
224 pub fn is_cheap(&self) -> bool {184 pub fn is_cheap(&self) -> bool {
225 match self {
226 ArrValue::Eager(_) | ArrValue::Range(..) | ArrValue::Bytes(_) | ArrValue::Chars(_) => {
227 true
228 }
229 ArrValue::Extended(v) => v.a.is_cheap() && v.b.is_cheap(),
230 ArrValue::Slice(r) => r.inner.is_cheap(),
231 ArrValue::Reverse(i) => i.0.is_cheap(),185 self.0.is_cheap()
232 ArrValue::Repeated(v) => v.is_cheap(),
233 ArrValue::Expr(_) | ArrValue::Lazy(_) | ArrValue::Mapped(_) => false,
234 }
235 }186 }
187
188 pub fn as_any(&self) -> &dyn Any {
189 &self.0
190 }
236}191}
237impl From<Vec<Val>> for ArrValue {192impl From<Vec<Val>> for ArrValue {
238 fn from(value: Vec<Val>) -> Self {193 fn from(value: Vec<Val>) -> Self {
241}196}
242impl From<Vec<Thunk<Val>>> for ArrValue {197impl From<Vec<Thunk<Val>>> for ArrValue {
243 fn from(value: Vec<Thunk<Val>>) -> Self {198 fn from(value: Vec<Thunk<Val>>) -> Self {
244 Self::lazy(Cc::new(value))199 Self::lazy(value)
245 }200 }
246}201}
247impl FromIterator<Val> for ArrValue {202impl FromIterator<Val> for ArrValue {
248 fn from_iter<T: IntoIterator<Item = Val>>(iter: T) -> Self {203 fn from_iter<T: IntoIterator<Item = Val>>(iter: T) -> Self {
249 Self::eager(iter.into_iter().collect())204 Self::eager(iter.into_iter().collect())
250 }205 }
251}206}
207impl ArrayLike for ArrValue {
208 fn len(&self) -> usize {
209 self.0.len()
210 }
211
212 fn get(&self, index: usize) -> Result<Option<Val>> {
213 self.0.get(index)
214 }
215
216 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
217 self.0.get_lazy(index)
218 }
219
220 fn get_cheap(&self, index: usize) -> Option<Val> {
221 self.0.get_cheap(index)
222 }
223
224 fn is_cheap(&self) -> bool {
225 self.0.is_cheap()
226 }
227}
252228
253#[cfg(target_pointer_width = "64")]229#[cfg(target_pointer_width = "64")]
254static_assertions::assert_eq_size!(ArrValue, [u8; 16]);230static_assertions::assert_eq_size!(ArrValue, [u8; 8]);
255231
modifiedcrates/jrsonnet-evaluator/src/arr/spec.rsdiffbeforeafterboth
1use std::{cell::RefCell, iter, mem::replace, rc::Rc};1use std::{any::Any, cell::RefCell, fmt::Debug, iter, mem::replace};
22
3use jrsonnet_gcmodule::{Cc, Trace};3use jrsonnet_gcmodule::{Cc, Trace};
4use jrsonnet_interner::{IBytes, IStr};4use jrsonnet_interner::{IBytes, IStr};
13 Context, Error, Result, Thunk, Val,13 Context, Error, Result, Thunk, Val,
14};14};
1515
16pub trait ArrayLike: Sized + Into<ArrValue> {16pub trait ArrayLike: Any + Trace + Debug {
17 fn len(&self) -> usize;17 fn len(&self) -> usize;
18 fn is_empty(&self) -> bool {18 fn is_empty(&self) -> bool {
19 self.len() == 019 self.len() == 0
22 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>>;22 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>>;
23 fn get_cheap(&self, index: usize) -> Option<Val>;23 fn get_cheap(&self, index: usize) -> Option<Val>;
2424
25 fn reverse(self) -> ArrValue {25 fn is_cheap(&self) -> bool;
26 ArrValue::Reverse(Cc::new(ReverseArray(self.into())))
27 }
28}26}
2927
30#[derive(Debug, Clone, Trace)]28#[derive(Debug, Trace)]
31pub struct SliceArray {29pub struct SliceArray {
32 pub(crate) inner: ArrValue,30 pub(crate) inner: ArrValue,
33 pub(crate) from: u32,31 pub(crate) from: u32,
62 )60 )
63 }61 }
64}62}
65impl ArrayLike for SliceArray {63impl ArrayLike for SliceArray {
66 fn len(&self) -> usize {64 fn len(&self) -> usize {
67 iter::repeat(())65 iter::repeat(())
68 .take((self.to - self.from) as usize)66 .take((self.to - self.from) as usize)
81 fn get_cheap(&self, index: usize) -> Option<Val> {79 fn get_cheap(&self, index: usize) -> Option<Val> {
82 self.iter_cheap()?.nth(index)80 self.iter_cheap()?.nth(index)
83 }81 }
84}
85impl From<SliceArray> for ArrValue {
86 fn from(value: SliceArray) -> Self {82 fn is_cheap(&self) -> bool {
87 Self::Slice(Cc::new(value))83 self.inner.is_cheap()
88 }84 }
89}85}
9086
91#[derive(Trace, Debug, Clone)]87#[derive(Trace, Debug)]
92pub struct CharArray(pub Rc<Vec<char>>);88pub struct CharArray(pub Vec<char>);
93impl ArrayLike for CharArray {89impl ArrayLike for CharArray {
94 fn len(&self) -> usize {90 fn len(&self) -> usize {
95 self.0.len()91 self.0.len()
96 }92 }
108 .get(index)104 .get(index)
109 .map(|v| Val::Str(StrValue::Flat(IStr::from(*v))))105 .map(|v| Val::Str(StrValue::Flat(IStr::from(*v))))
110 }106 }
111}
112impl From<CharArray> for ArrValue {
113 fn from(value: CharArray) -> Self {107 fn is_cheap(&self) -> bool {
114 ArrValue::Chars(value)108 true
115 }109 }
116}110}
117111
118#[derive(Trace, Debug, Clone)]112#[derive(Trace, Debug)]
119pub struct BytesArray(pub IBytes);113pub struct BytesArray(pub IBytes);
120impl ArrayLike for BytesArray {114impl ArrayLike for BytesArray {
121 fn len(&self) -> usize {115 fn len(&self) -> usize {
122 self.0.len()116 self.0.len()
123 }117 }
133 fn get_cheap(&self, index: usize) -> Option<Val> {127 fn get_cheap(&self, index: usize) -> Option<Val> {
134 self.0.get(index).map(|v| Val::Num(f64::from(*v)))128 self.0.get(index).map(|v| Val::Num(f64::from(*v)))
135 }129 }
136}
137impl From<BytesArray> for ArrValue {
138 fn from(value: BytesArray) -> Self {130 fn is_cheap(&self) -> bool {
139 ArrValue::Bytes(value)131 true
140 }132 }
141}133}
142134
143#[derive(Debug, Trace, Clone)]135#[derive(Debug, Trace, Clone)]
144enum ArrayThunk<T: 'static + Trace> {136enum ArrayThunk<T: 'static + Trace> {
148 Pending,140 Pending,
149}141}
150142
151#[derive(Debug, Trace)]143#[derive(Debug, Trace, Clone)]
152pub struct ExprArrayInner {144pub struct ExprArray {
153 ctx: Context,145 ctx: Context,
154 cached: RefCell<Vec<ArrayThunk<LocExpr>>>,146 cached: Cc<RefCell<Vec<ArrayThunk<LocExpr>>>>,
155}147}
156#[derive(Debug, Trace, Clone)]
157pub struct ExprArray(pub Cc<ExprArrayInner>);
158impl ExprArray {148impl ExprArray {
159 pub fn new(ctx: Context, items: impl IntoIterator<Item = LocExpr>) -> Self {149 pub fn new(ctx: Context, items: impl IntoIterator<Item = LocExpr>) -> Self {
160 Self(Cc::new(ExprArrayInner {150 Self {
161 ctx,151 ctx,
162 cached: RefCell::new(items.into_iter().map(ArrayThunk::Waiting).collect()),152 cached: Cc::new(RefCell::new(
153 items.into_iter().map(ArrayThunk::Waiting).collect(),
163 }))154 )),
155 }
164 }156 }
165}157}
166impl ArrayLike for ExprArray {158impl ArrayLike for ExprArray {
167 fn len(&self) -> usize {159 fn len(&self) -> usize {
168 self.0.cached.borrow().len()160 self.cached.borrow().len()
169 }161 }
170 fn get(&self, index: usize) -> Result<Option<Val>> {162 fn get(&self, index: usize) -> Result<Option<Val>> {
171 if index >= self.len() {163 if index >= self.len() {
172 return Ok(None);164 return Ok(None);
173 }165 }
174 match &self.0.cached.borrow()[index] {166 match &self.cached.borrow()[index] {
175 ArrayThunk::Computed(c) => return Ok(Some(c.clone())),167 ArrayThunk::Computed(c) => return Ok(Some(c.clone())),
176 ArrayThunk::Errored(e) => return Err(e.clone()),168 ArrayThunk::Errored(e) => return Err(e.clone()),
177 ArrayThunk::Pending => return Err(InfiniteRecursionDetected.into()),169 ArrayThunk::Pending => return Err(InfiniteRecursionDetected.into()),
178 ArrayThunk::Waiting(..) => {}170 ArrayThunk::Waiting(..) => {}
179 };171 };
180172
181 let ArrayThunk::Waiting(expr) =173 let ArrayThunk::Waiting(expr) =
182 replace(&mut self.0.cached.borrow_mut()[index], ArrayThunk::Pending)174 replace(&mut self.cached.borrow_mut()[index], ArrayThunk::Pending)
183 else {175 else {
184 unreachable!()176 unreachable!()
185 };177 };
186178
187 let new_value = match evaluate(self.0.ctx.clone(), &expr) {179 let new_value = match evaluate(self.ctx.clone(), &expr) {
188 Ok(v) => v,180 Ok(v) => v,
189 Err(e) => {181 Err(e) => {
190 self.0.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone());182 self.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone());
191 return Err(e);183 return Err(e);
192 }184 }
193 };185 };
194 self.0.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone());186 self.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone());
195 Ok(Some(new_value))187 Ok(Some(new_value))
196 }188 }
197 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {189 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
215 if index >= self.len() {207 if index >= self.len() {
216 return None;208 return None;
217 }209 }
218 match &self.0.cached.borrow()[index] {210 match &self.cached.borrow()[index] {
219 ArrayThunk::Computed(c) => return Some(Thunk::evaluated(c.clone())),211 ArrayThunk::Computed(c) => return Some(Thunk::evaluated(c.clone())),
220 ArrayThunk::Errored(e) => return Some(Thunk::errored(e.clone())),212 ArrayThunk::Errored(e) => return Some(Thunk::errored(e.clone())),
221 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}213 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}
229 fn get_cheap(&self, _index: usize) -> Option<Val> {221 fn get_cheap(&self, _index: usize) -> Option<Val> {
230 None222 None
231 }223 }
224 fn is_cheap(&self) -> bool {
225 false
226 }
232}227}
233impl From<ExprArray> for ArrValue {
234 fn from(value: ExprArray) -> Self {
235 Self::Expr(value)
236 }
237}
238228
239#[derive(Trace, Debug, Clone)]229#[derive(Trace, Debug)]
240pub struct ExtendedArray {230pub struct ExtendedArray {
241 pub a: ArrValue,231 pub a: ArrValue,
242 pub b: ArrValue,232 pub b: ArrValue,
292 self.1282 self.1
293 }283 }
294}284}
295impl ArrayLike for ExtendedArray {285impl ArrayLike for ExtendedArray {
296 fn get(&self, index: usize) -> Result<Option<Val>> {286 fn get(&self, index: usize) -> Result<Option<Val>> {
297 if self.split > index {287 if self.split > index {
298 self.a.get(index)288 self.a.get(index)
319 self.b.get_cheap(index - self.split)309 self.b.get_cheap(index - self.split)
320 }310 }
321 }311 }
322}
323impl From<ExtendedArray> for ArrValue {
324 fn from(value: ExtendedArray) -> Self {312 fn is_cheap(&self) -> bool {
325 Self::Extended(Cc::new(value))313 self.a.is_cheap() && self.b.is_cheap()
326 }314 }
327}315}
328316
329#[derive(Trace, Debug, Clone)]317#[derive(Trace, Debug)]
330pub struct LazyArray(pub Cc<Vec<Thunk<Val>>>);318pub struct LazyArray(pub Vec<Thunk<Val>>);
331impl ArrayLike for LazyArray {319impl ArrayLike for LazyArray {
332 fn len(&self) -> usize {320 fn len(&self) -> usize {
333 self.0.len()321 self.0.len()
334 }322 }
344 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {332 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
345 self.0.get(index).cloned()333 self.0.get(index).cloned()
346 }334 }
347}
348impl From<LazyArray> for ArrValue {
349 fn from(value: LazyArray) -> Self {335 fn is_cheap(&self) -> bool {
350 Self::Lazy(value)336 false
351 }337 }
352}338}
353339
354#[derive(Trace, Debug, Clone)]340#[derive(Trace, Debug)]
355pub struct EagerArray(pub Cc<Vec<Val>>);341pub struct EagerArray(pub Vec<Val>);
356impl ArrayLike for EagerArray {342impl ArrayLike for EagerArray {
357 fn len(&self) -> usize {343 fn len(&self) -> usize {
358 self.0.len()344 self.0.len()
359 }345 }
369 fn get_cheap(&self, index: usize) -> Option<Val> {355 fn get_cheap(&self, index: usize) -> Option<Val> {
370 self.0.get(index).cloned()356 self.0.get(index).cloned()
371 }357 }
372}
373impl From<EagerArray> for ArrValue {
374 fn from(value: EagerArray) -> Self {358 fn is_cheap(&self) -> bool {
375 Self::Eager(value)359 true
376 }360 }
377}361}
378362
379/// Inclusive range type363/// Inclusive range type
380#[derive(Debug, Trace, Clone, PartialEq, Eq)]364#[derive(Debug, Trace, PartialEq, Eq)]
381pub struct RangeArray {365pub struct RangeArray {
382 start: i32,366 start: i32,
383 end: i32,367 end: i32,
403 }387 }
404}388}
405389
406impl ArrayLike for RangeArray {390impl ArrayLike for RangeArray {
407 fn len(&self) -> usize {391 fn len(&self) -> usize {
408 self.range().len()392 self.range().len()
409 }393 }
422 fn get_cheap(&self, index: usize) -> Option<Val> {406 fn get_cheap(&self, index: usize) -> Option<Val> {
423 self.range().nth(index).map(|i| Val::Num(f64::from(i)))407 self.range().nth(index).map(|i| Val::Num(f64::from(i)))
424 }408 }
425}
426impl From<RangeArray> for ArrValue {
427 fn from(value: RangeArray) -> Self {409 fn is_cheap(&self) -> bool {
428 Self::Range(value)410 true
429 }411 }
430}412}
431413
432#[derive(Debug, Trace, Clone)]414#[derive(Debug, Trace)]
433pub struct ReverseArray(pub ArrValue);415pub struct ReverseArray(pub ArrValue);
434impl ArrayLike for ReverseArray {416impl ArrayLike for ReverseArray {
435 fn len(&self) -> usize {417 fn len(&self) -> usize {
447 fn get_cheap(&self, index: usize) -> Option<Val> {429 fn get_cheap(&self, index: usize) -> Option<Val> {
448 self.0.get_cheap(self.0.len() - index - 1)430 self.0.get_cheap(self.0.len() - index - 1)
449 }431 }
450 fn reverse(self) -> ArrValue {432 fn is_cheap(&self) -> bool {
451 self.0433 self.0.is_cheap()
452 }434 }
453}435}
454impl From<ReverseArray> for ArrValue {
455 fn from(value: ReverseArray) -> Self {
456 Self::Reverse(Cc::new(value))
457 }
458}
459436
460#[derive(Trace, Debug)]437#[derive(Trace, Debug, Clone)]
461pub struct MappedArrayInner {438pub struct MappedArray {
462 inner: ArrValue,439 inner: ArrValue,
463 cached: RefCell<Vec<ArrayThunk<()>>>,440 cached: Cc<RefCell<Vec<ArrayThunk<()>>>>,
464 mapper: FuncVal,441 mapper: FuncVal,
465}442}
466#[derive(Trace, Debug, Clone)]
467pub struct MappedArray(Cc<MappedArrayInner>);
468impl MappedArray {443impl MappedArray {
469 pub fn new(inner: ArrValue, mapper: FuncVal) -> Self {444 pub fn new(inner: ArrValue, mapper: FuncVal) -> Self {
470 let len = inner.len();445 let len = inner.len();
471 Self(Cc::new(MappedArrayInner {446 Self {
472 inner,447 inner,
473 cached: RefCell::new(vec![ArrayThunk::Waiting(()); len]),448 cached: Cc::new(RefCell::new(vec![ArrayThunk::Waiting(()); len])),
474 mapper,449 mapper,
475 }))450 }
476 }451 }
477}452}
478impl ArrayLike for MappedArray {453impl ArrayLike for MappedArray {
479 fn len(&self) -> usize {454 fn len(&self) -> usize {
480 self.0.cached.borrow().len()455 self.cached.borrow().len()
481 }456 }
482457
483 fn get(&self, index: usize) -> Result<Option<Val>> {458 fn get(&self, index: usize) -> Result<Option<Val>> {
484 if index >= self.len() {459 if index >= self.len() {
485 return Ok(None);460 return Ok(None);
486 }461 }
487 match &self.0.cached.borrow()[index] {462 match &self.cached.borrow()[index] {
488 ArrayThunk::Computed(c) => return Ok(Some(c.clone())),463 ArrayThunk::Computed(c) => return Ok(Some(c.clone())),
489 ArrayThunk::Errored(e) => return Err(e.clone()),464 ArrayThunk::Errored(e) => return Err(e.clone()),
490 ArrayThunk::Pending => return Err(InfiniteRecursionDetected.into()),465 ArrayThunk::Pending => return Err(InfiniteRecursionDetected.into()),
491 ArrayThunk::Waiting(..) => {}466 ArrayThunk::Waiting(..) => {}
492 };467 };
493468
494 let ArrayThunk::Waiting(_) =469 let ArrayThunk::Waiting(_) =
495 replace(&mut self.0.cached.borrow_mut()[index], ArrayThunk::Pending)470 replace(&mut self.cached.borrow_mut()[index], ArrayThunk::Pending)
496 else {471 else {
497 unreachable!()472 unreachable!()
498 };473 };
499474
500 let val = self475 let val = self
501 .0
502 .inner476 .inner
503 .get(index)477 .get(index)
504 .transpose()478 .transpose()
505 .expect("index checked")479 .expect("index checked")
506 .and_then(|r| self.0.mapper.evaluate_simple(&(r,), false));480 .and_then(|r| self.mapper.evaluate_simple(&(r,), false));
507481
508 let new_value = match val {482 let new_value = match val {
509 Ok(v) => v,483 Ok(v) => v,
510 Err(e) => {484 Err(e) => {
511 self.0.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone());485 self.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone());
512 return Err(e);486 return Err(e);
513 }487 }
514 };488 };
515 self.0.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone());489 self.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone());
516 Ok(Some(new_value))490 Ok(Some(new_value))
517 }491 }
518 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {492 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
536 if index >= self.len() {510 if index >= self.len() {
537 return None;511 return None;
538 }512 }
539 match &self.0.cached.borrow()[index] {513 match &self.cached.borrow()[index] {
540 ArrayThunk::Computed(c) => return Some(Thunk::evaluated(c.clone())),514 ArrayThunk::Computed(c) => return Some(Thunk::evaluated(c.clone())),
541 ArrayThunk::Errored(e) => return Some(Thunk::errored(e.clone())),515 ArrayThunk::Errored(e) => return Some(Thunk::errored(e.clone())),
542 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}516 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}
551 fn get_cheap(&self, _index: usize) -> Option<Val> {525 fn get_cheap(&self, _index: usize) -> Option<Val> {
552 None526 None
553 }527 }
528 fn is_cheap(&self) -> bool {
529 false
530 }
554}531}
555impl From<MappedArray> for ArrValue {
556 fn from(value: MappedArray) -> Self {
557 Self::Mapped(value)
558 }
559}
560532
561#[derive(Trace, Debug)]533#[derive(Trace, Debug)]
562pub struct RepeatedArrayInner {534pub struct RepeatedArray {
563 data: ArrValue,535 data: ArrValue,
564 repeats: usize,536 repeats: usize,
565 total_len: usize,537 total_len: usize,
566}538}
567#[derive(Trace, Debug, Clone)]
568pub struct RepeatedArray(Cc<RepeatedArrayInner>);
569impl RepeatedArray {539impl RepeatedArray {
570 pub fn new(data: ArrValue, repeats: usize) -> Option<Self> {540 pub fn new(data: ArrValue, repeats: usize) -> Option<Self> {
571 let total_len = data.len().checked_mul(repeats)?;541 let total_len = data.len().checked_mul(repeats)?;
572 Some(Self(Cc::new(RepeatedArrayInner {542 Some(Self {
573 data,543 data,
574 repeats,544 repeats,
575 total_len,545 total_len,
576 })))546 })
577 }547 }
578 pub fn is_cheap(&self) -> bool {
579 self.0.data.is_cheap()
580 }
581}548}
582549
583impl ArrayLike for RepeatedArray {550impl ArrayLike for RepeatedArray {
584 fn len(&self) -> usize {551 fn len(&self) -> usize {
585 self.0.total_len552 self.total_len
586 }553 }
587554
588 fn get(&self, index: usize) -> Result<Option<Val>> {555 fn get(&self, index: usize) -> Result<Option<Val>> {
589 if index > self.0.total_len {556 if index > self.total_len {
590 return Ok(None);557 return Ok(None);
591 }558 }
592 self.0.data.get(index % self.0.data.len())559 self.data.get(index % self.data.len())
593 }560 }
594561
595 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {562 fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
596 if index > self.0.total_len {563 if index > self.total_len {
597 return None;564 return None;
598 }565 }
599 self.0.data.get_lazy(index % self.0.data.len())566 self.data.get_lazy(index % self.data.len())
600 }567 }
601568
602 fn get_cheap(&self, index: usize) -> Option<Val> {569 fn get_cheap(&self, index: usize) -> Option<Val> {
603 if index > self.0.total_len {570 if index > self.total_len {
604 return None;571 return None;
605 }572 }
606 self.0.data.get_cheap(index % self.0.data.len())573 self.data.get_cheap(index % self.data.len())
607 }574 }
575 fn is_cheap(&self) -> bool {
576 self.data.is_cheap()
577 }
608}578}
609impl From<RepeatedArray> for ArrValue {
610 fn from(value: RepeatedArray) -> Self {
611 Self::Repeated(value)
612 }
613}
614
615macro_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;
633579
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
573 evaluate(self.ctx, &self.item)573 evaluate(self.ctx, &self.item)
574 }574 }
575 }575 }
576 Val::Arr(ArrValue::lazy(Cc::new(vec![Thunk::new(ArrayElement {576 Val::Arr(ArrValue::lazy(vec![Thunk::new(ArrayElement {
577 ctx,577 ctx,
578 item: items[0].clone(),578 item: items[0].clone(),
579 })])))579 })]))
580 } else {580 } else {
581 Val::Arr(ArrValue::expr(ctx, items.iter().cloned()))581 Val::Arr(ArrValue::expr(ctx, items.iter().cloned()))
582 }582 }
modifiedcrates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth
17 operator::evaluate_add_op,17 operator::evaluate_add_op,
18 tb, throw,18 tb, throw,
19 val::ThunkValue,19 val::ThunkValue,
20 MaybeUnbound, Result, ResultExt, State, Thunk, Unbound, Val,20 MaybeUnbound, Result, State, Thunk, Unbound, Val,
21};21};
2222
23#[cfg(not(feature = "exp-preserve-order"))]23#[cfg(not(feature = "exp-preserve-order"))]
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
6use jrsonnet_types::{ComplexValType, ValType};6use jrsonnet_types::{ComplexValType, ValType};
77
8use crate::{8use crate::{
9 arr::ArrValue,9 arr::{ArrValue, BytesArray},
10 error::Result,10 error::Result,
11 function::{native::NativeDesc, FuncDesc, FuncVal},11 function::{native::NativeDesc, FuncDesc, FuncVal},
12 throw,12 throw,
434 }434 }
435435
436 fn from_untyped(value: Val) -> Result<Self> {436 fn from_untyped(value: Val) -> Result<Self> {
437 if let Val::Arr(ArrValue::Bytes(bytes)) = value {437 match &value {
438 Val::Arr(a) => {
439 if let Some(bytes) = a.as_any().downcast_ref::<BytesArray>() {
440 return Ok(bytes.0.as_slice().into());
438 return Ok(bytes.0);441 };
439 }
440 <Self as Typed>::TYPE.check(&value)?;442 <Self as Typed>::TYPE.check(&value)?;
441 match value {443 // Any::downcast_ref::<ByteArray>(&a);
442 Val::Arr(a) => {
443 let mut out = Vec::with_capacity(a.len());444 let mut out = Vec::with_capacity(a.len());
444 for e in a.iter() {445 for e in a.iter() {
445 let r = e?;446 let r = e?;
446 out.push(u8::from_untyped(r)?);447 out.push(u8::from_untyped(r)?);
447 }448 }
448 Ok(out.as_slice().into())449 Ok(out.as_slice().into())
449 }450 }
450 _ => unreachable!(),451 _ => {
451 }452 <Self as Typed>::TYPE.check(&value)?;
453 unreachable!()
454 }
455 }
452 }456 }
453}457}
454458
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
9use jrsonnet_interner::IStr;9use jrsonnet_interner::IStr;
10use jrsonnet_types::ValType;10use jrsonnet_types::ValType;
1111
12pub use crate::arr::ArrValue;12pub use crate::arr::{ArrValue, ArrayLike};
13use crate::{13use crate::{
14 error::{Error, ErrorKind::*},14 error::{Error, ErrorKind::*},
15 function::FuncVal,15 function::FuncVal,
modifiedcrates/jrsonnet-stdlib/src/sets.rsdiffbeforeafterboth
7 val::ArrValue,7 val::ArrValue,
8 Thunk, Val,8 Thunk, Val,
9};9};
10use jrsonnet_gcmodule::Cc;
11use jrsonnet_parser::BinaryOpType;10use jrsonnet_parser::BinaryOpType;
1211
13#[builtin]12#[builtin]
70 }69 }
71 };70 };
72 }71 }
73 Ok(ArrValue::lazy(Cc::new(out)))72 Ok(ArrValue::lazy(out))
74}73}
7574
modifiedcrates/jrsonnet-stdlib/src/sort.rsdiffbeforeafterboth
10 val::{equals, ArrValue},10 val::{equals, ArrValue},
11 Thunk, Val,11 Thunk, Val,
12};12};
13use jrsonnet_gcmodule::Cc;
14use jrsonnet_parser::BinaryOpType;13use jrsonnet_parser::BinaryOpType;
1514
16use crate::eval_on_empty;15use crate::eval_on_empty;
136 values.iter().collect::<Result<Vec<Val>>>()?,135 values.iter().collect::<Result<Vec<Val>>>()?,
137 )?))136 )?))
138 } else {137 } else {
139 Ok(ArrValue::lazy(Cc::new(sort_keyf(values, key_getter)?)))138 Ok(ArrValue::lazy(sort_keyf(values, key_getter)?))
140 }139 }
141}140}
142141
186 arr.iter().collect::<Result<Vec<Val>>>()?,185 arr.iter().collect::<Result<Vec<Val>>>()?,
187 )?))186 )?))
188 } else {187 } else {
189 Ok(ArrValue::lazy(Cc::new(uniq_keyf(arr, keyF)?)))188 Ok(ArrValue::lazy(uniq_keyf(arr, keyF)?))
190 }189 }
191}190}
192191
204 Ok(ArrValue::eager(arr))203 Ok(ArrValue::eager(arr))
205 } else {204 } else {
206 let arr = sort_keyf(arr, keyF.clone())?;205 let arr = sort_keyf(arr, keyF.clone())?;
207 let arr = uniq_keyf(ArrValue::lazy(Cc::new(arr)), keyF)?;206 let arr = uniq_keyf(ArrValue::lazy(arr), keyF)?;
208 Ok(ArrValue::lazy(Cc::new(arr)))207 Ok(ArrValue::lazy(arr))
209 }208 }
210}209}
211210