difftreelog
refactor switch gc to gcmodule
in: master
39 files changed
.github/workflows/release.ymldiffbeforeafterboth--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -21,7 +21,7 @@
args: --all
cargo-release:
- if: startsWith(github.ref, 'refs/tags/')
+ if: startsWith(github.ref, 'refs/tags/') && !endsWith(github.ref, '-test')
needs: [test]
runs-on: ubuntu-latest
steps:
Cargo.tomldiffbeforeafterboth--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,11 +1,6 @@
[workspace]
members = [
- "crates/jrsonnet-interner",
- "crates/jrsonnet-parser",
- "crates/jrsonnet-evaluator",
- "crates/jrsonnet-stdlib",
- "crates/jrsonnet-cli",
- "crates/jrsonnet-types",
+ "crates/*",
"bindings/jsonnet",
"cmds/jrsonnet",
]
bindings/jsonnet/Cargo.tomldiffbeforeafterboth--- a/bindings/jsonnet/Cargo.toml
+++ b/bindings/jsonnet/Cargo.toml
@@ -10,7 +10,7 @@
[dependencies]
jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "0.4.2" }
jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.4.2" }
-jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
+gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
[lib]
crate-type = ["cdylib"]
bindings/jsonnet/src/native.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/native.rs
+++ b/bindings/jsonnet/src/native.rs
@@ -1,9 +1,10 @@
+use gcmodule::Cc;
use jrsonnet_evaluator::{
error::{Error, LocError},
+ gc::TraceBox,
native::{NativeCallback, NativeCallbackHandler},
EvaluationState, Val,
};
-use jrsonnet_gc::{unsafe_empty_trace, Finalize, Gc, Trace};
use jrsonnet_parser::{Param, ParamsDesc};
use std::{
ffi::{c_void, CStr},
@@ -18,16 +19,15 @@
success: *mut c_int,
) -> *mut Val;
+#[derive(gcmodule::Trace)]
struct JsonnetNativeCallbackHandler {
+ #[skip_trace]
ctx: *const c_void,
+ #[skip_trace]
cb: JsonnetNativeCallback,
-}
-impl Finalize for JsonnetNativeCallbackHandler {}
-unsafe impl Trace for JsonnetNativeCallbackHandler {
- unsafe_empty_trace!();
}
impl NativeCallbackHandler for JsonnetNativeCallbackHandler {
- fn call(&self, _from: Option<Rc<Path>>, args: &[Val]) -> Result<Val, LocError> {
+ fn call(&self, _from: Rc<Path>, args: &[Val]) -> Result<Val, LocError> {
let mut n_args = Vec::new();
for a in args {
n_args.push(Some(Box::new(a.clone())));
@@ -74,9 +74,9 @@
vm.add_native(
name,
- Gc::new(NativeCallback::new(
+ Cc::new(NativeCallback::new(
params,
- Box::new(JsonnetNativeCallbackHandler { ctx, cb }),
+ TraceBox(Box::new(JsonnetNativeCallbackHandler { ctx, cb })),
)),
)
}
bindings/jsonnet/src/val_make.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/val_make.rs
+++ b/bindings/jsonnet/src/val_make.rs
@@ -1,7 +1,7 @@
//! Create values in VM
+use gcmodule::Cc;
use jrsonnet_evaluator::{ArrValue, EvaluationState, ObjValue, Val};
-use jrsonnet_gc::Gc;
use std::{
ffi::CStr,
os::raw::{c_char, c_double, c_int},
@@ -38,7 +38,7 @@
#[no_mangle]
pub extern "C" fn jsonnet_json_make_array(_vm: &EvaluationState) -> *mut Val {
- Box::into_raw(Box::new(Val::Arr(ArrValue::Eager(Gc::new(Vec::new())))))
+ Box::into_raw(Box::new(Val::Arr(ArrValue::Eager(Cc::new(Vec::new())))))
}
#[no_mangle]
bindings/jsonnet/src/val_modify.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/val_modify.rs
+++ b/bindings/jsonnet/src/val_modify.rs
@@ -2,8 +2,8 @@
//! Only tested with variables, which haven't altered by code before appearing here
//! In jrsonnet every value is immutable, and this code is probally broken
+use gcmodule::Cc;
use jrsonnet_evaluator::{ArrValue, EvaluationState, LazyBinding, LazyVal, ObjMember, Val};
-use jrsonnet_gc::Gc;
use jrsonnet_parser::Visibility;
use std::{ffi::CStr, os::raw::c_char};
@@ -23,7 +23,7 @@
new.push(item);
}
new.push(LazyVal::new_resolved(val.clone()));
- *arr = Val::Arr(ArrValue::Lazy(Gc::new(new)));
+ *arr = Val::Arr(ArrValue::Lazy(Cc::new(new)));
}
_ => panic!("should receive array"),
}
cmds/jrsonnet/Cargo.tomldiffbeforeafterboth--- a/cmds/jrsonnet/Cargo.toml
+++ b/cmds/jrsonnet/Cargo.toml
@@ -17,6 +17,7 @@
jrsonnet-cli = { path = "../../crates/jrsonnet-cli", version = "0.4.2" }
mimallocator = { version = "0.1.3", optional = true }
thiserror = "1.0"
+gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
[dependencies.clap]
git = "https://github.com/clap-rs/clap"
cmds/jrsonnet/src/main.rsdiffbeforeafterboth--- a/cmds/jrsonnet/src/main.rs
+++ b/cmds/jrsonnet/src/main.rs
@@ -136,7 +136,7 @@
let val = if opts.input.exec {
state.evaluate_snippet_raw(
- PathBuf::from("args").into(),
+ PathBuf::from("<cmdline>").into(),
(&opts.input.input as &str).into(),
)?
} else if opts.input.input == "-" {
crates/jrsonnet-cli/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-cli/Cargo.toml
+++ b/crates/jrsonnet-cli/Cargo.toml
@@ -12,11 +12,7 @@
"explaining-traces",
] }
jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.4.2" }
-jrsonnet-gc = { version = "0.4.2", features = [
- "derive",
- "unstable-config",
- "unstable-stats",
-] }
+gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
[dependencies.clap]
git = "https://github.com/clap-rs/clap"
crates/jrsonnet-cli/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-cli/src/lib.rs
+++ b/crates/jrsonnet-cli/src/lib.rs
@@ -103,12 +103,6 @@
#[derive(Clap)]
#[clap(help_heading = "GARBAGE COLLECTION")]
pub struct GcOpts {
- /// Min bytes allocated to start garbage collection
- #[clap(long, default_value = "20000000")]
- gc_initial_threshold: usize,
- /// How much heap should grow after unsuccessful garbage collection
- #[clap(long)]
- gc_used_space_ratio: Option<f64>,
/// Do not skip gc on exit
#[clap(long)]
gc_collect_on_exit: bool,
@@ -122,32 +116,28 @@
gc_collect_before_printing_stats: bool,
}
impl GcOpts {
+ pub fn configure_global(&self) {
+ if !self.gc_collect_on_exit {
+ gcmodule::set_thread_collect_on_drop(false)
+ }
+ }
pub fn stats_printer(&self) -> Option<GcStatsPrinter> {
- self.gc_print_stats
- .then(|| GcStatsPrinter(self.gc_collect_before_printing_stats))
+ self.gc_print_stats.then(|| GcStatsPrinter {
+ collect_before_printing_stats: self.gc_collect_before_printing_stats,
+ })
}
- pub fn configure_global(&self) {
- jrsonnet_gc::configure(|config| {
- config.leak_on_drop = !self.gc_collect_on_exit;
- config.threshold = self.gc_initial_threshold;
- if let Some(used_space_ratio) = self.gc_used_space_ratio {
- config.used_space_ratio = used_space_ratio;
- }
- });
- }
}
-pub struct GcStatsPrinter(bool);
+
+pub struct GcStatsPrinter {
+ collect_before_printing_stats: bool,
+}
impl Drop for GcStatsPrinter {
fn drop(&mut self) {
- if self.0 {
- jrsonnet_gc::force_collect()
+ eprintln!("=== GC STATS ===");
+ if self.collect_before_printing_stats {
+ let collected = gcmodule::collect_thread_cycles();
+ eprintln!("Collected: {}", collected);
}
- eprintln!("=== GC STATS ===");
- jrsonnet_gc::configure(|c| {
- eprintln!("Final threshold: {:?}", c.threshold);
- });
- let stats = jrsonnet_gc::stats();
- eprintln!("Collections performed: {}", stats.collections_performed);
- eprintln!("Bytes still allocated: {}", stats.bytes_allocated);
+ eprintln!("Tracked: {}", gcmodule::count_thread_tracked())
}
}
crates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-evaluator/Cargo.toml
+++ b/crates/jrsonnet-evaluator/Cargo.toml
@@ -32,7 +32,7 @@
rustc-hash = "1.1.0"
thiserror = "1.0"
-jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
+gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
[dependencies.anyhow]
version = "1.0"
@@ -53,7 +53,7 @@
# Explaining traces
[dependencies.annotate-snippets]
-version = "0.9.0"
+version = "0.9.1"
features = ["color"]
optional = true
crates/jrsonnet-evaluator/build.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/build.rs
+++ b/crates/jrsonnet-evaluator/build.rs
@@ -13,7 +13,6 @@
STDLIB_STR,
&ParserSettings {
file_name: PathBuf::from("std.jsonnet").into(),
- loc_data: true,
},
)
.expect("parse");
crates/jrsonnet-evaluator/src/builtin/format.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/format.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/format.rs
@@ -2,13 +2,12 @@
#![allow(clippy::too_many_arguments)]
use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val};
-use jrsonnet_gc::Trace;
+use gcmodule::Trace;
use jrsonnet_interner::IStr;
use jrsonnet_types::ValType;
use thiserror::Error;
#[derive(Debug, Clone, Error, Trace)]
-#[trivially_drop]
pub enum FormatError {
#[error("truncated format code")]
TruncatedFormatCode,
crates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/manifest.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/manifest.rs
@@ -1,6 +1,6 @@
use crate::error::Error::*;
use crate::error::Result;
-use crate::push_frame;
+use crate::push_description_frame;
use crate::{throw, Val};
#[derive(PartialEq, Clone, Copy)]
@@ -103,8 +103,7 @@
buf.push_str(cur_padding);
escape_string_json_buf(&field, buf);
buf.push_str(": ");
- push_frame(
- None,
+ push_description_frame(
|| format!("field <{}> manifestification", field.clone()),
|| {
let value = obj.get(field.clone())?.unwrap();
crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -7,7 +7,7 @@
EvaluationState, FuncVal, IndexableVal, LazyVal, Val,
};
use format::{format_arr, format_obj};
-use jrsonnet_gc::Gc;
+use gcmodule::Cc;
use jrsonnet_interner::IStr;
use jrsonnet_parser::{ArgsDesc, ExprLocation};
use jrsonnet_types::ty;
@@ -24,7 +24,7 @@
pub fn std_format(str: IStr, vals: Val) -> Result<Val> {
push_frame(
- Some(&ExprLocation(Rc::from(PathBuf::from("std.jsonnet")), 0, 0)),
+ &ExprLocation(Rc::from(PathBuf::from("std.jsonnet")), 0, 0),
|| format!("std.format of {}", str),
|| {
Ok(match vals {
@@ -68,7 +68,7 @@
}
}
-type Builtin = fn(context: Context, loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val>;
+type Builtin = fn(context: Context, loc: &ExprLocation, args: &ArgsDesc) -> Result<Val>;
type BuiltinsType = HashMap<Box<str>, Builtin>;
@@ -136,7 +136,7 @@
};
}
-fn builtin_length(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_length(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "length", args, 1, [
0, x: ty!((string | object | array));
], {
@@ -154,7 +154,7 @@
})
}
-fn builtin_type(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_type(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "type", args, 1, [
0, x: ty!(any);
], {
@@ -162,11 +162,7 @@
})
}
-fn builtin_make_array(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_make_array(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "makeArray", args, 2, [
0, sz: ty!(BoundedNumber<(Some(0.0)), (None)>) => Val::Num;
1, func: ty!(function) => Val::Func;
@@ -182,11 +178,7 @@
})
}
-fn builtin_codepoint(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_codepoint(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "codepoint", args, 1, [
0, str: ty!(char) => Val::Str;
], {
@@ -194,11 +186,7 @@
})
}
-fn builtin_object_fields_ex(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_object_fields_ex(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "objectFieldsEx", args, 2, [
0, obj: ty!(object) => Val::Obj;
1, inc_hidden: ty!(boolean) => Val::Bool;
@@ -208,11 +196,7 @@
})
}
-fn builtin_object_has_ex(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_object_has_ex(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "objectHasEx", args, 3, [
0, obj: ty!(object) => Val::Obj;
1, f: ty!(string) => Val::Str;
@@ -222,11 +206,7 @@
})
}
-fn builtin_parse_json(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_parse_json(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "parseJson", args, 1, [
0, s: ty!(string) => Val::Str;
], {
@@ -236,7 +216,7 @@
})
}
-fn builtin_slice(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_slice(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "slice", args, 4, [
0, indexable: ty!((string | array));
1, index: ty!((number | null));
@@ -252,7 +232,7 @@
})
}
-fn builtin_substr(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_substr(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "substr", args, 3, [
0, str: ty!(string) => Val::Str;
1, from: ty!(BoundedNumber<(Some(0.0)), (None)>) => Val::Num;
@@ -263,11 +243,7 @@
})
}
-fn builtin_primitive_equals(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_primitive_equals(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "primitiveEquals", args, 2, [
0, a: ty!(any);
1, b: ty!(any);
@@ -276,7 +252,7 @@
})
}
-fn builtin_equals(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_equals(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "equals", args, 2, [
0, a: ty!(any);
1, b: ty!(any);
@@ -285,7 +261,7 @@
})
}
-fn builtin_modulo(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_modulo(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "modulo", args, 2, [
0, a: ty!(number) => Val::Num;
1, b: ty!(number) => Val::Num;
@@ -294,7 +270,7 @@
})
}
-fn builtin_mod(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_mod(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "mod", args, 2, [
0, a: ty!((number | string));
1, b: ty!(any);
@@ -303,7 +279,7 @@
})
}
-fn builtin_floor(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_floor(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "floor", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -311,7 +287,7 @@
})
}
-fn builtin_ceil(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_ceil(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "ceil", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -319,7 +295,7 @@
})
}
-fn builtin_log(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_log(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "log", args, 1, [
0, n: ty!(number) => Val::Num;
], {
@@ -327,7 +303,7 @@
})
}
-fn builtin_pow(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_pow(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "pow", args, 2, [
0, x: ty!(number) => Val::Num;
1, n: ty!(number) => Val::Num;
@@ -336,7 +312,7 @@
})
}
-fn builtin_sqrt(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_sqrt(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "sqrt", args, 1, [
0, x: ty!(BoundedNumber<(Some(0.0)), (None)>) => Val::Num;
], {
@@ -344,7 +320,7 @@
})
}
-fn builtin_sin(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_sin(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "sin", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -352,7 +328,7 @@
})
}
-fn builtin_cos(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_cos(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "cos", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -360,7 +336,7 @@
})
}
-fn builtin_tan(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_tan(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "tan", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -368,7 +344,7 @@
})
}
-fn builtin_asin(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_asin(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "asin", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -376,7 +352,7 @@
})
}
-fn builtin_acos(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_acos(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "acos", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -384,7 +360,7 @@
})
}
-fn builtin_atan(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_atan(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "atan", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -392,7 +368,7 @@
})
}
-fn builtin_exp(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_exp(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "exp", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -411,7 +387,7 @@
}
}
-fn builtin_mantissa(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_mantissa(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "mantissa", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -419,7 +395,7 @@
})
}
-fn builtin_exponent(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_exponent(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "exponent", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -427,7 +403,7 @@
})
}
-fn builtin_ext_var(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_ext_var(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "extVar", args, 1, [
0, x: ty!(string) => Val::Str;
], {
@@ -435,15 +411,15 @@
})
}
-fn builtin_native(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_native(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "native", args, 1, [
0, x: ty!(string) => Val::Str;
], {
- 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))?)
+ 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))?)
})
}
-fn builtin_filter(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_filter(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "filter", args, 2, [
0, func: ty!(function) => Val::Func;
1, arr: ty!(array) => Val::Arr;
@@ -454,7 +430,7 @@
})
}
-fn builtin_map(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_map(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "map", args, 2, [
0, func: ty!(function) => Val::Func;
1, arr: ty!(array) => Val::Arr;
@@ -464,7 +440,7 @@
})
}
-fn builtin_flatmap(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_flatmap(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "flatMap", args, 2, [
0, func: ty!(function) => Val::Func;
1, arr: ty!((array | string));
@@ -498,7 +474,7 @@
})
}
-fn builtin_foldl(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_foldl(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "foldl", args, 3, [
0, func: ty!(function) => Val::Func;
1, arr: ty!(array) => Val::Arr;
@@ -512,7 +488,7 @@
})
}
-fn builtin_foldr(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_foldr(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "foldr", args, 3, [
0, func: ty!(function) => Val::Func;
1, arr: ty!(array) => Val::Arr;
@@ -527,11 +503,7 @@
}
#[allow(non_snake_case)]
-fn builtin_sort_impl(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_sort_impl(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "sort", args, 2, [
0, arr: ty!(array) => Val::Arr;
1, keyF: ty!(function) => Val::Func;
@@ -543,7 +515,7 @@
})
}
-fn builtin_format(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_format(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "format", args, 2, [
0, str: ty!(string) => Val::Str;
1, vals: ty!(any)
@@ -552,7 +524,7 @@
})
}
-fn builtin_range(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_range(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "range", args, 2, [
0, from: ty!(number) => Val::Num;
1, to: ty!(number) => Val::Num;
@@ -568,7 +540,7 @@
})
}
-fn builtin_char(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_char(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "char", args, 1, [
0, n: ty!(number) => Val::Num;
], {
@@ -580,11 +552,7 @@
})
}
-fn builtin_encode_utf8(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_encode_utf8(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "encodeUTF8", args, 1, [
0, str: ty!(string) => Val::Str;
], {
@@ -592,11 +560,7 @@
})
}
-fn builtin_decode_utf8(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_decode_utf8(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "decodeUTF8", args, 1, [
0, arr: ty!((Array<ubyte>)) => Val::Arr;
], {
@@ -609,7 +573,7 @@
})
}
-fn builtin_md5(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_md5(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "md5", args, 1, [
0, str: ty!(string) => Val::Str;
], {
@@ -617,24 +581,22 @@
})
}
-fn builtin_trace(context: Context, loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_trace(context: Context, loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "trace", args, 2, [
0, str: ty!(string) => Val::Str;
1, rest: ty!(any);
], {
eprint!("TRACE:");
- if let Some(loc) = loc {
with_state(|s|{
let locs = s.map_source_locations(&loc.0, &[loc.1]);
eprint!(" {}:{}", loc.0.file_name().unwrap().to_str().unwrap(), locs[0].line);
});
- }
eprintln!(" {}", str);
Ok(rest)
})
}
-fn builtin_base64(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_base64(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "base64", args, 1, [
0, input: ty!((string | (Array<number>)));
], {
@@ -654,7 +616,7 @@
fn builtin_base64_decode_bytes(
context: Context,
- _loc: Option<&ExprLocation>,
+ _loc: &ExprLocation,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "base64DecodeBytes", args, 1, [
@@ -669,11 +631,7 @@
})
}
-fn builtin_base64_decode(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_base64_decode(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "base64Decode", args, 1, [
0, input: ty!(string) => Val::Str;
], {
@@ -685,7 +643,7 @@
})
}
-fn builtin_join(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_join(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "join", args, 2, [
0, sep: ty!((string | array));
1, arr: ty!(array) => Val::Arr;
@@ -744,7 +702,7 @@
fn builtin_escape_string_json(
context: Context,
- _loc: Option<&ExprLocation>,
+ _loc: &ExprLocation,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "escapeStringJson", args, 1, [
@@ -754,11 +712,7 @@
})
}
-fn builtin_manifest_json_ex(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_manifest_json_ex(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "manifestJsonEx", args, 2, [
0, value: ty!(any);
1, indent: ty!(string) => Val::Str;
@@ -772,7 +726,7 @@
fn builtin_manifest_yaml_doc(
context: Context,
- _loc: Option<&ExprLocation>,
+ _loc: &ExprLocation,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "manifestYamlDoc", args, 2, [
@@ -786,7 +740,7 @@
})
}
-fn builtin_reverse(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_reverse(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "reverse", args, 1, [
0, value: ty!(array) => Val::Arr;
], {
@@ -794,7 +748,7 @@
})
}
-fn builtin_id(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_id(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "id", args, 1, [
0, v: ty!(any);
], {
@@ -802,11 +756,7 @@
})
}
-fn builtin_str_replace(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_str_replace(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "strReplace", args, 3, [
0, str: ty!(string) => Val::Str;
1, from: ty!(string) => Val::Str;
@@ -816,11 +766,7 @@
})
}
-fn builtin_splitlimit(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_splitlimit(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "splitLimit", args, 3, [
0, str: ty!(string) => Val::Str;
1, c: ty!(char) => Val::Str;
@@ -839,11 +785,7 @@
})
}
-fn builtin_ascii_upper(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_ascii_upper(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "asciiUpper", args, 1, [
0, str: ty!(string) => Val::Str;
], {
@@ -851,11 +793,7 @@
})
}
-fn builtin_ascii_lower(
- context: Context,
- _loc: Option<&ExprLocation>,
- args: &ArgsDesc,
-) -> Result<Val> {
+fn builtin_ascii_lower(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "asciiLower", args, 1, [
0, str: ty!(string) => Val::Str;
], {
@@ -863,7 +801,7 @@
})
}
-fn builtin_member(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_member(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "member", args, 2, [
0, arr: ty!((array | string));
1, x: ty!(any);
@@ -887,7 +825,7 @@
})
}
-fn builtin_count(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_count(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "count", args, 2, [
0, arr: ty!(array) => Val::Arr;
1, x: ty!(any);
@@ -905,7 +843,7 @@
pub fn call_builtin(
context: Context,
- loc: Option<&ExprLocation>,
+ loc: &ExprLocation,
name: &str,
args: &ArgsDesc,
) -> Result<Val> {
crates/jrsonnet-evaluator/src/builtin/sort.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/sort.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/sort.rs
@@ -2,9 +2,9 @@
error::{Error, LocError, Result},
throw, Context, FuncVal, Val,
};
-use jrsonnet_gc::{Finalize, Gc, Trace};
+use gcmodule::{Cc, Trace};
-#[derive(Debug, Clone, thiserror::Error, Trace, Finalize)]
+#[derive(Debug, Clone, thiserror::Error, Trace)]
pub enum SortError {
#[error("sort key should be string or number")]
SortKeyShouldBeStringOrNumber,
@@ -59,7 +59,7 @@
Ok(sort_type)
}
-pub fn sort(ctx: Context, values: Gc<Vec<Val>>, key_getter: &FuncVal) -> Result<Gc<Vec<Val>>> {
+pub fn sort(ctx: Context, values: Cc<Vec<Val>>, key_getter: &FuncVal) -> Result<Cc<Vec<Val>>> {
if values.len() <= 1 {
return Ok(values);
}
@@ -77,7 +77,7 @@
}),
SortKeyType::Unknown => unreachable!(),
};
- Ok(Gc::new(mvalues))
+ Ok(Cc::new(mvalues))
} else {
let mut vk = Vec::with_capacity(values.len());
for value in values.iter() {
@@ -98,6 +98,6 @@
}),
SortKeyType::Unknown => unreachable!(),
};
- Ok(Gc::new(vk.into_iter().map(|v| v.0).collect()))
+ Ok(Cc::new(vk.into_iter().map(|v| v.0).collect()))
}
}
crates/jrsonnet-evaluator/src/builtin/stdlib.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/stdlib.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/stdlib.rs
@@ -15,7 +15,6 @@
jrsonnet_parser::parse(
jrsonnet_stdlib::STDLIB_STR,
&ParserSettings {
- loc_data: true,
file_name: PathBuf::from("std.jsonnet").into(),
},
)
crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/ctx.rs
+++ b/crates/jrsonnet-evaluator/src/ctx.rs
@@ -1,16 +1,15 @@
+use crate::cc_ptr_eq;
+use crate::gc::GcHashMap;
use crate::{
error::Error::*, map::LayeredHashMap, FutureWrapper, LazyBinding, LazyVal, ObjValue, Result,
Val,
};
-use jrsonnet_gc::{Gc, Trace};
+use gcmodule::{Cc, Trace};
use jrsonnet_interner::IStr;
-use rustc_hash::FxHashMap;
use std::fmt::Debug;
-use std::hash::BuildHasherDefault;
#[derive(Clone, Trace)]
-#[trivially_drop]
-pub struct ContextCreator(pub Context, pub FutureWrapper<FxHashMap<IStr, LazyBinding>>);
+pub struct ContextCreator(pub Context, pub FutureWrapper<GcHashMap<IStr, LazyBinding>>);
impl ContextCreator {
pub fn create(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<Context> {
self.0.clone().extend_unbound(
@@ -23,7 +22,6 @@
}
#[derive(Trace)]
-#[trivially_drop]
struct ContextInternals {
dollar: Option<ObjValue>,
this: Option<ObjValue>,
@@ -37,8 +35,7 @@
}
#[derive(Debug, Clone, Trace)]
-#[trivially_drop]
-pub struct Context(Gc<ContextInternals>);
+pub struct Context(Cc<ContextInternals>);
impl Context {
pub fn new_future() -> FutureWrapper<Self> {
FutureWrapper::new()
@@ -57,7 +54,7 @@
}
pub fn new() -> Self {
- Self(Gc::new(ContextInternals {
+ Self(Cc::new(ContextInternals {
dollar: None,
this: None,
super_obj: None,
@@ -84,19 +81,18 @@
}
pub fn with_var(self, name: IStr, value: Val) -> Self {
- let mut new_bindings =
- FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());
+ let mut new_bindings = GcHashMap::with_capacity(1);
new_bindings.insert(name, LazyVal::new_resolved(value));
self.extend(new_bindings, None, None, None)
}
pub fn with_this_super(self, new_this: ObjValue, new_super_obj: Option<ObjValue>) -> Self {
- self.extend(FxHashMap::default(), None, Some(new_this), new_super_obj)
+ self.extend(GcHashMap::new(), None, Some(new_this), new_super_obj)
}
pub fn extend(
self,
- new_bindings: FxHashMap<IStr, LazyVal>,
+ new_bindings: GcHashMap<IStr, LazyVal>,
new_dollar: Option<ObjValue>,
new_this: Option<ObjValue>,
new_super_obj: Option<ObjValue>,
@@ -110,30 +106,29 @@
} else {
ctx.bindings.clone().extend(new_bindings)
};
- Self(Gc::new(ContextInternals {
+ Self(Cc::new(ContextInternals {
dollar,
this,
super_obj,
bindings,
}))
}
- pub fn extend_bound(self, new_bindings: FxHashMap<IStr, LazyVal>) -> Self {
+ pub fn extend_bound(self, new_bindings: GcHashMap<IStr, LazyVal>) -> Self {
let new_this = self.0.this.clone();
let new_super_obj = self.0.super_obj.clone();
self.extend(new_bindings, None, new_this, new_super_obj)
}
pub fn extend_unbound(
self,
- new_bindings: FxHashMap<IStr, LazyBinding>,
+ new_bindings: GcHashMap<IStr, LazyBinding>,
new_dollar: Option<ObjValue>,
new_this: Option<ObjValue>,
new_super_obj: Option<ObjValue>,
) -> Result<Self> {
let this = new_this.or_else(|| self.0.this.clone());
let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());
- let mut new =
- FxHashMap::with_capacity_and_hasher(new_bindings.len(), BuildHasherDefault::default());
- for (k, v) in new_bindings.into_iter() {
+ let mut new = GcHashMap::with_capacity(new_bindings.len());
+ for (k, v) in new_bindings.0.into_iter() {
new.insert(k, v.evaluate(this.clone(), super_obj.clone())?);
}
Ok(self.extend(new, new_dollar, this, super_obj))
@@ -152,6 +147,6 @@
impl PartialEq for Context {
fn eq(&self, other: &Self) -> bool {
- Gc::ptr_eq(&self.0, &other.0)
+ cc_ptr_eq(&self.0, &other.0)
}
}
crates/jrsonnet-evaluator/src/dynamic.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/dynamic.rs
+++ b/crates/jrsonnet-evaluator/src/dynamic.rs
@@ -1,11 +1,12 @@
-use jrsonnet_gc::{Gc, GcCell, Trace};
+use std::cell::RefCell;
+use gcmodule::{Cc, Trace};
+
#[derive(Clone, Trace)]
-#[trivially_drop]
-pub struct FutureWrapper<V: Trace + 'static>(pub Gc<GcCell<Option<V>>>);
+pub struct FutureWrapper<V: Trace + 'static>(pub Cc<RefCell<Option<V>>>);
impl<T: Trace + 'static> FutureWrapper<T> {
pub fn new() -> Self {
- Self(Gc::new(GcCell::new(None)))
+ Self(Cc::new(RefCell::new(None)))
}
pub fn fill(self, value: T) {
assert!(self.0.borrow().is_none(), "wrapper is filled already");
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -1,5 +1,8 @@
-use crate::{Val, builtin::{format::FormatError, sort::SortError}, typed::TypeLocError};
-use jrsonnet_gc::Trace;
+use crate::{
+ builtin::{format::FormatError, sort::SortError},
+ typed::TypeLocError,
+};
+use gcmodule::Trace;
use jrsonnet_interner::IStr;
use jrsonnet_parser::{BinaryOpType, ExprLocation, UnaryOpType};
use jrsonnet_types::ValType;
@@ -10,7 +13,6 @@
use thiserror::Error;
#[derive(Error, Debug, Clone, Trace)]
-#[trivially_drop]
pub enum Error {
#[error("intrinsic not found: {0}")]
IntrinsicNotFound(IStr),
@@ -85,14 +87,15 @@
#[error("tried to import {1} from {0}, but imports is not supported")]
ImportNotSupported(PathBuf, PathBuf),
#[error(
- "syntax error, expected one of {}, got {:?}",
+ "syntax error: expected {}, got {:?}",
.error.expected,
.source_code.chars().nth(error.location.offset).map(|c| c.to_string()).unwrap_or_else(|| "EOF".into())
)]
ImportSyntaxError {
+ #[skip_trace]
path: Rc<Path>,
source_code: IStr,
- #[unsafe_ignore_trace]
+ #[skip_trace]
error: Box<jrsonnet_parser::ParseError>,
},
@@ -150,17 +153,14 @@
}
#[derive(Clone, Debug, Trace)]
-#[trivially_drop]
pub struct StackTraceElement {
pub location: Option<ExprLocation>,
pub desc: String,
}
#[derive(Debug, Clone, Trace)]
-#[trivially_drop]
pub struct StackTrace(pub Vec<StackTraceElement>);
#[derive(Debug, Clone, Trace)]
-#[trivially_drop]
pub struct LocError(Box<(Error, StackTrace)>);
impl LocError {
pub fn new(e: Error) -> Self {
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -2,19 +2,18 @@
builtin::std_slice,
error::Error::*,
evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},
+ gc::TraceBox,
push_frame, throw, with_state, ArrValue, Bindable, Context, ContextCreator, FuncDesc, FuncVal,
- FutureWrapper, LazyBinding, LazyVal, LazyValValue, ObjValue, ObjValueBuilder, ObjectAssertion,
- Result, Val,
+ FutureWrapper, GcHashMap, LazyBinding, LazyVal, LazyValValue, ObjValue,
+ ObjValueBuilder, ObjectAssertion, Result, Val,
};
-use jrsonnet_gc::{Gc, Trace};
+use gcmodule::{Cc, Trace};
use jrsonnet_interner::IStr;
use jrsonnet_parser::{
ArgsDesc, AssertStmt, BindSpec, CompSpec, Expr, ExprLocation, FieldMember, ForSpecData,
IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc,
};
use jrsonnet_types::ValType;
-use rustc_hash::{FxHashMap, FxHasher};
-use std::{collections::HashMap, hash::BuildHasherDefault};
pub mod operator;
pub fn evaluate_binding_in_future(
@@ -26,7 +25,6 @@
let params = params.clone();
#[derive(Trace)]
- #[trivially_drop]
struct LazyMethodBinding {
context_creator: FutureWrapper<Context>,
name: IStr,
@@ -44,15 +42,14 @@
}
}
- LazyVal::new(Box::new(LazyMethodBinding {
+ LazyVal::new(TraceBox(Box::new(LazyMethodBinding {
context_creator,
name: b.name.clone(),
params,
value: b.value.clone(),
- }))
+ })))
} else {
#[derive(Trace)]
- #[trivially_drop]
struct LazyNamedBinding {
context_creator: FutureWrapper<Context>,
name: IStr,
@@ -63,11 +60,11 @@
evaluate_named(self.context_creator.unwrap(), &self.value, self.name)
}
}
- LazyVal::new(Box::new(LazyNamedBinding {
+ LazyVal::new(TraceBox(Box::new(LazyNamedBinding {
context_creator,
name: b.name.clone(),
value: b.value,
- }))
+ })))
}
}
@@ -77,7 +74,6 @@
let params = params.clone();
#[derive(Trace)]
- #[trivially_drop]
struct BindableMethodLazyVal {
this: Option<ObjValue>,
super_obj: Option<ObjValue>,
@@ -99,7 +95,6 @@
}
#[derive(Trace)]
- #[trivially_drop]
struct BindableMethod {
context_creator: ContextCreator,
name: IStr,
@@ -108,30 +103,31 @@
}
impl Bindable for BindableMethod {
fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {
- Ok(LazyVal::new(Box::new(BindableMethodLazyVal {
- this,
- super_obj,
+ Ok(LazyVal::new(TraceBox(Box::new(
+ BindableMethodLazyVal {
+ this,
+ super_obj,
- context_creator: self.context_creator.clone(),
- name: self.name.clone(),
- params: self.params.clone(),
- value: self.value.clone(),
- })))
+ context_creator: self.context_creator.clone(),
+ name: self.name.clone(),
+ params: self.params.clone(),
+ value: self.value.clone(),
+ },
+ ))))
}
}
(
b.name.clone(),
- LazyBinding::Bindable(Gc::new(Box::new(BindableMethod {
+ LazyBinding::Bindable(Cc::new(TraceBox(Box::new(BindableMethod {
context_creator,
name: b.name.clone(),
params,
value: b.value.clone(),
- }))),
+ })))),
)
} else {
#[derive(Trace)]
- #[trivially_drop]
struct BindableNamedLazyVal {
this: Option<ObjValue>,
super_obj: Option<ObjValue>,
@@ -151,7 +147,6 @@
}
#[derive(Trace)]
- #[trivially_drop]
struct BindableNamed {
context_creator: ContextCreator,
name: IStr,
@@ -159,30 +154,32 @@
}
impl Bindable for BindableNamed {
fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {
- Ok(LazyVal::new(Box::new(BindableNamedLazyVal {
- this,
- super_obj,
+ Ok(LazyVal::new(TraceBox(Box::new(
+ BindableNamedLazyVal {
+ this,
+ super_obj,
- context_creator: self.context_creator.clone(),
- name: self.name.clone(),
- value: self.value.clone(),
- })))
+ context_creator: self.context_creator.clone(),
+ name: self.name.clone(),
+ value: self.value.clone(),
+ },
+ ))))
}
}
(
b.name.clone(),
- LazyBinding::Bindable(Gc::new(Box::new(BindableNamed {
+ LazyBinding::Bindable(Cc::new(TraceBox(Box::new(BindableNamed {
context_creator,
name: b.name.clone(),
value: b.value.clone(),
- }))),
+ })))),
)
}
}
pub fn evaluate_method(ctx: Context, name: IStr, params: ParamsDesc, body: LocExpr) -> Val {
- Val::Func(Gc::new(FuncVal::Normal(FuncDesc {
+ Val::Func(Cc::new(FuncVal::Normal(FuncDesc {
name,
ctx,
params,
@@ -240,8 +237,7 @@
let future_this = FutureWrapper::new();
let context_creator = ContextCreator(context.clone(), new_bindings.clone());
{
- let mut bindings: FxHashMap<IStr, LazyBinding> =
- FxHashMap::with_capacity_and_hasher(members.len(), BuildHasherDefault::default());
+ let mut bindings: GcHashMap<IStr, LazyBinding> = GcHashMap::with_capacity(members.len());
for (n, b) in members
.iter()
.filter_map(|m| match m {
@@ -272,7 +268,6 @@
let name = name.unwrap();
#[derive(Trace)]
- #[trivially_drop]
struct ObjMemberBinding {
context_creator: ContextCreator,
value: LocExpr,
@@ -296,11 +291,11 @@
.with_add(*plus)
.with_visibility(*visibility)
.with_location(value.1.clone())
- .bindable(Box::new(ObjMemberBinding {
+ .bindable(TraceBox(Box::new(ObjMemberBinding {
context_creator: context_creator.clone(),
value: value.clone(),
name,
- }));
+ })));
}
Member::Field(FieldMember {
name,
@@ -314,7 +309,6 @@
}
let name = name.unwrap();
#[derive(Trace)]
- #[trivially_drop]
struct ObjMemberBinding {
context_creator: ContextCreator,
value: LocExpr,
@@ -339,17 +333,16 @@
.member(name.clone())
.hide()
.with_location(value.1.clone())
- .bindable(Box::new(ObjMemberBinding {
+ .bindable(TraceBox(Box::new(ObjMemberBinding {
context_creator: context_creator.clone(),
value: value.clone(),
params: params.clone(),
name,
- }));
+ })));
}
Member::BindStmt(_) => {}
Member::AssertStmt(stmt) => {
#[derive(Trace)]
- #[trivially_drop]
struct ObjectAssert {
context_creator: ContextCreator,
assert: AssertStmt,
@@ -364,10 +357,10 @@
evaluate_assert(ctx, &self.assert)
}
}
- builder.assert(Box::new(ObjectAssert {
+ builder.assert(TraceBox(Box::new(ObjectAssert {
context_creator: context_creator.clone(),
assert: stmt.clone(),
- }));
+ })));
}
}
}
@@ -385,11 +378,8 @@
evaluate_comp(context.clone(), &obj.compspecs, &mut |ctx| {
let new_bindings = FutureWrapper::new();
let context_creator = ContextCreator(context.clone(), new_bindings.clone());
- let mut bindings: FxHashMap<IStr, LazyBinding> =
- FxHashMap::with_capacity_and_hasher(
- obj.pre_locals.len() + obj.post_locals.len(),
- BuildHasherDefault::default(),
- );
+ let mut bindings: GcHashMap<IStr, LazyBinding> =
+ GcHashMap::with_capacity(obj.pre_locals.len() + obj.post_locals.len());
for (n, b) in obj
.pre_locals
.iter()
@@ -406,7 +396,6 @@
Val::Null => {}
Val::Str(n) => {
#[derive(Trace)]
- #[trivially_drop]
struct ObjCompBinding {
context: Context,
value: LocExpr,
@@ -418,12 +407,9 @@
_super_obj: Option<ObjValue>,
) -> Result<LazyVal> {
Ok(LazyVal::new_resolved(evaluate(
- self.context.clone().extend(
- FxHashMap::default(),
- None,
- this,
- None,
- ),
+ self.context
+ .clone()
+ .extend(GcHashMap::new(), None, this, None),
&self.value,
)?))
}
@@ -432,10 +418,10 @@
.member(n)
.with_location(obj.value.1.clone())
.with_add(obj.plus)
- .bindable(Box::new(ObjCompBinding {
+ .bindable(TraceBox(Box::new(ObjCompBinding {
context: ctx,
value: obj.value.clone(),
- }));
+ })));
}
v => throw!(FieldMustBeStringGot(v.value_type())),
}
@@ -454,7 +440,7 @@
context: Context,
value: &LocExpr,
args: &ArgsDesc,
- loc: Option<&ExprLocation>,
+ loc: &ExprLocation,
tailstrict: bool,
) -> Result<Val> {
let value = evaluate(context.clone(), value)?;
@@ -475,7 +461,7 @@
let value = &assertion.0;
let msg = &assertion.1;
let assertion_result = push_frame(
- value.1.as_ref(),
+ &value.1,
|| "assertion condition".to_owned(),
|| {
evaluate(context.clone(), value)?
@@ -484,7 +470,7 @@
)?;
if !assertion_result {
push_frame(
- value.1.as_ref(),
+ &value.1,
|| "assertion failure".to_owned(),
|| {
if let Some(msg) = msg {
@@ -534,8 +520,8 @@
BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, v1, *o, v2)?,
UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,
Var(name) => push_frame(
- loc.as_ref(),
- || format!("variable <{}>", name),
+ loc,
+ || format!("variable <{}> access", name),
|| context.binding(name.clone())?.evaluate(),
)?,
Index(value, index) => {
@@ -543,7 +529,7 @@
(Val::Obj(v), Val::Str(s)) => {
let sn = s.clone();
push_frame(
- loc.as_ref(),
+ loc,
|| format!("field <{}> access", sn),
|| {
if let Some(v) = v.get(s.clone())? {
@@ -591,10 +577,8 @@
}
}
LocalExpr(bindings, returned) => {
- let mut new_bindings: FxHashMap<IStr, LazyVal> = HashMap::with_capacity_and_hasher(
- bindings.len(),
- BuildHasherDefault::<FxHasher>::default(),
- );
+ let mut new_bindings: GcHashMap<IStr, LazyVal> =
+ GcHashMap::with_capacity(bindings.len());
let future_context = Context::new_future();
for b in bindings {
new_bindings.insert(
@@ -612,7 +596,6 @@
for item in items {
// TODO: Implement ArrValue::Lazy with same context for every element?
#[derive(Trace)]
- #[trivially_drop]
struct ArrayElement {
context: Context,
item: LocExpr,
@@ -622,10 +605,10 @@
evaluate(self.context, &self.item)
}
}
- out.push(LazyVal::new(Box::new(ArrayElement {
+ out.push(LazyVal::new(TraceBox(Box::new(ArrayElement {
context: context.clone(),
item: item.clone(),
- })));
+ }))));
}
Val::Arr(out.into())
}
@@ -635,26 +618,24 @@
out.push(evaluate(ctx, expr)?);
Ok(())
})?;
- Val::Arr(ArrValue::Eager(Gc::new(out)))
+ Val::Arr(ArrValue::Eager(Cc::new(out)))
}
Obj(body) => Val::Obj(evaluate_object(context, body)?),
ObjExtend(s, t) => evaluate_add_op(
&evaluate(context.clone(), s)?,
&Val::Obj(evaluate_object(context, t)?),
)?,
- Apply(value, args, tailstrict) => {
- evaluate_apply(context, value, args, loc.as_ref(), *tailstrict)?
- }
+ Apply(value, args, tailstrict) => evaluate_apply(context, value, args, loc, *tailstrict)?,
Function(params, body) => {
evaluate_method(context, "anonymous".into(), params.clone(), body.clone())
}
- Intrinsic(name) => Val::Func(Gc::new(FuncVal::Intrinsic(name.clone()))),
+ Intrinsic(name) => Val::Func(Cc::new(FuncVal::Intrinsic(name.clone()))),
AssertExpr(assert, returned) => {
evaluate_assert(context.clone(), assert)?;
evaluate(context, returned)?
}
ErrorStmt(e) => push_frame(
- loc.as_ref(),
+ loc,
|| "error statement".to_owned(),
|| {
throw!(RuntimeError(
@@ -668,7 +649,7 @@
cond_else,
} => {
if push_frame(
- loc.as_ref(),
+ loc,
|| "if condition".to_owned(),
|| evaluate(context.clone(), &cond.0)?.try_cast_bool("in if condition"),
)? {
@@ -703,23 +684,17 @@
std_slice(indexable.into_indexable()?, start, end, step)?
}
Import(path) => {
- let tmp = loc
- .clone()
- .expect("imports cannot be used without loc_data")
- .0;
+ let tmp = loc.clone().0;
let mut import_location = tmp.to_path_buf();
import_location.pop();
push_frame(
- loc.as_ref(),
+ loc,
|| format!("import {:?}", path),
|| with_state(|s| s.import_file(&import_location, path)),
)?
}
ImportStr(path) => {
- let tmp = loc
- .clone()
- .expect("imports cannot be used without loc_data")
- .0;
+ let tmp = loc.clone().0;
let mut import_location = tmp.to_path_buf();
import_location.pop();
Val::Str(with_state(|s| s.import_file_str(&import_location, path))?)
crates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function.rs
+++ b/crates/jrsonnet-evaluator/src/function.rs
@@ -1,18 +1,13 @@
-use crate::{
- error::Error::*, evaluate, evaluate_named, throw, Context, FutureWrapper, LazyVal,
- LazyValValue, Result, Val,
-};
-use jrsonnet_gc::Trace;
+use crate::{Context, FutureWrapper, GcHashMap, LazyVal, LazyValValue, Result, Val, error::Error::*, evaluate, evaluate_named, gc::TraceBox, throw};
+use gcmodule::Trace;
use jrsonnet_interner::IStr;
use jrsonnet_parser::{ArgsDesc, LocExpr, ParamsDesc};
-use rustc_hash::FxHashMap;
-use std::{collections::HashMap, hash::BuildHasherDefault};
+use std::collections::HashMap;
const NO_DEFAULT_CONTEXT: &str =
"no default context set for call with defined default parameter value";
#[derive(Trace)]
-#[trivially_drop]
struct EvaluateLazyVal {
context: Context,
expr: LocExpr,
@@ -38,8 +33,7 @@
args: &ArgsDesc,
tailstrict: bool,
) -> Result<Context> {
- let mut passed_args =
- HashMap::with_capacity_and_hasher(params.len(), BuildHasherDefault::default());
+ let mut passed_args = GcHashMap::with_capacity(params.len());
if args.unnamed.len() > params.len() {
throw!(TooManyArgsFunctionHas(params.len()))
}
@@ -53,10 +47,10 @@
if tailstrict {
LazyVal::new_resolved(evaluate(ctx.clone(), arg)?)
} else {
- LazyVal::new(Box::new(EvaluateLazyVal {
+ LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {
context: ctx.clone(),
expr: arg.clone(),
- }))
+ })))
},
);
filled_args += 1;
@@ -73,10 +67,10 @@
if tailstrict {
LazyVal::new_resolved(evaluate(ctx.clone(), value)?)
} else {
- LazyVal::new(Box::new(EvaluateLazyVal {
+ LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {
context: ctx.clone(),
expr: value.clone(),
- }))
+ })))
},
)
.is_some()
@@ -90,17 +84,13 @@
// Some args are unset, but maybe we have defaults for them
// Default values should be created in newly created context
let future_context = FutureWrapper::<Context>::new();
- let mut defaults = HashMap::with_capacity_and_hasher(
- params.len() - filled_args,
- BuildHasherDefault::default(),
- );
+ let mut defaults = GcHashMap::with_capacity(params.len() - filled_args);
for param in params.iter().filter(|p| p.1.is_some()) {
if passed_args.contains_key(¶m.0.clone()) {
continue;
}
#[derive(Trace)]
- #[trivially_drop]
struct LazyNamedBinding {
future_context: FutureWrapper<Context>,
name: IStr,
@@ -111,19 +101,19 @@
evaluate_named(self.future_context.unwrap(), &self.value, self.name)
}
}
- LazyVal::new(Box::new(LazyNamedBinding {
+ LazyVal::new(TraceBox(Box::new(LazyNamedBinding {
future_context: future_context.clone(),
name: param.0.clone(),
value: param.1.clone().unwrap(),
- }));
+ })));
defaults.insert(
param.0.clone(),
- LazyVal::new(Box::new(LazyNamedBinding {
+ LazyVal::new(TraceBox(Box::new(LazyNamedBinding {
future_context: future_context.clone(),
name: param.0.clone(),
value: param.1.clone().unwrap(),
- })),
+ }))),
);
filled_args += 1;
}
@@ -155,7 +145,7 @@
args: &HashMap<IStr, Val>,
tailstrict: bool,
) -> Result<Context> {
- let mut out = FxHashMap::with_capacity_and_hasher(params.len(), BuildHasherDefault::default());
+ let mut out = GcHashMap::with_capacity(params.len());
let mut positioned_args = vec![None; params.0.len()];
for (name, val) in args.iter() {
let idx = params
@@ -185,7 +175,6 @@
let body_ctx = body_ctx.clone();
let default = default.clone();
#[derive(Trace)]
- #[trivially_drop]
struct EvaluateLazyVal {
body_ctx: Option<Context>,
default: LocExpr,
@@ -198,7 +187,10 @@
)
}
}
- LazyVal::new(Box::new(EvaluateLazyVal { body_ctx, default }))
+ LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {
+ body_ctx,
+ default,
+ })))
}
} else {
throw!(FunctionParameterNotBoundInCall(p.0.clone()));
@@ -215,7 +207,7 @@
params: &ParamsDesc,
args: &[Val],
) -> Result<Context> {
- let mut out = FxHashMap::with_capacity_and_hasher(params.len(), BuildHasherDefault::default());
+ let mut out = GcHashMap::with_capacity(params.len());
let mut positioned_args = vec![None; params.0.len()];
for (id, arg) in args.iter().enumerate() {
if id >= params.len() {
@@ -243,7 +235,7 @@
($ctx: expr, $fn_name: expr, $args: expr, $total_args: expr, [
$($id: expr, $name: ident: $ty: expr $(=>$match: path)?);+ $(;)?
], $handler:block) => {{
- use $crate::{error::Error::*, throw, evaluate, push_frame, typed::CheckType};
+ use $crate::{error::Error::*, throw, evaluate, push_description_frame, typed::CheckType};
let args = $args;
if args.unnamed.len() + args.named.len() > $total_args {
@@ -263,7 +255,7 @@
} else {
&$args.unnamed[$id]
};
- let $name = push_frame(None, || format!("evaluating argument"), || {
+ let $name = push_description_frame(|| format!("evaluating builtin argument {}", stringify!($name)), || {
let value = evaluate($ctx.clone(), &$name)?;
$ty.check(&value)?;
Ok(value)
crates/jrsonnet-evaluator/src/gc.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-evaluator/src/gc.rs
@@ -0,0 +1,141 @@
+/// Macros to help deal with Gc
+use std::{
+ borrow::{Borrow, BorrowMut},
+ hash::BuildHasherDefault,
+ ops::{Deref, DerefMut},
+};
+
+use gcmodule::{Trace, Tracer};
+use rustc_hash::{FxHashMap, FxHashSet};
+
+/// Replacement for box, which assumes that the underlying type is [`Trace`]
+#[derive(Debug, Clone)]
+pub struct TraceBox<T: ?Sized>(pub Box<T>);
+
+impl<T: ?Sized + Trace> Trace for TraceBox<T> {
+ fn trace(&self, tracer: &mut Tracer) {
+ self.0.trace(tracer)
+ }
+
+ fn is_type_tracked() -> bool {
+ return true;
+ }
+}
+
+// TODO: Replace with CoerceUnsized
+impl<T: ?Sized> From<Box<T>> for TraceBox<T> {
+ fn from(inner: Box<T>) -> Self {
+ Self(inner)
+ }
+}
+
+impl<T: ?Sized> Deref for TraceBox<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl<T: Trace + ?Sized> DerefMut for TraceBox<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+impl<T: ?Sized> Borrow<T> for TraceBox<T> {
+ fn borrow(&self) -> &T {
+ &*self.0
+ }
+}
+
+impl<T: ?Sized> BorrowMut<T> for TraceBox<T> {
+ fn borrow_mut(&mut self) -> &mut T {
+ &mut *self.0
+ }
+}
+
+impl<T: ?Sized> AsRef<T> for TraceBox<T> {
+ fn as_ref(&self) -> &T {
+ &*self.0
+ }
+}
+
+impl<T: ?Sized> AsMut<T> for TraceBox<T> {
+ fn as_mut(&mut self) -> &mut T {
+ &mut *self.0
+ }
+}
+
+#[derive(Clone)]
+pub struct GcHashSet<V>(pub FxHashSet<V>);
+impl<V> GcHashSet<V> {
+ pub fn new() -> Self {
+ Self(Default::default())
+ }
+ pub fn with_capacity(capacity: usize) -> Self {
+ Self(FxHashSet::with_capacity_and_hasher(
+ capacity,
+ BuildHasherDefault::default(),
+ ))
+ }
+}
+impl<V> Trace for GcHashSet<V>
+where
+ V: Trace,
+{
+ fn trace(&self, tracer: &mut gcmodule::Tracer) {
+ for v in &self.0 {
+ v.trace(tracer);
+ }
+ }
+}
+impl<V> Deref for GcHashSet<V> {
+ type Target = FxHashSet<V>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl<V> DerefMut for GcHashSet<V> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+#[derive(Clone)]
+pub struct GcHashMap<K, V>(pub FxHashMap<K, V>);
+impl<K, V> GcHashMap<K, V> {
+ pub fn new() -> Self {
+ Self(Default::default())
+ }
+ pub fn with_capacity(capacity: usize) -> Self {
+ Self(FxHashMap::with_capacity_and_hasher(
+ capacity,
+ BuildHasherDefault::default(),
+ ))
+ }
+}
+impl<K, V> Trace for GcHashMap<K, V>
+where
+ K: Trace,
+ V: Trace,
+{
+ fn trace(&self, tracer: &mut gcmodule::Tracer) {
+ for (k, v) in &self.0 {
+ k.trace(tracer);
+ v.trace(tracer);
+ }
+ }
+}
+impl<K, V> Deref for GcHashMap<K, V> {
+ type Target = FxHashMap<K, V>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl<K, V> DerefMut for GcHashMap<K, V> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -25,30 +25,31 @@
use error::{Error::*, LocError, Result, StackTraceElement};
pub use evaluate::*;
pub use function::parse_function_call;
+use gc::{GcHashMap, TraceBox};
+use gcmodule::{Cc, Trace};
pub use import::*;
-use jrsonnet_gc::{Finalize, Gc, Trace};
pub use jrsonnet_interner::IStr;
use jrsonnet_parser::*;
use native::NativeCallback;
pub use obj::*;
-use rustc_hash::FxHashMap;
use std::{
cell::{Ref, RefCell, RefMut},
collections::HashMap,
fmt::Debug,
- hash::BuildHasherDefault,
path::{Path, PathBuf},
rc::Rc,
};
use trace::{location_to_offset, offset_to_location, CodeLocation, CompactFormat, TraceFormat};
pub use val::*;
+pub mod gc;
-pub trait Bindable: Trace {
+pub trait Bindable: Trace + 'static {
fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal>;
}
-#[derive(Trace, Finalize, Clone)]
+
+#[derive(Clone, Trace)]
pub enum LazyBinding {
- Bindable(Gc<Box<dyn Bindable>>),
+ Bindable(Cc<TraceBox<dyn Bindable>>),
Bound(LazyVal),
}
@@ -74,7 +75,7 @@
/// Used for s`td.extVar`
pub ext_vars: HashMap<IStr, Val>,
/// Used for ext.native
- pub ext_natives: HashMap<IStr, Gc<NativeCallback>>,
+ pub ext_natives: HashMap<IStr, Cc<NativeCallback>>,
/// TLA vars
pub tla_vars: HashMap<IStr, Val>,
/// Global variables are inserted in default context
@@ -172,19 +173,27 @@
EVAL_STATE.with(|s| f(s.borrow().as_ref().unwrap()))
}
pub(crate) fn push_frame<T>(
- e: Option<&ExprLocation>,
+ e: &ExprLocation,
frame_desc: impl FnOnce() -> String,
f: impl FnOnce() -> Result<T>,
) -> Result<T> {
with_state(|s| s.push(e, frame_desc, f))
}
+#[allow(dead_code)]
pub(crate) fn push_val_frame(
- e: Option<&ExprLocation>,
+ e: &ExprLocation,
frame_desc: impl FnOnce() -> String,
f: impl FnOnce() -> Result<Val>,
) -> Result<Val> {
- with_state(|s| s.push(e, frame_desc, f))
+ with_state(|s| s.push_val(e, frame_desc, f))
+}
+#[allow(dead_code)]
+pub(crate) fn push_description_frame<T>(
+ frame_desc: impl FnOnce() -> String,
+ f: impl FnOnce() -> Result<T>,
+) -> Result<T> {
+ with_state(|s| s.push_description(frame_desc, f))
}
/// Maintains stack trace and import resolution
@@ -201,7 +210,6 @@
&source_code,
&ParserSettings {
file_name: path.clone(),
- loc_data: true,
},
)
.map_err(|error| ImportSyntaxError {
@@ -246,7 +254,7 @@
ro_map.get(name).map(|value| value.source_code.clone())
}
pub fn map_source_locations(&self, file: &Path, locs: &[usize]) -> Vec<CodeLocation> {
- offset_to_location(&self.get_source(file).unwrap(), locs)
+ offset_to_location(&self.get_source(file).unwrap_or("".into()), locs)
}
pub fn map_from_source_location(
&self,
@@ -322,8 +330,7 @@
/// Creates context with all passed global variables
pub fn create_default_context(&self) -> Context {
let globals = &self.settings().globals;
- let mut new_bindings: FxHashMap<IStr, LazyVal> =
- FxHashMap::with_capacity_and_hasher(globals.len(), BuildHasherDefault::default());
+ let mut new_bindings = GcHashMap::with_capacity(globals.len());
for (name, value) in globals.iter() {
new_bindings.insert(name.clone(), LazyVal::new_resolved(value.clone()));
}
@@ -333,7 +340,7 @@
/// Executes code creating a new stack frame
pub fn push<T>(
&self,
- e: Option<&ExprLocation>,
+ e: &ExprLocation,
frame_desc: impl FnOnce() -> String,
f: impl FnOnce() -> Result<T>,
) -> Result<T> {
@@ -353,25 +360,21 @@
let mut data = self.data_mut();
data.stack_depth -= 1;
data.stack_generation += 1;
- // if let Some(e) = e {
- // result =
- // data.breakpoints
- // .insert(data.stack_depth, data.stack_generation, &e, result)
- // }
}
if let Err(mut err) = result {
err.trace_mut().0.push(StackTraceElement {
- location: e.cloned(),
+ location: Some(e.clone()),
desc: frame_desc(),
});
return Err(err);
}
result
}
+
/// Executes code creating a new stack frame
pub fn push_val(
&self,
- e: Option<&ExprLocation>,
+ e: &ExprLocation,
frame_desc: impl FnOnce() -> String,
f: impl FnOnce() -> Result<Val>,
) -> Result<Val> {
@@ -391,15 +394,45 @@
let mut data = self.data_mut();
data.stack_depth -= 1;
data.stack_generation += 1;
- if let Some(e) = e {
- result =
- data.breakpoints
- .insert(data.stack_depth, data.stack_generation, &e, result)
+ result = data
+ .breakpoints
+ .insert(data.stack_depth, data.stack_generation, &e, result);
+ }
+ if let Err(mut err) = result {
+ err.trace_mut().0.push(StackTraceElement {
+ location: Some(e.clone()),
+ desc: frame_desc(),
+ });
+ return Err(err);
+ }
+ result
+ }
+ /// Executes code creating a new stack frame
+ pub fn push_description<T>(
+ &self,
+ frame_desc: impl FnOnce() -> String,
+ f: impl FnOnce() -> Result<T>,
+ ) -> Result<T> {
+ {
+ let mut data = self.data_mut();
+ let stack_depth = &mut data.stack_depth;
+ if *stack_depth > self.max_stack() {
+ // Error creation uses data, so i drop guard here
+ drop(data);
+ throw!(StackOverflow);
+ } else {
+ *stack_depth += 1;
}
}
+ let result = f();
+ {
+ let mut data = self.data_mut();
+ data.stack_depth -= 1;
+ data.stack_generation += 1;
+ }
if let Err(mut err) = result {
err.trace_mut().0.push(StackTraceElement {
- location: e.cloned(),
+ location: None,
desc: frame_desc(),
});
return Err(err);
@@ -451,7 +484,12 @@
}
pub fn manifest(&self, val: Val) -> Result<IStr> {
- self.run_in_state(|| val.manifest(&self.manifest_format()))
+ self.run_in_state(|| {
+ push_description_frame(
+ || format!("manifestification"),
+ || val.manifest(&self.manifest_format()),
+ )
+ })
}
pub fn manifest_multi(&self, val: Val) -> Result<Vec<(IStr, IStr)>> {
self.run_in_state(|| val.manifest_multi(&self.manifest_format()))
@@ -464,8 +502,7 @@
pub fn with_tla(&self, val: Val) -> Result<Val> {
self.run_in_state(|| {
Ok(match val {
- Val::Func(func) => push_frame(
- None,
+ Val::Func(func) => push_description_frame(
|| "during TLA call".to_owned(),
|| {
func.evaluate_map(
@@ -511,7 +548,6 @@
&code,
&ParserSettings {
file_name: source.clone(),
- loc_data: true,
},
)
.map_err(|e| ImportSyntaxError {
@@ -570,7 +606,7 @@
self.settings_mut().import_resolver = resolver;
}
- pub fn add_native(&self, name: IStr, cb: Gc<NativeCallback>) {
+ pub fn add_native(&self, name: IStr, cb: Cc<NativeCallback>) {
self.settings_mut().ext_natives.insert(name, cb);
}
@@ -603,13 +639,20 @@
}
}
+pub fn cc_ptr_eq<T>(a: &Cc<T>, b: &Cc<T>) -> bool {
+ let a = &a as &T;
+ let b = &b as &T;
+ std::ptr::eq(a, b)
+}
+
#[cfg(test)]
pub mod tests {
use super::Val;
use crate::{
- error::Error::*, native::NativeCallbackHandler, primitive_equals, EvaluationState,
+ error::Error::*, gc::TraceBox, native::NativeCallbackHandler, primitive_equals,
+ EvaluationState,
};
- use jrsonnet_gc::{Finalize, Gc, Trace};
+ use gcmodule::{Cc, Trace};
use jrsonnet_interner::IStr;
use jrsonnet_parser::*;
use std::{
@@ -624,11 +667,11 @@
state.run_in_state(|| {
state
.push(
- Some(&ExprLocation(PathBuf::from("test1.jsonnet").into(), 10, 20)),
+ &ExprLocation(PathBuf::from("test1.jsonnet").into(), 10, 20),
|| "outer".to_owned(),
|| {
state.push(
- Some(&ExprLocation(PathBuf::from("test2.jsonnet").into(), 30, 40)),
+ &ExprLocation(PathBuf::from("test2.jsonnet").into(), 30, 40),
|| "inner".to_owned(),
|| Err(RuntimeError("".into()).into()),
)?;
@@ -1028,7 +1071,6 @@
"{ x: 1, y: 2 } == { x: 1, y: 2 }",
&ParserSettings {
file_name: PathBuf::from("equality").into(),
- loc_data: true,
}
)
);
@@ -1042,14 +1084,11 @@
evaluator.with_stdlib();
- #[derive(Trace, Finalize)]
+ #[derive(Trace)]
struct NativeAdd;
impl NativeCallbackHandler for NativeAdd {
- fn call(&self, from: Option<Rc<Path>>, args: &[Val]) -> crate::error::Result<Val> {
- assert_eq!(
- &from.unwrap() as &Path,
- &PathBuf::from("native_caller.jsonnet")
- );
+ fn call(&self, from: Rc<Path>, args: &[Val]) -> crate::error::Result<Val> {
+ assert_eq!(&from as &Path, &PathBuf::from("native_caller.jsonnet"));
match (&args[0], &args[1]) {
(Val::Num(a), Val::Num(b)) => Ok(Val::Num(a + b)),
(_, _) => unreachable!(),
@@ -1058,12 +1097,12 @@
}
evaluator.settings_mut().ext_natives.insert(
"native_add".into(),
- Gc::new(NativeCallback::new(
+ Cc::new(NativeCallback::new(
ParamsDesc(Rc::new(vec![
Param("a".into(), None),
Param("b".into(), None),
])),
- Box::new(NativeAdd),
+ TraceBox(Box::new(NativeAdd)),
)),
);
evaluator.evaluate_snippet_raw(
crates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/map.rs
+++ b/crates/jrsonnet-evaluator/src/map.rs
@@ -1,23 +1,21 @@
-use jrsonnet_gc::{Gc, Trace};
+use gcmodule::{Cc, Trace};
use jrsonnet_interner::IStr;
-use rustc_hash::FxHashMap;
-use crate::LazyVal;
+use crate::{GcHashMap, LazyVal};
#[derive(Trace)]
-#[trivially_drop]
+#[force_tracking]
pub struct LayeredHashMapInternals {
parent: Option<LayeredHashMap>,
- current: FxHashMap<IStr, LazyVal>,
+ current: GcHashMap<IStr, LazyVal>,
}
#[derive(Trace)]
-#[trivially_drop]
-pub struct LayeredHashMap(Gc<LayeredHashMapInternals>);
+pub struct LayeredHashMap(Cc<LayeredHashMapInternals>);
impl LayeredHashMap {
- pub fn extend(self, new_layer: FxHashMap<IStr, LazyVal>) -> Self {
- Self(Gc::new(LayeredHashMapInternals {
+ pub fn extend(self, new_layer: GcHashMap<IStr, LazyVal>) -> Self {
+ Self(Cc::new(LayeredHashMapInternals {
parent: Some(self),
current: new_layer,
}))
@@ -49,9 +47,9 @@
impl Default for LayeredHashMap {
fn default() -> Self {
- Self(Gc::new(LayeredHashMapInternals {
+ Self(Cc::new(LayeredHashMapInternals {
parent: None,
- current: FxHashMap::default(),
+ current: GcHashMap::new(),
}))
}
}
crates/jrsonnet-evaluator/src/native.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/native.rs
+++ b/crates/jrsonnet-evaluator/src/native.rs
@@ -1,27 +1,27 @@
#![allow(clippy::type_complexity)]
+use crate::gc::TraceBox;
use crate::{error::Result, Val};
-use jrsonnet_gc::Trace;
+use gcmodule::Trace;
use jrsonnet_parser::ParamsDesc;
use std::fmt::Debug;
use std::path::Path;
use std::rc::Rc;
pub trait NativeCallbackHandler: Trace {
- fn call(&self, from: Option<Rc<Path>>, args: &[Val]) -> Result<Val>;
+ fn call(&self, from: Rc<Path>, args: &[Val]) -> Result<Val>;
}
#[derive(Trace)]
-#[trivially_drop]
pub struct NativeCallback {
pub params: ParamsDesc,
- handler: Box<dyn NativeCallbackHandler>,
+ handler: TraceBox<dyn NativeCallbackHandler>,
}
impl NativeCallback {
- pub fn new(params: ParamsDesc, handler: Box<dyn NativeCallbackHandler>) -> Self {
+ pub fn new(params: ParamsDesc, handler: TraceBox<dyn NativeCallbackHandler>) -> Self {
Self { params, handler }
}
- pub fn call(&self, caller: Option<Rc<Path>>, args: &[Val]) -> Result<Val> {
+ pub fn call(&self, caller: Rc<Path>, args: &[Val]) -> Result<Val> {
self.handler.call(caller, args)
}
}
crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj.rs
+++ b/crates/jrsonnet-evaluator/src/obj.rs
@@ -1,15 +1,15 @@
+use crate::gc::{GcHashMap, GcHashSet, TraceBox};
use crate::operator::evaluate_add_op;
-use crate::{Bindable, LazyBinding, LazyVal, Result, Val};
-use jrsonnet_gc::{Gc, GcCell, Trace};
+use crate::{cc_ptr_eq, Bindable, LazyBinding, LazyVal, Result, Val};
+use gcmodule::{Cc, Trace};
use jrsonnet_interner::IStr;
use jrsonnet_parser::{ExprLocation, Visibility};
-use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
-use std::collections::HashMap;
+use rustc_hash::FxHashMap;
+use std::cell::RefCell;
+use std::fmt::Debug;
use std::hash::{Hash, Hasher};
-use std::{fmt::Debug, hash::BuildHasherDefault};
#[derive(Debug, Trace)]
-#[trivially_drop]
pub struct ObjMember {
pub add: bool,
pub visibility: Visibility,
@@ -24,19 +24,18 @@
// Field => This
type CacheKey = (IStr, ObjValue);
#[derive(Trace)]
-#[trivially_drop]
+#[force_tracking]
pub struct ObjValueInternals {
super_obj: Option<ObjValue>,
- assertions: Gc<Vec<Box<dyn ObjectAssertion>>>,
- assertions_ran: GcCell<FxHashSet<ObjValue>>,
+ assertions: Cc<Vec<TraceBox<dyn ObjectAssertion>>>,
+ assertions_ran: RefCell<GcHashSet<ObjValue>>,
this_obj: Option<ObjValue>,
- this_entries: Gc<FxHashMap<IStr, ObjMember>>,
- value_cache: GcCell<FxHashMap<CacheKey, Option<Val>>>,
+ this_entries: Cc<GcHashMap<IStr, ObjMember>>,
+ value_cache: RefCell<GcHashMap<CacheKey, Option<Val>>>,
}
#[derive(Clone, Trace)]
-#[trivially_drop]
-pub struct ObjValue(pub(crate) Gc<ObjValueInternals>);
+pub struct ObjValue(pub(crate) Cc<ObjValueInternals>);
impl Debug for ObjValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(super_obj) = self.0.super_obj.as_ref() {
@@ -65,20 +64,20 @@
impl ObjValue {
pub fn new(
super_obj: Option<Self>,
- this_entries: Gc<FxHashMap<IStr, ObjMember>>,
- assertions: Gc<Vec<Box<dyn ObjectAssertion>>>,
+ this_entries: Cc<GcHashMap<IStr, ObjMember>>,
+ assertions: Cc<Vec<TraceBox<dyn ObjectAssertion>>>,
) -> Self {
- Self(Gc::new(ObjValueInternals {
+ Self(Cc::new(ObjValueInternals {
super_obj,
assertions,
- assertions_ran: GcCell::new(FxHashSet::default()),
+ assertions_ran: RefCell::new(GcHashSet::new()),
this_obj: None,
this_entries,
- value_cache: GcCell::new(FxHashMap::default()),
+ value_cache: RefCell::new(GcHashMap::new()),
}))
}
pub fn new_empty() -> Self {
- Self::new(None, Gc::new(FxHashMap::default()), Gc::new(Vec::new()))
+ Self::new(None, Cc::new(GcHashMap::new()), Cc::new(Vec::new()))
}
pub fn extend_from(&self, super_obj: Self) -> Self {
match &self.0.super_obj {
@@ -95,13 +94,13 @@
}
}
pub fn with_this(&self, this_obj: Self) -> Self {
- Self(Gc::new(ObjValueInternals {
+ Self(Cc::new(ObjValueInternals {
super_obj: self.0.super_obj.clone(),
assertions: self.0.assertions.clone(),
- assertions_ran: GcCell::new(FxHashSet::default()),
+ assertions_ran: RefCell::new(GcHashSet::new()),
this_obj: Some(this_obj),
this_entries: self.0.this_entries.clone(),
- value_cache: GcCell::new(FxHashMap::default()),
+ value_cache: RefCell::new(GcHashMap::new()),
}))
}
@@ -117,14 +116,14 @@
}
/// Run callback for every field found in object
- pub(crate) fn enum_fields(&self, handler: &mut impl FnMut(&IStr, &Visibility) -> bool) -> bool {
+ pub(crate) fn enum_fields(&self, handler: &mut impl FnMut(&IStr, &ObjMember) -> bool) -> bool {
if let Some(s) = &self.0.super_obj {
if s.enum_fields(handler) {
return true;
}
}
for (name, member) in self.0.this_entries.iter() {
- if handler(name, &member.visibility) {
+ if handler(name, &member) {
return true;
}
}
@@ -133,8 +132,8 @@
pub fn fields_visibility(&self) -> FxHashMap<IStr, bool> {
let mut out = FxHashMap::default();
- self.enum_fields(&mut |name, visibility| {
- match visibility {
+ self.enum_fields(&mut |name, member| {
+ match member.visibility {
Visibility::Normal => {
let entry = out.entry(name.to_owned());
entry.or_insert(true);
@@ -211,9 +210,9 @@
}
pub fn extend_with_field(self, key: IStr, value: ObjMember) -> Self {
- let mut new = FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());
+ let mut new = GcHashMap::with_capacity(1);
new.insert(key, value);
- Self::new(Some(self), Gc::new(new), Gc::new(Vec::new()))
+ Self::new(Some(self), Cc::new(new), Cc::new(Vec::new()))
}
fn get_raw(&self, key: IStr, real_this: Option<&Self>) -> Result<Option<Val>> {
@@ -270,13 +269,13 @@
}
pub fn ptr_eq(a: &Self, b: &Self) -> bool {
- Gc::ptr_eq(&a.0, &b.0)
+ cc_ptr_eq(&a.0, &b.0)
}
}
impl PartialEq for ObjValue {
fn eq(&self, other: &Self) -> bool {
- Gc::ptr_eq(&self.0, &other.0)
+ cc_ptr_eq(&self.0, &other.0)
}
}
@@ -289,8 +288,8 @@
pub struct ObjValueBuilder {
super_obj: Option<ObjValue>,
- map: FxHashMap<IStr, ObjMember>,
- assertions: Vec<Box<dyn ObjectAssertion>>,
+ map: GcHashMap<IStr, ObjMember>,
+ assertions: Vec<TraceBox<dyn ObjectAssertion>>,
}
impl ObjValueBuilder {
pub fn new() -> Self {
@@ -299,10 +298,7 @@
pub fn with_capacity(capacity: usize) -> Self {
Self {
super_obj: None,
- map: HashMap::with_capacity_and_hasher(
- capacity,
- BuildHasherDefault::<FxHasher>::default(),
- ),
+ map: GcHashMap::with_capacity(capacity),
assertions: Vec::new(),
}
}
@@ -315,7 +311,7 @@
self
}
- pub fn assert(&mut self, assertion: Box<dyn ObjectAssertion>) -> &mut Self {
+ pub fn assert(&mut self, assertion: TraceBox<dyn ObjectAssertion>) -> &mut Self {
self.assertions.push(assertion);
self
}
@@ -330,7 +326,7 @@
}
pub fn build(self) -> ObjValue {
- ObjValue::new(self.super_obj, Gc::new(self.map), Gc::new(self.assertions))
+ ObjValue::new(self.super_obj, Cc::new(self.map), Cc::new(self.assertions))
}
}
impl Default for ObjValueBuilder {
@@ -364,15 +360,15 @@
pub fn hide(self) -> Self {
self.with_visibility(Visibility::Hidden)
}
- pub fn with_location(mut self, location: Option<ExprLocation>) -> Self {
- self.location = location;
+ pub fn with_location(mut self, location: ExprLocation) -> Self {
+ self.location = Some(location);
self
}
pub fn value(self, value: Val) -> &'v mut ObjValueBuilder {
self.binding(LazyBinding::Bound(LazyVal::new_resolved(value)))
}
- pub fn bindable(self, bindable: Box<dyn Bindable>) -> &'v mut ObjValueBuilder {
- self.binding(LazyBinding::Bindable(Gc::new(bindable)))
+ pub fn bindable(self, bindable: TraceBox<dyn Bindable>) -> &'v mut ObjValueBuilder {
+ self.binding(LazyBinding::Bindable(Cc::new(bindable)))
}
pub fn binding(self, binding: LazyBinding) -> &'v mut ObjValueBuilder {
self.value.map.insert(
crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/trace/mod.rs
+++ b/crates/jrsonnet-evaluator/src/trace/mod.rs
@@ -119,16 +119,21 @@
.trace()
.0
.iter()
- .map(|el| {
- el.location.as_ref().map(|l| {
- use std::fmt::Write;
- let mut resolved_path = self.resolver.resolve(&l.0);
+ .map(|el| &el.location)
+ .map(|location| {
+ use std::fmt::Write;
+ if let Some(location) = location {
+ let mut resolved_path = self.resolver.resolve(&location.0);
// TODO: Process all trace elements first
- let location = evaluation_state.map_source_locations(&l.0, &[l.1, l.2]);
+ let location = evaluation_state
+ .map_source_locations(&location.0, &[location.1, location.2]);
write!(resolved_path, ":").unwrap();
print_code_location(&mut resolved_path, &location[0], &location[1]).unwrap();
- resolved_path
- })
+ write!(resolved_path, ":").unwrap();
+ Some(resolved_path)
+ } else {
+ None
+ }
})
.collect::<Vec<_>>();
let align = file_names
@@ -139,15 +144,19 @@
.unwrap_or(0);
for (el, file) in error.trace().0.iter().zip(file_names) {
writeln!(out)?;
- write!(
- out,
- "{:<p$}{:<w$}: {}",
- "",
- file.unwrap_or_else(|| "".to_owned()),
- el.desc,
- p = self.padding,
- w = align
- )?;
+ if let Some(file) = file {
+ write!(
+ out,
+ "{:<p$}{:<w$} {}",
+ "",
+ file,
+ el.desc,
+ p = self.padding,
+ w = align
+ )?;
+ } else {
+ write!(out, "{:<p$}{}", "", el.desc, p = self.padding,)?;
+ }
}
Ok(())
}
@@ -178,7 +187,7 @@
start_end[0].column,
)?;
} else {
- write!(out, " at {}", desc,)?;
+ write!(out, " during {}", desc)?;
}
}
Ok(())
@@ -206,25 +215,21 @@
} = error.error()
{
writeln!(out)?;
- let mut offset = error.location.offset;
- if offset >= source_code.len() {
- offset = source_code.len() - 1;
- }
- let mut location = offset_to_location(source_code, &[offset])
+ let offset = error.location.offset;
+ let location = offset_to_location(source_code, &[offset])
.into_iter()
.next()
.unwrap();
- if location.column >= 1 {
- location.column -= 1;
- }
+ let mut end_location = location.clone();
+ end_location.offset += 1;
self.print_snippet(
out,
source_code,
path,
&location,
- &location,
- "^ syntax error",
+ &end_location,
+ "syntax error",
)?;
}
let trace = &error.trace();
@@ -289,7 +294,7 @@
annotation_type: AnnotationType::Error,
range: (
start.offset - start.line_start_offset,
- end.offset - start.line_start_offset,
+ (end.offset - start.line_start_offset).min(source_fragment.len()),
),
}],
}],
crates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/typed.rs
+++ b/crates/jrsonnet-evaluator/src/typed.rs
@@ -1,11 +1,7 @@
use std::{fmt::Display, rc::Rc};
-use crate::{
- error::{Error, LocError, Result},
- push_frame, Val,
-};
-use jrsonnet_gc::Trace;
-use jrsonnet_parser::ExprLocation;
+use crate::{Val, error::{Error, LocError, Result}, push_description_frame};
+use gcmodule::Trace;
use jrsonnet_types::{ComplexValType, ValType};
use thiserror::Error;
@@ -22,12 +18,11 @@
}
#[derive(Debug, Error, Clone, Trace)]
-#[trivially_drop]
pub enum TypeError {
#[error("expected {0}, got {1}")]
ExpectedGot(ComplexValType, ValType),
#[error("missing property {0} from {1:?}")]
- MissingProperty(Rc<str>, ComplexValType),
+ MissingProperty(#[skip_trace] Rc<str>, ComplexValType),
#[error("every failed from {0}:\n{1}")]
UnionFailed(ComplexValType, TypeLocErrorList),
#[error(
@@ -44,7 +39,6 @@
}
#[derive(Debug, Clone, Trace)]
-#[trivially_drop]
pub struct TypeLocError(Box<TypeError>, ValuePathStack);
impl From<TypeError> for TypeLocError {
fn from(e: TypeError) -> Self {
@@ -67,7 +61,6 @@
}
#[derive(Debug, Clone, Trace)]
-#[trivially_drop]
pub struct TypeLocErrorList(Vec<TypeLocError>);
impl Display for TypeLocErrorList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -97,13 +90,12 @@
}
}
-fn push_type(
- location: Option<&ExprLocation>,
+fn push_type_description(
error_reason: impl Fn() -> String,
path: impl Fn() -> ValuePathItem,
item: impl Fn() -> Result<()>,
) -> Result<()> {
- push_frame(location, error_reason, || match item() {
+ push_description_frame(error_reason, || match item() {
Ok(_) => Ok(()),
Err(mut e) => {
if let Error::TypeError(e) = &mut e.error_mut() {
@@ -131,9 +123,8 @@
}
#[derive(Clone, Debug, Trace)]
-#[trivially_drop]
enum ValuePathItem {
- Field(Rc<str>),
+ Field(#[skip_trace] Rc<str>),
Index(u64),
}
impl Display for ValuePathItem {
@@ -147,7 +138,6 @@
}
#[derive(Clone, Debug, Trace)]
-#[trivially_drop]
struct ValuePathStack(Vec<ValuePathItem>);
impl Display for ValuePathStack {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -183,8 +173,7 @@
Self::Array(elem_type) => match value {
Val::Arr(a) => {
for (i, item) in a.iter().enumerate() {
- push_type(
- None,
+ push_type_description(
|| format!("array index {}", i),
|| ValuePathItem::Index(i as u64),
|| elem_type.check(&item.clone()?),
@@ -197,8 +186,7 @@
Self::ArrayRef(elem_type) => match value {
Val::Arr(a) => {
for (i, item) in a.iter().enumerate() {
- push_type(
- None,
+ push_type_description(
|| format!("array index {}", i),
|| ValuePathItem::Index(i as u64),
|| elem_type.check(&item.clone()?),
@@ -212,8 +200,7 @@
Val::Obj(obj) => {
for (k, v) in elems.iter() {
if let Some(got_v) = obj.get((*k).into())? {
- push_type(
- None,
+ push_type_description(
|| format!("property {}", k),
|| ValuePathItem::Field((*k).into()),
|| v.check(&got_v),
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -6,40 +6,40 @@
ManifestYamlOptions,
},
},
+ cc_ptr_eq,
error::{Error::*, LocError},
evaluate,
function::{parse_function_call, parse_function_call_map, place_args},
+ gc::TraceBox,
native::NativeCallback,
throw, Context, ObjValue, Result,
};
-use jrsonnet_gc::{Gc, GcCell, Trace};
+use gcmodule::{Cc, Trace};
use jrsonnet_interner::IStr;
use jrsonnet_parser::{ArgsDesc, ExprLocation, LocExpr, ParamsDesc};
use jrsonnet_types::ValType;
-use std::{collections::HashMap, fmt::Debug, rc::Rc};
+use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};
pub trait LazyValValue: Trace {
fn get(self: Box<Self>) -> Result<Val>;
}
#[derive(Trace)]
-#[trivially_drop]
enum LazyValInternals {
Computed(Val),
Errored(LocError),
- Waiting(Box<dyn LazyValValue>),
+ Waiting(TraceBox<dyn LazyValValue>),
Pending,
}
#[derive(Clone, Trace)]
-#[trivially_drop]
-pub struct LazyVal(Gc<GcCell<LazyValInternals>>);
+pub struct LazyVal(Cc<RefCell<LazyValInternals>>);
impl LazyVal {
- pub fn new(f: Box<dyn LazyValValue>) -> Self {
- Self(Gc::new(GcCell::new(LazyValInternals::Waiting(f))))
+ pub fn new(f: TraceBox<dyn LazyValValue>) -> Self {
+ Self(Cc::new(RefCell::new(LazyValInternals::Waiting(f))))
}
pub fn new_resolved(val: Val) -> Self {
- Self(Gc::new(GcCell::new(LazyValInternals::Computed(val))))
+ Self(Cc::new(RefCell::new(LazyValInternals::Computed(val))))
}
pub fn evaluate(&self) -> Result<Val> {
match &*self.0.borrow() {
@@ -55,7 +55,7 @@
} else {
unreachable!()
};
- let new_value = match value.get() {
+ let new_value = match value.0.get() {
Ok(v) => v,
Err(e) => {
*self.0.borrow_mut() = LazyValInternals::Errored(e.clone());
@@ -74,12 +74,11 @@
}
impl PartialEq for LazyVal {
fn eq(&self, other: &Self) -> bool {
- Gc::ptr_eq(&self.0, &other.0)
+ cc_ptr_eq(&self.0, &other.0)
}
}
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub struct FuncDesc {
pub name: IStr,
pub ctx: Context,
@@ -88,14 +87,13 @@
}
#[derive(Debug, Trace)]
-#[trivially_drop]
pub enum FuncVal {
/// Plain function implemented in jsonnet
Normal(FuncDesc),
/// Standard library function
Intrinsic(IStr),
/// Library functions implemented in native
- NativeExt(IStr, Gc<NativeCallback>),
+ NativeExt(IStr, Cc<NativeCallback>),
}
impl PartialEq for FuncVal {
@@ -122,7 +120,7 @@
pub fn evaluate(
&self,
call_ctx: Context,
- loc: Option<&ExprLocation>,
+ loc: &ExprLocation,
args: &ArgsDesc,
tailstrict: bool,
) -> Result<Val> {
@@ -145,7 +143,7 @@
for p in handler.params.0.iter() {
out_args.push(args.binding(p.0.clone())?.evaluate()?);
}
- Ok(handler.call(loc.map(|l| l.0.clone()), &out_args)?)
+ Ok(handler.call(loc.0.clone(), &out_args)?)
}
}
}
@@ -194,15 +192,15 @@
}
#[derive(Debug, Clone, Trace)]
-#[trivially_drop]
+#[force_tracking]
pub enum ArrValue {
- Lazy(Gc<Vec<LazyVal>>),
- Eager(Gc<Vec<Val>>),
+ Lazy(Cc<Vec<LazyVal>>),
+ Eager(Cc<Vec<Val>>),
Extended(Box<(Self, Self)>),
}
impl ArrValue {
pub fn new_eager() -> Self {
- Self::Eager(Gc::new(Vec::new()))
+ Self::Eager(Cc::new(Vec::new()))
}
pub fn len(&self) -> usize {
@@ -253,14 +251,14 @@
}
}
- pub fn evaluated(&self) -> Result<Gc<Vec<Val>>> {
+ pub fn evaluated(&self) -> Result<Cc<Vec<Val>>> {
Ok(match self {
Self::Lazy(vec) => {
let mut out = Vec::with_capacity(vec.len());
for item in vec.iter() {
out.push(item.evaluate()?);
}
- Gc::new(out)
+ Cc::new(out)
}
Self::Eager(vec) => vec.clone(),
Self::Extended(_v) => {
@@ -268,7 +266,7 @@
for item in self.iter() {
out.push(item?);
}
- Gc::new(out)
+ Cc::new(out)
}
})
}
@@ -294,12 +292,12 @@
Self::Lazy(vec) => {
let mut out = (&vec as &Vec<_>).clone();
out.reverse();
- Self::Lazy(Gc::new(out))
+ Self::Lazy(Cc::new(out))
}
Self::Eager(vec) => {
let mut out = (&vec as &Vec<_>).clone();
out.reverse();
- Self::Eager(Gc::new(out))
+ Self::Eager(Cc::new(out))
}
Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),
}
@@ -312,7 +310,7 @@
out.push(mapper(value?)?);
}
- Ok(Self::Eager(Gc::new(out)))
+ Ok(Self::Eager(Cc::new(out)))
}
pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {
@@ -325,13 +323,13 @@
}
}
- Ok(Self::Eager(Gc::new(out)))
+ Ok(Self::Eager(Cc::new(out)))
}
pub fn ptr_eq(a: &Self, b: &Self) -> bool {
match (a, b) {
- (Self::Lazy(a), Self::Lazy(b)) => Gc::ptr_eq(a, b),
- (Self::Eager(a), Self::Eager(b)) => Gc::ptr_eq(a, b),
+ (Self::Lazy(a), Self::Lazy(b)) => cc_ptr_eq(a, b),
+ (Self::Eager(a), Self::Eager(b)) => cc_ptr_eq(a, b),
_ => false,
}
}
@@ -339,13 +337,13 @@
impl From<Vec<LazyVal>> for ArrValue {
fn from(v: Vec<LazyVal>) -> Self {
- Self::Lazy(Gc::new(v))
+ Self::Lazy(Cc::new(v))
}
}
impl From<Vec<Val>> for ArrValue {
fn from(v: Vec<Val>) -> Self {
- Self::Eager(Gc::new(v))
+ Self::Eager(Cc::new(v))
}
}
@@ -355,7 +353,6 @@
}
#[derive(Debug, Clone, Trace)]
-#[trivially_drop]
pub enum Val {
Bool(bool),
Null,
@@ -363,7 +360,7 @@
Num(f64),
Arr(ArrValue),
Obj(ObjValue),
- Func(Gc<FuncVal>),
+ Func(Cc<FuncVal>),
}
macro_rules! matches_unwrap {
@@ -402,7 +399,7 @@
pub fn unwrap_arr(self) -> Result<ArrValue> {
Ok(matches_unwrap!(self, Self::Arr(v), v))
}
- pub fn unwrap_func(self) -> Result<Gc<FuncVal>> {
+ pub fn unwrap_func(self) -> Result<Cc<FuncVal>> {
Ok(matches_unwrap!(self, Self::Func(v), v))
}
pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {
crates/jrsonnet-interner/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-interner/Cargo.toml
+++ b/crates/jrsonnet-interner/Cargo.toml
@@ -9,4 +9,4 @@
[dependencies]
serde = { version = "1.0" }
rustc-hash = "1.1.0"
-jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
+gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
crates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-interner/src/lib.rs
+++ b/crates/jrsonnet-interner/src/lib.rs
@@ -1,4 +1,4 @@
-use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};
+use gcmodule::Trace;
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use std::{
@@ -11,9 +11,10 @@
#[derive(Clone, PartialOrd, Ord, Eq)]
pub struct IStr(Rc<str>);
-impl Finalize for IStr {}
-unsafe impl Trace for IStr {
- unsafe_empty_trace!();
+impl Trace for IStr {
+ fn is_type_tracked() -> bool {
+ false
+ }
}
impl Deref for IStr {
crates/jrsonnet-parser/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-parser/Cargo.toml
+++ b/crates/jrsonnet-parser/Cargo.toml
@@ -15,10 +15,9 @@
jrsonnet-interner = { path = "../jrsonnet-interner", version = "0.4.2" }
peg = "0.7.0"
-unescape = "0.1.0"
serde = { version = "1.0", features = ["derive", "rc"], optional = true }
-jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
+gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
[dev-dependencies]
jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }
crates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/expr.rs
+++ b/crates/jrsonnet-parser/src/expr.rs
@@ -1,4 +1,4 @@
-use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};
+use gcmodule::Trace;
use jrsonnet_interner::IStr;
#[cfg(feature = "deserialize")]
use serde::Deserialize;
@@ -14,7 +14,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub enum FieldName {
/// {fixed: 2}
Fixed(IStr),
@@ -25,7 +24,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Trace)]
-#[trivially_drop]
pub enum Visibility {
/// :
Normal,
@@ -44,13 +42,11 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Clone, Debug, PartialEq, Trace)]
-#[trivially_drop]
pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub struct FieldMember {
pub name: FieldName,
pub plus: bool,
@@ -62,7 +58,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub enum Member {
Field(FieldMember),
BindStmt(BindSpec),
@@ -72,7 +67,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Trace)]
-#[trivially_drop]
pub enum UnaryOpType {
Plus,
Minus,
@@ -99,7 +93,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Trace)]
-#[trivially_drop]
pub enum BinaryOpType {
Mul,
Div,
@@ -167,21 +160,13 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub struct Param(pub IStr, pub Option<LocExpr>);
/// Defined function parameters
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, Trace)]
pub struct ParamsDesc(pub Rc<Vec<Param>>);
-
-/// Safety:
-/// AST is acyclic, and there should be no gc pointers
-unsafe impl Trace for ParamsDesc {
- unsafe_empty_trace!();
-}
-impl Finalize for ParamsDesc {}
impl Deref for ParamsDesc {
type Target = Vec<Param>;
@@ -193,7 +178,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub struct ArgsDesc {
pub unnamed: Vec<LocExpr>,
pub named: Vec<(IStr, LocExpr)>,
@@ -207,7 +191,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, Clone, PartialEq, Trace)]
-#[trivially_drop]
pub struct BindSpec {
pub name: IStr,
pub params: Option<ParamsDesc>,
@@ -217,19 +200,16 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub struct IfSpecData(pub LocExpr);
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub struct ForSpecData(pub IStr, pub LocExpr);
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub enum CompSpec {
IfSpec(IfSpecData),
ForSpec(ForSpecData),
@@ -238,7 +218,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub struct ObjComp {
pub pre_locals: Vec<BindSpec>,
pub key: LocExpr,
@@ -251,7 +230,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub enum ObjBody {
MemberList(Vec<Member>),
ObjComp(ObjComp),
@@ -260,7 +238,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Clone, Copy, Trace)]
-#[trivially_drop]
pub enum LiteralType {
This,
Super,
@@ -273,7 +250,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub struct SliceDesc {
pub start: Option<LocExpr>,
pub end: Option<LocExpr>,
@@ -284,7 +260,6 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
-#[trivially_drop]
pub enum Expr {
Literal(LiteralType),
@@ -354,7 +329,7 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Clone, PartialEq, Trace)]
-#[trivially_drop]
+#[skip_trace]
pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);
impl ExprLocation {
pub fn belongs_to(&self, other: &ExprLocation) -> bool {
@@ -371,14 +346,8 @@
/// Holds AST expression and its location in source file
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Clone, PartialEq)]
-pub struct LocExpr(pub Rc<Expr>, pub Option<ExprLocation>);
-/// Safety:
-/// AST is acyclic, and there should be no gc pointers
-unsafe impl Trace for LocExpr {
- unsafe_empty_trace!();
-}
-impl Finalize for LocExpr {}
+#[derive(Clone, PartialEq, Trace)]
+pub struct LocExpr(pub Rc<Expr>, pub ExprLocation);
impl Debug for LocExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -387,24 +356,7 @@
} else {
write!(f, "{:?}", self.0)?;
}
- if let Some(loc) = &self.1 {
- write!(f, " from {:?}", loc)?;
- }
+ write!(f, " from {:?}", self.1)?;
Ok(())
}
-}
-
-/// Creates LocExpr from Expr and ExprLocation components
-#[macro_export]
-macro_rules! loc_expr {
- ($expr:expr, $need_loc:expr,($name:expr, $start:expr, $end:expr)) => {
- LocExpr(
- std::rc::Rc::new($expr),
- if $need_loc {
- Some(ExprLocation($name, $start, $end))
- } else {
- None
- },
- )
- };
}
crates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/lib.rs
+++ b/crates/jrsonnet-parser/src/lib.rs
@@ -9,9 +9,9 @@
pub use expr::*;
pub use jrsonnet_interner::IStr;
pub use peg;
+mod unescape;
pub struct ParserSettings {
- pub loc_data: bool,
pub file_name: Rc<Path>,
}
@@ -103,10 +103,20 @@
lines:("\n" {"\n"} / [' ' | '\t']*<{prefix.len()}> s:whole_line() {s})*
[' ' | '\t']*<, {prefix.len() - 1}> "|||"
{let mut l = empty_lines.to_owned(); l.push_str(first_line); l.extend(lines); l}
+
+ rule hex_char()
+ = quiet! { ['0'..='9' | 'a'..='f' | 'A'..='F'] } / expected!("<hex char>")
+
+ rule string_char(c: rule<()>)
+ = (!['\\']!c()[_])+
+ / "\\\\"
+ / "\\u" hex_char() hex_char() hex_char() hex_char()
+ / "\\x" hex_char() hex_char()
+ / ['\\'] (quiet! { ['b' | 'f' | 'n' | 'r' | 't'] / c() } / expected!("<escape character>"))
pub rule string() -> String
- = quiet!{ "\"" str:$(("\\\"" / "\\\\" / (!['"'][_]))*) "\"" {unescape::unescape(str).unwrap()}
- / "'" str:$(("\\'" / "\\\\" / (!['\''][_]))*) "'" {unescape::unescape(str).unwrap()}
- / "@'" str:$(("''" / (!['\''][_]))*) "'" {str.replace("''", "'")}
+ = ['"'] str:$(string_char(<['"']>)*) ['"'] {? unescape::unescape(str).ok_or("<escaped string>")}
+ / ['\''] str:$(string_char(<['\'']>)*) ['\''] {? unescape::unescape(str).ok_or("<escaped string>")}
+ / quiet!{ "@'" str:$(("''" / (!['\''][_]))*) "'" {str.replace("''", "'")}
/ "@\"" str:$(("\"\"" / (!['"'][_]))*) "\"" {str.replace("\"\"", "\"")}
/ string_block() } / expected!("<string>")
@@ -177,6 +187,8 @@
= n:number() { expr::Expr::Num(n) }
pub rule var_expr(s: &ParserSettings) -> Expr
= n:$(id()) { expr::Expr::Var(n.into()) }
+ pub rule id_loc(s: &ParserSettings) -> LocExpr
+ = a:position!() n:$(id()) b:position!() { LocExpr(Rc::new(expr::Expr::Str(n.into())), ExprLocation(s.file_name.clone(), a,b)) }
pub rule if_then_else_expr(s: &ParserSettings) -> Expr
= cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{
cond,
@@ -240,7 +252,7 @@
use UnaryOpType::*;
rule expr(s: &ParserSettings) -> LocExpr
= precedence! {
- start:position!() v:@ end:position!() { loc_expr!(v, s.loc_data, (s.file_name.clone(), start, end)) }
+ start:position!() v:@ end:position!() { LocExpr(Rc::new(v), ExprLocation(s.file_name.clone(), start, end)) }
--
a:(@) _ binop(<"||">) _ b:@ {expr_bin!(a Or b)}
--
@@ -276,7 +288,7 @@
unaryop(<"~">) _ b:@ {expr_un!(BitNot b)}
--
a:(@) _ "[" _ e:slice_desc(s) _ "]" {Expr::Slice(a, e)}
- a:(@) _ "." _ e:$(id()) {Expr::Index(a, el!(Expr::Str(e.into())))}
+ a:(@) _ "." _ a:position!() e:id_loc(s) b:position!() {Expr::Index(a, e)}
a:(@) _ "[" _ e:expr(s) _ "]" {Expr::Index(a, e)}
a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {Expr::Apply(a, args, ts.is_some())}
a:(@) _ "{" _ body:objinside(s) _ "}" {Expr::ObjExtend(a, body)}
@@ -292,13 +304,6 @@
pub type ParseError = peg::error::ParseError<peg::str::LineCol>;
pub fn parse(str: &str, settings: &ParserSettings) -> Result<LocExpr, ParseError> {
jsonnet_parser::jsonnet(str, settings)
-}
-
-#[macro_export]
-macro_rules! el {
- ($expr:expr) => {
- LocExpr(std::rc::Rc::new($expr), None)
- };
}
#[cfg(test)]
@@ -313,53 +318,39 @@
parse(
$s,
&ParserSettings {
- loc_data: false,
- file_name: PathBuf::from("/test.jsonnet").into(),
+ file_name: PathBuf::from("test.jsonnet").into(),
},
)
.unwrap()
};
}
- macro_rules! el_loc {
- ($expr:expr, $loc:expr$(,)?) => {
- LocExpr(std::rc::Rc::new($expr), Some($loc))
+ macro_rules! el {
+ ($expr:expr, $from:expr, $to:expr$(,)?) => {
+ LocExpr(
+ std::rc::Rc::new($expr),
+ ExprLocation(PathBuf::from("test.jsonnet").into(), $from, $to),
+ )
};
- }
-
- mod expressions {
- use super::*;
-
- pub fn basic_math() -> LocExpr {
- el!(Expr::BinaryOp(
- el!(Expr::Num(2.0)),
- Add,
- el!(Expr::BinaryOp(
- el!(Expr::Num(2.0)),
- Mul,
- el!(Expr::Num(2.0)),
- )),
- ))
- }
}
#[test]
fn multiline_string() {
assert_eq!(
parse!("|||\n Hello world!\n a\n|||"),
- el!(Expr::Str("Hello world!\n a\n".into())),
+ el!(Expr::Str("Hello world!\n a\n".into()), 0, 31),
);
assert_eq!(
parse!("|||\n Hello world!\n a\n|||"),
- el!(Expr::Str("Hello world!\n a\n".into())),
+ el!(Expr::Str("Hello world!\n a\n".into()), 0, 27),
);
assert_eq!(
parse!("|||\n\t\tHello world!\n\t\t\ta\n|||"),
- el!(Expr::Str("Hello world!\n\ta\n".into())),
+ el!(Expr::Str("Hello world!\n\ta\n".into()), 0, 27),
);
assert_eq!(
parse!("|||\n Hello world!\n a\n |||"),
- el!(Expr::Str("Hello world!\n a\n".into())),
+ el!(Expr::Str("Hello world!\n a\n".into()), 0, 30),
);
}
@@ -376,20 +367,20 @@
fn string_escaping() {
assert_eq!(
parse!(r#""Hello, \"world\"!""#),
- el!(Expr::Str(r#"Hello, "world"!"#.into())),
+ el!(Expr::Str(r#"Hello, "world"!"#.into()), 0, 19),
);
assert_eq!(
parse!(r#"'Hello \'world\'!'"#),
- el!(Expr::Str("Hello 'world'!".into())),
+ el!(Expr::Str("Hello 'world'!".into()), 0, 18),
);
- assert_eq!(parse!(r#"'\\\\'"#), el!(Expr::Str("\\\\".into())),);
+ assert_eq!(parse!(r#"'\\\\'"#), el!(Expr::Str("\\\\".into()), 0, 6));
}
#[test]
fn string_unescaping() {
assert_eq!(
parse!(r#""Hello\nWorld""#),
- el!(Expr::Str("Hello\nWorld".into())),
+ el!(Expr::Str("Hello\nWorld".into()), 0, 14),
);
}
@@ -397,7 +388,7 @@
fn string_verbantim() {
assert_eq!(
parse!(r#"@"Hello\n""World""""#),
- el!(Expr::Str("Hello\\n\"World\"".into())),
+ el!(Expr::Str("Hello\\n\"World\"".into()), 0, 19),
);
}
@@ -405,49 +396,95 @@
fn imports() {
assert_eq!(
parse!("import \"hello\""),
- el!(Expr::Import(PathBuf::from("hello"))),
+ el!(Expr::Import(PathBuf::from("hello")), 0, 14),
);
assert_eq!(
parse!("importstr \"garnish.txt\""),
- el!(Expr::ImportStr(PathBuf::from("garnish.txt")))
+ el!(Expr::ImportStr(PathBuf::from("garnish.txt")), 0, 23)
);
}
#[test]
fn empty_object() {
- assert_eq!(parse!("{}"), el!(Expr::Obj(ObjBody::MemberList(vec![]))));
+ assert_eq!(
+ parse!("{}"),
+ el!(Expr::Obj(ObjBody::MemberList(vec![])), 0, 2)
+ );
}
#[test]
fn basic_math() {
assert_eq!(
parse!("2+2*2"),
- el!(Expr::BinaryOp(
- el!(Expr::Num(2.0)),
- Add,
- el!(Expr::BinaryOp(
- el!(Expr::Num(2.0)),
- Mul,
- el!(Expr::Num(2.0))
- ))
- ))
+ el!(
+ Expr::BinaryOp(
+ el!(Expr::Num(2.0), 0, 1),
+ Add,
+ el!(
+ Expr::BinaryOp(el!(Expr::Num(2.0), 2, 3), Mul, el!(Expr::Num(2.0), 4, 5)),
+ 2,
+ 5
+ )
+ ),
+ 0,
+ 5
+ )
);
}
#[test]
fn basic_math_with_indents() {
- assert_eq!(parse!("2 + 2 * 2 "), expressions::basic_math());
+ assert_eq!(
+ parse!("2 + 2 * 2 "),
+ el!(
+ Expr::BinaryOp(
+ el!(Expr::Num(2.0), 0, 1),
+ Add,
+ el!(
+ Expr::BinaryOp(el!(Expr::Num(2.0), 7, 8), Mul, el!(Expr::Num(2.0), 13, 14),),
+ 7,
+ 14
+ ),
+ ),
+ 0,
+ 14
+ )
+ );
}
#[test]
fn basic_math_parened() {
assert_eq!(
parse!("2+(2+2*2)"),
- el!(Expr::BinaryOp(
- el!(Expr::Num(2.0)),
- Add,
- el!(Expr::Parened(expressions::basic_math())),
- ))
+ el!(
+ Expr::BinaryOp(
+ el!(Expr::Num(2.0), 0, 1),
+ Add,
+ el!(
+ Expr::Parened(el!(
+ Expr::BinaryOp(
+ el!(Expr::Num(2.0), 3, 4),
+ Add,
+ el!(
+ Expr::BinaryOp(
+ el!(Expr::Num(2.0), 5, 6),
+ Mul,
+ el!(Expr::Num(2.0), 7, 8),
+ ),
+ 5,
+ 8
+ ),
+ ),
+ 3,
+ 8
+ )),
+ 2,
+ 9
+ ),
+ ),
+ 0,
+ 9
+ )
);
}
@@ -456,15 +493,23 @@
fn comments() {
assert_eq!(
parse!("2//comment\n+//comment\n3/*test*/*/*test*/4"),
- el!(Expr::BinaryOp(
- el!(Expr::Num(2.0)),
- Add,
- el!(Expr::BinaryOp(
- el!(Expr::Num(3.0)),
- Mul,
- el!(Expr::Num(4.0))
- ))
- ))
+ el!(
+ Expr::BinaryOp(
+ el!(Expr::Num(2.0), 0, 1),
+ Add,
+ el!(
+ Expr::BinaryOp(
+ el!(Expr::Num(3.0), 22, 23),
+ Mul,
+ el!(Expr::Num(4.0), 40, 41)
+ ),
+ 22,
+ 41
+ )
+ ),
+ 0,
+ 41
+ )
);
}
@@ -473,11 +518,11 @@
fn comment_escaping() {
assert_eq!(
parse!("2/*\\*/+*/ - 22"),
- el!(Expr::BinaryOp(
- el!(Expr::Num(2.0)),
- Sub,
- el!(Expr::Num(22.0))
- ))
+ el!(
+ Expr::BinaryOp(el!(Expr::Num(2.0), 0, 1), Sub, el!(Expr::Num(22.0), 12, 14)),
+ 0,
+ 14
+ )
);
}
@@ -492,27 +537,46 @@
#[test]
fn array_comp() {
use Expr::*;
+ /*
+ `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`,
+ `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`
+ */
assert_eq!(
parse!("[std.deepJoin(x) for x in arr]"),
- el!(ArrComp(
- el!(Apply(
- el!(Index(el!(Var("std".into())), el!(Str("deepJoin".into())))),
- ArgsDesc::new(vec![el!(Var("x".into()))], vec![]),
- false,
- )),
- vec![CompSpec::ForSpec(ForSpecData(
- "x".into(),
- el!(Var("arr".into()))
- ))]
- )),
+ el!(
+ ArrComp(
+ el!(
+ Apply(
+ el!(
+ Index(
+ el!(Var("std".into()), 1, 4),
+ el!(Str("deepJoin".into()), 5, 13)
+ ),
+ 1,
+ 13
+ ),
+ ArgsDesc::new(vec![el!(Var("x".into()), 14, 15)], vec![]),
+ false,
+ ),
+ 1,
+ 16
+ ),
+ vec![CompSpec::ForSpec(ForSpecData(
+ "x".into(),
+ el!(Var("arr".into()), 26, 29)
+ ))]
+ ),
+ 0,
+ 30
+ ),
)
}
#[test]
fn reserved() {
use Expr::*;
- assert_eq!(parse!("null"), el!(Literal(LiteralType::Null)));
- assert_eq!(parse!("nulla"), el!(Var("nulla".into())));
+ assert_eq!(parse!("null"), el!(Literal(LiteralType::Null), 0, 4));
+ assert_eq!(parse!("nulla"), el!(Var("nulla".into()), 0, 5));
}
#[test]
@@ -525,11 +589,15 @@
use Expr::*;
assert_eq!(
parse!("!a && !b"),
- el!(BinaryOp(
- el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),
- And,
- el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))
- ))
+ el!(
+ BinaryOp(
+ el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 1, 2)), 0, 2),
+ And,
+ el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()), 7, 8)), 6, 8)
+ ),
+ 0,
+ 8
+ )
);
}
@@ -538,11 +606,15 @@
use Expr::*;
assert_eq!(
parse!("!a / !b"),
- el!(BinaryOp(
- el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),
- Div,
- el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))
- ))
+ el!(
+ BinaryOp(
+ el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 1, 2)), 0, 2),
+ Div,
+ el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()), 6, 7)), 5, 7)
+ ),
+ 0,
+ 7
+ )
);
}
@@ -551,10 +623,14 @@
use Expr::*;
assert_eq!(
parse!("!!a"),
- el!(UnaryOp(
- UnaryOpType::Not,
- el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()))))
- ))
+ el!(
+ UnaryOp(
+ UnaryOpType::Not,
+ el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 2, 3)), 1, 3)
+ ),
+ 0,
+ 3
+ )
)
}
@@ -587,55 +663,44 @@
fn add_location_info_to_all_sub_expressions() {
use Expr::*;
- let file_name: std::rc::Rc<std::path::Path> = PathBuf::from("/test.jsonnet").into();
+ let file_name: std::rc::Rc<std::path::Path> = PathBuf::from("test.jsonnet").into();
let expr = parse(
"{} { local x = 1, x: x } + {}",
&ParserSettings {
- loc_data: true,
file_name: file_name.clone(),
},
)
.unwrap();
assert_eq!(
expr,
- el_loc!(
+ el!(
BinaryOp(
- el_loc!(
+ el!(
ObjExtend(
- el_loc!(
- Obj(ObjBody::MemberList(vec![])),
- ExprLocation(file_name.clone(), 0, 2)
- ),
+ el!(Obj(ObjBody::MemberList(vec![])), 0, 2),
ObjBody::MemberList(vec![
Member::BindStmt(BindSpec {
name: "x".into(),
params: None,
- value: el_loc!(
- Num(1.0),
- ExprLocation(file_name.clone(), 15, 16)
- )
+ value: el!(Num(1.0), 15, 16)
}),
Member::Field(FieldMember {
name: FieldName::Fixed("x".into()),
plus: false,
params: None,
visibility: Visibility::Normal,
- value: el_loc!(
- Var("x".into()),
- ExprLocation(file_name.clone(), 21, 22)
- ),
+ value: el!(Var("x".into()), 21, 22),
})
])
),
- ExprLocation(file_name.clone(), 0, 24)
+ 0,
+ 24
),
BinaryOpType::Add,
- el_loc!(
- Obj(ObjBody::MemberList(vec![])),
- ExprLocation(file_name.clone(), 27, 29)
- ),
+ el!(Obj(ObjBody::MemberList(vec![])), 27, 29),
),
- ExprLocation(file_name.clone(), 0, 29),
+ 0,
+ 29
),
);
}
crates/jrsonnet-parser/src/unescape.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-parser/src/unescape.rs
@@ -0,0 +1,38 @@
+pub fn unescape(s: &str) -> Option<String> {
+ let mut chars = s.chars();
+ let mut out = String::with_capacity(s.len());
+
+ while let Some(c) = chars.next() {
+ if c != '\\' {
+ out.push(c);
+ continue;
+ }
+ match chars.next()? {
+ c @ ('\\' | '"' | '\'') => out.push(c),
+ 'b' => out.push('\u{0008}'),
+ 'f' => out.push('\u{000c}'),
+ 'n' => out.push('\n'),
+ 'r' => out.push('\r'),
+ 't' => out.push('\t'),
+ 'u' => {
+ let c = IntoIterator::into_iter([
+ chars.next()?,
+ chars.next()?,
+ chars.next()?,
+ chars.next()?,
+ ])
+ .map(|c| c.to_digit(16))
+ .try_fold(0u32, |acc, v| Some((acc << 8) | (v?)))?;
+ out.push(char::from_u32(c)?)
+ }
+ 'x' => {
+ let c = IntoIterator::into_iter([chars.next()?, chars.next()?])
+ .map(|c| c.to_digit(16))
+ .try_fold(0u32, |acc, v| Some((acc << 8) | (v?)))?;
+ out.push(char::from_u32(c)?)
+ }
+ _ => return None,
+ }
+ }
+ Some(out)
+}
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.tomldiffbeforeafterboth--- a/crates/jrsonnet-types/Cargo.toml
+++ b/crates/jrsonnet-types/Cargo.toml
@@ -8,4 +8,4 @@
[dependencies]
peg = "0.7.0"
-jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
+gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }
crates/jrsonnet-types/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-types/src/lib.rs
+++ b/crates/jrsonnet-types/src/lib.rs
@@ -1,6 +1,6 @@
#![allow(clippy::redundant_closure_call)]
-use jrsonnet_gc::Trace;
+use gcmodule::Trace;
use std::fmt::Display;
#[macro_export]
@@ -82,7 +82,6 @@
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]
-#[trivially_drop]
pub enum ValType {
Bool,
Null,
@@ -115,7 +114,7 @@
}
#[derive(Debug, Clone, PartialEq, Trace)]
-#[trivially_drop]
+#[skip_trace]
pub enum ComplexValType {
Any,
Char,