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

difftreelog

refactor switch gc to gcmodule

Yaroslav Bolyukin2021-11-27parent: #09a4bd7.patch.diff
in: master

39 files changed

modified.github/workflows/release.ymldiffbeforeafterboth
21 args: --all21 args: --all
2222
23 cargo-release:23 cargo-release:
24 if: startsWith(github.ref, 'refs/tags/')24 if: startsWith(github.ref, 'refs/tags/') && !endsWith(github.ref, '-test')
25 needs: [test]25 needs: [test]
26 runs-on: ubuntu-latest26 runs-on: ubuntu-latest
27 steps:27 steps:
modifiedCargo.tomldiffbeforeafterboth
1[workspace]1[workspace]
2members = [2members = [
3 "crates/jrsonnet-interner",
4 "crates/jrsonnet-parser",
5 "crates/jrsonnet-evaluator",
6 "crates/jrsonnet-stdlib",
7 "crates/jrsonnet-cli",3 "crates/*",
8 "crates/jrsonnet-types",
9 "bindings/jsonnet",4 "bindings/jsonnet",
10 "cmds/jrsonnet",5 "cmds/jrsonnet",
11]6]
modifiedbindings/jsonnet/Cargo.tomldiffbeforeafterboth
10[dependencies]10[dependencies]
11jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "0.4.2" }11jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "0.4.2" }
12jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.4.2" }12jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.4.2" }
13jrsonnet-gc = { version = "0.4.2", features = ["derive"] }13gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
1414
15[lib]15[lib]
16crate-type = ["cdylib"]16crate-type = ["cdylib"]
modifiedbindings/jsonnet/src/native.rsdiffbeforeafterboth
1use gcmodule::Cc;
1use jrsonnet_evaluator::{2use jrsonnet_evaluator::{
2 error::{Error, LocError},3 error::{Error, LocError},
4 gc::TraceBox,
3 native::{NativeCallback, NativeCallbackHandler},5 native::{NativeCallback, NativeCallbackHandler},
4 EvaluationState, Val,6 EvaluationState, Val,
5};7};
6use jrsonnet_gc::{unsafe_empty_trace, Finalize, Gc, Trace};
7use jrsonnet_parser::{Param, ParamsDesc};8use jrsonnet_parser::{Param, ParamsDesc};
8use std::{9use std::{
9 ffi::{c_void, CStr},10 ffi::{c_void, CStr},
18 success: *mut c_int,19 success: *mut c_int,
19) -> *mut Val;20) -> *mut Val;
2021
22#[derive(gcmodule::Trace)]
21struct JsonnetNativeCallbackHandler {23struct JsonnetNativeCallbackHandler {
24 #[skip_trace]
22 ctx: *const c_void,25 ctx: *const c_void,
26 #[skip_trace]
23 cb: JsonnetNativeCallback,27 cb: JsonnetNativeCallback,
24}28}
25impl Finalize for JsonnetNativeCallbackHandler {}
26unsafe impl Trace for JsonnetNativeCallbackHandler {
27 unsafe_empty_trace!();
28}
29impl NativeCallbackHandler for JsonnetNativeCallbackHandler {29impl NativeCallbackHandler for JsonnetNativeCallbackHandler {
30 fn call(&self, _from: Option<Rc<Path>>, args: &[Val]) -> Result<Val, LocError> {30 fn call(&self, _from: Rc<Path>, args: &[Val]) -> Result<Val, LocError> {
31 let mut n_args = Vec::new();31 let mut n_args = Vec::new();
32 for a in args {32 for a in args {
33 n_args.push(Some(Box::new(a.clone())));33 n_args.push(Some(Box::new(a.clone())));
7474
75 vm.add_native(75 vm.add_native(
76 name,76 name,
77 Gc::new(NativeCallback::new(77 Cc::new(NativeCallback::new(
78 params,78 params,
79 Box::new(JsonnetNativeCallbackHandler { ctx, cb }),79 TraceBox(Box::new(JsonnetNativeCallbackHandler { ctx, cb })),
80 )),80 )),
81 )81 )
82}82}
modifiedbindings/jsonnet/src/val_make.rsdiffbeforeafterboth
1//! Create values in VM1//! Create values in VM
22
3use gcmodule::Cc;
3use jrsonnet_evaluator::{ArrValue, EvaluationState, ObjValue, Val};4use jrsonnet_evaluator::{ArrValue, EvaluationState, ObjValue, Val};
4use jrsonnet_gc::Gc;
5use std::{5use std::{
6 ffi::CStr,6 ffi::CStr,
7 os::raw::{c_char, c_double, c_int},7 os::raw::{c_char, c_double, c_int},
3838
39#[no_mangle]39#[no_mangle]
40pub extern "C" fn jsonnet_json_make_array(_vm: &EvaluationState) -> *mut Val {40pub extern "C" fn jsonnet_json_make_array(_vm: &EvaluationState) -> *mut Val {
41 Box::into_raw(Box::new(Val::Arr(ArrValue::Eager(Gc::new(Vec::new())))))41 Box::into_raw(Box::new(Val::Arr(ArrValue::Eager(Cc::new(Vec::new())))))
42}42}
4343
44#[no_mangle]44#[no_mangle]
modifiedbindings/jsonnet/src/val_modify.rsdiffbeforeafterboth
2//! Only tested with variables, which haven't altered by code before appearing here2//! Only tested with variables, which haven't altered by code before appearing here
3//! In jrsonnet every value is immutable, and this code is probally broken3//! In jrsonnet every value is immutable, and this code is probally broken
44
5use gcmodule::Cc;
5use jrsonnet_evaluator::{ArrValue, EvaluationState, LazyBinding, LazyVal, ObjMember, Val};6use jrsonnet_evaluator::{ArrValue, EvaluationState, LazyBinding, LazyVal, ObjMember, Val};
6use jrsonnet_gc::Gc;
7use jrsonnet_parser::Visibility;7use jrsonnet_parser::Visibility;
8use std::{ffi::CStr, os::raw::c_char};8use std::{ffi::CStr, os::raw::c_char};
99
23 new.push(item);23 new.push(item);
24 }24 }
25 new.push(LazyVal::new_resolved(val.clone()));25 new.push(LazyVal::new_resolved(val.clone()));
26 *arr = Val::Arr(ArrValue::Lazy(Gc::new(new)));26 *arr = Val::Arr(ArrValue::Lazy(Cc::new(new)));
27 }27 }
28 _ => panic!("should receive array"),28 _ => panic!("should receive array"),
29 }29 }
modifiedcmds/jrsonnet/Cargo.tomldiffbeforeafterboth
17jrsonnet-cli = { path = "../../crates/jrsonnet-cli", version = "0.4.2" }17jrsonnet-cli = { path = "../../crates/jrsonnet-cli", version = "0.4.2" }
18mimallocator = { version = "0.1.3", optional = true }18mimallocator = { version = "0.1.3", optional = true }
19thiserror = "1.0"19thiserror = "1.0"
20gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
2021
21[dependencies.clap]22[dependencies.clap]
22git = "https://github.com/clap-rs/clap"23git = "https://github.com/clap-rs/clap"
modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
136136
137 let val = if opts.input.exec {137 let val = if opts.input.exec {
138 state.evaluate_snippet_raw(138 state.evaluate_snippet_raw(
139 PathBuf::from("args").into(),139 PathBuf::from("<cmdline>").into(),
140 (&opts.input.input as &str).into(),140 (&opts.input.input as &str).into(),
141 )?141 )?
142 } else if opts.input.input == "-" {142 } else if opts.input.input == "-" {
modifiedcrates/jrsonnet-cli/Cargo.tomldiffbeforeafterboth
12 "explaining-traces",12 "explaining-traces",
13] }13] }
14jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.4.2" }14jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.4.2" }
15jrsonnet-gc = { version = "0.4.2", features = [15gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
16 "derive",
17 "unstable-config",
18 "unstable-stats",
19] }
2016
21[dependencies.clap]17[dependencies.clap]
22git = "https://github.com/clap-rs/clap"18git = "https://github.com/clap-rs/clap"
modifiedcrates/jrsonnet-cli/src/lib.rsdiffbeforeafterboth
103#[derive(Clap)]103#[derive(Clap)]
104#[clap(help_heading = "GARBAGE COLLECTION")]104#[clap(help_heading = "GARBAGE COLLECTION")]
105pub struct GcOpts {105pub struct GcOpts {
106 /// Min bytes allocated to start garbage collection
107 #[clap(long, default_value = "20000000")]
108 gc_initial_threshold: usize,
109 /// How much heap should grow after unsuccessful garbage collection
110 #[clap(long)]
111 gc_used_space_ratio: Option<f64>,
112 /// Do not skip gc on exit106 /// Do not skip gc on exit
113 #[clap(long)]107 #[clap(long)]
114 gc_collect_on_exit: bool,108 gc_collect_on_exit: bool,
122 gc_collect_before_printing_stats: bool,116 gc_collect_before_printing_stats: bool,
123}117}
124impl GcOpts {118impl GcOpts {
119 pub fn configure_global(&self) {
120 if !self.gc_collect_on_exit {
121 gcmodule::set_thread_collect_on_drop(false)
122 }
123 }
125 pub fn stats_printer(&self) -> Option<GcStatsPrinter> {124 pub fn stats_printer(&self) -> Option<GcStatsPrinter> {
126 self.gc_print_stats125 self.gc_print_stats.then(|| GcStatsPrinter {
127 .then(|| GcStatsPrinter(self.gc_collect_before_printing_stats))126 collect_before_printing_stats: self.gc_collect_before_printing_stats,
127 })
128 }128 }
129 pub fn configure_global(&self) {
130 jrsonnet_gc::configure(|config| {
131 config.leak_on_drop = !self.gc_collect_on_exit;
132 config.threshold = self.gc_initial_threshold;
133 if let Some(used_space_ratio) = self.gc_used_space_ratio {
134 config.used_space_ratio = used_space_ratio;
135 }
136 });
137 }
138}129}
130
139pub struct GcStatsPrinter(bool);131pub struct GcStatsPrinter {
132 collect_before_printing_stats: bool,
133}
140impl Drop for GcStatsPrinter {134impl Drop for GcStatsPrinter {
141 fn drop(&mut self) {135 fn drop(&mut self) {
142 if self.0 {
143 jrsonnet_gc::force_collect()
144 }
145 eprintln!("=== GC STATS ===");136 eprintln!("=== GC STATS ===");
146 jrsonnet_gc::configure(|c| {137 if self.collect_before_printing_stats {
147 eprintln!("Final threshold: {:?}", c.threshold);
148 });
149 let stats = jrsonnet_gc::stats();138 let collected = gcmodule::collect_thread_cycles();
150 eprintln!("Collections performed: {}", stats.collections_performed);139 eprintln!("Collected: {}", collected);
140 }
151 eprintln!("Bytes still allocated: {}", stats.bytes_allocated);141 eprintln!("Tracked: {}", gcmodule::count_thread_tracked())
152 }142 }
153}143}
154144
modifiedcrates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth
32rustc-hash = "1.1.0"32rustc-hash = "1.1.0"
3333
34thiserror = "1.0"34thiserror = "1.0"
35jrsonnet-gc = { version = "0.4.2", features = ["derive"] }35gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
3636
37[dependencies.anyhow]37[dependencies.anyhow]
38version = "1.0"38version = "1.0"
5353
54# Explaining traces54# Explaining traces
55[dependencies.annotate-snippets]55[dependencies.annotate-snippets]
56version = "0.9.0"56version = "0.9.1"
57features = ["color"]57features = ["color"]
58optional = true58optional = true
5959
modifiedcrates/jrsonnet-evaluator/build.rsdiffbeforeafterboth
13 STDLIB_STR,13 STDLIB_STR,
14 &ParserSettings {14 &ParserSettings {
15 file_name: PathBuf::from("std.jsonnet").into(),15 file_name: PathBuf::from("std.jsonnet").into(),
16 loc_data: true,
17 },16 },
18 )17 )
19 .expect("parse");18 .expect("parse");
modifiedcrates/jrsonnet-evaluator/src/builtin/format.rsdiffbeforeafterboth
2#![allow(clippy::too_many_arguments)]2#![allow(clippy::too_many_arguments)]
33
4use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val};4use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val};
5use jrsonnet_gc::Trace;5use gcmodule::Trace;
6use jrsonnet_interner::IStr;6use jrsonnet_interner::IStr;
7use jrsonnet_types::ValType;7use jrsonnet_types::ValType;
8use thiserror::Error;8use thiserror::Error;
99
10#[derive(Debug, Clone, Error, Trace)]10#[derive(Debug, Clone, Error, Trace)]
11#[trivially_drop]
12pub enum FormatError {11pub enum FormatError {
13 #[error("truncated format code")]12 #[error("truncated format code")]
14 TruncatedFormatCode,13 TruncatedFormatCode,
modifiedcrates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth
1use crate::error::Error::*;1use crate::error::Error::*;
2use crate::error::Result;2use crate::error::Result;
3use crate::push_frame;3use crate::push_description_frame;
4use crate::{throw, Val};4use crate::{throw, Val};
55
6#[derive(PartialEq, Clone, Copy)]6#[derive(PartialEq, Clone, Copy)]
103 buf.push_str(cur_padding);103 buf.push_str(cur_padding);
104 escape_string_json_buf(&field, buf);104 escape_string_json_buf(&field, buf);
105 buf.push_str(": ");105 buf.push_str(": ");
106 push_frame(106 push_description_frame(
107 None,
108 || format!("field <{}> manifestification", field.clone()),107 || format!("field <{}> manifestification", field.clone()),
109 || {108 || {
110 let value = obj.get(field.clone())?.unwrap();109 let value = obj.get(field.clone())?.unwrap();
modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
7 EvaluationState, FuncVal, IndexableVal, LazyVal, Val,7 EvaluationState, FuncVal, IndexableVal, LazyVal, Val,
8};8};
9use format::{format_arr, format_obj};9use format::{format_arr, format_obj};
10use jrsonnet_gc::Gc;10use gcmodule::Cc;
11use jrsonnet_interner::IStr;11use jrsonnet_interner::IStr;
12use jrsonnet_parser::{ArgsDesc, ExprLocation};12use jrsonnet_parser::{ArgsDesc, ExprLocation};
13use jrsonnet_types::ty;13use jrsonnet_types::ty;
2424
25pub fn std_format(str: IStr, vals: Val) -> Result<Val> {25pub fn std_format(str: IStr, vals: Val) -> Result<Val> {
26 push_frame(26 push_frame(
27 Some(&ExprLocation(Rc::from(PathBuf::from("std.jsonnet")), 0, 0)),27 &ExprLocation(Rc::from(PathBuf::from("std.jsonnet")), 0, 0),
28 || format!("std.format of {}", str),28 || format!("std.format of {}", str),
29 || {29 || {
30 Ok(match vals {30 Ok(match vals {
68 }68 }
69}69}
7070
71type Builtin = fn(context: Context, loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val>;71type Builtin = fn(context: Context, loc: &ExprLocation, args: &ArgsDesc) -> Result<Val>;
7272
73type BuiltinsType = HashMap<Box<str>, Builtin>;73type BuiltinsType = HashMap<Box<str>, Builtin>;
7474
136 };136 };
137}137}
138138
139fn builtin_length(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {139fn builtin_length(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
140 parse_args!(context, "length", args, 1, [140 parse_args!(context, "length", args, 1, [
141 0, x: ty!((string | object | array));141 0, x: ty!((string | object | array));
142 ], {142 ], {
154 })154 })
155}155}
156156
157fn builtin_type(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {157fn builtin_type(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
158 parse_args!(context, "type", args, 1, [158 parse_args!(context, "type", args, 1, [
159 0, x: ty!(any);159 0, x: ty!(any);
160 ], {160 ], {
164164
165fn builtin_make_array(165fn builtin_make_array(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
166 context: Context,
167 _loc: Option<&ExprLocation>,
168 args: &ArgsDesc,
169) -> Result<Val> {
170 parse_args!(context, "makeArray", args, 2, [166 parse_args!(context, "makeArray", args, 2, [
184180
185fn builtin_codepoint(181fn builtin_codepoint(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
186 context: Context,
187 _loc: Option<&ExprLocation>,
188 args: &ArgsDesc,
189) -> Result<Val> {
190 parse_args!(context, "codepoint", args, 1, [182 parse_args!(context, "codepoint", args, 1, [
196188
197fn builtin_object_fields_ex(189fn builtin_object_fields_ex(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
198 context: Context,
199 _loc: Option<&ExprLocation>,
200 args: &ArgsDesc,
201) -> Result<Val> {
202 parse_args!(context, "objectFieldsEx", args, 2, [190 parse_args!(context, "objectFieldsEx", args, 2, [
210198
211fn builtin_object_has_ex(199fn builtin_object_has_ex(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
212 context: Context,
213 _loc: Option<&ExprLocation>,
214 args: &ArgsDesc,
215) -> Result<Val> {
216 parse_args!(context, "objectHasEx", args, 3, [200 parse_args!(context, "objectHasEx", args, 3, [
224208
225fn builtin_parse_json(209fn builtin_parse_json(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
226 context: Context,
227 _loc: Option<&ExprLocation>,
228 args: &ArgsDesc,
229) -> Result<Val> {
230 parse_args!(context, "parseJson", args, 1, [210 parse_args!(context, "parseJson", args, 1, [
236 })216 })
237}217}
238218
239fn builtin_slice(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {219fn builtin_slice(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
240 parse_args!(context, "slice", args, 4, [220 parse_args!(context, "slice", args, 4, [
241 0, indexable: ty!((string | array));221 0, indexable: ty!((string | array));
242 1, index: ty!((number | null));222 1, index: ty!((number | null));
252 })232 })
253}233}
254234
255fn builtin_substr(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {235fn builtin_substr(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
256 parse_args!(context, "substr", args, 3, [236 parse_args!(context, "substr", args, 3, [
257 0, str: ty!(string) => Val::Str;237 0, str: ty!(string) => Val::Str;
258 1, from: ty!(BoundedNumber<(Some(0.0)), (None)>) => Val::Num;238 1, from: ty!(BoundedNumber<(Some(0.0)), (None)>) => Val::Num;
265245
266fn builtin_primitive_equals(246fn builtin_primitive_equals(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
267 context: Context,
268 _loc: Option<&ExprLocation>,
269 args: &ArgsDesc,
270) -> Result<Val> {
271 parse_args!(context, "primitiveEquals", args, 2, [247 parse_args!(context, "primitiveEquals", args, 2, [
276 })252 })
277}253}
278254
279fn builtin_equals(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {255fn builtin_equals(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
280 parse_args!(context, "equals", args, 2, [256 parse_args!(context, "equals", args, 2, [
281 0, a: ty!(any);257 0, a: ty!(any);
282 1, b: ty!(any);258 1, b: ty!(any);
285 })261 })
286}262}
287263
288fn builtin_modulo(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {264fn builtin_modulo(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
289 parse_args!(context, "modulo", args, 2, [265 parse_args!(context, "modulo", args, 2, [
290 0, a: ty!(number) => Val::Num;266 0, a: ty!(number) => Val::Num;
291 1, b: ty!(number) => Val::Num;267 1, b: ty!(number) => Val::Num;
294 })270 })
295}271}
296272
297fn builtin_mod(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {273fn builtin_mod(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
298 parse_args!(context, "mod", args, 2, [274 parse_args!(context, "mod", args, 2, [
299 0, a: ty!((number | string));275 0, a: ty!((number | string));
300 1, b: ty!(any);276 1, b: ty!(any);
303 })279 })
304}280}
305281
306fn builtin_floor(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {282fn builtin_floor(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
307 parse_args!(context, "floor", args, 1, [283 parse_args!(context, "floor", args, 1, [
308 0, x: ty!(number) => Val::Num;284 0, x: ty!(number) => Val::Num;
309 ], {285 ], {
310 Ok(Val::Num(x.floor()))286 Ok(Val::Num(x.floor()))
311 })287 })
312}288}
313289
314fn builtin_ceil(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {290fn builtin_ceil(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
315 parse_args!(context, "ceil", args, 1, [291 parse_args!(context, "ceil", args, 1, [
316 0, x: ty!(number) => Val::Num;292 0, x: ty!(number) => Val::Num;
317 ], {293 ], {
318 Ok(Val::Num(x.ceil()))294 Ok(Val::Num(x.ceil()))
319 })295 })
320}296}
321297
322fn builtin_log(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {298fn builtin_log(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
323 parse_args!(context, "log", args, 1, [299 parse_args!(context, "log", args, 1, [
324 0, n: ty!(number) => Val::Num;300 0, n: ty!(number) => Val::Num;
325 ], {301 ], {
326 Ok(Val::Num(n.ln()))302 Ok(Val::Num(n.ln()))
327 })303 })
328}304}
329305
330fn builtin_pow(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {306fn builtin_pow(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
331 parse_args!(context, "pow", args, 2, [307 parse_args!(context, "pow", args, 2, [
332 0, x: ty!(number) => Val::Num;308 0, x: ty!(number) => Val::Num;
333 1, n: ty!(number) => Val::Num;309 1, n: ty!(number) => Val::Num;
336 })312 })
337}313}
338314
339fn builtin_sqrt(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {315fn builtin_sqrt(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
340 parse_args!(context, "sqrt", args, 1, [316 parse_args!(context, "sqrt", args, 1, [
341 0, x: ty!(BoundedNumber<(Some(0.0)), (None)>) => Val::Num;317 0, x: ty!(BoundedNumber<(Some(0.0)), (None)>) => Val::Num;
342 ], {318 ], {
343 Ok(Val::Num(x.sqrt()))319 Ok(Val::Num(x.sqrt()))
344 })320 })
345}321}
346322
347fn builtin_sin(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {323fn builtin_sin(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
348 parse_args!(context, "sin", args, 1, [324 parse_args!(context, "sin", args, 1, [
349 0, x: ty!(number) => Val::Num;325 0, x: ty!(number) => Val::Num;
350 ], {326 ], {
351 Ok(Val::Num(x.sin()))327 Ok(Val::Num(x.sin()))
352 })328 })
353}329}
354330
355fn builtin_cos(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {331fn builtin_cos(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
356 parse_args!(context, "cos", args, 1, [332 parse_args!(context, "cos", args, 1, [
357 0, x: ty!(number) => Val::Num;333 0, x: ty!(number) => Val::Num;
358 ], {334 ], {
359 Ok(Val::Num(x.cos()))335 Ok(Val::Num(x.cos()))
360 })336 })
361}337}
362338
363fn builtin_tan(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {339fn builtin_tan(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
364 parse_args!(context, "tan", args, 1, [340 parse_args!(context, "tan", args, 1, [
365 0, x: ty!(number) => Val::Num;341 0, x: ty!(number) => Val::Num;
366 ], {342 ], {
367 Ok(Val::Num(x.tan()))343 Ok(Val::Num(x.tan()))
368 })344 })
369}345}
370346
371fn builtin_asin(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {347fn builtin_asin(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
372 parse_args!(context, "asin", args, 1, [348 parse_args!(context, "asin", args, 1, [
373 0, x: ty!(number) => Val::Num;349 0, x: ty!(number) => Val::Num;
374 ], {350 ], {
375 Ok(Val::Num(x.asin()))351 Ok(Val::Num(x.asin()))
376 })352 })
377}353}
378354
379fn builtin_acos(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {355fn builtin_acos(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
380 parse_args!(context, "acos", args, 1, [356 parse_args!(context, "acos", args, 1, [
381 0, x: ty!(number) => Val::Num;357 0, x: ty!(number) => Val::Num;
382 ], {358 ], {
383 Ok(Val::Num(x.acos()))359 Ok(Val::Num(x.acos()))
384 })360 })
385}361}
386362
387fn builtin_atan(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {363fn builtin_atan(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
388 parse_args!(context, "atan", args, 1, [364 parse_args!(context, "atan", args, 1, [
389 0, x: ty!(number) => Val::Num;365 0, x: ty!(number) => Val::Num;
390 ], {366 ], {
391 Ok(Val::Num(x.atan()))367 Ok(Val::Num(x.atan()))
392 })368 })
393}369}
394370
395fn builtin_exp(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {371fn builtin_exp(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
396 parse_args!(context, "exp", args, 1, [372 parse_args!(context, "exp", args, 1, [
397 0, x: ty!(number) => Val::Num;373 0, x: ty!(number) => Val::Num;
398 ], {374 ], {
411 }387 }
412}388}
413389
414fn builtin_mantissa(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {390fn builtin_mantissa(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
415 parse_args!(context, "mantissa", args, 1, [391 parse_args!(context, "mantissa", args, 1, [
416 0, x: ty!(number) => Val::Num;392 0, x: ty!(number) => Val::Num;
417 ], {393 ], {
418 Ok(Val::Num(frexp(x).0))394 Ok(Val::Num(frexp(x).0))
419 })395 })
420}396}
421397
422fn builtin_exponent(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {398fn builtin_exponent(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
423 parse_args!(context, "exponent", args, 1, [399 parse_args!(context, "exponent", args, 1, [
424 0, x: ty!(number) => Val::Num;400 0, x: ty!(number) => Val::Num;
425 ], {401 ], {
426 Ok(Val::Num(frexp(x).1.into()))402 Ok(Val::Num(frexp(x).1.into()))
427 })403 })
428}404}
429405
430fn builtin_ext_var(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {406fn builtin_ext_var(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
431 parse_args!(context, "extVar", args, 1, [407 parse_args!(context, "extVar", args, 1, [
432 0, x: ty!(string) => Val::Str;408 0, x: ty!(string) => Val::Str;
433 ], {409 ], {
434 Ok(with_state(|s| s.settings().ext_vars.get(&x).cloned()).ok_or(UndefinedExternalVariable(x))?)410 Ok(with_state(|s| s.settings().ext_vars.get(&x).cloned()).ok_or(UndefinedExternalVariable(x))?)
435 })411 })
436}412}
437413
438fn builtin_native(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {414fn builtin_native(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
439 parse_args!(context, "native", args, 1, [415 parse_args!(context, "native", args, 1, [
440 0, x: ty!(string) => Val::Str;416 0, x: ty!(string) => Val::Str;
441 ], {417 ], {
442 Ok(with_state(|s| s.settings().ext_natives.get(&x).cloned()).map(|v| Val::Func(Gc::new(FuncVal::NativeExt(x.clone(), v)))).ok_or(UndefinedExternalFunction(x))?)418 Ok(with_state(|s| s.settings().ext_natives.get(&x).cloned()).map(|v| Val::Func(Cc::new(FuncVal::NativeExt(x.clone(), v)))).ok_or(UndefinedExternalFunction(x))?)
443 })419 })
444}420}
445421
446fn builtin_filter(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {422fn builtin_filter(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
447 parse_args!(context, "filter", args, 2, [423 parse_args!(context, "filter", args, 2, [
448 0, func: ty!(function) => Val::Func;424 0, func: ty!(function) => Val::Func;
449 1, arr: ty!(array) => Val::Arr;425 1, arr: ty!(array) => Val::Arr;
454 })430 })
455}431}
456432
457fn builtin_map(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {433fn builtin_map(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
458 parse_args!(context, "map", args, 2, [434 parse_args!(context, "map", args, 2, [
459 0, func: ty!(function) => Val::Func;435 0, func: ty!(function) => Val::Func;
460 1, arr: ty!(array) => Val::Arr;436 1, arr: ty!(array) => Val::Arr;
464 })440 })
465}441}
466442
467fn builtin_flatmap(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {443fn builtin_flatmap(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
468 parse_args!(context, "flatMap", args, 2, [444 parse_args!(context, "flatMap", args, 2, [
469 0, func: ty!(function) => Val::Func;445 0, func: ty!(function) => Val::Func;
470 1, arr: ty!((array | string));446 1, arr: ty!((array | string));
498 })474 })
499}475}
500476
501fn builtin_foldl(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {477fn builtin_foldl(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
502 parse_args!(context, "foldl", args, 3, [478 parse_args!(context, "foldl", args, 3, [
503 0, func: ty!(function) => Val::Func;479 0, func: ty!(function) => Val::Func;
504 1, arr: ty!(array) => Val::Arr;480 1, arr: ty!(array) => Val::Arr;
512 })488 })
513}489}
514490
515fn builtin_foldr(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {491fn builtin_foldr(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
516 parse_args!(context, "foldr", args, 3, [492 parse_args!(context, "foldr", args, 3, [
517 0, func: ty!(function) => Val::Func;493 0, func: ty!(function) => Val::Func;
518 1, arr: ty!(array) => Val::Arr;494 1, arr: ty!(array) => Val::Arr;
529#[allow(non_snake_case)]505#[allow(non_snake_case)]
530fn builtin_sort_impl(506fn builtin_sort_impl(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
531 context: Context,
532 _loc: Option<&ExprLocation>,
533 args: &ArgsDesc,
534) -> Result<Val> {
535 parse_args!(context, "sort", args, 2, [507 parse_args!(context, "sort", args, 2, [
543 })515 })
544}516}
545517
546fn builtin_format(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {518fn builtin_format(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
547 parse_args!(context, "format", args, 2, [519 parse_args!(context, "format", args, 2, [
548 0, str: ty!(string) => Val::Str;520 0, str: ty!(string) => Val::Str;
549 1, vals: ty!(any)521 1, vals: ty!(any)
552 })524 })
553}525}
554526
555fn builtin_range(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {527fn builtin_range(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
556 parse_args!(context, "range", args, 2, [528 parse_args!(context, "range", args, 2, [
557 0, from: ty!(number) => Val::Num;529 0, from: ty!(number) => Val::Num;
558 1, to: ty!(number) => Val::Num;530 1, to: ty!(number) => Val::Num;
568 })540 })
569}541}
570542
571fn builtin_char(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {543fn builtin_char(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
572 parse_args!(context, "char", args, 1, [544 parse_args!(context, "char", args, 1, [
573 0, n: ty!(number) => Val::Num;545 0, n: ty!(number) => Val::Num;
574 ], {546 ], {
582554
583fn builtin_encode_utf8(555fn builtin_encode_utf8(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
584 context: Context,
585 _loc: Option<&ExprLocation>,
586 args: &ArgsDesc,
587) -> Result<Val> {
588 parse_args!(context, "encodeUTF8", args, 1, [556 parse_args!(context, "encodeUTF8", args, 1, [
594562
595fn builtin_decode_utf8(563fn builtin_decode_utf8(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
596 context: Context,
597 _loc: Option<&ExprLocation>,
598 args: &ArgsDesc,
599) -> Result<Val> {
600 parse_args!(context, "decodeUTF8", args, 1, [564 parse_args!(context, "decodeUTF8", args, 1, [
609 })573 })
610}574}
611575
612fn builtin_md5(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {576fn builtin_md5(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
613 parse_args!(context, "md5", args, 1, [577 parse_args!(context, "md5", args, 1, [
614 0, str: ty!(string) => Val::Str;578 0, str: ty!(string) => Val::Str;
615 ], {579 ], {
616 Ok(Val::Str(format!("{:x}", md5::compute(&str.as_bytes())).into()))580 Ok(Val::Str(format!("{:x}", md5::compute(&str.as_bytes())).into()))
617 })581 })
618}582}
619583
620fn builtin_trace(context: Context, loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {584fn builtin_trace(context: Context, loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
621 parse_args!(context, "trace", args, 2, [585 parse_args!(context, "trace", args, 2, [
622 0, str: ty!(string) => Val::Str;586 0, str: ty!(string) => Val::Str;
623 1, rest: ty!(any);587 1, rest: ty!(any);
624 ], {588 ], {
625 eprint!("TRACE:");589 eprint!("TRACE:");
626 if let Some(loc) = loc {
627 with_state(|s|{590 with_state(|s|{
628 let locs = s.map_source_locations(&loc.0, &[loc.1]);591 let locs = s.map_source_locations(&loc.0, &[loc.1]);
629 eprint!(" {}:{}", loc.0.file_name().unwrap().to_str().unwrap(), locs[0].line);592 eprint!(" {}:{}", loc.0.file_name().unwrap().to_str().unwrap(), locs[0].line);
630 });593 });
631 }
632 eprintln!(" {}", str);594 eprintln!(" {}", str);
633 Ok(rest)595 Ok(rest)
634 })596 })
635}597}
636598
637fn builtin_base64(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {599fn builtin_base64(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
638 parse_args!(context, "base64", args, 1, [600 parse_args!(context, "base64", args, 1, [
639 0, input: ty!((string | (Array<number>)));601 0, input: ty!((string | (Array<number>)));
640 ], {602 ], {
654616
655fn builtin_base64_decode_bytes(617fn builtin_base64_decode_bytes(
656 context: Context,618 context: Context,
657 _loc: Option<&ExprLocation>,619 _loc: &ExprLocation,
658 args: &ArgsDesc,620 args: &ArgsDesc,
659) -> Result<Val> {621) -> Result<Val> {
660 parse_args!(context, "base64DecodeBytes", args, 1, [622 parse_args!(context, "base64DecodeBytes", args, 1, [
671633
672fn builtin_base64_decode(634fn builtin_base64_decode(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
673 context: Context,
674 _loc: Option<&ExprLocation>,
675 args: &ArgsDesc,
676) -> Result<Val> {
677 parse_args!(context, "base64Decode", args, 1, [635 parse_args!(context, "base64Decode", args, 1, [
685 })643 })
686}644}
687645
688fn builtin_join(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {646fn builtin_join(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
689 parse_args!(context, "join", args, 2, [647 parse_args!(context, "join", args, 2, [
690 0, sep: ty!((string | array));648 0, sep: ty!((string | array));
691 1, arr: ty!(array) => Val::Arr;649 1, arr: ty!(array) => Val::Arr;
744702
745fn builtin_escape_string_json(703fn builtin_escape_string_json(
746 context: Context,704 context: Context,
747 _loc: Option<&ExprLocation>,705 _loc: &ExprLocation,
748 args: &ArgsDesc,706 args: &ArgsDesc,
749) -> Result<Val> {707) -> Result<Val> {
750 parse_args!(context, "escapeStringJson", args, 1, [708 parse_args!(context, "escapeStringJson", args, 1, [
756714
757fn builtin_manifest_json_ex(715fn builtin_manifest_json_ex(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
758 context: Context,
759 _loc: Option<&ExprLocation>,
760 args: &ArgsDesc,
761) -> Result<Val> {
762 parse_args!(context, "manifestJsonEx", args, 2, [716 parse_args!(context, "manifestJsonEx", args, 2, [
772726
773fn builtin_manifest_yaml_doc(727fn builtin_manifest_yaml_doc(
774 context: Context,728 context: Context,
775 _loc: Option<&ExprLocation>,729 _loc: &ExprLocation,
776 args: &ArgsDesc,730 args: &ArgsDesc,
777) -> Result<Val> {731) -> Result<Val> {
778 parse_args!(context, "manifestYamlDoc", args, 2, [732 parse_args!(context, "manifestYamlDoc", args, 2, [
786 })740 })
787}741}
788742
789fn builtin_reverse(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {743fn builtin_reverse(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
790 parse_args!(context, "reverse", args, 1, [744 parse_args!(context, "reverse", args, 1, [
791 0, value: ty!(array) => Val::Arr;745 0, value: ty!(array) => Val::Arr;
792 ], {746 ], {
793 Ok(Val::Arr(value.reversed()))747 Ok(Val::Arr(value.reversed()))
794 })748 })
795}749}
796750
797fn builtin_id(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {751fn builtin_id(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
798 parse_args!(context, "id", args, 1, [752 parse_args!(context, "id", args, 1, [
799 0, v: ty!(any);753 0, v: ty!(any);
800 ], {754 ], {
804758
805fn builtin_str_replace(759fn builtin_str_replace(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
806 context: Context,
807 _loc: Option<&ExprLocation>,
808 args: &ArgsDesc,
809) -> Result<Val> {
810 parse_args!(context, "strReplace", args, 3, [760 parse_args!(context, "strReplace", args, 3, [
818768
819fn builtin_splitlimit(769fn builtin_splitlimit(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
820 context: Context,
821 _loc: Option<&ExprLocation>,
822 args: &ArgsDesc,
823) -> Result<Val> {
824 parse_args!(context, "splitLimit", args, 3, [770 parse_args!(context, "splitLimit", args, 3, [
841787
842fn builtin_ascii_upper(788fn builtin_ascii_upper(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
843 context: Context,
844 _loc: Option<&ExprLocation>,
845 args: &ArgsDesc,
846) -> Result<Val> {
847 parse_args!(context, "asciiUpper", args, 1, [789 parse_args!(context, "asciiUpper", args, 1, [
853795
854fn builtin_ascii_lower(796fn builtin_ascii_lower(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
855 context: Context,
856 _loc: Option<&ExprLocation>,
857 args: &ArgsDesc,
858) -> Result<Val> {
859 parse_args!(context, "asciiLower", args, 1, [797 parse_args!(context, "asciiLower", args, 1, [
863 })801 })
864}802}
865803
866fn builtin_member(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {804fn builtin_member(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
867 parse_args!(context, "member", args, 2, [805 parse_args!(context, "member", args, 2, [
868 0, arr: ty!((array | string));806 0, arr: ty!((array | string));
869 1, x: ty!(any);807 1, x: ty!(any);
887 })825 })
888}826}
889827
890fn builtin_count(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {828fn builtin_count(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
891 parse_args!(context, "count", args, 2, [829 parse_args!(context, "count", args, 2, [
892 0, arr: ty!(array) => Val::Arr;830 0, arr: ty!(array) => Val::Arr;
893 1, x: ty!(any);831 1, x: ty!(any);
905843
906pub fn call_builtin(844pub fn call_builtin(
907 context: Context,845 context: Context,
908 loc: Option<&ExprLocation>,846 loc: &ExprLocation,
909 name: &str,847 name: &str,
910 args: &ArgsDesc,848 args: &ArgsDesc,
911) -> Result<Val> {849) -> Result<Val> {
modifiedcrates/jrsonnet-evaluator/src/builtin/sort.rsdiffbeforeafterboth
2 error::{Error, LocError, Result},2 error::{Error, LocError, Result},
3 throw, Context, FuncVal, Val,3 throw, Context, FuncVal, Val,
4};4};
5use jrsonnet_gc::{Finalize, Gc, Trace};5use gcmodule::{Cc, Trace};
66
7#[derive(Debug, Clone, thiserror::Error, Trace, Finalize)]7#[derive(Debug, Clone, thiserror::Error, Trace)]
8pub enum SortError {8pub enum SortError {
9 #[error("sort key should be string or number")]9 #[error("sort key should be string or number")]
10 SortKeyShouldBeStringOrNumber,10 SortKeyShouldBeStringOrNumber,
59 Ok(sort_type)59 Ok(sort_type)
60}60}
6161
62pub fn sort(ctx: Context, values: Gc<Vec<Val>>, key_getter: &FuncVal) -> Result<Gc<Vec<Val>>> {62pub fn sort(ctx: Context, values: Cc<Vec<Val>>, key_getter: &FuncVal) -> Result<Cc<Vec<Val>>> {
63 if values.len() <= 1 {63 if values.len() <= 1 {
64 return Ok(values);64 return Ok(values);
65 }65 }
77 }),77 }),
78 SortKeyType::Unknown => unreachable!(),78 SortKeyType::Unknown => unreachable!(),
79 };79 };
80 Ok(Gc::new(mvalues))80 Ok(Cc::new(mvalues))
81 } else {81 } else {
82 let mut vk = Vec::with_capacity(values.len());82 let mut vk = Vec::with_capacity(values.len());
83 for value in values.iter() {83 for value in values.iter() {
98 }),98 }),
99 SortKeyType::Unknown => unreachable!(),99 SortKeyType::Unknown => unreachable!(),
100 };100 };
101 Ok(Gc::new(vk.into_iter().map(|v| v.0).collect()))101 Ok(Cc::new(vk.into_iter().map(|v| v.0).collect()))
102 }102 }
103}103}
104104
modifiedcrates/jrsonnet-evaluator/src/builtin/stdlib.rsdiffbeforeafterboth
15 jrsonnet_parser::parse(15 jrsonnet_parser::parse(
16 jrsonnet_stdlib::STDLIB_STR,16 jrsonnet_stdlib::STDLIB_STR,
17 &ParserSettings {17 &ParserSettings {
18 loc_data: true,
19 file_name: PathBuf::from("std.jsonnet").into(),18 file_name: PathBuf::from("std.jsonnet").into(),
20 },19 },
21 )20 )
modifiedcrates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth
1use crate::cc_ptr_eq;
2use crate::gc::GcHashMap;
1use crate::{3use crate::{
2 error::Error::*, map::LayeredHashMap, FutureWrapper, LazyBinding, LazyVal, ObjValue, Result,4 error::Error::*, map::LayeredHashMap, FutureWrapper, LazyBinding, LazyVal, ObjValue, Result,
3 Val,5 Val,
4};6};
5use jrsonnet_gc::{Gc, Trace};7use gcmodule::{Cc, Trace};
6use jrsonnet_interner::IStr;8use jrsonnet_interner::IStr;
7use rustc_hash::FxHashMap;
8use std::fmt::Debug;9use std::fmt::Debug;
9use std::hash::BuildHasherDefault;
1010
11#[derive(Clone, Trace)]11#[derive(Clone, Trace)]
12#[trivially_drop]
13pub struct ContextCreator(pub Context, pub FutureWrapper<FxHashMap<IStr, LazyBinding>>);12pub struct ContextCreator(pub Context, pub FutureWrapper<GcHashMap<IStr, LazyBinding>>);
14impl ContextCreator {13impl ContextCreator {
15 pub fn create(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<Context> {14 pub fn create(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<Context> {
16 self.0.clone().extend_unbound(15 self.0.clone().extend_unbound(
23}22}
2423
25#[derive(Trace)]24#[derive(Trace)]
26#[trivially_drop]
27struct ContextInternals {25struct ContextInternals {
28 dollar: Option<ObjValue>,26 dollar: Option<ObjValue>,
29 this: Option<ObjValue>,27 this: Option<ObjValue>,
37}35}
3836
39#[derive(Debug, Clone, Trace)]37#[derive(Debug, Clone, Trace)]
40#[trivially_drop]
41pub struct Context(Gc<ContextInternals>);38pub struct Context(Cc<ContextInternals>);
42impl Context {39impl Context {
43 pub fn new_future() -> FutureWrapper<Self> {40 pub fn new_future() -> FutureWrapper<Self> {
44 FutureWrapper::new()41 FutureWrapper::new()
57 }54 }
5855
59 pub fn new() -> Self {56 pub fn new() -> Self {
60 Self(Gc::new(ContextInternals {57 Self(Cc::new(ContextInternals {
61 dollar: None,58 dollar: None,
62 this: None,59 this: None,
63 super_obj: None,60 super_obj: None,
84 }81 }
8582
86 pub fn with_var(self, name: IStr, value: Val) -> Self {83 pub fn with_var(self, name: IStr, value: Val) -> Self {
87 let mut new_bindings =84 let mut new_bindings = GcHashMap::with_capacity(1);
88 FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());
89 new_bindings.insert(name, LazyVal::new_resolved(value));85 new_bindings.insert(name, LazyVal::new_resolved(value));
90 self.extend(new_bindings, None, None, None)86 self.extend(new_bindings, None, None, None)
91 }87 }
9288
93 pub fn with_this_super(self, new_this: ObjValue, new_super_obj: Option<ObjValue>) -> Self {89 pub fn with_this_super(self, new_this: ObjValue, new_super_obj: Option<ObjValue>) -> Self {
94 self.extend(FxHashMap::default(), None, Some(new_this), new_super_obj)90 self.extend(GcHashMap::new(), None, Some(new_this), new_super_obj)
95 }91 }
9692
97 pub fn extend(93 pub fn extend(
98 self,94 self,
99 new_bindings: FxHashMap<IStr, LazyVal>,95 new_bindings: GcHashMap<IStr, LazyVal>,
100 new_dollar: Option<ObjValue>,96 new_dollar: Option<ObjValue>,
101 new_this: Option<ObjValue>,97 new_this: Option<ObjValue>,
102 new_super_obj: Option<ObjValue>,98 new_super_obj: Option<ObjValue>,
110 } else {106 } else {
111 ctx.bindings.clone().extend(new_bindings)107 ctx.bindings.clone().extend(new_bindings)
112 };108 };
113 Self(Gc::new(ContextInternals {109 Self(Cc::new(ContextInternals {
114 dollar,110 dollar,
115 this,111 this,
116 super_obj,112 super_obj,
117 bindings,113 bindings,
118 }))114 }))
119 }115 }
120 pub fn extend_bound(self, new_bindings: FxHashMap<IStr, LazyVal>) -> Self {116 pub fn extend_bound(self, new_bindings: GcHashMap<IStr, LazyVal>) -> Self {
121 let new_this = self.0.this.clone();117 let new_this = self.0.this.clone();
122 let new_super_obj = self.0.super_obj.clone();118 let new_super_obj = self.0.super_obj.clone();
123 self.extend(new_bindings, None, new_this, new_super_obj)119 self.extend(new_bindings, None, new_this, new_super_obj)
124 }120 }
125 pub fn extend_unbound(121 pub fn extend_unbound(
126 self,122 self,
127 new_bindings: FxHashMap<IStr, LazyBinding>,123 new_bindings: GcHashMap<IStr, LazyBinding>,
128 new_dollar: Option<ObjValue>,124 new_dollar: Option<ObjValue>,
129 new_this: Option<ObjValue>,125 new_this: Option<ObjValue>,
130 new_super_obj: Option<ObjValue>,126 new_super_obj: Option<ObjValue>,
131 ) -> Result<Self> {127 ) -> Result<Self> {
132 let this = new_this.or_else(|| self.0.this.clone());128 let this = new_this.or_else(|| self.0.this.clone());
133 let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());129 let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());
134 let mut new =130 let mut new = GcHashMap::with_capacity(new_bindings.len());
135 FxHashMap::with_capacity_and_hasher(new_bindings.len(), BuildHasherDefault::default());
136 for (k, v) in new_bindings.into_iter() {131 for (k, v) in new_bindings.0.into_iter() {
137 new.insert(k, v.evaluate(this.clone(), super_obj.clone())?);132 new.insert(k, v.evaluate(this.clone(), super_obj.clone())?);
138 }133 }
139 Ok(self.extend(new, new_dollar, this, super_obj))134 Ok(self.extend(new, new_dollar, this, super_obj))
152147
153impl PartialEq for Context {148impl PartialEq for Context {
154 fn eq(&self, other: &Self) -> bool {149 fn eq(&self, other: &Self) -> bool {
155 Gc::ptr_eq(&self.0, &other.0)150 cc_ptr_eq(&self.0, &other.0)
156 }151 }
157}152}
158153
modifiedcrates/jrsonnet-evaluator/src/dynamic.rsdiffbeforeafterboth
1use std::cell::RefCell;
2
1use jrsonnet_gc::{Gc, GcCell, Trace};3use gcmodule::{Cc, Trace};
24
3#[derive(Clone, Trace)]5#[derive(Clone, Trace)]
4#[trivially_drop]
5pub struct FutureWrapper<V: Trace + 'static>(pub Gc<GcCell<Option<V>>>);6pub struct FutureWrapper<V: Trace + 'static>(pub Cc<RefCell<Option<V>>>);
6impl<T: Trace + 'static> FutureWrapper<T> {7impl<T: Trace + 'static> FutureWrapper<T> {
7 pub fn new() -> Self {8 pub fn new() -> Self {
8 Self(Gc::new(GcCell::new(None)))9 Self(Cc::new(RefCell::new(None)))
9 }10 }
10 pub fn fill(self, value: T) {11 pub fn fill(self, value: T) {
11 assert!(self.0.borrow().is_none(), "wrapper is filled already");12 assert!(self.0.borrow().is_none(), "wrapper is filled already");
modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
1use crate::{Val, builtin::{format::FormatError, sort::SortError}, typed::TypeLocError};1use crate::{
2 builtin::{format::FormatError, sort::SortError},
3 typed::TypeLocError,
4};
2use jrsonnet_gc::Trace;5use gcmodule::Trace;
3use jrsonnet_interner::IStr;6use jrsonnet_interner::IStr;
4use jrsonnet_parser::{BinaryOpType, ExprLocation, UnaryOpType};7use jrsonnet_parser::{BinaryOpType, ExprLocation, UnaryOpType};
5use jrsonnet_types::ValType;8use jrsonnet_types::ValType;
10use thiserror::Error;13use thiserror::Error;
1114
12#[derive(Error, Debug, Clone, Trace)]15#[derive(Error, Debug, Clone, Trace)]
13#[trivially_drop]
14pub enum Error {16pub enum Error {
15 #[error("intrinsic not found: {0}")]17 #[error("intrinsic not found: {0}")]
16 IntrinsicNotFound(IStr),18 IntrinsicNotFound(IStr),
85 #[error("tried to import {1} from {0}, but imports is not supported")]87 #[error("tried to import {1} from {0}, but imports is not supported")]
86 ImportNotSupported(PathBuf, PathBuf),88 ImportNotSupported(PathBuf, PathBuf),
87 #[error(89 #[error(
88 "syntax error, expected one of {}, got {:?}",90 "syntax error: expected {}, got {:?}",
89 .error.expected,91 .error.expected,
90 .source_code.chars().nth(error.location.offset).map(|c| c.to_string()).unwrap_or_else(|| "EOF".into())92 .source_code.chars().nth(error.location.offset).map(|c| c.to_string()).unwrap_or_else(|| "EOF".into())
91 )]93 )]
92 ImportSyntaxError {94 ImportSyntaxError {
95 #[skip_trace]
93 path: Rc<Path>,96 path: Rc<Path>,
94 source_code: IStr,97 source_code: IStr,
95 #[unsafe_ignore_trace]98 #[skip_trace]
96 error: Box<jrsonnet_parser::ParseError>,99 error: Box<jrsonnet_parser::ParseError>,
97 },100 },
98101
150}153}
151154
152#[derive(Clone, Debug, Trace)]155#[derive(Clone, Debug, Trace)]
153#[trivially_drop]
154pub struct StackTraceElement {156pub struct StackTraceElement {
155 pub location: Option<ExprLocation>,157 pub location: Option<ExprLocation>,
156 pub desc: String,158 pub desc: String,
157}159}
158#[derive(Debug, Clone, Trace)]160#[derive(Debug, Clone, Trace)]
159#[trivially_drop]
160pub struct StackTrace(pub Vec<StackTraceElement>);161pub struct StackTrace(pub Vec<StackTraceElement>);
161162
162#[derive(Debug, Clone, Trace)]163#[derive(Debug, Clone, Trace)]
163#[trivially_drop]
164pub struct LocError(Box<(Error, StackTrace)>);164pub struct LocError(Box<(Error, StackTrace)>);
165impl LocError {165impl LocError {
166 pub fn new(e: Error) -> Self {166 pub fn new(e: Error) -> Self {
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
2 builtin::std_slice,2 builtin::std_slice,
3 error::Error::*,3 error::Error::*,
4 evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},4 evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},
5 gc::TraceBox,
5 push_frame, throw, with_state, ArrValue, Bindable, Context, ContextCreator, FuncDesc, FuncVal,6 push_frame, throw, with_state, ArrValue, Bindable, Context, ContextCreator, FuncDesc, FuncVal,
6 FutureWrapper, LazyBinding, LazyVal, LazyValValue, ObjValue, ObjValueBuilder, ObjectAssertion,7 FutureWrapper, GcHashMap, LazyBinding, LazyVal, LazyValValue, ObjValue,
7 Result, Val,8 ObjValueBuilder, ObjectAssertion, Result, Val,
8};9};
9use jrsonnet_gc::{Gc, Trace};10use gcmodule::{Cc, Trace};
10use jrsonnet_interner::IStr;11use jrsonnet_interner::IStr;
11use jrsonnet_parser::{12use jrsonnet_parser::{
12 ArgsDesc, AssertStmt, BindSpec, CompSpec, Expr, ExprLocation, FieldMember, ForSpecData,13 ArgsDesc, AssertStmt, BindSpec, CompSpec, Expr, ExprLocation, FieldMember, ForSpecData,
13 IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc,14 IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc,
14};15};
15use jrsonnet_types::ValType;16use jrsonnet_types::ValType;
16use rustc_hash::{FxHashMap, FxHasher};
17use std::{collections::HashMap, hash::BuildHasherDefault};
18pub mod operator;17pub mod operator;
1918
20pub fn evaluate_binding_in_future(19pub fn evaluate_binding_in_future(
26 let params = params.clone();25 let params = params.clone();
2726
28 #[derive(Trace)]27 #[derive(Trace)]
29 #[trivially_drop]
30 struct LazyMethodBinding {28 struct LazyMethodBinding {
31 context_creator: FutureWrapper<Context>,29 context_creator: FutureWrapper<Context>,
32 name: IStr,30 name: IStr,
44 }42 }
45 }43 }
4644
47 LazyVal::new(Box::new(LazyMethodBinding {45 LazyVal::new(TraceBox(Box::new(LazyMethodBinding {
48 context_creator,46 context_creator,
49 name: b.name.clone(),47 name: b.name.clone(),
50 params,48 params,
51 value: b.value.clone(),49 value: b.value.clone(),
52 }))50 })))
53 } else {51 } else {
54 #[derive(Trace)]52 #[derive(Trace)]
55 #[trivially_drop]
56 struct LazyNamedBinding {53 struct LazyNamedBinding {
57 context_creator: FutureWrapper<Context>,54 context_creator: FutureWrapper<Context>,
58 name: IStr,55 name: IStr,
63 evaluate_named(self.context_creator.unwrap(), &self.value, self.name)60 evaluate_named(self.context_creator.unwrap(), &self.value, self.name)
64 }61 }
65 }62 }
66 LazyVal::new(Box::new(LazyNamedBinding {63 LazyVal::new(TraceBox(Box::new(LazyNamedBinding {
67 context_creator,64 context_creator,
68 name: b.name.clone(),65 name: b.name.clone(),
69 value: b.value,66 value: b.value,
70 }))67 })))
71 }68 }
72}69}
7370
77 let params = params.clone();74 let params = params.clone();
7875
79 #[derive(Trace)]76 #[derive(Trace)]
80 #[trivially_drop]
81 struct BindableMethodLazyVal {77 struct BindableMethodLazyVal {
82 this: Option<ObjValue>,78 this: Option<ObjValue>,
83 super_obj: Option<ObjValue>,79 super_obj: Option<ObjValue>,
99 }95 }
10096
101 #[derive(Trace)]97 #[derive(Trace)]
102 #[trivially_drop]
103 struct BindableMethod {98 struct BindableMethod {
104 context_creator: ContextCreator,99 context_creator: ContextCreator,
105 name: IStr,100 name: IStr,
108 }103 }
109 impl Bindable for BindableMethod {104 impl Bindable for BindableMethod {
110 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {105 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {
111 Ok(LazyVal::new(Box::new(BindableMethodLazyVal {106 Ok(LazyVal::new(TraceBox(Box::new(
107 BindableMethodLazyVal {
112 this,108 this,
113 super_obj,109 super_obj,
114110
115 context_creator: self.context_creator.clone(),111 context_creator: self.context_creator.clone(),
116 name: self.name.clone(),112 name: self.name.clone(),
117 params: self.params.clone(),113 params: self.params.clone(),
118 value: self.value.clone(),114 value: self.value.clone(),
119 })))115 },
116 ))))
120 }117 }
121 }118 }
122119
123 (120 (
124 b.name.clone(),121 b.name.clone(),
125 LazyBinding::Bindable(Gc::new(Box::new(BindableMethod {122 LazyBinding::Bindable(Cc::new(TraceBox(Box::new(BindableMethod {
126 context_creator,123 context_creator,
127 name: b.name.clone(),124 name: b.name.clone(),
128 params,125 params,
129 value: b.value.clone(),126 value: b.value.clone(),
130 }))),127 })))),
131 )128 )
132 } else {129 } else {
133 #[derive(Trace)]130 #[derive(Trace)]
134 #[trivially_drop]
135 struct BindableNamedLazyVal {131 struct BindableNamedLazyVal {
136 this: Option<ObjValue>,132 this: Option<ObjValue>,
137 super_obj: Option<ObjValue>,133 super_obj: Option<ObjValue>,
151 }147 }
152148
153 #[derive(Trace)]149 #[derive(Trace)]
154 #[trivially_drop]
155 struct BindableNamed {150 struct BindableNamed {
156 context_creator: ContextCreator,151 context_creator: ContextCreator,
157 name: IStr,152 name: IStr,
158 value: LocExpr,153 value: LocExpr,
159 }154 }
160 impl Bindable for BindableNamed {155 impl Bindable for BindableNamed {
161 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {156 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {
162 Ok(LazyVal::new(Box::new(BindableNamedLazyVal {157 Ok(LazyVal::new(TraceBox(Box::new(
158 BindableNamedLazyVal {
163 this,159 this,
164 super_obj,160 super_obj,
165161
166 context_creator: self.context_creator.clone(),162 context_creator: self.context_creator.clone(),
167 name: self.name.clone(),163 name: self.name.clone(),
168 value: self.value.clone(),164 value: self.value.clone(),
169 })))165 },
166 ))))
170 }167 }
171 }168 }
172169
173 (170 (
174 b.name.clone(),171 b.name.clone(),
175 LazyBinding::Bindable(Gc::new(Box::new(BindableNamed {172 LazyBinding::Bindable(Cc::new(TraceBox(Box::new(BindableNamed {
176 context_creator,173 context_creator,
177 name: b.name.clone(),174 name: b.name.clone(),
178 value: b.value.clone(),175 value: b.value.clone(),
179 }))),176 })))),
180 )177 )
181 }178 }
182}179}
183180
184pub fn evaluate_method(ctx: Context, name: IStr, params: ParamsDesc, body: LocExpr) -> Val {181pub fn evaluate_method(ctx: Context, name: IStr, params: ParamsDesc, body: LocExpr) -> Val {
185 Val::Func(Gc::new(FuncVal::Normal(FuncDesc {182 Val::Func(Cc::new(FuncVal::Normal(FuncDesc {
186 name,183 name,
187 ctx,184 ctx,
188 params,185 params,
240 let future_this = FutureWrapper::new();237 let future_this = FutureWrapper::new();
241 let context_creator = ContextCreator(context.clone(), new_bindings.clone());238 let context_creator = ContextCreator(context.clone(), new_bindings.clone());
242 {239 {
243 let mut bindings: FxHashMap<IStr, LazyBinding> =240 let mut bindings: GcHashMap<IStr, LazyBinding> = GcHashMap::with_capacity(members.len());
244 FxHashMap::with_capacity_and_hasher(members.len(), BuildHasherDefault::default());
245 for (n, b) in members241 for (n, b) in members
246 .iter()242 .iter()
247 .filter_map(|m| match m {243 .filter_map(|m| match m {
272 let name = name.unwrap();268 let name = name.unwrap();
273269
274 #[derive(Trace)]270 #[derive(Trace)]
275 #[trivially_drop]
276 struct ObjMemberBinding {271 struct ObjMemberBinding {
277 context_creator: ContextCreator,272 context_creator: ContextCreator,
278 value: LocExpr,273 value: LocExpr,
296 .with_add(*plus)291 .with_add(*plus)
297 .with_visibility(*visibility)292 .with_visibility(*visibility)
298 .with_location(value.1.clone())293 .with_location(value.1.clone())
299 .bindable(Box::new(ObjMemberBinding {294 .bindable(TraceBox(Box::new(ObjMemberBinding {
300 context_creator: context_creator.clone(),295 context_creator: context_creator.clone(),
301 value: value.clone(),296 value: value.clone(),
302 name,297 name,
303 }));298 })));
304 }299 }
305 Member::Field(FieldMember {300 Member::Field(FieldMember {
306 name,301 name,
314 }309 }
315 let name = name.unwrap();310 let name = name.unwrap();
316 #[derive(Trace)]311 #[derive(Trace)]
317 #[trivially_drop]
318 struct ObjMemberBinding {312 struct ObjMemberBinding {
319 context_creator: ContextCreator,313 context_creator: ContextCreator,
320 value: LocExpr,314 value: LocExpr,
339 .member(name.clone())333 .member(name.clone())
340 .hide()334 .hide()
341 .with_location(value.1.clone())335 .with_location(value.1.clone())
342 .bindable(Box::new(ObjMemberBinding {336 .bindable(TraceBox(Box::new(ObjMemberBinding {
343 context_creator: context_creator.clone(),337 context_creator: context_creator.clone(),
344 value: value.clone(),338 value: value.clone(),
345 params: params.clone(),339 params: params.clone(),
346 name,340 name,
347 }));341 })));
348 }342 }
349 Member::BindStmt(_) => {}343 Member::BindStmt(_) => {}
350 Member::AssertStmt(stmt) => {344 Member::AssertStmt(stmt) => {
351 #[derive(Trace)]345 #[derive(Trace)]
352 #[trivially_drop]
353 struct ObjectAssert {346 struct ObjectAssert {
354 context_creator: ContextCreator,347 context_creator: ContextCreator,
355 assert: AssertStmt,348 assert: AssertStmt,
364 evaluate_assert(ctx, &self.assert)357 evaluate_assert(ctx, &self.assert)
365 }358 }
366 }359 }
367 builder.assert(Box::new(ObjectAssert {360 builder.assert(TraceBox(Box::new(ObjectAssert {
368 context_creator: context_creator.clone(),361 context_creator: context_creator.clone(),
369 assert: stmt.clone(),362 assert: stmt.clone(),
370 }));363 })));
371 }364 }
372 }365 }
373 }366 }
385 evaluate_comp(context.clone(), &obj.compspecs, &mut |ctx| {378 evaluate_comp(context.clone(), &obj.compspecs, &mut |ctx| {
386 let new_bindings = FutureWrapper::new();379 let new_bindings = FutureWrapper::new();
387 let context_creator = ContextCreator(context.clone(), new_bindings.clone());380 let context_creator = ContextCreator(context.clone(), new_bindings.clone());
388 let mut bindings: FxHashMap<IStr, LazyBinding> =381 let mut bindings: GcHashMap<IStr, LazyBinding> =
389 FxHashMap::with_capacity_and_hasher(382 GcHashMap::with_capacity(obj.pre_locals.len() + obj.post_locals.len());
390 obj.pre_locals.len() + obj.post_locals.len(),
391 BuildHasherDefault::default(),
392 );
393 for (n, b) in obj383 for (n, b) in obj
394 .pre_locals384 .pre_locals
406 Val::Null => {}396 Val::Null => {}
407 Val::Str(n) => {397 Val::Str(n) => {
408 #[derive(Trace)]398 #[derive(Trace)]
409 #[trivially_drop]
410 struct ObjCompBinding {399 struct ObjCompBinding {
411 context: Context,400 context: Context,
412 value: LocExpr,401 value: LocExpr,
420 Ok(LazyVal::new_resolved(evaluate(409 Ok(LazyVal::new_resolved(evaluate(
421 self.context.clone().extend(410 self.context
411 .clone()
422 FxHashMap::default(),412 .extend(GcHashMap::new(), None, this, None),
423 None,
424 this,
425 None,
432 .member(n)418 .member(n)
433 .with_location(obj.value.1.clone())419 .with_location(obj.value.1.clone())
434 .with_add(obj.plus)420 .with_add(obj.plus)
435 .bindable(Box::new(ObjCompBinding {421 .bindable(TraceBox(Box::new(ObjCompBinding {
436 context: ctx,422 context: ctx,
437 value: obj.value.clone(),423 value: obj.value.clone(),
438 }));424 })));
439 }425 }
440 v => throw!(FieldMustBeStringGot(v.value_type())),426 v => throw!(FieldMustBeStringGot(v.value_type())),
441 }427 }
454 context: Context,440 context: Context,
455 value: &LocExpr,441 value: &LocExpr,
456 args: &ArgsDesc,442 args: &ArgsDesc,
457 loc: Option<&ExprLocation>,443 loc: &ExprLocation,
458 tailstrict: bool,444 tailstrict: bool,
459) -> Result<Val> {445) -> Result<Val> {
460 let value = evaluate(context.clone(), value)?;446 let value = evaluate(context.clone(), value)?;
475 let value = &assertion.0;461 let value = &assertion.0;
476 let msg = &assertion.1;462 let msg = &assertion.1;
477 let assertion_result = push_frame(463 let assertion_result = push_frame(
478 value.1.as_ref(),464 &value.1,
479 || "assertion condition".to_owned(),465 || "assertion condition".to_owned(),
480 || {466 || {
481 evaluate(context.clone(), value)?467 evaluate(context.clone(), value)?
484 )?;470 )?;
485 if !assertion_result {471 if !assertion_result {
486 push_frame(472 push_frame(
487 value.1.as_ref(),473 &value.1,
488 || "assertion failure".to_owned(),474 || "assertion failure".to_owned(),
489 || {475 || {
490 if let Some(msg) = msg {476 if let Some(msg) = msg {
534 BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, v1, *o, v2)?,520 BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, v1, *o, v2)?,
535 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,521 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,
536 Var(name) => push_frame(522 Var(name) => push_frame(
537 loc.as_ref(),523 loc,
538 || format!("variable <{}>", name),524 || format!("variable <{}> access", name),
539 || context.binding(name.clone())?.evaluate(),525 || context.binding(name.clone())?.evaluate(),
540 )?,526 )?,
541 Index(value, index) => {527 Index(value, index) => {
542 match (evaluate(context.clone(), value)?, evaluate(context, index)?) {528 match (evaluate(context.clone(), value)?, evaluate(context, index)?) {
543 (Val::Obj(v), Val::Str(s)) => {529 (Val::Obj(v), Val::Str(s)) => {
544 let sn = s.clone();530 let sn = s.clone();
545 push_frame(531 push_frame(
546 loc.as_ref(),532 loc,
547 || format!("field <{}> access", sn),533 || format!("field <{}> access", sn),
548 || {534 || {
549 if let Some(v) = v.get(s.clone())? {535 if let Some(v) = v.get(s.clone())? {
591 }577 }
592 }578 }
593 LocalExpr(bindings, returned) => {579 LocalExpr(bindings, returned) => {
594 let mut new_bindings: FxHashMap<IStr, LazyVal> = HashMap::with_capacity_and_hasher(580 let mut new_bindings: GcHashMap<IStr, LazyVal> =
595 bindings.len(),581 GcHashMap::with_capacity(bindings.len());
596 BuildHasherDefault::<FxHasher>::default(),
597 );
598 let future_context = Context::new_future();582 let future_context = Context::new_future();
599 for b in bindings {583 for b in bindings {
612 for item in items {596 for item in items {
613 // TODO: Implement ArrValue::Lazy with same context for every element?597 // TODO: Implement ArrValue::Lazy with same context for every element?
614 #[derive(Trace)]598 #[derive(Trace)]
615 #[trivially_drop]
616 struct ArrayElement {599 struct ArrayElement {
617 context: Context,600 context: Context,
618 item: LocExpr,601 item: LocExpr,
622 evaluate(self.context, &self.item)605 evaluate(self.context, &self.item)
623 }606 }
624 }607 }
625 out.push(LazyVal::new(Box::new(ArrayElement {608 out.push(LazyVal::new(TraceBox(Box::new(ArrayElement {
626 context: context.clone(),609 context: context.clone(),
627 item: item.clone(),610 item: item.clone(),
628 })));611 }))));
629 }612 }
630 Val::Arr(out.into())613 Val::Arr(out.into())
631 }614 }
635 out.push(evaluate(ctx, expr)?);618 out.push(evaluate(ctx, expr)?);
636 Ok(())619 Ok(())
637 })?;620 })?;
638 Val::Arr(ArrValue::Eager(Gc::new(out)))621 Val::Arr(ArrValue::Eager(Cc::new(out)))
639 }622 }
640 Obj(body) => Val::Obj(evaluate_object(context, body)?),623 Obj(body) => Val::Obj(evaluate_object(context, body)?),
641 ObjExtend(s, t) => evaluate_add_op(624 ObjExtend(s, t) => evaluate_add_op(
642 &evaluate(context.clone(), s)?,625 &evaluate(context.clone(), s)?,
643 &Val::Obj(evaluate_object(context, t)?),626 &Val::Obj(evaluate_object(context, t)?),
644 )?,627 )?,
645 Apply(value, args, tailstrict) => {628 Apply(value, args, tailstrict) => evaluate_apply(context, value, args, loc, *tailstrict)?,
646 evaluate_apply(context, value, args, loc.as_ref(), *tailstrict)?
647 }
648 Function(params, body) => {629 Function(params, body) => {
649 evaluate_method(context, "anonymous".into(), params.clone(), body.clone())630 evaluate_method(context, "anonymous".into(), params.clone(), body.clone())
650 }631 }
651 Intrinsic(name) => Val::Func(Gc::new(FuncVal::Intrinsic(name.clone()))),632 Intrinsic(name) => Val::Func(Cc::new(FuncVal::Intrinsic(name.clone()))),
652 AssertExpr(assert, returned) => {633 AssertExpr(assert, returned) => {
653 evaluate_assert(context.clone(), assert)?;634 evaluate_assert(context.clone(), assert)?;
654 evaluate(context, returned)?635 evaluate(context, returned)?
655 }636 }
656 ErrorStmt(e) => push_frame(637 ErrorStmt(e) => push_frame(
657 loc.as_ref(),638 loc,
658 || "error statement".to_owned(),639 || "error statement".to_owned(),
659 || {640 || {
660 throw!(RuntimeError(641 throw!(RuntimeError(
668 cond_else,649 cond_else,
669 } => {650 } => {
670 if push_frame(651 if push_frame(
671 loc.as_ref(),652 loc,
672 || "if condition".to_owned(),653 || "if condition".to_owned(),
673 || evaluate(context.clone(), &cond.0)?.try_cast_bool("in if condition"),654 || evaluate(context.clone(), &cond.0)?.try_cast_bool("in if condition"),
674 )? {655 )? {
705 Import(path) => {686 Import(path) => {
706 let tmp = loc687 let tmp = loc.clone().0;
707 .clone()
708 .expect("imports cannot be used without loc_data")
709 .0;
710 let mut import_location = tmp.to_path_buf();688 let mut import_location = tmp.to_path_buf();
711 import_location.pop();689 import_location.pop();
712 push_frame(690 push_frame(
713 loc.as_ref(),691 loc,
714 || format!("import {:?}", path),692 || format!("import {:?}", path),
715 || with_state(|s| s.import_file(&import_location, path)),693 || with_state(|s| s.import_file(&import_location, path)),
716 )?694 )?
717 }695 }
718 ImportStr(path) => {696 ImportStr(path) => {
719 let tmp = loc697 let tmp = loc.clone().0;
720 .clone()
721 .expect("imports cannot be used without loc_data")
722 .0;
723 let mut import_location = tmp.to_path_buf();698 let mut import_location = tmp.to_path_buf();
724 import_location.pop();699 import_location.pop();
modifiedcrates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth
1use crate::{1use crate::{Context, FutureWrapper, GcHashMap, LazyVal, LazyValValue, Result, Val, error::Error::*, evaluate, evaluate_named, gc::TraceBox, throw};
2 error::Error::*, evaluate, evaluate_named, throw, Context, FutureWrapper, LazyVal,
3 LazyValValue, Result, Val,
4};
5use jrsonnet_gc::Trace;2use gcmodule::Trace;
6use jrsonnet_interner::IStr;3use jrsonnet_interner::IStr;
7use jrsonnet_parser::{ArgsDesc, LocExpr, ParamsDesc};4use jrsonnet_parser::{ArgsDesc, LocExpr, ParamsDesc};
8use rustc_hash::FxHashMap;
9use std::{collections::HashMap, hash::BuildHasherDefault};5use std::collections::HashMap;
106
11const NO_DEFAULT_CONTEXT: &str =7const NO_DEFAULT_CONTEXT: &str =
12 "no default context set for call with defined default parameter value";8 "no default context set for call with defined default parameter value";
139
14#[derive(Trace)]10#[derive(Trace)]
15#[trivially_drop]
16struct EvaluateLazyVal {11struct EvaluateLazyVal {
17 context: Context,12 context: Context,
18 expr: LocExpr,13 expr: LocExpr,
38 args: &ArgsDesc,33 args: &ArgsDesc,
39 tailstrict: bool,34 tailstrict: bool,
40) -> Result<Context> {35) -> Result<Context> {
41 let mut passed_args =36 let mut passed_args = GcHashMap::with_capacity(params.len());
42 HashMap::with_capacity_and_hasher(params.len(), BuildHasherDefault::default());
43 if args.unnamed.len() > params.len() {37 if args.unnamed.len() > params.len() {
44 throw!(TooManyArgsFunctionHas(params.len()))38 throw!(TooManyArgsFunctionHas(params.len()))
45 }39 }
53 if tailstrict {47 if tailstrict {
54 LazyVal::new_resolved(evaluate(ctx.clone(), arg)?)48 LazyVal::new_resolved(evaluate(ctx.clone(), arg)?)
55 } else {49 } else {
56 LazyVal::new(Box::new(EvaluateLazyVal {50 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {
57 context: ctx.clone(),51 context: ctx.clone(),
58 expr: arg.clone(),52 expr: arg.clone(),
59 }))53 })))
60 },54 },
61 );55 );
62 filled_args += 1;56 filled_args += 1;
73 if tailstrict {67 if tailstrict {
74 LazyVal::new_resolved(evaluate(ctx.clone(), value)?)68 LazyVal::new_resolved(evaluate(ctx.clone(), value)?)
75 } else {69 } else {
76 LazyVal::new(Box::new(EvaluateLazyVal {70 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {
77 context: ctx.clone(),71 context: ctx.clone(),
78 expr: value.clone(),72 expr: value.clone(),
79 }))73 })))
80 },74 },
81 )75 )
82 .is_some()76 .is_some()
90 // Some args are unset, but maybe we have defaults for them84 // Some args are unset, but maybe we have defaults for them
91 // Default values should be created in newly created context85 // Default values should be created in newly created context
92 let future_context = FutureWrapper::<Context>::new();86 let future_context = FutureWrapper::<Context>::new();
93 let mut defaults = HashMap::with_capacity_and_hasher(87 let mut defaults = GcHashMap::with_capacity(params.len() - filled_args);
94 params.len() - filled_args,
95 BuildHasherDefault::default(),
96 );
9788
98 for param in params.iter().filter(|p| p.1.is_some()) {89 for param in params.iter().filter(|p| p.1.is_some()) {
99 if passed_args.contains_key(&param.0.clone()) {90 if passed_args.contains_key(&param.0.clone()) {
100 continue;91 continue;
101 }92 }
102 #[derive(Trace)]93 #[derive(Trace)]
103 #[trivially_drop]
104 struct LazyNamedBinding {94 struct LazyNamedBinding {
105 future_context: FutureWrapper<Context>,95 future_context: FutureWrapper<Context>,
106 name: IStr,96 name: IStr,
111 evaluate_named(self.future_context.unwrap(), &self.value, self.name)101 evaluate_named(self.future_context.unwrap(), &self.value, self.name)
112 }102 }
113 }103 }
114 LazyVal::new(Box::new(LazyNamedBinding {104 LazyVal::new(TraceBox(Box::new(LazyNamedBinding {
115 future_context: future_context.clone(),105 future_context: future_context.clone(),
116 name: param.0.clone(),106 name: param.0.clone(),
117 value: param.1.clone().unwrap(),107 value: param.1.clone().unwrap(),
118 }));108 })));
119109
120 defaults.insert(110 defaults.insert(
121 param.0.clone(),111 param.0.clone(),
122 LazyVal::new(Box::new(LazyNamedBinding {112 LazyVal::new(TraceBox(Box::new(LazyNamedBinding {
123 future_context: future_context.clone(),113 future_context: future_context.clone(),
124 name: param.0.clone(),114 name: param.0.clone(),
125 value: param.1.clone().unwrap(),115 value: param.1.clone().unwrap(),
126 })),116 }))),
127 );117 );
128 filled_args += 1;118 filled_args += 1;
129 }119 }
155 args: &HashMap<IStr, Val>,145 args: &HashMap<IStr, Val>,
156 tailstrict: bool,146 tailstrict: bool,
157) -> Result<Context> {147) -> Result<Context> {
158 let mut out = FxHashMap::with_capacity_and_hasher(params.len(), BuildHasherDefault::default());148 let mut out = GcHashMap::with_capacity(params.len());
159 let mut positioned_args = vec![None; params.0.len()];149 let mut positioned_args = vec![None; params.0.len()];
160 for (name, val) in args.iter() {150 for (name, val) in args.iter() {
161 let idx = params151 let idx = params
185 let body_ctx = body_ctx.clone();175 let body_ctx = body_ctx.clone();
186 let default = default.clone();176 let default = default.clone();
187 #[derive(Trace)]177 #[derive(Trace)]
188 #[trivially_drop]
189 struct EvaluateLazyVal {178 struct EvaluateLazyVal {
190 body_ctx: Option<Context>,179 body_ctx: Option<Context>,
191 default: LocExpr,180 default: LocExpr,
198 )187 )
199 }188 }
200 }189 }
201 LazyVal::new(Box::new(EvaluateLazyVal { body_ctx, default }))190 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {
191 body_ctx,
192 default,
193 })))
202 }194 }
203 } else {195 } else {
204 throw!(FunctionParameterNotBoundInCall(p.0.clone()));196 throw!(FunctionParameterNotBoundInCall(p.0.clone()));
215 params: &ParamsDesc,207 params: &ParamsDesc,
216 args: &[Val],208 args: &[Val],
217) -> Result<Context> {209) -> Result<Context> {
218 let mut out = FxHashMap::with_capacity_and_hasher(params.len(), BuildHasherDefault::default());210 let mut out = GcHashMap::with_capacity(params.len());
219 let mut positioned_args = vec![None; params.0.len()];211 let mut positioned_args = vec![None; params.0.len()];
220 for (id, arg) in args.iter().enumerate() {212 for (id, arg) in args.iter().enumerate() {
221 if id >= params.len() {213 if id >= params.len() {
243 ($ctx: expr, $fn_name: expr, $args: expr, $total_args: expr, [235 ($ctx: expr, $fn_name: expr, $args: expr, $total_args: expr, [
244 $($id: expr, $name: ident: $ty: expr $(=>$match: path)?);+ $(;)?236 $($id: expr, $name: ident: $ty: expr $(=>$match: path)?);+ $(;)?
245 ], $handler:block) => {{237 ], $handler:block) => {{
246 use $crate::{error::Error::*, throw, evaluate, push_frame, typed::CheckType};238 use $crate::{error::Error::*, throw, evaluate, push_description_frame, typed::CheckType};
247239
248 let args = $args;240 let args = $args;
249 if args.unnamed.len() + args.named.len() > $total_args {241 if args.unnamed.len() + args.named.len() > $total_args {
263 } else {255 } else {
264 &$args.unnamed[$id]256 &$args.unnamed[$id]
265 };257 };
266 let $name = push_frame(None, || format!("evaluating argument"), || {258 let $name = push_description_frame(|| format!("evaluating builtin argument {}", stringify!($name)), || {
267 let value = evaluate($ctx.clone(), &$name)?;259 let value = evaluate($ctx.clone(), &$name)?;
268 $ty.check(&value)?;260 $ty.check(&value)?;
269 Ok(value)261 Ok(value)
addedcrates/jrsonnet-evaluator/src/gc.rsdiffbeforeafterboth

no changes

modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
25use error::{Error::*, LocError, Result, StackTraceElement};25use error::{Error::*, LocError, Result, StackTraceElement};
26pub use evaluate::*;26pub use evaluate::*;
27pub use function::parse_function_call;27pub use function::parse_function_call;
28pub use import::*;28use gc::{GcHashMap, TraceBox};
29use jrsonnet_gc::{Finalize, Gc, Trace};29use gcmodule::{Cc, Trace};
30pub use import::*;
30pub use jrsonnet_interner::IStr;31pub use jrsonnet_interner::IStr;
31use jrsonnet_parser::*;32use jrsonnet_parser::*;
32use native::NativeCallback;33use native::NativeCallback;
33pub use obj::*;34pub use obj::*;
34use rustc_hash::FxHashMap;
35use std::{35use std::{
36 cell::{Ref, RefCell, RefMut},36 cell::{Ref, RefCell, RefMut},
37 collections::HashMap,37 collections::HashMap,
38 fmt::Debug,38 fmt::Debug,
39 hash::BuildHasherDefault,
40 path::{Path, PathBuf},39 path::{Path, PathBuf},
41 rc::Rc,40 rc::Rc,
42};41};
43use trace::{location_to_offset, offset_to_location, CodeLocation, CompactFormat, TraceFormat};42use trace::{location_to_offset, offset_to_location, CodeLocation, CompactFormat, TraceFormat};
44pub use val::*;43pub use val::*;
44pub mod gc;
4545
46pub trait Bindable: Trace {46pub trait Bindable: Trace + 'static {
47 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal>;47 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal>;
48}48}
49
49#[derive(Trace, Finalize, Clone)]50#[derive(Clone, Trace)]
50pub enum LazyBinding {51pub enum LazyBinding {
51 Bindable(Gc<Box<dyn Bindable>>),52 Bindable(Cc<TraceBox<dyn Bindable>>),
52 Bound(LazyVal),53 Bound(LazyVal),
53}54}
5455
74 /// Used for s`td.extVar`75 /// Used for s`td.extVar`
75 pub ext_vars: HashMap<IStr, Val>,76 pub ext_vars: HashMap<IStr, Val>,
76 /// Used for ext.native77 /// Used for ext.native
77 pub ext_natives: HashMap<IStr, Gc<NativeCallback>>,78 pub ext_natives: HashMap<IStr, Cc<NativeCallback>>,
78 /// TLA vars79 /// TLA vars
79 pub tla_vars: HashMap<IStr, Val>,80 pub tla_vars: HashMap<IStr, Val>,
80 /// Global variables are inserted in default context81 /// Global variables are inserted in default context
172 EVAL_STATE.with(|s| f(s.borrow().as_ref().unwrap()))173 EVAL_STATE.with(|s| f(s.borrow().as_ref().unwrap()))
173}174}
174pub(crate) fn push_frame<T>(175pub(crate) fn push_frame<T>(
175 e: Option<&ExprLocation>,176 e: &ExprLocation,
176 frame_desc: impl FnOnce() -> String,177 frame_desc: impl FnOnce() -> String,
177 f: impl FnOnce() -> Result<T>,178 f: impl FnOnce() -> Result<T>,
178) -> Result<T> {179) -> Result<T> {
179 with_state(|s| s.push(e, frame_desc, f))180 with_state(|s| s.push(e, frame_desc, f))
180}181}
181182
183#[allow(dead_code)]
182pub(crate) fn push_val_frame(184pub(crate) fn push_val_frame(
183 e: Option<&ExprLocation>,185 e: &ExprLocation,
184 frame_desc: impl FnOnce() -> String,186 frame_desc: impl FnOnce() -> String,
185 f: impl FnOnce() -> Result<Val>,187 f: impl FnOnce() -> Result<Val>,
186) -> Result<Val> {188) -> Result<Val> {
187 with_state(|s| s.push(e, frame_desc, f))189 with_state(|s| s.push_val(e, frame_desc, f))
188}190}
191#[allow(dead_code)]
192pub(crate) fn push_description_frame<T>(
193 frame_desc: impl FnOnce() -> String,
194 f: impl FnOnce() -> Result<T>,
195) -> Result<T> {
196 with_state(|s| s.push_description(frame_desc, f))
197}
189198
190/// Maintains stack trace and import resolution199/// Maintains stack trace and import resolution
191#[derive(Default, Clone)]200#[derive(Default, Clone)]
201 &source_code,210 &source_code,
202 &ParserSettings {211 &ParserSettings {
203 file_name: path.clone(),212 file_name: path.clone(),
204 loc_data: true,
205 },213 },
206 )214 )
207 .map_err(|error| ImportSyntaxError {215 .map_err(|error| ImportSyntaxError {
246 ro_map.get(name).map(|value| value.source_code.clone())254 ro_map.get(name).map(|value| value.source_code.clone())
247 }255 }
248 pub fn map_source_locations(&self, file: &Path, locs: &[usize]) -> Vec<CodeLocation> {256 pub fn map_source_locations(&self, file: &Path, locs: &[usize]) -> Vec<CodeLocation> {
249 offset_to_location(&self.get_source(file).unwrap(), locs)257 offset_to_location(&self.get_source(file).unwrap_or("".into()), locs)
250 }258 }
251 pub fn map_from_source_location(259 pub fn map_from_source_location(
252 &self,260 &self,
322 /// Creates context with all passed global variables330 /// Creates context with all passed global variables
323 pub fn create_default_context(&self) -> Context {331 pub fn create_default_context(&self) -> Context {
324 let globals = &self.settings().globals;332 let globals = &self.settings().globals;
325 let mut new_bindings: FxHashMap<IStr, LazyVal> =333 let mut new_bindings = GcHashMap::with_capacity(globals.len());
326 FxHashMap::with_capacity_and_hasher(globals.len(), BuildHasherDefault::default());
327 for (name, value) in globals.iter() {334 for (name, value) in globals.iter() {
328 new_bindings.insert(name.clone(), LazyVal::new_resolved(value.clone()));335 new_bindings.insert(name.clone(), LazyVal::new_resolved(value.clone()));
329 }336 }
333 /// Executes code creating a new stack frame340 /// Executes code creating a new stack frame
334 pub fn push<T>(341 pub fn push<T>(
335 &self,342 &self,
336 e: Option<&ExprLocation>,343 e: &ExprLocation,
337 frame_desc: impl FnOnce() -> String,344 frame_desc: impl FnOnce() -> String,
338 f: impl FnOnce() -> Result<T>,345 f: impl FnOnce() -> Result<T>,
339 ) -> Result<T> {346 ) -> Result<T> {
353 let mut data = self.data_mut();360 let mut data = self.data_mut();
354 data.stack_depth -= 1;361 data.stack_depth -= 1;
355 data.stack_generation += 1;362 data.stack_generation += 1;
356 // if let Some(e) = e {
357 // result =
358 // data.breakpoints
359 // .insert(data.stack_depth, data.stack_generation, &e, result)
360 // }
361 }363 }
362 if let Err(mut err) = result {364 if let Err(mut err) = result {
363 err.trace_mut().0.push(StackTraceElement {365 err.trace_mut().0.push(StackTraceElement {
364 location: e.cloned(),366 location: Some(e.clone()),
365 desc: frame_desc(),367 desc: frame_desc(),
366 });368 });
367 return Err(err);369 return Err(err);
371 /// Executes code creating a new stack frame374 /// Executes code creating a new stack frame
372 pub fn push_val(375 pub fn push_val(
373 &self,376 &self,
374 e: Option<&ExprLocation>,377 e: &ExprLocation,
375 frame_desc: impl FnOnce() -> String,378 frame_desc: impl FnOnce() -> String,
376 f: impl FnOnce() -> Result<Val>,379 f: impl FnOnce() -> Result<Val>,
377 ) -> Result<Val> {380 ) -> Result<Val> {
391 let mut data = self.data_mut();394 let mut data = self.data_mut();
392 data.stack_depth -= 1;395 data.stack_depth -= 1;
393 data.stack_generation += 1;396 data.stack_generation += 1;
394 if let Some(e) = e {
395 result =397 result = data
396 data.breakpoints398 .breakpoints
397 .insert(data.stack_depth, data.stack_generation, &e, result)399 .insert(data.stack_depth, data.stack_generation, &e, result);
398 }
399 }400 }
400 if let Err(mut err) = result {401 if let Err(mut err) = result {
401 err.trace_mut().0.push(StackTraceElement {402 err.trace_mut().0.push(StackTraceElement {
402 location: e.cloned(),403 location: Some(e.clone()),
403 desc: frame_desc(),404 desc: frame_desc(),
404 });405 });
405 return Err(err);406 return Err(err);
406 }407 }
407 result408 result
408 }409 }
410 /// Executes code creating a new stack frame
411 pub fn push_description<T>(
412 &self,
413 frame_desc: impl FnOnce() -> String,
414 f: impl FnOnce() -> Result<T>,
415 ) -> Result<T> {
416 {
417 let mut data = self.data_mut();
418 let stack_depth = &mut data.stack_depth;
419 if *stack_depth > self.max_stack() {
420 // Error creation uses data, so i drop guard here
421 drop(data);
422 throw!(StackOverflow);
423 } else {
424 *stack_depth += 1;
425 }
426 }
427 let result = f();
428 {
429 let mut data = self.data_mut();
430 data.stack_depth -= 1;
431 data.stack_generation += 1;
432 }
433 if let Err(mut err) = result {
434 err.trace_mut().0.push(StackTraceElement {
435 location: None,
436 desc: frame_desc(),
437 });
438 return Err(err);
439 }
440 result
441 }
409442
410 /// Runs passed function in state (required if function needs to modify stack trace)443 /// Runs passed function in state (required if function needs to modify stack trace)
411 pub fn run_in_state<T>(&self, f: impl FnOnce() -> T) -> T {444 pub fn run_in_state<T>(&self, f: impl FnOnce() -> T) -> T {
451 }484 }
452485
453 pub fn manifest(&self, val: Val) -> Result<IStr> {486 pub fn manifest(&self, val: Val) -> Result<IStr> {
454 self.run_in_state(|| val.manifest(&self.manifest_format()))487 self.run_in_state(|| {
488 push_description_frame(
489 || format!("manifestification"),
490 || val.manifest(&self.manifest_format()),
491 )
492 })
455 }493 }
456 pub fn manifest_multi(&self, val: Val) -> Result<Vec<(IStr, IStr)>> {494 pub fn manifest_multi(&self, val: Val) -> Result<Vec<(IStr, IStr)>> {
457 self.run_in_state(|| val.manifest_multi(&self.manifest_format()))495 self.run_in_state(|| val.manifest_multi(&self.manifest_format()))
464 pub fn with_tla(&self, val: Val) -> Result<Val> {502 pub fn with_tla(&self, val: Val) -> Result<Val> {
465 self.run_in_state(|| {503 self.run_in_state(|| {
466 Ok(match val {504 Ok(match val {
467 Val::Func(func) => push_frame(505 Val::Func(func) => push_description_frame(
468 None,
469 || "during TLA call".to_owned(),506 || "during TLA call".to_owned(),
470 || {507 || {
471 func.evaluate_map(508 func.evaluate_map(
511 &code,548 &code,
512 &ParserSettings {549 &ParserSettings {
513 file_name: source.clone(),550 file_name: source.clone(),
514 loc_data: true,
515 },551 },
516 )552 )
517 .map_err(|e| ImportSyntaxError {553 .map_err(|e| ImportSyntaxError {
570 self.settings_mut().import_resolver = resolver;606 self.settings_mut().import_resolver = resolver;
571 }607 }
572608
573 pub fn add_native(&self, name: IStr, cb: Gc<NativeCallback>) {609 pub fn add_native(&self, name: IStr, cb: Cc<NativeCallback>) {
574 self.settings_mut().ext_natives.insert(name, cb);610 self.settings_mut().ext_natives.insert(name, cb);
575 }611 }
576612
603 }639 }
604}640}
641
642pub fn cc_ptr_eq<T>(a: &Cc<T>, b: &Cc<T>) -> bool {
643 let a = &a as &T;
644 let b = &b as &T;
645 std::ptr::eq(a, b)
646}
605647
606#[cfg(test)]648#[cfg(test)]
607pub mod tests {649pub mod tests {
608 use super::Val;650 use super::Val;
609 use crate::{651 use crate::{
610 error::Error::*, native::NativeCallbackHandler, primitive_equals, EvaluationState,652 error::Error::*, gc::TraceBox, native::NativeCallbackHandler, primitive_equals,
653 EvaluationState,
611 };654 };
612 use jrsonnet_gc::{Finalize, Gc, Trace};655 use gcmodule::{Cc, Trace};
613 use jrsonnet_interner::IStr;656 use jrsonnet_interner::IStr;
614 use jrsonnet_parser::*;657 use jrsonnet_parser::*;
615 use std::{658 use std::{
624 state.run_in_state(|| {667 state.run_in_state(|| {
625 state668 state
626 .push(669 .push(
627 Some(&ExprLocation(PathBuf::from("test1.jsonnet").into(), 10, 20)),670 &ExprLocation(PathBuf::from("test1.jsonnet").into(), 10, 20),
628 || "outer".to_owned(),671 || "outer".to_owned(),
629 || {672 || {
630 state.push(673 state.push(
631 Some(&ExprLocation(PathBuf::from("test2.jsonnet").into(), 30, 40)),674 &ExprLocation(PathBuf::from("test2.jsonnet").into(), 30, 40),
632 || "inner".to_owned(),675 || "inner".to_owned(),
633 || Err(RuntimeError("".into()).into()),676 || Err(RuntimeError("".into()).into()),
634 )?;677 )?;
1028 "{ x: 1, y: 2 } == { x: 1, y: 2 }",1071 "{ x: 1, y: 2 } == { x: 1, y: 2 }",
1029 &ParserSettings {1072 &ParserSettings {
1030 file_name: PathBuf::from("equality").into(),1073 file_name: PathBuf::from("equality").into(),
1031 loc_data: true,
1032 }1074 }
1033 )1075 )
1034 );1076 );
10421084
1043 evaluator.with_stdlib();1085 evaluator.with_stdlib();
10441086
1045 #[derive(Trace, Finalize)]1087 #[derive(Trace)]
1046 struct NativeAdd;1088 struct NativeAdd;
1047 impl NativeCallbackHandler for NativeAdd {1089 impl NativeCallbackHandler for NativeAdd {
1048 fn call(&self, from: Option<Rc<Path>>, args: &[Val]) -> crate::error::Result<Val> {1090 fn call(&self, from: Rc<Path>, args: &[Val]) -> crate::error::Result<Val> {
1049 assert_eq!(1091 assert_eq!(&from as &Path, &PathBuf::from("native_caller.jsonnet"));
1050 &from.unwrap() as &Path,
1051 &PathBuf::from("native_caller.jsonnet")
1052 );
1053 match (&args[0], &args[1]) {1092 match (&args[0], &args[1]) {
1058 }1097 }
1059 evaluator.settings_mut().ext_natives.insert(1098 evaluator.settings_mut().ext_natives.insert(
1060 "native_add".into(),1099 "native_add".into(),
1061 Gc::new(NativeCallback::new(1100 Cc::new(NativeCallback::new(
1062 ParamsDesc(Rc::new(vec![1101 ParamsDesc(Rc::new(vec![
1063 Param("a".into(), None),1102 Param("a".into(), None),
1064 Param("b".into(), None),1103 Param("b".into(), None),
1065 ])),1104 ])),
1066 Box::new(NativeAdd),1105 TraceBox(Box::new(NativeAdd)),
1067 )),1106 )),
1068 );1107 );
1069 evaluator.evaluate_snippet_raw(1108 evaluator.evaluate_snippet_raw(
modifiedcrates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth
1use jrsonnet_gc::{Gc, Trace};1use gcmodule::{Cc, Trace};
2use jrsonnet_interner::IStr;2use jrsonnet_interner::IStr;
3use rustc_hash::FxHashMap;
43
5use crate::LazyVal;4use crate::{GcHashMap, LazyVal};
65
7#[derive(Trace)]6#[derive(Trace)]
8#[trivially_drop]7#[force_tracking]
9pub struct LayeredHashMapInternals {8pub struct LayeredHashMapInternals {
10 parent: Option<LayeredHashMap>,9 parent: Option<LayeredHashMap>,
11 current: FxHashMap<IStr, LazyVal>,10 current: GcHashMap<IStr, LazyVal>,
12}11}
1312
14#[derive(Trace)]13#[derive(Trace)]
15#[trivially_drop]
16pub struct LayeredHashMap(Gc<LayeredHashMapInternals>);14pub struct LayeredHashMap(Cc<LayeredHashMapInternals>);
1715
18impl LayeredHashMap {16impl LayeredHashMap {
19 pub fn extend(self, new_layer: FxHashMap<IStr, LazyVal>) -> Self {17 pub fn extend(self, new_layer: GcHashMap<IStr, LazyVal>) -> Self {
20 Self(Gc::new(LayeredHashMapInternals {18 Self(Cc::new(LayeredHashMapInternals {
21 parent: Some(self),19 parent: Some(self),
22 current: new_layer,20 current: new_layer,
23 }))21 }))
4947
50impl Default for LayeredHashMap {48impl Default for LayeredHashMap {
51 fn default() -> Self {49 fn default() -> Self {
52 Self(Gc::new(LayeredHashMapInternals {50 Self(Cc::new(LayeredHashMapInternals {
53 parent: None,51 parent: None,
54 current: FxHashMap::default(),52 current: GcHashMap::new(),
55 }))53 }))
56 }54 }
57}55}
modifiedcrates/jrsonnet-evaluator/src/native.rsdiffbeforeafterboth
1#![allow(clippy::type_complexity)]1#![allow(clippy::type_complexity)]
22
3use crate::gc::TraceBox;
3use crate::{error::Result, Val};4use crate::{error::Result, Val};
4use jrsonnet_gc::Trace;5use gcmodule::Trace;
5use jrsonnet_parser::ParamsDesc;6use jrsonnet_parser::ParamsDesc;
6use std::fmt::Debug;7use std::fmt::Debug;
7use std::path::Path;8use std::path::Path;
8use std::rc::Rc;9use std::rc::Rc;
910
10pub trait NativeCallbackHandler: Trace {11pub trait NativeCallbackHandler: Trace {
11 fn call(&self, from: Option<Rc<Path>>, args: &[Val]) -> Result<Val>;12 fn call(&self, from: Rc<Path>, args: &[Val]) -> Result<Val>;
12}13}
1314
14#[derive(Trace)]15#[derive(Trace)]
15#[trivially_drop]
16pub struct NativeCallback {16pub struct NativeCallback {
17 pub params: ParamsDesc,17 pub params: ParamsDesc,
18 handler: Box<dyn NativeCallbackHandler>,18 handler: TraceBox<dyn NativeCallbackHandler>,
19}19}
20impl NativeCallback {20impl NativeCallback {
21 pub fn new(params: ParamsDesc, handler: Box<dyn NativeCallbackHandler>) -> Self {21 pub fn new(params: ParamsDesc, handler: TraceBox<dyn NativeCallbackHandler>) -> Self {
22 Self { params, handler }22 Self { params, handler }
23 }23 }
24 pub fn call(&self, caller: Option<Rc<Path>>, args: &[Val]) -> Result<Val> {24 pub fn call(&self, caller: Rc<Path>, args: &[Val]) -> Result<Val> {
25 self.handler.call(caller, args)25 self.handler.call(caller, args)
26 }26 }
27}27}
modifiedcrates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth
1use crate::gc::{GcHashMap, GcHashSet, TraceBox};
1use crate::operator::evaluate_add_op;2use crate::operator::evaluate_add_op;
2use crate::{Bindable, LazyBinding, LazyVal, Result, Val};3use crate::{cc_ptr_eq, Bindable, LazyBinding, LazyVal, Result, Val};
3use jrsonnet_gc::{Gc, GcCell, Trace};4use gcmodule::{Cc, Trace};
4use jrsonnet_interner::IStr;5use jrsonnet_interner::IStr;
5use jrsonnet_parser::{ExprLocation, Visibility};6use jrsonnet_parser::{ExprLocation, Visibility};
6use rustc_hash::{FxHashMap, FxHashSet, FxHasher};7use rustc_hash::FxHashMap;
7use std::collections::HashMap;8use std::cell::RefCell;
9use std::fmt::Debug;
8use std::hash::{Hash, Hasher};10use std::hash::{Hash, Hasher};
9use std::{fmt::Debug, hash::BuildHasherDefault};
1011
11#[derive(Debug, Trace)]12#[derive(Debug, Trace)]
12#[trivially_drop]
13pub struct ObjMember {13pub struct ObjMember {
14 pub add: bool,14 pub add: bool,
15 pub visibility: Visibility,15 pub visibility: Visibility,
24// Field => This24// Field => This
25type CacheKey = (IStr, ObjValue);25type CacheKey = (IStr, ObjValue);
26#[derive(Trace)]26#[derive(Trace)]
27#[trivially_drop]27#[force_tracking]
28pub struct ObjValueInternals {28pub struct ObjValueInternals {
29 super_obj: Option<ObjValue>,29 super_obj: Option<ObjValue>,
30 assertions: Gc<Vec<Box<dyn ObjectAssertion>>>,30 assertions: Cc<Vec<TraceBox<dyn ObjectAssertion>>>,
31 assertions_ran: GcCell<FxHashSet<ObjValue>>,31 assertions_ran: RefCell<GcHashSet<ObjValue>>,
32 this_obj: Option<ObjValue>,32 this_obj: Option<ObjValue>,
33 this_entries: Gc<FxHashMap<IStr, ObjMember>>,33 this_entries: Cc<GcHashMap<IStr, ObjMember>>,
34 value_cache: GcCell<FxHashMap<CacheKey, Option<Val>>>,34 value_cache: RefCell<GcHashMap<CacheKey, Option<Val>>>,
35}35}
3636
37#[derive(Clone, Trace)]37#[derive(Clone, Trace)]
38#[trivially_drop]
39pub struct ObjValue(pub(crate) Gc<ObjValueInternals>);38pub struct ObjValue(pub(crate) Cc<ObjValueInternals>);
40impl Debug for ObjValue {39impl Debug for ObjValue {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 if let Some(super_obj) = self.0.super_obj.as_ref() {41 if let Some(super_obj) = self.0.super_obj.as_ref() {
65impl ObjValue {64impl ObjValue {
66 pub fn new(65 pub fn new(
67 super_obj: Option<Self>,66 super_obj: Option<Self>,
68 this_entries: Gc<FxHashMap<IStr, ObjMember>>,67 this_entries: Cc<GcHashMap<IStr, ObjMember>>,
69 assertions: Gc<Vec<Box<dyn ObjectAssertion>>>,68 assertions: Cc<Vec<TraceBox<dyn ObjectAssertion>>>,
70 ) -> Self {69 ) -> Self {
71 Self(Gc::new(ObjValueInternals {70 Self(Cc::new(ObjValueInternals {
72 super_obj,71 super_obj,
73 assertions,72 assertions,
74 assertions_ran: GcCell::new(FxHashSet::default()),73 assertions_ran: RefCell::new(GcHashSet::new()),
75 this_obj: None,74 this_obj: None,
76 this_entries,75 this_entries,
77 value_cache: GcCell::new(FxHashMap::default()),76 value_cache: RefCell::new(GcHashMap::new()),
78 }))77 }))
79 }78 }
80 pub fn new_empty() -> Self {79 pub fn new_empty() -> Self {
81 Self::new(None, Gc::new(FxHashMap::default()), Gc::new(Vec::new()))80 Self::new(None, Cc::new(GcHashMap::new()), Cc::new(Vec::new()))
82 }81 }
83 pub fn extend_from(&self, super_obj: Self) -> Self {82 pub fn extend_from(&self, super_obj: Self) -> Self {
84 match &self.0.super_obj {83 match &self.0.super_obj {
95 }94 }
96 }95 }
97 pub fn with_this(&self, this_obj: Self) -> Self {96 pub fn with_this(&self, this_obj: Self) -> Self {
98 Self(Gc::new(ObjValueInternals {97 Self(Cc::new(ObjValueInternals {
99 super_obj: self.0.super_obj.clone(),98 super_obj: self.0.super_obj.clone(),
100 assertions: self.0.assertions.clone(),99 assertions: self.0.assertions.clone(),
101 assertions_ran: GcCell::new(FxHashSet::default()),100 assertions_ran: RefCell::new(GcHashSet::new()),
102 this_obj: Some(this_obj),101 this_obj: Some(this_obj),
103 this_entries: self.0.this_entries.clone(),102 this_entries: self.0.this_entries.clone(),
104 value_cache: GcCell::new(FxHashMap::default()),103 value_cache: RefCell::new(GcHashMap::new()),
105 }))104 }))
106 }105 }
107106
117 }116 }
118117
119 /// Run callback for every field found in object118 /// Run callback for every field found in object
120 pub(crate) fn enum_fields(&self, handler: &mut impl FnMut(&IStr, &Visibility) -> bool) -> bool {119 pub(crate) fn enum_fields(&self, handler: &mut impl FnMut(&IStr, &ObjMember) -> bool) -> bool {
121 if let Some(s) = &self.0.super_obj {120 if let Some(s) = &self.0.super_obj {
122 if s.enum_fields(handler) {121 if s.enum_fields(handler) {
123 return true;122 return true;
124 }123 }
125 }124 }
126 for (name, member) in self.0.this_entries.iter() {125 for (name, member) in self.0.this_entries.iter() {
127 if handler(name, &member.visibility) {126 if handler(name, &member) {
128 return true;127 return true;
129 }128 }
130 }129 }
133132
134 pub fn fields_visibility(&self) -> FxHashMap<IStr, bool> {133 pub fn fields_visibility(&self) -> FxHashMap<IStr, bool> {
135 let mut out = FxHashMap::default();134 let mut out = FxHashMap::default();
136 self.enum_fields(&mut |name, visibility| {135 self.enum_fields(&mut |name, member| {
137 match visibility {136 match member.visibility {
138 Visibility::Normal => {137 Visibility::Normal => {
139 let entry = out.entry(name.to_owned());138 let entry = out.entry(name.to_owned());
140 entry.or_insert(true);139 entry.or_insert(true);
211 }210 }
212211
213 pub fn extend_with_field(self, key: IStr, value: ObjMember) -> Self {212 pub fn extend_with_field(self, key: IStr, value: ObjMember) -> Self {
214 let mut new = FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());213 let mut new = GcHashMap::with_capacity(1);
215 new.insert(key, value);214 new.insert(key, value);
216 Self::new(Some(self), Gc::new(new), Gc::new(Vec::new()))215 Self::new(Some(self), Cc::new(new), Cc::new(Vec::new()))
217 }216 }
218217
219 fn get_raw(&self, key: IStr, real_this: Option<&Self>) -> Result<Option<Val>> {218 fn get_raw(&self, key: IStr, real_this: Option<&Self>) -> Result<Option<Val>> {
270 }269 }
271270
272 pub fn ptr_eq(a: &Self, b: &Self) -> bool {271 pub fn ptr_eq(a: &Self, b: &Self) -> bool {
273 Gc::ptr_eq(&a.0, &b.0)272 cc_ptr_eq(&a.0, &b.0)
274 }273 }
275}274}
276275
277impl PartialEq for ObjValue {276impl PartialEq for ObjValue {
278 fn eq(&self, other: &Self) -> bool {277 fn eq(&self, other: &Self) -> bool {
279 Gc::ptr_eq(&self.0, &other.0)278 cc_ptr_eq(&self.0, &other.0)
280 }279 }
281}280}
282281
289288
290pub struct ObjValueBuilder {289pub struct ObjValueBuilder {
291 super_obj: Option<ObjValue>,290 super_obj: Option<ObjValue>,
292 map: FxHashMap<IStr, ObjMember>,291 map: GcHashMap<IStr, ObjMember>,
293 assertions: Vec<Box<dyn ObjectAssertion>>,292 assertions: Vec<TraceBox<dyn ObjectAssertion>>,
294}293}
295impl ObjValueBuilder {294impl ObjValueBuilder {
296 pub fn new() -> Self {295 pub fn new() -> Self {
299 pub fn with_capacity(capacity: usize) -> Self {298 pub fn with_capacity(capacity: usize) -> Self {
300 Self {299 Self {
301 super_obj: None,300 super_obj: None,
302 map: HashMap::with_capacity_and_hasher(301 map: GcHashMap::with_capacity(capacity),
303 capacity,
304 BuildHasherDefault::<FxHasher>::default(),
305 ),
306 assertions: Vec::new(),302 assertions: Vec::new(),
307 }303 }
315 self311 self
316 }312 }
317313
318 pub fn assert(&mut self, assertion: Box<dyn ObjectAssertion>) -> &mut Self {314 pub fn assert(&mut self, assertion: TraceBox<dyn ObjectAssertion>) -> &mut Self {
319 self.assertions.push(assertion);315 self.assertions.push(assertion);
320 self316 self
321 }317 }
330 }326 }
331327
332 pub fn build(self) -> ObjValue {328 pub fn build(self) -> ObjValue {
333 ObjValue::new(self.super_obj, Gc::new(self.map), Gc::new(self.assertions))329 ObjValue::new(self.super_obj, Cc::new(self.map), Cc::new(self.assertions))
334 }330 }
335}331}
336impl Default for ObjValueBuilder {332impl Default for ObjValueBuilder {
364 pub fn hide(self) -> Self {360 pub fn hide(self) -> Self {
365 self.with_visibility(Visibility::Hidden)361 self.with_visibility(Visibility::Hidden)
366 }362 }
367 pub fn with_location(mut self, location: Option<ExprLocation>) -> Self {363 pub fn with_location(mut self, location: ExprLocation) -> Self {
368 self.location = location;364 self.location = Some(location);
369 self365 self
370 }366 }
371 pub fn value(self, value: Val) -> &'v mut ObjValueBuilder {367 pub fn value(self, value: Val) -> &'v mut ObjValueBuilder {
372 self.binding(LazyBinding::Bound(LazyVal::new_resolved(value)))368 self.binding(LazyBinding::Bound(LazyVal::new_resolved(value)))
373 }369 }
374 pub fn bindable(self, bindable: Box<dyn Bindable>) -> &'v mut ObjValueBuilder {370 pub fn bindable(self, bindable: TraceBox<dyn Bindable>) -> &'v mut ObjValueBuilder {
375 self.binding(LazyBinding::Bindable(Gc::new(bindable)))371 self.binding(LazyBinding::Bindable(Cc::new(bindable)))
376 }372 }
377 pub fn binding(self, binding: LazyBinding) -> &'v mut ObjValueBuilder {373 pub fn binding(self, binding: LazyBinding) -> &'v mut ObjValueBuilder {
378 self.value.map.insert(374 self.value.map.insert(
modifiedcrates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth
119 .trace()119 .trace()
120 .0120 .0
121 .iter()121 .iter()
122 .map(|el| {122 .map(|el| &el.location)
123 el.location.as_ref().map(|l| {123 .map(|location| {
124 use std::fmt::Write;124 use std::fmt::Write;
125 if let Some(location) = location {
125 let mut resolved_path = self.resolver.resolve(&l.0);126 let mut resolved_path = self.resolver.resolve(&location.0);
126 // TODO: Process all trace elements first127 // TODO: Process all trace elements first
127 let location = evaluation_state.map_source_locations(&l.0, &[l.1, l.2]);128 let location = evaluation_state
129 .map_source_locations(&location.0, &[location.1, location.2]);
128 write!(resolved_path, ":").unwrap();130 write!(resolved_path, ":").unwrap();
129 print_code_location(&mut resolved_path, &location[0], &location[1]).unwrap();131 print_code_location(&mut resolved_path, &location[0], &location[1]).unwrap();
132 write!(resolved_path, ":").unwrap();
130 resolved_path133 Some(resolved_path)
134 } else {
135 None
136 }
131 })137 })
132 })
133 .collect::<Vec<_>>();138 .collect::<Vec<_>>();
134 let align = file_names139 let align = file_names
135 .iter()140 .iter()
139 .unwrap_or(0);144 .unwrap_or(0);
140 for (el, file) in error.trace().0.iter().zip(file_names) {145 for (el, file) in error.trace().0.iter().zip(file_names) {
141 writeln!(out)?;146 writeln!(out)?;
147 if let Some(file) = file {
142 write!(148 write!(
143 out,149 out,
144 "{:<p$}{:<w$}: {}",150 "{:<p$}{:<w$} {}",
145 "",151 "",
146 file.unwrap_or_else(|| "".to_owned()),152 file,
147 el.desc,153 el.desc,
148 p = self.padding,154 p = self.padding,
149 w = align155 w = align
150 )?;156 )?;
157 } else {
158 write!(out, "{:<p$}{}", "", el.desc, p = self.padding,)?;
159 }
151 }160 }
152 Ok(())161 Ok(())
153 }162 }
178 start_end[0].column,187 start_end[0].column,
179 )?;188 )?;
180 } else {189 } else {
181 write!(out, " at {}", desc,)?;190 write!(out, " during {}", desc)?;
182 }191 }
183 }192 }
184 Ok(())193 Ok(())
206 } = error.error()215 } = error.error()
207 {216 {
208 writeln!(out)?;217 writeln!(out)?;
209 let mut offset = error.location.offset;218 let offset = error.location.offset;
210 if offset >= source_code.len() {
211 offset = source_code.len() - 1;
212 }
213 let mut location = offset_to_location(source_code, &[offset])219 let location = offset_to_location(source_code, &[offset])
214 .into_iter()220 .into_iter()
215 .next()221 .next()
216 .unwrap();222 .unwrap();
217 if location.column >= 1 {223 let mut end_location = location.clone();
218 location.column -= 1;224 end_location.offset += 1;
219 }
220225
221 self.print_snippet(226 self.print_snippet(
222 out,227 out,
223 source_code,228 source_code,
224 path,229 path,
225 &location,230 &location,
226 &location,231 &end_location,
227 "^ syntax error",232 "syntax error",
228 )?;233 )?;
229 }234 }
230 let trace = &error.trace();235 let trace = &error.trace();
289 annotation_type: AnnotationType::Error,294 annotation_type: AnnotationType::Error,
290 range: (295 range: (
291 start.offset - start.line_start_offset,296 start.offset - start.line_start_offset,
292 end.offset - start.line_start_offset,297 (end.offset - start.line_start_offset).min(source_fragment.len()),
293 ),298 ),
294 }],299 }],
295 }],300 }],
modifiedcrates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth
1use std::{fmt::Display, rc::Rc};1use std::{fmt::Display, rc::Rc};
22
3use crate::{3use crate::{Val, error::{Error, LocError, Result}, push_description_frame};
4 error::{Error, LocError, Result},
5 push_frame, Val,
6};
7use jrsonnet_gc::Trace;4use gcmodule::Trace;
8use jrsonnet_parser::ExprLocation;
9use jrsonnet_types::{ComplexValType, ValType};5use jrsonnet_types::{ComplexValType, ValType};
10use thiserror::Error;6use thiserror::Error;
117
22}18}
2319
24#[derive(Debug, Error, Clone, Trace)]20#[derive(Debug, Error, Clone, Trace)]
25#[trivially_drop]
26pub enum TypeError {21pub enum TypeError {
27 #[error("expected {0}, got {1}")]22 #[error("expected {0}, got {1}")]
28 ExpectedGot(ComplexValType, ValType),23 ExpectedGot(ComplexValType, ValType),
29 #[error("missing property {0} from {1:?}")]24 #[error("missing property {0} from {1:?}")]
30 MissingProperty(Rc<str>, ComplexValType),25 MissingProperty(#[skip_trace] Rc<str>, ComplexValType),
31 #[error("every failed from {0}:\n{1}")]26 #[error("every failed from {0}:\n{1}")]
32 UnionFailed(ComplexValType, TypeLocErrorList),27 UnionFailed(ComplexValType, TypeLocErrorList),
33 #[error(28 #[error(
44}39}
4540
46#[derive(Debug, Clone, Trace)]41#[derive(Debug, Clone, Trace)]
47#[trivially_drop]
48pub struct TypeLocError(Box<TypeError>, ValuePathStack);42pub struct TypeLocError(Box<TypeError>, ValuePathStack);
49impl From<TypeError> for TypeLocError {43impl From<TypeError> for TypeLocError {
50 fn from(e: TypeError) -> Self {44 fn from(e: TypeError) -> Self {
67}61}
6862
69#[derive(Debug, Clone, Trace)]63#[derive(Debug, Clone, Trace)]
70#[trivially_drop]
71pub struct TypeLocErrorList(Vec<TypeLocError>);64pub struct TypeLocErrorList(Vec<TypeLocError>);
72impl Display for TypeLocErrorList {65impl Display for TypeLocErrorList {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 }90 }
98}91}
9992
100fn push_type(93fn push_type_description(
101 location: Option<&ExprLocation>,
102 error_reason: impl Fn() -> String,94 error_reason: impl Fn() -> String,
103 path: impl Fn() -> ValuePathItem,95 path: impl Fn() -> ValuePathItem,
104 item: impl Fn() -> Result<()>,96 item: impl Fn() -> Result<()>,
105) -> Result<()> {97) -> Result<()> {
106 push_frame(location, error_reason, || match item() {98 push_description_frame(error_reason, || match item() {
107 Ok(_) => Ok(()),99 Ok(_) => Ok(()),
108 Err(mut e) => {100 Err(mut e) => {
109 if let Error::TypeError(e) = &mut e.error_mut() {101 if let Error::TypeError(e) = &mut e.error_mut() {
131}123}
132124
133#[derive(Clone, Debug, Trace)]125#[derive(Clone, Debug, Trace)]
134#[trivially_drop]
135enum ValuePathItem {126enum ValuePathItem {
136 Field(Rc<str>),127 Field(#[skip_trace] Rc<str>),
137 Index(u64),128 Index(u64),
138}129}
139impl Display for ValuePathItem {130impl Display for ValuePathItem {
147}138}
148139
149#[derive(Clone, Debug, Trace)]140#[derive(Clone, Debug, Trace)]
150#[trivially_drop]
151struct ValuePathStack(Vec<ValuePathItem>);141struct ValuePathStack(Vec<ValuePathItem>);
152impl Display for ValuePathStack {142impl Display for ValuePathStack {
153 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183 Self::Array(elem_type) => match value {173 Self::Array(elem_type) => match value {
184 Val::Arr(a) => {174 Val::Arr(a) => {
185 for (i, item) in a.iter().enumerate() {175 for (i, item) in a.iter().enumerate() {
186 push_type(176 push_type_description(
187 None,
188 || format!("array index {}", i),177 || format!("array index {}", i),
189 || ValuePathItem::Index(i as u64),178 || ValuePathItem::Index(i as u64),
190 || elem_type.check(&item.clone()?),179 || elem_type.check(&item.clone()?),
197 Self::ArrayRef(elem_type) => match value {186 Self::ArrayRef(elem_type) => match value {
198 Val::Arr(a) => {187 Val::Arr(a) => {
199 for (i, item) in a.iter().enumerate() {188 for (i, item) in a.iter().enumerate() {
200 push_type(189 push_type_description(
201 None,
202 || format!("array index {}", i),190 || format!("array index {}", i),
203 || ValuePathItem::Index(i as u64),191 || ValuePathItem::Index(i as u64),
204 || elem_type.check(&item.clone()?),192 || elem_type.check(&item.clone()?),
212 Val::Obj(obj) => {200 Val::Obj(obj) => {
213 for (k, v) in elems.iter() {201 for (k, v) in elems.iter() {
214 if let Some(got_v) = obj.get((*k).into())? {202 if let Some(got_v) = obj.get((*k).into())? {
215 push_type(203 push_type_description(
216 None,
217 || format!("property {}", k),204 || format!("property {}", k),
218 || ValuePathItem::Field((*k).into()),205 || ValuePathItem::Field((*k).into()),
219 || v.check(&got_v),206 || v.check(&got_v),
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
6 ManifestYamlOptions,6 ManifestYamlOptions,
7 },7 },
8 },8 },
9 cc_ptr_eq,
9 error::{Error::*, LocError},10 error::{Error::*, LocError},
10 evaluate,11 evaluate,
11 function::{parse_function_call, parse_function_call_map, place_args},12 function::{parse_function_call, parse_function_call_map, place_args},
13 gc::TraceBox,
12 native::NativeCallback,14 native::NativeCallback,
13 throw, Context, ObjValue, Result,15 throw, Context, ObjValue, Result,
14};16};
15use jrsonnet_gc::{Gc, GcCell, Trace};17use gcmodule::{Cc, Trace};
16use jrsonnet_interner::IStr;18use jrsonnet_interner::IStr;
17use jrsonnet_parser::{ArgsDesc, ExprLocation, LocExpr, ParamsDesc};19use jrsonnet_parser::{ArgsDesc, ExprLocation, LocExpr, ParamsDesc};
18use jrsonnet_types::ValType;20use jrsonnet_types::ValType;
19use std::{collections::HashMap, fmt::Debug, rc::Rc};21use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};
2022
21pub trait LazyValValue: Trace {23pub trait LazyValValue: Trace {
22 fn get(self: Box<Self>) -> Result<Val>;24 fn get(self: Box<Self>) -> Result<Val>;
23}25}
2426
25#[derive(Trace)]27#[derive(Trace)]
26#[trivially_drop]
27enum LazyValInternals {28enum LazyValInternals {
28 Computed(Val),29 Computed(Val),
29 Errored(LocError),30 Errored(LocError),
30 Waiting(Box<dyn LazyValValue>),31 Waiting(TraceBox<dyn LazyValValue>),
31 Pending,32 Pending,
32}33}
3334
34#[derive(Clone, Trace)]35#[derive(Clone, Trace)]
35#[trivially_drop]
36pub struct LazyVal(Gc<GcCell<LazyValInternals>>);36pub struct LazyVal(Cc<RefCell<LazyValInternals>>);
37impl LazyVal {37impl LazyVal {
38 pub fn new(f: Box<dyn LazyValValue>) -> Self {38 pub fn new(f: TraceBox<dyn LazyValValue>) -> Self {
39 Self(Gc::new(GcCell::new(LazyValInternals::Waiting(f))))39 Self(Cc::new(RefCell::new(LazyValInternals::Waiting(f))))
40 }40 }
41 pub fn new_resolved(val: Val) -> Self {41 pub fn new_resolved(val: Val) -> Self {
42 Self(Gc::new(GcCell::new(LazyValInternals::Computed(val))))42 Self(Cc::new(RefCell::new(LazyValInternals::Computed(val))))
43 }43 }
44 pub fn evaluate(&self) -> Result<Val> {44 pub fn evaluate(&self) -> Result<Val> {
45 match &*self.0.borrow() {45 match &*self.0.borrow() {
55 } else {55 } else {
56 unreachable!()56 unreachable!()
57 };57 };
58 let new_value = match value.get() {58 let new_value = match value.0.get() {
59 Ok(v) => v,59 Ok(v) => v,
60 Err(e) => {60 Err(e) => {
61 *self.0.borrow_mut() = LazyValInternals::Errored(e.clone());61 *self.0.borrow_mut() = LazyValInternals::Errored(e.clone());
74}74}
75impl PartialEq for LazyVal {75impl PartialEq for LazyVal {
76 fn eq(&self, other: &Self) -> bool {76 fn eq(&self, other: &Self) -> bool {
77 Gc::ptr_eq(&self.0, &other.0)77 cc_ptr_eq(&self.0, &other.0)
78 }78 }
79}79}
8080
81#[derive(Debug, PartialEq, Trace)]81#[derive(Debug, PartialEq, Trace)]
82#[trivially_drop]
83pub struct FuncDesc {82pub struct FuncDesc {
84 pub name: IStr,83 pub name: IStr,
85 pub ctx: Context,84 pub ctx: Context,
88}87}
8988
90#[derive(Debug, Trace)]89#[derive(Debug, Trace)]
91#[trivially_drop]
92pub enum FuncVal {90pub enum FuncVal {
93 /// Plain function implemented in jsonnet91 /// Plain function implemented in jsonnet
94 Normal(FuncDesc),92 Normal(FuncDesc),
95 /// Standard library function93 /// Standard library function
96 Intrinsic(IStr),94 Intrinsic(IStr),
97 /// Library functions implemented in native95 /// Library functions implemented in native
98 NativeExt(IStr, Gc<NativeCallback>),96 NativeExt(IStr, Cc<NativeCallback>),
99}97}
10098
101impl PartialEq for FuncVal {99impl PartialEq for FuncVal {
122 pub fn evaluate(120 pub fn evaluate(
123 &self,121 &self,
124 call_ctx: Context,122 call_ctx: Context,
125 loc: Option<&ExprLocation>,123 loc: &ExprLocation,
126 args: &ArgsDesc,124 args: &ArgsDesc,
127 tailstrict: bool,125 tailstrict: bool,
128 ) -> Result<Val> {126 ) -> Result<Val> {
145 for p in handler.params.0.iter() {143 for p in handler.params.0.iter() {
146 out_args.push(args.binding(p.0.clone())?.evaluate()?);144 out_args.push(args.binding(p.0.clone())?.evaluate()?);
147 }145 }
148 Ok(handler.call(loc.map(|l| l.0.clone()), &out_args)?)146 Ok(handler.call(loc.0.clone(), &out_args)?)
149 }147 }
150 }148 }
151 }149 }
194}192}
195193
196#[derive(Debug, Clone, Trace)]194#[derive(Debug, Clone, Trace)]
197#[trivially_drop]195#[force_tracking]
198pub enum ArrValue {196pub enum ArrValue {
199 Lazy(Gc<Vec<LazyVal>>),197 Lazy(Cc<Vec<LazyVal>>),
200 Eager(Gc<Vec<Val>>),198 Eager(Cc<Vec<Val>>),
201 Extended(Box<(Self, Self)>),199 Extended(Box<(Self, Self)>),
202}200}
203impl ArrValue {201impl ArrValue {
204 pub fn new_eager() -> Self {202 pub fn new_eager() -> Self {
205 Self::Eager(Gc::new(Vec::new()))203 Self::Eager(Cc::new(Vec::new()))
206 }204 }
207205
208 pub fn len(&self) -> usize {206 pub fn len(&self) -> usize {
253 }251 }
254 }252 }
255253
256 pub fn evaluated(&self) -> Result<Gc<Vec<Val>>> {254 pub fn evaluated(&self) -> Result<Cc<Vec<Val>>> {
257 Ok(match self {255 Ok(match self {
258 Self::Lazy(vec) => {256 Self::Lazy(vec) => {
259 let mut out = Vec::with_capacity(vec.len());257 let mut out = Vec::with_capacity(vec.len());
260 for item in vec.iter() {258 for item in vec.iter() {
261 out.push(item.evaluate()?);259 out.push(item.evaluate()?);
262 }260 }
263 Gc::new(out)261 Cc::new(out)
264 }262 }
265 Self::Eager(vec) => vec.clone(),263 Self::Eager(vec) => vec.clone(),
266 Self::Extended(_v) => {264 Self::Extended(_v) => {
267 let mut out = Vec::with_capacity(self.len());265 let mut out = Vec::with_capacity(self.len());
268 for item in self.iter() {266 for item in self.iter() {
269 out.push(item?);267 out.push(item?);
270 }268 }
271 Gc::new(out)269 Cc::new(out)
272 }270 }
273 })271 })
274 }272 }
294 Self::Lazy(vec) => {292 Self::Lazy(vec) => {
295 let mut out = (&vec as &Vec<_>).clone();293 let mut out = (&vec as &Vec<_>).clone();
296 out.reverse();294 out.reverse();
297 Self::Lazy(Gc::new(out))295 Self::Lazy(Cc::new(out))
298 }296 }
299 Self::Eager(vec) => {297 Self::Eager(vec) => {
300 let mut out = (&vec as &Vec<_>).clone();298 let mut out = (&vec as &Vec<_>).clone();
301 out.reverse();299 out.reverse();
302 Self::Eager(Gc::new(out))300 Self::Eager(Cc::new(out))
303 }301 }
304 Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),302 Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),
305 }303 }
312 out.push(mapper(value?)?);310 out.push(mapper(value?)?);
313 }311 }
314312
315 Ok(Self::Eager(Gc::new(out)))313 Ok(Self::Eager(Cc::new(out)))
316 }314 }
317315
318 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {316 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {
325 }323 }
326 }324 }
327325
328 Ok(Self::Eager(Gc::new(out)))326 Ok(Self::Eager(Cc::new(out)))
329 }327 }
330328
331 pub fn ptr_eq(a: &Self, b: &Self) -> bool {329 pub fn ptr_eq(a: &Self, b: &Self) -> bool {
332 match (a, b) {330 match (a, b) {
333 (Self::Lazy(a), Self::Lazy(b)) => Gc::ptr_eq(a, b),331 (Self::Lazy(a), Self::Lazy(b)) => cc_ptr_eq(a, b),
334 (Self::Eager(a), Self::Eager(b)) => Gc::ptr_eq(a, b),332 (Self::Eager(a), Self::Eager(b)) => cc_ptr_eq(a, b),
335 _ => false,333 _ => false,
336 }334 }
337 }335 }
338}336}
339337
340impl From<Vec<LazyVal>> for ArrValue {338impl From<Vec<LazyVal>> for ArrValue {
341 fn from(v: Vec<LazyVal>) -> Self {339 fn from(v: Vec<LazyVal>) -> Self {
342 Self::Lazy(Gc::new(v))340 Self::Lazy(Cc::new(v))
343 }341 }
344}342}
345343
346impl From<Vec<Val>> for ArrValue {344impl From<Vec<Val>> for ArrValue {
347 fn from(v: Vec<Val>) -> Self {345 fn from(v: Vec<Val>) -> Self {
348 Self::Eager(Gc::new(v))346 Self::Eager(Cc::new(v))
349 }347 }
350}348}
351349
355}353}
356354
357#[derive(Debug, Clone, Trace)]355#[derive(Debug, Clone, Trace)]
358#[trivially_drop]
359pub enum Val {356pub enum Val {
360 Bool(bool),357 Bool(bool),
361 Null,358 Null,
362 Str(IStr),359 Str(IStr),
363 Num(f64),360 Num(f64),
364 Arr(ArrValue),361 Arr(ArrValue),
365 Obj(ObjValue),362 Obj(ObjValue),
366 Func(Gc<FuncVal>),363 Func(Cc<FuncVal>),
367}364}
368365
369macro_rules! matches_unwrap {366macro_rules! matches_unwrap {
402 pub fn unwrap_arr(self) -> Result<ArrValue> {399 pub fn unwrap_arr(self) -> Result<ArrValue> {
403 Ok(matches_unwrap!(self, Self::Arr(v), v))400 Ok(matches_unwrap!(self, Self::Arr(v), v))
404 }401 }
405 pub fn unwrap_func(self) -> Result<Gc<FuncVal>> {402 pub fn unwrap_func(self) -> Result<Cc<FuncVal>> {
406 Ok(matches_unwrap!(self, Self::Func(v), v))403 Ok(matches_unwrap!(self, Self::Func(v), v))
407 }404 }
408 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {405 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {
modifiedcrates/jrsonnet-interner/Cargo.tomldiffbeforeafterboth
9[dependencies]9[dependencies]
10serde = { version = "1.0" }10serde = { version = "1.0" }
11rustc-hash = "1.1.0"11rustc-hash = "1.1.0"
12jrsonnet-gc = { version = "0.4.2", features = ["derive"] }12gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
1313
modifiedcrates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth
1use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};1use gcmodule::Trace;
2use rustc_hash::FxHashMap;2use rustc_hash::FxHashMap;
3use serde::{Deserialize, Serialize};3use serde::{Deserialize, Serialize};
4use std::{4use std::{
1111
12#[derive(Clone, PartialOrd, Ord, Eq)]12#[derive(Clone, PartialOrd, Ord, Eq)]
13pub struct IStr(Rc<str>);13pub struct IStr(Rc<str>);
14impl Finalize for IStr {}
15unsafe impl Trace for IStr {14impl Trace for IStr {
16 unsafe_empty_trace!();15 fn is_type_tracked() -> bool {
16 false
17 }
17}18}
1819
19impl Deref for IStr {20impl Deref for IStr {
modifiedcrates/jrsonnet-parser/Cargo.tomldiffbeforeafterboth
15jrsonnet-interner = { path = "../jrsonnet-interner", version = "0.4.2" }15jrsonnet-interner = { path = "../jrsonnet-interner", version = "0.4.2" }
1616
17peg = "0.7.0"17peg = "0.7.0"
18unescape = "0.1.0"
1918
20serde = { version = "1.0", features = ["derive", "rc"], optional = true }19serde = { version = "1.0", features = ["derive", "rc"], optional = true }
21jrsonnet-gc = { version = "0.4.2", features = ["derive"] }20gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
2221
23[dev-dependencies]22[dev-dependencies]
24jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }23jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
1use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};1use gcmodule::Trace;
2use jrsonnet_interner::IStr;2use jrsonnet_interner::IStr;
3#[cfg(feature = "deserialize")]3#[cfg(feature = "deserialize")]
4use serde::Deserialize;4use serde::Deserialize;
14#[cfg_attr(feature = "serialize", derive(Serialize))]14#[cfg_attr(feature = "serialize", derive(Serialize))]
15#[cfg_attr(feature = "deserialize", derive(Deserialize))]15#[cfg_attr(feature = "deserialize", derive(Deserialize))]
16#[derive(Debug, PartialEq, Trace)]16#[derive(Debug, PartialEq, Trace)]
17#[trivially_drop]
18pub enum FieldName {17pub enum FieldName {
19 /// {fixed: 2}18 /// {fixed: 2}
20 Fixed(IStr),19 Fixed(IStr),
25#[cfg_attr(feature = "serialize", derive(Serialize))]24#[cfg_attr(feature = "serialize", derive(Serialize))]
26#[cfg_attr(feature = "deserialize", derive(Deserialize))]25#[cfg_attr(feature = "deserialize", derive(Deserialize))]
27#[derive(Debug, Clone, Copy, PartialEq, Trace)]26#[derive(Debug, Clone, Copy, PartialEq, Trace)]
28#[trivially_drop]
29pub enum Visibility {27pub enum Visibility {
30 /// :28 /// :
31 Normal,29 Normal,
44#[cfg_attr(feature = "serialize", derive(Serialize))]42#[cfg_attr(feature = "serialize", derive(Serialize))]
45#[cfg_attr(feature = "deserialize", derive(Deserialize))]43#[cfg_attr(feature = "deserialize", derive(Deserialize))]
46#[derive(Clone, Debug, PartialEq, Trace)]44#[derive(Clone, Debug, PartialEq, Trace)]
47#[trivially_drop]
48pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);45pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);
4946
50#[cfg_attr(feature = "serialize", derive(Serialize))]47#[cfg_attr(feature = "serialize", derive(Serialize))]
51#[cfg_attr(feature = "deserialize", derive(Deserialize))]48#[cfg_attr(feature = "deserialize", derive(Deserialize))]
52#[derive(Debug, PartialEq, Trace)]49#[derive(Debug, PartialEq, Trace)]
53#[trivially_drop]
54pub struct FieldMember {50pub struct FieldMember {
55 pub name: FieldName,51 pub name: FieldName,
56 pub plus: bool,52 pub plus: bool,
62#[cfg_attr(feature = "serialize", derive(Serialize))]58#[cfg_attr(feature = "serialize", derive(Serialize))]
63#[cfg_attr(feature = "deserialize", derive(Deserialize))]59#[cfg_attr(feature = "deserialize", derive(Deserialize))]
64#[derive(Debug, PartialEq, Trace)]60#[derive(Debug, PartialEq, Trace)]
65#[trivially_drop]
66pub enum Member {61pub enum Member {
67 Field(FieldMember),62 Field(FieldMember),
68 BindStmt(BindSpec),63 BindStmt(BindSpec),
72#[cfg_attr(feature = "serialize", derive(Serialize))]67#[cfg_attr(feature = "serialize", derive(Serialize))]
73#[cfg_attr(feature = "deserialize", derive(Deserialize))]68#[cfg_attr(feature = "deserialize", derive(Deserialize))]
74#[derive(Debug, Clone, Copy, PartialEq, Trace)]69#[derive(Debug, Clone, Copy, PartialEq, Trace)]
75#[trivially_drop]
76pub enum UnaryOpType {70pub enum UnaryOpType {
77 Plus,71 Plus,
78 Minus,72 Minus,
99#[cfg_attr(feature = "serialize", derive(Serialize))]93#[cfg_attr(feature = "serialize", derive(Serialize))]
100#[cfg_attr(feature = "deserialize", derive(Deserialize))]94#[cfg_attr(feature = "deserialize", derive(Deserialize))]
101#[derive(Debug, Clone, Copy, PartialEq, Trace)]95#[derive(Debug, Clone, Copy, PartialEq, Trace)]
102#[trivially_drop]
103pub enum BinaryOpType {96pub enum BinaryOpType {
104 Mul,97 Mul,
105 Div,98 Div,
167#[cfg_attr(feature = "serialize", derive(Serialize))]160#[cfg_attr(feature = "serialize", derive(Serialize))]
168#[cfg_attr(feature = "deserialize", derive(Deserialize))]161#[cfg_attr(feature = "deserialize", derive(Deserialize))]
169#[derive(Debug, PartialEq, Trace)]162#[derive(Debug, PartialEq, Trace)]
170#[trivially_drop]
171pub struct Param(pub IStr, pub Option<LocExpr>);163pub struct Param(pub IStr, pub Option<LocExpr>);
172164
173/// Defined function parameters165/// Defined function parameters
174#[cfg_attr(feature = "serialize", derive(Serialize))]166#[cfg_attr(feature = "serialize", derive(Serialize))]
175#[cfg_attr(feature = "deserialize", derive(Deserialize))]167#[cfg_attr(feature = "deserialize", derive(Deserialize))]
176#[derive(Debug, Clone, PartialEq)]168#[derive(Debug, Clone, PartialEq, Trace)]
177pub struct ParamsDesc(pub Rc<Vec<Param>>);169pub struct ParamsDesc(pub Rc<Vec<Param>>);
178
179/// Safety:
180/// AST is acyclic, and there should be no gc pointers
181unsafe impl Trace for ParamsDesc {
182 unsafe_empty_trace!();
183}
184impl Finalize for ParamsDesc {}
185170
186impl Deref for ParamsDesc {171impl Deref for ParamsDesc {
187 type Target = Vec<Param>;172 type Target = Vec<Param>;
193#[cfg_attr(feature = "serialize", derive(Serialize))]178#[cfg_attr(feature = "serialize", derive(Serialize))]
194#[cfg_attr(feature = "deserialize", derive(Deserialize))]179#[cfg_attr(feature = "deserialize", derive(Deserialize))]
195#[derive(Debug, PartialEq, Trace)]180#[derive(Debug, PartialEq, Trace)]
196#[trivially_drop]
197pub struct ArgsDesc {181pub struct ArgsDesc {
198 pub unnamed: Vec<LocExpr>,182 pub unnamed: Vec<LocExpr>,
199 pub named: Vec<(IStr, LocExpr)>,183 pub named: Vec<(IStr, LocExpr)>,
207#[cfg_attr(feature = "serialize", derive(Serialize))]191#[cfg_attr(feature = "serialize", derive(Serialize))]
208#[cfg_attr(feature = "deserialize", derive(Deserialize))]192#[cfg_attr(feature = "deserialize", derive(Deserialize))]
209#[derive(Debug, Clone, PartialEq, Trace)]193#[derive(Debug, Clone, PartialEq, Trace)]
210#[trivially_drop]
211pub struct BindSpec {194pub struct BindSpec {
212 pub name: IStr,195 pub name: IStr,
213 pub params: Option<ParamsDesc>,196 pub params: Option<ParamsDesc>,
217#[cfg_attr(feature = "serialize", derive(Serialize))]200#[cfg_attr(feature = "serialize", derive(Serialize))]
218#[cfg_attr(feature = "deserialize", derive(Deserialize))]201#[cfg_attr(feature = "deserialize", derive(Deserialize))]
219#[derive(Debug, PartialEq, Trace)]202#[derive(Debug, PartialEq, Trace)]
220#[trivially_drop]
221pub struct IfSpecData(pub LocExpr);203pub struct IfSpecData(pub LocExpr);
222204
223#[cfg_attr(feature = "serialize", derive(Serialize))]205#[cfg_attr(feature = "serialize", derive(Serialize))]
224#[cfg_attr(feature = "deserialize", derive(Deserialize))]206#[cfg_attr(feature = "deserialize", derive(Deserialize))]
225#[derive(Debug, PartialEq, Trace)]207#[derive(Debug, PartialEq, Trace)]
226#[trivially_drop]
227pub struct ForSpecData(pub IStr, pub LocExpr);208pub struct ForSpecData(pub IStr, pub LocExpr);
228209
229#[cfg_attr(feature = "serialize", derive(Serialize))]210#[cfg_attr(feature = "serialize", derive(Serialize))]
230#[cfg_attr(feature = "deserialize", derive(Deserialize))]211#[cfg_attr(feature = "deserialize", derive(Deserialize))]
231#[derive(Debug, PartialEq, Trace)]212#[derive(Debug, PartialEq, Trace)]
232#[trivially_drop]
233pub enum CompSpec {213pub enum CompSpec {
234 IfSpec(IfSpecData),214 IfSpec(IfSpecData),
235 ForSpec(ForSpecData),215 ForSpec(ForSpecData),
238#[cfg_attr(feature = "serialize", derive(Serialize))]218#[cfg_attr(feature = "serialize", derive(Serialize))]
239#[cfg_attr(feature = "deserialize", derive(Deserialize))]219#[cfg_attr(feature = "deserialize", derive(Deserialize))]
240#[derive(Debug, PartialEq, Trace)]220#[derive(Debug, PartialEq, Trace)]
241#[trivially_drop]
242pub struct ObjComp {221pub struct ObjComp {
243 pub pre_locals: Vec<BindSpec>,222 pub pre_locals: Vec<BindSpec>,
244 pub key: LocExpr,223 pub key: LocExpr,
251#[cfg_attr(feature = "serialize", derive(Serialize))]230#[cfg_attr(feature = "serialize", derive(Serialize))]
252#[cfg_attr(feature = "deserialize", derive(Deserialize))]231#[cfg_attr(feature = "deserialize", derive(Deserialize))]
253#[derive(Debug, PartialEq, Trace)]232#[derive(Debug, PartialEq, Trace)]
254#[trivially_drop]
255pub enum ObjBody {233pub enum ObjBody {
256 MemberList(Vec<Member>),234 MemberList(Vec<Member>),
257 ObjComp(ObjComp),235 ObjComp(ObjComp),
260#[cfg_attr(feature = "serialize", derive(Serialize))]238#[cfg_attr(feature = "serialize", derive(Serialize))]
261#[cfg_attr(feature = "deserialize", derive(Deserialize))]239#[cfg_attr(feature = "deserialize", derive(Deserialize))]
262#[derive(Debug, PartialEq, Clone, Copy, Trace)]240#[derive(Debug, PartialEq, Clone, Copy, Trace)]
263#[trivially_drop]
264pub enum LiteralType {241pub enum LiteralType {
265 This,242 This,
266 Super,243 Super,
273#[cfg_attr(feature = "serialize", derive(Serialize))]250#[cfg_attr(feature = "serialize", derive(Serialize))]
274#[cfg_attr(feature = "deserialize", derive(Deserialize))]251#[cfg_attr(feature = "deserialize", derive(Deserialize))]
275#[derive(Debug, PartialEq, Trace)]252#[derive(Debug, PartialEq, Trace)]
276#[trivially_drop]
277pub struct SliceDesc {253pub struct SliceDesc {
278 pub start: Option<LocExpr>,254 pub start: Option<LocExpr>,
279 pub end: Option<LocExpr>,255 pub end: Option<LocExpr>,
284#[cfg_attr(feature = "serialize", derive(Serialize))]260#[cfg_attr(feature = "serialize", derive(Serialize))]
285#[cfg_attr(feature = "deserialize", derive(Deserialize))]261#[cfg_attr(feature = "deserialize", derive(Deserialize))]
286#[derive(Debug, PartialEq, Trace)]262#[derive(Debug, PartialEq, Trace)]
287#[trivially_drop]
288pub enum Expr {263pub enum Expr {
289 Literal(LiteralType),264 Literal(LiteralType),
290265
354#[cfg_attr(feature = "serialize", derive(Serialize))]329#[cfg_attr(feature = "serialize", derive(Serialize))]
355#[cfg_attr(feature = "deserialize", derive(Deserialize))]330#[cfg_attr(feature = "deserialize", derive(Deserialize))]
356#[derive(Clone, PartialEq, Trace)]331#[derive(Clone, PartialEq, Trace)]
357#[trivially_drop]332#[skip_trace]
358pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);333pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);
359impl ExprLocation {334impl ExprLocation {
360 pub fn belongs_to(&self, other: &ExprLocation) -> bool {335 pub fn belongs_to(&self, other: &ExprLocation) -> bool {
371/// Holds AST expression and its location in source file346/// Holds AST expression and its location in source file
372#[cfg_attr(feature = "serialize", derive(Serialize))]347#[cfg_attr(feature = "serialize", derive(Serialize))]
373#[cfg_attr(feature = "deserialize", derive(Deserialize))]348#[cfg_attr(feature = "deserialize", derive(Deserialize))]
374#[derive(Clone, PartialEq)]349#[derive(Clone, PartialEq, Trace)]
375pub struct LocExpr(pub Rc<Expr>, pub Option<ExprLocation>);350pub struct LocExpr(pub Rc<Expr>, pub ExprLocation);
376/// Safety:
377/// AST is acyclic, and there should be no gc pointers
378unsafe impl Trace for LocExpr {
379 unsafe_empty_trace!();
380}
381impl Finalize for LocExpr {}
382351
383impl Debug for LocExpr {352impl Debug for LocExpr {
384 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {353 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
387 } else {356 } else {
388 write!(f, "{:?}", self.0)?;357 write!(f, "{:?}", self.0)?;
389 }358 }
390 if let Some(loc) = &self.1 {
391 write!(f, " from {:?}", loc)?;359 write!(f, " from {:?}", self.1)?;
392 }
393 Ok(())360 Ok(())
394 }361 }
395}362}
396
397/// Creates LocExpr from Expr and ExprLocation components
398#[macro_export]
399macro_rules! loc_expr {
400 ($expr:expr, $need_loc:expr,($name:expr, $start:expr, $end:expr)) => {
401 LocExpr(
402 std::rc::Rc::new($expr),
403 if $need_loc {
404 Some(ExprLocation($name, $start, $end))
405 } else {
406 None
407 },
408 )
409 };
410}
411363
modifiedcrates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth
9pub use expr::*;9pub use expr::*;
10pub use jrsonnet_interner::IStr;10pub use jrsonnet_interner::IStr;
11pub use peg;11pub use peg;
12mod unescape;
1213
13pub struct ParserSettings {14pub struct ParserSettings {
14 pub loc_data: bool,
15 pub file_name: Rc<Path>,15 pub file_name: Rc<Path>,
16}16}
1717
104 [' ' | '\t']*<, {prefix.len() - 1}> "|||"104 [' ' | '\t']*<, {prefix.len() - 1}> "|||"
105 {let mut l = empty_lines.to_owned(); l.push_str(first_line); l.extend(lines); l}105 {let mut l = empty_lines.to_owned(); l.push_str(first_line); l.extend(lines); l}
106
107 rule hex_char()
108 = quiet! { ['0'..='9' | 'a'..='f' | 'A'..='F'] } / expected!("<hex char>")
109
110 rule string_char(c: rule<()>)
111 = (!['\\']!c()[_])+
112 / "\\\\"
113 / "\\u" hex_char() hex_char() hex_char() hex_char()
114 / "\\x" hex_char() hex_char()
115 / ['\\'] (quiet! { ['b' | 'f' | 'n' | 'r' | 't'] / c() } / expected!("<escape character>"))
106 pub rule string() -> String116 pub rule string() -> String
107 = quiet!{ "\"" str:$(("\\\"" / "\\\\" / (!['"'][_]))*) "\"" {unescape::unescape(str).unwrap()}117 = ['"'] str:$(string_char(<['"']>)*) ['"'] {? unescape::unescape(str).ok_or("<escaped string>")}
108 / "'" str:$(("\\'" / "\\\\" / (!['\''][_]))*) "'" {unescape::unescape(str).unwrap()}118 / ['\''] str:$(string_char(<['\'']>)*) ['\''] {? unescape::unescape(str).ok_or("<escaped string>")}
109 / "@'" str:$(("''" / (!['\''][_]))*) "'" {str.replace("''", "'")}119 / quiet!{ "@'" str:$(("''" / (!['\''][_]))*) "'" {str.replace("''", "'")}
110 / "@\"" str:$(("\"\"" / (!['"'][_]))*) "\"" {str.replace("\"\"", "\"")}120 / "@\"" str:$(("\"\"" / (!['"'][_]))*) "\"" {str.replace("\"\"", "\"")}
111 / string_block() } / expected!("<string>")121 / string_block() } / expected!("<string>")
112122
113 pub rule field_name(s: &ParserSettings) -> expr::FieldName123 pub rule field_name(s: &ParserSettings) -> expr::FieldName
114 = name:$(id()) {expr::FieldName::Fixed(name.into())}124 = name:$(id()) {expr::FieldName::Fixed(name.into())}
177 = n:number() { expr::Expr::Num(n) }187 = n:number() { expr::Expr::Num(n) }
178 pub rule var_expr(s: &ParserSettings) -> Expr188 pub rule var_expr(s: &ParserSettings) -> Expr
179 = n:$(id()) { expr::Expr::Var(n.into()) }189 = n:$(id()) { expr::Expr::Var(n.into()) }
190 pub rule id_loc(s: &ParserSettings) -> LocExpr
191 = a:position!() n:$(id()) b:position!() { LocExpr(Rc::new(expr::Expr::Str(n.into())), ExprLocation(s.file_name.clone(), a,b)) }
180 pub rule if_then_else_expr(s: &ParserSettings) -> Expr192 pub rule if_then_else_expr(s: &ParserSettings) -> Expr
181 = cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{193 = cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{
182 cond,194 cond,
240 use UnaryOpType::*;252 use UnaryOpType::*;
241 rule expr(s: &ParserSettings) -> LocExpr253 rule expr(s: &ParserSettings) -> LocExpr
242 = precedence! {254 = precedence! {
243 start:position!() v:@ end:position!() { loc_expr!(v, s.loc_data, (s.file_name.clone(), start, end)) }255 start:position!() v:@ end:position!() { LocExpr(Rc::new(v), ExprLocation(s.file_name.clone(), start, end)) }
244 --256 --
245 a:(@) _ binop(<"||">) _ b:@ {expr_bin!(a Or b)}257 a:(@) _ binop(<"||">) _ b:@ {expr_bin!(a Or b)}
246 --258 --
276 unaryop(<"~">) _ b:@ {expr_un!(BitNot b)}288 unaryop(<"~">) _ b:@ {expr_un!(BitNot b)}
277 --289 --
278 a:(@) _ "[" _ e:slice_desc(s) _ "]" {Expr::Slice(a, e)}290 a:(@) _ "[" _ e:slice_desc(s) _ "]" {Expr::Slice(a, e)}
279 a:(@) _ "." _ e:$(id()) {Expr::Index(a, el!(Expr::Str(e.into())))}291 a:(@) _ "." _ a:position!() e:id_loc(s) b:position!() {Expr::Index(a, e)}
280 a:(@) _ "[" _ e:expr(s) _ "]" {Expr::Index(a, e)}292 a:(@) _ "[" _ e:expr(s) _ "]" {Expr::Index(a, e)}
281 a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {Expr::Apply(a, args, ts.is_some())}293 a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {Expr::Apply(a, args, ts.is_some())}
282 a:(@) _ "{" _ body:objinside(s) _ "}" {Expr::ObjExtend(a, body)}294 a:(@) _ "{" _ body:objinside(s) _ "}" {Expr::ObjExtend(a, body)}
294 jsonnet_parser::jsonnet(str, settings)306 jsonnet_parser::jsonnet(str, settings)
295}307}
296
297#[macro_export]
298macro_rules! el {
299 ($expr:expr) => {
300 LocExpr(std::rc::Rc::new($expr), None)
301 };
302}
303308
304#[cfg(test)]309#[cfg(test)]
305pub mod tests {310pub mod tests {
313 parse(318 parse(
314 $s,319 $s,
315 &ParserSettings {320 &ParserSettings {
316 loc_data: false,
317 file_name: PathBuf::from("/test.jsonnet").into(),321 file_name: PathBuf::from("test.jsonnet").into(),
318 },322 },
319 )323 )
320 .unwrap()324 .unwrap()
321 };325 };
322 }326 }
323327
324 macro_rules! el_loc {328 macro_rules! el {
325 ($expr:expr, $loc:expr$(,)?) => {329 ($expr:expr, $from:expr, $to:expr$(,)?) => {
326 LocExpr(std::rc::Rc::new($expr), Some($loc))330 LocExpr(
331 std::rc::Rc::new($expr),
332 ExprLocation(PathBuf::from("test.jsonnet").into(), $from, $to),
333 )
327 };334 };
328 }335 }
329
330 mod expressions {
331 use super::*;
332
333 pub fn basic_math() -> LocExpr {
334 el!(Expr::BinaryOp(
335 el!(Expr::Num(2.0)),
336 Add,
337 el!(Expr::BinaryOp(
338 el!(Expr::Num(2.0)),
339 Mul,
340 el!(Expr::Num(2.0)),
341 )),
342 ))
343 }
344 }
345336
346 #[test]337 #[test]
347 fn multiline_string() {338 fn multiline_string() {
348 assert_eq!(339 assert_eq!(
349 parse!("|||\n Hello world!\n a\n|||"),340 parse!("|||\n Hello world!\n a\n|||"),
350 el!(Expr::Str("Hello world!\n a\n".into())),341 el!(Expr::Str("Hello world!\n a\n".into()), 0, 31),
351 );342 );
352 assert_eq!(343 assert_eq!(
353 parse!("|||\n Hello world!\n a\n|||"),344 parse!("|||\n Hello world!\n a\n|||"),
354 el!(Expr::Str("Hello world!\n a\n".into())),345 el!(Expr::Str("Hello world!\n a\n".into()), 0, 27),
355 );346 );
356 assert_eq!(347 assert_eq!(
357 parse!("|||\n\t\tHello world!\n\t\t\ta\n|||"),348 parse!("|||\n\t\tHello world!\n\t\t\ta\n|||"),
358 el!(Expr::Str("Hello world!\n\ta\n".into())),349 el!(Expr::Str("Hello world!\n\ta\n".into()), 0, 27),
359 );350 );
360 assert_eq!(351 assert_eq!(
361 parse!("|||\n Hello world!\n a\n |||"),352 parse!("|||\n Hello world!\n a\n |||"),
362 el!(Expr::Str("Hello world!\n a\n".into())),353 el!(Expr::Str("Hello world!\n a\n".into()), 0, 30),
363 );354 );
364 }355 }
365356
376 fn string_escaping() {367 fn string_escaping() {
377 assert_eq!(368 assert_eq!(
378 parse!(r#""Hello, \"world\"!""#),369 parse!(r#""Hello, \"world\"!""#),
379 el!(Expr::Str(r#"Hello, "world"!"#.into())),370 el!(Expr::Str(r#"Hello, "world"!"#.into()), 0, 19),
380 );371 );
381 assert_eq!(372 assert_eq!(
382 parse!(r#"'Hello \'world\'!'"#),373 parse!(r#"'Hello \'world\'!'"#),
383 el!(Expr::Str("Hello 'world'!".into())),374 el!(Expr::Str("Hello 'world'!".into()), 0, 18),
384 );375 );
385 assert_eq!(parse!(r#"'\\\\'"#), el!(Expr::Str("\\\\".into())),);376 assert_eq!(parse!(r#"'\\\\'"#), el!(Expr::Str("\\\\".into()), 0, 6));
386 }377 }
387378
388 #[test]379 #[test]
389 fn string_unescaping() {380 fn string_unescaping() {
390 assert_eq!(381 assert_eq!(
391 parse!(r#""Hello\nWorld""#),382 parse!(r#""Hello\nWorld""#),
392 el!(Expr::Str("Hello\nWorld".into())),383 el!(Expr::Str("Hello\nWorld".into()), 0, 14),
393 );384 );
394 }385 }
395386
396 #[test]387 #[test]
397 fn string_verbantim() {388 fn string_verbantim() {
398 assert_eq!(389 assert_eq!(
399 parse!(r#"@"Hello\n""World""""#),390 parse!(r#"@"Hello\n""World""""#),
400 el!(Expr::Str("Hello\\n\"World\"".into())),391 el!(Expr::Str("Hello\\n\"World\"".into()), 0, 19),
401 );392 );
402 }393 }
403394
404 #[test]395 #[test]
405 fn imports() {396 fn imports() {
406 assert_eq!(397 assert_eq!(
407 parse!("import \"hello\""),398 parse!("import \"hello\""),
408 el!(Expr::Import(PathBuf::from("hello"))),399 el!(Expr::Import(PathBuf::from("hello")), 0, 14),
409 );400 );
410 assert_eq!(401 assert_eq!(
411 parse!("importstr \"garnish.txt\""),402 parse!("importstr \"garnish.txt\""),
412 el!(Expr::ImportStr(PathBuf::from("garnish.txt")))403 el!(Expr::ImportStr(PathBuf::from("garnish.txt")), 0, 23)
413 );404 );
414 }405 }
415406
416 #[test]407 #[test]
417 fn empty_object() {408 fn empty_object() {
418 assert_eq!(parse!("{}"), el!(Expr::Obj(ObjBody::MemberList(vec![]))));409 assert_eq!(
410 parse!("{}"),
411 el!(Expr::Obj(ObjBody::MemberList(vec![])), 0, 2)
412 );
419 }413 }
420414
421 #[test]415 #[test]
422 fn basic_math() {416 fn basic_math() {
423 assert_eq!(417 assert_eq!(
424 parse!("2+2*2"),418 parse!("2+2*2"),
425 el!(Expr::BinaryOp(419 el!(
420 Expr::BinaryOp(
426 el!(Expr::Num(2.0)),421 el!(Expr::Num(2.0), 0, 1),
427 Add,422 Add,
428 el!(Expr::BinaryOp(423 el!(
429 el!(Expr::Num(2.0)),424 Expr::BinaryOp(el!(Expr::Num(2.0), 2, 3), Mul, el!(Expr::Num(2.0), 4, 5)),
430 Mul,425 2,
431 el!(Expr::Num(2.0))426 5
432 ))427 )
433 ))428 ),
429 0,
430 5
431 )
434 );432 );
435 }433 }
436434
437 #[test]435 #[test]
438 fn basic_math_with_indents() {436 fn basic_math_with_indents() {
439 assert_eq!(parse!("2 + 2 * 2 "), expressions::basic_math());437 assert_eq!(
438 parse!("2 + 2 * 2 "),
439 el!(
440 Expr::BinaryOp(
441 el!(Expr::Num(2.0), 0, 1),
442 Add,
443 el!(
444 Expr::BinaryOp(el!(Expr::Num(2.0), 7, 8), Mul, el!(Expr::Num(2.0), 13, 14),),
445 7,
446 14
447 ),
448 ),
449 0,
450 14
451 )
452 );
440 }453 }
441454
445 parse!("2+(2+2*2)"),458 parse!("2+(2+2*2)"),
446 el!(Expr::BinaryOp(459 el!(
460 Expr::BinaryOp(
447 el!(Expr::Num(2.0)),461 el!(Expr::Num(2.0), 0, 1),
448 Add,462 Add,
449 el!(Expr::Parened(expressions::basic_math())),463 el!(
464 Expr::Parened(el!(
465 Expr::BinaryOp(
466 el!(Expr::Num(2.0), 3, 4),
467 Add,
468 el!(
469 Expr::BinaryOp(
470 el!(Expr::Num(2.0), 5, 6),
471 Mul,
472 el!(Expr::Num(2.0), 7, 8),
473 ),
474 5,
475 8
476 ),
477 ),
478 3,
479 8
480 )),
481 2,
482 9
483 ),
450 ))484 ),
485 0,
486 9
487 )
451 );488 );
452 }489 }
458 parse!("2//comment\n+//comment\n3/*test*/*/*test*/4"),495 parse!("2//comment\n+//comment\n3/*test*/*/*test*/4"),
459 el!(Expr::BinaryOp(496 el!(
497 Expr::BinaryOp(
460 el!(Expr::Num(2.0)),498 el!(Expr::Num(2.0), 0, 1),
461 Add,499 Add,
462 el!(Expr::BinaryOp(500 el!(
501 Expr::BinaryOp(
463 el!(Expr::Num(3.0)),502 el!(Expr::Num(3.0), 22, 23),
464 Mul,503 Mul,
465 el!(Expr::Num(4.0))504 el!(Expr::Num(4.0), 40, 41)
466 ))505 ),
506 22,
507 41
508 )
467 ))509 ),
510 0,
511 41
512 )
468 );513 );
469 }514 }
474 assert_eq!(519 assert_eq!(
475 parse!("2/*\\*/+*/ - 22"),520 parse!("2/*\\*/+*/ - 22"),
476 el!(Expr::BinaryOp(521 el!(
477 el!(Expr::Num(2.0)),522 Expr::BinaryOp(el!(Expr::Num(2.0), 0, 1), Sub, el!(Expr::Num(22.0), 12, 14)),
478 Sub,523 0,
479 el!(Expr::Num(22.0))524 14
480 ))525 )
481 );526 );
482 }527 }
492 #[test]537 #[test]
493 fn array_comp() {538 fn array_comp() {
494 use Expr::*;539 use Expr::*;
540 /*
541 `ArrComp(Apply(Index(Var("std") from "test.jsonnet":1-4, Var("deepJoin") from "test.jsonnet":5-13) from "test.jsonnet":1-13, ArgsDesc { unnamed: [Var("x") from "test.jsonnet":14-15], named: [] }, false) from "test.jsonnet":1-16, [ForSpec(ForSpecData("x", Var("arr") from "test.jsonnet":26-29))]) from "test.jsonnet":0-30`,
542 `ArrComp(Apply(Index(Var("std") from "test.jsonnet":1-4, Str("deepJoin") from "test.jsonnet":5-13) from "test.jsonnet":1-13, ArgsDesc { unnamed: [Var("x") from "test.jsonnet":14-15], named: [] }, false) from "test.jsonnet":1-16, [ForSpec(ForSpecData("x", Var("arr") from "test.jsonnet":26-29))]) from "test.jsonnet":0-30`
543 */
495 assert_eq!(544 assert_eq!(
496 parse!("[std.deepJoin(x) for x in arr]"),545 parse!("[std.deepJoin(x) for x in arr]"),
497 el!(ArrComp(546 el!(
547 ArrComp(
498 el!(Apply(548 el!(
549 Apply(
499 el!(Index(el!(Var("std".into())), el!(Str("deepJoin".into())))),550 el!(
551 Index(
552 el!(Var("std".into()), 1, 4),
553 el!(Str("deepJoin".into()), 5, 13)
554 ),
555 1,
556 13
557 ),
500 ArgsDesc::new(vec![el!(Var("x".into()))], vec![]),558 ArgsDesc::new(vec![el!(Var("x".into()), 14, 15)], vec![]),
501 false,559 false,
502 )),560 ),
561 1,
562 16
563 ),
503 vec![CompSpec::ForSpec(ForSpecData(564 vec![CompSpec::ForSpec(ForSpecData(
504 "x".into(),565 "x".into(),
505 el!(Var("arr".into()))566 el!(Var("arr".into()), 26, 29)
506 ))]567 ))]
507 )),568 ),
569 0,
570 30
571 ),
508 )572 )
509 }573 }
510574
511 #[test]575 #[test]
512 fn reserved() {576 fn reserved() {
513 use Expr::*;577 use Expr::*;
514 assert_eq!(parse!("null"), el!(Literal(LiteralType::Null)));578 assert_eq!(parse!("null"), el!(Literal(LiteralType::Null), 0, 4));
515 assert_eq!(parse!("nulla"), el!(Var("nulla".into())));579 assert_eq!(parse!("nulla"), el!(Var("nulla".into()), 0, 5));
516 }580 }
517581
518 #[test]582 #[test]
527 parse!("!a && !b"),591 parse!("!a && !b"),
528 el!(BinaryOp(592 el!(
593 BinaryOp(
529 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),594 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 1, 2)), 0, 2),
530 And,595 And,
531 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))596 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()), 7, 8)), 6, 8)
532 ))597 ),
598 0,
599 8
600 )
533 );601 );
534 }602 }
540 parse!("!a / !b"),608 parse!("!a / !b"),
541 el!(BinaryOp(609 el!(
610 BinaryOp(
542 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),611 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 1, 2)), 0, 2),
543 Div,612 Div,
544 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))613 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()), 6, 7)), 5, 7)
545 ))614 ),
615 0,
616 7
617 )
546 );618 );
547 }619 }
554 el!(UnaryOp(626 el!(
627 UnaryOp(
555 UnaryOpType::Not,628 UnaryOpType::Not,
556 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()))))629 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 2, 3)), 1, 3)
557 ))630 ),
631 0,
632 3
633 )
558 )634 )
559 }635 }
587 fn add_location_info_to_all_sub_expressions() {663 fn add_location_info_to_all_sub_expressions() {
588 use Expr::*;664 use Expr::*;
589665
590 let file_name: std::rc::Rc<std::path::Path> = PathBuf::from("/test.jsonnet").into();666 let file_name: std::rc::Rc<std::path::Path> = PathBuf::from("test.jsonnet").into();
591 let expr = parse(667 let expr = parse(
592 "{} { local x = 1, x: x } + {}",668 "{} { local x = 1, x: x } + {}",
593 &ParserSettings {669 &ParserSettings {
594 loc_data: true,
595 file_name: file_name.clone(),670 file_name: file_name.clone(),
596 },671 },
597 )672 )
598 .unwrap();673 .unwrap();
599 assert_eq!(674 assert_eq!(
600 expr,675 expr,
601 el_loc!(676 el!(
602 BinaryOp(677 BinaryOp(
603 el_loc!(678 el!(
604 ObjExtend(679 ObjExtend(
605 el_loc!(680 el!(Obj(ObjBody::MemberList(vec![])), 0, 2),
606 Obj(ObjBody::MemberList(vec![])),
607 ExprLocation(file_name.clone(), 0, 2)
608 ),
609 ObjBody::MemberList(vec![681 ObjBody::MemberList(vec![
610 Member::BindStmt(BindSpec {682 Member::BindStmt(BindSpec {
611 name: "x".into(),683 name: "x".into(),
612 params: None,684 params: None,
613 value: el_loc!(685 value: el!(Num(1.0), 15, 16)
614 Num(1.0),
615 ExprLocation(file_name.clone(), 15, 16)
616 )
617 }),686 }),
618 Member::Field(FieldMember {687 Member::Field(FieldMember {
619 name: FieldName::Fixed("x".into()),688 name: FieldName::Fixed("x".into()),
620 plus: false,689 plus: false,
621 params: None,690 params: None,
622 visibility: Visibility::Normal,691 visibility: Visibility::Normal,
623 value: el_loc!(692 value: el!(Var("x".into()), 21, 22),
624 Var("x".into()),
625 ExprLocation(file_name.clone(), 21, 22)
626 ),
627 })693 })
628 ])694 ])
629 ),695 ),
630 ExprLocation(file_name.clone(), 0, 24)696 0,
697 24
631 ),698 ),
632 BinaryOpType::Add,699 BinaryOpType::Add,
633 el_loc!(700 el!(Obj(ObjBody::MemberList(vec![])), 27, 29),
634 Obj(ObjBody::MemberList(vec![])),
635 ExprLocation(file_name.clone(), 27, 29)
636 ),
637 ),701 ),
638 ExprLocation(file_name.clone(), 0, 29),702 0,
703 29
639 ),704 ),
640 );705 );
addedcrates/jrsonnet-parser/src/unescape.rsdiffbeforeafterboth

no changes

modifiedcrates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth
370 ch;370 ch;
371 std.foldl(function(a, b) a + trans(b), std.stringChars(str), ''),371 std.foldl(function(a, b) a + trans(b), std.stringChars(str), ''),
372372
373 manifestJson(value):: std.manifestJsonEx(value, ' '),373 manifestJson(value):: std.manifestJsonEx(value, ' ') tailstrict,
374374
375 manifestJsonEx:: $intrinsic(manifestJsonEx),375 manifestJsonEx:: $intrinsic(manifestJsonEx),
376376
modifiedcrates/jrsonnet-types/Cargo.tomldiffbeforeafterboth
88
9[dependencies]9[dependencies]
10peg = "0.7.0"10peg = "0.7.0"
11jrsonnet-gc = { version = "0.4.2", features = ["derive"] }11gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
1212
modifiedcrates/jrsonnet-types/src/lib.rsdiffbeforeafterboth
1#![allow(clippy::redundant_closure_call)]1#![allow(clippy::redundant_closure_call)]
22
3use jrsonnet_gc::Trace;3use gcmodule::Trace;
4use std::fmt::Display;4use std::fmt::Display;
55
6#[macro_export]6#[macro_export]
82}82}
8383
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]84#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]
85#[trivially_drop]
86pub enum ValType {85pub enum ValType {
87 Bool,86 Bool,
88 Null,87 Null,
115}114}
116115
117#[derive(Debug, Clone, PartialEq, Trace)]116#[derive(Debug, Clone, PartialEq, Trace)]
118#[trivially_drop]117#[skip_trace]
119pub enum ComplexValType {118pub enum ComplexValType {
120 Any,119 Any,
121 Char,120 Char,