difftreelog
refactor switch gc to gcmodule
in: master
39 files changed
.github/workflows/release.ymldiffbeforeafterboth21 args: --all21 args: --all222223 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-latest27 steps:27 steps:Cargo.tomldiffbeforeafterboth1[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]bindings/jsonnet/Cargo.tomldiffbeforeafterboth10[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" }141415[lib]15[lib]16crate-type = ["cdylib"]16crate-type = ["cdylib"]bindings/jsonnet/src/native.rsdiffbeforeafterboth1use 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;202122#[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())));747475 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}bindings/jsonnet/src/val_make.rsdiffbeforeafterboth1//! Create values in VM1//! Create values in VM223use 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},383839#[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}434344#[no_mangle]44#[no_mangle]bindings/jsonnet/src/val_modify.rsdiffbeforeafterboth2//! 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 here3//! In jrsonnet every value is immutable, and this code is probally broken3//! In jrsonnet every value is immutable, and this code is probally broken445use 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};9923 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 }cmds/jrsonnet/Cargo.tomldiffbeforeafterboth17jrsonnet-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" }202121[dependencies.clap]22[dependencies.clap]22git = "https://github.com/clap-rs/clap"23git = "https://github.com/clap-rs/clap"cmds/jrsonnet/src/main.rsdiffbeforeafterboth136136137 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 == "-" {crates/jrsonnet-cli/Cargo.tomldiffbeforeafterboth12 "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] }201621[dependencies.clap]17[dependencies.clap]22git = "https://github.com/clap-rs/clap"18git = "https://github.com/clap-rs/clap"crates/jrsonnet-cli/src/lib.rsdiffbeforeafterboth103#[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 collection107 #[clap(long, default_value = "20000000")]108 gc_initial_threshold: usize,109 /// How much heap should grow after unsuccessful garbage collection110 #[clap(long)]111 gc_used_space_ratio: Option<f64>,112 /// Do not skip gc on exit106 /// Do not skip gc on exit113 #[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}130139pub 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}154144crates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth32rustc-hash = "1.1.0"32rustc-hash = "1.1.0"333334thiserror = "1.0"34thiserror = "1.0"35jrsonnet-gc = { version = "0.4.2", features = ["derive"] }35gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }363637[dependencies.anyhow]37[dependencies.anyhow]38version = "1.0"38version = "1.0"535354# Explaining traces54# Explaining traces55[dependencies.annotate-snippets]55[dependencies.annotate-snippets]56version = "0.9.0"56version = "0.9.1"57features = ["color"]57features = ["color"]58optional = true58optional = true5959crates/jrsonnet-evaluator/build.rsdiffbeforeafterboth13 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");crates/jrsonnet-evaluator/src/builtin/format.rsdiffbeforeafterboth2#![allow(clippy::too_many_arguments)]2#![allow(clippy::too_many_arguments)]334use 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;9910#[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,crates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth1use 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};556#[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();crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth7 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;242425pub 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}707071type Builtin = fn(context: Context, loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val>;71type Builtin = fn(context: Context, loc: &ExprLocation, args: &ArgsDesc) -> Result<Val>;727273type BuiltinsType = HashMap<Box<str>, Builtin>;73type BuiltinsType = HashMap<Box<str>, Builtin>;7474136 };136 };137}137}138138139fn 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}156156157fn 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 ], {164164165fn 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, [184180185fn 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, [196188197fn 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, [210198211fn 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, [224208225fn 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}238218239fn 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}254234255fn 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;265245266fn 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}278254279fn 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}287263288fn 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}296272297fn 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}305281306fn 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}313289314fn 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}321297322fn 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}329305330fn 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}338314339fn 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}346322347fn 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}354330355fn 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}362338363fn 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}370346371fn 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}378354379fn 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}386362387fn 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}394370395fn 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}413389414fn 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}421397422fn 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}429405430fn 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}437413438fn 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}445421446fn 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}456432457fn 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}466442467fn 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}500476501fn 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}514490515fn 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}545517546fn 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}554526555fn 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}570542571fn 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 ], {582554583fn 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, [594562595fn 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}611575612fn 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}619583620fn 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}636598637fn 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 ], {654616655fn 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, [671633672fn 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}687645688fn 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;744702745fn 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, [756714757fn 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, [772726773fn 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}788742789fn 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}796750797fn 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 ], {804758805fn 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, [818768819fn 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, [841787842fn 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, [853795854fn 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}865803866fn 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}889827890fn 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);905843906pub 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> {crates/jrsonnet-evaluator/src/builtin/sort.rsdiffbeforeafterboth2 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};667#[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}616162pub 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}104104crates/jrsonnet-evaluator/src/builtin/stdlib.rsdiffbeforeafterboth15 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 )crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth1use 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;101011#[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}242325#[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}383639#[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 }585559 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 }858286 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 }928893 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 }969297 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))152147153impl 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}158153crates/jrsonnet-evaluator/src/dynamic.rsdiffbeforeafterboth1use std::cell::RefCell;21use jrsonnet_gc::{Gc, GcCell, Trace};3use gcmodule::{Cc, Trace};243#[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");crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth1use 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;111412#[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 },98101150}153}151154152#[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>);161162162#[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 {crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth2 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;191820pub fn evaluate_binding_in_future(19pub fn evaluate_binding_in_future(26 let params = params.clone();25 let params = params.clone();272628 #[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 }464447 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}737077 let params = params.clone();74 let params = params.clone();787579 #[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 }10096101 #[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,114110115 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 }122119123 (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 }152148153 #[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,165161166 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 }172169173 (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}183180184pub 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 members246 .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();273269274 #[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 obj394 .pre_locals384 .pre_locals406 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.context411 .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();crates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth1use 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;10611const 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";13914#[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 them91 // Default values should be created in newly created context85 // Default values should be created in newly created context92 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 );978898 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(¶m.0.clone()) {90 if passed_args.contains_key(¶m.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 })));119109120 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 = params185 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};247239248 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)crates/jrsonnet-evaluator/src/gc.rsdiffbeforeafterbothno changes
crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth25use 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;454546pub 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}4949#[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}545574 /// 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.native77 pub ext_natives: HashMap<IStr, Gc<NativeCallback>>,78 pub ext_natives: HashMap<IStr, Cc<NativeCallback>>,78 /// TLA vars79 /// TLA vars79 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 context172 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}181182183#[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}189198190/// Maintains stack trace and import resolution199/// Maintains stack trace and import resolution191#[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 variables323 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 frame334 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.breakpoints359 // .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 frame372 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 = data396 data.breakpoints398 .breakpoints397 .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 result408 }409 }410 /// Executes code creating a new stack frame411 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 here421 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 result441 }409442410 /// 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 }452485453 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 }572608573 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 }576612603 }639 }604}640}641642pub 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}605647606#[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 state626 .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 );104210841043 evaluator.with_stdlib();1085 evaluator.with_stdlib();104410861045 #[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(crates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth1use jrsonnet_gc::{Gc, Trace};1use gcmodule::{Cc, Trace};2use jrsonnet_interner::IStr;2use jrsonnet_interner::IStr;3use rustc_hash::FxHashMap;435use crate::LazyVal;4use crate::{GcHashMap, LazyVal};657#[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}131214#[derive(Trace)]13#[derive(Trace)]15#[trivially_drop]16pub struct LayeredHashMap(Gc<LayeredHashMapInternals>);14pub struct LayeredHashMap(Cc<LayeredHashMapInternals>);171518impl 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 }))494750impl 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}crates/jrsonnet-evaluator/src/native.rsdiffbeforeafterboth1#![allow(clippy::type_complexity)]1#![allow(clippy::type_complexity)]223use 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;91010pub 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}131414#[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}crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth1use 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};101111#[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 => This25type 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}363637#[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 }107106117 }116 }118117119 /// Run callback for every field found in object118 /// Run callback for every field found in object120 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 }133132134 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 }212211213 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 }218217219 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 }271270272 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}276275277impl 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}282281289288290pub 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 self316 }312 }317313318 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 self321 }317 }330 }326 }331327332 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 self370 }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(crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth119 .trace()119 .trace()120 .0120 .0121 .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 first127 let location = evaluation_state.map_source_locations(&l.0, &[l.1, l.2]);128 let location = evaluation_state129 .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 None136 }131 })137 })132 })133 .collect::<Vec<_>>();138 .collect::<Vec<_>>();134 let align = file_names139 let align = file_names135 .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 = align150 )?;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 }220225221 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 }],crates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth1use std::{fmt::Display, rc::Rc};1use std::{fmt::Display, rc::Rc};223use 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;11722}18}231924#[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}454046#[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}686269#[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}9992100fn 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}132124133#[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}148139149#[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),crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth6 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};202221pub 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}242625#[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}333434#[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}808081#[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}898890#[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 jsonnet94 Normal(FuncDesc),92 Normal(FuncDesc),95 /// Standard library function93 /// Standard library function96 Intrinsic(IStr),94 Intrinsic(IStr),97 /// Library functions implemented in native95 /// Library functions implemented in native98 NativeExt(IStr, Gc<NativeCallback>),96 NativeExt(IStr, Cc<NativeCallback>),99}97}10098101impl 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}195193196#[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 }207205208 pub fn len(&self) -> usize {206 pub fn len(&self) -> usize {253 }251 }254 }252 }255253256 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 }314312315 Ok(Self::Eager(Gc::new(out)))313 Ok(Self::Eager(Cc::new(out)))316 }314 }317315318 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 }327325328 Ok(Self::Eager(Gc::new(out)))326 Ok(Self::Eager(Cc::new(out)))329 }327 }330328331 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}339337340impl 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}345343346impl 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}351349355}353}356354357#[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}368365369macro_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> {crates/jrsonnet-interner/Cargo.tomldiffbeforeafterboth9[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" }1313crates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth1use 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::{111112#[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 false17 }17}18}181919impl Deref for IStr {20impl Deref for IStr {crates/jrsonnet-parser/Cargo.tomldiffbeforeafterboth15jrsonnet-interner = { path = "../jrsonnet-interner", version = "0.4.2" }15jrsonnet-interner = { path = "../jrsonnet-interner", version = "0.4.2" }161617peg = "0.7.0"17peg = "0.7.0"18unescape = "0.1.0"191820serde = { 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" }222123[dev-dependencies]22[dev-dependencies]24jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }23jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }crates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth1use 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>);494650#[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>);172164173/// Defined function parameters165/// Defined function parameters174#[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>>);178179/// Safety:180/// AST is acyclic, and there should be no gc pointers181unsafe impl Trace for ParamsDesc {182 unsafe_empty_trace!();183}184impl Finalize for ParamsDesc {}185170186impl 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);222204223#[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);228209229#[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),290265354#[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 file372#[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 pointers378unsafe impl Trace for LocExpr {379 unsafe_empty_trace!();380}381impl Finalize for LocExpr {}382351383impl 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}396397/// Creates LocExpr from Expr and ExprLocation components398#[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 None407 },408 )409 };410}411363crates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth9pub use expr::*;9pub use expr::*;10pub use jrsonnet_interner::IStr;10pub use jrsonnet_interner::IStr;11pub use peg;11pub use peg;12mod unescape;121313pub struct ParserSettings {14pub struct ParserSettings {14 pub loc_data: bool,15 pub file_name: Rc<Path>,15 pub file_name: Rc<Path>,16}16}1717104 [' ' | '\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}106107 rule hex_char()108 = quiet! { ['0'..='9' | 'a'..='f' | 'A'..='F'] } / expected!("<hex char>")109110 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() -> String107 = 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>")112122113 pub rule field_name(s: &ParserSettings) -> expr::FieldName123 pub rule field_name(s: &ParserSettings) -> expr::FieldName114 = 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) -> Expr179 = n:$(id()) { expr::Expr::Var(n.into()) }189 = n:$(id()) { expr::Expr::Var(n.into()) }190 pub rule id_loc(s: &ParserSettings) -> LocExpr191 = 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) -> Expr181 = 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) -> LocExpr242 = 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}296297#[macro_export]298macro_rules! el {299 ($expr:expr) => {300 LocExpr(std::rc::Rc::new($expr), None)301 };302}303308304#[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 }323327324 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 }329330 mod expressions {331 use super::*;332333 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 }345336346 #[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 }365356376 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 }387378388 #[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 }395386396 #[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 }403394404 #[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 }415406416 #[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 }420414421 #[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 5432 ))427 )433 ))428 ),429 0,430 5431 )434 );432 );435 }433 }436434437 #[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 14447 ),448 ),449 0,450 14451 )452 );440 }453 }441454445 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 8476 ),477 ),478 3,479 8480 )),481 2,482 9483 ),450 ))484 ),485 0,486 9487 )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 41508 )467 ))509 ),510 0,511 41512 )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 14480 ))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 13557 ),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 16563 ),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 30571 ),508 )572 )509 }573 }510574511 #[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 }517581518 #[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 8600 )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 7617 )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 3633 )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::*;589665590 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 24631 ),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 29639 ),704 ),640 );705 );crates/jrsonnet-parser/src/unescape.rsdiffbeforeafterbothno changes
crates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth370 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), ''),372372373 manifestJson(value):: std.manifestJsonEx(value, ' '),373 manifestJson(value):: std.manifestJsonEx(value, ' ') tailstrict,374374375 manifestJsonEx:: $intrinsic(manifestJsonEx),375 manifestJsonEx:: $intrinsic(manifestJsonEx),376376crates/jrsonnet-types/Cargo.tomldiffbeforeafterboth889[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" }1212crates/jrsonnet-types/src/lib.rsdiffbeforeafterboth1#![allow(clippy::redundant_closure_call)]1#![allow(clippy::redundant_closure_call)]223use jrsonnet_gc::Trace;3use gcmodule::Trace;4use std::fmt::Display;4use std::fmt::Display;556#[macro_export]6#[macro_export]82}82}838384#[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}116115117#[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,