git.delta.rocks / jrsonnet / refs/commits / cb29d2975edf

difftreelog

refactor remove implicit global state

Yaroslav Bolyukin2022-04-21parent: #0d5cefb.patch.diff
in: master

31 files changed

modifiedbindings/jsonnet/src/import.rsdiffbeforeafterboth
1515
16use jrsonnet_evaluator::{16use jrsonnet_evaluator::{
17 error::{Error::*, Result},17 error::{Error::*, Result},
18 throw, EvaluationState, ImportResolver,18 throw, ImportResolver, State,
19};19};
2020
21pub type JsonnetImportCallback = unsafe extern "C" fn(21pub type JsonnetImportCallback = unsafe extern "C" fn(
87/// # Safety87/// # Safety
88#[no_mangle]88#[no_mangle]
89pub unsafe extern "C" fn jsonnet_import_callback(89pub unsafe extern "C" fn jsonnet_import_callback(
90 vm: &EvaluationState,90 vm: &State,
91 cb: JsonnetImportCallback,91 cb: JsonnetImportCallback,
92 ctx: *mut c_void,92 ctx: *mut c_void,
93) {93) {
141///141///
142/// This function is safe, if received v is a pointer to normal C string142/// This function is safe, if received v is a pointer to normal C string
143#[no_mangle]143#[no_mangle]
144pub unsafe extern "C" fn jsonnet_jpath_add(vm: &EvaluationState, v: *const c_char) {144pub unsafe extern "C" fn jsonnet_jpath_add(vm: &State, v: *const c_char) {
145 let cstr = CStr::from_ptr(v);145 let cstr = CStr::from_ptr(v);
146 let path = PathBuf::from(cstr.to_str().unwrap());146 let path = PathBuf::from(cstr.to_str().unwrap());
147 let any_resolver = &vm.settings().import_resolver;147 let any_resolver = &vm.settings().import_resolver;
modifiedbindings/jsonnet/src/interop.rsdiffbeforeafterboth
5 os::raw::{c_char, c_int},5 os::raw::{c_char, c_int},
6};6};
77
8use jrsonnet_evaluator::{EvaluationState, Val};8use jrsonnet_evaluator::{State, Val};
99
10use crate::{import::jsonnet_import_callback, native::jsonnet_native_callback};10use crate::{import::jsonnet_import_callback, native::jsonnet_native_callback};
1111
2828
29/// # Safety29/// # Safety
30#[no_mangle]30#[no_mangle]
31pub unsafe extern "C" fn jrsonnet_apply_static_import_callback(31pub unsafe extern "C" fn jrsonnet_apply_static_import_callback(vm: &State, ctx: *mut c_void) {
32 vm: &EvaluationState,
33 ctx: *mut c_void,
34) {
35 jsonnet_import_callback(vm, _jrsonnet_static_import_callback, ctx)32 jsonnet_import_callback(vm, _jrsonnet_static_import_callback, ctx)
38/// # Safety35/// # Safety
39#[no_mangle]36#[no_mangle]
40pub unsafe extern "C" fn jrsonnet_apply_static_native_callback(37pub unsafe extern "C" fn jrsonnet_apply_static_native_callback(
41 vm: &EvaluationState,38 vm: &State,
42 name: *const c_char,39 name: *const c_char,
43 ctx: *mut c_void,40 ctx: *mut c_void,
44 raw_params: *const *const c_char,41 raw_params: *const *const c_char,
47}44}
4845
49#[no_mangle]46#[no_mangle]
50pub extern "C" fn jrsonnet_set_trace_format(vm: &EvaluationState, format: u8) {47pub extern "C" fn jrsonnet_set_trace_format(vm: &State, format: u8) {
51 use jrsonnet_evaluator::trace::JsFormat;48 use jrsonnet_evaluator::trace::JsFormat;
52 match format {49 match format {
53 1 => vm.set_trace_format(Box::new(JsFormat)),50 1 => vm.set_trace_format(Box::new(JsFormat)),
modifiedbindings/jsonnet/src/lib.rsdiffbeforeafterboth
16};16};
1717
18use import::NativeImportResolver;18use import::NativeImportResolver;
19use jrsonnet_evaluator::{EvaluationState, IStr, ManifestFormat, Val};19use jrsonnet_evaluator::{IStr, ManifestFormat, State, Val};
2020
21/// WASM stub21/// WASM stub
22#[cfg(target_arch = "wasm32")]22#[cfg(target_arch = "wasm32")]
29}29}
3030
31#[no_mangle]31#[no_mangle]
32pub extern "C" fn jsonnet_make() -> *mut EvaluationState {32pub extern "C" fn jsonnet_make() -> *mut State {
33 let state = EvaluationState::default();33 let state = State::default();
34 state.with_stdlib();34 state.with_stdlib();
35 state.settings_mut().import_resolver = Box::new(NativeImportResolver::default());35 state.settings_mut().import_resolver = Box::new(NativeImportResolver::default());
36 Box::into_raw(Box::new(state))36 Box::into_raw(Box::new(state))
39/// # Safety39/// # Safety
40#[no_mangle]40#[no_mangle]
41#[allow(clippy::boxed_local)]41#[allow(clippy::boxed_local)]
42pub unsafe extern "C" fn jsonnet_destroy(vm: *mut EvaluationState) {42pub unsafe extern "C" fn jsonnet_destroy(vm: *mut State) {
43 Box::from_raw(vm);43 Box::from_raw(vm);
44}44}
4545
46#[no_mangle]46#[no_mangle]
47pub extern "C" fn jsonnet_max_stack(vm: &EvaluationState, v: c_uint) {47pub extern "C" fn jsonnet_max_stack(vm: &State, v: c_uint) {
48 vm.settings_mut().max_stack = v as usize;48 vm.settings_mut().max_stack = v as usize;
49}49}
5050
51// jrsonnet currently have no GC, so these functions is no-op51// jrsonnet currently have no GC, so these functions is no-op
52#[no_mangle]52#[no_mangle]
53pub extern "C" fn jsonnet_gc_min_objects(_vm: &EvaluationState, _v: c_uint) {}53pub extern "C" fn jsonnet_gc_min_objects(_vm: &State, _v: c_uint) {}
54#[no_mangle]54#[no_mangle]
55pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &EvaluationState, _v: c_double) {}55pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &State, _v: c_double) {}
5656
57#[no_mangle]57#[no_mangle]
58pub extern "C" fn jsonnet_string_output(vm: &EvaluationState, v: c_int) {58pub extern "C" fn jsonnet_string_output(vm: &State, v: c_int) {
59 match v {59 match v {
60 1 => vm.set_manifest_format(ManifestFormat::String),60 1 => vm.set_manifest_format(ManifestFormat::String),
61 0 => vm.set_manifest_format(ManifestFormat::Json {61 0 => vm.set_manifest_format(ManifestFormat::Json {
71///71///
72/// This function is most definitely broken, but it works somehow, see TODO inside72/// This function is most definitely broken, but it works somehow, see TODO inside
73#[no_mangle]73#[no_mangle]
74pub unsafe extern "C" fn jsonnet_realloc(74pub unsafe extern "C" fn jsonnet_realloc(_vm: &State, buf: *mut u8, sz: usize) -> *mut u8 {
75 _vm: &EvaluationState,
76 buf: *mut u8,
77 sz: usize,
78) -> *mut u8 {
95/// # Safety91/// # Safety
96#[no_mangle]92#[no_mangle]
97#[allow(clippy::boxed_local)]93#[allow(clippy::boxed_local)]
98pub unsafe extern "C" fn jsonnet_json_destroy(_vm: &EvaluationState, v: *mut Val) {94pub unsafe extern "C" fn jsonnet_json_destroy(_vm: &State, v: *mut Val) {
99 Box::from_raw(v);95 Box::from_raw(v);
100}96}
10197
102#[no_mangle]98#[no_mangle]
103pub extern "C" fn jsonnet_max_trace(vm: &EvaluationState, v: c_uint) {99pub extern "C" fn jsonnet_max_trace(vm: &State, v: c_uint) {
104 vm.set_max_trace(v as usize)100 vm.set_max_trace(v as usize)
105}101}
106102
109/// This function is safe, if received v is a pointer to normal C string105/// This function is safe, if received v is a pointer to normal C string
110#[no_mangle]106#[no_mangle]
111pub unsafe extern "C" fn jsonnet_evaluate_file(107pub unsafe extern "C" fn jsonnet_evaluate_file(
112 vm: &EvaluationState,108 vm: &State,
113 filename: *const c_char,109 filename: *const c_char,
114 error: &mut c_int,110 error: &mut c_int,
115) -> *const c_char {111) -> *const c_char {
116 vm.run_in_state(|| {
117 let filename = CStr::from_ptr(filename);112 let filename = CStr::from_ptr(filename);
118 match vm113 match vm
119 .evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))114 .evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))
130 CString::new(&out as &str).unwrap().into_raw()125 CString::new(&out as &str).unwrap().into_raw()
131 }126 }
132 }127 }
133 })
134}128}
135129
136/// # Safety130/// # Safety
137///131///
138/// This function is safe, if received v is a pointer to normal C string132/// This function is safe, if received v is a pointer to normal C string
139#[no_mangle]133#[no_mangle]
140pub unsafe extern "C" fn jsonnet_evaluate_snippet(134pub unsafe extern "C" fn jsonnet_evaluate_snippet(
141 vm: &EvaluationState,135 vm: &State,
142 filename: *const c_char,136 filename: *const c_char,
143 snippet: *const c_char,137 snippet: *const c_char,
144 error: &mut c_int,138 error: &mut c_int,
145) -> *const c_char {139) -> *const c_char {
146 vm.run_in_state(|| {
147 let filename = CStr::from_ptr(filename);140 let filename = CStr::from_ptr(filename);
148 let snippet = CStr::from_ptr(snippet);141 let snippet = CStr::from_ptr(snippet);
149 match vm142 match vm
164 CString::new(&out as &str).unwrap().into_raw()157 CString::new(&out as &str).unwrap().into_raw()
165 }158 }
166 }159 }
167 })
168}160}
169161
170fn multi_to_raw(multi: Vec<(IStr, IStr)>) -> *const c_char {162fn multi_to_raw(multi: Vec<(IStr, IStr)>) -> *const c_char {
187/// # Safety179/// # Safety
188#[no_mangle]180#[no_mangle]
189pub unsafe extern "C" fn jsonnet_evaluate_file_multi(181pub unsafe extern "C" fn jsonnet_evaluate_file_multi(
190 vm: &EvaluationState,182 vm: &State,
191 filename: *const c_char,183 filename: *const c_char,
192 error: &mut c_int,184 error: &mut c_int,
193) -> *const c_char {185) -> *const c_char {
194 vm.run_in_state(|| {
195 let filename = CStr::from_ptr(filename);186 let filename = CStr::from_ptr(filename);
196 match vm187 match vm
197 .evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))188 .evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))
208 CString::new(&out as &str).unwrap().into_raw()199 CString::new(&out as &str).unwrap().into_raw()
209 }200 }
210 }201 }
211 })
212}202}
213203
214/// # Safety204/// # Safety
215#[no_mangle]205#[no_mangle]
216pub unsafe extern "C" fn jsonnet_evaluate_snippet_multi(206pub unsafe extern "C" fn jsonnet_evaluate_snippet_multi(
217 vm: &EvaluationState,207 vm: &State,
218 filename: *const c_char,208 filename: *const c_char,
219 snippet: *const c_char,209 snippet: *const c_char,
220 error: &mut c_int,210 error: &mut c_int,
221) -> *const c_char {211) -> *const c_char {
222 vm.run_in_state(|| {
223 let filename = CStr::from_ptr(filename);212 let filename = CStr::from_ptr(filename);
224 let snippet = CStr::from_ptr(snippet);213 let snippet = CStr::from_ptr(snippet);
225 match vm214 match vm
240 CString::new(&out as &str).unwrap().into_raw()229 CString::new(&out as &str).unwrap().into_raw()
241 }230 }
242 }231 }
243 })
244}232}
245233
246fn stream_to_raw(multi: Vec<IStr>) -> *const c_char {234fn stream_to_raw(multi: Vec<IStr>) -> *const c_char {
261/// # Safety249/// # Safety
262#[no_mangle]250#[no_mangle]
263pub unsafe extern "C" fn jsonnet_evaluate_file_stream(251pub unsafe extern "C" fn jsonnet_evaluate_file_stream(
264 vm: &EvaluationState,252 vm: &State,
265 filename: *const c_char,253 filename: *const c_char,
266 error: &mut c_int,254 error: &mut c_int,
267) -> *const c_char {255) -> *const c_char {
268 vm.run_in_state(|| {
269 let filename = CStr::from_ptr(filename);256 let filename = CStr::from_ptr(filename);
270 match vm257 match vm
271 .evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))258 .evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))
282 CString::new(&out as &str).unwrap().into_raw()269 CString::new(&out as &str).unwrap().into_raw()
283 }270 }
284 }271 }
285 })
286}272}
287273
288/// # Safety274/// # Safety
289#[no_mangle]275#[no_mangle]
290pub unsafe extern "C" fn jsonnet_evaluate_snippet_stream(276pub unsafe extern "C" fn jsonnet_evaluate_snippet_stream(
291 vm: &EvaluationState,277 vm: &State,
292 filename: *const c_char,278 filename: *const c_char,
293 snippet: *const c_char,279 snippet: *const c_char,
294 error: &mut c_int,280 error: &mut c_int,
295) -> *const c_char {281) -> *const c_char {
296 vm.run_in_state(|| {
297 let filename = CStr::from_ptr(filename);282 let filename = CStr::from_ptr(filename);
298 let snippet = CStr::from_ptr(snippet);283 let snippet = CStr::from_ptr(snippet);
299 match vm284 match vm
314 CString::new(&out as &str).unwrap().into_raw()299 CString::new(&out as &str).unwrap().into_raw()
315 }300 }
316 }301 }
317 })
318}302}
319303
modifiedbindings/jsonnet/src/native.rsdiffbeforeafterboth
1use std::{1use std::{
2 convert::TryFrom,
3 ffi::{c_void, CStr},2 ffi::{c_void, CStr},
4 os::raw::{c_char, c_int},3 os::raw::{c_char, c_int},
5 path::Path,4 path::Path,
12 function::BuiltinParam,11 function::BuiltinParam,
13 gc::TraceBox,12 gc::TraceBox,
14 native::{NativeCallback, NativeCallbackHandler},13 native::{NativeCallback, NativeCallbackHandler},
15 EvaluationState, IStr, Val,14 typed::Typed,
15 IStr, State, Val,
16};16};
1717
18type JsonnetNativeCallback = unsafe extern "C" fn(18type JsonnetNativeCallback = unsafe extern "C" fn(
29 cb: JsonnetNativeCallback,29 cb: JsonnetNativeCallback,
30}30}
31impl NativeCallbackHandler for JsonnetNativeCallbackHandler {31impl NativeCallbackHandler for JsonnetNativeCallbackHandler {
32 fn call(&self, _from: Option<Rc<Path>>, args: &[Val]) -> Result<Val, LocError> {32 fn call(&self, s: State, _from: Option<Rc<Path>>, args: &[Val]) -> Result<Val, LocError> {
33 let mut n_args = Vec::new();33 let mut n_args = Vec::new();
34 for a in args {34 for a in args {
35 n_args.push(Some(Box::new(a.clone())));35 n_args.push(Some(Box::new(a.clone())));
47 if success == 1 {47 if success == 1 {
48 Ok(v)48 Ok(v)
49 } else {49 } else {
50 let e = IStr::try_from(v).expect("error msg");50 let e = IStr::from_untyped(v, s).expect("error msg");
51 Err(Error::RuntimeError(e).into())51 Err(Error::RuntimeError(e).into())
52 }52 }
53 }53 }
56/// # Safety56/// # Safety
57#[no_mangle]57#[no_mangle]
58pub unsafe extern "C" fn jsonnet_native_callback(58pub unsafe extern "C" fn jsonnet_native_callback(
59 vm: &EvaluationState,59 vm: &State,
60 name: *const c_char,60 name: *const c_char,
61 cb: JsonnetNativeCallback,61 cb: JsonnetNativeCallback,
62 ctx: *const c_void,62 ctx: *const c_void,
modifiedbindings/jsonnet/src/val_extract.rsdiffbeforeafterboth
5 os::raw::{c_char, c_double, c_int},5 os::raw::{c_char, c_double, c_int},
6};6};
77
8use jrsonnet_evaluator::{EvaluationState, Val};8use jrsonnet_evaluator::{State, Val};
99
10#[no_mangle]10#[no_mangle]
11pub extern "C" fn jsonnet_json_extract_string(_vm: &EvaluationState, v: &Val) -> *mut c_char {11pub extern "C" fn jsonnet_json_extract_string(_vm: &State, v: &Val) -> *mut c_char {
12 match v {12 match v {
13 Val::Str(s) => CString::new(&*s as &str).unwrap().into_raw(),13 Val::Str(s) => CString::new(&*s as &str).unwrap().into_raw(),
14 _ => std::ptr::null_mut(),14 _ => std::ptr::null_mut(),
15 }15 }
16}16}
17#[no_mangle]17#[no_mangle]
18pub extern "C" fn jsonnet_json_extract_number(18pub extern "C" fn jsonnet_json_extract_number(_vm: &State, v: &Val, out: &mut c_double) -> c_int {
19 _vm: &EvaluationState,
20 v: &Val,
21 out: &mut c_double,
22) -> c_int {
29 }25 }
30}26}
31#[no_mangle]27#[no_mangle]
32pub extern "C" fn jsonnet_json_extract_bool(_vm: &EvaluationState, v: &Val) -> c_int {28pub extern "C" fn jsonnet_json_extract_bool(_vm: &State, v: &Val) -> c_int {
33 match v {29 match v {
34 Val::Bool(false) => 0,30 Val::Bool(false) => 0,
35 Val::Bool(true) => 1,31 Val::Bool(true) => 1,
36 _ => 2,32 _ => 2,
37 }33 }
38}34}
39#[no_mangle]35#[no_mangle]
40pub extern "C" fn jsonnet_json_extract_null(_vm: &EvaluationState, v: &Val) -> c_int {36pub extern "C" fn jsonnet_json_extract_null(_vm: &State, v: &Val) -> c_int {
41 match v {37 match v {
42 Val::Null => 1,38 Val::Null => 1,
43 _ => 0,39 _ => 0,
modifiedbindings/jsonnet/src/val_make.rsdiffbeforeafterboth
6};6};
77
8use gcmodule::Cc;8use gcmodule::Cc;
9use jrsonnet_evaluator::{val::ArrValue, EvaluationState, ObjValue, Val};9use jrsonnet_evaluator::{val::ArrValue, ObjValue, State, Val};
1010
11/// # Safety11/// # Safety
12///12///
13/// This function is safe, if received v is a pointer to normal C string13/// This function is safe, if received v is a pointer to normal C string
14#[no_mangle]14#[no_mangle]
15pub unsafe extern "C" fn jsonnet_json_make_string(15pub unsafe extern "C" fn jsonnet_json_make_string(_vm: &State, v: *const c_char) -> *mut Val {
16 _vm: &EvaluationState,
17 v: *const c_char,
18) -> *mut Val {
19 let cstr = CStr::from_ptr(v);16 let cstr = CStr::from_ptr(v);
22}19}
2320
24#[no_mangle]21#[no_mangle]
25pub extern "C" fn jsonnet_json_make_number(_vm: &EvaluationState, v: c_double) -> *mut Val {22pub extern "C" fn jsonnet_json_make_number(_vm: &State, v: c_double) -> *mut Val {
26 Box::into_raw(Box::new(Val::Num(v)))23 Box::into_raw(Box::new(Val::Num(v)))
27}24}
2825
29#[no_mangle]26#[no_mangle]
30pub extern "C" fn jsonnet_json_make_bool(_vm: &EvaluationState, v: c_int) -> *mut Val {27pub extern "C" fn jsonnet_json_make_bool(_vm: &State, v: c_int) -> *mut Val {
31 assert!(v == 0 || v == 1);28 assert!(v == 0 || v == 1);
32 Box::into_raw(Box::new(Val::Bool(v == 1)))29 Box::into_raw(Box::new(Val::Bool(v == 1)))
33}30}
3431
35#[no_mangle]32#[no_mangle]
36pub extern "C" fn jsonnet_json_make_null(_vm: &EvaluationState) -> *mut Val {33pub extern "C" fn jsonnet_json_make_null(_vm: &State) -> *mut Val {
37 Box::into_raw(Box::new(Val::Null))34 Box::into_raw(Box::new(Val::Null))
38}35}
3936
40#[no_mangle]37#[no_mangle]
41pub extern "C" fn jsonnet_json_make_array(_vm: &EvaluationState) -> *mut Val {38pub extern "C" fn jsonnet_json_make_array(_vm: &State) -> *mut Val {
42 Box::into_raw(Box::new(Val::Arr(ArrValue::Eager(Cc::new(Vec::new())))))39 Box::into_raw(Box::new(Val::Arr(ArrValue::Eager(Cc::new(Vec::new())))))
43}40}
4441
45#[no_mangle]42#[no_mangle]
46pub extern "C" fn jsonnet_json_make_object(_vm: &EvaluationState) -> *mut Val {43pub extern "C" fn jsonnet_json_make_object(_vm: &State) -> *mut Val {
47 Box::into_raw(Box::new(Val::Obj(ObjValue::new_empty())))44 Box::into_raw(Box::new(Val::Obj(ObjValue::new_empty())))
48}45}
4946
modifiedbindings/jsonnet/src/val_modify.rsdiffbeforeafterboth
5use std::{ffi::CStr, os::raw::c_char};5use std::{ffi::CStr, os::raw::c_char};
66
7use gcmodule::Cc;7use gcmodule::Cc;
8use jrsonnet_evaluator::{val::ArrValue, EvaluationState, LazyVal, Val};8use jrsonnet_evaluator::{val::ArrValue, LazyVal, State, Val};
99
10/// # Safety10/// # Safety
11///11///
12/// Received arr value should be correct pointer to array allocated by make_array12/// Received arr value should be correct pointer to array allocated by make_array
13#[no_mangle]13#[no_mangle]
14pub unsafe extern "C" fn jsonnet_json_array_append(14pub unsafe extern "C" fn jsonnet_json_array_append(_vm: &State, arr: &mut Val, val: &Val) {
15 _vm: &EvaluationState,
16 arr: &mut Val,
17 val: &Val,
18) {
34/// This function is safe if passed name is ok30/// This function is safe if passed name is ok
35#[no_mangle]31#[no_mangle]
36pub unsafe extern "C" fn jsonnet_json_object_append(32pub unsafe extern "C" fn jsonnet_json_object_append(
37 _vm: &EvaluationState,33 _vm: &State,
38 obj: &mut Val,34 obj: &mut Val,
39 name: *const c_char,35 name: *const c_char,
40 val: &Val,36 val: &Val,
modifiedbindings/jsonnet/src/vars_tlas.rsdiffbeforeafterboth
22
3use std::{ffi::CStr, os::raw::c_char};3use std::{ffi::CStr, os::raw::c_char};
44
5use jrsonnet_evaluator::EvaluationState;5use jrsonnet_evaluator::State;
66
7/// # Safety7/// # Safety
8#[no_mangle]8#[no_mangle]
9pub unsafe extern "C" fn jsonnet_ext_var(9pub unsafe extern "C" fn jsonnet_ext_var(vm: &State, name: *const c_char, value: *const c_char) {
10 vm: &EvaluationState,
11 name: *const c_char,
12 value: *const c_char,
13) {
2117
22/// # Safety18/// # Safety
23#[no_mangle]19#[no_mangle]
24pub unsafe extern "C" fn jsonnet_ext_code(20pub unsafe extern "C" fn jsonnet_ext_code(vm: &State, name: *const c_char, value: *const c_char) {
25 vm: &EvaluationState,
26 name: *const c_char,
27 value: *const c_char,
28) {
36}28}
37/// # Safety29/// # Safety
38#[no_mangle]30#[no_mangle]
39pub unsafe extern "C" fn jsonnet_tla_var(31pub unsafe extern "C" fn jsonnet_tla_var(vm: &State, name: *const c_char, value: *const c_char) {
40 vm: &EvaluationState,
41 name: *const c_char,
42 value: *const c_char,
43) {
50}38}
51/// # Safety39/// # Safety
52#[no_mangle]40#[no_mangle]
53pub unsafe extern "C" fn jsonnet_tla_code(41pub unsafe extern "C" fn jsonnet_tla_code(vm: &State, name: *const c_char, value: *const c_char) {
54 vm: &EvaluationState,
55 name: *const c_char,
56 value: *const c_char,
57) {
modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
7use clap::{AppSettings, IntoApp, Parser};7use clap::{AppSettings, IntoApp, Parser};
8use clap_complete::Shell;8use clap_complete::Shell;
9use jrsonnet_cli::{ConfigureState, GcOpts, GeneralOpts, InputOpts, ManifestOpts, OutputOpts};9use jrsonnet_cli::{ConfigureState, GcOpts, GeneralOpts, InputOpts, ManifestOpts, OutputOpts};
10use jrsonnet_evaluator::{error::LocError, EvaluationState};10use jrsonnet_evaluator::{error::LocError, State};
1111
12#[cfg(feature = "mimalloc")]12#[cfg(feature = "mimalloc")]
13#[global_allocator]13#[global_allocator]
102102
103fn main_catch(opts: Opts) -> bool {103fn main_catch(opts: Opts) -> bool {
104 let _printer = opts.gc.stats_printer();104 let _printer = opts.gc.stats_printer();
105 let state = EvaluationState::default();105 let s = State::default();
106 if let Err(e) = main_real(&state, opts) {106 if let Err(e) = main_real(&s, opts) {
107 if let Error::Evaluation(e) = e {107 if let Error::Evaluation(e) = e {
108 eprintln!("{}", state.stringify_err(&e));108 eprintln!("{}", s.stringify_err(&e));
109 } else {109 } else {
110 eprintln!("{}", e);110 eprintln!("{}", e);
111 }111 }
114 true114 true
115}115}
116116
117fn main_real(state: &EvaluationState, opts: Opts) -> Result<(), Error> {117fn main_real(s: &State, opts: Opts) -> Result<(), Error> {
118 opts.gc.configure_global();118 opts.gc.configure_global();
119 opts.general.configure(state)?;119 opts.general.configure(s)?;
120 opts.manifest.configure(state)?;120 opts.manifest.configure(s)?;
121121
122 let val = if opts.input.exec {122 let val = if opts.input.exec {
123 state.evaluate_snippet_raw(123 s.evaluate_snippet_raw(
124 PathBuf::from("<cmdline>").into(),124 PathBuf::from("<cmdline>").into(),
125 (&opts.input.input as &str).into(),125 (&opts.input.input as &str).into(),
126 )?126 )?
127 } else if opts.input.input == "-" {127 } else if opts.input.input == "-" {
128 let mut input = Vec::new();128 let mut input = Vec::new();
129 std::io::stdin().read_to_end(&mut input)?;129 std::io::stdin().read_to_end(&mut input)?;
130 let input_str = std::str::from_utf8(&input)?.into();130 let input_str = std::str::from_utf8(&input)?.into();
131 state.evaluate_snippet_raw(PathBuf::from("<stdin>").into(), input_str)?131 s.evaluate_snippet_raw(PathBuf::from("<stdin>").into(), input_str)?
132 } else {132 } else {
133 state.evaluate_file_raw(&PathBuf::from(opts.input.input))?133 s.evaluate_file_raw(&PathBuf::from(opts.input.input))?
134 };134 };
135135
136 let val = state.with_tla(val)?;136 let val = s.with_tla(val)?;
137137
138 if let Some(multi) = opts.output.multi {138 if let Some(multi) = opts.output.multi {
139 if opts.output.create_output_dirs {139 if opts.output.create_output_dirs {
140 let mut dir = multi.clone();140 let mut dir = multi.clone();
141 dir.pop();141 dir.pop();
142 create_dir_all(dir)?;142 create_dir_all(dir)?;
143 }143 }
144 for (file, data) in state.manifest_multi(val)?.iter() {144 for (file, data) in s.manifest_multi(val)?.iter() {
145 let mut path = multi.clone();145 let mut path = multi.clone();
146 path.push(file as &str);146 path.push(file as &str);
147 if opts.output.create_output_dirs {147 if opts.output.create_output_dirs {
160 create_dir_all(dir)?;160 create_dir_all(dir)?;
161 }161 }
162 let mut file = File::create(path)?;162 let mut file = File::create(path)?;
163 writeln!(file, "{}", state.manifest(val)?)?;163 writeln!(file, "{}", s.manifest(val)?)?;
164 } else {164 } else {
165 let output = state.manifest(val)?;165 let output = s.manifest(val)?;
166 if !output.is_empty() {166 if !output.is_empty() {
167 println!("{}", output);167 println!("{}", output);
168 }168 }
modifiedcrates/jrsonnet-cli/src/ext.rsdiffbeforeafterboth
1use std::{fs::read_to_string, str::FromStr};1use std::{fs::read_to_string, str::FromStr};
22
3use clap::Parser;3use clap::Parser;
4use jrsonnet_evaluator::{error::Result, EvaluationState};4use jrsonnet_evaluator::{error::Result, State};
55
6use crate::ConfigureState;6use crate::ConfigureState;
77
100 ext_code_file: Vec<ExtFile>,100 ext_code_file: Vec<ExtFile>,
101}101}
102impl ConfigureState for ExtVarOpts {102impl ConfigureState for ExtVarOpts {
103 fn configure(&self, state: &EvaluationState) -> Result<()> {103 fn configure(&self, s: &State) -> Result<()> {
104 for ext in self.ext_str.iter() {104 for ext in self.ext_str.iter() {
105 state.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into());105 s.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into());
106 }106 }
107 for ext in self.ext_str_file.iter() {107 for ext in self.ext_str_file.iter() {
108 state.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into());108 s.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into());
109 }109 }
110 for ext in self.ext_code.iter() {110 for ext in self.ext_code.iter() {
111 state.add_ext_code((&ext.name as &str).into(), (&ext.value as &str).into())?;111 s.add_ext_code((&ext.name as &str).into(), (&ext.value as &str).into())?;
112 }112 }
113 for ext in self.ext_code_file.iter() {113 for ext in self.ext_code_file.iter() {
114 state.add_ext_code((&ext.name as &str).into(), (&ext.value as &str).into())?;114 s.add_ext_code((&ext.name as &str).into(), (&ext.value as &str).into())?;
115 }115 }
116 Ok(())116 Ok(())
117 }117 }
modifiedcrates/jrsonnet-cli/src/lib.rsdiffbeforeafterboth
77
8use clap::Parser;8use clap::Parser;
9pub use ext::*;9pub use ext::*;
10use jrsonnet_evaluator::{error::Result, EvaluationState, FileImportResolver};10use jrsonnet_evaluator::{error::Result, FileImportResolver, State};
11pub use manifest::*;11pub use manifest::*;
12pub use tla::*;12pub use tla::*;
13pub use trace::*;13pub use trace::*;
1414
15pub trait ConfigureState {15pub trait ConfigureState {
16 fn configure(&self, state: &EvaluationState) -> Result<()>;16 fn configure(&self, s: &State) -> Result<()>;
17}17}
1818
19#[derive(Parser)]19#[derive(Parser)]
50 jpath: Vec<PathBuf>,50 jpath: Vec<PathBuf>,
51}51}
52impl ConfigureState for MiscOpts {52impl ConfigureState for MiscOpts {
53 fn configure(&self, state: &EvaluationState) -> Result<()> {53 fn configure(&self, s: &State) -> Result<()> {
54 if !self.no_stdlib {54 if !self.no_stdlib {
55 state.with_stdlib();55 s.with_stdlib();
56 }56 }
5757
58 let mut library_paths = self.jpath.clone();58 let mut library_paths = self.jpath.clone();
61 library_paths.extend(env::split_paths(path.as_os_str()));61 library_paths.extend(env::split_paths(path.as_os_str()));
62 }62 }
6363
64 state.set_import_resolver(Box::new(FileImportResolver { library_paths }));64 s.set_import_resolver(Box::new(FileImportResolver { library_paths }));
6565
66 state.set_max_stack(self.max_stack);66 s.set_max_stack(self.max_stack);
67 Ok(())67 Ok(())
68 }68 }
69}69}
85}85}
8686
87impl ConfigureState for GeneralOpts {87impl ConfigureState for GeneralOpts {
88 fn configure(&self, state: &EvaluationState) -> Result<()> {88 fn configure(&self, s: &State) -> Result<()> {
89 // Configure trace first, because tla-code/ext-code can throw89 // Configure trace first, because tla-code/ext-code can throw
90 self.trace.configure(state)?;90 self.trace.configure(s)?;
91 self.misc.configure(state)?;91 self.misc.configure(s)?;
92 self.tla.configure(state)?;92 self.tla.configure(s)?;
93 self.ext.configure(state)?;93 self.ext.configure(s)?;
94 Ok(())94 Ok(())
95 }95 }
96}96}
modifiedcrates/jrsonnet-cli/src/manifest.rsdiffbeforeafterboth
1use std::{path::PathBuf, str::FromStr};1use std::{path::PathBuf, str::FromStr};
22
3use clap::Parser;3use clap::Parser;
4use jrsonnet_evaluator::{error::Result, EvaluationState, ManifestFormat};4use jrsonnet_evaluator::{error::Result, ManifestFormat, State};
55
6use crate::ConfigureState;6use crate::ConfigureState;
77
49 exp_preserve_order: bool,49 exp_preserve_order: bool,
50}50}
51impl ConfigureState for ManifestOpts {51impl ConfigureState for ManifestOpts {
52 fn configure(&self, state: &EvaluationState) -> Result<()> {52 fn configure(&self, s: &State) -> Result<()> {
53 if self.string {53 if self.string {
54 state.set_manifest_format(ManifestFormat::String);54 s.set_manifest_format(ManifestFormat::String);
55 } else {55 } else {
56 #[cfg(feature = "exp-preserve-order")]56 #[cfg(feature = "exp-preserve-order")]
57 let preserve_order = self.exp_preserve_order;57 let preserve_order = self.exp_preserve_order;
58 match self.format {58 match self.format {
59 ManifestFormatName::String => state.set_manifest_format(ManifestFormat::String),59 ManifestFormatName::String => s.set_manifest_format(ManifestFormat::String),
60 ManifestFormatName::Json => state.set_manifest_format(ManifestFormat::Json {60 ManifestFormatName::Json => s.set_manifest_format(ManifestFormat::Json {
61 padding: self.line_padding.unwrap_or(3),61 padding: self.line_padding.unwrap_or(3),
62 #[cfg(feature = "exp-preserve-order")]62 #[cfg(feature = "exp-preserve-order")]
63 preserve_order,63 preserve_order,
64 }),64 }),
65 ManifestFormatName::Yaml => state.set_manifest_format(ManifestFormat::Yaml {65 ManifestFormatName::Yaml => s.set_manifest_format(ManifestFormat::Yaml {
66 padding: self.line_padding.unwrap_or(2),66 padding: self.line_padding.unwrap_or(2),
67 #[cfg(feature = "exp-preserve-order")]67 #[cfg(feature = "exp-preserve-order")]
68 preserve_order,68 preserve_order,
69 }),69 }),
70 }70 }
71 }71 }
72 if self.yaml_stream {72 if self.yaml_stream {
73 state.set_manifest_format(ManifestFormat::YamlStream(Box::new(73 s.set_manifest_format(ManifestFormat::YamlStream(Box::new(s.manifest_format())))
74 state.manifest_format(),
75 )))
76 }74 }
77 Ok(())75 Ok(())
modifiedcrates/jrsonnet-cli/src/tla.rsdiffbeforeafterboth
1use clap::Parser;1use clap::Parser;
2use jrsonnet_evaluator::{error::Result, EvaluationState};2use jrsonnet_evaluator::{error::Result, State};
33
4use crate::{ConfigureState, ExtFile, ExtStr};4use crate::{ConfigureState, ExtFile, ExtStr};
55
47 tla_code_file: Vec<ExtFile>,47 tla_code_file: Vec<ExtFile>,
48}48}
49impl ConfigureState for TLAOpts {49impl ConfigureState for TLAOpts {
50 fn configure(&self, state: &EvaluationState) -> Result<()> {50 fn configure(&self, s: &State) -> Result<()> {
51 for tla in self.tla_str.iter() {51 for tla in self.tla_str.iter() {
52 state.add_tla_str((&tla.name as &str).into(), (&tla.value as &str).into());52 s.add_tla_str((&tla.name as &str).into(), (&tla.value as &str).into());
53 }53 }
54 for tla in self.tla_str_file.iter() {54 for tla in self.tla_str_file.iter() {
55 state.add_tla_str((&tla.name as &str).into(), (&tla.value as &str).into())55 s.add_tla_str((&tla.name as &str).into(), (&tla.value as &str).into())
56 }56 }
57 for tla in self.tla_code.iter() {57 for tla in self.tla_code.iter() {
58 state.add_tla_code((&tla.name as &str).into(), (&tla.value as &str).into())?;58 s.add_tla_code((&tla.name as &str).into(), (&tla.value as &str).into())?;
59 }59 }
60 for tla in self.tla_code_file.iter() {60 for tla in self.tla_code_file.iter() {
61 state.add_tla_code((&tla.name as &str).into(), (&tla.value as &str).into())?;61 s.add_tla_code((&tla.name as &str).into(), (&tla.value as &str).into())?;
62 }62 }
63 Ok(())63 Ok(())
64 }64 }
modifiedcrates/jrsonnet-cli/src/trace.rsdiffbeforeafterboth
4use jrsonnet_evaluator::{4use jrsonnet_evaluator::{
5 error::Result,5 error::Result,
6 trace::{CompactFormat, ExplainingFormat, PathResolver},6 trace::{CompactFormat, ExplainingFormat, PathResolver},
7 EvaluationState,7 State,
8};8};
99
10use crate::ConfigureState;10use crate::ConfigureState;
41 max_trace: usize,41 max_trace: usize,
42}42}
43impl ConfigureState for TraceOpts {43impl ConfigureState for TraceOpts {
44 fn configure(&self, state: &EvaluationState) -> Result<()> {44 fn configure(&self, s: &State) -> Result<()> {
45 let resolver = PathResolver::Absolute;45 let resolver = PathResolver::Absolute;
46 match self46 match self
47 .trace_format47 .trace_format
48 .as_ref()48 .as_ref()
49 .unwrap_or(&TraceFormatName::Compact)49 .unwrap_or(&TraceFormatName::Compact)
50 {50 {
51 TraceFormatName::Compact => state.set_trace_format(Box::new(CompactFormat {51 TraceFormatName::Compact => s.set_trace_format(Box::new(CompactFormat {
52 resolver,52 resolver,
53 padding: 4,53 padding: 4,
54 })),54 })),
55 TraceFormatName::Explaining => {55 TraceFormatName::Explaining => {
56 state.set_trace_format(Box::new(ExplainingFormat { resolver }))56 s.set_trace_format(Box::new(ExplainingFormat { resolver }))
57 }57 }
58 }58 }
59 state.set_max_trace(self.max_trace);59 s.set_max_trace(self.max_trace);
60 Ok(())60 Ok(())
61 }61 }
62}62}
modifiedcrates/jrsonnet-evaluator/src/builtin/format.rsdiffbeforeafterboth
1//! faster std.format impl1//! faster std.format impl
2#![allow(clippy::too_many_arguments)]2#![allow(clippy::too_many_arguments)]
3
4use std::convert::TryFrom;
53
6use gcmodule::Trace;4use gcmodule::Trace;
7use jrsonnet_interner::IStr;5use jrsonnet_interner::IStr;
8use jrsonnet_types::ValType;6use jrsonnet_types::ValType;
9use thiserror::Error;7use thiserror::Error;
108
11use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val};9use crate::{error::Error::*, throw, typed::Typed, LocError, ObjValue, Result, State, Val};
1210
13#[derive(Debug, Clone, Error, Trace)]11#[derive(Debug, Clone, Error, Trace)]
14pub enum FormatError {12pub enum FormatError {
464}462}
465463
466pub fn format_code(464pub fn format_code(
465 s: State,
467 out: &mut String,466 out: &mut String,
468 value: &Val,467 value: &Val,
469 code: &Code,468 code: &Code,
485 let mut tmp_out = String::new();484 let mut tmp_out = String::new();
486485
487 match code.convtype {486 match code.convtype {
488 ConvTypeV::String => tmp_out.push_str(&value.clone().to_string()?),487 ConvTypeV::String => tmp_out.push_str(&value.clone().to_string(s)?),
489 ConvTypeV::Decimal => {488 ConvTypeV::Decimal => {
490 let value = f64::try_from(value.clone())?;489 let value = f64::from_untyped(value.clone(), s)?;
491 render_decimal(490 render_decimal(
492 &mut tmp_out,491 &mut tmp_out,
493 value as i64,492 value as i64,
498 );497 );
499 }498 }
500 ConvTypeV::Octal => {499 ConvTypeV::Octal => {
501 let value = f64::try_from(value.clone())?;500 let value = f64::from_untyped(value.clone(), s)?;
502 render_octal(501 render_octal(
503 &mut tmp_out,502 &mut tmp_out,
504 value as i64,503 value as i64,
510 );509 );
511 }510 }
512 ConvTypeV::Hexadecimal => {511 ConvTypeV::Hexadecimal => {
513 let value = f64::try_from(value.clone())?;512 let value = f64::from_untyped(value.clone(), s)?;
514 render_hexadecimal(513 render_hexadecimal(
515 &mut tmp_out,514 &mut tmp_out,
516 value as i64,515 value as i64,
523 );522 );
524 }523 }
525 ConvTypeV::Scientific => {524 ConvTypeV::Scientific => {
526 let value = f64::try_from(value.clone())?;525 let value = f64::from_untyped(value.clone(), s)?;
527 render_float_sci(526 render_float_sci(
528 &mut tmp_out,527 &mut tmp_out,
529 value,528 value,
537 );536 );
538 }537 }
539 ConvTypeV::Float => {538 ConvTypeV::Float => {
540 let value = f64::try_from(value.clone())?;539 let value = f64::from_untyped(value.clone(), s)?;
541 render_float(540 render_float(
542 &mut tmp_out,541 &mut tmp_out,
543 value,542 value,
550 );549 );
551 }550 }
552 ConvTypeV::Shorter => {551 ConvTypeV::Shorter => {
553 let value = f64::try_from(value.clone())?;552 let value = f64::from_untyped(value.clone(), s)?;
554 let exponent = value.log10().floor();553 let exponent = value.log10().floor();
555 if exponent < -4.0 || exponent >= fpprec as f64 {554 if exponent < -4.0 || exponent >= fpprec as f64 {
556 render_float_sci(555 render_float_sci(
617 Ok(())616 Ok(())
618}617}
619618
620pub fn format_arr(str: &str, mut values: &[Val]) -> Result<String> {619pub fn format_arr(s: State, str: &str, mut values: &[Val]) -> Result<String> {
621 let codes = parse_codes(str)?;620 let codes = parse_codes(str)?;
622 let mut out = String::new();621 let mut out = String::new();
623622
634 }633 }
635 let value = &values[0];634 let value = &values[0];
636 values = &values[1..];635 values = &values[1..];
637 usize::try_from(value.clone())?636 usize::from_untyped(value.clone(), s.clone())?
638 }637 }
639 Width::Fixed(n) => n,638 Width::Fixed(n) => n,
640 };639 };
645 }644 }
646 let value = &values[0];645 let value = &values[0];
647 values = &values[1..];646 values = &values[1..];
648 Some(usize::try_from(value.clone())?)647 Some(usize::from_untyped(value.clone(), s.clone())?)
649 }648 }
650 Some(Width::Fixed(n)) => Some(n),649 Some(Width::Fixed(n)) => Some(n),
651 None => None,650 None => None,
663 value662 value
664 };663 };
665664
666 format_code(&mut out, value, &c, width, precision)?;665 format_code(s.clone(), &mut out, value, &c, width, precision)?;
667 }666 }
668 }667 }
669 }668 }
670669
671 Ok(out)670 Ok(out)
672}671}
673672
674pub fn format_obj(str: &str, values: &ObjValue) -> Result<String> {673pub fn format_obj(s: State, str: &str, values: &ObjValue) -> Result<String> {
675 let codes = parse_codes(str)?;674 let codes = parse_codes(str)?;
676 let mut out = String::new();675 let mut out = String::new();
677676
703 if f.is_empty() {702 if f.is_empty() {
704 throw!(MappingKeysRequired);703 throw!(MappingKeysRequired);
705 }704 }
706 if let Some(v) = values.get(f.clone())? {705 if let Some(v) = values.get(s.clone(), f.clone())? {
707 v706 v
708 } else {707 } else {
709 throw!(NoSuchFormatField(f));708 throw!(NoSuchFormatField(f));
710 }709 }
711 };710 };
712711
713 format_code(&mut out, &value, &c, width, precision)?;712 format_code(s.clone(), &mut out, &value, &c, width, precision)?;
714 }713 }
715 }714 }
716 }715 }
modifiedcrates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 error::{Error::*, Result},2 error::{Error::*, Result},
3 push_description_frame, throw, Val,3 throw, State, Val,
4};4};
55
6#[derive(PartialEq, Clone, Copy)]6#[derive(PartialEq, Clone, Copy)]
25 pub preserve_order: bool,25 pub preserve_order: bool,
26}26}
2727
28pub fn manifest_json_ex(val: &Val, options: &ManifestJsonOptions<'_>) -> Result<String> {28pub fn manifest_json_ex(s: State, val: &Val, options: &ManifestJsonOptions<'_>) -> Result<String> {
29 let mut out = String::new();29 let mut out = String::new();
30 manifest_json_ex_buf(val, &mut out, &mut String::new(), options)?;30 manifest_json_ex_buf(s, val, &mut out, &mut String::new(), options)?;
31 Ok(out)31 Ok(out)
32}32}
33fn manifest_json_ex_buf(33fn manifest_json_ex_buf(
34 s: State,
34 val: &Val,35 val: &Val,
35 buf: &mut String,36 buf: &mut String,
36 cur_padding: &mut String,37 cur_padding: &mut String,
5859
59 let old_len = cur_padding.len();60 let old_len = cur_padding.len();
60 cur_padding.push_str(options.padding);61 cur_padding.push_str(options.padding);
61 for (i, item) in items.iter().enumerate() {62 for (i, item) in items.iter(s.clone()).enumerate() {
62 if i != 0 {63 if i != 0 {
63 buf.push(',');64 buf.push(',');
64 if mtype == ManifestType::ToString {65 if mtype == ManifestType::ToString {
68 }69 }
69 }70 }
70 buf.push_str(cur_padding);71 buf.push_str(cur_padding);
71 manifest_json_ex_buf(&item?, buf, cur_padding, options)?;72 manifest_json_ex_buf(s.clone(), &item?, buf, cur_padding, options)?;
72 }73 }
73 cur_padding.truncate(old_len);74 cur_padding.truncate(old_len);
7475
85 buf.push(']');86 buf.push(']');
86 }87 }
87 Val::Obj(obj) => {88 Val::Obj(obj) => {
88 obj.run_assertions()?;89 obj.run_assertions(s.clone())?;
89 buf.push('{');90 buf.push('{');
90 let fields = obj.fields(91 let fields = obj.fields(
91 #[cfg(feature = "exp-preserve-order")]92 #[cfg(feature = "exp-preserve-order")]
110 buf.push_str(cur_padding);111 buf.push_str(cur_padding);
111 escape_string_json_buf(&field, buf);112 escape_string_json_buf(&field, buf);
112 buf.push_str(options.key_val_sep);113 buf.push_str(options.key_val_sep);
113 push_description_frame(114 s.push_description(
114 || format!("field <{}> manifestification", field.clone()),115 || format!("field <{}> manifestification", field.clone()),
115 || {116 || {
116 let value = obj.get(field.clone())?.unwrap();117 let value = obj.get(s.clone(), field.clone())?.unwrap();
117 manifest_json_ex_buf(&value, buf, cur_padding, options)?;118 manifest_json_ex_buf(s.clone(), &value, buf, cur_padding, options)?;
118 Ok(Val::Null)119 Ok(Val::Null)
119 },120 },
120 )?;121 )?;
221 || string.parse::<f64>().is_ok()222 || string.parse::<f64>().is_ok()
222}223}
223224
224pub fn manifest_yaml_ex(val: &Val, options: &ManifestYamlOptions<'_>) -> Result<String> {225pub fn manifest_yaml_ex(s: State, val: &Val, options: &ManifestYamlOptions<'_>) -> Result<String> {
225 let mut out = String::new();226 let mut out = String::new();
226 manifest_yaml_ex_buf(val, &mut out, &mut String::new(), options)?;227 manifest_yaml_ex_buf(s, val, &mut out, &mut String::new(), options)?;
227 Ok(out)228 Ok(out)
228}229}
229fn manifest_yaml_ex_buf(230fn manifest_yaml_ex_buf(
231 s: State,
230 val: &Val,232 val: &Val,
231 buf: &mut String,233 buf: &mut String,
232 cur_padding: &mut String,234 cur_padding: &mut String,
249 buf.push('|');251 buf.push('|');
250 for line in s.split('\n') {252 for line in s.split('\n') {
251 buf.push('\n');253 buf.push('\n');
252 buf.push_str(&cur_padding);254 buf.push_str(cur_padding);
253 buf.push_str(options.padding);255 buf.push_str(options.padding);
254 buf.push_str(line);256 buf.push_str(line);
255 }257 }
264 if a.is_empty() {266 if a.is_empty() {
265 buf.push_str("[]");267 buf.push_str("[]");
266 } else {268 } else {
267 for (i, item) in a.iter().enumerate() {269 for (i, item) in a.iter(s.clone()).enumerate() {
268 if i != 0 {270 if i != 0 {
269 buf.push('\n');271 buf.push('\n');
270 buf.push_str(cur_padding);272 buf.push_str(cur_padding);
288 if extra_padding {290 if extra_padding {
289 cur_padding.push_str(options.padding);291 cur_padding.push_str(options.padding);
290 }292 }
291 manifest_yaml_ex_buf(&item, buf, cur_padding, options)?;293 manifest_yaml_ex_buf(s.clone(), &item, buf, cur_padding, options)?;
292 cur_padding.truncate(prev_len);294 cur_padding.truncate(prev_len);
293 }295 }
294 }296 }
316 }318 }
317 buf.push(':');319 buf.push(':');
318 let prev_len = cur_padding.len();320 let prev_len = cur_padding.len();
319 let item = o.get(key.clone())?.expect("field exists");321 let item = o.get(s.clone(), key.clone())?.expect("field exists");
320 match &item {322 match &item {
321 Val::Arr(a) if !a.is_empty() => {323 Val::Arr(a) if !a.is_empty() => {
322 buf.push('\n');324 buf.push('\n');
332 }334 }
333 _ => buf.push(' '),335 _ => buf.push(' '),
334 }336 }
335 manifest_yaml_ex_buf(&item, buf, cur_padding, options)?;337 manifest_yaml_ex_buf(s.clone(), &item, buf, cur_padding, options)?;
336 cur_padding.truncate(prev_len);338 cur_padding.truncate(prev_len);
337 }339 }
338 }340 }
modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
1use std::{1use std::collections::HashMap;
2 collections::HashMap,
3 convert::{TryFrom, TryInto},
4};
52
6use format::{format_arr, format_obj};3use format::{format_arr, format_obj};
7use gcmodule::Cc;4use gcmodule::Cc;
14 error::{Error::*, Result},11 error::{Error::*, Result},
15 function::{CallLocation, StaticBuiltin},12 function::{CallLocation, StaticBuiltin},
16 operator::evaluate_mod_op,13 operator::evaluate_mod_op,
17 push_frame, throw,14 throw,
18 typed::{Any, BoundedUsize, Bytes, Either2, Either4, PositiveF64, VecVal, M1},15 typed::{Any, BoundedUsize, Bytes, Either2, Either4, PositiveF64, Typed, VecVal, M1},
19 val::{equals, primitive_equals, ArrValue, FuncVal, IndexableVal, Slice},16 val::{equals, primitive_equals, ArrValue, FuncVal, IndexableVal, Slice},
20 with_state, Either, ObjValue, Val,17 Either, ObjValue, State, Val,
21};18};
2219
23pub mod stdlib;20pub mod stdlib;
29pub mod manifest;26pub mod manifest;
30pub mod sort;27pub mod sort;
3128
32pub fn std_format(str: IStr, vals: Val) -> Result<String> {29pub fn std_format(s: State, str: IStr, vals: Val) -> Result<String> {
33 push_frame(30 s.push(
34 CallLocation::native(),31 CallLocation::native(),
35 || format!("std.format of {}", str),32 || format!("std.format of {}", str),
36 || {33 || {
37 Ok(match vals {34 Ok(match vals {
38 Val::Arr(vals) => format_arr(&str, &vals.evaluated()?)?,35 Val::Arr(vals) => format_arr(s.clone(), &str, &vals.evaluated(s.clone())?)?,
39 Val::Obj(obj) => format_obj(&str, &obj)?,36 Val::Obj(obj) => format_obj(s.clone(), &str, &obj)?,
40 o => format_arr(&str, &[o])?,37 o => format_arr(s.clone(), &str, &[o])?,
41 })38 })
42 },39 },
43 )40 )
173}170}
174171
175#[jrsonnet_macros::builtin]172#[jrsonnet_macros::builtin]
176fn builtin_make_array(sz: usize, func: FuncVal) -> Result<VecVal> {173fn builtin_make_array(s: State, sz: usize, func: FuncVal) -> Result<VecVal> {
177 let mut out = Vec::with_capacity(sz);174 let mut out = Vec::with_capacity(sz);
178 for i in 0..sz {175 for i in 0..sz {
179 out.push(func.evaluate_simple(&[i as f64].as_slice())?)176 out.push(func.evaluate_simple(s.clone(), &[i as f64].as_slice())?)
180 }177 }
181 Ok(VecVal(Cc::new(out)))178 Ok(VecVal(Cc::new(out)))
182}179}
210}207}
211208
212#[jrsonnet_macros::builtin]209#[jrsonnet_macros::builtin]
213fn builtin_parse_json(s: IStr) -> Result<Any> {210fn builtin_parse_json(st: State, s: IStr) -> Result<Any> {
211 use serde_json::Value;
214 let value: serde_json::Value = serde_json::from_str(&s)212 let value: Value = serde_json::from_str(&s)
215 .map_err(|e| RuntimeError(format!("failed to parse json: {}", e).into()))?;213 .map_err(|e| RuntimeError(format!("failed to parse json: {}", e).into()))?;
216 Ok(Any(Val::try_from(&value)?))214 Ok(Any(Value::into_untyped(value, st)?))
217}215}
218216
219#[jrsonnet_macros::builtin]217#[jrsonnet_macros::builtin]
220fn builtin_parse_yaml(s: IStr) -> Result<Any> {218fn builtin_parse_yaml(st: State, s: IStr) -> Result<Any> {
219 use serde_json::Value;
221 let value = serde_yaml::Deserializer::from_str_with_quirks(220 let value = serde_yaml::Deserializer::from_str_with_quirks(
222 &s,221 &s,
223 DeserializingQuirks { old_octals: true },222 DeserializingQuirks { old_octals: true },
224 );223 );
225 let mut out = vec![];224 let mut out = vec![];
226 for item in value {225 for item in value {
227 let value = serde_json::Value::deserialize(item)226 let value = Value::deserialize(item)
228 .map_err(|e| RuntimeError(format!("failed to parse yaml: {}", e).into()))?;227 .map_err(|e| RuntimeError(format!("failed to parse yaml: {}", e).into()))?;
229 let val = Val::try_from(&value)?;228 let val = Value::into_untyped(value, st.clone())?;
230 out.push(val);229 out.push(val);
231 }230 }
232 Ok(Any(if out.is_empty() {231 Ok(Any(if out.is_empty() {
259}258}
260259
261#[jrsonnet_macros::builtin]260#[jrsonnet_macros::builtin]
262fn builtin_equals(a: Any, b: Any) -> Result<bool> {261fn builtin_equals(s: State, a: Any, b: Any) -> Result<bool> {
263 equals(&a.0, &b.0)262 equals(s, &a.0, &b.0)
264}263}
265264
266#[jrsonnet_macros::builtin]265#[jrsonnet_macros::builtin]
269}268}
270269
271#[jrsonnet_macros::builtin]270#[jrsonnet_macros::builtin]
272fn builtin_mod(a: Either![f64, IStr], b: Any) -> Result<Any> {271fn builtin_mod(s: State, a: Either![f64, IStr], b: Any) -> Result<Any> {
273 use Either2::*;272 use Either2::*;
274 Ok(Any(evaluate_mod_op(273 Ok(Any(evaluate_mod_op(
274 s,
275 &match a {275 &match a {
276 A(v) => Val::Num(v),276 A(v) => Val::Num(v),
277 B(s) => Val::Str(s),277 B(s) => Val::Str(s),
362}362}
363363
364#[jrsonnet_macros::builtin]364#[jrsonnet_macros::builtin]
365fn builtin_ext_var(x: IStr) -> Result<Any> {365fn builtin_ext_var(s: State, x: IStr) -> Result<Any> {
366 Ok(Any(with_state(|s| s.settings().ext_vars.get(&x).cloned())366 Ok(Any(s
367 .settings()
368 .ext_vars
369 .get(&x)
370 .cloned()
367 .ok_or(UndefinedExternalVariable(x))?))371 .ok_or(UndefinedExternalVariable(x))?))
368}372}
369373
370#[jrsonnet_macros::builtin]374#[jrsonnet_macros::builtin]
371fn builtin_native(name: IStr) -> Result<FuncVal> {375fn builtin_native(s: State, name: IStr) -> Result<FuncVal> {
372 Ok(with_state(|s| s.settings().ext_natives.get(&name).cloned())376 Ok(s.settings()
377 .ext_natives
378 .get(&name)
379 .cloned()
373 .map(|v| FuncVal::Builtin(v.clone()))380 .map(|v| FuncVal::Builtin(v.clone()))
374 .ok_or(UndefinedExternalFunction(name))?)381 .ok_or(UndefinedExternalFunction(name))?)
375}382}
376383
377#[jrsonnet_macros::builtin]384#[jrsonnet_macros::builtin]
378fn builtin_filter(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {385fn builtin_filter(s: State, func: FuncVal, arr: ArrValue) -> Result<ArrValue> {
379 arr.filter(|val| bool::try_from(func.evaluate_simple(&[Any(val.clone())].as_slice())?))386 arr.filter(s.clone(), |val| {
387 bool::from_untyped(
388 func.evaluate_simple(s.clone(), &[Any(val.clone())].as_slice())?,
389 s.clone(),
390 )
391 })
380}392}
381393
382#[jrsonnet_macros::builtin]394#[jrsonnet_macros::builtin]
383fn builtin_map(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {395fn builtin_map(s: State, func: FuncVal, arr: ArrValue) -> Result<ArrValue> {
384 arr.map(|val| func.evaluate_simple(&[Any(val)].as_slice()))396 arr.map(s.clone(), |val| {
397 func.evaluate_simple(s.clone(), &[Any(val)].as_slice())
398 })
385}399}
386400
387#[jrsonnet_macros::builtin]401#[jrsonnet_macros::builtin]
388fn builtin_flatmap(func: FuncVal, arr: IndexableVal) -> Result<IndexableVal> {402fn builtin_flatmap(s: State, func: FuncVal, arr: IndexableVal) -> Result<IndexableVal> {
389 match arr {403 match arr {
390 IndexableVal::Str(s) => {404 IndexableVal::Str(str) => {
391 let mut out = String::new();405 let mut out = String::new();
392 for c in s.chars() {406 for c in str.chars() {
393 match func.evaluate_simple(&[c.to_string()].as_slice())? {407 match func.evaluate_simple(s.clone(), &[c.to_string()].as_slice())? {
394 Val::Str(o) => out.push_str(&o),408 Val::Str(o) => out.push_str(&o),
395 _ => throw!(RuntimeError(409 _ => throw!(RuntimeError(
396 "in std.join all items should be strings".into()410 "in std.join all items should be strings".into()
401 }415 }
402 IndexableVal::Arr(a) => {416 IndexableVal::Arr(a) => {
403 let mut out = Vec::new();417 let mut out = Vec::new();
404 for el in a.iter() {418 for el in a.iter(s.clone()) {
405 let el = el?;419 let el = el?;
406 match func.evaluate_simple(&[Any(el)].as_slice())? {420 match func.evaluate_simple(s.clone(), &[Any(el)].as_slice())? {
407 Val::Arr(o) => {421 Val::Arr(o) => {
408 for oe in o.iter() {422 for oe in o.iter(s.clone()) {
409 out.push(oe?)423 out.push(oe?)
410 }424 }
411 }425 }
420}434}
421435
422#[jrsonnet_macros::builtin]436#[jrsonnet_macros::builtin]
423fn builtin_foldl(func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {437fn builtin_foldl(s: State, func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {
424 let mut acc = init.0;438 let mut acc = init.0;
425 for i in arr.iter() {439 for i in arr.iter(s.clone()) {
426 acc = func.evaluate_simple(&[Any(acc), Any(i?)].as_slice())?;440 acc = func.evaluate_simple(s.clone(), &[Any(acc), Any(i?)].as_slice())?;
427 }441 }
428 Ok(Any(acc))442 Ok(Any(acc))
429}443}
430444
431#[jrsonnet_macros::builtin]445#[jrsonnet_macros::builtin]
432fn builtin_foldr(func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {446fn builtin_foldr(s: State, func: FuncVal, arr: ArrValue, init: Any) -> Result<Any> {
433 let mut acc = init.0;447 let mut acc = init.0;
434 for i in arr.iter().rev() {448 for i in arr.iter(s.clone()).rev() {
435 acc = func.evaluate_simple(&[Any(i?), Any(acc)].as_slice())?;449 acc = func.evaluate_simple(s.clone(), &[Any(i?), Any(acc)].as_slice())?;
436 }450 }
437 Ok(Any(acc))451 Ok(Any(acc))
438}452}
439453
440#[jrsonnet_macros::builtin]454#[jrsonnet_macros::builtin]
441#[allow(non_snake_case)]455#[allow(non_snake_case)]
442fn builtin_sort(arr: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {456fn builtin_sort(s: State, arr: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {
443 if arr.len() <= 1 {457 if arr.len() <= 1 {
444 return Ok(arr);458 return Ok(arr);
445 }459 }
446 Ok(ArrValue::Eager(sort::sort(460 Ok(ArrValue::Eager(sort::sort(
461 s.clone(),
447 arr.evaluated()?,462 arr.evaluated(s)?,
448 keyF.as_ref(),463 keyF.as_ref(),
449 )?))464 )?))
450}465}
451466
452#[jrsonnet_macros::builtin]467#[jrsonnet_macros::builtin]
453fn builtin_format(str: IStr, vals: Any) -> Result<String> {468fn builtin_format(s: State, str: IStr, vals: Any) -> Result<String> {
454 std_format(str, vals.0)469 std_format(s, str, vals.0)
455}470}
456471
457#[jrsonnet_macros::builtin]472#[jrsonnet_macros::builtin]
485}500}
486501
487#[jrsonnet_macros::builtin]502#[jrsonnet_macros::builtin]
488fn builtin_trace(loc: CallLocation, str: IStr, rest: Any) -> Result<Any> {503fn builtin_trace(s: State, loc: CallLocation, str: IStr, rest: Any) -> Result<Any> {
489 eprint!("TRACE:");504 eprint!("TRACE:");
490 if let Some(loc) = loc.0 {505 if let Some(loc) = loc.0 {
491 with_state(|s| {
492 let locs = s.map_source_locations(&loc.0, &[loc.1]);506 let locs = s.map_source_locations(&loc.0, &[loc.1]);
493 eprint!(507 eprint!(
494 " {}:{}",508 " {}:{}",
495 loc.0.file_name().unwrap().to_str().unwrap(),509 loc.0.file_name().unwrap().to_str().unwrap(),
496 locs[0].line510 locs[0].line
497 );511 );
498 });
499 }512 }
500 eprintln!(" {}", str);513 eprintln!(" {}", str);
501 Ok(rest) as Result<Any>514 Ok(rest) as Result<Any>
526}539}
527540
528#[jrsonnet_macros::builtin]541#[jrsonnet_macros::builtin]
529fn builtin_join(sep: IndexableVal, arr: ArrValue) -> Result<IndexableVal> {542fn builtin_join(s: State, sep: IndexableVal, arr: ArrValue) -> Result<IndexableVal> {
530 Ok(match sep {543 Ok(match sep {
531 IndexableVal::Arr(joiner_items) => {544 IndexableVal::Arr(joiner_items) => {
532 let mut out = Vec::new();545 let mut out = Vec::new();
533546
534 let mut first = true;547 let mut first = true;
535 for item in arr.iter() {548 for item in arr.iter(s.clone()) {
536 let item = item?.clone();549 let item = item?.clone();
537 if let Val::Arr(items) = item {550 if let Val::Arr(items) = item {
538 if !first {551 if !first {
539 out.reserve(joiner_items.len());552 out.reserve(joiner_items.len());
540 // TODO: extend553 // TODO: extend
541 for item in joiner_items.iter() {554 for item in joiner_items.iter(s.clone()) {
542 out.push(item?);555 out.push(item?);
543 }556 }
544 }557 }
545 first = false;558 first = false;
546 out.reserve(items.len());559 out.reserve(items.len());
547 // TODO: extend
548 for item in items.iter() {560 for item in items.iter(s.clone()) {
549 out.push(item?);561 out.push(item?);
550 }562 }
551 } else {563 } else {
561 let mut out = String::new();573 let mut out = String::new();
562574
563 let mut first = true;575 let mut first = true;
564 for item in arr.iter() {576 for item in arr.iter(s) {
565 let item = item?.clone();577 let item = item?.clone();
566 if let Val::Str(item) = item {578 if let Val::Str(item) = item {
567 if !first {579 if !first {
588600
589#[jrsonnet_macros::builtin]601#[jrsonnet_macros::builtin]
590fn builtin_manifest_json_ex(602fn builtin_manifest_json_ex(
603 s: State,
591 value: Any,604 value: Any,
592 indent: IStr,605 indent: IStr,
593 newline: Option<IStr>,606 newline: Option<IStr>,
597 let newline = newline.as_deref().unwrap_or("\n");610 let newline = newline.as_deref().unwrap_or("\n");
598 let key_val_sep = key_val_sep.as_deref().unwrap_or(": ");611 let key_val_sep = key_val_sep.as_deref().unwrap_or(": ");
599 manifest_json_ex(612 manifest_json_ex(
613 s,
600 &value.0,614 &value.0,
601 &ManifestJsonOptions {615 &ManifestJsonOptions {
602 padding: &indent,616 padding: &indent,
611625
612#[jrsonnet_macros::builtin]626#[jrsonnet_macros::builtin]
613fn builtin_manifest_yaml_doc(627fn builtin_manifest_yaml_doc(
628 s: State,
614 value: Any,629 value: Any,
615 indent_array_in_object: Option<bool>,630 indent_array_in_object: Option<bool>,
616 quote_keys: Option<bool>,631 quote_keys: Option<bool>,
617 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,632 #[cfg(feature = "exp-preserve-order")] preserve_order: Option<bool>,
618) -> Result<String> {633) -> Result<String> {
619 manifest_yaml_ex(634 manifest_yaml_ex(
635 s,
620 &value.0,636 &value.0,
621 &ManifestYamlOptions {637 &ManifestYamlOptions {
622 padding: " ",638 padding: " ",
670}686}
671687
672#[jrsonnet_macros::builtin]688#[jrsonnet_macros::builtin]
673fn builtin_member(arr: IndexableVal, x: Any) -> Result<bool> {689fn builtin_member(s: State, arr: IndexableVal, x: Any) -> Result<bool> {
674 match arr {690 match arr {
675 IndexableVal::Str(s) => {691 IndexableVal::Str(str) => {
676 let x: IStr = IStr::try_from(x.0)?;692 let x: IStr = IStr::from_untyped(x.0, s)?;
677 Ok(!x.is_empty() && s.contains(&*x))693 Ok(!x.is_empty() && str.contains(&*x))
678 }694 }
679 IndexableVal::Arr(a) => {695 IndexableVal::Arr(a) => {
680 for item in a.iter() {696 for item in a.iter(s.clone()) {
681 let item = item?;697 let item = item?;
682 if equals(&item, &x.0)? {698 if equals(s.clone(), &item, &x.0)? {
683 return Ok(true);699 return Ok(true);
684 }700 }
685 }701 }
689}705}
690706
691#[jrsonnet_macros::builtin]707#[jrsonnet_macros::builtin]
692fn builtin_count(arr: Vec<Any>, v: Any) -> Result<usize> {708fn builtin_count(s: State, arr: Vec<Any>, v: Any) -> Result<usize> {
693 let mut count = 0;709 let mut count = 0;
694 for item in arr.iter() {710 for item in arr.iter() {
695 if equals(&item.0, &v.0)? {711 if equals(s.clone(), &item.0, &v.0)? {
696 count += 1;712 count += 1;
697 }713 }
698 }714 }
699 Ok(count)715 Ok(count)
700}716}
701717
702#[jrsonnet_macros::builtin]718#[jrsonnet_macros::builtin]
703fn builtin_any(arr: ArrValue) -> Result<bool> {719fn builtin_any(s: State, arr: ArrValue) -> Result<bool> {
704 for v in arr.iter() {720 for v in arr.iter(s.clone()) {
705 let v: bool = v?.try_into()?;721 let v = bool::from_untyped(v?, s.clone())?;
706 if v {722 if v {
707 return Ok(true);723 return Ok(true);
708 }724 }
711}727}
712728
713#[jrsonnet_macros::builtin]729#[jrsonnet_macros::builtin]
714fn builtin_all(arr: ArrValue) -> Result<bool> {730fn builtin_all(s: State, arr: ArrValue) -> Result<bool> {
715 for v in arr.iter() {731 for v in arr.iter(s.clone()) {
716 let v: bool = v?.try_into()?;732 let v = bool::from_untyped(v?, s.clone())?;
717 if !v {733 if !v {
718 return Ok(false);734 return Ok(false);
719 }735 }
modifiedcrates/jrsonnet-evaluator/src/builtin/sort.rsdiffbeforeafterboth
5 throw,5 throw,
6 typed::Any,6 typed::Any,
7 val::FuncVal,7 val::FuncVal,
8 Val,8 State, Val,
9};9};
1010
11#[derive(Debug, Clone, thiserror::Error, Trace)]11#[derive(Debug, Clone, thiserror::Error, Trace)]
63 Ok(sort_type)63 Ok(sort_type)
64}64}
6565
66pub fn sort(values: Cc<Vec<Val>>, key_getter: Option<&FuncVal>) -> Result<Cc<Vec<Val>>> {66pub fn sort(s: State, values: Cc<Vec<Val>>, key_getter: Option<&FuncVal>) -> Result<Cc<Vec<Val>>> {
67 if values.len() <= 1 {67 if values.len() <= 1 {
68 return Ok(values);68 return Ok(values);
69 }69 }
73 for value in values.iter() {73 for value in values.iter() {
74 vk.push((74 vk.push((
75 value.clone(),75 value.clone(),
76 key_getter.evaluate_simple(&[Any(value.clone())].as_slice())?,76 key_getter.evaluate_simple(s.clone(), &[Any(value.clone())].as_slice())?,
77 ));77 ));
78 }78 }
79 let sort_type = get_sort_type(&mut vk, |v| &mut v.1)?;79 let sort_type = get_sort_type(&mut vk, |v| &mut v.1)?;
modifiedcrates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth
55
6use crate::{6use crate::{
7 cc_ptr_eq, error::Error::*, gc::GcHashMap, map::LayeredHashMap, FutureWrapper, LazyBinding,7 cc_ptr_eq, error::Error::*, gc::GcHashMap, map::LayeredHashMap, FutureWrapper, LazyBinding,
8 LazyVal, ObjValue, Result, Val,8 LazyVal, ObjValue, Result, State, Val,
9};9};
1010
11#[derive(Clone, Trace)]11#[derive(Clone, Trace)]
12pub struct ContextCreator(pub Context, pub FutureWrapper<GcHashMap<IStr, LazyBinding>>);12pub struct ContextCreator(pub Context, pub FutureWrapper<GcHashMap<IStr, LazyBinding>>);
13impl ContextCreator {13impl ContextCreator {
14 pub fn create(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<Context> {14 pub fn create(
15 &self,
16 s: State,
17 this: Option<ObjValue>,
18 super_obj: Option<ObjValue>,
19 ) -> Result<Context> {
15 self.0.clone().extend_unbound(20 self.0.clone().extend_unbound(
21 s,
16 self.1.clone().unwrap(),22 self.1.clone().unwrap(),
17 self.0.dollar().clone().or_else(|| this.clone()),23 self.0.dollar().clone().or_else(|| this.clone()),
18 this,24 this,
120 }126 }
121 pub fn extend_unbound(127 pub fn extend_unbound(
122 self,128 self,
129 s: State,
123 new_bindings: GcHashMap<IStr, LazyBinding>,130 new_bindings: GcHashMap<IStr, LazyBinding>,
124 new_dollar: Option<ObjValue>,131 new_dollar: Option<ObjValue>,
125 new_this: Option<ObjValue>,132 new_this: Option<ObjValue>,
129 let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());136 let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());
130 let mut new = GcHashMap::with_capacity(new_bindings.len());137 let mut new = GcHashMap::with_capacity(new_bindings.len());
131 for (k, v) in new_bindings.0.into_iter() {138 for (k, v) in new_bindings.0.into_iter() {
132 new.insert(k, v.evaluate(this.clone(), super_obj.clone())?);139 new.insert(k, v.evaluate(s.clone(), this.clone(), super_obj.clone())?);
133 }140 }
134 Ok(self.extend(new, new_dollar, this, super_obj))141 Ok(self.extend(new, new_dollar, this, super_obj))
135 }142 }
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
1use std::convert::TryFrom;
2
3use gcmodule::{Cc, Trace};1use gcmodule::{Cc, Trace};
4use jrsonnet_interner::IStr;2use jrsonnet_interner::IStr;
14 evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},12 evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},
15 function::CallLocation,13 function::CallLocation,
16 gc::TraceBox,14 gc::TraceBox,
17 push_frame, throw,15 throw,
18 typed::BoundedUsize,16 typed::Typed,
19 val::{ArrValue, FuncDesc, FuncVal, LazyValValue},17 val::{ArrValue, FuncDesc, FuncVal, LazyValValue},
20 with_state, Bindable, Context, ContextCreator, FutureWrapper, GcHashMap, LazyBinding, LazyVal,18 Bindable, Context, ContextCreator, FutureWrapper, GcHashMap, LazyBinding, LazyVal, ObjValue,
21 ObjValue, ObjValueBuilder, ObjectAssertion, Result, Val,19 ObjValueBuilder, ObjectAssertion, Result, State, Val,
22};20};
23pub mod operator;21pub mod operator;
2422
25pub fn evaluate_binding_in_future(23pub fn evaluate_binding_in_future(b: &BindSpec, fctx: FutureWrapper<Context>) -> LazyVal {
26 b: &BindSpec,
27 context_creator: FutureWrapper<Context>,
28) -> LazyVal {
29 let b = b.clone();24 let b = b.clone();
30 if let Some(params) = &b.params {25 if let Some(params) = &b.params {
31 let params = params.clone();26 let params = params.clone();
3227
33 #[derive(Trace)]28 #[derive(Trace)]
34 struct LazyMethodBinding {29 struct LazyMethodBinding {
35 context_creator: FutureWrapper<Context>,30 fctx: FutureWrapper<Context>,
36 name: IStr,31 name: IStr,
37 params: ParamsDesc,32 params: ParamsDesc,
38 value: LocExpr,33 value: LocExpr,
39 }34 }
40 impl LazyValValue for LazyMethodBinding {35 impl LazyValValue for LazyMethodBinding {
41 fn get(self: Box<Self>) -> Result<Val> {36 fn get(self: Box<Self>, _: State) -> Result<Val> {
42 Ok(evaluate_method(37 Ok(evaluate_method(
43 self.context_creator.unwrap(),38 self.fctx.unwrap(),
44 self.name,39 self.name,
45 self.params,40 self.params,
46 self.value,41 self.value,
49 }44 }
5045
51 LazyVal::new(TraceBox(Box::new(LazyMethodBinding {46 LazyVal::new(TraceBox(Box::new(LazyMethodBinding {
52 context_creator,47 fctx,
53 name: b.name.clone(),48 name: b.name.clone(),
54 params,49 params,
55 value: b.value.clone(),50 value: b.value.clone(),
56 })))51 })))
57 } else {52 } else {
58 #[derive(Trace)]53 #[derive(Trace)]
59 struct LazyNamedBinding {54 struct LazyNamedBinding {
60 context_creator: FutureWrapper<Context>,55 fctx: FutureWrapper<Context>,
61 name: IStr,56 name: IStr,
62 value: LocExpr,57 value: LocExpr,
63 }58 }
64 impl LazyValValue for LazyNamedBinding {59 impl LazyValValue for LazyNamedBinding {
65 fn get(self: Box<Self>) -> Result<Val> {60 fn get(self: Box<Self>, s: State) -> Result<Val> {
66 evaluate_named(self.context_creator.unwrap(), &self.value, self.name)61 evaluate_named(s, self.fctx.unwrap(), &self.value, self.name)
67 }62 }
68 }63 }
69 LazyVal::new(TraceBox(Box::new(LazyNamedBinding {64 LazyVal::new(TraceBox(Box::new(LazyNamedBinding {
70 context_creator,65 fctx,
71 name: b.name.clone(),66 name: b.name.clone(),
72 value: b.value,67 value: b.value,
73 })))68 })))
74 }69 }
75}70}
7671
77pub fn evaluate_binding(b: &BindSpec, context_creator: ContextCreator) -> (IStr, LazyBinding) {72pub fn evaluate_binding(b: &BindSpec, cctx: ContextCreator) -> (IStr, LazyBinding) {
78 let b = b.clone();73 let b = b.clone();
79 if let Some(params) = &b.params {74 if let Some(params) = &b.params {
80 let params = params.clone();75 let params = params.clone();
84 this: Option<ObjValue>,79 this: Option<ObjValue>,
85 super_obj: Option<ObjValue>,80 super_obj: Option<ObjValue>,
8681
87 context_creator: ContextCreator,82 cctx: ContextCreator,
88 name: IStr,83 name: IStr,
89 params: ParamsDesc,84 params: ParamsDesc,
90 value: LocExpr,85 value: LocExpr,
91 }86 }
92 impl LazyValValue for BindableMethodLazyVal {87 impl LazyValValue for BindableMethodLazyVal {
93 fn get(self: Box<Self>) -> Result<Val> {88 fn get(self: Box<Self>, s: State) -> Result<Val> {
94 Ok(evaluate_method(89 Ok(evaluate_method(
95 self.context_creator.create(self.this, self.super_obj)?,90 self.cctx.create(s, self.this, self.super_obj)?,
96 self.name,91 self.name,
97 self.params,92 self.params,
98 self.value,93 self.value,
10297
103 #[derive(Trace)]98 #[derive(Trace)]
104 struct BindableMethod {99 struct BindableMethod {
105 context_creator: ContextCreator,100 cctx: ContextCreator,
106 name: IStr,101 name: IStr,
107 params: ParamsDesc,102 params: ParamsDesc,
108 value: LocExpr,103 value: LocExpr,
109 }104 }
110 impl Bindable for BindableMethod {105 impl Bindable for BindableMethod {
111 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {106 fn bind(
107 &self,
108 _: State,
109 this: Option<ObjValue>,
110 super_obj: Option<ObjValue>,
111 ) -> Result<LazyVal> {
112 Ok(LazyVal::new(TraceBox(Box::new(BindableMethodLazyVal {112 Ok(LazyVal::new(TraceBox(Box::new(BindableMethodLazyVal {
113 this,113 this,
114 super_obj,114 super_obj,
115115
116 context_creator: self.context_creator.clone(),116 cctx: self.cctx.clone(),
117 name: self.name.clone(),117 name: self.name.clone(),
118 params: self.params.clone(),118 params: self.params.clone(),
119 value: self.value.clone(),119 value: self.value.clone(),
124 (124 (
125 b.name.clone(),125 b.name.clone(),
126 LazyBinding::Bindable(Cc::new(TraceBox(Box::new(BindableMethod {126 LazyBinding::Bindable(Cc::new(TraceBox(Box::new(BindableMethod {
127 context_creator,127 cctx,
128 name: b.name.clone(),128 name: b.name.clone(),
129 params,129 params,
130 value: b.value.clone(),130 value: b.value.clone(),
136 this: Option<ObjValue>,136 this: Option<ObjValue>,
137 super_obj: Option<ObjValue>,137 super_obj: Option<ObjValue>,
138138
139 context_creator: ContextCreator,139 cctx: ContextCreator,
140 name: IStr,140 name: IStr,
141 value: LocExpr,141 value: LocExpr,
142 }142 }
143 impl LazyValValue for BindableNamedLazyVal {143 impl LazyValValue for BindableNamedLazyVal {
144 fn get(self: Box<Self>) -> Result<Val> {144 fn get(self: Box<Self>, s: State) -> Result<Val> {
145 evaluate_named(145 evaluate_named(
146 s.clone(),
146 self.context_creator.create(self.this, self.super_obj)?,147 self.cctx.create(s, self.this, self.super_obj)?,
147 &self.value,148 &self.value,
148 self.name,149 self.name,
149 )150 )
152153
153 #[derive(Trace)]154 #[derive(Trace)]
154 struct BindableNamed {155 struct BindableNamed {
155 context_creator: ContextCreator,156 cctx: ContextCreator,
156 name: IStr,157 name: IStr,
157 value: LocExpr,158 value: LocExpr,
158 }159 }
159 impl Bindable for BindableNamed {160 impl Bindable for BindableNamed {
160 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {161 fn bind(
162 &self,
163 _: State,
164 this: Option<ObjValue>,
165 super_obj: Option<ObjValue>,
166 ) -> Result<LazyVal> {
161 Ok(LazyVal::new(TraceBox(Box::new(BindableNamedLazyVal {167 Ok(LazyVal::new(TraceBox(Box::new(BindableNamedLazyVal {
162 this,168 this,
163 super_obj,169 super_obj,
164170
165 context_creator: self.context_creator.clone(),171 cctx: self.cctx.clone(),
166 name: self.name.clone(),172 name: self.name.clone(),
167 value: self.value.clone(),173 value: self.value.clone(),
168 }))))174 }))))
172 (178 (
173 b.name.clone(),179 b.name.clone(),
174 LazyBinding::Bindable(Cc::new(TraceBox(Box::new(BindableNamed {180 LazyBinding::Bindable(Cc::new(TraceBox(Box::new(BindableNamed {
175 context_creator,181 cctx,
176 name: b.name.clone(),182 name: b.name.clone(),
177 value: b.value.clone(),183 value: b.value.clone(),
178 })))),184 })))),
190}196}
191197
192pub fn evaluate_field_name(198pub fn evaluate_field_name(
199 s: State,
193 context: Context,200 ctx: Context,
194 field_name: &jrsonnet_parser::FieldName,201 field_name: &jrsonnet_parser::FieldName,
195) -> Result<Option<IStr>> {202) -> Result<Option<IStr>> {
196 Ok(match field_name {203 Ok(match field_name {
197 jrsonnet_parser::FieldName::Fixed(n) => Some(n.clone()),204 jrsonnet_parser::FieldName::Fixed(n) => Some(n.clone()),
198 jrsonnet_parser::FieldName::Dyn(expr) => push_frame(205 jrsonnet_parser::FieldName::Dyn(expr) => s.push(
199 CallLocation::new(&expr.1),206 CallLocation::new(&expr.1),
200 || "evaluating field name".to_string(),207 || "evaluating field name".to_string(),
201 || {208 || {
202 let value = evaluate(context, expr)?;209 let value = evaluate(s.clone(), ctx, expr)?;
203 if matches!(value, Val::Null) {210 if matches!(value, Val::Null) {
204 Ok(None)211 Ok(None)
205 } else {212 } else {
206 Ok(Some(IStr::try_from(value)?))213 Ok(Some(IStr::from_untyped(value, s.clone())?))
207 }214 }
208 },215 },
209 )?,216 )?,
210 })217 })
211}218}
212219
213pub fn evaluate_comp(220pub fn evaluate_comp(
221 s: State,
214 context: Context,222 ctx: Context,
215 specs: &[CompSpec],223 specs: &[CompSpec],
216 callback: &mut impl FnMut(Context) -> Result<()>,224 callback: &mut impl FnMut(Context) -> Result<()>,
217) -> Result<()> {225) -> Result<()> {
218 match specs.get(0) {226 match specs.get(0) {
219 None => callback(context)?,227 None => callback(ctx)?,
220 Some(CompSpec::IfSpec(IfSpecData(cond))) => {228 Some(CompSpec::IfSpec(IfSpecData(cond))) => {
221 if bool::try_from(evaluate(context.clone(), cond)?)? {229 if bool::from_untyped(evaluate(s.clone(), ctx.clone(), cond)?, s.clone())? {
222 evaluate_comp(context, &specs[1..], callback)?230 evaluate_comp(s, ctx, &specs[1..], callback)?
223 }231 }
224 }232 }
225 Some(CompSpec::ForSpec(ForSpecData(var, expr))) => match evaluate(context.clone(), expr)? {233 Some(CompSpec::ForSpec(ForSpecData(var, expr))) => {
234 match evaluate(s.clone(), ctx.clone(), expr)? {
226 Val::Arr(list) => {235 Val::Arr(list) => {
227 for item in list.iter() {236 for item in list.iter(s.clone()) {
228 evaluate_comp(237 evaluate_comp(
238 s.clone(),
229 context.clone().with_var(var.clone(), item?.clone()),239 ctx.clone().with_var(var.clone(), item?.clone()),
230 &specs[1..],240 &specs[1..],
231 callback,241 callback,
232 )?242 )?
233 }243 }
234 }244 }
235 _ => throw!(InComprehensionCanOnlyIterateOverArray),245 _ => throw!(InComprehensionCanOnlyIterateOverArray),
236 },246 }
247 }
237 }248 }
238 Ok(())249 Ok(())
239}250}
240251
241pub fn evaluate_member_list_object(context: Context, members: &[Member]) -> Result<ObjValue> {252pub fn evaluate_member_list_object(s: State, ctx: Context, members: &[Member]) -> Result<ObjValue> {
242 let new_bindings = FutureWrapper::new();253 let new_bindings = FutureWrapper::new();
243 let future_this = FutureWrapper::new();254 let future_this = FutureWrapper::new();
244 let context_creator = ContextCreator(context.clone(), new_bindings.clone());255 let cctx = ContextCreator(ctx.clone(), new_bindings.clone());
245 {256 {
246 let mut bindings: GcHashMap<IStr, LazyBinding> = GcHashMap::with_capacity(members.len());257 let mut bindings: GcHashMap<IStr, LazyBinding> = GcHashMap::with_capacity(members.len());
247 for (n, b) in members258 for (n, b) in members
250 Member::BindStmt(b) => Some(b.clone()),261 Member::BindStmt(b) => Some(b.clone()),
251 _ => None,262 _ => None,
252 })263 })
253 .map(|b| evaluate_binding(&b, context_creator.clone()))264 .map(|b| evaluate_binding(&b, cctx.clone()))
254 {265 {
255 bindings.insert(n, b);266 bindings.insert(n, b);
256 }267 }
267 visibility,278 visibility,
268 value,279 value,
269 }) => {280 }) => {
270 let name = evaluate_field_name(context.clone(), name)?;281 let name = evaluate_field_name(s.clone(), ctx.clone(), name)?;
271 if name.is_none() {282 if name.is_none() {
272 continue;283 continue;
273 }284 }
274 let name = name.unwrap();285 let name = name.unwrap();
275286
276 #[derive(Trace)]287 #[derive(Trace)]
277 struct ObjMemberBinding {288 struct ObjMemberBinding {
278 context_creator: ContextCreator,289 cctx: ContextCreator,
279 value: LocExpr,290 value: LocExpr,
280 name: IStr,291 name: IStr,
281 }292 }
282 impl Bindable for ObjMemberBinding {293 impl Bindable for ObjMemberBinding {
283 fn bind(294 fn bind(
284 &self,295 &self,
296 s: State,
285 this: Option<ObjValue>,297 this: Option<ObjValue>,
286 super_obj: Option<ObjValue>,298 super_obj: Option<ObjValue>,
287 ) -> Result<LazyVal> {299 ) -> Result<LazyVal> {
288 Ok(LazyVal::new_resolved(evaluate_named(300 Ok(LazyVal::new_resolved(evaluate_named(
301 s.clone(),
289 self.context_creator.create(this, super_obj)?,302 self.cctx.create(s, this, super_obj)?,
290 &self.value,303 &self.value,
291 self.name.clone(),304 self.name.clone(),
292 )?))305 )?))
298 .with_visibility(*visibility)311 .with_visibility(*visibility)
299 .with_location(value.1.clone())312 .with_location(value.1.clone())
300 .bindable(TraceBox(Box::new(ObjMemberBinding {313 .bindable(
314 s.clone(),
315 TraceBox(Box::new(ObjMemberBinding {
301 context_creator: context_creator.clone(),316 cctx: cctx.clone(),
302 value: value.clone(),317 value: value.clone(),
303 name,318 name,
304 })))?;319 })),
320 )?;
305 }321 }
306 Member::Field(FieldMember {322 Member::Field(FieldMember {
309 value,325 value,
310 ..326 ..
311 }) => {327 }) => {
312 let name = evaluate_field_name(context.clone(), name)?;328 let name = evaluate_field_name(s.clone(), ctx.clone(), name)?;
313 if name.is_none() {329 if name.is_none() {
314 continue;330 continue;
315 }331 }
316 let name = name.unwrap();332 let name = name.unwrap();
317 #[derive(Trace)]333 #[derive(Trace)]
318 struct ObjMemberBinding {334 struct ObjMemberBinding {
319 context_creator: ContextCreator,335 cctx: ContextCreator,
320 value: LocExpr,336 value: LocExpr,
321 params: ParamsDesc,337 params: ParamsDesc,
322 name: IStr,338 name: IStr,
323 }339 }
324 impl Bindable for ObjMemberBinding {340 impl Bindable for ObjMemberBinding {
325 fn bind(341 fn bind(
326 &self,342 &self,
343 s: State,
327 this: Option<ObjValue>,344 this: Option<ObjValue>,
328 super_obj: Option<ObjValue>,345 super_obj: Option<ObjValue>,
329 ) -> Result<LazyVal> {346 ) -> Result<LazyVal> {
330 Ok(LazyVal::new_resolved(evaluate_method(347 Ok(LazyVal::new_resolved(evaluate_method(
331 self.context_creator.create(this, super_obj)?,348 self.cctx.create(s, this, super_obj)?,
332 self.name.clone(),349 self.name.clone(),
333 self.params.clone(),350 self.params.clone(),
334 self.value.clone(),351 self.value.clone(),
340 .hide()357 .hide()
341 .with_location(value.1.clone())358 .with_location(value.1.clone())
342 .bindable(TraceBox(Box::new(ObjMemberBinding {359 .bindable(
360 s.clone(),
361 TraceBox(Box::new(ObjMemberBinding {
343 context_creator: context_creator.clone(),362 cctx: cctx.clone(),
344 value: value.clone(),363 value: value.clone(),
345 params: params.clone(),364 params: params.clone(),
346 name,365 name,
347 })))?;366 })),
367 )?;
348 }368 }
349 Member::BindStmt(_) => {}369 Member::BindStmt(_) => {}
350 Member::AssertStmt(stmt) => {370 Member::AssertStmt(stmt) => {
351 #[derive(Trace)]371 #[derive(Trace)]
352 struct ObjectAssert {372 struct ObjectAssert {
353 context_creator: ContextCreator,373 cctx: ContextCreator,
354 assert: AssertStmt,374 assert: AssertStmt,
355 }375 }
356 impl ObjectAssertion for ObjectAssert {376 impl ObjectAssertion for ObjectAssert {
357 fn run(377 fn run(
358 &self,378 &self,
379 s: State,
359 this: Option<ObjValue>,380 this: Option<ObjValue>,
360 super_obj: Option<ObjValue>,381 super_obj: Option<ObjValue>,
361 ) -> Result<()> {382 ) -> Result<()> {
362 let ctx = self.context_creator.create(this, super_obj)?;383 let ctx = self.cctx.create(s.clone(), this, super_obj)?;
363 evaluate_assert(ctx, &self.assert)384 evaluate_assert(s, ctx, &self.assert)
364 }385 }
365 }386 }
366 builder.assert(TraceBox(Box::new(ObjectAssert {387 builder.assert(TraceBox(Box::new(ObjectAssert {
367 context_creator: context_creator.clone(),388 cctx: cctx.clone(),
368 assert: stmt.clone(),389 assert: stmt.clone(),
369 })));390 })));
370 }391 }
375 Ok(this)396 Ok(this)
376}397}
377398
378pub fn evaluate_object(context: Context, object: &ObjBody) -> Result<ObjValue> {399pub fn evaluate_object(s: State, ctx: Context, object: &ObjBody) -> Result<ObjValue> {
379 Ok(match object {400 Ok(match object {
380 ObjBody::MemberList(members) => evaluate_member_list_object(context, members)?,401 ObjBody::MemberList(members) => evaluate_member_list_object(s, ctx, members)?,
381 ObjBody::ObjComp(obj) => {402 ObjBody::ObjComp(obj) => {
382 let future_this = FutureWrapper::new();403 let future_this = FutureWrapper::new();
383 let mut builder = ObjValueBuilder::new();404 let mut builder = ObjValueBuilder::new();
384 evaluate_comp(context.clone(), &obj.compspecs, &mut |ctx| {405 evaluate_comp(s.clone(), ctx, &obj.compspecs, &mut |ctx| {
385 let new_bindings = FutureWrapper::new();406 let new_bindings = FutureWrapper::new();
386 let context_creator = ContextCreator(context.clone(), new_bindings.clone());407 let cctx = ContextCreator(ctx.clone(), new_bindings.clone());
387 let mut bindings: GcHashMap<IStr, LazyBinding> =408 let mut bindings: GcHashMap<IStr, LazyBinding> =
388 GcHashMap::with_capacity(obj.pre_locals.len() + obj.post_locals.len());409 GcHashMap::with_capacity(obj.pre_locals.len() + obj.post_locals.len());
389 for (n, b) in obj410 for (n, b) in obj
390 .pre_locals411 .pre_locals
391 .iter()412 .iter()
392 .chain(obj.post_locals.iter())413 .chain(obj.post_locals.iter())
393 .map(|b| evaluate_binding(b, context_creator.clone()))414 .map(|b| evaluate_binding(b, cctx.clone()))
394 {415 {
395 bindings.insert(n, b);416 bindings.insert(n, b);
396 }417 }
397 new_bindings.fill(bindings.clone());418 new_bindings.fill(bindings.clone());
398 let ctx = ctx.extend_unbound(bindings, None, None, None)?;419 let ctx = ctx.extend_unbound(s.clone(), bindings, None, None, None)?;
399 let key = evaluate(ctx.clone(), &obj.key)?;420 let key = evaluate(s.clone(), ctx.clone(), &obj.key)?;
400421
401 match key {422 match key {
402 Val::Null => {}423 Val::Null => {}
403 Val::Str(n) => {424 Val::Str(n) => {
404 #[derive(Trace)]425 #[derive(Trace)]
405 struct ObjCompBinding {426 struct ObjCompBinding {
406 context: Context,427 ctx: Context,
407 value: LocExpr,428 value: LocExpr,
408 }429 }
409 impl Bindable for ObjCompBinding {430 impl Bindable for ObjCompBinding {
410 fn bind(431 fn bind(
411 &self,432 &self,
433 s: State,
412 this: Option<ObjValue>,434 this: Option<ObjValue>,
413 _super_obj: Option<ObjValue>,435 _super_obj: Option<ObjValue>,
414 ) -> Result<LazyVal> {436 ) -> Result<LazyVal> {
415 Ok(LazyVal::new_resolved(evaluate(437 Ok(LazyVal::new_resolved(evaluate(
438 s,
416 self.context439 self.ctx.clone().extend(GcHashMap::new(), None, this, None),
417 .clone()
418 .extend(GcHashMap::new(), None, this, None),
419 &self.value,440 &self.value,
425 .with_location(obj.value.1.clone())446 .with_location(obj.value.1.clone())
426 .with_add(obj.plus)447 .with_add(obj.plus)
427 .bindable(TraceBox(Box::new(ObjCompBinding {448 .bindable(
449 s.clone(),
450 TraceBox(Box::new(ObjCompBinding {
428 context: ctx,451 ctx,
429 value: obj.value.clone(),452 value: obj.value.clone(),
430 })))?;453 })),
454 )?;
431 }455 }
432 v => throw!(FieldMustBeStringGot(v.value_type())),456 v => throw!(FieldMustBeStringGot(v.value_type())),
443}467}
444468
445pub fn evaluate_apply(469pub fn evaluate_apply(
470 s: State,
446 context: Context,471 ctx: Context,
447 value: &LocExpr,472 value: &LocExpr,
448 args: &ArgsDesc,473 args: &ArgsDesc,
449 loc: CallLocation,474 loc: CallLocation,
450 tailstrict: bool,475 tailstrict: bool,
451) -> Result<Val> {476) -> Result<Val> {
452 let value = evaluate(context.clone(), value)?;477 let value = evaluate(s.clone(), ctx.clone(), value)?;
453 Ok(match value {478 Ok(match value {
454 Val::Func(f) => {479 Val::Func(f) => {
455 let body = || f.evaluate(context, loc, args, tailstrict);480 let body = || f.evaluate(s.clone(), ctx, loc, args, tailstrict);
456 if tailstrict {481 if tailstrict {
457 body()?482 body()?
458 } else {483 } else {
459 push_frame(loc, || format!("function <{}> call", f.name()), body)?484 s.push(loc, || format!("function <{}> call", f.name()), body)?
460 }485 }
461 }486 }
462 v => throw!(OnlyFunctionsCanBeCalledGot(v.value_type())),487 v => throw!(OnlyFunctionsCanBeCalledGot(v.value_type())),
463 })488 })
464}489}
465490
466pub fn evaluate_assert(context: Context, assertion: &AssertStmt) -> Result<()> {491pub fn evaluate_assert(s: State, ctx: Context, assertion: &AssertStmt) -> Result<()> {
467 let value = &assertion.0;492 let value = &assertion.0;
468 let msg = &assertion.1;493 let msg = &assertion.1;
469 let assertion_result = push_frame(494 let assertion_result = s.push(
470 CallLocation::new(&value.1),495 CallLocation::new(&value.1),
471 || "assertion condition".to_owned(),496 || "assertion condition".to_owned(),
472 || bool::try_from(evaluate(context.clone(), value)?),497 || bool::from_untyped(evaluate(s.clone(), ctx.clone(), value)?, s.clone()),
473 )?;498 )?;
474 if !assertion_result {499 if !assertion_result {
475 push_frame(500 s.push(
476 CallLocation::new(&value.1),501 CallLocation::new(&value.1),
477 || "assertion failure".to_owned(),502 || "assertion failure".to_owned(),
478 || {503 || {
479 if let Some(msg) = msg {504 if let Some(msg) = msg {
480 throw!(AssertionFailed(evaluate(context, msg)?.to_string()?));505 throw!(AssertionFailed(
506 evaluate(s.clone(), ctx, msg)?.to_string(s.clone())?
507 ));
481 } else {508 } else {
482 throw!(AssertionFailed(Val::Null.to_string()?));509 throw!(AssertionFailed(Val::Null.to_string(s.clone())?));
483 }510 }
484 },511 },
485 )?512 )?
486 }513 }
487 Ok(())514 Ok(())
488}515}
489516
490pub fn evaluate_named(context: Context, lexpr: &LocExpr, name: IStr) -> Result<Val> {517pub fn evaluate_named(s: State, ctx: Context, lexpr: &LocExpr, name: IStr) -> Result<Val> {
491 use Expr::*;518 use Expr::*;
492 let LocExpr(expr, _loc) = lexpr;519 let LocExpr(expr, _loc) = lexpr;
493 Ok(match &**expr {520 Ok(match &**expr {
494 Function(params, body) => evaluate_method(context, name, params.clone(), body.clone()),521 Function(params, body) => evaluate_method(ctx, name, params.clone(), body.clone()),
495 _ => evaluate(context, lexpr)?,522 _ => evaluate(s, ctx, lexpr)?,
496 })523 })
497}524}
498525
499pub fn evaluate(context: Context, expr: &LocExpr) -> Result<Val> {526pub fn evaluate(s: State, ctx: Context, expr: &LocExpr) -> Result<Val> {
500 use Expr::*;527 use Expr::*;
501 let LocExpr(expr, loc) = expr;528 let LocExpr(expr, loc) = expr;
502 // let bp = with_state(|s| s.0.stop_at.borrow().clone());529 // let bp = with_state(|s| s.0.stop_at.borrow().clone());
503 Ok(match &**expr {530 Ok(match &**expr {
504 Literal(LiteralType::This) => {531 Literal(LiteralType::This) => {
505 Val::Obj(context.this().clone().ok_or(CantUseSelfOutsideOfObject)?)532 Val::Obj(ctx.this().clone().ok_or(CantUseSelfOutsideOfObject)?)
506 }533 }
507 Literal(LiteralType::Super) => Val::Obj(534 Literal(LiteralType::Super) => Val::Obj(
508 context
509 .super_obj()535 ctx.super_obj()
510 .clone()536 .clone()
511 .ok_or(NoSuperFound)?537 .ok_or(NoSuperFound)?
512 .with_this(context.this().clone().unwrap()),538 .with_this(ctx.this().clone().unwrap()),
513 ),539 ),
514 Literal(LiteralType::Dollar) => {540 Literal(LiteralType::Dollar) => {
515 Val::Obj(context.dollar().clone().ok_or(NoTopLevelObjectFound)?)541 Val::Obj(ctx.dollar().clone().ok_or(NoTopLevelObjectFound)?)
516 }542 }
517 Literal(LiteralType::True) => Val::Bool(true),543 Literal(LiteralType::True) => Val::Bool(true),
518 Literal(LiteralType::False) => Val::Bool(false),544 Literal(LiteralType::False) => Val::Bool(false),
519 Literal(LiteralType::Null) => Val::Null,545 Literal(LiteralType::Null) => Val::Null,
520 Parened(e) => evaluate(context, e)?,546 Parened(e) => evaluate(s, ctx, e)?,
521 Str(v) => Val::Str(v.clone()),547 Str(v) => Val::Str(v.clone()),
522 Num(v) => Val::new_checked_num(*v)?,548 Num(v) => Val::new_checked_num(*v)?,
523 BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, v1, *o, v2)?,549 BinaryOp(v1, o, v2) => evaluate_binary_op_special(s, ctx, v1, *o, v2)?,
524 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,550 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(s, ctx, v)?)?,
525 Var(name) => push_frame(551 Var(name) => s.push(
526 CallLocation::new(loc),552 CallLocation::new(loc),
527 || format!("variable <{}> access", name),553 || format!("variable <{}> access", name),
528 || context.binding(name.clone())?.evaluate(),554 || ctx.binding(name.clone())?.evaluate(s.clone()),
529 )?,555 )?,
530 Index(value, index) => {556 Index(value, index) => {
531 match (evaluate(context.clone(), value)?, evaluate(context, index)?) {557 match (
558 evaluate(s.clone(), ctx.clone(), value)?,
559 evaluate(s.clone(), ctx, index)?,
560 ) {
532 (Val::Obj(v), Val::Str(s)) => {561 (Val::Obj(v), Val::Str(key)) => s.push(
533 let sn = s.clone();
534 push_frame(
535 CallLocation::new(loc),562 CallLocation::new(loc),
536 || format!("field <{}> access", sn),563 || format!("field <{}> access", key),
537 || {564 || {
538 if let Some(v) = v.get(s.clone())? {565 if let Some(v) = v.get(s.clone(), key.clone())? {
539 Ok(v)566 Ok(v)
540 } else {567 } else {
541 throw!(NoSuchField(s))568 throw!(NoSuchField(key.clone()))
542 }569 }
543 },570 },
544 )?571 )?,
545 }
546 (Val::Obj(_), n) => throw!(ValueIndexMustBeTypeGot(572 (Val::Obj(_), n) => throw!(ValueIndexMustBeTypeGot(
547 ValType::Obj,573 ValType::Obj,
548 ValType::Str,574 ValType::Str,
553 if n.fract() > f64::EPSILON {579 if n.fract() > f64::EPSILON {
554 throw!(FractionalIndex)580 throw!(FractionalIndex)
555 }581 }
556 v.get(n as usize)?582 v.get(s, n as usize)?
557 .ok_or_else(|| ArrayBoundsError(n as usize, v.len()))?583 .ok_or_else(|| ArrayBoundsError(n as usize, v.len()))?
558 }584 }
559 (Val::Arr(_), Val::Str(n)) => throw!(AttemptedIndexAnArrayWithString(n)),585 (Val::Arr(_), Val::Str(n)) => throw!(AttemptedIndexAnArrayWithString(n)),
582 LocalExpr(bindings, returned) => {608 LocalExpr(bindings, returned) => {
583 let mut new_bindings: GcHashMap<IStr, LazyVal> =609 let mut new_bindings: GcHashMap<IStr, LazyVal> =
584 GcHashMap::with_capacity(bindings.len());610 GcHashMap::with_capacity(bindings.len());
585 let future_context = Context::new_future();611 let fctx = Context::new_future();
586 for b in bindings {612 for b in bindings {
587 new_bindings.insert(613 new_bindings.insert(b.name.clone(), evaluate_binding_in_future(b, fctx.clone()));
588 b.name.clone(),
589 evaluate_binding_in_future(b, future_context.clone()),
590 );
591 }614 }
592 let context = context615 let ctx = ctx.extend_bound(new_bindings).into_future(fctx);
593 .extend_bound(new_bindings)
594 .into_future(future_context);
595 evaluate(context, &returned.clone())?616 evaluate(s, ctx, &returned.clone())?
596 }617 }
597 Arr(items) => {618 Arr(items) => {
598 let mut out = Vec::with_capacity(items.len());619 let mut out = Vec::with_capacity(items.len());
599 for item in items {620 for item in items {
600 // TODO: Implement ArrValue::Lazy with same context for every element?621 // TODO: Implement ArrValue::Lazy with same context for every element?
601 #[derive(Trace)]622 #[derive(Trace)]
602 struct ArrayElement {623 struct ArrayElement {
603 context: Context,624 ctx: Context,
604 item: LocExpr,625 item: LocExpr,
605 }626 }
606 impl LazyValValue for ArrayElement {627 impl LazyValValue for ArrayElement {
607 fn get(self: Box<Self>) -> Result<Val> {628 fn get(self: Box<Self>, s: State) -> Result<Val> {
608 evaluate(self.context, &self.item)629 evaluate(s, self.ctx, &self.item)
609 }630 }
610 }631 }
611 out.push(LazyVal::new(TraceBox(Box::new(ArrayElement {632 out.push(LazyVal::new(TraceBox(Box::new(ArrayElement {
612 context: context.clone(),633 ctx: ctx.clone(),
613 item: item.clone(),634 item: item.clone(),
614 }))));635 }))));
615 }636 }
616 Val::Arr(out.into())637 Val::Arr(out.into())
617 }638 }
618 ArrComp(expr, comp_specs) => {639 ArrComp(expr, comp_specs) => {
619 let mut out = Vec::new();640 let mut out = Vec::new();
620 evaluate_comp(context, comp_specs, &mut |ctx| {641 evaluate_comp(s.clone(), ctx, comp_specs, &mut |ctx| {
621 out.push(evaluate(ctx, expr)?);642 out.push(evaluate(s.clone(), ctx, expr)?);
622 Ok(())643 Ok(())
623 })?;644 })?;
624 Val::Arr(ArrValue::Eager(Cc::new(out)))645 Val::Arr(ArrValue::Eager(Cc::new(out)))
625 }646 }
626 Obj(body) => Val::Obj(evaluate_object(context, body)?),647 Obj(body) => Val::Obj(evaluate_object(s, ctx, body)?),
627 ObjExtend(s, t) => evaluate_add_op(648 ObjExtend(a, b) => evaluate_add_op(
649 s.clone(),
628 &evaluate(context.clone(), s)?,650 &evaluate(s.clone(), ctx.clone(), a)?,
629 &Val::Obj(evaluate_object(context, t)?),651 &Val::Obj(evaluate_object(s, ctx, b)?),
630 )?,652 )?,
631 Apply(value, args, tailstrict) => {653 Apply(value, args, tailstrict) => {
632 evaluate_apply(context, value, args, CallLocation::new(loc), *tailstrict)?654 evaluate_apply(s, ctx, value, args, CallLocation::new(loc), *tailstrict)?
633 }655 }
634 Function(params, body) => {656 Function(params, body) => {
635 evaluate_method(context, "anonymous".into(), params.clone(), body.clone())657 evaluate_method(ctx, "anonymous".into(), params.clone(), body.clone())
636 }658 }
637 Intrinsic(name) => Val::Func(FuncVal::StaticBuiltin(659 Intrinsic(name) => Val::Func(FuncVal::StaticBuiltin(
638 BUILTINS660 BUILTINS
639 .with(|b| b.get(name).copied())661 .with(|b| b.get(name).copied())
640 .ok_or_else(|| IntrinsicNotFound(name.clone()))?,662 .ok_or_else(|| IntrinsicNotFound(name.clone()))?,
641 )),663 )),
642 AssertExpr(assert, returned) => {664 AssertExpr(assert, returned) => {
643 evaluate_assert(context.clone(), assert)?;665 evaluate_assert(s.clone(), ctx.clone(), assert)?;
644 evaluate(context, returned)?666 evaluate(s, ctx, returned)?
645 }667 }
646 ErrorStmt(e) => push_frame(668 ErrorStmt(e) => s.push(
647 CallLocation::new(loc),669 CallLocation::new(loc),
648 || "error statement".to_owned(),670 || "error statement".to_owned(),
649 || throw!(RuntimeError(evaluate(context, e)?.to_string()?,)),671 || {
672 throw!(RuntimeError(
673 evaluate(s.clone(), ctx, e)?.to_string(s.clone())?,
674 ))
675 },
650 )?,676 )?,
651 IfElse {677 IfElse {
652 cond,678 cond,
653 cond_then,679 cond_then,
654 cond_else,680 cond_else,
655 } => {681 } => {
656 if push_frame(682 if s.push(
657 CallLocation::new(loc),683 CallLocation::new(loc),
658 || "if condition".to_owned(),684 || "if condition".to_owned(),
659 || bool::try_from(evaluate(context.clone(), &cond.0)?),685 || bool::from_untyped(evaluate(s.clone(), ctx.clone(), &cond.0)?, s.clone()),
660 )? {686 )? {
661 evaluate(context, cond_then)?687 evaluate(s, ctx, cond_then)?
662 } else {688 } else {
663 match cond_else {689 match cond_else {
664 Some(v) => evaluate(context, v)?,690 Some(v) => evaluate(s, ctx, v)?,
665 None => Val::Null,691 None => Val::Null,
666 }692 }
667 }693 }
668 }694 }
669 Slice(value, desc) => {695 Slice(value, desc) => {
670 let indexable = evaluate(context.clone(), value)?;696 let indexable = evaluate(s.clone(), ctx.clone(), value)?;
671 let loc = CallLocation::new(loc);697 let loc = CallLocation::new(loc);
672698
673 fn parse_idx<const MIN: usize>(699 fn parse_idx<T: Typed>(
674 loc: CallLocation,700 loc: CallLocation,
701 s: State,
675 context: &Context,702 ctx: &Context,
676 expr: &Option<LocExpr>,703 expr: &Option<LocExpr>,
677 desc: &'static str,704 desc: &'static str,
678 ) -> Result<Option<BoundedUsize<MIN, { i32::MAX as usize }>>> {705 ) -> Result<Option<T>> {
679 if let Some(value) = expr {706 if let Some(value) = expr {
680 Ok(Some(push_frame(707 Ok(Some(s.push(
681 loc,708 loc,
682 || format!("slice {}", desc),709 || format!("slice {}", desc),
683 || evaluate(context.clone(), value)?.try_into(),710 || T::from_untyped(evaluate(s.clone(), ctx.clone(), value)?, s.clone()),
684 )?))711 )?))
685 } else {712 } else {
686 Ok(None)713 Ok(None)
687 }714 }
688 }715 }
689716
690 let start = parse_idx(loc, &context, &desc.start, "start")?;717 let start = parse_idx(loc, s.clone(), &ctx, &desc.start, "start")?;
691 let end = parse_idx(loc, &context, &desc.end, "end")?;718 let end = parse_idx(loc, s.clone(), &ctx, &desc.end, "end")?;
692 let step = parse_idx(loc, &context, &desc.step, "step")?;719 let step = parse_idx(loc, s, &ctx, &desc.step, "step")?;
693720
694 std_slice(indexable.into_indexable()?, start, end, step)?721 std_slice(indexable.into_indexable()?, start, end, step)?
695 }722 }
696 Import(path) => {723 Import(path) => {
697 let tmp = loc.clone().0;724 let tmp = loc.clone().0;
698 let mut import_location = tmp.to_path_buf();725 let mut import_location = tmp.to_path_buf();
699 import_location.pop();726 import_location.pop();
700 push_frame(727 s.push(
701 CallLocation::new(loc),728 CallLocation::new(loc),
702 || format!("import {:?}", path),729 || format!("import {:?}", path),
703 || with_state(|s| s.import_file(&import_location, path)),730 || s.import_file(&import_location, path),
704 )?731 )?
705 }732 }
706 ImportStr(path) => {733 ImportStr(path) => {
707 let tmp = loc.clone().0;734 let tmp = loc.clone().0;
708 let mut import_location = tmp.to_path_buf();735 let mut import_location = tmp.to_path_buf();
709 import_location.pop();736 import_location.pop();
710 Val::Str(with_state(|s| s.import_file_str(&import_location, path))?)737 Val::Str(s.import_file_str(&import_location, path)?)
711 }738 }
712 ImportBin(path) => {739 ImportBin(path) => {
713 let tmp = loc.clone().0;740 let tmp = loc.clone().0;
714 let mut import_location = tmp.to_path_buf();741 let mut import_location = tmp.to_path_buf();
715 import_location.pop();742 import_location.pop();
716 let bytes = with_state(|s| s.import_file_bin(&import_location, path))?;743 let bytes = s.import_file_bin(&import_location, path)?;
717 Val::Arr(ArrValue::Bytes(bytes))744 Val::Arr(ArrValue::Bytes(bytes))
718 }745 }
719 })746 })
modifiedcrates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth
1use std::convert::TryInto;
2
3use jrsonnet_parser::{BinaryOpType, LocExpr, UnaryOpType};1use jrsonnet_parser::{BinaryOpType, LocExpr, UnaryOpType};
42
5use crate::{3use crate::{
6 builtin::std_format, error::Error::*, evaluate, throw, val::equals, Context, Result, Val,4 builtin::std_format, error::Error::*, evaluate, throw, typed::Typed, val::equals, Context,
5 Result, State, Val,
7};6};
87
9pub fn evaluate_unary_op(op: UnaryOpType, b: &Val) -> Result<Val> {8pub fn evaluate_unary_op(op: UnaryOpType, b: &Val) -> Result<Val> {
17 })16 })
18}17}
1918
20pub fn evaluate_add_op(a: &Val, b: &Val) -> Result<Val> {19pub fn evaluate_add_op(s: State, a: &Val, b: &Val) -> Result<Val> {
21 use Val::*;20 use Val::*;
22 Ok(match (a, b) {21 Ok(match (a, b) {
23 (Str(v1), Str(v2)) => Str(((**v1).to_owned() + v2).into()),22 (Str(v1), Str(v2)) => Str(((**v1).to_owned() + v2).into()),
26 (Num(n), Str(o)) => Str(format!("{}{}", n, o).into()),25 (Num(n), Str(o)) => Str(format!("{}{}", n, o).into()),
27 (Str(o), Num(n)) => Str(format!("{}{}", o, n).into()),26 (Str(o), Num(n)) => Str(format!("{}{}", o, n).into()),
2827
29 (Str(s), o) => Str(format!("{}{}", s, o.clone().to_string()?).into()),28 (Str(a), o) => Str(format!("{}{}", a, o.clone().to_string(s)?).into()),
30 (o, Str(s)) => Str(format!("{}{}", o.clone().to_string()?, s).into()),29 (o, Str(a)) => Str(format!("{}{}", o.clone().to_string(s)?, a).into()),
3130
32 (Obj(v1), Obj(v2)) => Obj(v2.extend_from(v1.clone())),31 (Obj(v1), Obj(v2)) => Obj(v2.extend_from(v1.clone())),
33 (Arr(a), Arr(b)) => {32 (Arr(a), Arr(b)) => {
45 })44 })
46}45}
4746
48pub fn evaluate_mod_op(a: &Val, b: &Val) -> Result<Val> {47pub fn evaluate_mod_op(s: State, a: &Val, b: &Val) -> Result<Val> {
49 use Val::*;48 use Val::*;
50 match (a, b) {49 match (a, b) {
51 (Num(a), Num(b)) => Ok(Num(a % b)),50 (Num(a), Num(b)) => Ok(Num(a % b)),
52 (Str(str), vals) => std_format(str.clone(), vals.clone())?.try_into(),51 (Str(str), vals) => {
52 String::into_untyped(std_format(s.clone(), str.clone(), vals.clone())?, s)
53 }
53 (a, b) => throw!(BinaryOperatorDoesNotOperateOnValues(54 (a, b) => throw!(BinaryOperatorDoesNotOperateOnValues(
54 BinaryOpType::Mod,55 BinaryOpType::Mod,
55 a.value_type(),56 a.value_type(),
59}60}
6061
61pub fn evaluate_binary_op_special(62pub fn evaluate_binary_op_special(
63 s: State,
62 context: Context,64 ctx: Context,
63 a: &LocExpr,65 a: &LocExpr,
64 op: BinaryOpType,66 op: BinaryOpType,
65 b: &LocExpr,67 b: &LocExpr,
66) -> Result<Val> {68) -> Result<Val> {
67 use BinaryOpType::*;69 use BinaryOpType::*;
68 use Val::*;70 use Val::*;
69 Ok(match (evaluate(context.clone(), a)?, op, b) {71 Ok(match (evaluate(s.clone(), ctx.clone(), a)?, op, b) {
70 (Bool(true), Or, _o) => Val::Bool(true),72 (Bool(true), Or, _o) => Val::Bool(true),
71 (Bool(false), And, _o) => Val::Bool(false),73 (Bool(false), And, _o) => Val::Bool(false),
72 (a, op, eb) => evaluate_binary_op_normal(&a, op, &evaluate(context, eb)?)?,74 (a, op, eb) => evaluate_binary_op_normal(s.clone(), &a, op, &evaluate(s, ctx, eb)?)?,
73 })75 })
74}76}
7577
76pub fn evaluate_binary_op_normal(a: &Val, op: BinaryOpType, b: &Val) -> Result<Val> {78pub fn evaluate_binary_op_normal(s: State, a: &Val, op: BinaryOpType, b: &Val) -> Result<Val> {
77 use BinaryOpType::*;79 use BinaryOpType::*;
78 use Val::*;80 use Val::*;
79 Ok(match (a, op, b) {81 Ok(match (a, op, b) {
80 (a, Add, b) => evaluate_add_op(a, b)?,82 (a, Add, b) => evaluate_add_op(s, a, b)?,
8183
82 (a, Eq, b) => Bool(equals(a, b)?),84 (a, Eq, b) => Bool(equals(s, a, b)?),
83 (a, Neq, b) => Bool(!equals(a, b)?),85 (a, Neq, b) => Bool(!equals(s, a, b)?),
8486
85 (Str(a), In, Obj(obj)) => Bool(obj.has_field_ex(a.clone(), true)),87 (Str(a), In, Obj(obj)) => Bool(obj.has_field_ex(a.clone(), true)),
86 (a, Mod, b) => evaluate_mod_op(a, b)?,88 (a, Mod, b) => evaluate_mod_op(s, a, b)?,
8789
88 (Str(v1), Mul, Num(v2)) => Str(v1.repeat(*v2 as usize).into()),90 (Str(v1), Mul, Num(v2)) => Str(v1.repeat(*v2 as usize).into()),
8991
modifiedcrates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth
1use std::{borrow::Cow, collections::HashMap, convert::TryFrom};1use std::{borrow::Cow, collections::HashMap};
22
3use gcmodule::Trace;3use gcmodule::Trace;
4use jrsonnet_interner::IStr;4use jrsonnet_interner::IStr;
5pub use jrsonnet_macros::builtin;5pub use jrsonnet_macros::builtin;
6use jrsonnet_parser::{ArgsDesc, ExprLocation, LocExpr, ParamsDesc};6use jrsonnet_parser::{ArgsDesc, ExprLocation, LocExpr, ParamsDesc};
77
8use crate::{8use crate::{
9 error::{Error::*, LocError},9 error::Error::*, evaluate, evaluate_named, gc::TraceBox, throw, typed::Typed,
10 evaluate, evaluate_named,
11 gc::TraceBox,
12 throw,
13 typed::Typed,
14 val::LazyValValue,10 val::LazyValValue, Context, FutureWrapper, GcHashMap, LazyVal, Result, State, Val,
15 Context, FutureWrapper, GcHashMap, LazyVal, Result, Val,
16};11};
1712
3025
31#[derive(Trace)]26#[derive(Trace)]
32struct EvaluateLazyVal {27struct EvaluateLazyVal {
33 context: Context,28 ctx: Context,
34 expr: LocExpr,29 expr: LocExpr,
35}30}
36impl LazyValValue for EvaluateLazyVal {31impl LazyValValue for EvaluateLazyVal {
37 fn get(self: Box<Self>) -> Result<Val> {32 fn get(self: Box<Self>, s: State) -> Result<Val> {
38 evaluate(self.context, &self.expr)33 evaluate(s, self.ctx, &self.expr)
39 }34 }
40}35}
4136
42#[derive(Trace)]37#[derive(Trace)]
43struct EvaluateNamedLazyVal {38struct EvaluateNamedLazyVal {
44 future_context: FutureWrapper<Context>,39 ctx: FutureWrapper<Context>,
45 name: IStr,40 name: IStr,
46 value: LocExpr,41 value: LocExpr,
47}42}
48impl LazyValValue for EvaluateNamedLazyVal {43impl LazyValValue for EvaluateNamedLazyVal {
49 fn get(self: Box<Self>) -> Result<Val> {44 fn get(self: Box<Self>, s: State) -> Result<Val> {
50 evaluate_named(self.future_context.unwrap(), &self.value, self.name)45 evaluate_named(s, self.ctx.unwrap(), &self.value, self.name)
51 }46 }
52}47}
5348
54pub trait ArgLike {49pub trait ArgLike {
55 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<LazyVal>;50 fn evaluate_arg(&self, s: State, ctx: Context, tailstrict: bool) -> Result<LazyVal>;
56}51}
57impl ArgLike for &LocExpr {52impl ArgLike for &LocExpr {
58 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<LazyVal> {53 fn evaluate_arg(&self, s: State, ctx: Context, tailstrict: bool) -> Result<LazyVal> {
59 Ok(if tailstrict {54 Ok(if tailstrict {
60 LazyVal::new_resolved(evaluate(ctx, self)?)55 LazyVal::new_resolved(evaluate(s, ctx, self)?)
61 } else {56 } else {
62 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {57 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {
63 context: ctx,58 ctx,
64 expr: (*self).clone(),59 expr: (*self).clone(),
65 })))60 })))
66 })61 })
69impl<T> ArgLike for T64impl<T> ArgLike for T
70where65where
71 T: Typed + Clone,66 T: Typed + Clone,
72 Val: TryFrom<T, Error = LocError>,
73{67{
74 fn evaluate_arg(&self, _ctx: Context, _tailstrict: bool) -> Result<LazyVal> {68 fn evaluate_arg(&self, s: State, _ctx: Context, _tailstrict: bool) -> Result<LazyVal> {
75 let val: Val = Val::try_from(self.clone())?;69 let val = T::into_untyped(self.clone(), s)?;
76 Ok(LazyVal::new_resolved(val))70 Ok(LazyVal::new_resolved(val))
77 }71 }
78}72}
82 Val(Val),76 Val(Val),
83}77}
84impl ArgLike for TlaArg {78impl ArgLike for TlaArg {
85 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<LazyVal> {79 fn evaluate_arg(&self, s: State, ctx: Context, tailstrict: bool) -> Result<LazyVal> {
86 match self {80 match self {
87 TlaArg::String(s) => Ok(LazyVal::new_resolved(Val::Str(s.clone()))),81 TlaArg::String(s) => Ok(LazyVal::new_resolved(Val::Str(s.clone()))),
88 TlaArg::Code(code) => Ok(if tailstrict {82 TlaArg::Code(code) => Ok(if tailstrict {
89 LazyVal::new_resolved(evaluate(ctx, code)?)83 LazyVal::new_resolved(evaluate(s, ctx, code)?)
90 } else {84 } else {
91 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {85 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {
92 context: ctx,86 ctx,
93 expr: code.clone(),87 expr: code.clone(),
94 })))88 })))
95 }),89 }),
102 fn unnamed_len(&self) -> usize;96 fn unnamed_len(&self) -> usize;
103 fn unnamed_iter(97 fn unnamed_iter(
104 &self,98 &self,
99 s: State,
105 ctx: Context,100 ctx: Context,
106 tailstrict: bool,101 tailstrict: bool,
107 handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,102 handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,
108 ) -> Result<()>;103 ) -> Result<()>;
109 fn named_iter(104 fn named_iter(
110 &self,105 &self,
106 s: State,
111 ctx: Context,107 ctx: Context,
112 tailstrict: bool,108 tailstrict: bool,
113 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,109 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,
122118
123 fn unnamed_iter(119 fn unnamed_iter(
124 &self,120 &self,
121 s: State,
125 ctx: Context,122 ctx: Context,
126 tailstrict: bool,123 tailstrict: bool,
127 handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,124 handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,
130 handler(127 handler(
131 id,128 id,
132 if tailstrict {129 if tailstrict {
133 LazyVal::new_resolved(evaluate(ctx.clone(), arg)?)130 LazyVal::new_resolved(evaluate(s.clone(), ctx.clone(), arg)?)
134 } else {131 } else {
135 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {132 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {
136 context: ctx.clone(),133 ctx: ctx.clone(),
137 expr: arg.clone(),134 expr: arg.clone(),
138 })))135 })))
139 },136 },
144141
145 fn named_iter(142 fn named_iter(
146 &self,143 &self,
144 s: State,
147 ctx: Context,145 ctx: Context,
148 tailstrict: bool,146 tailstrict: bool,
149 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,147 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,
152 handler(150 handler(
153 name,151 name,
154 if tailstrict {152 if tailstrict {
155 LazyVal::new_resolved(evaluate(ctx.clone(), arg)?)153 LazyVal::new_resolved(evaluate(s.clone(), ctx.clone(), arg)?)
156 } else {154 } else {
157 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {155 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {
158 context: ctx.clone(),156 ctx: ctx.clone(),
159 expr: arg.clone(),157 expr: arg.clone(),
160 })))158 })))
161 },159 },
178176
179 fn unnamed_iter(177 fn unnamed_iter(
180 &self,178 &self,
179 _s: State,
181 _ctx: Context,180 _ctx: Context,
182 _tailstrict: bool,181 _tailstrict: bool,
183 _handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,182 _handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,
187186
188 fn named_iter(187 fn named_iter(
189 &self,188 &self,
189 s: State,
190 ctx: Context,190 ctx: Context,
191 tailstrict: bool,191 tailstrict: bool,
192 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,192 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,
193 ) -> Result<()> {193 ) -> Result<()> {
194 for (name, val) in self.iter() {194 for (name, val) in self.iter() {
195 handler(name, val.evaluate_arg(ctx.clone(), tailstrict)?)?;195 handler(name, val.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?)?;
196 }196 }
197 Ok(())197 Ok(())
198 }198 }
211211
212 fn unnamed_iter(212 fn unnamed_iter(
213 &self,213 &self,
214 _s: State,
214 _ctx: Context,215 _ctx: Context,
215 _tailstrict: bool,216 _tailstrict: bool,
216 _handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,217 _handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,
220221
221 fn named_iter(222 fn named_iter(
222 &self,223 &self,
224 s: State,
223 ctx: Context,225 ctx: Context,
224 tailstrict: bool,226 tailstrict: bool,
225 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,227 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,
226 ) -> Result<()> {228 ) -> Result<()> {
227 for (name, value) in self.iter() {229 for (name, value) in self.iter() {
228 handler(name, value.evaluate_arg(ctx.clone(), tailstrict)?)?;230 handler(
231 name,
232 value.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?,
233 )?;
229 }234 }
230 Ok(())235 Ok(())
244249
245 fn unnamed_iter(250 fn unnamed_iter(
246 &self,251 &self,
252 s: State,
247 ctx: Context,253 ctx: Context,
248 tailstrict: bool,254 tailstrict: bool,
249 handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,255 handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,
250 ) -> Result<()> {256 ) -> Result<()> {
251 for (i, arg) in self.iter().enumerate() {257 for (i, arg) in self.iter().enumerate() {
252 handler(i, arg.evaluate_arg(ctx.clone(), tailstrict)?)?;258 handler(i, arg.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?)?;
253 }259 }
254 Ok(())260 Ok(())
255 }261 }
256262
257 fn named_iter(263 fn named_iter(
258 &self,264 &self,
265 _s: State,
259 _ctx: Context,266 _ctx: Context,
260 _tailstrict: bool,267 _tailstrict: bool,
261 _handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,268 _handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,
272279
273 fn unnamed_iter(280 fn unnamed_iter(
274 &self,281 &self,
282 s: State,
275 ctx: Context,283 ctx: Context,
276 tailstrict: bool,284 tailstrict: bool,
277 handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,285 handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,
278 ) -> Result<()> {286 ) -> Result<()> {
279 (*self).unnamed_iter(ctx, tailstrict, handler)287 (*self).unnamed_iter(s, ctx, tailstrict, handler)
280 }288 }
281289
282 fn named_iter(290 fn named_iter(
283 &self,291 &self,
292 s: State,
284 ctx: Context,293 ctx: Context,
285 tailstrict: bool,294 tailstrict: bool,
286 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,295 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,
287 ) -> Result<()> {296 ) -> Result<()> {
288 (*self).named_iter(ctx, tailstrict, handler)297 (*self).named_iter(s, ctx, tailstrict, handler)
289 }298 }
290299
291 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {300 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {
302/// * `args`: passed function arguments311/// * `args`: passed function arguments
303/// * `tailstrict`: if set to `true` function arguments are eagerly executed, otherwise - lazily312/// * `tailstrict`: if set to `true` function arguments are eagerly executed, otherwise - lazily
304pub fn parse_function_call(313pub fn parse_function_call(
314 s: State,
305 ctx: Context,315 ctx: Context,
306 body_ctx: Context,316 body_ctx: Context,
307 params: &ParamsDesc,317 params: &ParamsDesc,
315325
316 let mut filled_args = 0;326 let mut filled_args = 0;
317327
318 args.unnamed_iter(ctx.clone(), tailstrict, &mut |id, arg| {328 args.unnamed_iter(s.clone(), ctx.clone(), tailstrict, &mut |id, arg| {
319 let name = params[id].0.clone();329 let name = params[id].0.clone();
320 passed_args.insert(name, arg);330 passed_args.insert(name, arg);
321 filled_args += 1;331 filled_args += 1;
322 Ok(())332 Ok(())
323 })?;333 })?;
324334
325 args.named_iter(ctx, tailstrict, &mut |name, value| {335 args.named_iter(s, ctx, tailstrict, &mut |name, value| {
326 // FIXME: O(n) for arg existence check336 // FIXME: O(n) for arg existence check
327 if !params.iter().any(|p| &p.0 == name) {337 if !params.iter().any(|p| &p.0 == name) {
328 throw!(UnknownFunctionParameter((name as &str).to_owned()));338 throw!(UnknownFunctionParameter((name as &str).to_owned()));
337 if filled_args < params.len() {347 if filled_args < params.len() {
338 // Some args are unset, but maybe we have defaults for them348 // Some args are unset, but maybe we have defaults for them
339 // Default values should be created in newly created context349 // Default values should be created in newly created context
340 let future_context = Context::new_future();350 let fctx = Context::new_future();
341 let mut defaults = GcHashMap::with_capacity(params.len() - filled_args);351 let mut defaults = GcHashMap::with_capacity(params.len() - filled_args);
342352
343 for param in params.iter().filter(|p| p.1.is_some()) {353 for param in params.iter().filter(|p| p.1.is_some()) {
344 if passed_args.contains_key(&param.0.clone()) {354 if passed_args.contains_key(&param.0.clone()) {
345 continue;355 continue;
346 }356 }
347 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {357 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {
348 future_context: future_context.clone(),358 ctx: fctx.clone(),
349 name: param.0.clone(),359 name: param.0.clone(),
350 value: param.1.clone().unwrap(),360 value: param.1.clone().unwrap(),
351 })));361 })));
352362
353 defaults.insert(363 defaults.insert(
354 param.0.clone(),364 param.0.clone(),
355 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {365 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {
356 future_context: future_context.clone(),366 ctx: fctx.clone(),
357 name: param.0.clone(),367 name: param.0.clone(),
358 value: param.1.clone().unwrap(),368 value: param.1.clone().unwrap(),
359 }))),369 }))),
380 Ok(body_ctx390 Ok(body_ctx
381 .extend(passed_args, None, None, None)391 .extend(passed_args, None, None, None)
382 .extend_bound(defaults)392 .extend_bound(defaults)
383 .into_future(future_context))393 .into_future(fctx))
384 } else {394 } else {
385 let body_ctx = body_ctx.extend(passed_args, None, None, None);395 let body_ctx = body_ctx.extend(passed_args, None, None, None);
386 Ok(body_ctx)396 Ok(body_ctx)
399pub trait Builtin: Trace {409pub trait Builtin: Trace {
400 fn name(&self) -> &str;410 fn name(&self) -> &str;
401 fn params(&self) -> &[BuiltinParam];411 fn params(&self) -> &[BuiltinParam];
402 fn call(&self, context: Context, loc: CallLocation, args: &dyn ArgsLike) -> Result<Val>;412 fn call(&self, s: State, ctx: Context, loc: CallLocation, args: &dyn ArgsLike) -> Result<Val>;
403}413}
404414
405pub trait StaticBuiltin: Builtin + Send + Sync415pub trait StaticBuiltin: Builtin + Send + Sync
418/// * `args`: passed function arguments428/// * `args`: passed function arguments
419/// * `tailstrict`: if set to `true` function arguments are eagerly executed, otherwise - lazily429/// * `tailstrict`: if set to `true` function arguments are eagerly executed, otherwise - lazily
420pub fn parse_builtin_call(430pub fn parse_builtin_call(
431 s: State,
421 ctx: Context,432 ctx: Context,
422 params: &[BuiltinParam],433 params: &[BuiltinParam],
423 args: &dyn ArgsLike,434 args: &dyn ArgsLike,
430441
431 let mut filled_args = 0;442 let mut filled_args = 0;
432443
433 args.unnamed_iter(ctx.clone(), tailstrict, &mut |id, arg| {444 args.unnamed_iter(s.clone(), ctx.clone(), tailstrict, &mut |id, arg| {
434 let name = params[id].name.clone();445 let name = params[id].name.clone();
435 passed_args.insert(name, arg);446 passed_args.insert(name, arg);
436 filled_args += 1;447 filled_args += 1;
437 Ok(())448 Ok(())
438 })?;449 })?;
439450
440 args.named_iter(ctx, tailstrict, &mut |name, arg| {451 args.named_iter(s, ctx, tailstrict, &mut |name, arg| {
441 // FIXME: O(n) for arg existence check452 // FIXME: O(n) for arg existence check
442 let p = params453 let p = params
443 .iter()454 .iter()
480/// Creates Context, which has all argument default values applied491/// Creates Context, which has all argument default values applied
481/// and with unbound values causing error to be returned492/// and with unbound values causing error to be returned
482pub fn parse_default_function_call(body_ctx: Context, params: &ParamsDesc) -> Context {493pub fn parse_default_function_call(body_ctx: Context, params: &ParamsDesc) -> Context {
483 let ctx = Context::new_future();494 let fctx = Context::new_future();
484495
485 let mut bindings = GcHashMap::new();496 let mut bindings = GcHashMap::new();
486497
487 #[derive(Trace)]498 #[derive(Trace)]
488 struct DependsOnUnbound(IStr);499 struct DependsOnUnbound(IStr);
489 impl LazyValValue for DependsOnUnbound {500 impl LazyValValue for DependsOnUnbound {
490 fn get(self: Box<Self>) -> Result<Val> {501 fn get(self: Box<Self>, _: State) -> Result<Val> {
491 Err(FunctionParameterNotBoundInCall(self.0.clone()).into())502 Err(FunctionParameterNotBoundInCall(self.0.clone()).into())
492 }503 }
493 }504 }
497 bindings.insert(508 bindings.insert(
498 param.0.clone(),509 param.0.clone(),
499 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {510 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {
500 future_context: ctx.clone(),511 ctx: fctx.clone(),
501 name: param.0.clone(),512 name: param.0.clone(),
502 value: v.clone(),513 value: v.clone(),
503 }))),514 }))),
510 }521 }
511 }522 }
512523
513 body_ctx.extend(bindings, None, None, None).into_future(ctx)524 body_ctx
525 .extend(bindings, None, None, None)
526 .into_future(fctx)
514}527}
515528
modifiedcrates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth
1use std::convert::{TryFrom, TryInto};1use jrsonnet_types::ComplexValType;
2
3use serde_json::{Map, Number, Value};2use serde_json::{Map, Number, Value};
43
5use crate::{4use crate::{
6 error::{Error::*, LocError, Result},5 error::{Error::*, Result},
7 throw, ObjValueBuilder, Val,6 throw,
7 typed::Typed,
8 ObjValueBuilder, State, Val,
8};9};
910
10impl TryFrom<&Val> for Value {11impl Typed for Value {
12 const TYPE: &'static ComplexValType = &ComplexValType::Any;
13
14 fn into_untyped(value: Self, s: State) -> Result<Val> {
15 Ok(match value {
16 Value::Null => Val::Null,
17 Value::Bool(v) => Val::Bool(v),
18 Value::Number(n) => Val::Num(n.as_f64().ok_or_else(|| {
19 RuntimeError(format!("json number can't be represented as jsonnet: {}", n).into())
20 })?),
21 Value::String(s) => Val::Str((&s as &str).into()),
22 Value::Array(a) => {
23 let mut out: Vec<Val> = Vec::with_capacity(a.len());
24 for v in a {
25 out.push(Self::into_untyped(v, s.clone())?);
26 }
27 Val::Arr(out.into())
28 }
29 Value::Object(o) => {
11 type Error = LocError;30 let mut builder = ObjValueBuilder::with_capacity(o.len());
31 for (k, v) in o {
32 builder
33 .member((&k as &str).into())
34 .value(s.clone(), Self::into_untyped(v, s.clone())?)?;
35 }
36 Val::Obj(builder.build())
37 }
38 })
39 }
40
12 fn try_from(v: &Val) -> Result<Self> {41 fn from_untyped(value: Val, s: State) -> Result<Self> {
13 Ok(match v {42 Ok(match value {
14 Val::Bool(b) => Self::Bool(*b),43 Val::Bool(b) => Self::Bool(b),
15 Val::Null => Self::Null,44 Val::Null => Self::Null,
16 Val::Str(s) => Self::String((s as &str).into()),45 Val::Str(s) => Self::String((&s as &str).into()),
17 Val::Num(n) => Self::Number(if n.fract() <= f64::EPSILON {46 Val::Num(n) => Self::Number(if n.fract() <= f64::EPSILON {
18 (*n as i64).into()47 (n as i64).into()
19 } else {48 } else {
20 Number::from_f64(*n).expect("jsonnet numbers can't be infinite or NaN")49 Number::from_f64(n).expect("jsonnet numbers can't be infinite or NaN")
21 }),50 }),
22 Val::Arr(a) => {51 Val::Arr(a) => {
23 let mut out = Vec::with_capacity(a.len());52 let mut out = Vec::with_capacity(a.len());
24 for item in a.iter() {53 for item in a.iter(s.clone()) {
25 out.push(item?.try_into()?);54 out.push(Self::from_untyped(item?, s.clone())?);
26 }55 }
27 Self::Array(out)56 Self::Array(out)
28 }57 }
34 ) {63 ) {
35 out.insert(64 out.insert(
36 (&key as &str).into(),65 (&key as &str).into(),
66 Self::from_untyped(
37 o.get(key)?67 o.get(s.clone(), key)?
38 .expect("key is present in fields, so value should exist")68 .expect("key is present in fields, so value should exist"),
39 .try_into()?,69 s.clone(),
70 )?,
40 );71 );
41 }72 }
42 Self::Object(out)73 Self::Object(out)
43 }74 }
44 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),75 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),
45 })76 })
46 }77 }
47}78}
48impl TryFrom<Val> for Value {
49 type Error = LocError;
50
51 fn try_from(value: Val) -> Result<Self, Self::Error> {
52 <Self as TryFrom<&Val>>::try_from(&value)
53 }
54}
55
56impl TryFrom<&Value> for Val {
57 type Error = LocError;
58 fn try_from(v: &Value) -> Result<Self> {
59 Ok(match v {
60 Value::Null => Self::Null,
61 Value::Bool(v) => Self::Bool(*v),
62 Value::Number(n) => Self::Num(n.as_f64().ok_or_else(|| {
63 RuntimeError(format!("json number can't be represented as jsonnet: {}", n).into())
64 })?),
65 Value::String(s) => Self::Str((s as &str).into()),
66 Value::Array(a) => {
67 let mut out: Vec<Self> = Vec::with_capacity(a.len());
68 for v in a {
69 out.push(v.try_into()?);
70 }
71 Self::Arr(out.into())
72 }
73 Value::Object(o) => {
74 let mut builder = ObjValueBuilder::with_capacity(o.len());
75 for (k, v) in o {
76 builder.member((k as &str).into()).value(v.try_into()?)?;
77 }
78 Self::Obj(builder.build())
79 }
80 })
81 }
82}
83impl TryFrom<Value> for Val {
84 type Error = LocError;
85
86 fn try_from(value: Value) -> Result<Self, Self::Error> {
87 <Self as TryFrom<&Value>>::try_from(&value)
88 }
89}
9079
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
49pub trait Bindable: Trace + 'static {49pub trait Bindable: Trace + 'static {
50 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal>;50 fn bind(
51 &self,
52 s: State,
53 this: Option<ObjValue>,
54 super_obj: Option<ObjValue>,
55 ) -> Result<LazyVal>;
51}56}
5257
64impl LazyBinding {69impl LazyBinding {
65 pub fn evaluate(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {70 pub fn evaluate(
71 &self,
72 s: State,
73 this: Option<ObjValue>,
74 super_obj: Option<ObjValue>,
75 ) -> Result<LazyVal> {
66 match self {76 match self {
67 Self::Bindable(v) => v.bind(this, super_obj),77 Self::Bindable(v) => v.bind(s, this, super_obj),
68 Self::Bound(v) => Ok(v.clone()),78 Self::Bound(v) => Ok(v.clone()),
69 }79 }
70 }80 }
173 settings: RefCell<EvaluationSettings>,183 settings: RefCell<EvaluationSettings>,
174}184}
175
176thread_local! {
177 /// Contains the state for a currently executed file.
178 /// Global state is fine here.
179 pub(crate) static EVAL_STATE: RefCell<Option<EvaluationState>> = RefCell::new(None)
180}
181
182pub(crate) fn with_state<T>(f: impl FnOnce(&EvaluationState) -> T) -> T {
183 EVAL_STATE.with(|s| {
184 f(s.borrow().as_ref().expect(
185 "missing evaluation state, some functions should be called inside of run_in_state call",
186 ))
187 })
188}
189pub fn push_frame<T>(
190 e: CallLocation,
191 frame_desc: impl FnOnce() -> String,
192 f: impl FnOnce() -> Result<T>,
193) -> Result<T> {
194 with_state(|s| s.push(e, frame_desc, f))
195}
196
197#[allow(dead_code)]
198pub fn push_val_frame(
199 e: &ExprLocation,
200 frame_desc: impl FnOnce() -> String,
201 f: impl FnOnce() -> Result<Val>,
202) -> Result<Val> {
203 with_state(|s| s.push_val(e, frame_desc, f))
204}
205#[allow(dead_code)]
206pub fn push_description_frame<T>(
207 frame_desc: impl FnOnce() -> String,
208 f: impl FnOnce() -> Result<T>,
209) -> Result<T> {
210 with_state(|s| s.push_description(frame_desc, f))
211}
212185
213/// Maintains stack trace and import resolution186/// Maintains stack trace and import resolution
214#[derive(Default, Clone)]187#[derive(Default, Clone)]
215pub struct EvaluationState(Rc<EvaluationStateInternals>);188pub struct State(Rc<EvaluationStateInternals>);
216189
217impl EvaluationState {190impl State {
218 /// Parses and adds file as loaded191 /// Parses and adds file as loaded
219 pub fn add_file(&self, path: Rc<Path>, source_code: IStr) -> Result<LocExpr> {192 pub fn add_file(&self, path: Rc<Path>, source_code: IStr) -> Result<LocExpr> {
220 let parsed = parse(193 let parsed = parse(
317 }290 }
318 value.parsed.clone()291 value.parsed.clone()
319 };292 };
320 let value = evaluate(self.create_default_context(), &expr)?;293 let value = evaluate(self.clone(), self.create_default_context(), &expr)?;
321 {294 {
322 self.data_mut()295 self.data_mut()
323 .files296 .files
333 pub fn with_stdlib(&self) -> &Self {306 pub fn with_stdlib(&self) -> &Self {
334 use jrsonnet_stdlib::STDLIB_STR;307 use jrsonnet_stdlib::STDLIB_STR;
335 let std_path: Rc<Path> = PathBuf::from("std.jsonnet").into();308 let std_path: Rc<Path> = PathBuf::from("std.jsonnet").into();
336 self.run_in_state(|| {309
337 self.add_parsed_file(310 self.add_parsed_file(
338 std_path.clone(),311 std_path.clone(),
339 STDLIB_STR.to_owned().into(),312 STDLIB_STR.to_owned().into(),
342 .unwrap();315 .unwrap();
343 let val = self.evaluate_loaded_file_raw(&std_path).unwrap();316 let val = self.evaluate_loaded_file_raw(&std_path).unwrap();
344 self.settings_mut().globals.insert("std".into(), val);317 self.settings_mut().globals.insert("std".into(), val);
345 });
346 self318 self
347 }319 }
348320
459 result431 result
460 }432 }
461
462 /// Runs passed function in state (required if function needs to modify stack trace)
463 pub fn run_in_state<T>(&self, f: impl FnOnce() -> T) -> T {
464 EVAL_STATE.with(|v| {
465 let has_state = v.borrow().is_some();
466 if !has_state {
467 v.borrow_mut().replace(self.clone());
468 }
469 let result = f();
470 if !has_state {
471 v.borrow_mut().take();
472 }
473 result
474 })
475 }
476 pub fn run_in_state_with_breakpoint(
477 &self,
478 bp: Rc<Breakpoint>,
479 f: impl FnOnce() -> Result<()>,
480 ) -> Result<()> {
481 {
482 let mut data = self.data_mut();
483 data.breakpoints.0.push(bp);
484 }
485
486 let result = self.run_in_state(f);
487
488 {
489 let mut data = self.data_mut();
490 data.breakpoints.0.pop();
491 }
492
493 result
494 }
495433
496 pub fn stringify_err(&self, e: &LocError) -> String {434 pub fn stringify_err(&self, e: &LocError) -> String {
497 let mut out = String::new();435 let mut out = String::new();
503 }441 }
504442
505 pub fn manifest(&self, val: Val) -> Result<IStr> {443 pub fn manifest(&self, val: Val) -> Result<IStr> {
506 self.run_in_state(|| {444 self.push_description(
507 push_description_frame(
508 || "manifestification".to_string(),445 || "manifestification".to_string(),
509 || val.manifest(&self.manifest_format()),446 || val.manifest(self.clone(), &self.manifest_format()),
510 )
511 })447 )
512 }448 }
513 pub fn manifest_multi(&self, val: Val) -> Result<Vec<(IStr, IStr)>> {449 pub fn manifest_multi(&self, val: Val) -> Result<Vec<(IStr, IStr)>> {
514 self.run_in_state(|| val.manifest_multi(&self.manifest_format()))450 val.manifest_multi(self.clone(), &self.manifest_format())
515 }451 }
516 pub fn manifest_stream(&self, val: Val) -> Result<Vec<IStr>> {452 pub fn manifest_stream(&self, val: Val) -> Result<Vec<IStr>> {
517 self.run_in_state(|| val.manifest_stream(&self.manifest_format()))453 val.manifest_stream(self.clone(), &self.manifest_format())
518 }454 }
519455
520 /// If passed value is function then call with set TLA456 /// If passed value is function then call with set TLA
521 pub fn with_tla(&self, val: Val) -> Result<Val> {457 pub fn with_tla(&self, val: Val) -> Result<Val> {
522 self.run_in_state(|| {
523 Ok(match val {458 Ok(match val {
524 Val::Func(func) => push_description_frame(459 Val::Func(func) => self.push_description(
525 || "during TLA call".to_owned(),460 || "during TLA call".to_owned(),
526 || {461 || {
527 func.evaluate(462 func.evaluate(
463 self.clone(),
528 self.create_default_context(),464 self.create_default_context(),
529 CallLocation::native(),465 CallLocation::native(),
530 &self.settings().tla_vars,466 &self.settings().tla_vars,
534 )?,470 )?,
535 v => v,471 v => v,
536 })472 })
537 })
538 }473 }
539}474}
540475
541/// Internals476/// Internals
542impl EvaluationState {477impl State {
543 fn data(&self) -> Ref<EvaluationData> {478 fn data(&self) -> Ref<EvaluationData> {
544 self.0.data.borrow()479 self.0.data.borrow()
545 }480 }
555}490}
556491
557/// Raw methods evaluate passed values but don't perform TLA execution492/// Raw methods evaluate passed values but don't perform TLA execution
558impl EvaluationState {493impl State {
559 pub fn evaluate_file_raw(&self, name: &Path) -> Result<Val> {494 pub fn evaluate_file_raw(&self, name: &Path) -> Result<Val> {
560 self.run_in_state(|| self.import_file(&std::env::current_dir().expect("cwd"), name))495 self.import_file(&std::env::current_dir().expect("cwd"), name)
561 }496 }
562 pub fn evaluate_file_raw_nocwd(&self, name: &Path) -> Result<Val> {497 pub fn evaluate_file_raw_nocwd(&self, name: &Path) -> Result<Val> {
563 self.run_in_state(|| self.import_file(&PathBuf::from("."), name))498 self.import_file(&PathBuf::from("."), name)
564 }499 }
565 /// Parses and evaluates the given snippet500 /// Parses and evaluates the given snippet
566 pub fn evaluate_snippet_raw(&self, source: Rc<Path>, code: IStr) -> Result<Val> {501 pub fn evaluate_snippet_raw(&self, source: Rc<Path>, code: IStr) -> Result<Val> {
580 }515 }
581 /// Evaluates the parsed expression516 /// Evaluates the parsed expression
582 pub fn evaluate_expr_raw(&self, code: LocExpr) -> Result<Val> {517 pub fn evaluate_expr_raw(&self, code: LocExpr) -> Result<Val> {
583 self.run_in_state(|| evaluate(self.create_default_context(), &code))518 evaluate(self.clone(), self.create_default_context(), &code)
584 }519 }
585}520}
586521
587/// Settings utilities522/// Settings utilities
588impl EvaluationState {523impl State {
589 pub fn add_ext_var(&self, name: IStr, value: Val) {524 pub fn add_ext_var(&self, name: IStr, value: Val) {
590 self.settings_mut().ext_vars.insert(name, value);525 self.settings_mut().ext_vars.insert(name, value);
591 }526 }
712 gc::TraceBox,647 gc::TraceBox,
713 native::NativeCallbackHandler,648 native::NativeCallbackHandler,
714 val::primitive_equals,649 val::primitive_equals,
715 EvaluationState,650 State,
716 };651 };
717652
718 #[test]653 #[test]
719 #[should_panic]654 #[should_panic]
720 fn eval_state_stacktrace() {655 fn eval_state_stacktrace() {
721 let state = EvaluationState::default();656 let state = State::default();
722 state.run_in_state(|| {
723 state657 state
724 .push(658 .push(
725 CallLocation::new(&ExprLocation(PathBuf::from("test1.jsonnet").into(), 10, 20)),659 CallLocation::new(&ExprLocation(PathBuf::from("test1.jsonnet").into(), 10, 20)),
738 },672 },
739 )673 )
740 .unwrap();674 .unwrap();
741 });
742 }675 }
743676
744 #[test]677 #[test]
745 fn eval_state_standard() {678 fn eval_state_standard() {
746 let state = EvaluationState::default();679 let state = State::default();
747 state.with_stdlib();680 state.with_stdlib();
748 assert!(primitive_equals(681 assert!(primitive_equals(
749 &state682 &state
759692
760 macro_rules! eval {693 macro_rules! eval {
761 ($str: expr) => {{694 ($str: expr) => {{
762 let evaluator = EvaluationState::default();695 let evaluator = State::default();
763 evaluator.with_stdlib();696 evaluator.with_stdlib();
764 evaluator.run_in_state(|| {697 evaluator
765 evaluator
766 .evaluate_snippet_raw(PathBuf::from("raw.jsonnet").into(), $str.into())698 .evaluate_snippet_raw(PathBuf::from("raw.jsonnet").into(), $str.into())
767 .unwrap()699 .unwrap()
768 })
769 }};700 }};
770 }701 }
771 macro_rules! eval_json {702 macro_rules! eval_json {
772 ($str: expr) => {{703 ($str: expr) => {{
773 let evaluator = EvaluationState::default();704 let evaluator = State::default();
774 evaluator.with_stdlib();705 evaluator.with_stdlib();
775 evaluator.run_in_state(|| {706 evaluator
776 evaluator
777 .evaluate_snippet_raw(PathBuf::from("raw.jsonnet").into(), $str.into())707 .evaluate_snippet_raw(PathBuf::from("raw.jsonnet").into(), $str.into())
778 .unwrap()708 .unwrap()
779 .to_json(0)709 .to_json(0)
780 .unwrap()710 .unwrap()
781 .replace("\n", "")711 .replace("\n", "")
782 })
783 }};712 }};
784 }713 }
785714
1143 #[test]1072 #[test]
1144 fn native_ext() -> crate::error::Result<()> {1073 fn native_ext() -> crate::error::Result<()> {
1145 use super::native::NativeCallback;1074 use super::native::NativeCallback;
1146 let evaluator = EvaluationState::default();1075 let evaluator = State::default();
11471076
1148 evaluator.with_stdlib();1077 evaluator.with_stdlib();
11491078
1178 TraceBox(Box::new(NativeAdd)),1107 TraceBox(Box::new(NativeAdd)),
1179 )))),1108 )))),
1180 );1109 );
1110 dbg!(evaluator.settings().ext_natives.keys().collect::<Vec<_>>());
1181 evaluator.evaluate_snippet_raw(1111 evaluator.evaluate_snippet_raw(
1182 PathBuf::from("native_caller.jsonnet").into(),1112 PathBuf::from("native_caller.jsonnet").into(),
1183 "std.assertEqual(std.native(\"native_add\")(1, 2), 3)".into(),1113 "std.assertEqual(std.native(\"native_add\")(1, 2), 3)".into(),
1184 )?;1114 )?;
1115 dbg!(evaluator.settings().ext_natives.keys().collect::<Vec<_>>());
1185 Ok(())1116 Ok(())
1186 }1117 }
11871118
12501181
1251 #[test]1182 #[test]
1252 fn issue_23() {1183 fn issue_23() {
1253 let state = EvaluationState::default();1184 let state = State::default();
1254 state.set_import_resolver(Box::new(TestImportResolver(r#"import "/test""#.into())));1185 state.set_import_resolver(Box::new(TestImportResolver(r#"import "/test""#.into())));
1255 let _ = state.evaluate_file_raw(&PathBuf::from("/test"));1186 let _ = state.evaluate_file_raw(&PathBuf::from("/test"));
1256 }1187 }
12571188
1258 #[test]1189 #[test]
1259 fn issue_40() {1190 fn issue_40() {
1260 let state = EvaluationState::default();1191 let state = State::default();
1261 state.with_stdlib();1192 state.with_stdlib();
12621193
1263 let error = state1194 let error = state
1306 mod derive_typed {1237 mod derive_typed {
1307 use std::path::PathBuf;1238 use std::path::PathBuf;
13081239
1309 use crate::{typed::Typed, EvaluationState};1240 use crate::{typed::Typed, State};
13101241
1311 #[derive(PartialEq, Debug, Typed)]1242 #[derive(PartialEq, Debug, Typed)]
1312 struct MyTyped {1243 struct MyTyped {
13171248
1318 #[test]1249 #[test]
1319 fn test() {1250 fn test() {
1320 let es = EvaluationState::default();1251 let es = State::default();
1321 let val = eval!("{a: 14, b: 'Hello, world!'}");1252 let val = eval!("{a: 14, b: 'Hello, world!'}");
1322 let typed = es.run_in_state(|| MyTyped::try_from(val).unwrap());1253 let typed = MyTyped::try_from(val).unwrap();
13231254
1324 assert_eq!(1255 assert_eq!(
1325 typed,1256 typed,
1331 es.settings_mut().globals.insert(1262 es.settings_mut()
1263 .globals
1332 "mytyped".into(),1264 .insert("mytyped".into(), typed.try_into().unwrap());
1333 es.run_in_state(|| typed.try_into()).unwrap(),
1334 );
13351265
1336 let v = es1266 let v = es
modifiedcrates/jrsonnet-evaluator/src/native.rsdiffbeforeafterboth
8 error::Result,8 error::Result,
9 function::{parse_builtin_call, ArgsLike, Builtin, BuiltinParam, CallLocation},9 function::{parse_builtin_call, ArgsLike, Builtin, BuiltinParam, CallLocation},
10 gc::TraceBox,10 gc::TraceBox,
11 Context, Val,11 Context, State, Val,
12};12};
1313
14#[derive(Trace)]14#[derive(Trace)]
34 &self.params34 &self.params
35 }35 }
3636
37 fn call(&self, context: Context, loc: CallLocation, args: &dyn ArgsLike) -> Result<Val> {37 fn call(&self, s: State, ctx: Context, loc: CallLocation, args: &dyn ArgsLike) -> Result<Val> {
38 let args = parse_builtin_call(context, &self.params, args, true)?;38 let args = parse_builtin_call(s.clone(), ctx, &self.params, args, true)?;
39 let mut out_args = Vec::with_capacity(self.params.len());39 let mut out_args = Vec::with_capacity(self.params.len());
40 for p in self.params.iter() {40 for p in self.params.iter() {
41 out_args.push(args[&p.name].evaluate()?);41 out_args.push(args[&p.name].evaluate(s.clone())?);
42 }42 }
43 self.handler.call(loc.0.map(|l| l.0.clone()), &out_args)43 self.handler.call(s, loc.0.map(|l| l.0.clone()), &out_args)
44 }44 }
45}45}
4646
47pub trait NativeCallbackHandler: Trace {47pub trait NativeCallbackHandler: Trace {
48 fn call(&self, from: Option<Rc<Path>>, args: &[Val]) -> Result<Val>;48 fn call(&self, s: State, from: Option<Rc<Path>>, args: &[Val]) -> Result<Val>;
49}49}
5050
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 push_frame, throw, weak_ptr_eq, weak_raw, Bindable, LazyBinding, LazyVal, Result, Val,18 throw, weak_ptr_eq, weak_raw, Bindable, LazyBinding, LazyVal, Result, State, Val,
19};19};
2020
21#[cfg(not(feature = "exp-preserve-order"))]21#[cfg(not(feature = "exp-preserve-order"))]
99}99}
100100
101pub trait ObjectAssertion: Trace {101pub trait ObjectAssertion: Trace {
102 fn run(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<()>;102 fn run(&self, s: State, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<()>;
103}103}
104104
105// Field => This105// Field => This
360 .unwrap_or(false)360 .unwrap_or(false)
361 }361 }
362362
363 pub fn get(&self, key: IStr) -> Result<Option<Val>> {363 pub fn get(&self, s: State, key: IStr) -> Result<Option<Val>> {
364 self.run_assertions()?;364 self.run_assertions(s.clone())?;
365 self.get_raw(key, self.0.this_obj.as_ref())365 self.get_raw(s, key, self.0.this_obj.as_ref())
366 }366 }
367367
368 // pub fn extend_with(self, key: )368 // pub fn extend_with(self, key: )
369369
370 fn get_raw(&self, key: IStr, real_this: Option<&Self>) -> Result<Option<Val>> {370 fn get_raw(&self, s: State, key: IStr, real_this: Option<&Self>) -> Result<Option<Val>> {
371 let real_this = real_this.unwrap_or(self);371 let real_this = real_this.unwrap_or(self);
372 let cache_key = (key.clone(), WeakObjValue(real_this.0.downgrade()));372 let cache_key = (key.clone(), WeakObjValue(real_this.0.downgrade()));
373373
384 .borrow_mut()384 .borrow_mut()
385 .insert(cache_key.clone(), CacheValue::Pending);385 .insert(cache_key.clone(), CacheValue::Pending);
386 let value = match (self.0.this_entries.get(&key), &self.0.super_obj) {386 let value = match (self.0.this_entries.get(&key), &self.0.super_obj) {
387 (Some(k), None) => Ok(Some(self.evaluate_this(k, real_this)?)),387 (Some(k), None) => Ok(Some(self.evaluate_this(s, k, real_this)?)),
388 (Some(k), Some(s)) => {388 (Some(k), Some(super_obj)) => {
389 let our = self.evaluate_this(k, real_this)?;389 let our = self.evaluate_this(s.clone(), k, real_this)?;
390 if k.add {390 if k.add {
391 super_obj
391 s.get_raw(key, Some(real_this))?392 .get_raw(s.clone(), key, Some(real_this))?
392 .map_or(Ok(Some(our.clone())), |v| {393 .map_or(Ok(Some(our.clone())), |v| {
393 Ok(Some(evaluate_add_op(&v, &our)?))394 Ok(Some(evaluate_add_op(s.clone(), &v, &our)?))
394 })395 })
395 } else {396 } else {
396 Ok(Some(our))397 Ok(Some(our))
397 }398 }
398 }399 }
399 (None, Some(s)) => s.get_raw(key, Some(real_this)),400 (None, Some(super_obj)) => super_obj.get_raw(s, key, Some(real_this)),
400 (None, None) => Ok(None),401 (None, None) => Ok(None),
401 };402 };
402 let value = match value {403 let value = match value {
418 );419 );
419 Ok(value)420 Ok(value)
420 }421 }
421 fn evaluate_this(&self, v: &ObjMember, real_this: &Self) -> Result<Val> {422 fn evaluate_this(&self, s: State, v: &ObjMember, real_this: &Self) -> Result<Val> {
422 v.invoke423 v.invoke
423 .evaluate(Some(real_this.clone()), self.0.super_obj.clone())?424 .evaluate(s.clone(), Some(real_this.clone()), self.0.super_obj.clone())?
424 .evaluate()425 .evaluate(s)
425 }426 }
426427
427 fn run_assertions_raw(&self, real_this: &Self) -> Result<()> {428 fn run_assertions_raw(&self, s: State, real_this: &Self) -> Result<()> {
428 if self.0.assertions_ran.borrow_mut().insert(real_this.clone()) {429 if self.0.assertions_ran.borrow_mut().insert(real_this.clone()) {
429 for assertion in self.0.assertions.iter() {430 for assertion in self.0.assertions.iter() {
430 if let Err(e) = assertion.run(Some(real_this.clone()), self.0.super_obj.clone()) {431 if let Err(e) =
432 assertion.run(s.clone(), Some(real_this.clone()), self.0.super_obj.clone())
433 {
431 self.0.assertions_ran.borrow_mut().remove(real_this);434 self.0.assertions_ran.borrow_mut().remove(real_this);
432 return Err(e);435 return Err(e);
433 }436 }
434 }437 }
435 if let Some(super_obj) = &self.0.super_obj {438 if let Some(super_obj) = &self.0.super_obj {
436 super_obj.run_assertions_raw(real_this)?;439 super_obj.run_assertions_raw(s, real_this)?;
437 }440 }
438 }441 }
439 Ok(())442 Ok(())
440 }443 }
441 pub fn run_assertions(&self) -> Result<()> {444 pub fn run_assertions(&self, s: State) -> Result<()> {
442 self.run_assertions_raw(self)445 self.run_assertions_raw(s, self)
443 }446 }
444447
445 pub fn ptr_eq(a: &Self, b: &Self) -> bool {448 pub fn ptr_eq(a: &Self, b: &Self) -> bool {
565568
566pub struct ValueBuilder<'v>(&'v mut ObjValueBuilder);569pub struct ValueBuilder<'v>(&'v mut ObjValueBuilder);
567impl<'v> ObjMemberBuilder<ValueBuilder<'v>> {570impl<'v> ObjMemberBuilder<ValueBuilder<'v>> {
568 pub fn value(self, value: Val) -> Result<()> {571 pub fn value(self, s: State, value: Val) -> Result<()> {
569 self.binding(LazyBinding::Bound(LazyVal::new_resolved(value)))572 self.binding(s, LazyBinding::Bound(LazyVal::new_resolved(value)))
570 }573 }
571 pub fn bindable(self, bindable: TraceBox<dyn Bindable>) -> Result<()> {574 pub fn bindable(self, s: State, bindable: TraceBox<dyn Bindable>) -> Result<()> {
572 self.binding(LazyBinding::Bindable(Cc::new(bindable)))575 self.binding(s, LazyBinding::Bindable(Cc::new(bindable)))
573 }576 }
574 pub fn binding(self, binding: LazyBinding) -> Result<()> {577 pub fn binding(self, s: State, binding: LazyBinding) -> Result<()> {
575 let (receiver, name, member) = self.build_member(binding);578 let (receiver, name, member) = self.build_member(binding);
576 let location = member.location.clone();579 let location = member.location.clone();
577 let old = receiver.0.map.insert(name.clone(), member);580 let old = receiver.0.map.insert(name.clone(), member);
578 if old.is_some() {581 if old.is_some() {
579 push_frame(582 s.push(
580 CallLocation(location.as_ref()),583 CallLocation(location.as_ref()),
581 || format!("field <{}> initializtion", name.clone()),584 || format!("field <{}> initializtion", name.clone()),
582 || throw!(DuplicateFieldName(name.clone())),585 || throw!(DuplicateFieldName(name.clone())),
modifiedcrates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth
44
5pub use location::*;5pub use location::*;
66
7use crate::{error::Error, EvaluationState, LocError};7use crate::{error::Error, LocError, State};
88
9/// The way paths should be displayed9/// The way paths should be displayed
10pub enum PathResolver {10pub enum PathResolver {
39 fn write_trace(39 fn write_trace(
40 &self,40 &self,
41 out: &mut dyn std::fmt::Write,41 out: &mut dyn std::fmt::Write,
42 evaluation_state: &EvaluationState,42 s: &State,
43 error: &LocError,43 error: &LocError,
44 ) -> Result<(), std::fmt::Error>;44 ) -> Result<(), std::fmt::Error>;
45 // fn print_trace(
46 // &self,
47 // evaluation_state: &EvaluationState,
48 // error: &LocError,
49 // ) -> Result<(), std::fmt::Error> {
50 // self.write_trace(&mut std::fmt::stdout(), evaluation_state, error)
51 // }
52}45}
5346
54fn print_code_location(47fn print_code_location(
85 fn write_trace(78 fn write_trace(
86 &self,79 &self,
87 out: &mut dyn std::fmt::Write,80 out: &mut dyn std::fmt::Write,
88 evaluation_state: &EvaluationState,81 s: &State,
89 error: &LocError,82 error: &LocError,
90 ) -> Result<(), std::fmt::Error> {83 ) -> Result<(), std::fmt::Error> {
91 write!(out, "{}", error.error())?;84 write!(out, "{}", error.error())?;
128 if let Some(location) = location {121 if let Some(location) = location {
129 let mut resolved_path = self.resolver.resolve(&location.0);122 let mut resolved_path = self.resolver.resolve(&location.0);
130 // TODO: Process all trace elements first123 // TODO: Process all trace elements first
131 let location = evaluation_state124 let location = s.map_source_locations(&location.0, &[location.1, location.2]);
132 .map_source_locations(&location.0, &[location.1, location.2]);
133 write!(resolved_path, ":").unwrap();125 write!(resolved_path, ":").unwrap();
134 print_code_location(&mut resolved_path, &location[0], &location[1]).unwrap();126 print_code_location(&mut resolved_path, &location[0], &location[1]).unwrap();
170 fn write_trace(162 fn write_trace(
171 &self,163 &self,
172 out: &mut dyn std::fmt::Write,164 out: &mut dyn std::fmt::Write,
173 evaluation_state: &EvaluationState,165 s: &State,
174 error: &LocError,166 error: &LocError,
175 ) -> Result<(), std::fmt::Error> {167 ) -> Result<(), std::fmt::Error> {
176 write!(out, "{}", error.error())?;168 write!(out, "{}", error.error())?;
177 for item in error.trace().0.iter() {169 for item in error.trace().0.iter() {
178 writeln!(out)?;170 writeln!(out)?;
179 let desc = &item.desc;171 let desc = &item.desc;
180 if let Some(source) = &item.location {172 if let Some(source) = &item.location {
181 let start_end =173 let start_end = s.map_source_locations(&source.0, &[source.1, source.2]);
182 evaluation_state.map_source_locations(&source.0, &[source.1, source.2]);
183174
184 write!(175 write!(
185 out,176 out,
207 fn write_trace(198 fn write_trace(
208 &self,199 &self,
209 out: &mut dyn std::fmt::Write,200 out: &mut dyn std::fmt::Write,
210 evaluation_state: &EvaluationState,201 s: &State,
211 error: &LocError,202 error: &LocError,
212 ) -> Result<(), std::fmt::Error> {203 ) -> Result<(), std::fmt::Error> {
213 write!(out, "{}", error.error())?;204 write!(out, "{}", error.error())?;
240 writeln!(out)?;231 writeln!(out)?;
241 let desc = &item.desc;232 let desc = &item.desc;
242 if let Some(source) = &item.location {233 if let Some(source) = &item.location {
243 let start_end =234 let start_end = s.map_source_locations(&source.0, &[source.1, source.2]);
244 evaluation_state.map_source_locations(&source.0, &[source.1, source.2]);
245 self.print_snippet(235 self.print_snippet(
246 out,236 out,
247 &evaluation_state.get_source(&source.0).unwrap(),237 &s.get_source(&source.0).unwrap(),
248 &source.0,238 &source.0,
249 &start_end[0],239 &start_end[0],
250 &start_end[1],240 &start_end[1],
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
1use std::{1use std::{ops::Deref, rc::Rc};
2 convert::{TryFrom, TryInto},
3 ops::Deref,
4 rc::Rc,
5};
62
7use gcmodule::Cc;3use gcmodule::Cc;
10use jrsonnet_types::{ComplexValType, ValType};6use jrsonnet_types::{ComplexValType, ValType};
117
12use crate::{8use crate::{
13 error::{Error::*, LocError, Result},9 error::{Error::*, Result},
14 throw,10 throw,
15 typed::CheckType,11 typed::CheckType,
16 val::{ArrValue, FuncDesc, FuncVal, IndexableVal},12 val::{ArrValue, FuncDesc, FuncVal, IndexableVal},
17 ObjValue, ObjValueBuilder, Val,13 ObjValue, ObjValueBuilder, State, Val,
18};14};
1915
20pub trait TypedObj: Typed {16pub trait TypedObj: Typed {
27 }23 }
28}24}
2925
30pub trait Typed: TryFrom<Val, Error = LocError> + TryInto<Val, Error = LocError> {26pub trait Typed: Sized {
31 const TYPE: &'static ComplexValType;27 const TYPE: &'static ComplexValType;
28 fn into_untyped(typed: Self, s: State) -> Result<Val>;
29 fn from_untyped(untyped: Val, s: State) -> Result<Self>;
32}30}
3331
34macro_rules! impl_int {32macro_rules! impl_int {
35 ($($ty:ty)*) => {$(33 ($($ty:ty)*) => {$(
36 impl Typed for $ty {34 impl Typed for $ty {
37 const TYPE: &'static ComplexValType =35 const TYPE: &'static ComplexValType =
38 &ComplexValType::BoundedNumber(Some(Self::MIN as f64), Some(Self::MAX as f64));36 &ComplexValType::BoundedNumber(Some(Self::MIN as f64), Some(Self::MAX as f64));
39 }
40 impl TryFrom<Val> for $ty {
41 type Error = LocError;
42
43 fn try_from(value: Val) -> Result<Self> {37 fn from_untyped(value: Val, s: State) -> Result<Self> {
44 <Self as Typed>::TYPE.check(&value)?;38 <Self as Typed>::TYPE.check(s, &value)?;
45 match value {39 match value {
46 Val::Num(n) => {40 Val::Num(n) => {
47 if n.trunc() != n {41 if n.trunc() != n {
58 _ => unreachable!(),52 _ => unreachable!(),
59 }53 }
60 }54 }
61 }
62 impl TryFrom<$ty> for Val {
63 type Error = LocError;
64
65 fn try_from(value: $ty) -> Result<Self> {55 fn into_untyped(value: Self, _: State) -> Result<Val> {
66 Ok(Self::Num(value as f64))56 Ok(Val::Num(value as f64))
67 }57 }
68 }58 }
69 )*};59 )*};
70}60}
7161
94 }84 }
95 }85 }
9686
97 impl<const MIN: $ty, const MAX: $ty> Typed for $name<MIN, MAX> {87 impl<const MIN: $ty, const MAX: $ty> Typed for $name<MIN, MAX> {
98 const TYPE: &'static ComplexValType =88 const TYPE: &'static ComplexValType =
99 &ComplexValType::BoundedNumber(89 &ComplexValType::BoundedNumber(
100 Some(MIN as f64),90 Some(MIN as f64),
101 Some(MAX as f64),91 Some(MAX as f64),
102 );92 );
103 }
104 impl<const MIN: $ty, const MAX: $ty> TryFrom<Val> for $name<MIN, MAX> {
105 type Error = LocError;
10693
107 fn try_from(value: Val) -> Result<Self> {94 fn from_untyped(value: Val, s: State) -> Result<Self> {
108 <Self as Typed>::TYPE.check(&value)?;95 <Self as Typed>::TYPE.check(s, &value)?;
109 match value {96 match value {
110 Val::Num(n) => {97 Val::Num(n) => {
111 if n.trunc() != n {98 if n.trunc() != n {
122 _ => unreachable!(),109 _ => unreachable!(),
123 }110 }
124 }111 }
125 }
126 impl<const MIN: $ty, const MAX: $ty> TryFrom<$name<MIN, MAX>> for Val {
127 type Error = LocError;
128112
129 fn try_from(value: $name<MIN, MAX>) -> Result<Self> {113 fn into_untyped(value: Self, _: State) -> Result<Val> {
130 Ok(Self::Num(value.0 as f64))114 Ok(Val::Num(value.0 as f64))
131 }115 }
132 }116 }
133 )*};117 )*};
134}118}
135119
141 BoundedUsize = usize125 BoundedUsize = usize
142);126);
143127
144impl Typed for f64 {128impl Typed for f64 {
145 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Num);129 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Num);
146}130
147impl TryFrom<Val> for f64 {131 fn into_untyped(value: Self, _: State) -> Result<Val> {
148 type Error = LocError;132 Ok(Val::Num(value))
133 }
149134
150 fn try_from(value: Val) -> Result<Self> {135 fn from_untyped(value: Val, s: State) -> Result<Self> {
151 <Self as Typed>::TYPE.check(&value)?;136 <Self as Typed>::TYPE.check(s, &value)?;
152 match value {137 match value {
153 Val::Num(n) => Ok(n),138 Val::Num(n) => Ok(n),
154 _ => unreachable!(),139 _ => unreachable!(),
155 }140 }
156 }141 }
157}142}
158impl TryFrom<f64> for Val {
159 type Error = LocError;
160
161 fn try_from(value: f64) -> Result<Self> {
162 Ok(Self::Num(value))
163 }
164}
165143
166pub struct PositiveF64(pub f64);144pub struct PositiveF64(pub f64);
167impl Typed for PositiveF64 {145impl Typed for PositiveF64 {
168 const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(0.0), None);146 const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(0.0), None);
169}147
170impl TryFrom<Val> for PositiveF64 {148 fn into_untyped(value: Self, _: State) -> Result<Val> {
171 type Error = LocError;149 Ok(Val::Num(value.0))
150 }
172151
173 fn try_from(value: Val) -> Result<Self> {152 fn from_untyped(value: Val, s: State) -> Result<Self> {
174 <Self as Typed>::TYPE.check(&value)?;153 <Self as Typed>::TYPE.check(s, &value)?;
175 match value {154 match value {
176 Val::Num(n) => Ok(Self(n)),155 Val::Num(n) => Ok(Self(n)),
177 _ => unreachable!(),156 _ => unreachable!(),
178 }157 }
179 }158 }
180}159}
181impl TryFrom<PositiveF64> for Val {160impl Typed for usize {
182 type Error = LocError;
183
184 fn try_from(value: PositiveF64) -> Result<Self> {
185 Ok(Self::Num(value.0))
186 }
187}
188
189impl Typed for usize {
190 // It is possible to store 54 bits of precision in f64, but leaving u32::MAX here for compatibility161 // It is possible to store 54 bits of precision in f64, but leaving u32::MAX here for compatibility
191 const TYPE: &'static ComplexValType =162 const TYPE: &'static ComplexValType =
192 &ComplexValType::BoundedNumber(Some(0.0), Some(4294967295.0));163 &ComplexValType::BoundedNumber(Some(0.0), Some(4294967295.0));
193}164
194impl TryFrom<Val> for usize {165 fn into_untyped(value: Self, _: State) -> Result<Val> {
195 type Error = LocError;166 if value > u32::MAX as Self {
167 throw!(RuntimeError("number is too large".into()))
168 }
169 Ok(Val::Num(value as f64))
170 }
196171
197 fn try_from(value: Val) -> Result<Self> {172 fn from_untyped(value: Val, s: State) -> Result<Self> {
198 <Self as Typed>::TYPE.check(&value)?;173 <Self as Typed>::TYPE.check(s, &value)?;
199 match value {174 match value {
200 Val::Num(n) => {175 Val::Num(n) => {
201 if n.trunc() != n {176 if n.trunc() != n {
208 _ => unreachable!(),183 _ => unreachable!(),
209 }184 }
210 }185 }
211}186}
187
212impl TryFrom<usize> for Val {188impl Typed for IStr {
213 type Error = LocError;
214
215 fn try_from(value: usize) -> Result<Self> {
216 if value > u32::MAX as usize {
217 throw!(RuntimeError("number is too large".into()))
218 }
219 Ok(Self::Num(value as f64))
220 }
221}
222
223impl Typed for IStr {
224 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);189 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);
225}190
226impl TryFrom<Val> for IStr {191 fn into_untyped(value: Self, _: State) -> Result<Val> {
227 type Error = LocError;192 Ok(Val::Str(value))
193 }
228194
229 fn try_from(value: Val) -> Result<Self> {195 fn from_untyped(value: Val, s: State) -> Result<Self> {
230 <Self as Typed>::TYPE.check(&value)?;196 <Self as Typed>::TYPE.check(s, &value)?;
231 match value {197 match value {
232 Val::Str(s) => Ok(s),198 Val::Str(s) => Ok(s),
233 _ => unreachable!(),199 _ => unreachable!(),
234 }200 }
235 }201 }
236}202}
203
237impl TryFrom<IStr> for Val {204impl Typed for String {
238 type Error = LocError;
239
240 fn try_from(value: IStr) -> Result<Self> {
241 Ok(Self::Str(value))
242 }
243}
244
245impl Typed for String {
246 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);205 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);
247}206
248impl TryFrom<Val> for String {207 fn into_untyped(value: Self, _: State) -> Result<Val> {
249 type Error = LocError;208 Ok(Val::Str(value.into()))
209 }
250210
251 fn try_from(value: Val) -> Result<Self> {211 fn from_untyped(value: Val, s: State) -> Result<Self> {
252 <Self as Typed>::TYPE.check(&value)?;212 <Self as Typed>::TYPE.check(s, &value)?;
253 match value {213 match value {
254 Val::Str(s) => Ok(s.to_string()),214 Val::Str(s) => Ok(s.to_string()),
255 _ => unreachable!(),215 _ => unreachable!(),
256 }216 }
257 }217 }
258}218}
219
259impl TryFrom<String> for Val {220impl Typed for char {
260 type Error = LocError;
261
262 fn try_from(value: String) -> Result<Self> {
263 Ok(Self::Str(value.into()))
264 }
265}
266
267impl Typed for char {
268 const TYPE: &'static ComplexValType = &ComplexValType::Char;221 const TYPE: &'static ComplexValType = &ComplexValType::Char;
269}222
270impl TryFrom<Val> for char {223 fn into_untyped(value: Self, _: State) -> Result<Val> {
271 type Error = LocError;224 Ok(Val::Str(value.to_string().into()))
225 }
272226
273 fn try_from(value: Val) -> Result<Self> {227 fn from_untyped(value: Val, s: State) -> Result<Self> {
274 <Self as Typed>::TYPE.check(&value)?;228 <Self as Typed>::TYPE.check(s, &value)?;
275 match value {229 match value {
276 Val::Str(s) => Ok(s.chars().next().unwrap()),230 Val::Str(s) => Ok(s.chars().next().unwrap()),
277 _ => unreachable!(),231 _ => unreachable!(),
278 }232 }
279 }233 }
280}234}
235
281impl TryFrom<char> for Val {236impl<T> Typed for Vec<T>
282 type Error = LocError;
283
284 fn try_from(value: char) -> Result<Self> {
285 Ok(Self::Str(value.to_string().into()))
286 }
287}
288
289impl<T> Typed for Vec<T>
290where237where
291 T: Typed,238 T: Typed,
292 T: TryFrom<Val, Error = LocError>,239{
293 T: TryInto<Val, Error = LocError>,
294{
295 const TYPE: &'static ComplexValType = &ComplexValType::ArrayRef(T::TYPE);240 const TYPE: &'static ComplexValType = &ComplexValType::ArrayRef(T::TYPE);
296}241
297impl<T> TryFrom<Val> for Vec<T>
298where
299 T: Typed,242 fn into_untyped(value: Self, s: State) -> Result<Val> {
300 T: TryFrom<Val, Error = LocError>,243 let mut o = Vec::with_capacity(value.len());
244 for i in value {
301 T: TryInto<Val, Error = LocError>,245 o.push(T::into_untyped(i, s.clone())?);
302{246 }
303 type Error = LocError;247 Ok(Val::Arr(o.into()))
248 }
304249
305 fn try_from(value: Val) -> Result<Self> {250 fn from_untyped(value: Val, s: State) -> Result<Self> {
306 <Self as Typed>::TYPE.check(&value)?;251 <Self as Typed>::TYPE.check(s.clone(), &value)?;
307 match value {252 match value {
308 Val::Arr(a) => {253 Val::Arr(a) => {
309 let mut o = Self::with_capacity(a.len());254 let mut o = Self::with_capacity(a.len());
310 for i in a.iter() {255 for i in a.iter(s.clone()) {
311 o.push(T::try_from(i?)?);256 o.push(T::from_untyped(i?, s.clone())?);
312 }257 }
313 Ok(o)258 Ok(o)
314 }259 }
315 _ => unreachable!(),260 _ => unreachable!(),
316 }261 }
317 }262 }
318}263}
319impl<T> TryFrom<Vec<T>> for Val
320where
321 T: Typed,
322 T: TryFrom<Self, Error = LocError>,
323 T: TryInto<Self, Error = LocError>,
324{
325 type Error = LocError;
326
327 fn try_from(value: Vec<T>) -> Result<Self> {
328 let mut o = Vec::with_capacity(value.len());
329 for i in value {
330 o.push(i.try_into()?);
331 }
332 Ok(Self::Arr(o.into()))
333 }
334}
335264
336/// To be used in Vec<Any>265/// To be used in Vec<Any>
337/// Regular Val can't be used here, because it has wrong TryFrom::Error type266/// Regular Val can't be used here, because it has wrong TryFrom::Error type
338#[derive(Clone)]267#[derive(Clone)]
339pub struct Any(pub Val);268pub struct Any(pub Val);
340269
341impl Typed for Any {270impl Typed for Any {
342 const TYPE: &'static ComplexValType = &ComplexValType::Any;271 const TYPE: &'static ComplexValType = &ComplexValType::Any;
343}
344impl TryFrom<Val> for Any {
345 type Error = LocError;
346272
347 fn try_from(value: Val) -> Result<Self> {273 fn into_untyped(value: Self, _: State) -> Result<Val> {
348 Ok(Self(value))274 Ok(value.0)
349 }275 }
350}
351impl TryFrom<Any> for Val {
352 type Error = LocError;
353276
354 fn try_from(value: Any) -> Result<Self> {277 fn from_untyped(value: Val, _: State) -> Result<Self> {
355 Ok(value.0)278 Ok(Self(value))
356 }279 }
357}280}
358281
359/// Specialization, provides faster TryFrom<VecVal> for Val282/// Specialization, provides faster TryFrom<VecVal> for Val
360pub struct VecVal(pub Cc<Vec<Val>>);283pub struct VecVal(pub Cc<Vec<Val>>);
361284
362impl Typed for VecVal {285impl Typed for VecVal {
363 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);286 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);
364}287
365impl TryFrom<Val> for VecVal {288 fn into_untyped(value: Self, _: State) -> Result<Val> {
366 type Error = LocError;289 Ok(Val::Arr(ArrValue::Eager(value.0)))
290 }
367291
368 fn try_from(value: Val) -> Result<Self> {292 fn from_untyped(value: Val, s: State) -> Result<Self> {
369 <Self as Typed>::TYPE.check(&value)?;293 <Self as Typed>::TYPE.check(s.clone(), &value)?;
370 match value {294 match value {
371 Val::Arr(a) => Ok(Self(a.evaluated()?)),295 Val::Arr(a) => Ok(Self(a.evaluated(s)?)),
372 _ => unreachable!(),296 _ => unreachable!(),
373 }297 }
374 }298 }
375}299}
376impl TryFrom<VecVal> for Val {
377 type Error = LocError;
378
379 fn try_from(value: VecVal) -> Result<Self> {
380 Ok(Self::Arr(ArrValue::Eager(value.0)))
381 }
382}
383300
384/// Specialization301/// Specialization
385pub struct Bytes(pub Rc<[u8]>);302pub struct Bytes(pub Rc<[u8]>);
386303
387impl Typed for Bytes {304impl Typed for Bytes {
388 const TYPE: &'static ComplexValType =305 const TYPE: &'static ComplexValType =
389 &ComplexValType::ArrayRef(&ComplexValType::BoundedNumber(Some(0.0), Some(255.0)));306 &ComplexValType::ArrayRef(&ComplexValType::BoundedNumber(Some(0.0), Some(255.0)));
390}307
391impl TryFrom<Val> for Bytes {308 fn into_untyped(value: Self, _: State) -> Result<Val> {
392 type Error = LocError;309 Ok(Val::Arr(ArrValue::Bytes(value.0)))
310 }
393311
394 fn try_from(value: Val) -> Result<Self> {312 fn from_untyped(value: Val, s: State) -> Result<Self> {
395 match value {313 match value {
396 Val::Arr(ArrValue::Bytes(bytes)) => Ok(Self(bytes)),314 Val::Arr(ArrValue::Bytes(bytes)) => Ok(Self(bytes)),
397 _ => {315 _ => {
398 <Self as Typed>::TYPE.check(&value)?;316 <Self as Typed>::TYPE.check(s.clone(), &value)?;
399 match value {317 match value {
400 Val::Arr(a) => {318 Val::Arr(a) => {
401 let mut out = Vec::with_capacity(a.len());319 let mut out = Vec::with_capacity(a.len());
402 for e in a.iter() {320 for e in a.iter(s.clone()) {
403 let r = e?;321 let r = e?;
404 out.push(u8::try_from(r)?);322 out.push(u8::from_untyped(r, s.clone())?);
405 }323 }
406 Ok(Self(out.into()))324 Ok(Self(out.into()))
407 }325 }
410 }328 }
411 }329 }
412 }330 }
413}331}
414impl TryFrom<Bytes> for Val {
415 type Error = LocError;
416
417 fn try_from(value: Bytes) -> Result<Self> {
418 Ok(Self::Arr(ArrValue::Bytes(value.0)))
419 }
420}
421332
422pub struct M1;333pub struct M1;
423impl Typed for M1 {334impl Typed for M1 {
424 const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(-1.0), Some(-1.0));335 const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(-1.0), Some(-1.0));
425}336
426impl TryFrom<Val> for M1 {337 fn into_untyped(_: Self, _: State) -> Result<Val> {
427 type Error = LocError;338 Ok(Val::Num(-1.0))
339 }
428340
429 fn try_from(value: Val) -> Result<Self> {341 fn from_untyped(value: Val, s: State) -> Result<Self> {
430 <Self as Typed>::TYPE.check(&value)?;342 <Self as Typed>::TYPE.check(s, &value)?;
431 Ok(Self)343 Ok(Self)
432 }344 }
433}345}
434impl TryFrom<M1> for Val {
435 type Error = LocError;
436
437 fn try_from(_: M1) -> Result<Self> {
438 Ok(Self::Num(-1.0))
439 }
440}
441346
442macro_rules! decl_either {347macro_rules! decl_either {
443 ($($name: ident, $($id: ident)*);*) => {$(348 ($($name: ident, $($id: ident)*);*) => {$(
447 impl<$($id),*> Typed for $name<$($id),*>352 impl<$($id),*> Typed for $name<$($id),*>
448 where353 where
449 $($id: Typed,)*354 $($id: Typed,)*
450 {355 {
451 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[$($id::TYPE),*]);356 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[$($id::TYPE),*]);
452 }357
453 impl<$($id),*> TryFrom<Val> for $name<$($id),*>358 fn into_untyped(value: Self, s: State) -> Result<Val> {
454 where
455 $($id: Typed,)*359 match value {$(
456 {360 $name::$id(v) => $id::into_untyped(v, s)
457 type Error = LocError;361 ),*}
362 }
458363
459 fn try_from(value: Val) -> Result<Self> {364 fn from_untyped(value: Val, s: State) -> Result<Self> {
460 $(365 $(
461 if $id::TYPE.check(&value).is_ok() {366 if $id::TYPE.check(s.clone(), &value).is_ok() {
462 $id::try_from(value).map(Self::$id)367 $id::from_untyped(value, s.clone()).map(Self::$id)
463 } else368 } else
464 )* {369 )* {
465 <Self as Typed>::TYPE.check(&value)?;370 <Self as Typed>::TYPE.check(s, &value)?;
466 unreachable!()371 unreachable!()
467 }372 }
468 }373 }
469 }374 }
470 impl<$($id),*> TryFrom<$name<$($id),*>> for Val
471 where
472 $($id: Typed,)*
473 {
474 type Error = LocError;
475 fn try_from(value: $name<$($id),*>) -> Result<Self> {
476 match value {$(
477 $name::$id(v) => v.try_into()
478 ),*}
479 }
480 }
481 )*}375 )*}
482}376}
483decl_either!(377decl_either!(
502396
503pub type MyType = Either![u32, f64, String];397pub type MyType = Either![u32, f64, String];
504398
505impl Typed for ArrValue {399impl Typed for ArrValue {
506 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);400 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);
507}401
508impl TryFrom<Val> for ArrValue {402 fn into_untyped(value: Self, _: State) -> Result<Val> {
509 type Error = LocError;403 Ok(Val::Arr(value))
404 }
510405
511 fn try_from(value: Val) -> Result<Self> {406 fn from_untyped(value: Val, s: State) -> Result<Self> {
512 <Self as Typed>::TYPE.check(&value)?;407 <Self as Typed>::TYPE.check(s, &value)?;
513 match value {408 match value {
514 Val::Arr(a) => Ok(a),409 Val::Arr(a) => Ok(a),
515 _ => unreachable!(),410 _ => unreachable!(),
516 }411 }
517 }412 }
518}413}
414
519impl TryFrom<ArrValue> for Val {415impl Typed for FuncVal {
520 type Error = LocError;
521
522 fn try_from(value: ArrValue) -> Result<Self> {
523 Ok(Self::Arr(value))
524 }
525}
526
527impl Typed for FuncVal {
528 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);416 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);
529}417
530impl TryFrom<Val> for FuncVal {418 fn into_untyped(value: Self, _: State) -> Result<Val> {
531 type Error = LocError;419 Ok(Val::Func(value))
420 }
532421
533 fn try_from(value: Val) -> Result<Self> {422 fn from_untyped(value: Val, s: State) -> Result<Self> {
534 <Self as Typed>::TYPE.check(&value)?;423 <Self as Typed>::TYPE.check(s, &value)?;
535 match value {424 match value {
536 Val::Func(a) => Ok(a),425 Val::Func(a) => Ok(a),
537 _ => unreachable!(),426 _ => unreachable!(),
538 }427 }
539 }428 }
540}429}
430
541impl TryFrom<FuncVal> for Val {431impl Typed for Cc<FuncDesc> {
542 type Error = LocError;
543
544 fn try_from(value: FuncVal) -> Result<Self> {
545 Ok(Self::Func(value))
546 }
547}
548
549impl Typed for Cc<FuncDesc> {
550 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);432 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);
551}433
552impl TryFrom<Val> for Cc<FuncDesc> {434 fn into_untyped(value: Self, _: State) -> Result<Val> {
553 type Error = LocError;435 Ok(Val::Func(FuncVal::Normal(value)))
436 }
554437
555 fn try_from(value: Val) -> Result<Self, Self::Error> {438 fn from_untyped(value: Val, s: State) -> Result<Self> {
556 <Self as Typed>::TYPE.check(&value)?;439 <Self as Typed>::TYPE.check(s, &value)?;
557 match value {440 match value {
558 Val::Func(FuncVal::Normal(desc)) => Ok(desc),441 Val::Func(FuncVal::Normal(desc)) => Ok(desc),
559 Val::Func(_) => throw!(RuntimeError("expected normal function, not builtin".into())),442 Val::Func(_) => throw!(RuntimeError("expected normal function, not builtin".into())),
560 _ => unreachable!(),443 _ => unreachable!(),
561 }444 }
562 }445 }
563}446}
447
564impl TryFrom<Cc<FuncDesc>> for Val {448impl Typed for ObjValue {
565 type Error = LocError;
566
567 fn try_from(value: Cc<FuncDesc>) -> Result<Self, Self::Error> {
568 Ok(Self::Func(FuncVal::Normal(value)))
569 }
570}
571
572impl Typed for ObjValue {
573 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Obj);449 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Obj);
574}450
575impl TryFrom<Val> for ObjValue {451 fn into_untyped(value: Self, _: State) -> Result<Val> {
576 type Error = LocError;452 Ok(Val::Obj(value))
453 }
577454
578 fn try_from(value: Val) -> Result<Self> {455 fn from_untyped(value: Val, s: State) -> Result<Self> {
579 <Self as Typed>::TYPE.check(&value)?;456 <Self as Typed>::TYPE.check(s, &value)?;
580 match value {457 match value {
581 Val::Obj(a) => Ok(a),458 Val::Obj(a) => Ok(a),
582 _ => unreachable!(),459 _ => unreachable!(),
583 }460 }
584 }461 }
585}462}
463
586impl TryFrom<ObjValue> for Val {464impl Typed for bool {
587 type Error = LocError;
588
589 fn try_from(value: ObjValue) -> Result<Self> {
590 Ok(Self::Obj(value))
591 }
592}
593
594impl Typed for bool {
595 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Bool);465 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Bool);
596}466
597impl TryFrom<Val> for bool {467 fn into_untyped(value: Self, _: State) -> Result<Val> {
598 type Error = LocError;468 Ok(Val::Bool(value))
469 }
599470
600 fn try_from(value: Val) -> Result<Self> {471 fn from_untyped(value: Val, s: State) -> Result<Self> {
601 <Self as Typed>::TYPE.check(&value)?;472 <Self as Typed>::TYPE.check(s, &value)?;
602 match value {473 match value {
603 Val::Bool(a) => Ok(a),474 Val::Bool(a) => Ok(a),
604 _ => unreachable!(),475 _ => unreachable!(),
605 }476 }
606 }477 }
607}478}
608impl TryFrom<bool> for Val {479impl Typed for IndexableVal {
609 type Error = LocError;
610
611 fn try_from(value: bool) -> Result<Self> {
612 Ok(Self::Bool(value))
613 }
614}
615
616impl Typed for IndexableVal {
617 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[480 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[
618 &ComplexValType::Simple(ValType::Arr),481 &ComplexValType::Simple(ValType::Arr),
619 &ComplexValType::Simple(ValType::Str),482 &ComplexValType::Simple(ValType::Str),
620 ]);483 ]);
621}
622impl TryFrom<Val> for IndexableVal {
623 type Error = LocError;
624
625 fn try_from(value: Val) -> Result<Self> {
626 <Self as Typed>::TYPE.check(&value)?;
627 value.into_indexable()
628 }
629}
630impl TryFrom<IndexableVal> for Val {
631 type Error = LocError;
632484
633 fn try_from(value: IndexableVal) -> Result<Self> {485 fn into_untyped(value: Self, _: State) -> Result<Val> {
634 match value {486 match value {
635 IndexableVal::Str(s) => Ok(Self::Str(s)),487 IndexableVal::Str(s) => Ok(Val::Str(s)),
636 IndexableVal::Arr(a) => Ok(Self::Arr(a)),488 IndexableVal::Arr(a) => Ok(Val::Arr(a)),
637 }489 }
638 }490 }
639}491
492 fn from_untyped(value: Val, s: State) -> Result<Self> {
493 <Self as Typed>::TYPE.check(s, &value)?;
494 value.into_indexable()
495 }
496}
640497
641pub struct Null;498pub struct Null;
642impl Typed for Null {499impl Typed for Null {
643 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Null);500 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Null);
644}501
645impl TryFrom<Val> for Null {502 fn into_untyped(_: Self, _: State) -> Result<Val> {
646 type Error = LocError;503 Ok(Val::Null)
504 }
647505
648 fn try_from(value: Val) -> Result<Self> {506 fn from_untyped(value: Val, s: State) -> Result<Self> {
649 <Self as Typed>::TYPE.check(&value)?;507 <Self as Typed>::TYPE.check(s, &value)?;
650 Ok(Self)508 Ok(Self)
651 }509 }
652}510}
653impl TryFrom<Null> for Val {
654 type Error = LocError;
655
656 fn try_from(_: Null) -> Result<Self> {
657 Ok(Self::Null)
658 }
659}
660511
modifiedcrates/jrsonnet-evaluator/src/typed/mod.rsdiffbeforeafterboth
88
9use crate::{9use crate::{
10 error::{Error, LocError, Result},10 error::{Error, LocError, Result},
11 push_description_frame, Val,11 State, Val,
12};12};
1313
14#[derive(Debug, Error, Clone, Trace)]14#[derive(Debug, Error, Clone, Trace)]
85}85}
8686
87fn push_type_description(87fn push_type_description(
88 s: State,
88 error_reason: impl Fn() -> String,89 error_reason: impl Fn() -> String,
89 path: impl Fn() -> ValuePathItem,90 path: impl Fn() -> ValuePathItem,
90 item: impl Fn() -> Result<()>,91 item: impl Fn() -> Result<()>,
91) -> Result<()> {92) -> Result<()> {
92 push_description_frame(error_reason, || match item() {93 s.push_description(error_reason, || match item() {
93 Ok(_) => Ok(()),94 Ok(_) => Ok(()),
94 Err(mut e) => {95 Err(mut e) => {
95 if let Error::TypeError(e) = &mut e.error_mut() {96 if let Error::TypeError(e) = &mut e.error_mut() {
102103
103// TODO: check_fast for fast path of union type checking104// TODO: check_fast for fast path of union type checking
104pub trait CheckType {105pub trait CheckType {
105 fn check(&self, value: &Val) -> Result<()>;106 fn check(&self, s: State, value: &Val) -> Result<()>;
106}107}
107108
108impl CheckType for ValType {109impl CheckType for ValType {
109 fn check(&self, value: &Val) -> Result<()> {110 fn check(&self, _: State, value: &Val) -> Result<()> {
110 let got = value.value_type();111 let got = value.value_type();
111 if got != *self {112 if got != *self {
112 let loc_error: TypeLocError = TypeError::ExpectedGot((*self).into(), got).into();113 let loc_error: TypeLocError = TypeError::ExpectedGot((*self).into(), got).into();
144}145}
145146
146impl CheckType for ComplexValType {147impl CheckType for ComplexValType {
147 fn check(&self, value: &Val) -> Result<()> {148 fn check(&self, s: State, value: &Val) -> Result<()> {
148 match self {149 match self {
149 Self::Any => Ok(()),150 Self::Any => Ok(()),
150 Self::Simple(s) => s.check(value),151 Self::Simple(t) => t.check(s, value),
151 Self::Char => match value {152 Self::Char => match value {
152 Val::Str(s) if s.len() == 1 || s.chars().count() == 1 => Ok(()),153 Val::Str(s) if s.len() == 1 || s.chars().count() == 1 => Ok(()),
153 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),154 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
166 }167 }
167 Self::Array(elem_type) => match value {168 Self::Array(elem_type) => match value {
168 Val::Arr(a) => {169 Val::Arr(a) => {
169 for (i, item) in a.iter().enumerate() {170 for (i, item) in a.iter(s.clone()).enumerate() {
170 push_type_description(171 push_type_description(
172 s.clone(),
171 || format!("array index {}", i),173 || format!("array index {}", i),
172 || ValuePathItem::Index(i as u64),174 || ValuePathItem::Index(i as u64),
173 || elem_type.check(&item.clone()?),175 || elem_type.check(s.clone(), &item.clone()?),
174 )?;176 )?;
175 }177 }
176 Ok(())178 Ok(())
179 },181 },
180 Self::ArrayRef(elem_type) => match value {182 Self::ArrayRef(elem_type) => match value {
181 Val::Arr(a) => {183 Val::Arr(a) => {
182 for (i, item) in a.iter().enumerate() {184 for (i, item) in a.iter(s.clone()).enumerate() {
183 push_type_description(185 push_type_description(
186 s.clone(),
184 || format!("array index {}", i),187 || format!("array index {}", i),
185 || ValuePathItem::Index(i as u64),188 || ValuePathItem::Index(i as u64),
186 || elem_type.check(&item.clone()?),189 || elem_type.check(s.clone(), &item.clone()?),
187 )?;190 )?;
188 }191 }
189 Ok(())192 Ok(())
193 Self::ObjectRef(elems) => match value {196 Self::ObjectRef(elems) => match value {
194 Val::Obj(obj) => {197 Val::Obj(obj) => {
195 for (k, v) in elems.iter() {198 for (k, v) in elems.iter() {
196 if let Some(got_v) = obj.get((*k).into())? {199 if let Some(got_v) = obj.get(s.clone(), (*k).into())? {
197 push_type_description(200 push_type_description(
201 s.clone(),
198 || format!("property {}", k),202 || format!("property {}", k),
199 || ValuePathItem::Field((*k).into()),203 || ValuePathItem::Field((*k).into()),
200 || v.check(&got_v),204 || v.check(s.clone(), &got_v),
201 )?205 )?
202 } else {206 } else {
203 return Err(207 return Err(
212 Self::Union(types) => {216 Self::Union(types) => {
213 let mut errors = Vec::new();217 let mut errors = Vec::new();
214 for ty in types.iter() {218 for ty in types.iter() {
215 match ty.check(value) {219 match ty.check(s.clone(), value) {
216 Ok(()) => {220 Ok(()) => {
217 return Ok(());221 return Ok(());
218 }222 }
227 Self::UnionRef(types) => {231 Self::UnionRef(types) => {
228 let mut errors = Vec::new();232 let mut errors = Vec::new();
229 for ty in types.iter() {233 for ty in types.iter() {
230 match ty.check(value) {234 match ty.check(s.clone(), value) {
231 Ok(()) => {235 Ok(()) => {
232 return Ok(());236 return Ok(());
233 }237 }
241 }245 }
242 Self::Sum(types) => {246 Self::Sum(types) => {
243 for ty in types.iter() {247 for ty in types.iter() {
244 ty.check(value)?248 ty.check(s.clone(), value)?
245 }249 }
246 Ok(())250 Ok(())
247 }251 }
248 Self::SumRef(types) => {252 Self::SumRef(types) => {
249 for ty in types.iter() {253 for ty in types.iter() {
250 ty.check(value)?254 ty.check(s.clone(), value)?
251 }255 }
252 Ok(())256 Ok(())
253 }257 }
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
17 StaticBuiltin,17 StaticBuiltin,
18 },18 },
19 gc::TraceBox,19 gc::TraceBox,
20 throw, Context, ObjValue, Result,20 throw, Context, ObjValue, Result, State,
21};21};
2222
23pub trait LazyValValue: Trace {23pub trait LazyValValue: Trace {
24 fn get(self: Box<Self>) -> Result<Val>;24 fn get(self: Box<Self>, s: State) -> Result<Val>;
25}25}
2626
27#[derive(Trace)]27#[derive(Trace)]
41 pub fn new_resolved(val: Val) -> Self {41 pub fn new_resolved(val: Val) -> Self {
42 Self(Cc::new(RefCell::new(LazyValInternals::Computed(val))))42 Self(Cc::new(RefCell::new(LazyValInternals::Computed(val))))
43 }43 }
44 pub fn force(&self) -> Result<()> {44 pub fn force(&self, s: State) -> Result<()> {
45 self.evaluate()?;45 self.evaluate(s)?;
46 Ok(())46 Ok(())
47 }47 }
48 pub fn evaluate(&self) -> Result<Val> {48 pub fn evaluate(&self, s: State) -> Result<Val> {
49 match &*self.0.borrow() {49 match &*self.0.borrow() {
50 LazyValInternals::Computed(v) => return Ok(v.clone()),50 LazyValInternals::Computed(v) => return Ok(v.clone()),
51 LazyValInternals::Errored(e) => return Err(e.clone()),51 LazyValInternals::Errored(e) => return Err(e.clone()),
59 } else {59 } else {
60 unreachable!()60 unreachable!()
61 };61 };
62 let new_value = match value.0.get() {62 let new_value = match value.0.get(s) {
63 Ok(v) => v,63 Ok(v) => v,
64 Err(e) => {64 Err(e) => {
65 *self.0.borrow_mut() = LazyValInternals::Errored(e.clone());65 *self.0.borrow_mut() = LazyValInternals::Errored(e.clone());
98 /// Create context, with which body code will run98 /// Create context, with which body code will run
99 pub fn call_body_context(99 pub fn call_body_context(
100 &self,100 &self,
101 s: State,
101 call_ctx: Context,102 call_ctx: Context,
102 args: &dyn ArgsLike,103 args: &dyn ArgsLike,
103 tailstrict: bool,104 tailstrict: bool,
104 ) -> Result<Context> {105 ) -> Result<Context> {
105 parse_function_call(call_ctx, self.ctx.clone(), &self.params, args, tailstrict)106 parse_function_call(
107 s,
108 call_ctx,
109 self.ctx.clone(),
110 &self.params,
111 args,
112 tailstrict,
113 )
106 }114 }
107}115}
145 }153 }
146 pub fn evaluate(154 pub fn evaluate(
147 &self,155 &self,
156 s: State,
148 call_ctx: Context,157 call_ctx: Context,
149 loc: CallLocation,158 loc: CallLocation,
150 args: &dyn ArgsLike,159 args: &dyn ArgsLike,
151 tailstrict: bool,160 tailstrict: bool,
152 ) -> Result<Val> {161 ) -> Result<Val> {
153 match self {162 match self {
154 Self::Normal(func) => {163 Self::Normal(func) => {
155 let body_ctx = func.call_body_context(call_ctx, args, tailstrict)?;164 let body_ctx = func.call_body_context(s.clone(), call_ctx, args, tailstrict)?;
156 evaluate(body_ctx, &func.body)165 evaluate(s, body_ctx, &func.body)
157 }166 }
158 Self::StaticBuiltin(b) => b.call(call_ctx, loc, args),167 Self::StaticBuiltin(b) => b.call(s, call_ctx, loc, args),
159 Self::Builtin(b) => b.call(call_ctx, loc, args),168 Self::Builtin(b) => b.call(s, call_ctx, loc, args),
160 }169 }
161 }170 }
162 pub fn evaluate_simple(&self, args: &dyn ArgsLike) -> Result<Val> {171 pub fn evaluate_simple(&self, s: State, args: &dyn ArgsLike) -> Result<Val> {
163 self.evaluate(Context::default(), CallLocation::native(), args, true)172 self.evaluate(s, Context::default(), CallLocation::native(), args, true)
164 }173 }
165}174}
166175
276 self.len() == 0285 self.len() == 0
277 }286 }
278287
279 pub fn get(&self, index: usize) -> Result<Option<Val>> {288 pub fn get(&self, s: State, index: usize) -> Result<Option<Val>> {
280 match self {289 match self {
281 Self::Bytes(i) => i290 Self::Bytes(i) => i
282 .get(index)291 .get(index)
283 .map_or(Ok(None), |v| Ok(Some(Val::Num(*v as f64)))),292 .map_or(Ok(None), |v| Ok(Some(Val::Num(*v as f64)))),
284 Self::Lazy(vec) => {293 Self::Lazy(vec) => {
285 if let Some(v) = vec.get(index) {294 if let Some(v) = vec.get(index) {
286 Ok(Some(v.evaluate()?))295 Ok(Some(v.evaluate(s)?))
287 } else {296 } else {
288 Ok(None)297 Ok(None)
289 }298 }
292 Self::Extended(v) => {301 Self::Extended(v) => {
293 let a_len = v.0.len();302 let a_len = v.0.len();
294 if a_len > index {303 if a_len > index {
295 v.0.get(index)304 v.0.get(s, index)
296 } else {305 } else {
297 v.1.get(index - a_len)306 v.1.get(s, index - a_len)
298 }307 }
299 }308 }
300 Self::Range(a, _) => {309 Self::Range(a, _) => {
308 if index >= len {317 if index >= len {
309 return Ok(None);318 return Ok(None);
310 }319 }
311 v.get(len - index - 1)320 v.get(s, len - index - 1)
312 }321 }
313 Self::Slice(s) => {322 Self::Slice(v) => {
314 let index = s.from() + index * s.step();323 let index = v.from() + index * v.step();
315 if index >= s.to() {324 if index >= v.to() {
316 return Ok(None);325 return Ok(None);
317 }326 }
318 s.inner.get(index as usize)327 v.inner.get(s, index as usize)
319 }328 }
320 }329 }
321 }330 }
360 }369 }
361 }370 }
362371
363 pub fn evaluated(&self) -> Result<Cc<Vec<Val>>> {372 pub fn evaluated(&self, s: State) -> Result<Cc<Vec<Val>>> {
364 Ok(match self {373 Ok(match self {
365 Self::Bytes(i) => {374 Self::Bytes(i) => {
366 let mut out = Vec::with_capacity(i.len());375 let mut out = Vec::with_capacity(i.len());
372 Self::Lazy(vec) => {381 Self::Lazy(vec) => {
373 let mut out = Vec::with_capacity(vec.len());382 let mut out = Vec::with_capacity(vec.len());
374 for item in vec.iter() {383 for item in vec.iter() {
375 out.push(item.evaluate()?);384 out.push(item.evaluate(s.clone())?);
376 }385 }
377 Cc::new(out)386 Cc::new(out)
378 }387 }
379 Self::Eager(vec) => vec.clone(),388 Self::Eager(vec) => vec.clone(),
380 Self::Extended(_v) => {389 Self::Extended(_v) => {
381 let mut out = Vec::with_capacity(self.len());390 let mut out = Vec::with_capacity(self.len());
382 for item in self.iter() {391 for item in self.iter(s) {
383 out.push(item?);392 out.push(item?);
384 }393 }
385 Cc::new(out)394 Cc::new(out)
392 Cc::new(out)401 Cc::new(out)
393 }402 }
394 Self::Reversed(r) => {403 Self::Reversed(r) => {
395 let mut r = r.evaluated()?;404 let mut r = r.evaluated(s)?;
396 Cc::update_with(&mut r, |v| v.reverse());405 Cc::update_with(&mut r, |v| v.reverse());
397 r406 r
398 }407 }
405 .take(v.to() - v.from())414 .take(v.to() - v.from())
406 .step_by(v.step())415 .step_by(v.step())
407 {416 {
408 out.push(v.evaluate()?)417 out.push(v.evaluate(s.clone())?)
409 }418 }
410 Cc::new(out)419 Cc::new(out)
411 }420 }
412 })421 })
413 }422 }
414423
415 pub fn iter(&self) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {424 pub fn iter(&self, s: State) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {
416 (0..self.len()).map(move |idx| match self {425 (0..self.len()).map(move |idx| match self {
417 Self::Bytes(b) => Ok(Val::Num(b[idx] as f64)),426 Self::Bytes(b) => Ok(Val::Num(b[idx] as f64)),
418 Self::Lazy(l) => l[idx].evaluate(),427 Self::Lazy(l) => l[idx].evaluate(s.clone()),
419 Self::Eager(e) => Ok(e[idx].clone()),428 Self::Eager(e) => Ok(e[idx].clone()),
420 Self::Extended(_) => self.get(idx).map(|e| e.unwrap()),429 Self::Extended(_) => self.get(s.clone(), idx).map(|e| e.unwrap()),
421 Self::Range(..) => self.get(idx).map(|e| e.unwrap()),430 Self::Range(..) => self.get(s.clone(), idx).map(|e| e.unwrap()),
422 Self::Reversed(..) => self.get(idx).map(|e| e.unwrap()),431 Self::Reversed(..) => self.get(s.clone(), idx).map(|e| e.unwrap()),
423 Self::Slice(..) => self.get(idx).map(|e| e.unwrap()),432 Self::Slice(..) => self.get(s.clone(), idx).map(|e| e.unwrap()),
424 })433 })
425 }434 }
426435
440 Self::Reversed(Box::new(self))449 Self::Reversed(Box::new(self))
441 }450 }
442451
443 pub fn map(self, mapper: impl Fn(Val) -> Result<Val>) -> Result<Self> {452 pub fn map(self, s: State, mapper: impl Fn(Val) -> Result<Val>) -> Result<Self> {
444 let mut out = Vec::with_capacity(self.len());453 let mut out = Vec::with_capacity(self.len());
445454
446 for value in self.iter() {455 for value in self.iter(s) {
447 out.push(mapper(value?)?);456 out.push(mapper(value?)?);
448 }457 }
449458
450 Ok(Self::Eager(Cc::new(out)))459 Ok(Self::Eager(Cc::new(out)))
451 }460 }
452461
453 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {462 pub fn filter(self, s: State, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {
454 let mut out = Vec::with_capacity(self.len());463 let mut out = Vec::with_capacity(self.len());
455464
456 for value in self.iter() {465 for value in self.iter(s) {
457 let value = value?;466 let value = value?;
458 if filter(&value)? {467 if filter(&value)? {
459 out.push(value);468 out.push(value);
566 }575 }
567 }576 }
568577
569 pub fn to_string(&self) -> Result<IStr> {578 pub fn to_string(&self, s: State) -> Result<IStr> {
570 Ok(match self {579 Ok(match self {
571 Self::Bool(true) => "true".into(),580 Self::Bool(true) => "true".into(),
572 Self::Bool(false) => "false".into(),581 Self::Bool(false) => "false".into(),
573 Self::Null => "null".into(),582 Self::Null => "null".into(),
574 Self::Str(s) => s.clone(),583 Self::Str(s) => s.clone(),
575 v => manifest_json_ex(584 v => manifest_json_ex(
585 s,
576 v,586 v,
577 &ManifestJsonOptions {587 &ManifestJsonOptions {
578 padding: "",588 padding: "",
588 }598 }
589599
590 /// Expects value to be object, outputs (key, manifested value) pairs600 /// Expects value to be object, outputs (key, manifested value) pairs
591 pub fn manifest_multi(&self, ty: &ManifestFormat) -> Result<Vec<(IStr, IStr)>> {601 pub fn manifest_multi(&self, s: State, ty: &ManifestFormat) -> Result<Vec<(IStr, IStr)>> {
592 let obj = match self {602 let obj = match self {
593 Self::Obj(obj) => obj,603 Self::Obj(obj) => obj,
594 _ => throw!(MultiManifestOutputIsNotAObject),604 _ => throw!(MultiManifestOutputIsNotAObject),
600 let mut out = Vec::with_capacity(keys.len());610 let mut out = Vec::with_capacity(keys.len());
601 for key in keys {611 for key in keys {
602 let value = obj612 let value = obj
603 .get(key.clone())?613 .get(s.clone(), key.clone())?
604 .expect("item in object")614 .expect("item in object")
605 .manifest(ty)?;615 .manifest(s.clone(), ty)?;
606 out.push((key, value));616 out.push((key, value));
607 }617 }
608 Ok(out)618 Ok(out)
609 }619 }
610620
611 /// Expects value to be array, outputs manifested values621 /// Expects value to be array, outputs manifested values
612 pub fn manifest_stream(&self, ty: &ManifestFormat) -> Result<Vec<IStr>> {622 pub fn manifest_stream(&self, s: State, ty: &ManifestFormat) -> Result<Vec<IStr>> {
613 let arr = match self {623 let arr = match self {
614 Self::Arr(a) => a,624 Self::Arr(a) => a,
615 _ => throw!(StreamManifestOutputIsNotAArray),625 _ => throw!(StreamManifestOutputIsNotAArray),
616 };626 };
617 let mut out = Vec::with_capacity(arr.len());627 let mut out = Vec::with_capacity(arr.len());
618 for i in arr.iter() {628 for i in arr.iter(s.clone()) {
619 out.push(i?.manifest(ty)?);629 out.push(i?.manifest(s.clone(), ty)?);
620 }630 }
621 Ok(out)631 Ok(out)
622 }632 }
623633
624 pub fn manifest(&self, ty: &ManifestFormat) -> Result<IStr> {634 pub fn manifest(&self, s: State, ty: &ManifestFormat) -> Result<IStr> {
625 Ok(match ty {635 Ok(match ty {
626 ManifestFormat::YamlStream(format) => {636 ManifestFormat::YamlStream(format) => {
627 let arr = match self {637 let arr = match self {
637 };647 };
638648
639 if !arr.is_empty() {649 if !arr.is_empty() {
640 for v in arr.iter() {650 for v in arr.iter(s.clone()) {
641 out.push_str("---\n");651 out.push_str("---\n");
642 out.push_str(&v?.manifest(format)?);652 out.push_str(&v?.manifest(s.clone(), format)?);
643 out.push('\n');653 out.push('\n');
644 }654 }
645 out.push_str("...");655 out.push_str("...");
652 #[cfg(feature = "exp-preserve-order")]662 #[cfg(feature = "exp-preserve-order")]
653 preserve_order,663 preserve_order,
654 } => self.to_yaml(664 } => self.to_yaml(
665 s,
655 *padding,666 *padding,
656 #[cfg(feature = "exp-preserve-order")]667 #[cfg(feature = "exp-preserve-order")]
657 *preserve_order,668 *preserve_order,
661 #[cfg(feature = "exp-preserve-order")]672 #[cfg(feature = "exp-preserve-order")]
662 preserve_order,673 preserve_order,
663 } => self.to_json(674 } => self.to_json(
675 s,
664 *padding,676 *padding,
665 #[cfg(feature = "exp-preserve-order")]677 #[cfg(feature = "exp-preserve-order")]
666 *preserve_order,678 *preserve_order,
667 )?,679 )?,
668 ManifestFormat::ToString => self.to_string()?,680 ManifestFormat::ToString => self.to_string(s)?,
669 ManifestFormat::String => match self {681 ManifestFormat::String => match self {
670 Self::Str(s) => s.clone(),682 Self::Str(s) => s.clone(),
671 _ => throw!(StringManifestOutputIsNotAString),683 _ => throw!(StringManifestOutputIsNotAString),
676 /// For manifestification688 /// For manifestification
677 pub fn to_json(689 pub fn to_json(
678 &self,690 &self,
691 s: State,
679 padding: usize,692 padding: usize,
680 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,693 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,
681 ) -> Result<IStr> {694 ) -> Result<IStr> {
682 manifest_json_ex(695 manifest_json_ex(
696 s,
683 self,697 self,
684 &ManifestJsonOptions {698 &ManifestJsonOptions {
685 padding: &" ".repeat(padding),699 padding: &" ".repeat(padding),
700 /// Calls `std.manifestJson`714 /// Calls `std.manifestJson`
701 pub fn to_std_json(715 pub fn to_std_json(
702 &self,716 &self,
717 s: State,
703 padding: usize,718 padding: usize,
704 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,719 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,
705 ) -> Result<Rc<str>> {720 ) -> Result<Rc<str>> {
706 manifest_json_ex(721 manifest_json_ex(
722 s,
707 self,723 self,
708 &ManifestJsonOptions {724 &ManifestJsonOptions {
709 padding: &" ".repeat(padding),725 padding: &" ".repeat(padding),
719735
720 pub fn to_yaml(736 pub fn to_yaml(
721 &self,737 &self,
738 s: State,
722 padding: usize,739 padding: usize,
723 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,740 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,
724 ) -> Result<IStr> {741 ) -> Result<IStr> {
725 let padding = &" ".repeat(padding);742 let padding = &" ".repeat(padding);
726 manifest_yaml_ex(743 manifest_yaml_ex(
744 s,
727 self,745 self,
728 &ManifestYamlOptions {746 &ManifestYamlOptions {
729 padding,747 padding,
769}787}
770788
771/// Native implementation of `std.equals`789/// Native implementation of `std.equals`
772pub fn equals(val_a: &Val, val_b: &Val) -> Result<bool> {790pub fn equals(s: State, val_a: &Val, val_b: &Val) -> Result<bool> {
773 if val_a.value_type() != val_b.value_type() {791 if val_a.value_type() != val_b.value_type() {
774 return Ok(false);792 return Ok(false);
775 }793 }
781 if a.len() != b.len() {799 if a.len() != b.len() {
782 return Ok(false);800 return Ok(false);
783 }801 }
784 for (a, b) in a.iter().zip(b.iter()) {802 for (a, b) in a.iter(s.clone()).zip(b.iter(s.clone())) {
785 if !equals(&a?, &b?)? {803 if !equals(s.clone(), &a?, &b?)? {
786 return Ok(false);804 return Ok(false);
787 }805 }
788 }806 }
805 }823 }
806 for field in fields {824 for field in fields {
807 if !equals(&a.get(field.clone())?.unwrap(), &b.get(field)?.unwrap())? {825 if !equals(
826 s.clone(),
827 &a.get(s.clone(), field.clone())?.unwrap(),
828 &b.get(s.clone(), field)?.unwrap(),
829 )? {
808 return Ok(false);830 return Ok(false);
809 }831 }
modifiedcrates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth
129 is_option: bool,129 is_option: bool,
130 name: String,130 name: String,
131 },131 },
132 State,
132 Location,133 Location,
133 This,134 This,
134}135}
144 _ => return Err(Error::new(arg.pat.span(), "arg should be plain identifier")),145 _ => return Err(Error::new(arg.pat.span(), "arg should be plain identifier")),
145 };146 };
146 let ty = &arg.ty;147 let ty = &arg.ty;
148 if type_is_path(ty, "State").is_some() {
149 return Ok(Self::State);
147 if type_is_path(ty, "CallLocation").is_some() {150 } else if type_is_path(ty, "CallLocation").is_some() {
148 return Ok(Self::Location);151 return Ok(Self::Location);
149 } else if type_is_path(ty, "Self").is_some() {152 } else if type_is_path(ty, "Self").is_some() {
150 return Ok(Self::This);153 return Ok(Self::This);
208 }211 }
209 ReturnType::Type(_, ref ty) => ty.clone(),212 ReturnType::Type(_, ref ty) => ty.clone(),
210 };213 };
214 let result_inner = if let Some(args) = type_is_path(&result, "Result") {
215 let generic_arg = match args {
216 PathArguments::AngleBracketed(params) => params.args.iter().next().unwrap(),
217 _ => return Err(Error::new(args.span(), "missing result generic")),
218 };
219 // This argument must be a type:
220 match generic_arg {
221 GenericArgument::Type(ty) => ty,
222 _ => {
223 return Err(Error::new(
224 generic_arg.span(),
225 "option generic should be a type",
226 ))
227 }
228 }
229 } else {
230 return Err(Error::new(result.span(), "return value should be result"));
231 };
211232
212 let args = fun233 let args = fun
213 .sig234 .sig
235 has_default: #is_option,256 has_default: #is_option,
236 },257 },
237 }),258 }),
259 ArgInfo::State => None,
238 ArgInfo::Location => None,260 ArgInfo::Location => None,
239 ArgInfo::This => None,261 ArgInfo::This => None,
240 });262 });
246 name,268 name,
247 cfg_attrs,269 cfg_attrs,
248 } => {270 } => {
249 let eval = quote! {::jrsonnet_evaluator::push_description_frame(271 let eval = quote! {s.push_description(
250 || format!("argument <{}> evaluation", #name),272 || format!("argument <{}> evaluation", #name),
251 || <#ty>::try_from(value.evaluate()?),273 || <#ty>::from_untyped(value.evaluate(s.clone())?, s.clone()),
252 )?};274 )?};
253 let value = if *is_option {275 let value = if *is_option {
254 quote! {if let Some(value) = parsed.get(#name) {276 quote! {if let Some(value) = parsed.get(#name) {
280 }302 }
281 }303 }
282 }304 }
305 ArgInfo::State => quote! {s.clone(),},
283 ArgInfo::Location => quote! {location,},306 ArgInfo::Location => quote! {location,},
284 ArgInfo::This => quote! {self,},307 ArgInfo::This => quote! {self,},
285 });308 });
320 }343 }
321 const _: () = {344 const _: () = {
322 use ::jrsonnet_evaluator::{345 use ::jrsonnet_evaluator::{
346 State,
323 function::{Builtin, CallLocation, StaticBuiltin, BuiltinParam, ArgsLike, parse_builtin_call},347 function::{Builtin, CallLocation, StaticBuiltin, BuiltinParam, ArgsLike, parse_builtin_call},
324 error::Result, Context,348 error::Result, Context,
325 parser::ExprLocation,349 parser::ExprLocation,
339 fn params(&self) -> &[BuiltinParam] {363 fn params(&self) -> &[BuiltinParam] {
340 PARAMS364 PARAMS
341 }365 }
342 fn call(&self, context: Context, location: CallLocation, args: &dyn ArgsLike) -> Result<Val> {366 fn call(&self, s: State, ctx: Context, location: CallLocation, args: &dyn ArgsLike) -> Result<Val> {
343 let parsed = parse_builtin_call(context, &PARAMS, args, false)?;367 let parsed = parse_builtin_call(s.clone(), ctx, &PARAMS, args, false)?;
344368
345 let result: #result = #name(#(#pass)*);369 let result: #result = #name(#(#pass)*);
346 let result = result?;370 let result = result?;
347 result.try_into()371 <#result_inner>::into_untyped(result, s)
348 }372 }
349 }373 }
350 };374 };
540 impl Typed for #ident {564 impl Typed for #ident {
541 const TYPE: &'static ComplexValType = &ComplexValType::ObjectRef(&ITEMS);565 const TYPE: &'static ComplexValType = &ComplexValType::ObjectRef(&ITEMS);
566
567 fn from_untyped(value: Val, s: State) -> Result<Self> {
568 let obj = value.as_obj().expect("shape is correct");
569 Self::parse(&obj)
570 }
571
572 fn into_untyped(value: Self, s: State) -> Result<Val> {
573 let mut out = ObjValueBuilder::new();
574 value.serialize(&mut out)?;
575 Ok(Val::Obj(out.build()))
576 }
577
542 }578 }
543 }579 }
570 }606 }
571 }607 }
572
573 impl TryFrom<Val> for #ident {
574 type Error = LocError;
575 fn try_from(value: Val) -> Result<Self, Self::Error> {
576 let obj = value.as_obj().expect("shape is correct");
577 Self::parse(&obj)
578 }
579 }
580 impl TryInto<Val> for #ident {
581 type Error = LocError;
582 fn try_into(self) -> Result<Val, Self::Error> {
583 let mut out = ObjValueBuilder::new();
584 self.serialize(&mut out)?;
585 Ok(Val::Obj(out.build()))
586 }
587 }
588 ()
589 };608 };
590 })609 })
591}610}