git.delta.rocks / jrsonnet / refs/commits / 4c3faa0f088c

difftreelog

refactor reduce callsite boilerplate

Yaroslav Bolyukin2022-12-08parent: #ccafbf7.patch.diff
in: master

38 files changed

modifiedbindings/jsonnet/src/import.rsdiffbeforeafterboth
117 ctx: *mut c_void,117 ctx: *mut c_void,
118) {118) {
119 vm.state119 vm.state.set_import_resolver(CallbackImportResolver {
120 .set_import_resolver(Box::new(CallbackImportResolver {
121 cb,120 cb,
122 ctx,121 ctx,
123 out: RefCell::new(HashMap::new()),122 out: RefCell::new(HashMap::new()),
124 }))123 })
125}124}
126125
127/// # Safety126/// # Safety
modifiedbindings/jsonnet/src/native.rsdiffbeforeafterboth
7use jrsonnet_evaluator::{7use jrsonnet_evaluator::{
8 error::{Error, ErrorKind},8 error::{Error, ErrorKind},
9 function::builtin::{NativeCallback, NativeCallbackHandler},9 function::builtin::{NativeCallback, NativeCallbackHandler},
10 tb,
11 typed::Typed,10 typed::Typed,
12 IStr, Val,11 IStr, Val,
13};12};
14use jrsonnet_gcmodule::Cc;
1513
16use crate::VM;14use crate::VM;
1715
102 .add_native(100 .add_native(
103 name,101 name,
104 #[allow(deprecated)]102 #[allow(deprecated)]
105 Cc::new(tb!(NativeCallback::new(103 NativeCallback::new(params, JsonnetNativeCallbackHandler { ctx, cb }),
106 params,
107 tb!(JsonnetNativeCallbackHandler { ctx, cb }),
108 ))),
109 )104 )
110}105}
111106
modifiedbindings/jsonnet/src/val_extract.rsdiffbeforeafterboth
13#[no_mangle]13#[no_mangle]
14pub extern "C" fn jsonnet_json_extract_string(_vm: &VM, v: &Val) -> *mut c_char {14pub extern "C" fn jsonnet_json_extract_string(_vm: &VM, v: &Val) -> *mut c_char {
15 match v {15 match v {
16 Val::Str(s) => CString::new(s as &str).unwrap().into_raw(),16 Val::Str(s) => {
17 let s = s.clone().into_flat();
18 CString::new(s.as_str()).unwrap().into_raw()
19 }
17 _ => std::ptr::null_mut(),20 _ => std::ptr::null_mut(),
18 }21 }
19}22}
modifiedbindings/jsonnet/src/val_make.rsdiffbeforeafterboth
6};6};
77
8use jrsonnet_evaluator::{val::ArrValue, ObjValue, Val};8use jrsonnet_evaluator::{
9use jrsonnet_gcmodule::Cc;9 val::{ArrValue, StrValue},
10 ObjValue, Val,
11};
1012
11use crate::VM;13use crate::VM;
19pub unsafe extern "C" fn jsonnet_json_make_string(_vm: &VM, val: *const c_char) -> *mut Val {21pub unsafe extern "C" fn jsonnet_json_make_string(_vm: &VM, val: *const c_char) -> *mut Val {
20 let val = CStr::from_ptr(val);22 let val = CStr::from_ptr(val);
21 let val = val.to_str().expect("string is not utf-8");23 let val = val.to_str().expect("string is not utf-8");
22 Box::into_raw(Box::new(Val::Str(val.into())))24 Box::into_raw(Box::new(Val::Str(StrValue::Flat(val.into()))))
23}25}
2426
25/// Convert the given double to a `JsonnetJsonValue`.27/// Convert the given double to a `JsonnetJsonValue`.
46/// Assign elements with [`jsonnet_json_array_append`].48/// Assign elements with [`jsonnet_json_array_append`].
47#[no_mangle]49#[no_mangle]
48pub extern "C" fn jsonnet_json_make_array(_vm: &VM) -> *mut Val {50pub extern "C" fn jsonnet_json_make_array(_vm: &VM) -> *mut Val {
49 Box::into_raw(Box::new(Val::Arr(ArrValue::eager(Cc::new(Vec::new())))))51 Box::into_raw(Box::new(Val::Arr(ArrValue::eager(Vec::new()))))
50}52}
5153
52/// Make a `JsonnetJsonValue` representing an object.54/// Make a `JsonnetJsonValue` representing an object.
modifiedcrates/jrsonnet-cli/src/lib.rsdiffbeforeafterboth
54 library_paths.extend(env::split_paths(path.as_os_str()));54 library_paths.extend(env::split_paths(path.as_os_str()));
55 }55 }
5656
57 s.set_import_resolver(Box::new(FileImportResolver::new(library_paths)));57 s.set_import_resolver(FileImportResolver::new(library_paths));
5858
59 set_stack_depth_limit(self.max_stack);59 set_stack_depth_limit(self.max_stack);
60 Ok(())60 Ok(())
modifiedcrates/jrsonnet-evaluator/src/arr/mod.rsdiffbeforeafterboth
55 Self::Lazy(LazyArray(thunks))55 Self::Lazy(LazyArray(thunks))
56 }56 }
5757
58 pub fn eager(values: Cc<Vec<Val>>) -> Self {58 pub fn eager(values: Vec<Val>) -> Self {
59 Self::Eager(EagerArray(values))59 Self::Eager(EagerArray(Cc::new(values)))
60 }60 }
6161
62 pub fn repeated(data: ArrValue, repeats: usize) -> Option<Self> {62 pub fn repeated(data: ArrValue, repeats: usize) -> Option<Self> {
81 out.push(i);81 out.push(i);
82 };82 };
83 }83 }
84 Ok(Self::eager(Cc::new(out)))84 Ok(Self::eager(out))
85 }85 }
8686
87 pub fn extended(a: ArrValue, b: ArrValue) -> Self {87 pub fn extended(a: ArrValue, b: ArrValue) -> Self {
98 let mut out = Vec::with_capacity(a.len() + b.len());98 let mut out = Vec::with_capacity(a.len() + b.len());
99 out.extend(a);99 out.extend(a);
100 out.extend(b);100 out.extend(b);
101 Self::eager(Cc::new(out))101 Self::eager(out)
102 } else {102 } else {
103 let mut out = Vec::with_capacity(a.len() + b.len());103 let mut out = Vec::with_capacity(a.len() + b.len());
104 out.extend(a.iter_lazy());104 out.extend(a.iter_lazy());
235}235}
236impl From<Vec<Val>> for ArrValue {236impl From<Vec<Val>> for ArrValue {
237 fn from(value: Vec<Val>) -> Self {237 fn from(value: Vec<Val>) -> Self {
238 Self::eager(Cc::new(value))238 Self::eager(value)
239 }239 }
240}240}
241impl From<Vec<Thunk<Val>>> for ArrValue {241impl From<Vec<Thunk<Val>>> for ArrValue {
242 fn from(value: Vec<Thunk<Val>>) -> Self {242 fn from(value: Vec<Thunk<Val>>) -> Self {
243 Self::lazy(Cc::new(value))243 Self::lazy(Cc::new(value))
244 }244 }
245}245}
246impl FromIterator<Val> for ArrValue {
247 fn from_iter<T: IntoIterator<Item = Val>>(iter: T) -> Self {
248 Self::eager(iter.into_iter().collect())
249 }
250}
246251
247#[cfg(target_pointer_width = "64")]252#[cfg(target_pointer_width = "64")]
248static_assertions::assert_eq_size!(ArrValue, [u8; 16]);253static_assertions::assert_eq_size!(ArrValue, [u8; 16]);
modifiedcrates/jrsonnet-evaluator/src/arr/spec.rsdiffbeforeafterboth
7use jrsonnet_interner::IBytes;7use jrsonnet_interner::IBytes;
8use jrsonnet_parser::LocExpr;8use jrsonnet_parser::LocExpr;
99
10use super::{ArrValue, ArrayLikeIter};10use super::ArrValue;
11use crate::{11use crate::{
12 error::ErrorKind::InfiniteRecursionDetected, evaluate, function::FuncVal, tb, typed::Any,12 error::ErrorKind::InfiniteRecursionDetected, evaluate, function::FuncVal, val::ThunkValue,
13 val::ThunkValue, Context, Error, Result, Thunk, Val,13 Context, Error, Result, Thunk, Val,
14};14};
1515
75 }75 }
7676
77 #[cfg(not(feature = "nightly"))]77 #[cfg(not(feature = "nightly"))]
78 fn iter_cheap(&self) -> Option<impl ArrayLikeIter<Val> + '_> {78 fn iter_cheap(&self) -> Option<impl crate::arr::ArrayLikeIter<Val> + '_> {
79 Some(79 Some(
80 self.inner80 self.inner
81 .iter_cheap()?81 .iter_cheap()?
300 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}300 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}
301 };301 };
302302
303 Some(Thunk::new(tb!(ArrayElement {303 Some(Thunk::new(ArrayElement {
304 arr_thunk: self.clone(),304 arr_thunk: self.clone(),
305 index,305 index,
306 })))306 }))
307 }307 }
308 fn get_cheap(&self, _index: usize) -> Option<Val> {308 fn get_cheap(&self, _index: usize) -> Option<Val> {
309 None309 None
748 .get(index)748 .get(index)
749 .transpose()749 .transpose()
750 .expect("index checked")750 .expect("index checked")
751 .and_then(|r| self.0.mapper.evaluate_simple(&(Any(r),)));751 .and_then(|r| self.0.mapper.evaluate_simple(&(r,)));
752752
753 let new_value = match val {753 let new_value = match val {
754 Ok(v) => v,754 Ok(v) => v,
787 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}787 ArrayThunk::Waiting(_) | ArrayThunk::Pending => {}
788 };788 };
789789
790 Some(Thunk::new(tb!(ArrayElement {790 Some(Thunk::new(ArrayElement {
791 arr_thunk: self.clone(),791 arr_thunk: self.clone(),
792 index,792 index,
793 })))793 }))
794 }794 }
795795
796 fn get_cheap(&self, _index: usize) -> Option<Val> {796 fn get_cheap(&self, _index: usize) -> Option<Val> {
modifiedcrates/jrsonnet-evaluator/src/async_import.rsdiffbeforeafterboth
294 path: handler.resolve(path.as_ref()).await?,294 path: handler.resolve(path.as_ref()).await?,
295 parse: true,295 parse: true,
296 }];296 }];
297 // let mut resolved = HashMap::<(SourcePath, IStr), (SourcePath, bool)>::new();
298 while let Some(job) = queue.pop() {297 while let Some(job) = queue.pop() {
299 match job {298 match job {
300 Job::LoadFile { path, parse } => {299 Job::LoadFile { path, parse } => {
349 }348 }
350 }349 }
351 }350 }
352 s.set_import_resolver(Box::new(ResolvedImportResolver {351 s.set_import_resolver(ResolvedImportResolver {
353 resolved: RefCell::new(resolved),352 resolved: RefCell::new(resolved),
354 }));353 });
355 Ok(())354 Ok(())
356}355}
357356
modifiedcrates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth
39 .expect("used state from dummy context")39 .expect("used state from dummy context")
40 }40 }
4141
42 pub fn dollar(&self) -> &Option<ObjValue> {42 pub fn dollar(&self) -> Option<&ObjValue> {
43 &self.0.dollar43 self.0.dollar.as_ref()
44 }44 }
4545
46 pub fn this(&self) -> &Option<ObjValue> {46 pub fn this(&self) -> Option<&ObjValue> {
47 &self.0.this47 self.0.this.as_ref()
48 }48 }
4949
50 pub fn super_obj(&self) -> &Option<ObjValue> {50 pub fn super_obj(&self) -> Option<&ObjValue> {
51 &self.0.sup51 self.0.sup.as_ref()
52 }52 }
5353
54 #[cfg(not(feature = "friendly-errors"))]54 #[cfg(not(feature = "friendly-errors"))]
131 }131 }
132}132}
133
134// impl Default for Context {
135// fn default() -> Self {
136// Self::new()
137// }
138// }
139133
140impl PartialEq for Context {134impl PartialEq for Context {
141 fn eq(&self, other: &Self) -> bool {135 fn eq(&self, other: &Self) -> bool {
modifiedcrates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth
6 error::{ErrorKind::*, Result},6 error::{ErrorKind::*, Result},
7 evaluate, evaluate_method, evaluate_named,7 evaluate, evaluate_method, evaluate_named,
8 gc::GcHashMap,8 gc::GcHashMap,
9 tb, throw,9 throw,
10 val::ThunkValue,10 val::ThunkValue,
11 Context, Pending, Thunk, Val,11 Context, Pending, Thunk, Val,
12};12};
63 }63 }
64 }64 }
6565
66 let full = Thunk::new(tb!(DataThunk {66 let full = Thunk::new(DataThunk {
67 min_len: start.len() + end.len(),67 min_len: start.len() + end.len(),
68 has_rest: rest.is_some(),68 has_rest: rest.is_some(),
69 parent,69 parent,
70 }));70 });
7171
72 {72 {
73 #[derive(Trace)]73 #[derive(Trace)]
86 for (i, d) in start.iter().enumerate() {86 for (i, d) in start.iter().enumerate() {
87 destruct(87 destruct(
88 d,88 d,
89 Thunk::new(tb!(BaseThunk {89 Thunk::new(BaseThunk {
90 full: full.clone(),90 full: full.clone(),
91 index: i,91 index: i,
92 })),92 }),
93 fctx.clone(),93 fctx.clone(),
94 new_bindings,94 new_bindings,
95 )?;95 )?;
119119
120 destruct(120 destruct(
121 &Destruct::Full(v.clone()),121 &Destruct::Full(v.clone()),
122 Thunk::new(tb!(RestThunk {122 Thunk::new(RestThunk {
123 full: full.clone(),123 full: full.clone(),
124 start: start.len(),124 start: start.len(),
125 end: end.len(),125 end: end.len(),
126 })),126 }),
127 fctx.clone(),127 fctx.clone(),
128 new_bindings,128 new_bindings,
129 )?;129 )?;
151 for (i, d) in end.iter().enumerate() {151 for (i, d) in end.iter().enumerate() {
152 destruct(152 destruct(
153 d,153 d,
154 Thunk::new(tb!(EndThunk {154 Thunk::new(EndThunk {
155 full: full.clone(),155 full: full.clone(),
156 index: i,156 index: i,
157 end: end.len(),157 end: end.len(),
158 })),158 }),
159 fctx.clone(),159 fctx.clone(),
160 new_bindings,160 new_bindings,
161 )?;161 )?;
199 .filter(|f| f.2.is_none())199 .filter(|f| f.2.is_none())
200 .map(|f| f.0.clone())200 .map(|f| f.0.clone())
201 .collect();201 .collect();
202 let full = Thunk::new(tb!(DataThunk {202 let full = Thunk::new(DataThunk {
203 parent,203 parent,
204 field_names,204 field_names,
205 has_rest: rest.is_some()205 has_rest: rest.is_some(),
206 }));206 });
207207
208 for (field, d, default) in fields {208 for (field, d, default) in fields {
209 #[derive(Trace)]209 #[derive(Trace)]
225 }225 }
226 }226 }
227 }227 }
228 let value = Thunk::new(tb!(FieldThunk {228 let value = Thunk::new(FieldThunk {
229 full: full.clone(),229 full: full.clone(),
230 field: field.clone(),230 field: field.clone(),
231 default: default.clone().map(|e| (fctx.clone(), e)),231 default: default.clone().map(|e| (fctx.clone(), e)),
232 }));232 });
233 if let Some(d) = d {233 if let Some(d) = d {
234 destruct(d, value, fctx.clone(), new_bindings)?;234 destruct(d, value, fctx.clone(), new_bindings)?;
235 } else {235 } else {
268 )268 )
269 }269 }
270 }270 }
271 let data = Thunk::new(tb!(EvaluateThunkValue {271 let data = Thunk::new(EvaluateThunkValue {
272 name: into.name(),272 name: into.name(),
273 fctx: fctx.clone(),273 fctx: fctx.clone(),
274 expr: value.clone(),274 expr: value.clone(),
275 }));275 });
276 destruct(into, data, fctx, new_bindings)?;276 destruct(into, data, fctx, new_bindings)?;
277 }277 }
278 BindSpec::Function {278 BindSpec::Function {
302302
303 let old = new_bindings.insert(303 let old = new_bindings.insert(
304 name.clone(),304 name.clone(),
305 Thunk::new(tb!(MethodThunk {305 Thunk::new(MethodThunk {
306 fctx,306 fctx,
307 name: name.clone(),307 name: name.clone(),
308 params: params.clone(),308 params: params.clone(),
309 value: value.clone()309 value: value.clone(),
310 })),310 }),
311 );311 );
312 if old.is_some() {312 if old.is_some() {
313 throw!(DuplicateLocalVar(name.clone()))313 throw!(DuplicateLocalVar(name.clone()))
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
15 error::ErrorKind::*,15 error::ErrorKind::*,
16 evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},16 evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},
17 function::{CallLocation, FuncDesc, FuncVal},17 function::{CallLocation, FuncDesc, FuncVal},
18 tb, throw,18 throw,
19 typed::Typed,19 typed::Typed,
20 val::{CachedUnbound, IndexableVal, StrValue, Thunk, ThunkValue},20 val::{CachedUnbound, IndexableVal, StrValue, Thunk, ThunkValue},
21 Context, GcHashMap, ObjValue, ObjValueBuilder, ObjectAssertion, Pending, Result, State,21 Context, GcHashMap, ObjValue, ObjValueBuilder, ObjectAssertion, Pending, Result, State,
45 if n.iter().any(|e| !is_trivial(e)) {45 if n.iter().any(|e| !is_trivial(e)) {
46 return None;46 return None;
47 }47 }
48 Val::Arr(ArrValue::eager(Cc::new(48 Val::Arr(ArrValue::eager(
49 n.iter()49 n.iter()
50 .map(evaluate_trivial)50 .map(evaluate_trivial)
51 .map(|e| e.expect("checked trivial"))51 .map(|e| e.expect("checked trivial"))
52 .collect(),52 .collect(),
53 )))53 ))
54 }54 }
55 Expr::Parened(e) => evaluate_trivial(e)?,55 Expr::Parened(e) => evaluate_trivial(e)?,
56 _ => return None,56 _ => return None,
136 let mut new_bindings = GcHashMap::with_capacity(var.capacity_hint());136 let mut new_bindings = GcHashMap::with_capacity(var.capacity_hint());
137 let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(Cc::new(vec![137 let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(Cc::new(vec![
138 Thunk::evaluated(Val::Str(StrValue::Flat(field.clone()))),138 Thunk::evaluated(Val::Str(StrValue::Flat(field.clone()))),
139 Thunk::new(tb!(ObjectFieldThunk {139 Thunk::new(ObjectFieldThunk {
140 field: field.clone(),140 field: field.clone(),
141 obj: obj.clone(),141 obj: obj.clone(),
142 })),142 }),
143 ]))));143 ]))));
144 destruct(var, value, fctx.clone(), &mut new_bindings)?;144 destruct(var, value, fctx.clone(), &mut new_bindings)?;
145 let ctx = ctx145 let ctx = ctx
180 }180 }
181181
182 let ctx = self.fctx.unwrap();182 let ctx = self.fctx.unwrap();
183 let new_dollar = ctx.dollar().clone().or_else(|| this.clone());183 let new_dollar = ctx.dollar().cloned().or_else(|| this.clone());
184184
185 let ctx = ctx185 let ctx = ctx
186 .extend(new_bindings, new_dollar, sup, this)186 .extend(new_bindings, new_dollar, sup, this)
230 .with_add(*plus)230 .with_add(*plus)
231 .with_visibility(*visibility)231 .with_visibility(*visibility)
232 .with_location(value.1.clone())232 .with_location(value.1.clone())
233 .bindable(tb!(UnboundValue {233 .bindable(UnboundValue {
234 uctx,234 uctx,
235 value: value.clone(),235 value: value.clone(),
236 name,236 name,
237 }))?;237 })?;
238 }238 }
239 FieldMember {239 FieldMember {
240 params: Some(params),240 params: Some(params),
265 .member(name.clone())265 .member(name.clone())
266 .with_visibility(*visibility)266 .with_visibility(*visibility)
267 .with_location(value.1.clone())267 .with_location(value.1.clone())
268 .bindable(tb!(UnboundMethod {268 .bindable(UnboundMethod {
269 uctx,269 uctx,
270 value: value.clone(),270 value: value.clone(),
271 params: params.clone(),271 params: params.clone(),
272 name,272 name,
273 }))?;273 })?;
274 }274 }
275 }275 }
276 Ok(())276 Ok(())
311 evaluate_assert(ctx, &self.assert)311 evaluate_assert(ctx, &self.assert)
312 }312 }
313 }313 }
314 builder.assert(tb!(ObjectAssert {314 builder.assert(ObjectAssert {
315 uctx: uctx.clone(),315 uctx: uctx.clone(),
316 assert: stmt.clone(),316 assert: stmt.clone(),
317 }));317 });
318 }318 }
319 Member::BindStmt(_) => {319 Member::BindStmt(_) => {
320 // Already handled320 // Already handled
420 let LocExpr(expr, loc) = expr;420 let LocExpr(expr, loc) = expr;
421 Ok(match &**expr {421 Ok(match &**expr {
422 Literal(LiteralType::This) => {422 Literal(LiteralType::This) => {
423 Val::Obj(ctx.this().clone().ok_or(CantUseSelfOutsideOfObject)?)423 Val::Obj(ctx.this().ok_or(CantUseSelfOutsideOfObject)?.clone())
424 }424 }
425 Literal(LiteralType::Super) => Val::Obj(425 Literal(LiteralType::Super) => Val::Obj(
426 ctx.super_obj().clone().ok_or(NoSuperFound)?.with_this(426 ctx.super_obj().ok_or(NoSuperFound)?.with_this(
427 ctx.this()427 ctx.this()
428 .clone()428 .expect("if super exists - then this should too")
429 .expect("if super exists - then this should too"),429 .clone(),
430 ),430 ),
431 ),431 ),
432 Literal(LiteralType::Dollar) => {432 Literal(LiteralType::Dollar) => {
433 Val::Obj(ctx.dollar().clone().ok_or(NoTopLevelObjectFound)?)433 Val::Obj(ctx.dollar().ok_or(NoTopLevelObjectFound)?.clone())
434 }434 }
435 Literal(LiteralType::True) => Val::Bool(true),435 Literal(LiteralType::True) => Val::Bool(true),
436 Literal(LiteralType::False) => Val::Bool(false),436 Literal(LiteralType::False) => Val::Bool(false),
455 ))455 ))
456 };456 };
457 ctx.super_obj()457 ctx.super_obj()
458 .clone()
459 .expect("no super found")458 .expect("no super found")
460 .get_for(name.into_flat(), ctx.this().clone().expect("no this found"))?459 .get_for(name.into_flat(), ctx.this().expect("no this found").clone())?
461 .expect("value not found")460 .expect("value not found")
462 }461 }
463 Index(value, index) => match (evaluate(ctx.clone(), value)?, evaluate(ctx, index)?) {462 Index(value, index) => match (evaluate(ctx.clone(), value)?, evaluate(ctx, index)?) {
563 evaluate(self.ctx, &self.item)562 evaluate(self.ctx, &self.item)
564 }563 }
565 }564 }
566 Val::Arr(ArrValue::lazy(Cc::new(vec![Thunk::new(tb!(565 Val::Arr(ArrValue::lazy(Cc::new(vec![Thunk::new(ArrayElement {
567 ArrayElement {
568 ctx,566 ctx,
569 item: items[0].clone(),567 item: items[0].clone(),
570 }568 })])))
571 ))])))
572 } else {569 } else {
573 Val::Arr(ArrValue::expr(ctx, items.iter().cloned()))570 Val::Arr(ArrValue::expr(ctx, items.iter().cloned()))
574 }571 }
579 out.push(evaluate(ctx, expr)?);576 out.push(evaluate(ctx, expr)?);
580 Ok(())577 Ok(())
581 })?;578 })?;
582 Val::Arr(ArrValue::eager(Cc::new(out)))579 Val::Arr(ArrValue::eager(out))
583 }580 }
584 Obj(body) => Val::Obj(evaluate_object(ctx, body)?),581 Obj(body) => Val::Obj(evaluate_object(ctx, body)?),
585 ObjExtend(a, b) => evaluate_add_op(582 ObjExtend(a, b) => evaluate_add_op(
623 fn parse_idx<T: Typed>(620 fn parse_idx<T: Typed>(
624 loc: CallLocation<'_>,621 loc: CallLocation<'_>,
625 ctx: &Context,622 ctx: &Context,
626 expr: &Option<LocExpr>,623 expr: Option<&LocExpr>,
627 desc: &'static str,624 desc: &'static str,
628 ) -> Result<Option<T>> {625 ) -> Result<Option<T>> {
629 if let Some(value) = expr {626 if let Some(value) = expr {
640 let indexable = evaluate(ctx.clone(), value)?;637 let indexable = evaluate(ctx.clone(), value)?;
641 let loc = CallLocation::new(loc);638 let loc = CallLocation::new(loc);
642639
643 let start = parse_idx(loc, &ctx, &desc.start, "start")?;640 let start = parse_idx(loc, &ctx, desc.start.as_ref(), "start")?;
644 let end = parse_idx(loc, &ctx, &desc.end, "end")?;641 let end = parse_idx(loc, &ctx, desc.end.as_ref(), "end")?;
645 let step = parse_idx(loc, &ctx, &desc.step, "step")?;642 let step = parse_idx(loc, &ctx, desc.step.as_ref(), "step")?;
646643
647 IndexableVal::into_untyped(indexable.into_indexable()?.slice(start, end, step)?)?644 IndexableVal::into_untyped(indexable.into_indexable()?.slice(start, end, step)?)?
648 }645 }
modifiedcrates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth
7 error::Result,7 error::Result,
8 evaluate,8 evaluate,
9 gc::GcHashMap,9 gc::GcHashMap,
10 tb,
11 typed::Typed,10 typed::Typed,
12 val::{StrValue, ThunkValue},11 val::{StrValue, ThunkValue},
13 Context, Thunk, Val,12 Context, Thunk, Val,
37 Ok(if tailstrict {36 Ok(if tailstrict {
38 Thunk::evaluated(evaluate(ctx, self)?)37 Thunk::evaluated(evaluate(ctx, self)?)
39 } else {38 } else {
40 Thunk::new(tb!(EvaluateThunk {39 Thunk::new(EvaluateThunk {
41 ctx,40 ctx,
42 expr: (*self).clone(),41 expr: (*self).clone(),
43 }))42 })
44 })43 })
45 }44 }
46}45}
69 TlaArg::Code(code) => Ok(if tailstrict {68 TlaArg::Code(code) => Ok(if tailstrict {
70 Thunk::evaluated(evaluate(ctx, code)?)69 Thunk::evaluated(evaluate(ctx, code)?)
71 } else {70 } else {
72 Thunk::new(tb!(EvaluateThunk {71 Thunk::new(EvaluateThunk {
73 ctx,72 ctx,
74 expr: code.clone(),73 expr: code.clone(),
75 }))74 })
76 }),75 }),
77 TlaArg::Val(val) => Ok(Thunk::evaluated(val.clone())),76 TlaArg::Val(val) => Ok(Thunk::evaluated(val.clone())),
78 }77 }
128 }127 }
129 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}128 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}
130}129}
131impl OptionalContext for Vec<Val> {}
132130
133impl ArgsLike for ArgsDesc {131impl ArgsLike for ArgsDesc {
134 fn unnamed_len(&self) -> usize {132 fn unnamed_len(&self) -> usize {
147 if tailstrict {145 if tailstrict {
148 Thunk::evaluated(evaluate(ctx.clone(), arg)?)146 Thunk::evaluated(evaluate(ctx.clone(), arg)?)
149 } else {147 } else {
150 Thunk::new(tb!(EvaluateThunk {148 Thunk::new(EvaluateThunk {
151 ctx: ctx.clone(),149 ctx: ctx.clone(),
152 expr: arg.clone(),150 expr: arg.clone(),
153 }))151 })
154 },152 },
155 )?;153 )?;
156 }154 }
169 if tailstrict {167 if tailstrict {
170 Thunk::evaluated(evaluate(ctx.clone(), arg)?)168 Thunk::evaluated(evaluate(ctx.clone(), arg)?)
171 } else {169 } else {
172 Thunk::new(tb!(EvaluateThunk {170 Thunk::new(EvaluateThunk {
173 ctx: ctx.clone(),171 ctx: ctx.clone(),
174 expr: arg.clone(),172 expr: arg.clone(),
175 }))173 })
176 },174 },
177 )?;175 )?;
178 }176 }
modifiedcrates/jrsonnet-evaluator/src/function/builtin.rsdiffbeforeafterboth
3use jrsonnet_gcmodule::Trace;3use jrsonnet_gcmodule::Trace;
44
5use super::{arglike::ArgsLike, parse::parse_builtin_call, CallLocation};5use super::{arglike::ArgsLike, parse::parse_builtin_call, CallLocation};
6use crate::{error::Result, gc::TraceBox, Context, Val};6use crate::{error::Result, gc::TraceBox, tb, Context, Val};
77
8pub type BuiltinParamName = Cow<'static, str>;8pub type BuiltinParamName = Cow<'static, str>;
99
42}42}
43impl NativeCallback {43impl NativeCallback {
44 #[deprecated = "prefer using builtins directly, use this interface only for bindings"]44 #[deprecated = "prefer using builtins directly, use this interface only for bindings"]
45 pub fn new(45 pub fn new(params: Vec<Cow<'static, str>>, handler: impl NativeCallbackHandler) -> Self {
46 params: Vec<Cow<'static, str>>,
47 handler: TraceBox<dyn NativeCallbackHandler>,
48 ) -> Self {
49 Self {46 Self {
50 params: params47 params: params
54 has_default: false,51 has_default: false,
55 })52 })
56 .collect(),53 .collect(),
57 handler,54 handler: tb!(handler),
58 }55 }
59 }56 }
60}57}
modifiedcrates/jrsonnet-evaluator/src/function/mod.rsdiffbeforeafterboth
12 native::NativeDesc,12 native::NativeDesc,
13 parse::{parse_default_function_call, parse_function_call},13 parse::{parse_default_function_call, parse_function_call},
14};14};
15use crate::{15use crate::{evaluate, evaluate_trivial, gc::TraceBox, tb, Context, ContextBuilder, Result, Val};
16 evaluate, evaluate_trivial, gc::TraceBox, typed::Any, Context, ContextBuilder, Result, Val,
17};
1816
19pub mod arglike;17pub mod arglike;
116}114}
117115
118impl FuncVal {116impl FuncVal {
117 pub fn builtin(builtin: impl Builtin) -> Self {
118 Self::Builtin(Cc::new(tb!(builtin)))
119 }
119 /// Amount of non-default required arguments120 /// Amount of non-default required arguments
120 pub fn params_len(&self) -> usize {121 pub fn params_len(&self) -> usize {
121 match self {122 match self {
148 Self::Id => {149 Self::Id => {
149 #[allow(clippy::unnecessary_wraps)]150 #[allow(clippy::unnecessary_wraps)]
150 #[builtin]151 #[builtin]
151 const fn builtin_id(v: Any) -> Result<Any> {152 const fn builtin_id(x: Val) -> Val {
152 Ok(v)153 x
153 }154 }
154 static ID: &builtin_id = &builtin_id {};155 static ID: &builtin_id = &builtin_id {};
155156
modifiedcrates/jrsonnet-evaluator/src/function/parse.rsdiffbeforeafterboth
10 error::{ErrorKind::*, Result},10 error::{ErrorKind::*, Result},
11 evaluate_named,11 evaluate_named,
12 gc::GcHashMap,12 gc::GcHashMap,
13 tb, throw,13 throw,
14 val::ThunkValue,14 val::ThunkValue,
15 Context, Pending, Thunk, Val,15 Context, Pending, Thunk, Val,
16};16};
100100
101 destruct(101 destruct(
102 &param.0,102 &param.0,
103 Thunk::new(tb!(EvaluateNamedThunk {103 Thunk::new(EvaluateNamedThunk {
104 ctx: fctx.clone(),104 ctx: fctx.clone(),
105 name: param.0.name().unwrap_or_else(|| "<destruct>".into()),105 name: param.0.name().unwrap_or_else(|| "<destruct>".into()),
106 value: param.1.clone().expect("default exists"),106 value: param.1.clone().expect("default exists"),
107 })),107 }),
108 fctx.clone(),108 fctx.clone(),
109 &mut defaults,109 &mut defaults,
110 )?;110 )?;
250 if let Some(v) = &param.1 {250 if let Some(v) = &param.1 {
251 destruct(251 destruct(
252 &param.0.clone(),252 &param.0.clone(),
253 Thunk::new(tb!(EvaluateNamedThunk {253 Thunk::new(EvaluateNamedThunk {
254 ctx: fctx.clone(),254 ctx: fctx.clone(),
255 name: param.0.name().unwrap_or_else(|| "<destruct>".into()),255 name: param.0.name().unwrap_or_else(|| "<destruct>".into()),
256 value: v.clone(),256 value: v.clone(),
257 })),257 }),
258 fctx.clone(),258 fctx.clone(),
259 &mut bindings,259 &mut bindings,
260 )?;260 )?;
261 } else {261 } else {
262 destruct(262 destruct(
263 &param.0,263 &param.0,
264 Thunk::new(tb!(DependsOnUnbound(264 Thunk::new(DependsOnUnbound(
265 param.0.name().unwrap_or_else(|| "<destruct>".into()),265 param.0.name().unwrap_or_else(|| "<destruct>".into()),
266 params.clone()266 params.clone(),
267 ))),267 )),
268 fctx.clone(),268 fctx.clone(),
269 &mut bindings,269 &mut bindings,
270 )?;270 )?;
modifiedcrates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth
1use std::borrow::Cow;1use std::borrow::Cow;
22
3use jrsonnet_gcmodule::Cc;
4use serde::{3use serde::{
5 de::Visitor,4 de::Visitor,
6 ser::{Error, SerializeMap, SerializeSeq},5 ser::{Error, SerializeMap, SerializeSeq},
117 out.push(val);116 out.push(val);
118 }117 }
119118
120 Ok(Val::Arr(ArrValue::eager(Cc::new(out))))119 Ok(Val::Arr(ArrValue::eager(out)))
121 }120 }
122121
123 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>122 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
433 pub fn import_resolver(&self) -> Ref<'_, dyn ImportResolver> {433 pub fn import_resolver(&self) -> Ref<'_, dyn ImportResolver> {
434 Ref::map(self.settings(), |s| &*s.import_resolver)434 Ref::map(self.settings(), |s| &*s.import_resolver)
435 }435 }
436 pub fn set_import_resolver(&self, resolver: Box<dyn ImportResolver>) {436 pub fn set_import_resolver(&self, resolver: impl ImportResolver) {
437 self.settings_mut().import_resolver = TraceBox(resolver);437 self.settings_mut().import_resolver = tb!(resolver);
438 }438 }
439 pub fn context_initializer(&self) -> Ref<'_, dyn ContextInitializer> {439 pub fn context_initializer(&self) -> Ref<'_, dyn ContextInitializer> {
440 Ref::map(self.settings(), |s| &*s.context_initializer)440 Ref::map(self.settings(), |s| &*s.context_initializer)
441 }441 }
442 pub fn set_context_initializer(&self, initializer: impl ContextInitializer) {
443 self.settings_mut().context_initializer = tb!(initializer);
444 }
442}445}
443446
modifiedcrates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth
15 function::CallLocation,15 function::CallLocation,
16 gc::{GcHashMap, GcHashSet, TraceBox},16 gc::{GcHashMap, GcHashSet, TraceBox},
17 operator::evaluate_add_op,17 operator::evaluate_add_op,
18 throw, MaybeUnbound, Result, State, Thunk, Unbound, Val,18 tb, throw, MaybeUnbound, Result, State, Thunk, Unbound, Val,
19};19};
2020
21#[cfg(not(feature = "exp-preserve-order"))]21#[cfg(not(feature = "exp-preserve-order"))]
538 self538 self
539 }539 }
540540
541 pub fn assert(&mut self, assertion: TraceBox<dyn ObjectAssertion>) -> &mut Self {541 pub fn assert(&mut self, assertion: impl ObjectAssertion + 'static) -> &mut Self {
542 self.assertions.push(assertion);542 self.assertions.push(tb!(assertion));
543 self543 self
544 }544 }
545 pub fn member(&mut self, name: IStr) -> ObjMemberBuilder<ValueBuilder<'_>> {545 pub fn member(&mut self, name: IStr) -> ObjMemberBuilder<ValueBuilder<'_>> {
631 pub fn thunk(self, value: Thunk<Val>) -> Result<()> {631 pub fn thunk(self, value: Thunk<Val>) -> Result<()> {
632 self.binding(MaybeUnbound::Bound(value))632 self.binding(MaybeUnbound::Bound(value))
633 }633 }
634 pub fn bindable(self, bindable: TraceBox<dyn Unbound<Bound = Val>>) -> Result<()> {634 pub fn bindable(self, bindable: impl Unbound<Bound = Val>) -> Result<()> {
635 self.binding(MaybeUnbound::Unbound(Cc::new(bindable)))635 self.binding(MaybeUnbound::Unbound(Cc::new(tb!(bindable))))
636 }636 }
637 pub fn binding(self, binding: MaybeUnbound) -> Result<()> {637 pub fn binding(self, binding: MaybeUnbound) -> Result<()> {
638 let (receiver, name, member) = self.build_member(binding);638 let (receiver, name, member) = self.build_member(binding);
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
30 fn into_untyped(typed: Self) -> Result<Val>;30 fn into_untyped(typed: Self) -> Result<Val>;
31 fn from_untyped(untyped: Val) -> Result<Self>;31 fn from_untyped(untyped: Val) -> Result<Self>;
32
33 /// Hack to make builtins be able to return non-result values, and make macros able to convert those values to result
34 /// This method returns identity in impl Typed for Result, and should not be overriden
35 #[doc(hidden)]
36 fn into_result(typed: Self) -> Result<Val> {
37 let value = Self::into_untyped(typed)?;
38 Ok(value)
39 }
32}40}
3341
34const MAX_SAFE_INTEGER: f64 = ((1u64 << (f64::MANTISSA_DIGITS + 1)) - 1) as f64;42const MAX_SAFE_INTEGER: f64 = ((1u64 << (f64::MANTISSA_DIGITS + 1)) - 1) as f64;
238 const TYPE: &'static ComplexValType = &ComplexValType::ArrayRef(T::TYPE);246 const TYPE: &'static ComplexValType = &ComplexValType::ArrayRef(T::TYPE);
239247
240 fn into_untyped(value: Self) -> Result<Val> {248 fn into_untyped(value: Self) -> Result<Val> {
241 let mut o = Vec::with_capacity(value.len());
242 for i in value {
243 o.push(T::into_untyped(i)?);
244 }
245 Ok(Val::Arr(o.into()))249 Ok(Val::Arr(
250 value
251 .into_iter()
252 .map(T::into_untyped)
253 .collect::<Result<ArrValue>>()?,
254 ))
246 }255 }
247256
248 fn from_untyped(value: Val) -> Result<Self> {257 fn from_untyped(value: Val) -> Result<Self> {
258 let Val::Arr(a) = value else {
249 <Self as Typed>::TYPE.check(&value)?;259 <Self as Typed>::TYPE.check(&value)?;
250 match value {
251 Val::Arr(a) => {260 unreachable!("typecheck should fail")
252 let mut o = Self::with_capacity(a.len());261 };
253 for i in a.iter() {262 a.iter()
254 o.push(T::from_untyped(i?)?);263 .map(|r| r.and_then(T::from_untyped))
255 }
256 Ok(o)
257 }
258 _ => unreachable!(),264 .collect::<Result<Vec<T>>>()
259 }
260 }265 }
261}266}
262
263/// To be used in Vec<Any>
264/// Regular Val can't be used here, because it has wrong `TryFrom::Error` type
265#[derive(Clone)]
266pub struct Any(pub Val);
267267
268impl Typed for Any {268impl Typed for Val {
269 const TYPE: &'static ComplexValType = &ComplexValType::Any;269 const TYPE: &'static ComplexValType = &ComplexValType::Any;
270270
271 fn into_untyped(value: Self) -> Result<Val> {271 fn into_untyped(typed: Self) -> Result<Val> {
272 Ok(value.0)272 Ok(typed)
273 }273 }
274
275 fn from_untyped(value: Val) -> Result<Self> {274 fn from_untyped(untyped: Val) -> Result<Self> {
276 Ok(Self(value))275 Ok(untyped)
277 }276 }
278}277}
279278
280/// Specialization, provides faster `TryFrom<VecVal>` for Val279// Hack
281pub struct VecVal(pub Vec<Val>);280#[doc(hidden)]
282
283impl Typed for VecVal {281impl<T> Typed for Result<T>
282where
283 T: Typed,
284{
284 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);285 const TYPE: &'static ComplexValType = &ComplexValType::Any;
285286
286 fn into_untyped(value: Self) -> Result<Val> {287 fn into_untyped(_typed: Self) -> Result<Val> {
287 Ok(Val::Arr(ArrValue::eager(Cc::new(value.0))))288 panic!("do not use this conversion")
288 }289 }
289290
290 fn from_untyped(value: Val) -> Result<Self> {291 fn from_untyped(_untyped: Val) -> Result<Self> {
291 <Self as Typed>::TYPE.check(&value)?;292 panic!("do not use this conversion")
292 match value {293 }
294
293 Val::Arr(a) => Ok(Self(a.iter().collect::<Result<Vec<_>>>()?)),295 fn into_result(typed: Self) -> Result<Val> {
294 _ => unreachable!(),296 typed.map(T::into_untyped)?
295 }297 }
296 }
297}298}
298299
299/// Specialization300/// Specialization
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
15 function::FuncVal,15 function::FuncVal,
16 gc::{GcHashMap, TraceBox},16 gc::{GcHashMap, TraceBox},
17 manifest::{ManifestFormat, ToStringFormat},17 manifest::{ManifestFormat, ToStringFormat},
18 throw,18 tb, throw,
19 typed::BoundedUsize,19 typed::BoundedUsize,
20 ObjValue, Result, Unbound, WeakObjValue,20 ObjValue, Result, Unbound, WeakObjValue,
21};21};
41 pub fn evaluated(val: T) -> Self {41 pub fn evaluated(val: T) -> Self {
42 Self(Cc::new(RefCell::new(ThunkInner::Computed(val))))42 Self(Cc::new(RefCell::new(ThunkInner::Computed(val))))
43 }43 }
44 pub fn new(f: TraceBox<dyn ThunkValue<Output = T>>) -> Self {44 pub fn new(f: impl ThunkValue<Output = T> + 'static) -> Self {
45 Self(Cc::new(RefCell::new(ThunkInner::Waiting(f))))45 Self(Cc::new(RefCell::new(ThunkInner::Waiting(tb!(f)))))
46 }46 }
47 pub fn errored(e: Error) -> Self {47 pub fn errored(e: Error) -> Self {
48 Self(Cc::new(RefCell::new(ThunkInner::Errored(e))))48 Self(Cc::new(RefCell::new(ThunkInner::Errored(e))))
modifiedcrates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth
192 item: proc_macro::TokenStream,192 item: proc_macro::TokenStream,
193) -> proc_macro::TokenStream {193) -> proc_macro::TokenStream {
194 let attr = parse_macro_input!(attr as BuiltinAttrs);194 let attr = parse_macro_input!(attr as BuiltinAttrs);
195 let item: ItemFn = parse_macro_input!(item);195 let item_fn = item.clone();
196 let item_fn: ItemFn = parse_macro_input!(item_fn);
196197
197 match builtin_inner(attr, item) {198 match builtin_inner(attr, item_fn, item.into()) {
198 Ok(v) => v.into(),199 Ok(v) => v.into(),
199 Err(e) => e.into_compile_error().into(),200 Err(e) => e.into_compile_error().into(),
200 }201 }
201}202}
202203
203fn builtin_inner(attr: BuiltinAttrs, fun: ItemFn) -> syn::Result<TokenStream> {204fn builtin_inner(
205 attr: BuiltinAttrs,
206 fun: ItemFn,
207 item: proc_macro2::TokenStream,
208) -> syn::Result<TokenStream> {
204 let ReturnType::Type(_, result) = &fun.sig.output else {209 let ReturnType::Type(_, result) = &fun.sig.output else {
205 return Err(Error::new(210 return Err(Error::new(
208 ))213 ))
209 };214 };
210
211 let Some(args) = type_is_path(result, "Result") else {
212 return Err(Error::new(result.span(), "return value should be result"));
213
214 };
215 let PathArguments::AngleBracketed(params) = args else {
216 return Err(Error::new(args.span(), "missing result generic"));
217 };
218 let generic_arg = params.args.iter().next().unwrap();
219 // This argument must be a type:
220 let GenericArgument::Type(result_inner) = generic_arg else {
221 return Err(Error::new(
222 generic_arg.span(),
223 "option generic should be a type",
224 ))
225 };
226215
227 let name = fun.sig.ident.to_string();216 let name = fun.sig.ident.to_string();
228 let args = fun217 let args = fun
355 };344 };
356345
357 Ok(quote! {346 Ok(quote! {
358 #fun347 #item
348
359 #[doc(hidden)]349 #[doc(hidden)]
360 #[allow(non_camel_case_types)]350 #[allow(non_camel_case_types)]
388 let parsed = parse_builtin_call(ctx.clone(), &PARAMS, args, false)?;378 let parsed = parse_builtin_call(ctx.clone(), &PARAMS, args, false)?;
389379
390 let result: #result = #name(#(#pass)*);380 let result: #result = #name(#(#pass)*);
391 let result = result?;
392 <#result_inner>::into_untyped(result)381 <_ as Typed>::into_result(result)
393 }382 }
394 }383 }
395 };384 };
modifiedcrates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth
2 error::{ErrorKind::RuntimeError, Result},2 error::{ErrorKind::RuntimeError, Result},
3 function::{builtin, FuncVal},3 function::{builtin, FuncVal},
4 throw,4 throw,
5 typed::{Any, BoundedI32, BoundedUsize, Either2, NativeFn, Typed},5 typed::{BoundedI32, BoundedUsize, Either2, NativeFn, Typed},
6 val::{equals, ArrValue, IndexableVal, StrValue},6 val::{equals, ArrValue, IndexableVal, StrValue},
7 Either, IStr, Val,7 Either, IStr, Val,
8};8};
9use jrsonnet_gcmodule::Cc;
109
11#[builtin]10#[builtin]
12pub fn builtin_make_array(sz: BoundedI32<0, { i32::MAX }>, func: FuncVal) -> Result<ArrValue> {11pub fn builtin_make_array(sz: BoundedI32<0, { i32::MAX }>, func: FuncVal) -> Result<ArrValue> {
18 for _ in 0..*sz {17 for _ in 0..*sz {
19 out.push(trivial.clone())18 out.push(trivial.clone())
20 }19 }
21 Ok(ArrValue::eager(Cc::new(out)))20 Ok(ArrValue::eager(out))
22 } else {21 } else {
23 Ok(ArrValue::range_exclusive(0, *sz).map(func))22 Ok(ArrValue::range_exclusive(0, *sz).map(func))
24 }23 }
25}24}
2625
27#[builtin]26#[builtin]
28pub fn builtin_repeat(what: Either![IStr, ArrValue], count: usize) -> Result<Any> {27pub fn builtin_repeat(what: Either![IStr, ArrValue], count: usize) -> Result<Val> {
29 Ok(Any(match what {28 Ok(match what {
30 Either2::A(s) => Val::Str(StrValue::Flat(s.repeat(count).into())),29 Either2::A(s) => Val::Str(StrValue::Flat(s.repeat(count).into())),
31 Either2::B(arr) => Val::Arr(30 Either2::B(arr) => Val::Arr(
32 ArrValue::repeated(arr, count)31 ArrValue::repeated(arr, count)
33 .ok_or_else(|| RuntimeError("repeated length overflow".into()))?,32 .ok_or_else(|| RuntimeError("repeated length overflow".into()))?,
34 ),33 ),
35 }))34 })
36}35}
3736
38#[builtin]37#[builtin]
41 index: Option<BoundedUsize<0, { i32::MAX as usize }>>,40 index: Option<BoundedUsize<0, { i32::MAX as usize }>>,
42 end: Option<BoundedUsize<0, { i32::MAX as usize }>>,41 end: Option<BoundedUsize<0, { i32::MAX as usize }>>,
43 step: Option<BoundedUsize<1, { i32::MAX as usize }>>,42 step: Option<BoundedUsize<1, { i32::MAX as usize }>>,
44) -> Result<Any> {43) -> Result<Val> {
45 indexable.slice(index, end, step).map(Val::from).map(Any)44 indexable.slice(index, end, step).map(Val::from)
46}45}
4746
48#[builtin]47#[builtin]
5251
53#[builtin]52#[builtin]
54pub fn builtin_flatmap(53pub fn builtin_flatmap(
55 func: NativeFn<((Either![String, Any],), Any)>,54 func: NativeFn<((Either![String, Val],), Val)>,
56 arr: IndexableVal,55 arr: IndexableVal,
57) -> Result<IndexableVal> {56) -> Result<IndexableVal> {
58 use std::fmt::Write;57 use std::fmt::Write;
59 match arr {58 match arr {
60 IndexableVal::Str(str) => {59 IndexableVal::Str(str) => {
61 let mut out = String::new();60 let mut out = String::new();
62 for c in str.chars() {61 for c in str.chars() {
63 match func(Either2::A(c.to_string()))?.0 {62 match func(Either2::A(c.to_string()))? {
64 Val::Str(o) => write!(out, "{o}").unwrap(),63 Val::Str(o) => write!(out, "{o}").unwrap(),
65 Val::Null => continue,64 Val::Null => continue,
66 _ => throw!("in std.join all items should be strings"),65 _ => throw!("in std.join all items should be strings"),
72 let mut out = Vec::new();71 let mut out = Vec::new();
73 for el in a.iter() {72 for el in a.iter() {
74 let el = el?;73 let el = el?;
75 match func(Either2::B(Any(el)))?.0 {74 match func(Either2::B(el))? {
76 Val::Arr(o) => {75 Val::Arr(o) => {
77 for oe in o.iter() {76 for oe in o.iter() {
78 out.push(oe?);77 out.push(oe?);
8988
90#[builtin]89#[builtin]
91pub fn builtin_filter(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {90pub fn builtin_filter(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {
92 arr.filter(|val| bool::from_untyped(func.evaluate_simple(&(Any(val.clone()),))?))91 arr.filter(|val| bool::from_untyped(func.evaluate_simple(&(val.clone(),))?))
93}92}
9493
95#[builtin]94#[builtin]
96pub fn builtin_foldl(func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {95pub fn builtin_foldl(func: FuncVal, arr: ArrValue, init: Val) -> Result<Val> {
97 let mut acc = init.0;96 let mut acc = init;
98 for i in arr.iter() {97 for i in arr.iter() {
99 acc = func.evaluate_simple(&(Any(acc), Any(i?)))?;98 acc = func.evaluate_simple(&(acc, i?))?;
100 }99 }
101 Ok(Any(acc))100 Ok(acc)
102}101}
103102
104#[builtin]103#[builtin]
105pub fn builtin_foldr(func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {104pub fn builtin_foldr(func: FuncVal, arr: ArrValue, init: Val) -> Result<Val> {
106 let mut acc = init.0;105 let mut acc = init;
107 for i in arr.iter().rev() {106 for i in arr.iter().rev() {
108 acc = func.evaluate_simple(&(Any(i?), Any(acc)))?;107 acc = func.evaluate_simple(&(i?, acc))?;
109 }108 }
110 Ok(Any(acc))109 Ok(acc)
111}110}
112111
113#[builtin]112#[builtin]
175}174}
176175
177#[builtin]176#[builtin]
178pub fn builtin_reverse(value: ArrValue) -> Result<ArrValue> {177pub fn builtin_reverse(arr: ArrValue) -> ArrValue {
179 Ok(value.reversed())178 arr.reversed()
180}179}
181180
182#[builtin]181#[builtin]
202}201}
203202
204#[builtin]203#[builtin]
205pub fn builtin_member(arr: IndexableVal, x: Any) -> Result<bool> {204pub fn builtin_member(arr: IndexableVal, x: Val) -> Result<bool> {
206 match arr {205 match arr {
207 IndexableVal::Str(str) => {206 IndexableVal::Str(str) => {
208 let x: IStr = IStr::from_untyped(x.0)?;207 let x: IStr = IStr::from_untyped(x)?;
209 Ok(!x.is_empty() && str.contains(&*x))208 Ok(!x.is_empty() && str.contains(&*x))
210 }209 }
211 IndexableVal::Arr(a) => {210 IndexableVal::Arr(a) => {
212 for item in a.iter() {211 for item in a.iter() {
213 let item = item?;212 let item = item?;
214 if equals(&item, &x.0)? {213 if equals(&item, &x)? {
215 return Ok(true);214 return Ok(true);
216 }215 }
217 }216 }
221}220}
222221
223#[builtin]222#[builtin]
224pub fn builtin_count(arr: Vec<Any>, v: Any) -> Result<usize> {223pub fn builtin_count(arr: ArrValue, x: Val) -> Result<usize> {
225 let mut count = 0;224 let mut count = 0;
226 for item in &arr {225 for item in arr.iter() {
227 if equals(&item.0, &v.0)? {226 if equals(&item?, &x)? {
228 count += 1;227 count += 1;
229 }228 }
230 }229 }
modifiedcrates/jrsonnet-stdlib/src/encoding.rsdiffbeforeafterboth
6};6};
77
8#[builtin]8#[builtin]
9pub fn builtin_encode_utf8(str: IStr) -> Result<IBytes> {9pub fn builtin_encode_utf8(str: IStr) -> IBytes {
10 Ok(str.cast_bytes())10 str.cast_bytes()
11}11}
1212
13#[builtin]13#[builtin]
18}18}
1919
20#[builtin]20#[builtin]
21pub fn builtin_base64(input: Either![IStr, IBytes]) -> Result<String> {21pub fn builtin_base64(input: Either![IStr, IBytes]) -> String {
22 use Either2::*;22 use Either2::*;
23 Ok(match input {23 match input {
24 A(l) => base64::encode(l.as_bytes()),24 A(l) => base64::encode(l.as_bytes()),
25 B(a) => base64::encode(a.as_slice()),25 B(a) => base64::encode(a.as_slice()),
26 })26 }
27}27}
2828
29#[builtin]29#[builtin]
30pub fn builtin_base64_decode_bytes(input: IStr) -> Result<IBytes> {30pub fn builtin_base64_decode_bytes(str: IStr) -> Result<IBytes> {
31 Ok(base64::decode(input.as_bytes())31 Ok(base64::decode(str.as_bytes())
32 .map_err(|_| RuntimeError("bad base64".into()))?32 .map_err(|_| RuntimeError("bad base64".into()))?
33 .as_slice()33 .as_slice()
34 .into())34 .into())
35}35}
3636
37#[builtin]37#[builtin]
38pub fn builtin_base64_decode(input: IStr) -> Result<String> {38pub fn builtin_base64_decode(str: IStr) -> Result<String> {
39 let bytes = base64::decode(input.as_bytes()).map_err(|_| RuntimeError("bad base64".into()))?;39 let bytes = base64::decode(str.as_bytes()).map_err(|_| RuntimeError("bad base64".into()))?;
40 Ok(String::from_utf8(bytes).map_err(|_| RuntimeError("bad utf8".into()))?)40 Ok(String::from_utf8(bytes).map_err(|_| RuntimeError("bad utf8".into()))?)
41}41}
4242
modifiedcrates/jrsonnet-stdlib/src/hash.rsdiffbeforeafterboth
1use jrsonnet_evaluator::{error::Result, function::builtin, IStr};1use jrsonnet_evaluator::{function::builtin, IStr};
22
3#[builtin]3#[builtin]
4pub fn builtin_md5(str: IStr) -> Result<String> {4pub fn builtin_md5(s: IStr) -> String {
5 Ok(format!("{:x}", md5::compute(str.as_bytes())))5 format!("{:x}", md5::compute(s.as_bytes()))
6}6}
77
8#[cfg(feature = "exp-more-hashes")]8#[cfg(feature = "exp-more-hashes")]
9#[builtin]9#[builtin]
10pub fn builtin_sha256(str: IStr) -> Result<String> {10pub fn builtin_sha256(s: IStr) -> String {
11 use sha2::digest::Digest;11 use sha2::digest::Digest;
12 Ok(format!("{:?}", sha2::Sha256::digest(str.as_bytes())))12 format!("{:?}", sha2::Sha256::digest(s.as_bytes()))
13}13}
1414
modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
155 builder155 builder
156 .member("extVar".into())156 .member("extVar".into())
157 .hide()157 .hide()
158 .value(Val::Func(FuncVal::Builtin(Cc::new(tb!(builtin_ext_var {158 .value(Val::Func(FuncVal::builtin(builtin_ext_var {
159 settings: settings.clone()159 settings: settings.clone(),
160 })))))160 })))
161 .expect("no conflict");161 .expect("no conflict");
162 builder162 builder
163 .member("native".into())163 .member("native".into())
164 .hide()164 .hide()
165 .value(Val::Func(FuncVal::Builtin(Cc::new(tb!(builtin_native {165 .value(Val::Func(FuncVal::builtin(builtin_native {
166 settings: settings.clone()166 settings: settings.clone(),
167 })))))167 })))
168 .expect("no conflict");168 .expect("no conflict");
169 builder169 builder
170 .member("trace".into())170 .member("trace".into())
171 .hide()171 .hide()
172 .value(Val::Func(FuncVal::Builtin(Cc::new(tb!(builtin_trace {172 .value(Val::Func(FuncVal::builtin(builtin_trace { settings })))
173 settings
174 })))))
175 .expect("no conflict");173 .expect("no conflict");
176174
177 builder175 builder
301 .insert(name.into(), TlaArg::Code(parsed));299 .insert(name.into(), TlaArg::Code(parsed));
302 Ok(())300 Ok(())
303 }301 }
304 pub fn add_native(&self, name: IStr, cb: Cc<TraceBox<dyn Builtin>>) {302 pub fn add_native(&self, name: IStr, cb: impl Builtin) {
305 self.settings_mut().ext_natives.insert(name, cb);303 self.settings_mut()
304 .ext_natives
305 .insert(name, Cc::new(tb!(cb)));
306 }306 }
307}307}
308impl jrsonnet_evaluator::ContextInitializer for ContextInitializer {308impl jrsonnet_evaluator::ContextInitializer for ContextInitializer {
modifiedcrates/jrsonnet-stdlib/src/manifest/mod.rsdiffbeforeafterboth
5 error::Result,5 error::Result,
6 function::builtin,6 function::builtin,
7 manifest::{escape_string_json, JsonFormat},7 manifest::{escape_string_json, JsonFormat},
8 typed::Any,
9 IStr, ObjValue, Val,8 IStr, ObjValue, Val,
10};9};
11pub use toml::TomlFormat;10pub use toml::TomlFormat;
1817
19#[builtin]18#[builtin]
20pub fn builtin_manifest_json_ex(19pub fn builtin_manifest_json_ex(
21 value: Any,20 value: Val,
22 indent: IStr,21 indent: IStr,
23 newline: Option<IStr>,22 newline: Option<IStr>,
24 key_val_sep: Option<IStr>,23 key_val_sep: Option<IStr>,
25 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,24 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,
26) -> Result<String> {25) -> Result<String> {
27 let newline = newline.as_deref().unwrap_or("\n");26 let newline = newline.as_deref().unwrap_or("\n");
28 let key_val_sep = key_val_sep.as_deref().unwrap_or(": ");27 let key_val_sep = key_val_sep.as_deref().unwrap_or(": ");
29 value.0.manifest(JsonFormat::std_to_json(28 value.manifest(JsonFormat::std_to_json(
30 indent.to_string(),29 indent.to_string(),
31 newline,30 newline,
32 key_val_sep,31 key_val_sep,
3736
38#[builtin]37#[builtin]
39pub fn builtin_manifest_yaml_doc(38pub fn builtin_manifest_yaml_doc(
40 value: Any,39 value: Val,
41 indent_array_in_object: Option<bool>,40 indent_array_in_object: Option<bool>,
42 quote_keys: Option<bool>,41 quote_keys: Option<bool>,
43 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,42 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,
44) -> Result<String> {43) -> Result<String> {
45 value.0.manifest(YamlFormat::std_to_yaml(44 value.manifest(YamlFormat::std_to_yaml(
46 indent_array_in_object.unwrap_or(false),45 indent_array_in_object.unwrap_or(false),
47 quote_keys.unwrap_or(true),46 quote_keys.unwrap_or(true),
48 #[cfg(feature = "exp-preserve-order")]47 #[cfg(feature = "exp-preserve-order")]
modifiedcrates/jrsonnet-stdlib/src/math.rsdiffbeforeafterboth
1use jrsonnet_evaluator::{error::Result, function::builtin, typed::PositiveF64};1use jrsonnet_evaluator::{function::builtin, typed::PositiveF64};
22
3#[builtin]3#[builtin]
4pub fn builtin_abs(n: f64) -> Result<f64> {4pub fn builtin_abs(n: f64) -> f64 {
5 Ok(n.abs())5 n.abs()
6}6}
77
8#[builtin]8#[builtin]
9pub fn builtin_sign(n: f64) -> Result<f64> {9pub fn builtin_sign(n: f64) -> f64 {
10 Ok(if n == 0. { 0. } else { n.signum() })10 if n == 0. {
11 0.
12 } else {
13 n.signum()
14 }
11}15}
1216
13#[builtin]17#[builtin]
14pub fn builtin_max(a: f64, b: f64) -> Result<f64> {18pub fn builtin_max(a: f64, b: f64) -> f64 {
15 Ok(a.max(b))19 a.max(b)
16}20}
1721
18#[builtin]22#[builtin]
19pub fn builtin_min(a: f64, b: f64) -> Result<f64> {23pub fn builtin_min(a: f64, b: f64) -> f64 {
20 Ok(a.min(b))24 a.min(b)
21}25}
2226
23#[builtin]27#[builtin]
24pub fn builtin_modulo(a: f64, b: f64) -> Result<f64> {28pub fn builtin_modulo(x: f64, y: f64) -> f64 {
25 Ok(a % b)29 x % y
26}30}
2731
28#[builtin]32#[builtin]
29pub fn builtin_floor(x: f64) -> Result<f64> {33pub fn builtin_floor(x: f64) -> f64 {
30 Ok(x.floor())34 x.floor()
31}35}
3236
33#[builtin]37#[builtin]
34pub fn builtin_ceil(x: f64) -> Result<f64> {38pub fn builtin_ceil(x: f64) -> f64 {
35 Ok(x.ceil())39 x.ceil()
36}40}
3741
38#[builtin]42#[builtin]
39pub fn builtin_log(n: f64) -> Result<f64> {43pub fn builtin_log(x: f64) -> f64 {
40 Ok(n.ln())44 x.ln()
41}45}
4246
43#[builtin]47#[builtin]
44pub fn builtin_pow(x: f64, n: f64) -> Result<f64> {48pub fn builtin_pow(x: f64, n: f64) -> f64 {
45 Ok(x.powf(n))49 x.powf(n)
46}50}
4751
48#[builtin]52#[builtin]
49pub fn builtin_sqrt(x: PositiveF64) -> Result<f64> {53pub fn builtin_sqrt(x: PositiveF64) -> f64 {
50 Ok(x.0.sqrt())54 x.0.sqrt()
51}55}
5256
53#[builtin]57#[builtin]
54pub fn builtin_sin(x: f64) -> Result<f64> {58pub fn builtin_sin(x: f64) -> f64 {
55 Ok(x.sin())59 x.sin()
56}60}
5761
58#[builtin]62#[builtin]
59pub fn builtin_cos(x: f64) -> Result<f64> {63pub fn builtin_cos(x: f64) -> f64 {
60 Ok(x.cos())64 x.cos()
61}65}
6266
63#[builtin]67#[builtin]
64pub fn builtin_tan(x: f64) -> Result<f64> {68pub fn builtin_tan(x: f64) -> f64 {
65 Ok(x.tan())69 x.tan()
66}70}
6771
68#[builtin]72#[builtin]
69pub fn builtin_asin(x: f64) -> Result<f64> {73pub fn builtin_asin(x: f64) -> f64 {
70 Ok(x.asin())74 x.asin()
71}75}
7276
73#[builtin]77#[builtin]
74pub fn builtin_acos(x: f64) -> Result<f64> {78pub fn builtin_acos(x: f64) -> f64 {
75 Ok(x.acos())79 x.acos()
76}80}
7781
78#[builtin]82#[builtin]
79pub fn builtin_atan(x: f64) -> Result<f64> {83pub fn builtin_atan(x: f64) -> f64 {
80 Ok(x.atan())84 x.atan()
81}85}
8286
83#[builtin]87#[builtin]
84pub fn builtin_exp(x: f64) -> Result<f64> {88pub fn builtin_exp(x: f64) -> f64 {
85 Ok(x.exp())89 x.exp()
86}90}
8791
88fn frexp(s: f64) -> (f64, i16) {92fn frexp(s: f64) -> (f64, i16) {
97}101}
98102
99#[builtin]103#[builtin]
100pub fn builtin_mantissa(x: f64) -> Result<f64> {104pub fn builtin_mantissa(x: f64) -> f64 {
101 Ok(frexp(x).0)105 frexp(x).0
102}106}
103107
104#[builtin]108#[builtin]
105pub fn builtin_exponent(x: f64) -> Result<i16> {109pub fn builtin_exponent(x: f64) -> i16 {
106 Ok(frexp(x).1)110 frexp(x).1
107}111}
108112
modifiedcrates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth
4 error::{ErrorKind::*, Result},4 error::{ErrorKind::*, Result},
5 function::{builtin, ArgLike, CallLocation, FuncVal},5 function::{builtin, ArgLike, CallLocation, FuncVal},
6 throw,6 throw,
7 typed::{Any, Either2, Either4},7 typed::{Either2, Either4},
8 val::{equals, ArrValue},8 val::{equals, ArrValue},
9 Context, Either, IStr, ObjValue, Thunk, Val,9 Context, Either, IStr, ObjValue, Thunk, Val,
10};10};
1111
12use crate::{extvar_source, Settings};12use crate::{extvar_source, Settings};
1313
14#[builtin]14#[builtin]
15pub fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> Result<usize> {15pub fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> usize {
16 use Either4::*;16 use Either4::*;
17 Ok(match x {17 match x {
18 A(x) => x.chars().count(),18 A(x) => x.chars().count(),
19 B(x) => x.len(),19 B(x) => x.len(),
20 C(x) => x.len(),20 C(x) => x.len(),
21 D(f) => f.params_len(),21 D(f) => f.params_len(),
22 })22 }
23}23}
2424
25#[builtin(fields(25#[builtin(fields(
26 settings: Rc<RefCell<Settings>>,26 settings: Rc<RefCell<Settings>>,
27))]27))]
28pub fn builtin_ext_var(this: &builtin_ext_var, ctx: Context, x: IStr) -> Result<Any> {28pub fn builtin_ext_var(this: &builtin_ext_var, ctx: Context, x: IStr) -> Result<Val> {
29 let ctx = ctx.state().create_default_context(extvar_source(&x, ""));29 let ctx = ctx.state().create_default_context(extvar_source(&x, ""));
30 Ok(Any(this30 this.settings
31 .settings
32 .borrow()31 .borrow()
33 .ext_vars32 .ext_vars
34 .get(&x)33 .get(&x)
35 .cloned()34 .cloned()
36 .ok_or_else(|| UndefinedExternalVariable(x))?35 .ok_or_else(|| UndefinedExternalVariable(x))?
37 .evaluate_arg(ctx, true)?36 .evaluate_arg(ctx, true)?
38 .evaluate()?))37 .evaluate()
39}38}
4039
41#[builtin(fields(40#[builtin(fields(
42 settings: Rc<RefCell<Settings>>,41 settings: Rc<RefCell<Settings>>,
43))]42))]
44pub fn builtin_native(this: &builtin_native, name: IStr) -> Result<Any> {43pub fn builtin_native(this: &builtin_native, x: IStr) -> Val {
45 Ok(Any(this44 this.settings
46 .settings45 .borrow()
47 .borrow()46 .ext_natives
48 .ext_natives47 .get(&x)
49 .get(&name)
50 .cloned()48 .cloned()
51 .map_or(Val::Null, |v| {49 .map_or(Val::Null, |v| Val::Func(FuncVal::Builtin(v.clone())))
52 Val::Func(FuncVal::Builtin(v.clone()))
53 })))
54}50}
5551
56#[builtin(fields(52#[builtin(fields(
61 loc: CallLocation,57 loc: CallLocation,
62 str: IStr,58 str: IStr,
63 rest: Thunk<Val>,59 rest: Thunk<Val>,
64) -> Result<Any> {60) -> Result<Val> {
65 this.settings.borrow().trace_printer.print_trace(loc, str);61 this.settings.borrow().trace_printer.print_trace(loc, str);
66 Ok(Any(rest.evaluate()?))62 rest.evaluate()
67}63}
6864
69#[allow(clippy::comparison_chain)]65#[allow(clippy::comparison_chain)]
modifiedcrates/jrsonnet-stdlib/src/objects.rsdiffbeforeafterboth
1use jrsonnet_evaluator::{1use jrsonnet_evaluator::{
2 error::Result,
3 function::builtin,2 function::builtin,
4 typed::VecVal,
5 val::{StrValue, Val},3 val::{StrValue, Val},
6 IStr, ObjValue,4 IStr, ObjValue,
7};5};
86
9#[builtin]7#[builtin]
10pub fn builtin_object_fields_ex(8pub fn builtin_object_fields_ex(
11 obj: ObjValue,9 obj: ObjValue,
12 inc_hidden: bool,10 hidden: bool,
13 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,11 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,
14) -> Result<VecVal> {12) -> Vec<Val> {
15 #[cfg(feature = "exp-preserve-order")]13 #[cfg(feature = "exp-preserve-order")]
16 let preserve_order = preserve_order.unwrap_or(false);14 let preserve_order = preserve_order.unwrap_or(false);
17 let out = obj.fields_ex(15 let out = obj.fields_ex(
18 inc_hidden,16 hidden,
19 #[cfg(feature = "exp-preserve-order")]17 #[cfg(feature = "exp-preserve-order")]
20 preserve_order,18 preserve_order,
21 );19 );
22 Ok(VecVal(
23 out.into_iter()20 out.into_iter()
24 .map(StrValue::Flat)21 .map(StrValue::Flat)
25 .map(Val::Str)22 .map(Val::Str)
26 .collect::<Vec<_>>(),23 .collect::<Vec<_>>()
27 ))
28}24}
2925
30#[builtin]26#[builtin]
31pub fn builtin_object_has_ex(obj: ObjValue, f: IStr, inc_hidden: bool) -> Result<bool> {27pub fn builtin_object_has_ex(obj: ObjValue, fname: IStr, hidden: bool) -> bool {
32 Ok(obj.has_field_ex(f, inc_hidden))28 obj.has_field_ex(fname, hidden)
33}29}
3430
modifiedcrates/jrsonnet-stdlib/src/operator.rsdiffbeforeafterboth
6 function::builtin,6 function::builtin,
7 operator::evaluate_mod_op,7 operator::evaluate_mod_op,
8 stdlib::std_format,8 stdlib::std_format,
9 typed::{Any, Either, Either2},9 typed::{Either, Either2},
10 val::{equals, primitive_equals, StrValue},10 val::{equals, primitive_equals, StrValue},
11 IStr, Val,11 IStr, Val,
12};12};
1313
14#[builtin]14#[builtin]
15pub fn builtin_mod(a: Either![f64, IStr], b: Any) -> Result<Any> {15pub fn builtin_mod(a: Either![f64, IStr], b: Val) -> Result<Val> {
16 use Either2::*;16 use Either2::*;
17 Ok(Any(evaluate_mod_op(17 evaluate_mod_op(
18 &match a {18 &match a {
19 A(v) => Val::Num(v),19 A(v) => Val::Num(v),
20 B(s) => Val::Str(StrValue::Flat(s)),20 B(s) => Val::Str(StrValue::Flat(s)),
21 },21 },
22 &b.0,22 &b,
23 )?))23 )
24}24}
2525
26#[builtin]26#[builtin]
27pub fn builtin_primitive_equals(a: Any, b: Any) -> Result<bool> {27pub fn builtin_primitive_equals(x: Val, y: Val) -> Result<bool> {
28 primitive_equals(&a.0, &b.0)28 primitive_equals(&x, &y)
29}29}
3030
31#[builtin]31#[builtin]
32pub fn builtin_equals(a: Any, b: Any) -> Result<bool> {32pub fn builtin_equals(a: Val, b: Val) -> Result<bool> {
33 equals(&a.0, &b.0)33 equals(&a, &b)
34}34}
3535
36#[builtin]36#[builtin]
37pub fn builtin_format(str: IStr, vals: Any) -> Result<String> {37pub fn builtin_format(str: IStr, vals: Val) -> Result<String> {
38 std_format(&str, vals.0)38 std_format(&str, vals)
39}39}
4040
modifiedcrates/jrsonnet-stdlib/src/parse.rsdiffbeforeafterboth
1use jrsonnet_evaluator::{1use jrsonnet_evaluator::{
2 error::{ErrorKind::RuntimeError, Result},2 error::{ErrorKind::RuntimeError, Result},
3 function::builtin,3 function::builtin,
4 typed::Any,
5 IStr, Val,4 IStr, Val,
6};5};
7use serde::Deserialize;6use serde::Deserialize;
87
9#[builtin]8#[builtin]
10pub fn builtin_parse_json(s: IStr) -> Result<Any> {9pub fn builtin_parse_json(str: IStr) -> Result<Val> {
11 let value: Val = serde_json::from_str(&s)10 let value: Val = serde_json::from_str(&str)
12 .map_err(|e| RuntimeError(format!("failed to parse json: {}", e).into()))?;11 .map_err(|e| RuntimeError(format!("failed to parse json: {}", e).into()))?;
13 Ok(Any(value))12 Ok(value)
14}13}
1514
16#[builtin]15#[builtin]
17pub fn builtin_parse_yaml(s: IStr) -> Result<Any> {16pub fn builtin_parse_yaml(str: IStr) -> Result<Val> {
18 use serde_yaml_with_quirks::DeserializingQuirks;17 use serde_yaml_with_quirks::DeserializingQuirks;
19 let value = serde_yaml_with_quirks::Deserializer::from_str_with_quirks(18 let value = serde_yaml_with_quirks::Deserializer::from_str_with_quirks(
20 &s,19 &str,
21 DeserializingQuirks { old_octals: true },20 DeserializingQuirks { old_octals: true },
22 );21 );
23 let mut out = vec![];22 let mut out = vec![];
26 .map_err(|e| RuntimeError(format!("failed to parse yaml: {}", e).into()))?;25 .map_err(|e| RuntimeError(format!("failed to parse yaml: {}", e).into()))?;
27 out.push(val);26 out.push(val);
28 }27 }
29 Ok(Any(if out.is_empty() {28 Ok(if out.is_empty() {
30 Val::Null29 Val::Null
31 } else if out.len() == 1 {30 } else if out.len() == 1 {
32 out.into_iter().next().unwrap()31 out.into_iter().next().unwrap()
33 } else {32 } else {
34 Val::Arr(out.into())33 Val::Arr(out.into())
35 }))34 })
36}35}
3736
modifiedcrates/jrsonnet-stdlib/src/sort.rsdiffbeforeafterboth
2 error::Result,2 error::Result,
3 function::{builtin, CallLocation, FuncVal},3 function::{builtin, CallLocation, FuncVal},
4 throw,4 throw,
5 typed::Any,
6 val::ArrValue,5 val::ArrValue,
7 Context, Val,6 Context, Val,
8};7};
9use jrsonnet_gcmodule::Cc;
108
11#[derive(Copy, Clone)]9#[derive(Copy, Clone)]
12enum SortKeyType {10enum SortKeyType {
78 key_getter.evaluate(76 key_getter.evaluate(
79 ctx.clone(),77 ctx.clone(),
80 CallLocation::native(),78 CallLocation::native(),
81 &(Any(value.clone()),),79 &(value.clone(),),
82 true,80 true,
83 )?,81 )?,
84 ));82 ));
105 if arr.len() <= 1 {103 if arr.len() <= 1 {
106 return Ok(arr);104 return Ok(arr);
107 }105 }
108 Ok(ArrValue::eager(Cc::new(super::sort::sort(106 Ok(ArrValue::eager(super::sort::sort(
109 ctx,107 ctx,
110 arr.iter().collect::<Result<Vec<_>>>()?,108 arr.iter().collect::<Result<Vec<_>>>()?,
111 keyF.unwrap_or_else(FuncVal::identity),109 keyF.unwrap_or_else(FuncVal::identity),
112 )?)))110 )?))
113}111}
114112
modifiedcrates/jrsonnet-stdlib/src/strings.rsdiffbeforeafterboth
2 error::{ErrorKind::*, Result},2 error::{ErrorKind::*, Result},
3 function::builtin,3 function::builtin,
4 throw,4 throw,
5 typed::{Either2, VecVal, M1},5 typed::{Either2, M1},
6 val::{ArrValue, StrValue},6 val::{ArrValue, StrValue},
7 Either, IStr, Val,7 Either, IStr, Val,
8};8};
99
10#[builtin]10#[builtin]
11pub const fn builtin_codepoint(str: char) -> Result<u32> {11pub const fn builtin_codepoint(str: char) -> u32 {
12 Ok(str as u32)12 str as u32
13}13}
1414
15#[builtin]15#[builtin]
16pub fn builtin_substr(str: IStr, from: usize, len: usize) -> Result<String> {16pub fn builtin_substr(str: IStr, from: usize, len: usize) -> String {
17 Ok(str.chars().skip(from).take(len).collect())17 str.chars().skip(from).take(len).collect()
18}18}
1919
20#[builtin]20#[builtin]
23}23}
2424
25#[builtin]25#[builtin]
26pub fn builtin_str_replace(str: String, from: IStr, to: IStr) -> Result<String> {26pub fn builtin_str_replace(str: String, from: IStr, to: IStr) -> String {
27 Ok(str.replace(&from as &str, &to as &str))27 str.replace(&from as &str, &to as &str)
28}28}
2929
30#[builtin]30#[builtin]
31pub fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> Result<VecVal> {31pub fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> ArrValue {
32 use Either2::*;32 use Either2::*;
33 Ok(VecVal(match maxsplits {33 match maxsplits {
34 A(n) => str34 A(n) => str
35 .splitn(n + 1, &c as &str)35 .splitn(n + 1, &c as &str)
36 .map(|s| Val::Str(StrValue::Flat(s.into())))36 .map(|s| Val::Str(StrValue::Flat(s.into())))
39 .split(&c as &str)39 .split(&c as &str)
40 .map(|s| Val::Str(StrValue::Flat(s.into())))40 .map(|s| Val::Str(StrValue::Flat(s.into())))
41 .collect(),41 .collect(),
42 }))42 }
43}43}
4444
45#[builtin]45#[builtin]
46pub fn builtin_ascii_upper(str: IStr) -> Result<String> {46pub fn builtin_ascii_upper(str: IStr) -> String {
47 Ok(str.to_ascii_uppercase())47 str.to_ascii_uppercase()
48}48}
4949
50#[builtin]50#[builtin]
51pub fn builtin_ascii_lower(str: IStr) -> Result<String> {51pub fn builtin_ascii_lower(str: IStr) -> String {
52 Ok(str.to_ascii_lowercase())52 str.to_ascii_lowercase()
53}53}
5454
55#[builtin]55#[builtin]
56pub fn builtin_find_substr(pat: IStr, str: IStr) -> Result<ArrValue> {56pub fn builtin_find_substr(pat: IStr, str: IStr) -> ArrValue {
57 if pat.is_empty() || str.is_empty() || pat.len() > str.len() {57 if pat.is_empty() || str.is_empty() || pat.len() > str.len() {
58 return Ok(ArrValue::empty());58 return ArrValue::empty();
59 }59 }
6060
61 let str = str.as_str();61 let str = str.as_str();
74 out.push(Val::Num(ch_idx as f64))74 out.push(Val::Num(ch_idx as f64))
75 }75 }
76 }76 }
77 Ok(out.into())77 out.into()
78}78}
7979
80#[builtin]80#[builtin]
modifiedcrates/jrsonnet-stdlib/src/types.rsdiffbeforeafterboth
1use jrsonnet_evaluator::{error::Result, function::builtin, typed::Any, IStr, Val};1use jrsonnet_evaluator::{function::builtin, IStr, Val};
22
3#[builtin]3#[builtin]
4pub fn builtin_type(v: Any) -> Result<IStr> {4pub fn builtin_type(x: Val) -> IStr {
5 Ok(v.0.value_type().name().into())5 x.value_type().name().into()
6}6}
77
8#[builtin]8#[builtin]
9pub fn builtin_is_string(v: Any) -> Result<bool> {9pub fn builtin_is_string(v: Val) -> bool {
10 Ok(matches!(v.0, Val::Str(_)))10 matches!(v, Val::Str(_))
11}11}
12#[builtin]12#[builtin]
13pub fn builtin_is_number(v: Any) -> Result<bool> {13pub fn builtin_is_number(v: Val) -> bool {
14 Ok(matches!(v.0, Val::Num(_)))14 matches!(v, Val::Num(_))
15}15}
16#[builtin]16#[builtin]
17pub fn builtin_is_boolean(v: Any) -> Result<bool> {17pub fn builtin_is_boolean(v: Val) -> bool {
18 Ok(matches!(v.0, Val::Bool(_)))18 matches!(v, Val::Bool(_))
19}19}
20#[builtin]20#[builtin]
21pub fn builtin_is_object(v: Any) -> Result<bool> {21pub fn builtin_is_object(v: Val) -> bool {
22 Ok(matches!(v.0, Val::Obj(_)))22 matches!(v, Val::Obj(_))
23}23}
24#[builtin]24#[builtin]
25pub fn builtin_is_array(v: Any) -> Result<bool> {25pub fn builtin_is_array(v: Val) -> bool {
26 Ok(matches!(v.0, Val::Arr(_)))26 matches!(v, Val::Arr(_))
27}27}
28#[builtin]28#[builtin]
29pub fn builtin_is_function(v: Any) -> Result<bool> {29pub fn builtin_is_function(v: Val) -> bool {
30 Ok(matches!(v.0, Val::Func(_)))30 matches!(v, Val::Func(_))
31}31}
3232
modifiedtests/tests/builtin.rsdiffbeforeafterboth
3use jrsonnet_evaluator::{3use jrsonnet_evaluator::{
4 error::Result,4 error::Result,
5 function::{builtin, builtin::Builtin, CallLocation, FuncVal},5 function::{builtin, builtin::Builtin, CallLocation, FuncVal},
6 tb,
7 typed::Typed,6 typed::Typed,
8 ContextBuilder, State, Thunk, Val,7 ContextBuilder, State, Thunk, Val,
9};8};
10use jrsonnet_gcmodule::Cc;
11use jrsonnet_stdlib::StateExt;9use jrsonnet_stdlib::StateExt;
1210
13#[builtin]11#[builtin]
6361
64#[builtin]62#[builtin]
65fn curry_add(a: u32) -> Result<FuncVal> {63fn curry_add(a: u32) -> Result<FuncVal> {
66 Ok(FuncVal::Builtin(Cc::new(tb!(curried_add { a }))))64 Ok(FuncVal::builtin(curried_add { a }))
67}65}
6866
69#[test]67#[test]
modifiedtests/tests/common.rsdiffbeforeafterboth
1use std::borrow::Cow;
2
1use jrsonnet_evaluator::{3use jrsonnet_evaluator::{
2 error::Result,4 error::Result,
53 Ok(true)55 Ok(true)
54}56}
57
58#[builtin]
59fn param_names(fun: FuncVal) -> Vec<String> {
60 match fun {
61 FuncVal::Id => vec!["x".to_string()],
62 FuncVal::Normal(func) => func
63 .params
64 .iter()
65 .map(|p| p.0.name().unwrap_or_else(|| "<unnamed>".into()).to_string())
66 .collect(),
67 FuncVal::StaticBuiltin(b) => b
68 .params()
69 .iter()
70 .map(|p| {
71 p.name
72 .as_ref()
73 .unwrap_or(&Cow::Borrowed("<unnamed>"))
74 .to_string()
75 })
76 .collect(),
77 FuncVal::Builtin(b) => b
78 .params()
79 .iter()
80 .map(|p| {
81 p.name
82 .as_ref()
83 .unwrap_or(&Cow::Borrowed("<unnamed>"))
84 .to_string()
85 })
86 .collect(),
87 }
88}
5589
56#[allow(dead_code)]90#[allow(dead_code)]
57pub fn with_test(s: &State) {91pub fn with_test(s: &State) {
58 let mut bobj = ObjValueBuilder::new();92 let mut bobj = ObjValueBuilder::new();
59 bobj.member("assertThrow".into())93 bobj.member("assertThrow".into())
60 .hide()94 .hide()
61 .value(Val::Func(FuncVal::StaticBuiltin(assert_throw::INST)))95 .value_unchecked(Val::Func(FuncVal::StaticBuiltin(assert_throw::INST)));
62 .expect("no error");96 bobj.member("paramNames".into())
97 .hide()
98 .value_unchecked(Val::Func(FuncVal::StaticBuiltin(param_names::INST)));
6399
64 s.add_global("test".into(), Thunk::evaluated(Val::Obj(bobj.build())))100 s.add_global("test".into(), Thunk::evaluated(Val::Obj(bobj.build())))
65}101}
modifiedtests/tests/golden.rsdiffbeforeafterboth
16 let s = State::default();16 let s = State::default();
17 s.with_stdlib();17 s.with_stdlib();
18 common::with_test(&s);18 common::with_test(&s);
19 s.set_import_resolver(Box::new(FileImportResolver::default()));19 s.set_import_resolver(FileImportResolver::default());
20 let trace_format = CompactFormat {20 let trace_format = CompactFormat {
21 resolver: PathResolver::FileName,21 resolver: PathResolver::FileName,
22 max_trace: 20,22 max_trace: 20,
modifiedtests/tests/suite.rsdiffbeforeafterboth
15 let s = State::default();15 let s = State::default();
16 s.with_stdlib();16 s.with_stdlib();
17 common::with_test(&s);17 common::with_test(&s);
18 s.set_import_resolver(Box::new(FileImportResolver::default()));18 s.set_import_resolver(FileImportResolver::default());
19 let trace_format = CompactFormat::default();19 let trace_format = CompactFormat::default();
2020
21 match s.import(file) {21 match s.import(file) {