git.delta.rocks / jrsonnet / refs/commits / 8db09e1bbe2e

difftreelog

Merge pull request #45 from CertainLach/gc-v2

Yaroslav Bolyukin2021-07-04parents: #1f2f94e #56cee93.patch.diff
in: master
Implement tracing Gc with rust-gc

35 files changed

modifiedCargo.lockdiffbeforeafterboth
99 "clap",99 "clap",
100]100]
101
102[[package]]
103name = "closure"
104version = "0.3.0"
105source = "registry+https://github.com/rust-lang/crates.io-index"
106checksum = "d6173fd61b610d15a7566dd7b7620775627441c4ab9dac8906e17cb93a24b782"
107101
108[[package]]102[[package]]
109name = "hashbrown"103name = "hashbrown"
164dependencies = [158dependencies = [
165 "clap",159 "clap",
166 "jrsonnet-evaluator",160 "jrsonnet-evaluator",
161 "jrsonnet-gc",
167 "jrsonnet-parser",162 "jrsonnet-parser",
168]163]
169164
175 "anyhow",170 "anyhow",
176 "base64",171 "base64",
177 "bincode",172 "bincode",
178 "closure",173 "jrsonnet-gc",
179 "jrsonnet-interner",174 "jrsonnet-interner",
180 "jrsonnet-parser",175 "jrsonnet-parser",
181 "jrsonnet-stdlib",176 "jrsonnet-stdlib",
188 "thiserror",183 "thiserror",
189]184]
185
186[[package]]
187name = "jrsonnet-gc"
188version = "0.4.2"
189source = "registry+https://github.com/rust-lang/crates.io-index"
190checksum = "68da8bc2f00117b1373bb8877af03b1d391e4c4800e6585d7279e5b99c919dde"
191dependencies = [
192 "jrsonnet-gc-derive",
193]
194
195[[package]]
196name = "jrsonnet-gc-derive"
197version = "0.4.1"
198source = "registry+https://github.com/rust-lang/crates.io-index"
199checksum = "adcba9c387b64b054f06cc4d724905296e21edeeb7506847f3299117a2d92d12"
200dependencies = [
201 "proc-macro2",
202 "quote",
203 "syn",
204 "synstructure",
205]
190206
191[[package]]207[[package]]
192name = "jrsonnet-interner"208name = "jrsonnet-interner"
193version = "0.3.8"209version = "0.3.8"
194dependencies = [210dependencies = [
211 "jrsonnet-gc",
195 "rustc-hash",212 "rustc-hash",
196 "serde",213 "serde",
197]214]
200name = "jrsonnet-parser"217name = "jrsonnet-parser"
201version = "0.3.8"218version = "0.3.8"
202dependencies = [219dependencies = [
220 "jrsonnet-gc",
203 "jrsonnet-interner",221 "jrsonnet-interner",
204 "jrsonnet-stdlib",222 "jrsonnet-stdlib",
205 "peg",223 "peg",
215name = "jrsonnet-types"233name = "jrsonnet-types"
216version = "0.3.8"234version = "0.3.8"
217dependencies = [235dependencies = [
236 "jrsonnet-gc",
218 "peg",237 "peg",
219]238]
220239
223version = "0.3.8"242version = "0.3.8"
224dependencies = [243dependencies = [
225 "jrsonnet-evaluator",244 "jrsonnet-evaluator",
245 "jrsonnet-gc",
226 "jrsonnet-parser",246 "jrsonnet-parser",
227]247]
228248
404 "unicode-xid",424 "unicode-xid",
405]425]
426
427[[package]]
428name = "synstructure"
429version = "0.12.4"
430source = "registry+https://github.com/rust-lang/crates.io-index"
431checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
432dependencies = [
433 "proc-macro2",
434 "quote",
435 "syn",
436 "unicode-xid",
437]
406438
407[[package]]439[[package]]
408name = "termcolor"440name = "termcolor"
modifiedbindings/jsonnet/Cargo.tomldiffbeforeafterboth
10[dependencies]10[dependencies]
11jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "0.3.8" }11jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "0.3.8" }
12jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.3.8" }12jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.3.8" }
13jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
1314
14[lib]15[lib]
15crate-type = ["cdylib"]16crate-type = ["cdylib"]
modifiedbindings/jsonnet/src/native.rsdiffbeforeafterboth
1use jrsonnet_evaluator::{error::Error, native::NativeCallback, EvaluationState, Val};1use jrsonnet_evaluator::{
2 error::{Error, LocError},
3 native::{NativeCallback, NativeCallbackHandler},
4 EvaluationState, Val,
5};
6use jrsonnet_gc::{unsafe_empty_trace, Finalize, Gc, Trace};
2use jrsonnet_parser::{Param, ParamsDesc};7use jrsonnet_parser::{Param, ParamsDesc};
3use std::{8use std::{
4 ffi::{c_void, CStr},9 ffi::{c_void, CStr},
5 os::raw::{c_char, c_int},10 os::raw::{c_char, c_int},
11 path::Path,
6 rc::Rc,12 rc::Rc,
7};13};
814
12 success: *mut c_int,18 success: *mut c_int,
13) -> *mut Val;19) -> *mut Val;
20
21struct JsonnetNativeCallbackHandler {
22 ctx: *const c_void,
23 cb: JsonnetNativeCallback,
24}
25impl Finalize for JsonnetNativeCallbackHandler {}
26unsafe impl Trace for JsonnetNativeCallbackHandler {
27 unsafe_empty_trace!();
28}
29impl NativeCallbackHandler for JsonnetNativeCallbackHandler {
30 fn call(&self, _from: Option<Rc<Path>>, args: &[Val]) -> Result<Val, LocError> {
31 let mut n_args = Vec::new();
32 for a in args {
33 n_args.push(Some(Box::new(a.clone())));
34 }
35 n_args.push(None);
36 let mut success = 1;
37 let v = unsafe {
38 (self.cb)(
39 self.ctx,
40 &n_args as *const _ as *const *const Val,
41 &mut success,
42 )
43 };
44 let v = unsafe { *Box::from_raw(v) };
45 if success == 1 {
46 Ok(v)
47 } else {
48 let e = v.try_cast_str("native error").expect("error msg");
49 Err(Error::RuntimeError(e).into())
50 }
51 }
52}
1453
15/// # Safety54/// # Safety
16#[no_mangle]55#[no_mangle]
3574
36 vm.add_native(75 vm.add_native(
37 name,76 name,
38 Rc::new(NativeCallback::new(params, move |_caller, args| {77 Gc::new(NativeCallback::new(
39 let mut n_args = Vec::new();78 params,
40 for a in args {
41 n_args.push(Some(Box::new(a.clone())));79 Box::new(JsonnetNativeCallbackHandler { ctx, cb }),
42 }
43 n_args.push(None);
44 let mut success = 1;
45 let v = cb(ctx, &n_args as *const _ as *const *const Val, &mut success);
46 let v = *Box::from_raw(v);
47 if success == 1 {
48 Ok(v)
49 } else {
50 let e = v.try_cast_str("native error").expect("error msg");
51 Err(Error::RuntimeError(e).into())
52 }
53 })),80 )),
54 )81 )
55}82}
5683
modifiedbindings/jsonnet/src/val_make.rsdiffbeforeafterboth
1//! Create values in VM1//! Create values in VM
22
3use jrsonnet_evaluator::{ArrValue, EvaluationState, ObjValue, Val};3use jrsonnet_evaluator::{ArrValue, EvaluationState, ObjValue, Val};
4use jrsonnet_gc::Gc;
4use std::{5use std::{
5 ffi::CStr,6 ffi::CStr,
6 os::raw::{c_char, c_double, c_int},7 os::raw::{c_char, c_double, c_int},
7 rc::Rc,
8};8};
99
10/// # Safety10/// # Safety
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(Rc::new(Vec::new())))))41 Box::into_raw(Box::new(Val::Arr(ArrValue::Eager(Gc::new(Vec::new())))))
42}42}
4343
44#[no_mangle]44#[no_mangle]
modifiedbindings/jsonnet/src/val_modify.rsdiffbeforeafterboth
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 jrsonnet_evaluator::{ArrValue, EvaluationState, LazyBinding, LazyVal, ObjMember, Val};5use jrsonnet_evaluator::{ArrValue, EvaluationState, LazyBinding, LazyVal, ObjMember, Val};
6use jrsonnet_gc::Gc;
6use jrsonnet_parser::Visibility;7use jrsonnet_parser::Visibility;
7use std::{ffi::CStr, os::raw::c_char, rc::Rc};8use std::{ffi::CStr, os::raw::c_char};
89
9/// # Safety10/// # Safety
10///11///
22 new.push(item);23 new.push(item);
23 }24 }
24 new.push(LazyVal::new_resolved(val.clone()));25 new.push(LazyVal::new_resolved(val.clone()));
25 *arr = Val::Arr(ArrValue::Lazy(Rc::new(new)));26 *arr = Val::Arr(ArrValue::Lazy(Gc::new(new)));
26 }27 }
27 _ => panic!("should receive array"),28 _ => panic!("should receive array"),
28 }29 }
modifiedcmds/jrsonnet/Cargo.tomldiffbeforeafterboth
8publish = false8publish = false
99
10[features]10[features]
11default = []11default = ["mimalloc"]
12# Use mimalloc as allocator12# Use mimalloc as allocator
13mimalloc = []13mimalloc = ["mimallocator"]
1414
15[dependencies]15[dependencies]
16jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "0.3.8" }16jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "0.3.8" }
17jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.3.8" }17jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.3.8" }
18jrsonnet-cli = { path = "../../crates/jrsonnet-cli", version = "0.3.8" }18jrsonnet-cli = { path = "../../crates/jrsonnet-cli", version = "0.3.8" }
19# TODO: Fix mimalloc compile errors, and use them
20mimallocator = { version = "0.1.3", optional = true }19mimallocator = { version = "0.1.3", optional = true }
21thiserror = "1.0"20thiserror = "1.0"
2221
modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
1use clap::{AppSettings, Clap, IntoApp};1use clap::{AppSettings, Clap, IntoApp};
2use jrsonnet_cli::{ConfigureState, GeneralOpts, InputOpts, ManifestOpts, OutputOpts};2use jrsonnet_cli::{ConfigureState, GcOpts, GeneralOpts, InputOpts, ManifestOpts, OutputOpts};
3use jrsonnet_evaluator::{error::LocError, EvaluationState, ManifestFormat};3use jrsonnet_evaluator::{error::LocError, EvaluationState, ManifestFormat};
4use std::{4use std::{
5 fs::{create_dir_all, File},5 fs::{create_dir_all, File},
61 output: OutputOpts,61 output: OutputOpts,
62 #[clap(flatten)]62 #[clap(flatten)]
63 debug: DebugOpts,63 debug: DebugOpts,
64 #[clap(flatten)]
65 gc: GcOpts,
64}66}
6567
66fn main() {68fn main() {
114}116}
115117
116fn main_catch(opts: Opts) -> bool {118fn main_catch(opts: Opts) -> bool {
119 let _printer = opts.gc.stats_printer();
117 let state = EvaluationState::default();120 let state = EvaluationState::default();
118 if let Err(e) = main_real(&state, opts) {121 if let Err(e) = main_real(&state, opts) {
119 if let Error::Evaluation(e) = e {122 if let Error::Evaluation(e) = e {
127}130}
128131
129fn main_real(state: &EvaluationState, opts: Opts) -> Result<(), Error> {132fn main_real(state: &EvaluationState, opts: Opts) -> Result<(), Error> {
133 opts.gc.configure_global();
130 opts.general.configure(&state)?;134 opts.general.configure(&state)?;
131 opts.manifest.configure(&state)?;135 opts.manifest.configure(&state)?;
132136
modifiedcrates/jrsonnet-cli/Cargo.tomldiffbeforeafterboth
10[dependencies]10[dependencies]
11jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "0.3.6", features = ["explaining-traces"] }11jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "0.3.6", features = ["explaining-traces"] }
12jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.3.6" }12jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.3.6" }
13jrsonnet-gc = { version = "0.4.2", features = ["derive", "unstable-config", "unstable-stats"] }
1314
14[dependencies.clap]15[dependencies.clap]
15git = "https://github.com/clap-rs/clap"16git = "https://github.com/clap-rs/clap"
modifiedcrates/jrsonnet-cli/src/lib.rsdiffbeforeafterboth
96 }96 }
97}97}
98
99#[derive(Clap)]
100#[clap(help_heading = "GARBAGE COLLECTION")]
101pub struct GcOpts {
102 /// Min bytes allocated to start garbage collection
103 #[clap(long, default_value = "20000000")]
104 gc_initial_threshold: usize,
105 /// How much heap should grow after unsuccessful garbage collection
106 #[clap(long)]
107 gc_used_space_ratio: Option<f64>,
108 /// Do not skip gc on exit
109 #[clap(long)]
110 gc_collect_on_exit: bool,
111 /// Print gc stats before exit
112 #[clap(long)]
113 gc_print_stats: bool,
114 /// Force garbage collection before printing stats
115 /// Useful for checking for memory leaks
116 /// Does nothing useless --gc-print-stats is specified
117 #[clap(long)]
118 gc_collect_before_printing_stats: bool,
119}
120impl GcOpts {
121 pub fn stats_printer(&self) -> Option<GcStatsPrinter> {
122 self.gc_print_stats
123 .then(|| GcStatsPrinter(self.gc_collect_before_printing_stats))
124 }
125 pub fn configure_global(&self) {
126 jrsonnet_gc::configure(|config| {
127 config.leak_on_drop = !self.gc_collect_on_exit;
128 config.threshold = self.gc_initial_threshold;
129 if let Some(used_space_ratio) = self.gc_used_space_ratio {
130 config.used_space_ratio = used_space_ratio;
131 }
132 });
133 }
134}
135pub struct GcStatsPrinter(bool);
136impl Drop for GcStatsPrinter {
137 fn drop(&mut self) {
138 if self.0 {
139 jrsonnet_gc::force_collect()
140 }
141 eprintln!("=== GC STATS ===");
142 jrsonnet_gc::configure(|c| {
143 eprintln!("Final threshold: {:?}", c.threshold);
144 });
145 let stats = jrsonnet_gc::stats();
146 eprintln!("Collections performed: {}", stats.collections_performed);
147 eprintln!("Bytes still allocated: {}", stats.bytes_allocated);
148 }
149}
98150
modifiedcrates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth
30jrsonnet-types = { path = "../jrsonnet-types", version = "0.3.8" }30jrsonnet-types = { path = "../jrsonnet-types", version = "0.3.8" }
31pathdiff = "0.2.0"31pathdiff = "0.2.0"
32
33closure = "0.3.0"
3432
35md5 = "0.7.0"33md5 = "0.7.0"
36base64 = "0.13.0"34base64 = "0.13.0"
37rustc-hash = "1.1.0"35rustc-hash = "1.1.0"
3836
39thiserror = "1.0"37thiserror = "1.0"
38jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
4039
41[dependencies.anyhow]40[dependencies.anyhow]
42version = "1.0"41version = "1.0"
modifiedcrates/jrsonnet-evaluator/README.mddiffbeforeafterboth
66
7jsonnet stdlib is embedded into evaluator, but there is different modes for this:7jsonnet stdlib is embedded into evaluator, but there is different modes for this:
88
9- `codegenerated-stdlib`
10 - generates source code for reproducing stdlib AST ([Example](https://gist.githubusercontent.com/CertainLach/7b3149df556f3406f5e9368aaa9f32ec/raw/0c80d8ab9aa7b9288c6219a2779cb2ab37287669/a.rs))
11 - fastest on interpretation, slowest on compilation (it takes more than 5 minutes to optimize them by llvm)
12- `serialized-stdlib`9- `serialized-stdlib`
13 - serializes standard library AST using serde10 - serializes standard library AST using serde
14 - slower than `codegenerated-stdlib` at runtime, but have no compilation speed penality11 - slower than `codegenerated-stdlib` at runtime, but have no compilation speed penality
23Can also be run via `cargo bench`20Can also be run via `cargo bench`
2421
25```markdown22```markdown
26# codegenerated-stdlib
27test tests::bench_codegen ... bench: 401,696 ns/iter (+/- 38,521)
28# serialized-stdlib23# serialized-stdlib
29test tests::bench_serialize ... bench: 1,763,999 ns/iter (+/- 76,211)24test tests::bench_serialize ... bench: 1,763,999 ns/iter (+/- 76,211)
30# none25# none
34## Intrinsics29## Intrinsics
3530
36Some functions from stdlib are implemented as intrinsics31Some functions from stdlib are implemented as intrinsics
37
38### Intrinsic handling
39
40If indexed jsonnet object has field '__intrinsic_namespace__' of type 'string', then any not found field/method is resolved as `Val::Intrinsic(__intrinsic_namespace__, name)`
4132
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 jrsonnet_interner::IStr;6use jrsonnet_interner::IStr;
6use jrsonnet_types::ValType;7use jrsonnet_types::ValType;
7use thiserror::Error;8use thiserror::Error;
89
9#[derive(Debug, Clone, Error)]10#[derive(Debug, Clone, Error, Trace)]
11#[trivially_drop]
10pub enum FormatError {12pub enum FormatError {
11 #[error("truncated format code")]13 #[error("truncated format code")]
12 TruncatedFormatCode,14 TruncatedFormatCode,
modifiedcrates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth
126 buf.push('}');126 buf.push('}');
127 }127 }
128 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),128 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),
129 Val::DebugGcTraceValue(v) => manifest_json_ex_buf(&v.value, buf, cur_padding, options)?,
129 };130 };
130 Ok(())131 Ok(())
131}132}
modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 equals,2 equals,
3 error::{Error::*, Result},3 error::{Error::*, Result},
4 parse_args, primitive_equals, push, throw, with_state, ArrValue, Context, EvaluationState,4 parse_args, primitive_equals, push, throw, with_state, ArrValue, Context, DebugGcTraceValue,
5 FuncVal, LazyVal, Val,5 EvaluationState, FuncVal, LazyVal, Val,
6};6};
7use format::{format_arr, format_obj};7use format::{format_arr, format_obj};
8use jrsonnet_gc::Gc;
8use jrsonnet_interner::IStr;9use jrsonnet_interner::IStr;
9use jrsonnet_parser::{ArgsDesc, BinaryOpType, ExprLocation};10use jrsonnet_parser::{ArgsDesc, BinaryOpType, ExprLocation};
10use jrsonnet_types::ty;11use jrsonnet_types::ty;
68 ("md5".into(), builtin_md5),69 ("md5".into(), builtin_md5),
69 ("base64".into(), builtin_base64),70 ("base64".into(), builtin_base64),
70 ("trace".into(), builtin_trace),71 ("trace".into(), builtin_trace),
72 ("gc".into(), builtin_gc),
73 ("gcTrace".into(), builtin_gc_trace),
71 ("join".into(), builtin_join),74 ("join".into(), builtin_join),
72 ("escapeStringJson".into(), builtin_escape_string_json),75 ("escapeStringJson".into(), builtin_escape_string_json),
73 ("manifestJsonEx".into(), builtin_manifest_json_ex),76 ("manifestJsonEx".into(), builtin_manifest_json_ex),
301 parse_args!(context, "native", args, 1, [304 parse_args!(context, "native", args, 1, [
302 0, x: ty!(string) => Val::Str;305 0, x: ty!(string) => Val::Str;
303 ], {306 ], {
304 Ok(with_state(|s| s.settings().ext_natives.get(&x).cloned()).map(|v| Val::Func(Rc::new(FuncVal::NativeExt(x.clone(), v)))).ok_or(UndefinedExternalFunction(x))?)307 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))?)
305 })308 })
306}309}
307310
446 })449 })
447}450}
451
452fn builtin_gc(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
453 parse_args!(context, "gc", args, 1, [
454 0, rest: ty!(any);
455 ], {
456 println!("GC start");
457 jrsonnet_gc::force_collect();
458 println!("GC done");
459
460 Ok(rest)
461 })
462}
463
464fn builtin_gc_trace(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
465 parse_args!(context, "gcTrace", args, 2, [
466 0, name: ty!(string) => Val::Str;
467 1, rest: ty!(any);
468 ], {
469 Ok(DebugGcTraceValue::create(name, rest))
470 })
471}
448472
449fn builtin_base64(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {473fn builtin_base64(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
450 parse_args!(context, "base64", args, 1, [474 parse_args!(context, "base64", args, 1, [
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 std::rc::Rc;5use jrsonnet_gc::{Finalize, Gc, Trace};
66
7#[derive(Debug, Clone, thiserror::Error)]7#[derive(Debug, Clone, thiserror::Error, Trace, Finalize)]
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, mut values: Rc<Vec<Val>>, key_getter: &FuncVal) -> Result<Rc<Vec<Val>>> {62pub fn sort(ctx: Context, values: Gc<Vec<Val>>, key_getter: &FuncVal) -> Result<Gc<Vec<Val>>> {
63 if values.len() <= 1 {63 if values.len() <= 1 {
64 return Ok(values);64 return Ok(values);
65 }65 }
66 if key_getter.is_ident() {66 if key_getter.is_ident() {
67 let mvalues = Rc::make_mut(&mut values);67 let mut mvalues = (*values).clone();
68 let sort_type = get_sort_type(mvalues, |k| k)?;68 let sort_type = get_sort_type(&mut mvalues, |k| k)?;
69 match sort_type {69 match sort_type {
70 SortKeyType::Number => mvalues.sort_by_key(|v| match v {70 SortKeyType::Number => mvalues.sort_by_key(|v| match v {
71 Val::Num(n) => NonNaNf64(*n),71 Val::Num(n) => NonNaNf64(*n),
77 }),77 }),
78 SortKeyType::Unknown => unreachable!(),78 SortKeyType::Unknown => unreachable!(),
79 };79 };
80 Ok(values)80 Ok(Gc::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(Rc::new(vk.into_iter().map(|v| v.0).collect()))101 Ok(Gc::new(vk.into_iter().map(|v| v.0).collect()))
102 }102 }
103}103}
104104
modifiedcrates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 error::Error::*, map::LayeredHashMap, resolved_lazy_val, FutureWrapper, LazyBinding, LazyVal,2 error::Error::*, map::LayeredHashMap, FutureWrapper, LazyBinding, LazyVal, ObjValue, Result,
3 ObjValue, Result, Val,3 Val,
4};4};
5use jrsonnet_gc::{Gc, Trace};
5use jrsonnet_interner::IStr;6use jrsonnet_interner::IStr;
6use rustc_hash::FxHashMap;7use rustc_hash::FxHashMap;
7use std::hash::BuildHasherDefault;8use std::fmt::Debug;
8use std::{fmt::Debug, rc::Rc};9use std::hash::BuildHasherDefault;
910
10#[derive(Clone)]11#[derive(Clone, Trace)]
12#[trivially_drop]
11pub struct ContextCreator(pub Context, pub FutureWrapper<FxHashMap<IStr, LazyBinding>>);13pub struct ContextCreator(pub Context, pub FutureWrapper<FxHashMap<IStr, LazyBinding>>);
12impl ContextCreator {14impl ContextCreator {
13 pub fn create(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<Context> {15 pub fn create(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<Context> {
20 }22 }
21}23}
2224
25#[derive(Trace)]
26#[trivially_drop]
23struct ContextInternals {27struct ContextInternals {
24 dollar: Option<ObjValue>,28 dollar: Option<ObjValue>,
25 this: Option<ObjValue>,29 this: Option<ObjValue>,
26 super_obj: Option<ObjValue>,30 super_obj: Option<ObjValue>,
27 bindings: LayeredHashMap<LazyVal>,31 bindings: LayeredHashMap,
28}32}
29impl Debug for ContextInternals {33impl Debug for ContextInternals {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 f.debug_struct("Context")35 f.debug_struct("Context").finish()
32 .field("this", &self.this.as_ref().map(|e| Rc::as_ptr(&e.0)))
33 .field("bindings", &self.bindings)
34 .finish()
35 }36 }
36}37}
3738
38#[derive(Debug, Clone)]39#[derive(Debug, Clone, Trace)]
40#[trivially_drop]
39pub struct Context(Rc<ContextInternals>);41pub struct Context(Gc<ContextInternals>);
40impl Context {42impl Context {
41 pub fn new_future() -> FutureWrapper<Self> {43 pub fn new_future() -> FutureWrapper<Self> {
42 FutureWrapper::new()44 FutureWrapper::new()
55 }57 }
5658
57 pub fn new() -> Self {59 pub fn new() -> Self {
58 Self(Rc::new(ContextInternals {60 Self(Gc::new(ContextInternals {
59 dollar: None,61 dollar: None,
60 this: None,62 this: None,
61 super_obj: None,63 super_obj: None,
81 pub fn with_var(self, name: IStr, value: Val) -> Self {83 pub fn with_var(self, name: IStr, value: Val) -> Self {
82 let mut new_bindings =84 let mut new_bindings =
83 FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());85 FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());
84 new_bindings.insert(name, resolved_lazy_val!(value));86 new_bindings.insert(name, LazyVal::new_resolved(value));
85 self.extend(new_bindings, None, None, None)87 self.extend(new_bindings, None, None, None)
86 }88 }
8789
96 new_this: Option<ObjValue>,98 new_this: Option<ObjValue>,
97 new_super_obj: Option<ObjValue>,99 new_super_obj: Option<ObjValue>,
98 ) -> Self {100 ) -> Self {
99 match Rc::try_unwrap(self.0) {
100 Ok(mut ctx) => {
101 // Extended context aren't used by anything else, we can freely mutate it without cloning
102 if let Some(dollar) = new_dollar {101 let ctx = &self.0;
103 ctx.dollar = Some(dollar);
104 }
105 if let Some(this) = new_this {
106 ctx.this = Some(this);
107 }
108 if let Some(super_obj) = new_super_obj {
109 ctx.super_obj = Some(super_obj);
110 }
111 if !new_bindings.is_empty() {
112 ctx.bindings = ctx.bindings.extend(new_bindings);
113 }
114 Self(Rc::new(ctx))
115 }
116 Err(ctx) => {
117 let dollar = new_dollar.or_else(|| ctx.dollar.clone());102 let dollar = new_dollar.or_else(|| ctx.dollar.clone());
118 let this = new_this.or_else(|| ctx.this.clone());103 let this = new_this.or_else(|| ctx.this.clone());
119 let super_obj = new_super_obj.or_else(|| ctx.super_obj.clone());104 let super_obj = new_super_obj.or_else(|| ctx.super_obj.clone());
122 } else {107 } else {
123 ctx.bindings.clone().extend(new_bindings)108 ctx.bindings.clone().extend(new_bindings)
124 };109 };
125 Self(Rc::new(ContextInternals {110 Self(Gc::new(ContextInternals {
126 dollar,111 dollar,
127 this,112 this,
128 super_obj,113 super_obj,
129 bindings,114 bindings,
130 }))115 }))
131 }
132 }
133 }116 }
134 pub fn extend_bound(self, new_bindings: FxHashMap<IStr, LazyVal>) -> Self {117 pub fn extend_bound(self, new_bindings: FxHashMap<IStr, LazyVal>) -> Self {
135 let new_this = self.0.this.clone();118 let new_this = self.0.this.clone();
166149
167impl PartialEq for Context {150impl PartialEq for Context {
168 fn eq(&self, other: &Self) -> bool {151 fn eq(&self, other: &Self) -> bool {
169 Rc::ptr_eq(&self.0, &other.0)152 Gc::ptr_eq(&self.0, &other.0)
170 }153 }
171}154}
172
173#[cfg(feature = "unstable")]
174#[derive(Debug, Clone)]
175pub struct WeakContext(std::rc::Weak<ContextInternals>);
176#[cfg(feature = "unstable")]
177impl WeakContext {
178 pub fn upgrade(&self) -> Context {
179 Context(self.0.upgrade().expect("context is removed"))
180 }
181}
182#[cfg(feature = "unstable")]
183impl PartialEq for WeakContext {
184 fn eq(&self, other: &Self) -> bool {
185 self.0.ptr_eq(&other.0)
186 }
187}
188155
modifiedcrates/jrsonnet-evaluator/src/dynamic.rsdiffbeforeafterboth
1use std::{cell::RefCell, rc::Rc};1use jrsonnet_gc::{Gc, GcCell, Trace};
22
3#[derive(Clone)]3#[derive(Clone, Trace)]
4#[trivially_drop]
4pub struct FutureWrapper<V>(pub Rc<RefCell<Option<V>>>);5pub struct FutureWrapper<V: Trace + 'static>(pub Gc<GcCell<Option<V>>>);
5impl<T> FutureWrapper<T> {6impl<T: Trace + 'static> FutureWrapper<T> {
6 pub fn new() -> Self {7 pub fn new() -> Self {
7 Self(Rc::new(RefCell::new(None)))8 Self(Gc::new(GcCell::new(None)))
8 }9 }
9 pub fn fill(self, value: T) {10 pub fn fill(self, value: T) {
10 assert!(self.0.borrow().is_none(), "wrapper is filled already");11 assert!(self.0.borrow().is_none(), "wrapper is filled already");
11 self.0.borrow_mut().replace(value);12 self.0.borrow_mut().replace(value);
12 }13 }
13}14}
14impl<T: Clone> FutureWrapper<T> {15impl<T: Clone + Trace + 'static> FutureWrapper<T> {
15 pub fn unwrap(&self) -> T {16 pub fn unwrap(&self) -> T {
16 self.0.borrow().as_ref().cloned().unwrap()17 self.0.borrow().as_ref().cloned().unwrap()
17 }18 }
18}19}
1920
20impl<T> Default for FutureWrapper<T> {21impl<T: Trace + 'static> Default for FutureWrapper<T> {
21 fn default() -> Self {22 fn default() -> Self {
22 Self::new()23 Self::new()
23 }24 }
modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
2 builtin::{format::FormatError, sort::SortError},2 builtin::{format::FormatError, sort::SortError},
3 typed::TypeLocError,3 typed::TypeLocError,
4};4};
5use jrsonnet_gc::Trace;
5use jrsonnet_interner::IStr;6use jrsonnet_interner::IStr;
6use jrsonnet_parser::{BinaryOpType, ExprLocation, UnaryOpType};7use jrsonnet_parser::{BinaryOpType, ExprLocation, UnaryOpType};
7use jrsonnet_types::ValType;8use jrsonnet_types::ValType;
11};12};
12use thiserror::Error;13use thiserror::Error;
1314
14#[derive(Error, Debug, Clone)]15#[derive(Error, Debug, Clone, Trace)]
16#[trivially_drop]
15pub enum Error {17pub enum Error {
16 #[error("intrinsic not found: {0}")]18 #[error("intrinsic not found: {0}")]
17 IntrinsicNotFound(IStr),19 IntrinsicNotFound(IStr),
91 ImportSyntaxError {93 ImportSyntaxError {
92 path: Rc<Path>,94 path: Rc<Path>,
93 source_code: IStr,95 source_code: IStr,
96 #[unsafe_ignore_trace]
94 error: Box<jrsonnet_parser::ParseError>,97 error: Box<jrsonnet_parser::ParseError>,
95 },98 },
9699
97 #[error("runtime error: {0}")]100 #[error("runtime error: {0}")]
98 RuntimeError(IStr),101 RuntimeError(IStr),
99 #[error("stack overflow, try to reduce recursion, or set --max-stack to bigger value")]102 #[error("stack overflow, try to reduce recursion, or set --max-stack to bigger value")]
100 StackOverflow,103 StackOverflow,
104 #[error("infinite recursion detected")]
105 RecursiveLazyValueEvaluation,
101 #[error("tried to index by fractional value")]106 #[error("tried to index by fractional value")]
102 FractionalIndex,107 FractionalIndex,
103 #[error("attempted to divide by zero")]108 #[error("attempted to divide by zero")]
145 }150 }
146}151}
147152
148#[derive(Clone, Debug)]153#[derive(Clone, Debug, Trace)]
154#[trivially_drop]
149pub struct StackTraceElement {155pub struct StackTraceElement {
150 pub location: Option<ExprLocation>,156 pub location: Option<ExprLocation>,
151 pub desc: String,157 pub desc: String,
152}158}
153#[derive(Debug, Clone)]159#[derive(Debug, Clone, Trace)]
160#[trivially_drop]
154pub struct StackTrace(pub Vec<StackTraceElement>);161pub struct StackTrace(pub Vec<StackTraceElement>);
155162
156#[derive(Debug, Clone)]163#[derive(Debug, Clone, Trace)]
164#[trivially_drop]
157pub struct LocError(Box<(Error, StackTrace)>);165pub struct LocError(Box<(Error, StackTrace)>);
158impl LocError {166impl LocError {
159 pub fn new(e: Error) -> Self {167 pub fn new(e: Error) -> Self {
modifiedcrates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 equals, error::Error::*, lazy_val, push, throw, with_state, ArrValue, Context, ContextCreator,2 equals, error::Error::*, push, throw, with_state, ArrValue, Bindable, Context, ContextCreator,
3 FuncDesc, FuncVal, FutureWrapper, LazyBinding, LazyVal, ObjMember, ObjValue, Result, Val,3 FuncDesc, FuncVal, FutureWrapper, LazyBinding, LazyVal, LazyValValue, ObjMember, ObjValue,
4 ObjectAssertion, Result, Val,
4};5};
5use closure::closure;6use jrsonnet_gc::{Gc, Trace};
6use jrsonnet_interner::IStr;7use jrsonnet_interner::IStr;
7use jrsonnet_parser::{8use jrsonnet_parser::{
8 ArgsDesc, AssertStmt, BinaryOpType, BindSpec, CompSpec, Expr, ExprLocation, FieldMember,9 ArgsDesc, AssertStmt, BinaryOpType, BindSpec, CompSpec, Expr, ExprLocation, FieldMember,
11};12};
12use jrsonnet_types::ValType;13use jrsonnet_types::ValType;
13use rustc_hash::{FxHashMap, FxHasher};14use rustc_hash::{FxHashMap, FxHasher};
14use std::{collections::HashMap, hash::BuildHasherDefault, rc::Rc};15use std::{collections::HashMap, hash::BuildHasherDefault};
1516
16pub fn evaluate_binding_in_future(17pub fn evaluate_binding_in_future(
17 b: &BindSpec,18 b: &BindSpec,
21 if let Some(params) = &b.params {22 if let Some(params) = &b.params {
22 let params = params.clone();23 let params = params.clone();
24
25 #[derive(Trace)]
26 #[trivially_drop]
27 struct LazyMethodBinding {
28 context_creator: FutureWrapper<Context>,
29 name: IStr,
30 params: ParamsDesc,
31 value: LocExpr,
32 }
33 impl LazyValValue for LazyMethodBinding {
34 fn get(self: Box<Self>) -> Result<Val> {
35 Ok(evaluate_method(
36 self.context_creator.unwrap(),
37 self.name,
38 self.params,
39 self.value,
40 ))
41 }
42 }
43
23 LazyVal::new(Box::new(move || {44 LazyVal::new(Box::new(LazyMethodBinding {
24 Ok(evaluate_method(
25 context_creator.unwrap(),45 context_creator,
26 b.name.clone(),46 name: b.name.clone(),
27 params.clone(),47 params,
28 b.value.clone(),48 value: b.value.clone(),
29 ))
30 }))49 }))
31 } else {50 } else {
51 #[derive(Trace)]
52 #[trivially_drop]
53 struct LazyNamedBinding {
54 context_creator: FutureWrapper<Context>,
55 name: IStr,
56 value: LocExpr,
57 }
58 impl LazyValValue for LazyNamedBinding {
59 fn get(self: Box<Self>) -> Result<Val> {
60 evaluate_named(self.context_creator.unwrap(), &self.value, self.name)
61 }
62 }
32 LazyVal::new(Box::new(move || {63 LazyVal::new(Box::new(LazyNamedBinding {
33 evaluate_named(context_creator.unwrap(), &b.value, b.name.clone())64 context_creator,
65 name: b.name.clone(),
66 value: b.value,
34 }))67 }))
35 }68 }
36}69}
40 if let Some(params) = &b.params {73 if let Some(params) = &b.params {
41 let params = params.clone();74 let params = params.clone();
75
76 #[derive(Trace)]
77 #[trivially_drop]
78 struct BindableMethodLazyVal {
79 this: Option<ObjValue>,
80 super_obj: Option<ObjValue>,
81
82 context_creator: ContextCreator,
83 name: IStr,
84 params: ParamsDesc,
85 value: LocExpr,
86 }
87 impl LazyValValue for BindableMethodLazyVal {
88 fn get(self: Box<Self>) -> Result<Val> {
89 Ok(evaluate_method(
90 self.context_creator.create(self.this, self.super_obj)?,
91 self.name,
92 self.params,
93 self.value,
94 ))
95 }
96 }
97
98 #[derive(Trace)]
99 #[trivially_drop]
100 struct BindableMethod {
101 context_creator: ContextCreator,
102 name: IStr,
103 params: ParamsDesc,
104 value: LocExpr,
105 }
106 impl Bindable for BindableMethod {
107 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {
108 Ok(LazyVal::new(Box::new(BindableMethodLazyVal {
109 this,
110 super_obj,
111
112 context_creator: self.context_creator.clone(),
113 name: self.name.clone(),
114 params: self.params.clone(),
115 value: self.value.clone(),
116 })))
117 }
118 }
119
42 (120 (
43 b.name.clone(),121 b.name.clone(),
44 LazyBinding::Bindable(Rc::new(move |this, super_obj| {122 LazyBinding::Bindable(Gc::new(Box::new(BindableMethod {
45 Ok(lazy_val!(
46 closure!(clone b, clone params, clone context_creator, || Ok(evaluate_method(123 context_creator,
47 context_creator.create(this.clone(), super_obj.clone())?,
48 b.name.clone(),124 name: b.name.clone(),
49 params.clone(),125 params,
50 b.value.clone(),126 value: b.value.clone(),
51 )))
52 ))127 }))),
53 })),
54 )128 )
55 } else {129 } else {
130 #[derive(Trace)]
131 #[trivially_drop]
132 struct BindableNamedLazyVal {
133 this: Option<ObjValue>,
134 super_obj: Option<ObjValue>,
135
136 context_creator: ContextCreator,
137 name: IStr,
138 value: LocExpr,
139 }
140 impl LazyValValue for BindableNamedLazyVal {
141 fn get(self: Box<Self>) -> Result<Val> {
142 evaluate_named(
143 self.context_creator.create(self.this, self.super_obj)?,
144 &self.value,
145 self.name,
146 )
147 }
148 }
149
150 #[derive(Trace)]
151 #[trivially_drop]
152 struct BindableNamed {
153 context_creator: ContextCreator,
154 name: IStr,
155 value: LocExpr,
156 }
157 impl Bindable for BindableNamed {
158 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {
159 Ok(LazyVal::new(Box::new(BindableNamedLazyVal {
160 this,
161 super_obj,
162
163 context_creator: self.context_creator.clone(),
164 name: self.name.clone(),
165 value: self.value.clone(),
166 })))
167 }
168 }
169
56 (170 (
57 b.name.clone(),171 b.name.clone(),
58 LazyBinding::Bindable(Rc::new(move |this, super_obj| {172 LazyBinding::Bindable(Gc::new(Box::new(BindableNamed {
59 Ok(lazy_val!(closure!(clone context_creator, clone b, ||173 context_creator,
60 evaluate_named(
61 context_creator.create(this.clone(), super_obj.clone())?,174 name: b.name.clone(),
62 &b.value,175 value: b.value.clone(),
63 b.name.clone()
64 )
65 )))176 }))),
66 })),
67 )177 )
68 }178 }
69}179}
70180
71pub 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 {
72 Val::Func(Rc::new(FuncVal::Normal(FuncDesc {182 Val::Func(Gc::new(FuncVal::Normal(FuncDesc {
73 name,183 name,
74 ctx,184 ctx,
75 params,185 params,
105215
106pub fn evaluate_add_op(a: &Val, b: &Val) -> Result<Val> {216pub fn evaluate_add_op(a: &Val, b: &Val) -> Result<Val> {
107 Ok(match (a, b) {217 Ok(match (a, b) {
218 (Val::DebugGcTraceValue(v1), Val::DebugGcTraceValue(v2)) => {
219 evaluate_add_op(&v1.value, &v2.value)?
220 }
108 (Val::Str(v1), Val::Str(v2)) => Val::Str(((**v1).to_owned() + v2).into()),221 (Val::Str(v1), Val::Str(v2)) => Val::Str(((**v1).to_owned() + v2).into()),
109222
110 // Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)223 // Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)
257 }370 }
258371
259 let mut new_members = FxHashMap::default();372 let mut new_members = FxHashMap::default();
260 let mut assertions = Vec::new();373 let mut assertions: Vec<Box<dyn ObjectAssertion>> = Vec::new();
261 for member in members.iter() {374 for member in members.iter() {
262 match member {375 match member {
263 Member::Field(FieldMember {376 Member::Field(FieldMember {
273 }386 }
274 let name = name.unwrap();387 let name = name.unwrap();
388
389 #[derive(Trace)]
390 #[trivially_drop]
391 struct ObjMemberBinding {
392 context_creator: ContextCreator,
393 value: LocExpr,
394 name: IStr,
395 }
396 impl Bindable for ObjMemberBinding {
397 fn bind(
398 &self,
399 this: Option<ObjValue>,
400 super_obj: Option<ObjValue>,
401 ) -> Result<LazyVal> {
402 Ok(LazyVal::new_resolved(evaluate_named(
403 self.context_creator.create(this, super_obj)?,
404 &self.value,
405 self.name.clone(),
406 )?))
407 }
408 }
275 new_members.insert(409 new_members.insert(
276 name.clone(),410 name.clone(),
277 ObjMember {411 ObjMember {
278 add: *plus,412 add: *plus,
279 visibility: *visibility,413 visibility: *visibility,
280 invoke: LazyBinding::Bindable(Rc::new(414 invoke: LazyBinding::Bindable(Gc::new(Box::new(ObjMemberBinding {
281 closure!(clone name, clone value, clone context_creator, |this, super_obj| {415 context_creator: context_creator.clone(),
282 Ok(LazyVal::new_resolved(evaluate_named(
283 context_creator.create(this, super_obj)?,
284 &value,416 value: value.clone(),
285 name.clone(),417 name,
286 )?))
287 }),418 }))),
288 )),
289 location: value.1.clone(),419 location: value.1.clone(),
290 },420 },
301 continue;431 continue;
302 }432 }
303 let name = name.unwrap();433 let name = name.unwrap();
434 #[derive(Trace)]
435 #[trivially_drop]
436 struct ObjMemberBinding {
437 context_creator: ContextCreator,
438 value: LocExpr,
439 params: ParamsDesc,
440 name: IStr,
441 }
442 impl Bindable for ObjMemberBinding {
443 fn bind(
444 &self,
445 this: Option<ObjValue>,
446 super_obj: Option<ObjValue>,
447 ) -> Result<LazyVal> {
448 Ok(LazyVal::new_resolved(evaluate_method(
449 self.context_creator.create(this, super_obj)?,
450 self.name.clone(),
451 self.params.clone(),
452 self.value.clone(),
453 )))
454 }
455 }
304 new_members.insert(456 new_members.insert(
305 name.clone(),457 name.clone(),
306 ObjMember {458 ObjMember {
307 add: false,459 add: false,
308 visibility: Visibility::Hidden,460 visibility: Visibility::Hidden,
309 invoke: LazyBinding::Bindable(Rc::new(461 invoke: LazyBinding::Bindable(Gc::new(Box::new(ObjMemberBinding {
310 closure!(clone value, clone context_creator, clone params, clone name, |this, super_obj| {462 context_creator: context_creator.clone(),
311 // TODO: Assert
312 Ok(LazyVal::new_resolved(evaluate_method(
313 context_creator.create(this, super_obj)?,
314 name.clone(),463 value: value.clone(),
315 params.clone(),464 params: params.clone(),
316 value.clone(),465 name,
317 )))
318 }),466 }))),
319 )),
320 location: value.1.clone(),467 location: value.1.clone(),
321 },468 },
322 );469 );
323 }470 }
324 Member::BindStmt(_) => {}471 Member::BindStmt(_) => {}
325 Member::AssertStmt(stmt) => {472 Member::AssertStmt(stmt) => {
473 #[derive(Trace)]
474 #[trivially_drop]
475 struct ObjectAssert {
476 context_creator: ContextCreator,
477 assert: AssertStmt,
478 }
479 impl ObjectAssertion for ObjectAssert {
480 fn run(
481 &self,
482 this: Option<ObjValue>,
483 super_obj: Option<ObjValue>,
484 ) -> Result<()> {
485 let ctx = self.context_creator.create(this, super_obj)?;
486 evaluate_assert(ctx, &self.assert)
487 }
488 }
326 assertions.push(stmt.clone());489 assertions.push(Box::new(ObjectAssert {
490 context_creator: context_creator.clone(),
491 assert: stmt.clone(),
492 }));
327 }493 }
328 }494 }
329 }495 }
330 let this = ObjValue::new(context, None, Rc::new(new_members), Rc::new(assertions));496 let this = ObjValue::new(None, Gc::new(new_members), Gc::new(assertions));
331 future_this.fill(this.clone());497 future_this.fill(this.clone());
332 Ok(this)498 Ok(this)
333}499}
361 match key {527 match key {
362 Val::Null => {}528 Val::Null => {}
363 Val::Str(n) => {529 Val::Str(n) => {
530 #[derive(Trace)]
531 #[trivially_drop]
532 struct ObjCompBinding {
533 context: Context,
534 value: LocExpr,
535 }
536 impl Bindable for ObjCompBinding {
537 fn bind(
538 &self,
539 this: Option<ObjValue>,
540 _super_obj: Option<ObjValue>,
541 ) -> Result<LazyVal> {
542 Ok(LazyVal::new_resolved(evaluate(
543 self.context.clone().extend(
544 FxHashMap::default(),
545 None,
546 this,
547 None,
548 ),
549 &self.value,
550 )?))
551 }
552 }
364 new_members.insert(553 new_members.insert(
365 n,554 n,
366 ObjMember {555 ObjMember {
367 add: false,556 add: false,
368 visibility: Visibility::Normal,557 visibility: Visibility::Normal,
369 invoke: LazyBinding::Bindable(Rc::new(558 invoke: LazyBinding::Bindable(Gc::new(Box::new(ObjCompBinding {
370 closure!(clone ctx, clone obj.value, |this, _super_obj| {559 context: ctx,
371 Ok(LazyVal::new_resolved(evaluate(ctx.clone().extend(FxHashMap::default(), None, this, None), &value)?))560 value: obj.value.clone(),
372 }),561 }))),
373 )),
374 location: obj.value.1.clone(),562 location: obj.value.1.clone(),
375 },563 },
381 Ok(())569 Ok(())
382 })?;570 })?;
383571
384 let this = ObjValue::new(context, None, Rc::new(new_members), Rc::new(Vec::new()));572 let this = ObjValue::new(None, Gc::new(new_members), Gc::new(Vec::new()));
385 future_this.fill(this.clone());573 future_this.fill(this.clone());
386 this574 this
387 }575 }
486 if let Some(v) = v.get(s.clone())? {674 if let Some(v) = v.get(s.clone())? {
487 Ok(v)675 Ok(v)
488 } else if v.get("__intrinsic_namespace__".into())?.is_some() {676 } else if v.get("__intrinsic_namespace__".into())?.is_some() {
489 Ok(Val::Func(Rc::new(FuncVal::Intrinsic(s))))677 Ok(Val::Func(Gc::new(FuncVal::Intrinsic(s))))
490 } else {678 } else {
491 throw!(NoSuchField(s))679 throw!(NoSuchField(s))
492 }680 }
549 Arr(items) => {737 Arr(items) => {
550 let mut out = Vec::with_capacity(items.len());738 let mut out = Vec::with_capacity(items.len());
551 for item in items {739 for item in items {
740 // TODO: Implement ArrValue::Lazy with same context for every element?
741 #[derive(Trace)]
742 #[trivially_drop]
743 struct ArrayElement {
744 context: Context,
745 item: LocExpr,
746 }
747 impl LazyValValue for ArrayElement {
748 fn get(self: Box<Self>) -> Result<Val> {
749 evaluate(self.context, &self.item)
750 }
751 }
552 out.push(LazyVal::new(Box::new(752 out.push(LazyVal::new(Box::new(ArrayElement {
553 closure!(clone context, clone item, || {753 context: context.clone(),
554 evaluate(context.clone(), &item)754 item: item.clone(),
555 }),
556 )));755 })));
557 }756 }
558 Val::Arr(out.into())757 Val::Arr(out.into())
559 }758 }
563 out.push(evaluate(ctx, expr)?);762 out.push(evaluate(ctx, expr)?);
564 Ok(())763 Ok(())
565 })?;764 })?;
566 Val::Arr(ArrValue::Eager(Rc::new(out)))765 Val::Arr(ArrValue::Eager(Gc::new(out)))
567 }766 }
568 Obj(body) => Val::Obj(evaluate_object(context, body)?),767 Obj(body) => Val::Obj(evaluate_object(context, body)?),
569 ObjExtend(s, t) => evaluate_add_op(768 ObjExtend(s, t) => evaluate_add_op(
576 Function(params, body) => {775 Function(params, body) => {
577 evaluate_method(context, "anonymous".into(), params.clone(), body.clone())776 evaluate_method(context, "anonymous".into(), params.clone(), body.clone())
578 }777 }
579 Intrinsic(name) => Val::Func(Rc::new(FuncVal::Intrinsic(name.clone()))),778 Intrinsic(name) => Val::Func(Gc::new(FuncVal::Intrinsic(name.clone()))),
580 AssertExpr(assert, returned) => {779 AssertExpr(assert, returned) => {
581 evaluate_assert(context.clone(), assert)?;780 evaluate_assert(context.clone(), assert)?;
582 evaluate(context, returned)?781 evaluate(context, returned)?
modifiedcrates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth
1use crate::{error::Error::*, evaluate, lazy_val, resolved_lazy_val, throw, Context, Result, Val};1use crate::{error::Error::*, evaluate, throw, Context, LazyVal, LazyValValue, Result, Val};
2use closure::closure;2use jrsonnet_gc::Trace;
3use jrsonnet_interner::IStr;3use jrsonnet_interner::IStr;
4use jrsonnet_parser::{ArgsDesc, ParamsDesc};4use jrsonnet_parser::{ArgsDesc, LocExpr, ParamsDesc};
5use rustc_hash::FxHashMap;5use rustc_hash::FxHashMap;
6use std::{collections::HashMap, hash::BuildHasherDefault};6use std::{collections::HashMap, hash::BuildHasherDefault};
77
53 throw!(FunctionParameterNotBoundInCall(p.0.clone()));53 throw!(FunctionParameterNotBoundInCall(p.0.clone()));
54 };54 };
55 let val = if tailstrict {55 let val = if tailstrict {
56 resolved_lazy_val!(evaluate(ctx, expr)?)56 LazyVal::new_resolved(evaluate(ctx, expr)?)
57 } else {57 } else {
58 #[derive(Trace)]
59 #[trivially_drop]
60 struct EvaluateLazyVal {
61 context: Context,
62 expr: LocExpr,
63 }
64 impl LazyValValue for EvaluateLazyVal {
65 fn get(self: Box<Self>) -> Result<Val> {
66 evaluate(self.context, &self.expr)
67 }
68 }
69
58 lazy_val!(closure!(clone ctx, clone expr, ||evaluate(ctx.clone(), &expr)))70 LazyVal::new(Box::new(EvaluateLazyVal {
71 context: ctx.clone(),
72 expr: expr.clone(),
73 }))
59 };74 };
60 out.insert(p.0.clone(), val);75 out.insert(p.0.clone(), val);
61 }76 }
89 // Fill defaults104 // Fill defaults
90 for (id, p) in params.iter().enumerate() {105 for (id, p) in params.iter().enumerate() {
91 let val = if let Some(arg) = positioned_args[id].take() {106 let val = if let Some(arg) = positioned_args[id].take() {
92 resolved_lazy_val!(arg)107 LazyVal::new_resolved(arg)
93 } else if let Some(default) = &p.1 {108 } else if let Some(default) = &p.1 {
94 if tailstrict {109 if tailstrict {
95 resolved_lazy_val!(evaluate(110 LazyVal::new_resolved(evaluate(
96 body_ctx.clone().expect(NO_DEFAULT_CONTEXT),111 body_ctx.clone().expect(NO_DEFAULT_CONTEXT),
97 default112 default,
98 )?)113 )?)
99 } else {114 } else {
100 let body_ctx = body_ctx.clone();115 let body_ctx = body_ctx.clone();
101 let default = default.clone();116 let default = default.clone();
117 #[derive(Trace)]
118 #[trivially_drop]
119 struct EvaluateLazyVal {
120 body_ctx: Option<Context>,
121 default: LocExpr,
122 }
123 impl LazyValValue for EvaluateLazyVal {
102 lazy_val!(move || {124 fn get(self: Box<Self>) -> Result<Val> {
103 evaluate(body_ctx.clone().expect(NO_DEFAULT_CONTEXT), &default)125 evaluate(
126 self.body_ctx.clone().expect(NO_DEFAULT_CONTEXT),
127 &self.default,
128 )
104 })129 }
130 }
131 LazyVal::new(Box::new(EvaluateLazyVal { body_ctx, default }))
105 }132 }
106 } else {133 } else {
107 throw!(FunctionParameterNotBoundInCall(p.0.clone()));134 throw!(FunctionParameterNotBoundInCall(p.0.clone()));
135 } else {162 } else {
136 throw!(FunctionParameterNotBoundInCall(p.0.clone()));163 throw!(FunctionParameterNotBoundInCall(p.0.clone()));
137 };164 };
138 out.insert(p.0.clone(), resolved_lazy_val!(val));165 out.insert(p.0.clone(), LazyVal::new_resolved(val));
139 }166 }
140167
141 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))168 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))
modifiedcrates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 error::{Error::*, LocError, Result},2 error::{Error::*, LocError, Result},
3 throw, Context, LazyBinding, LazyVal, ObjMember, ObjValue, Val,3 throw, LazyBinding, LazyVal, ObjMember, ObjValue, Val,
4};4};
5use jrsonnet_gc::Gc;
5use jrsonnet_parser::Visibility;6use jrsonnet_parser::Visibility;
6use rustc_hash::FxHasher;7use rustc_hash::FxHasher;
7use serde_json::{Map, Number, Value};8use serde_json::{Map, Number, Value};
8use std::{9use std::{
9 collections::HashMap,10 collections::HashMap,
10 convert::{TryFrom, TryInto},11 convert::{TryFrom, TryInto},
11 hash::BuildHasherDefault,12 hash::BuildHasherDefault,
12 rc::Rc,
13};13};
1414
15impl TryFrom<&Val> for Value {15impl TryFrom<&Val> for Value {
42 Self::Object(out)42 Self::Object(out)
43 }43 }
44 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),44 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),
45 Val::DebugGcTraceValue(v) => Self::try_from(&*v.value as &Val)?,
45 })46 })
46 }47 }
47}48}
76 },77 },
77 );78 );
78 }79 }
79 Self::Obj(ObjValue::new(80 Self::Obj(ObjValue::new(None, Gc::new(entries), Gc::new(Vec::new())))
80 Context::new(),
81 None,
82 Rc::new(entries),
83 Rc::new(Vec::new()),
84 ))
85 }81 }
86 }82 }
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
26pub use evaluate::*;26pub use evaluate::*;
27pub use function::parse_function_call;27pub use function::parse_function_call;
28pub use import::*;28pub use import::*;
29use jrsonnet_gc::{Finalize, Gc, Trace};
30pub use jrsonnet_interner::IStr;
29use jrsonnet_parser::*;31use jrsonnet_parser::*;
30use native::NativeCallback;32use native::NativeCallback;
31pub use obj::*;33pub use obj::*;
41use trace::{offset_to_location, CodeLocation, CompactFormat, TraceFormat};43use trace::{offset_to_location, CodeLocation, CompactFormat, TraceFormat};
42pub use val::*;44pub use val::*;
4345
44// Re-exports
45pub use jrsonnet_interner::IStr;46pub trait Bindable: Trace {
46
47type BindableFn = dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Result<LazyVal>;47 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal>;
48}
48#[derive(Clone)]49#[derive(Trace, Finalize, Clone)]
49pub enum LazyBinding {50pub enum LazyBinding {
50 Bindable(Rc<BindableFn>),51 Bindable(Gc<Box<dyn Bindable>>),
51 Bound(LazyVal),52 Bound(LazyVal),
52}53}
5354
59impl LazyBinding {60impl LazyBinding {
60 pub fn evaluate(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {61 pub fn evaluate(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {
61 match self {62 match self {
62 Self::Bindable(v) => v(this, super_obj),63 Self::Bindable(v) => v.bind(this, super_obj),
63 Self::Bound(v) => Ok(v.clone()),64 Self::Bound(v) => Ok(v.clone()),
64 }65 }
65 }66 }
73 /// Used for s`td.extVar`74 /// Used for s`td.extVar`
74 pub ext_vars: HashMap<IStr, Val>,75 pub ext_vars: HashMap<IStr, Val>,
75 /// Used for ext.native76 /// Used for ext.native
76 pub ext_natives: HashMap<IStr, Rc<NativeCallback>>,77 pub ext_natives: HashMap<IStr, Gc<NativeCallback>>,
77 /// TLA vars78 /// TLA vars
78 pub tla_vars: HashMap<IStr, Val>,79 pub tla_vars: HashMap<IStr, Val>,
79 /// Global variables are inserted in default context80 /// Global variables are inserted in default context
272 let mut new_bindings: FxHashMap<IStr, LazyVal> =273 let mut new_bindings: FxHashMap<IStr, LazyVal> =
273 FxHashMap::with_capacity_and_hasher(globals.len(), BuildHasherDefault::default());274 FxHashMap::with_capacity_and_hasher(globals.len(), BuildHasherDefault::default());
274 for (name, value) in globals.iter() {275 for (name, value) in globals.iter() {
275 new_bindings.insert(name.clone(), resolved_lazy_val!(value.clone()));276 new_bindings.insert(name.clone(), LazyVal::new_resolved(value.clone()));
276 }277 }
277 Context::new().extend_bound(new_bindings)278 Context::new().extend_bound(new_bindings)
278 }279 }
451 self.settings_mut().import_resolver = resolver;452 self.settings_mut().import_resolver = resolver;
452 }453 }
453454
454 pub fn add_native(&self, name: IStr, cb: Rc<NativeCallback>) {455 pub fn add_native(&self, name: IStr, cb: Gc<NativeCallback>) {
455 self.settings_mut().ext_natives.insert(name, cb);456 self.settings_mut().ext_natives.insert(name, cb);
456 }457 }
457458
488pub mod tests {489pub mod tests {
489 use super::Val;490 use super::Val;
490 use crate::{error::Error::*, primitive_equals, EvaluationState};491 use crate::{
492 error::Error::*, native::NativeCallbackHandler, primitive_equals, EvaluationState,
493 };
494 use jrsonnet_gc::{Finalize, Gc, Trace};
491 use jrsonnet_interner::IStr;495 use jrsonnet_interner::IStr;
492 use jrsonnet_parser::*;496 use jrsonnet_parser::*;
493 use std::{497 use std::{
919 let evaluator = EvaluationState::default();923 let evaluator = EvaluationState::default();
920924
921 evaluator.with_stdlib();925 evaluator.with_stdlib();
922 evaluator.settings_mut().ext_natives.insert(926
923 "native_add".into(),927 #[derive(Trace, Finalize)]
924 Rc::new(NativeCallback::new(928 struct NativeAdd;
925 ParamsDesc(Rc::new(vec![929 impl NativeCallbackHandler for NativeAdd {
926 Param("a".into(), None),
927 Param("b".into(), None),
928 ])),
929 |caller, args| {930 fn call(&self, from: Option<Rc<Path>>, args: &[Val]) -> crate::error::Result<Val> {
930 assert_eq!(931 assert_eq!(
931 &caller.unwrap() as &Path,932 &from.unwrap() as &Path,
932 &PathBuf::from("native_caller.jsonnet")933 &PathBuf::from("native_caller.jsonnet")
933 );934 );
934 match (&args[0], &args[1]) {935 match (&args[0], &args[1]) {
935 (Val::Num(a), Val::Num(b)) => Ok(Val::Num(a + b)),936 (Val::Num(a), Val::Num(b)) => Ok(Val::Num(a + b)),
936 (_, _) => unreachable!(),937 (_, _) => unreachable!(),
937 }938 }
938 },939 }
939 )),940 }
940 );941 evaluator.settings_mut().ext_natives.insert(
942 "native_add".into(),
943 Gc::new(NativeCallback::new(
944 ParamsDesc(Rc::new(vec![
945 Param("a".into(), None),
946 Param("b".into(), None),
947 ])),
948 Box::new(NativeAdd),
949 )),
950 );
941 evaluator.evaluate_snippet_raw(951 evaluator.evaluate_snippet_raw(
942 PathBuf::from("native_caller.jsonnet").into(),952 PathBuf::from("native_caller.jsonnet").into(),
943 "std.assertEqual(std.native(\"native_add\")(1, 2), 3)".into(),953 "std.assertEqual(std.native(\"native_add\")(1, 2), 3)".into(),
modifiedcrates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth
1use jrsonnet_gc::{Gc, Trace};
1use jrsonnet_interner::IStr;2use jrsonnet_interner::IStr;
2use rustc_hash::FxHashMap;3use rustc_hash::FxHashMap;
4
3use std::rc::Rc;5use crate::LazyVal;
46
5#[derive(Default, Debug)]7#[derive(Trace)]
8#[trivially_drop]
6struct LayeredHashMapInternals<V> {9pub struct LayeredHashMapInternals {
7 parent: Option<LayeredHashMap<V>>,10 parent: Option<LayeredHashMap>,
8 current: FxHashMap<IStr, V>,11 current: FxHashMap<IStr, LazyVal>,
9}12}
1013
11#[derive(Debug)]14#[derive(Trace)]
15#[trivially_drop]
12pub struct LayeredHashMap<V>(Rc<LayeredHashMapInternals<V>>);16pub struct LayeredHashMap(Gc<LayeredHashMapInternals>);
1317
14impl<V> LayeredHashMap<V> {18impl LayeredHashMap {
15 pub fn extend(self, new_layer: FxHashMap<IStr, V>) -> Self {19 pub fn extend(self, new_layer: FxHashMap<IStr, LazyVal>) -> Self {
16 match Rc::try_unwrap(self.0) {
17 Ok(mut map) => {
18 map.current.extend(new_layer);
19 Self(Rc::new(map))
20 }
21 Err(this) => Self(Rc::new(LayeredHashMapInternals {20 Self(Gc::new(LayeredHashMapInternals {
22 parent: Some(Self(this)),21 parent: Some(self),
23 current: new_layer,22 current: new_layer,
24 })),23 }))
25 }
26 }24 }
2725
28 pub fn get(&self, key: &IStr) -> Option<&V> {26 pub fn get(&self, key: &IStr) -> Option<&LazyVal> {
29 (self.0)27 (self.0)
30 .current28 .current
31 .get(key)29 .get(key)
32 .or_else(|| self.0.parent.as_ref().and_then(|p| p.get(key)))30 .or_else(|| self.0.parent.as_ref().and_then(|p| p.get(key)))
33 }31 }
34}32}
3533
36impl<V> Clone for LayeredHashMap<V> {34impl Clone for LayeredHashMap {
37 fn clone(&self) -> Self {35 fn clone(&self) -> Self {
38 Self(self.0.clone())36 Self(self.0.clone())
39 }37 }
40}38}
4139
42impl<V> Default for LayeredHashMap<V> {40impl Default for LayeredHashMap {
43 fn default() -> Self {41 fn default() -> Self {
44 Self(Rc::new(LayeredHashMapInternals {42 Self(Gc::new(LayeredHashMapInternals {
45 parent: None,43 parent: None,
46 current: FxHashMap::default(),44 current: FxHashMap::default(),
47 }))45 }))
modifiedcrates/jrsonnet-evaluator/src/native.rsdiffbeforeafterboth
1#![allow(clippy::type_complexity)]1#![allow(clippy::type_complexity)]
22
3use crate::{error::Result, Val};3use crate::{error::Result, Val};
4use jrsonnet_gc::Trace;
4use jrsonnet_parser::ParamsDesc;5use jrsonnet_parser::ParamsDesc;
5use std::fmt::Debug;6use std::fmt::Debug;
6use std::path::Path;7use std::path::Path;
7use std::rc::Rc;8use std::rc::Rc;
89
10pub trait NativeCallbackHandler: Trace {
11 fn call(&self, from: Option<Rc<Path>>, args: &[Val]) -> Result<Val>;
12}
13
14#[derive(Trace)]
15#[trivially_drop]
9pub struct NativeCallback {16pub struct NativeCallback {
10 pub params: ParamsDesc,17 pub params: ParamsDesc,
11 handler: Box<dyn Fn(Option<Rc<Path>>, &[Val]) -> Result<Val>>,18 handler: Box<dyn NativeCallbackHandler>,
12}19}
13impl NativeCallback {20impl NativeCallback {
14 pub fn new(21 pub fn new(params: ParamsDesc, handler: Box<dyn NativeCallbackHandler>) -> Self {
15 params: ParamsDesc,
16 handler: impl Fn(Option<Rc<Path>>, &[Val]) -> Result<Val> + 'static,
17 ) -> Self {
18 Self {22 Self { params, handler }
19 params,
20 handler: Box::new(handler),
21 }
22 }23 }
23 pub fn call(&self, caller: Option<Rc<Path>>, args: &[Val]) -> Result<Val> {24 pub fn call(&self, caller: Option<Rc<Path>>, args: &[Val]) -> Result<Val> {
24 (self.handler)(caller, args)25 self.handler.call(caller, args)
25 }26 }
26}27}
27impl Debug for NativeCallback {28impl Debug for NativeCallback {
modifiedcrates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth
1use crate::{evaluate_add_op, evaluate_assert, Context, LazyBinding, Result, Val};1use crate::{evaluate_add_op, LazyBinding, Result, Val};
2use jrsonnet_gc::{Gc, GcCell, Trace};
2use jrsonnet_interner::IStr;3use jrsonnet_interner::IStr;
3use jrsonnet_parser::{AssertStmt, ExprLocation, Visibility};4use jrsonnet_parser::{ExprLocation, Visibility};
4use rustc_hash::{FxHashMap, FxHashSet};5use rustc_hash::{FxHashMap, FxHashSet};
5use std::hash::{Hash, Hasher};6use std::hash::{Hash, Hasher};
6use std::{cell::RefCell, fmt::Debug, hash::BuildHasherDefault, rc::Rc};7use std::{fmt::Debug, hash::BuildHasherDefault};
78
8#[derive(Debug)]9#[derive(Debug, Trace)]
10#[trivially_drop]
9pub struct ObjMember {11pub struct ObjMember {
10 pub add: bool,12 pub add: bool,
11 pub visibility: Visibility,13 pub visibility: Visibility,
12 pub invoke: LazyBinding,14 pub invoke: LazyBinding,
13 pub location: Option<ExprLocation>,15 pub location: Option<ExprLocation>,
14}16}
17
18pub trait ObjectAssertion: Trace {
19 fn run(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<()>;
20}
1521
16// Field => This22// Field => This
17type CacheKey = (IStr, ObjValue);23type CacheKey = (IStr, ObjValue);
18#[derive(Debug)]24#[derive(Trace)]
25#[trivially_drop]
19pub struct ObjValueInternals {26pub struct ObjValueInternals {
20 context: Context,
21 super_obj: Option<ObjValue>,27 super_obj: Option<ObjValue>,
22 assertions: Rc<Vec<AssertStmt>>,28 assertions: Gc<Vec<Box<dyn ObjectAssertion>>>,
23 assertions_ran: RefCell<FxHashSet<ObjValue>>,29 assertions_ran: GcCell<FxHashSet<ObjValue>>,
24 this_obj: Option<ObjValue>,30 this_obj: Option<ObjValue>,
25 this_entries: Rc<FxHashMap<IStr, ObjMember>>,31 this_entries: Gc<FxHashMap<IStr, ObjMember>>,
26 value_cache: RefCell<FxHashMap<CacheKey, Option<Val>>>,32 value_cache: GcCell<FxHashMap<CacheKey, Option<Val>>>,
27}33}
2834
29#[derive(Clone)]35#[derive(Clone, Trace)]
36#[trivially_drop]
30pub struct ObjValue(pub(crate) Rc<ObjValueInternals>);37pub struct ObjValue(pub(crate) Gc<ObjValueInternals>);
31impl Debug for ObjValue {38impl Debug for ObjValue {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 if let Some(super_obj) = self.0.super_obj.as_ref() {40 if let Some(super_obj) = self.0.super_obj.as_ref() {
5562
56impl ObjValue {63impl ObjValue {
57 pub fn new(64 pub fn new(
58 context: Context,
59 super_obj: Option<Self>,65 super_obj: Option<Self>,
60 this_entries: Rc<FxHashMap<IStr, ObjMember>>,66 this_entries: Gc<FxHashMap<IStr, ObjMember>>,
61 assertions: Rc<Vec<AssertStmt>>,67 assertions: Gc<Vec<Box<dyn ObjectAssertion>>>,
62 ) -> Self {68 ) -> Self {
63 Self(Rc::new(ObjValueInternals {69 Self(Gc::new(ObjValueInternals {
64 context,
65 super_obj,70 super_obj,
66 assertions,71 assertions,
67 assertions_ran: RefCell::new(FxHashSet::default()),72 assertions_ran: GcCell::new(FxHashSet::default()),
68 this_obj: None,73 this_obj: None,
69 this_entries,74 this_entries,
70 value_cache: RefCell::new(FxHashMap::default()),75 value_cache: GcCell::new(FxHashMap::default()),
71 }))76 }))
72 }77 }
73 pub fn new_empty() -> Self {78 pub fn new_empty() -> Self {
74 Self::new(79 Self::new(None, Gc::new(FxHashMap::default()), Gc::new(Vec::new()))
75 Context::new(),
76 None,
77 Rc::new(FxHashMap::default()),
78 Rc::new(Vec::new()),
79 )
80 }80 }
81 pub fn extend_from(&self, super_obj: Self) -> Self {81 pub fn extend_from(&self, super_obj: Self) -> Self {
82 match &self.0.super_obj {82 match &self.0.super_obj {
83 None => Self::new(83 None => Self::new(
84 self.0.context.clone(),
85 Some(super_obj),84 Some(super_obj),
86 self.0.this_entries.clone(),85 self.0.this_entries.clone(),
87 self.0.assertions.clone(),86 self.0.assertions.clone(),
88 ),87 ),
89 Some(v) => Self::new(88 Some(v) => Self::new(
90 self.0.context.clone(),
91 Some(v.extend_from(super_obj)),89 Some(v.extend_from(super_obj)),
92 self.0.this_entries.clone(),90 self.0.this_entries.clone(),
93 self.0.assertions.clone(),91 self.0.assertions.clone(),
94 ),92 ),
95 }93 }
96 }94 }
97 pub fn with_this(&self, this_obj: Self) -> Self {95 pub fn with_this(&self, this_obj: Self) -> Self {
98 Self(Rc::new(ObjValueInternals {96 Self(Gc::new(ObjValueInternals {
99 context: self.0.context.clone(),
100 super_obj: self.0.super_obj.clone(),97 super_obj: self.0.super_obj.clone(),
101 assertions: self.0.assertions.clone(),98 assertions: self.0.assertions.clone(),
102 assertions_ran: RefCell::new(FxHashSet::default()),99 assertions_ran: GcCell::new(FxHashSet::default()),
103 this_obj: Some(this_obj),100 this_obj: Some(this_obj),
104 this_entries: self.0.this_entries.clone(),101 this_entries: self.0.this_entries.clone(),
105 value_cache: RefCell::new(FxHashMap::default()),102 value_cache: GcCell::new(FxHashMap::default()),
106 }))103 }))
107 }104 }
108105
203 pub fn extend_with_field(self, key: IStr, value: ObjMember) -> Self {200 pub fn extend_with_field(self, key: IStr, value: ObjMember) -> Self {
204 let mut new = FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());201 let mut new = FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());
205 new.insert(key, value);202 new.insert(key, value);
206 Self::new(203 Self::new(Some(self), Gc::new(new), Gc::new(Vec::new()))
207 Context::new(),
208 Some(self),
209 Rc::new(new),
210 Rc::new(Vec::new()),
211 )
212 }204 }
213205
249 fn run_assertions_raw(&self, real_this: &Self) -> Result<()> {241 fn run_assertions_raw(&self, real_this: &Self) -> Result<()> {
250 if self.0.assertions_ran.borrow_mut().insert(real_this.clone()) {242 if self.0.assertions_ran.borrow_mut().insert(real_this.clone()) {
251 for assertion in self.0.assertions.iter() {243 for assertion in self.0.assertions.iter() {
252 if let Err(e) = evaluate_assert(244 if let Err(e) = assertion.run(Some(real_this.clone()), self.0.super_obj.clone()) {
253 self.0
254 .context
255 .clone()
256 .with_this_super(real_this.clone(), self.0.super_obj.clone()),
257 assertion,
258 ) {
259 self.0.assertions_ran.borrow_mut().remove(real_this);245 self.0.assertions_ran.borrow_mut().remove(real_this);
260 return Err(e);246 return Err(e);
261 }247 }
271 }257 }
272258
273 pub fn ptr_eq(a: &Self, b: &Self) -> bool {259 pub fn ptr_eq(a: &Self, b: &Self) -> bool {
274 Rc::ptr_eq(&a.0, &b.0)260 Gc::ptr_eq(&a.0, &b.0)
275 }261 }
276}262}
277263
278impl PartialEq for ObjValue {264impl PartialEq for ObjValue {
279 fn eq(&self, other: &Self) -> bool {265 fn eq(&self, other: &Self) -> bool {
280 Rc::ptr_eq(&self.0, &other.0)266 Gc::ptr_eq(&self.0, &other.0)
281 }267 }
282}268}
283269
284impl Eq for ObjValue {}270impl Eq for ObjValue {}
285impl Hash for ObjValue {271impl Hash for ObjValue {
286 fn hash<H: Hasher>(&self, state: &mut H) {272 fn hash<H: Hasher>(&self, hasher: &mut H) {
287 state.write_usize(Rc::as_ptr(&self.0) as usize)273 hasher.write_usize(&*self.0 as *const _ as usize)
288 }274 }
289}275}
290276
modifiedcrates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth
4 error::{Error, LocError, Result},4 error::{Error, LocError, Result},
5 push, Val,5 push, Val,
6};6};
7use jrsonnet_gc::Trace;
7use jrsonnet_parser::ExprLocation;8use jrsonnet_parser::ExprLocation;
8use jrsonnet_types::{ComplexValType, ValType};9use jrsonnet_types::{ComplexValType, ValType};
9use thiserror::Error;10use thiserror::Error;
20 }};21 }};
21}22}
2223
23#[derive(Debug, Error, Clone)]24#[derive(Debug, Error, Clone, Trace)]
25#[trivially_drop]
24pub enum TypeError {26pub enum TypeError {
25 #[error("expected {0}, got {1}")]27 #[error("expected {0}, got {1}")]
26 ExpectedGot(ComplexValType, ValType),28 ExpectedGot(ComplexValType, ValType),
37 }39 }
38}40}
3941
40#[derive(Debug, Clone)]42#[derive(Debug, Clone, Trace)]
43#[trivially_drop]
41pub struct TypeLocError(Box<TypeError>, ValuePathStack);44pub struct TypeLocError(Box<TypeError>, ValuePathStack);
42impl From<TypeError> for TypeLocError {45impl From<TypeError> for TypeLocError {
43 fn from(e: TypeError) -> Self {46 fn from(e: TypeError) -> Self {
59 }62 }
60}63}
6164
62#[derive(Debug, Clone)]65#[derive(Debug, Clone, Trace)]
66#[trivially_drop]
63pub struct TypeLocErrorList(Vec<TypeLocError>);67pub struct TypeLocErrorList(Vec<TypeLocError>);
64impl Display for TypeLocErrorList {68impl Display for TypeLocErrorList {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 }126 }
123}127}
124128
125#[derive(Clone, Debug)]129#[derive(Clone, Debug, Trace)]
130#[trivially_drop]
126enum ValuePathItem {131enum ValuePathItem {
127 Field(Rc<str>),132 Field(Rc<str>),
128 Index(u64),133 Index(u64),
137 }142 }
138}143}
139144
140#[derive(Clone, Debug)]145#[derive(Clone, Debug, Trace)]
146#[trivially_drop]
141struct ValuePathStack(Vec<ValuePathItem>);147struct ValuePathStack(Vec<ValuePathItem>);
142impl Display for ValuePathStack {148impl Display for ValuePathStack {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
3 call_builtin,3 call_builtin,
4 manifest::{manifest_json_ex, ManifestJsonOptions, ManifestType},4 manifest::{manifest_json_ex, ManifestJsonOptions, ManifestType},
5 },5 },
6 error::Error::*,6 error::{Error::*, LocError},
7 evaluate,7 evaluate,
8 function::{parse_function_call, parse_function_call_map, place_args},8 function::{parse_function_call, parse_function_call_map, place_args},
9 native::NativeCallback,9 native::NativeCallback,
10 throw, with_state, Context, ObjValue, Result,10 throw, with_state, Context, ObjValue, Result,
11};11};
12use jrsonnet_gc::{Finalize, Gc, GcCell, Trace};
12use jrsonnet_interner::IStr;13use jrsonnet_interner::IStr;
13use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, ExprLocation, LiteralType, LocExpr, ParamsDesc};14use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, ExprLocation, LiteralType, LocExpr, ParamsDesc};
14use jrsonnet_types::ValType;15use jrsonnet_types::ValType;
15use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};16use std::{collections::HashMap, fmt::Debug, rc::Rc};
1617
18pub trait LazyValValue: Trace {
19 fn get(self: Box<Self>) -> Result<Val>;
20}
21
22#[derive(Trace)]
23#[trivially_drop]
17enum LazyValInternals {24enum LazyValInternals {
18 Computed(Val),25 Computed(Val),
26 Errored(LocError),
19 Waiting(Box<dyn Fn() -> Result<Val>>),27 Waiting(Box<dyn LazyValValue>),
28 Pending,
20}29}
30
21#[derive(Clone)]31#[derive(Clone, Trace)]
32#[trivially_drop]
22pub struct LazyVal(Rc<RefCell<LazyValInternals>>);33pub struct LazyVal(Gc<GcCell<LazyValInternals>>);
23impl LazyVal {34impl LazyVal {
24 pub fn new(f: Box<dyn Fn() -> Result<Val>>) -> Self {35 pub fn new(f: Box<dyn LazyValValue>) -> Self {
25 Self(Rc::new(RefCell::new(LazyValInternals::Waiting(f))))36 Self(Gc::new(GcCell::new(LazyValInternals::Waiting(f))))
26 }37 }
27 pub fn new_resolved(val: Val) -> Self {38 pub fn new_resolved(val: Val) -> Self {
28 Self(Rc::new(RefCell::new(LazyValInternals::Computed(val))))39 Self(Gc::new(GcCell::new(LazyValInternals::Computed(val))))
29 }40 }
30 pub fn evaluate(&self) -> Result<Val> {41 pub fn evaluate(&self) -> Result<Val> {
31 let new_value = match &*self.0.borrow() {42 match &*self.0.borrow() {
32 LazyValInternals::Computed(v) => return Ok(v.clone()),43 LazyValInternals::Computed(v) => return Ok(v.clone()),
33 LazyValInternals::Waiting(f) => f()?,44 LazyValInternals::Errored(e) => return Err(e.clone()),
45 LazyValInternals::Pending => return Err(RecursiveLazyValueEvaluation.into()),
46 _ => (),
34 };47 };
48 let value = if let LazyValInternals::Waiting(value) =
49 std::mem::replace(&mut *self.0.borrow_mut(), LazyValInternals::Pending)
50 {
51 value
52 } else {
53 unreachable!()
54 };
55 let new_value = match value.get() {
56 Ok(v) => v,
57 Err(e) => {
58 *self.0.borrow_mut() = LazyValInternals::Errored(e.clone());
59 return Err(e);
60 }
61 };
35 *self.0.borrow_mut() = LazyValInternals::Computed(new_value.clone());62 *self.0.borrow_mut() = LazyValInternals::Computed(new_value.clone());
36 Ok(new_value)63 Ok(new_value)
37 }64 }
38}65}
3966
40#[macro_export]
41macro_rules! lazy_val {
42 ($f: expr) => {
43 $crate::LazyVal::new(Box::new($f))
44 };
45}
46#[macro_export]
47macro_rules! resolved_lazy_val {
48 ($f: expr) => {
49 $crate::LazyVal::new_resolved($f)
50 };
51}
52impl Debug for LazyVal {67impl Debug for LazyVal {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 write!(f, "Lazy")69 write!(f, "Lazy")
55 }70 }
56}71}
57impl PartialEq for LazyVal {72impl PartialEq for LazyVal {
58 fn eq(&self, other: &Self) -> bool {73 fn eq(&self, other: &Self) -> bool {
59 Rc::ptr_eq(&self.0, &other.0)74 Gc::ptr_eq(&self.0, &other.0)
60 }75 }
61}76}
6277
63#[derive(Debug, PartialEq)]78#[derive(Debug, PartialEq, Trace)]
79#[trivially_drop]
64pub struct FuncDesc {80pub struct FuncDesc {
65 pub name: IStr,81 pub name: IStr,
66 pub ctx: Context,82 pub ctx: Context,
67 pub params: ParamsDesc,83 pub params: ParamsDesc,
68 pub body: LocExpr,84 pub body: LocExpr,
69}85}
7086
71#[derive(Debug)]87#[derive(Debug, Trace)]
88#[trivially_drop]
72pub enum FuncVal {89pub enum FuncVal {
73 /// Plain function implemented in jsonnet90 /// Plain function implemented in jsonnet
74 Normal(FuncDesc),91 Normal(FuncDesc),
75 /// Standard library function92 /// Standard library function
76 Intrinsic(IStr),93 Intrinsic(IStr),
77 /// Library functions implemented in native94 /// Library functions implemented in native
78 NativeExt(IStr, Rc<NativeCallback>),95 NativeExt(IStr, Gc<NativeCallback>),
79}96}
8097
81impl PartialEq for FuncVal {98impl PartialEq for FuncVal {
172 String,189 String,
173}190}
174191
175#[derive(Debug, Clone)]192#[derive(Debug, Clone, Trace)]
193#[trivially_drop]
176pub enum ArrValue {194pub enum ArrValue {
177 Lazy(Rc<Vec<LazyVal>>),195 Lazy(Gc<Vec<LazyVal>>),
178 Eager(Rc<Vec<Val>>),196 Eager(Gc<Vec<Val>>),
179 Extended(Box<(Self, Self)>),197 Extended(Box<(Self, Self)>),
180}198}
181impl ArrValue {199impl ArrValue {
182 pub fn new_eager() -> Self {200 pub fn new_eager() -> Self {
183 Self::Eager(Rc::new(Vec::new()))201 Self::Eager(Gc::new(Vec::new()))
184 }202 }
185203
186 pub fn len(&self) -> usize {204 pub fn len(&self) -> usize {
231 }249 }
232 }250 }
233251
234 pub fn evaluated(&self) -> Result<Rc<Vec<Val>>> {252 pub fn evaluated(&self) -> Result<Gc<Vec<Val>>> {
235 Ok(match self {253 Ok(match self {
236 Self::Lazy(vec) => {254 Self::Lazy(vec) => {
237 let mut out = Vec::with_capacity(vec.len());255 let mut out = Vec::with_capacity(vec.len());
238 for item in vec.iter() {256 for item in vec.iter() {
239 out.push(item.evaluate()?);257 out.push(item.evaluate()?);
240 }258 }
241 Rc::new(out)259 Gc::new(out)
242 }260 }
243 Self::Eager(vec) => vec.clone(),261 Self::Eager(vec) => vec.clone(),
244 Self::Extended(_v) => {262 Self::Extended(_v) => {
245 let mut out = Vec::with_capacity(self.len());263 let mut out = Vec::with_capacity(self.len());
246 for item in self.iter() {264 for item in self.iter() {
247 out.push(item?);265 out.push(item?);
248 }266 }
249 Rc::new(out)267 Gc::new(out)
250 }268 }
251 })269 })
252 }270 }
272 Self::Lazy(vec) => {290 Self::Lazy(vec) => {
273 let mut out = (&vec as &Vec<_>).clone();291 let mut out = (&vec as &Vec<_>).clone();
274 out.reverse();292 out.reverse();
275 Self::Lazy(Rc::new(out))293 Self::Lazy(Gc::new(out))
276 }294 }
277 Self::Eager(vec) => {295 Self::Eager(vec) => {
278 let mut out = (&vec as &Vec<_>).clone();296 let mut out = (&vec as &Vec<_>).clone();
279 out.reverse();297 out.reverse();
280 Self::Eager(Rc::new(out))298 Self::Eager(Gc::new(out))
281 }299 }
282 Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),300 Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),
283 }301 }
290 out.push(mapper(value?)?);308 out.push(mapper(value?)?);
291 }309 }
292310
293 Ok(Self::Eager(Rc::new(out)))311 Ok(Self::Eager(Gc::new(out)))
294 }312 }
295313
296 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {314 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {
303 }321 }
304 }322 }
305323
306 Ok(Self::Eager(Rc::new(out)))324 Ok(Self::Eager(Gc::new(out)))
307 }325 }
308326
309 pub fn ptr_eq(a: &Self, b: &Self) -> bool {327 pub fn ptr_eq(a: &Self, b: &Self) -> bool {
310 match (a, b) {328 match (a, b) {
311 (Self::Lazy(a), Self::Lazy(b)) => Rc::ptr_eq(a, b),329 (Self::Lazy(a), Self::Lazy(b)) => Gc::ptr_eq(a, b),
312 (Self::Eager(a), Self::Eager(b)) => Rc::ptr_eq(a, b),330 (Self::Eager(a), Self::Eager(b)) => Gc::ptr_eq(a, b),
313 _ => false,331 _ => false,
314 }332 }
315 }333 }
316}334}
317335
318impl From<Vec<LazyVal>> for ArrValue {336impl From<Vec<LazyVal>> for ArrValue {
319 fn from(v: Vec<LazyVal>) -> Self {337 fn from(v: Vec<LazyVal>) -> Self {
320 Self::Lazy(Rc::new(v))338 Self::Lazy(Gc::new(v))
321 }339 }
322}340}
323341
324impl From<Vec<Val>> for ArrValue {342impl From<Vec<Val>> for ArrValue {
325 fn from(v: Vec<Val>) -> Self {343 fn from(v: Vec<Val>) -> Self {
326 Self::Eager(Rc::new(v))344 Self::Eager(Gc::new(v))
327 }345 }
328}346}
347
348#[derive(Debug)]
349pub struct DebugGcTraceValue {
350 name: IStr,
351 pub value: Box<Val>,
352}
353impl DebugGcTraceValue {
354 fn print(&self, action: &str) {
355 println!("{} {}#{:?}", action, self.name, &*self.value as *const _)
356 }
357}
358impl Finalize for DebugGcTraceValue {
359 fn finalize(&self) {
360 self.print("Garbage-collecting")
361 }
362}
363impl Drop for DebugGcTraceValue {
364 fn drop(&mut self) {
365 self.print("Garbage-collected")
366 }
367}
368unsafe impl Trace for DebugGcTraceValue {
369 unsafe fn trace(&self) {
370 self.print("Traced");
371 self.value.trace()
372 }
373 unsafe fn root(&self) {
374 self.print("Rooted");
375 self.value.root()
376 }
377 unsafe fn unroot(&self) {
378 self.print("Unrooted");
379 self.value.unroot()
380 }
381 fn finalize_glue(&self) {
382 Finalize::finalize(self)
383 }
384}
385impl Clone for DebugGcTraceValue {
386 fn clone(&self) -> Self {
387 self.print("Cloned");
388 let value = Self {
389 name: self.name.clone(),
390 value: self.value.clone(),
391 };
392 value.print("I'm clone");
393 value
394 }
395}
396impl DebugGcTraceValue {
397 pub fn create(name: IStr, value: Val) -> Val {
398 let value = Self {
399 name,
400 value: Box::new(value),
401 };
402 value.print("Constructed");
403 Val::DebugGcTraceValue(value)
404 }
405}
329406
330#[derive(Debug, Clone)]407#[derive(Debug, Clone, Trace)]
408#[trivially_drop]
331pub enum Val {409pub enum Val {
332 Bool(bool),410 Bool(bool),
333 Null,411 Null,
334 Str(IStr),412 Str(IStr),
335 Num(f64),413 Num(f64),
336 Arr(ArrValue),414 Arr(ArrValue),
337 Obj(ObjValue),415 Obj(ObjValue),
338 Func(Rc<FuncVal>),416 Func(Gc<FuncVal>),
417 DebugGcTraceValue(DebugGcTraceValue),
339}418}
340419
341macro_rules! matches_unwrap {420macro_rules! matches_unwrap {
368 pub fn unwrap_num(self) -> Result<f64> {447 pub fn unwrap_num(self) -> Result<f64> {
369 Ok(matches_unwrap!(self, Self::Num(v), v))448 Ok(matches_unwrap!(self, Self::Num(v), v))
370 }449 }
371 pub fn unwrap_func(self) -> Result<Rc<FuncVal>> {450 pub fn unwrap_func(self) -> Result<Gc<FuncVal>> {
372 Ok(matches_unwrap!(self, Self::Func(v), v))451 Ok(matches_unwrap!(self, Self::Func(v), v))
373 }452 }
374 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {453 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {
392 Self::Bool(_) => ValType::Bool,471 Self::Bool(_) => ValType::Bool,
393 Self::Null => ValType::Null,472 Self::Null => ValType::Null,
394 Self::Func(..) => ValType::Func,473 Self::Func(..) => ValType::Func,
474 Self::DebugGcTraceValue(v) => v.value.value_type(),
395 }475 }
396 }476 }
397477
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"] }
1213
modifiedcrates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth
1use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};
1use rustc_hash::FxHashMap;2use rustc_hash::FxHashMap;
2use serde::{Deserialize, Serialize};3use serde::{Deserialize, Serialize};
3use std::{4use std::{
1011
11#[derive(Clone, PartialOrd, Ord, Eq)]12#[derive(Clone, PartialOrd, Ord, Eq)]
12pub struct IStr(Rc<str>);13pub struct IStr(Rc<str>);
14impl Finalize for IStr {}
15unsafe impl Trace for IStr {
16 unsafe_empty_trace!();
17}
1318
14impl Deref for IStr {19impl Deref for IStr {
15 type Target = str;20 type Target = str;
modifiedcrates/jrsonnet-parser/Cargo.tomldiffbeforeafterboth
18unescape = "0.1.0"18unescape = "0.1.0"
1919
20serde = { version = "1.0", features = ["derive", "rc"], optional = true }20serde = { version = "1.0", features = ["derive", "rc"], optional = true }
21jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
2122
22[dev-dependencies]23[dev-dependencies]
23jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.3.8" }24jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.3.8" }
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
1use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};
1use jrsonnet_interner::IStr;2use jrsonnet_interner::IStr;
2#[cfg(feature = "deserialize")]3#[cfg(feature = "deserialize")]
3use serde::Deserialize;4use serde::Deserialize;
1213
13#[cfg_attr(feature = "serialize", derive(Serialize))]14#[cfg_attr(feature = "serialize", derive(Serialize))]
14#[cfg_attr(feature = "deserialize", derive(Deserialize))]15#[cfg_attr(feature = "deserialize", derive(Deserialize))]
15#[derive(Debug, PartialEq)]16#[derive(Debug, PartialEq, Trace)]
17#[trivially_drop]
16pub enum FieldName {18pub enum FieldName {
17 /// {fixed: 2}19 /// {fixed: 2}
18 Fixed(IStr),20 Fixed(IStr),
2224
23#[cfg_attr(feature = "serialize", derive(Serialize))]25#[cfg_attr(feature = "serialize", derive(Serialize))]
24#[cfg_attr(feature = "deserialize", derive(Deserialize))]26#[cfg_attr(feature = "deserialize", derive(Deserialize))]
25#[derive(Debug, Clone, Copy, PartialEq)]27#[derive(Debug, Clone, Copy, PartialEq, Trace)]
28#[trivially_drop]
26pub enum Visibility {29pub enum Visibility {
27 /// :30 /// :
28 Normal,31 Normal,
4043
41#[cfg_attr(feature = "serialize", derive(Serialize))]44#[cfg_attr(feature = "serialize", derive(Serialize))]
42#[cfg_attr(feature = "deserialize", derive(Deserialize))]45#[cfg_attr(feature = "deserialize", derive(Deserialize))]
43#[derive(Clone, Debug, PartialEq)]46#[derive(Clone, Debug, PartialEq, Trace)]
47#[trivially_drop]
44pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);48pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);
4549
46#[cfg_attr(feature = "serialize", derive(Serialize))]50#[cfg_attr(feature = "serialize", derive(Serialize))]
47#[cfg_attr(feature = "deserialize", derive(Deserialize))]51#[cfg_attr(feature = "deserialize", derive(Deserialize))]
48#[derive(Debug, PartialEq)]52#[derive(Debug, PartialEq, Trace)]
53#[trivially_drop]
49pub struct FieldMember {54pub struct FieldMember {
50 pub name: FieldName,55 pub name: FieldName,
51 pub plus: bool,56 pub plus: bool,
5661
57#[cfg_attr(feature = "serialize", derive(Serialize))]62#[cfg_attr(feature = "serialize", derive(Serialize))]
58#[cfg_attr(feature = "deserialize", derive(Deserialize))]63#[cfg_attr(feature = "deserialize", derive(Deserialize))]
59#[derive(Debug, PartialEq)]64#[derive(Debug, PartialEq, Trace)]
65#[trivially_drop]
60pub enum Member {66pub enum Member {
61 Field(FieldMember),67 Field(FieldMember),
62 BindStmt(BindSpec),68 BindStmt(BindSpec),
6571
66#[cfg_attr(feature = "serialize", derive(Serialize))]72#[cfg_attr(feature = "serialize", derive(Serialize))]
67#[cfg_attr(feature = "deserialize", derive(Deserialize))]73#[cfg_attr(feature = "deserialize", derive(Deserialize))]
68#[derive(Debug, Clone, Copy, PartialEq)]74#[derive(Debug, Clone, Copy, PartialEq, Trace)]
75#[trivially_drop]
69pub enum UnaryOpType {76pub enum UnaryOpType {
70 Plus,77 Plus,
71 Minus,78 Minus,
9098
91#[cfg_attr(feature = "serialize", derive(Serialize))]99#[cfg_attr(feature = "serialize", derive(Serialize))]
92#[cfg_attr(feature = "deserialize", derive(Deserialize))]100#[cfg_attr(feature = "deserialize", derive(Deserialize))]
93#[derive(Debug, Clone, Copy, PartialEq)]101#[derive(Debug, Clone, Copy, PartialEq, Trace)]
102#[trivially_drop]
94pub enum BinaryOpType {103pub enum BinaryOpType {
95 Mul,104 Mul,
96 Div,105 Div,
152/// name, default value162/// name, default value
153#[cfg_attr(feature = "serialize", derive(Serialize))]163#[cfg_attr(feature = "serialize", derive(Serialize))]
154#[cfg_attr(feature = "deserialize", derive(Deserialize))]164#[cfg_attr(feature = "deserialize", derive(Deserialize))]
155#[derive(Debug, PartialEq)]165#[derive(Debug, PartialEq, Trace)]
166#[trivially_drop]
156pub struct Param(pub IStr, pub Option<LocExpr>);167pub struct Param(pub IStr, pub Option<LocExpr>);
157168
158/// Defined function parameters169/// Defined function parameters
161#[derive(Debug, Clone, PartialEq)]172#[derive(Debug, Clone, PartialEq)]
162pub struct ParamsDesc(pub Rc<Vec<Param>>);173pub struct ParamsDesc(pub Rc<Vec<Param>>);
174
175/// Safety:
176/// AST is acyclic, and there should be no gc pointers
177unsafe impl Trace for ParamsDesc {
178 unsafe_empty_trace!();
179}
180impl Finalize for ParamsDesc {}
181
163impl Deref for ParamsDesc {182impl Deref for ParamsDesc {
164 type Target = Vec<Param>;183 type Target = Vec<Param>;
169188
170#[cfg_attr(feature = "serialize", derive(Serialize))]189#[cfg_attr(feature = "serialize", derive(Serialize))]
171#[cfg_attr(feature = "deserialize", derive(Deserialize))]190#[cfg_attr(feature = "deserialize", derive(Deserialize))]
172#[derive(Debug, PartialEq)]191#[derive(Debug, PartialEq, Trace)]
192#[trivially_drop]
173pub struct Arg(pub Option<String>, pub LocExpr);193pub struct Arg(pub Option<String>, pub LocExpr);
174194
175#[cfg_attr(feature = "serialize", derive(Serialize))]195#[cfg_attr(feature = "serialize", derive(Serialize))]
176#[cfg_attr(feature = "deserialize", derive(Deserialize))]196#[cfg_attr(feature = "deserialize", derive(Deserialize))]
177#[derive(Debug, PartialEq)]197#[derive(Debug, PartialEq, Trace)]
198#[trivially_drop]
178pub struct ArgsDesc(pub Vec<Arg>);199pub struct ArgsDesc(pub Vec<Arg>);
200
179impl Deref for ArgsDesc {201impl Deref for ArgsDesc {
185207
186#[cfg_attr(feature = "serialize", derive(Serialize))]208#[cfg_attr(feature = "serialize", derive(Serialize))]
187#[cfg_attr(feature = "deserialize", derive(Deserialize))]209#[cfg_attr(feature = "deserialize", derive(Deserialize))]
188#[derive(Debug, Clone, PartialEq)]210#[derive(Debug, Clone, PartialEq, Trace)]
211#[trivially_drop]
189pub struct BindSpec {212pub struct BindSpec {
190 pub name: IStr,213 pub name: IStr,
191 pub params: Option<ParamsDesc>,214 pub params: Option<ParamsDesc>,
194217
195#[cfg_attr(feature = "serialize", derive(Serialize))]218#[cfg_attr(feature = "serialize", derive(Serialize))]
196#[cfg_attr(feature = "deserialize", derive(Deserialize))]219#[cfg_attr(feature = "deserialize", derive(Deserialize))]
197#[derive(Debug, PartialEq)]220#[derive(Debug, PartialEq, Trace)]
221#[trivially_drop]
198pub struct IfSpecData(pub LocExpr);222pub struct IfSpecData(pub LocExpr);
199223
200#[cfg_attr(feature = "serialize", derive(Serialize))]224#[cfg_attr(feature = "serialize", derive(Serialize))]
201#[cfg_attr(feature = "deserialize", derive(Deserialize))]225#[cfg_attr(feature = "deserialize", derive(Deserialize))]
202#[derive(Debug, PartialEq)]226#[derive(Debug, PartialEq, Trace)]
227#[trivially_drop]
203pub struct ForSpecData(pub IStr, pub LocExpr);228pub struct ForSpecData(pub IStr, pub LocExpr);
204229
205#[cfg_attr(feature = "serialize", derive(Serialize))]230#[cfg_attr(feature = "serialize", derive(Serialize))]
206#[cfg_attr(feature = "deserialize", derive(Deserialize))]231#[cfg_attr(feature = "deserialize", derive(Deserialize))]
207#[derive(Debug, PartialEq)]232#[derive(Debug, PartialEq, Trace)]
233#[trivially_drop]
208pub enum CompSpec {234pub enum CompSpec {
209 IfSpec(IfSpecData),235 IfSpec(IfSpecData),
210 ForSpec(ForSpecData),236 ForSpec(ForSpecData),
211}237}
212238
213#[cfg_attr(feature = "serialize", derive(Serialize))]239#[cfg_attr(feature = "serialize", derive(Serialize))]
214#[cfg_attr(feature = "deserialize", derive(Deserialize))]240#[cfg_attr(feature = "deserialize", derive(Deserialize))]
215#[derive(Debug, PartialEq)]241#[derive(Debug, PartialEq, Trace)]
242#[trivially_drop]
216pub struct ObjComp {243pub struct ObjComp {
217 pub pre_locals: Vec<BindSpec>,244 pub pre_locals: Vec<BindSpec>,
218 pub key: LocExpr,245 pub key: LocExpr,
223250
224#[cfg_attr(feature = "serialize", derive(Serialize))]251#[cfg_attr(feature = "serialize", derive(Serialize))]
225#[cfg_attr(feature = "deserialize", derive(Deserialize))]252#[cfg_attr(feature = "deserialize", derive(Deserialize))]
226#[derive(Debug, PartialEq)]253#[derive(Debug, PartialEq, Trace)]
254#[trivially_drop]
227pub enum ObjBody {255pub enum ObjBody {
228 MemberList(Vec<Member>),256 MemberList(Vec<Member>),
229 ObjComp(ObjComp),257 ObjComp(ObjComp),
230}258}
231259
232#[cfg_attr(feature = "serialize", derive(Serialize))]260#[cfg_attr(feature = "serialize", derive(Serialize))]
233#[cfg_attr(feature = "deserialize", derive(Deserialize))]261#[cfg_attr(feature = "deserialize", derive(Deserialize))]
234#[derive(Debug, PartialEq, Clone, Copy)]262#[derive(Debug, PartialEq, Clone, Copy, Trace)]
263#[trivially_drop]
235pub enum LiteralType {264pub enum LiteralType {
236 This,265 This,
237 Super,266 Super,
241 False,270 False,
242}271}
243272
244#[derive(Debug, PartialEq)]273#[derive(Debug, PartialEq, Trace)]
274#[trivially_drop]
245pub struct SliceDesc {275pub struct SliceDesc {
246 pub start: Option<LocExpr>,276 pub start: Option<LocExpr>,
247 pub end: Option<LocExpr>,277 pub end: Option<LocExpr>,
251/// Syntax base281/// Syntax base
252#[cfg_attr(feature = "serialize", derive(Serialize))]282#[cfg_attr(feature = "serialize", derive(Serialize))]
253#[cfg_attr(feature = "deserialize", derive(Deserialize))]283#[cfg_attr(feature = "deserialize", derive(Deserialize))]
254#[derive(Debug, PartialEq)]284#[derive(Debug, PartialEq, Trace)]
285#[trivially_drop]
255pub enum Expr {286pub enum Expr {
256 Literal(LiteralType),287 Literal(LiteralType),
257288
319/// file, begin offset, end offset350/// file, begin offset, end offset
320#[cfg_attr(feature = "serialize", derive(Serialize))]351#[cfg_attr(feature = "serialize", derive(Serialize))]
321#[cfg_attr(feature = "deserialize", derive(Deserialize))]352#[cfg_attr(feature = "deserialize", derive(Deserialize))]
322#[derive(Clone, PartialEq)]353#[derive(Clone, PartialEq, Trace)]
354#[trivially_drop]
323pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);355pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);
356
324impl Debug for ExprLocation {357impl Debug for ExprLocation {
332#[cfg_attr(feature = "deserialize", derive(Deserialize))]365#[cfg_attr(feature = "deserialize", derive(Deserialize))]
333#[derive(Clone, PartialEq)]366#[derive(Clone, PartialEq)]
334pub struct LocExpr(pub Rc<Expr>, pub Option<ExprLocation>);367pub struct LocExpr(pub Rc<Expr>, pub Option<ExprLocation>);
368/// Safety:
369/// AST is acyclic, and there should be no gc pointers
370unsafe impl Trace for LocExpr {
371 unsafe_empty_trace!();
372}
373impl Finalize for LocExpr {}
374
335impl Debug for LocExpr {375impl Debug for LocExpr {
336 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {376 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
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"] }
1112
modifiedcrates/jrsonnet-types/src/lib.rsdiffbeforeafterboth
1#![allow(clippy::redundant_closure_call)]1#![allow(clippy::redundant_closure_call)]
22
3use jrsonnet_gc::Trace;
3use std::fmt::Display;4use std::fmt::Display;
45
5#[macro_export]6#[macro_export]
77 );78 );
78}79}
7980
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]81#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]
82#[trivially_drop]
81pub enum ValType {83pub enum ValType {
82 Bool,84 Bool,
83 Null,85 Null,
109 }111 }
110}112}
111113
112#[derive(Debug, Clone, PartialEq)]114#[derive(Debug, Clone, PartialEq, Trace)]
115#[trivially_drop]
113pub enum ComplexValType {116pub enum ComplexValType {
114 Any,117 Any,
115 Char,118 Char,
modifiedflake.lockdiffbeforeafterboth
2 "nodes": {2 "nodes": {
3 "flake-utils": {3 "flake-utils": {
4 "locked": {4 "locked": {
5 "lastModified": 1614513358,5 "lastModified": 1623875721,
6 "narHash": "sha256-LakhOx3S1dRjnh0b5Dg3mbZyH0ToC9I8Y2wKSkBaTzU=",6 "narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=",
7 "owner": "numtide",7 "owner": "numtide",
8 "repo": "flake-utils",8 "repo": "flake-utils",
9 "rev": "5466c5bbece17adaab2d82fae80b46e807611bf3",9 "rev": "f7e004a55b120c02ecb6219596820fcd32ca8772",
10 "type": "github"10 "type": "github"
11 },11 },
12 "original": {12 "original": {
17 },17 },
18 "nixpkgs": {18 "nixpkgs": {
19 "locked": {19 "locked": {
20 "lastModified": 1615532953,20 "lastModified": 1625281901,
21 "narHash": "sha256-SWpaGjrp/INzorEqMz3HLi6Uuk9I0KAn4YS8B4n3q5g=",21 "narHash": "sha256-DkZDtTIPzhXATqIps2ifNFpnI+PTcfMYdcrx/oFm00Q=",
22 "owner": "NixOS",22 "owner": "NixOS",
23 "repo": "nixpkgs",23 "repo": "nixpkgs",
24 "rev": "916ee862e87ac5ee2439f2fb7856386b4dc906ae",24 "rev": "09c38c29f2c719cd76ca17a596c2fdac9e186ceb",
25 "type": "github"25 "type": "github"
26 },26 },
27 "original": {27 "original": {
modifiedflake.nixdiffbeforeafterboth
12 pname = "jrsonnet";12 pname = "jrsonnet";
13 version = "0.1.0";13 version = "0.1.0";
14 src = self;14 src = self;
15 cargoSha256 = "sha256-6VhaQi3L2LWzR0cq7oRG81MDbrKJbzSNPcvYSoQ5ISo=";15 cargoSha256 = "sha256-cez8pJ/uwj+PHAPQwpSB4CKaxcP8Uvv8xguOrVXR2xE=";
16 };16 };
17 in { 17 in {
18 defaultPackage = jrsonnet;18 defaultPackage = jrsonnet;