difftreelog
refactor switch to jrsonnet-gc
in: master
27 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -100,27 +100,6 @@
]
[[package]]
-name = "gc"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3edaac0f5832202ebc99520cb77c932248010c4645d20be1dc62d6579f5b3752"
-dependencies = [
- "gc_derive",
-]
-
-[[package]]
-name = "gc_derive"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60df8444f094ff7885631d80e78eb7d88c3c2361a98daaabb06256e4500db941"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
name = "hashbrown"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -190,7 +169,7 @@
"anyhow",
"base64",
"bincode",
- "gc",
+ "jrsonnet-gc",
"jrsonnet-interner",
"jrsonnet-parser",
"jrsonnet-stdlib",
@@ -204,10 +183,31 @@
]
[[package]]
+name = "jrsonnet-gc"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68da8bc2f00117b1373bb8877af03b1d391e4c4800e6585d7279e5b99c919dde"
+dependencies = [
+ "jrsonnet-gc-derive",
+]
+
+[[package]]
+name = "jrsonnet-gc-derive"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adcba9c387b64b054f06cc4d724905296e21edeeb7506847f3299117a2d92d12"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
name = "jrsonnet-interner"
version = "0.3.8"
dependencies = [
- "gc",
+ "jrsonnet-gc",
"rustc-hash",
"serde",
]
@@ -216,7 +216,7 @@
name = "jrsonnet-parser"
version = "0.3.8"
dependencies = [
- "gc",
+ "jrsonnet-gc",
"jrsonnet-interner",
"jrsonnet-stdlib",
"peg",
@@ -232,7 +232,7 @@
name = "jrsonnet-types"
version = "0.3.8"
dependencies = [
- "gc",
+ "jrsonnet-gc",
"peg",
]
@@ -240,8 +240,8 @@
name = "jsonnet"
version = "0.3.8"
dependencies = [
- "gc",
"jrsonnet-evaluator",
+ "jrsonnet-gc",
"jrsonnet-parser",
]
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.3.8" }
jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.3.8" }
-gc = { version = "0.4.1", features = ["derive"] }
+jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
[lib]
crate-type = ["cdylib"]
bindings/jsonnet/src/native.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/native.rs
+++ b/bindings/jsonnet/src/native.rs
@@ -1,9 +1,9 @@
-use gc::{unsafe_empty_trace, Finalize, Gc, Trace};
use jrsonnet_evaluator::{
error::{Error, LocError},
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},
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 gc::Gc;
use jrsonnet_evaluator::{ArrValue, EvaluationState, ObjValue, Val};
+use jrsonnet_gc::Gc;
use std::{
ffi::CStr,
os::raw::{c_char, c_double, c_int},
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 gc::Gc;
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};
crates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-evaluator/Cargo.toml
+++ b/crates/jrsonnet-evaluator/Cargo.toml
@@ -35,7 +35,7 @@
rustc-hash = "1.1.0"
thiserror = "1.0"
-gc = { version = "0.4.1", features = ["derive"] }
+jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
[dependencies.anyhow]
version = "1.0"
crates/jrsonnet-evaluator/src/builtin/format.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/format.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/format.rs
@@ -2,12 +2,13 @@
#![allow(clippy::too_many_arguments)]
use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val};
-use gc::{Finalize, Trace};
+use jrsonnet_gc::Trace;
use jrsonnet_interner::IStr;
use jrsonnet_types::ValType;
use thiserror::Error;
-#[derive(Debug, Clone, Error, Trace, Finalize)]
+#[derive(Debug, Clone, Error, Trace)]
+#[trivially_drop]
pub enum FormatError {
#[error("truncated format code")]
TruncatedFormatCode,
crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -5,7 +5,7 @@
EvaluationState, FuncVal, LazyVal, Val,
};
use format::{format_arr, format_obj};
-use gc::Gc;
+use jrsonnet_gc::Gc;
use jrsonnet_interner::IStr;
use jrsonnet_parser::{ArgsDesc, BinaryOpType, ExprLocation};
use jrsonnet_types::ty;
@@ -454,7 +454,7 @@
0, rest: ty!(any);
], {
println!("GC start");
- gc::force_collect();
+ jrsonnet_gc::force_collect();
println!("GC done");
Ok(rest)
crates/jrsonnet-evaluator/src/builtin/sort.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/sort.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/sort.rs
@@ -2,7 +2,7 @@
error::{Error, LocError, Result},
throw, Context, FuncVal, Val,
};
-use gc::{Finalize, Gc, Trace};
+use jrsonnet_gc::{Finalize, Gc, Trace};
#[derive(Debug, Clone, thiserror::Error, Trace, Finalize)]
pub enum SortError {
crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/ctx.rs
+++ b/crates/jrsonnet-evaluator/src/ctx.rs
@@ -2,13 +2,14 @@
error::Error::*, map::LayeredHashMap, FutureWrapper, LazyBinding, LazyVal, ObjValue, Result,
Val,
};
-use gc::{Finalize, Gc, Trace};
+use jrsonnet_gc::{Gc, Trace};
use jrsonnet_interner::IStr;
use rustc_hash::FxHashMap;
use std::fmt::Debug;
use std::hash::BuildHasherDefault;
-#[derive(Clone, Trace, Finalize)]
+#[derive(Clone, Trace)]
+#[trivially_drop]
pub struct ContextCreator(pub Context, pub FutureWrapper<FxHashMap<IStr, LazyBinding>>);
impl ContextCreator {
pub fn create(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<Context> {
@@ -21,12 +22,13 @@
}
}
-#[derive(Trace, Finalize)]
+#[derive(Trace)]
+#[trivially_drop]
struct ContextInternals {
dollar: Option<ObjValue>,
this: Option<ObjValue>,
super_obj: Option<ObjValue>,
- bindings: LayeredHashMap<LazyVal>,
+ bindings: LayeredHashMap,
}
impl Debug for ContextInternals {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -34,7 +36,8 @@
}
}
-#[derive(Debug, Clone, Trace, Finalize)]
+#[derive(Debug, Clone, Trace)]
+#[trivially_drop]
pub struct Context(Gc<ContextInternals>);
impl Context {
pub fn new_future() -> FutureWrapper<Self> {
crates/jrsonnet-evaluator/src/dynamic.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/dynamic.rs
+++ b/crates/jrsonnet-evaluator/src/dynamic.rs
@@ -1,6 +1,7 @@
-use gc::{Finalize, Gc, GcCell, Trace};
+use jrsonnet_gc::{Gc, GcCell, Trace};
-#[derive(Clone, Trace, Finalize)]
+#[derive(Clone, Trace)]
+#[trivially_drop]
pub struct FutureWrapper<V: Trace + 'static>(pub Gc<GcCell<Option<V>>>);
impl<T: Trace + 'static> FutureWrapper<T> {
pub fn new() -> Self {
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -2,7 +2,7 @@
builtin::{format::FormatError, sort::SortError},
typed::TypeLocError,
};
-use gc::{Finalize, Trace};
+use jrsonnet_gc::Trace;
use jrsonnet_interner::IStr;
use jrsonnet_parser::{BinaryOpType, ExprLocation, UnaryOpType};
use jrsonnet_types::ValType;
@@ -12,7 +12,8 @@
};
use thiserror::Error;
-#[derive(Error, Debug, Clone, Trace, Finalize)]
+#[derive(Error, Debug, Clone, Trace)]
+#[trivially_drop]
pub enum Error {
#[error("intrinsic not found: {0}")]
IntrinsicNotFound(IStr),
@@ -149,15 +150,18 @@
}
}
-#[derive(Clone, Debug, Trace, Finalize)]
+#[derive(Clone, Debug, Trace)]
+#[trivially_drop]
pub struct StackTraceElement {
pub location: Option<ExprLocation>,
pub desc: String,
}
-#[derive(Debug, Clone, Trace, Finalize)]
+#[derive(Debug, Clone, Trace)]
+#[trivially_drop]
pub struct StackTrace(pub Vec<StackTraceElement>);
-#[derive(Debug, Clone, Trace, Finalize)]
+#[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.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate.rs
@@ -3,7 +3,7 @@
FuncDesc, FuncVal, FutureWrapper, LazyBinding, LazyVal, LazyValValue, ObjMember, ObjValue,
ObjectAssertion, Result, Val,
};
-use gc::{custom_trace, Finalize, Gc, Trace};
+use jrsonnet_gc::{Gc, Trace};
use jrsonnet_interner::IStr;
use jrsonnet_parser::{
ArgsDesc, AssertStmt, BinaryOpType, BindSpec, CompSpec, Expr, ExprLocation, FieldMember,
@@ -22,21 +22,14 @@
if let Some(params) = &b.params {
let params = params.clone();
+ #[derive(Trace)]
+ #[trivially_drop]
struct LazyMethodBinding {
context_creator: FutureWrapper<Context>,
name: IStr,
params: ParamsDesc,
value: LocExpr,
}
- impl Finalize for LazyMethodBinding {}
- unsafe impl Trace for LazyMethodBinding {
- custom_trace!(this, {
- mark(&this.context_creator);
- mark(&this.name);
- mark(&this.params);
- mark(&this.value);
- });
- }
impl LazyValValue for LazyMethodBinding {
fn get(self: Box<Self>) -> Result<Val> {
Ok(evaluate_method(
@@ -55,19 +48,13 @@
value: b.value.clone(),
}))
} else {
+ #[derive(Trace)]
+ #[trivially_drop]
struct LazyNamedBinding {
context_creator: FutureWrapper<Context>,
name: IStr,
value: LocExpr,
}
- impl Finalize for LazyNamedBinding {}
- unsafe impl Trace for LazyNamedBinding {
- custom_trace!(this, {
- mark(&this.context_creator);
- mark(&this.name);
- mark(&this.value);
- });
- }
impl LazyValValue for LazyNamedBinding {
fn get(self: Box<Self>) -> Result<Val> {
evaluate_named(self.context_creator.unwrap(), &self.value, self.name)
@@ -86,6 +73,8 @@
if let Some(params) = &b.params {
let params = params.clone();
+ #[derive(Trace)]
+ #[trivially_drop]
struct BindableMethodLazyVal {
this: Option<ObjValue>,
super_obj: Option<ObjValue>,
@@ -94,17 +83,6 @@
name: IStr,
params: ParamsDesc,
value: LocExpr,
- }
- impl Finalize for BindableMethodLazyVal {}
- unsafe impl Trace for BindableMethodLazyVal {
- custom_trace!(this, {
- mark(&this.this);
- mark(&this.super_obj);
- mark(&this.context_creator);
- mark(&this.name);
- mark(&this.params);
- mark(&this.value);
- });
}
impl LazyValValue for BindableMethodLazyVal {
fn get(self: Box<Self>) -> Result<Val> {
@@ -117,7 +95,8 @@
}
}
- #[derive(Trace, Finalize)]
+ #[derive(Trace)]
+ #[trivially_drop]
struct BindableMethod {
context_creator: ContextCreator,
name: IStr,
@@ -148,6 +127,8 @@
}))),
)
} else {
+ #[derive(Trace)]
+ #[trivially_drop]
struct BindableNamedLazyVal {
this: Option<ObjValue>,
super_obj: Option<ObjValue>,
@@ -156,16 +137,6 @@
name: IStr,
value: LocExpr,
}
- impl Finalize for BindableNamedLazyVal {}
- unsafe impl Trace for BindableNamedLazyVal {
- custom_trace!(this, {
- mark(&this.this);
- mark(&this.super_obj);
- mark(&this.context_creator);
- mark(&this.name);
- mark(&this.value);
- });
- }
impl LazyValValue for BindableNamedLazyVal {
fn get(self: Box<Self>) -> Result<Val> {
evaluate_named(
@@ -176,7 +147,8 @@
}
}
- #[derive(Trace, Finalize)]
+ #[derive(Trace)]
+ #[trivially_drop]
struct BindableNamed {
context_creator: ContextCreator,
name: IStr,
@@ -414,7 +386,8 @@
}
let name = name.unwrap();
- #[derive(Trace, Finalize)]
+ #[derive(Trace)]
+ #[trivially_drop]
struct ObjMemberBinding {
context_creator: ContextCreator,
value: LocExpr,
@@ -458,7 +431,8 @@
continue;
}
let name = name.unwrap();
- #[derive(Trace, Finalize)]
+ #[derive(Trace)]
+ #[trivially_drop]
struct ObjMemberBinding {
context_creator: ContextCreator,
value: LocExpr,
@@ -496,16 +470,11 @@
}
Member::BindStmt(_) => {}
Member::AssertStmt(stmt) => {
+ #[derive(Trace)]
+ #[trivially_drop]
struct ObjectAssert {
context_creator: ContextCreator,
assert: AssertStmt,
- }
- impl Finalize for ObjectAssert {}
- unsafe impl Trace for ObjectAssert {
- custom_trace!(this, {
- mark(&this.context_creator);
- mark(&this.assert);
- });
}
impl ObjectAssertion for ObjectAssert {
fn run(
@@ -558,7 +527,8 @@
match key {
Val::Null => {}
Val::Str(n) => {
- #[derive(Trace, Finalize)]
+ #[derive(Trace)]
+ #[trivially_drop]
struct ObjCompBinding {
context: Context,
value: LocExpr,
@@ -768,16 +738,11 @@
let mut out = Vec::with_capacity(items.len());
for item in items {
// TODO: Implement ArrValue::Lazy with same context for every element?
+ #[derive(Trace)]
+ #[trivially_drop]
struct ArrayElement {
context: Context,
item: LocExpr,
- }
- impl Finalize for ArrayElement {}
- unsafe impl Trace for ArrayElement {
- custom_trace!(this, {
- mark(&this.context);
- mark(&this.item);
- });
}
impl LazyValValue for ArrayElement {
fn get(self: Box<Self>) -> Result<Val> {
crates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function.rs
+++ b/crates/jrsonnet-evaluator/src/function.rs
@@ -1,5 +1,5 @@
use crate::{error::Error::*, evaluate, throw, Context, LazyVal, LazyValValue, Result, Val};
-use gc::{custom_trace, Finalize, Trace};
+use jrsonnet_gc::Trace;
use jrsonnet_interner::IStr;
use jrsonnet_parser::{ArgsDesc, LocExpr, ParamsDesc};
use rustc_hash::FxHashMap;
@@ -55,16 +55,11 @@
let val = if tailstrict {
LazyVal::new_resolved(evaluate(ctx, expr)?)
} else {
+ #[derive(Trace)]
+ #[trivially_drop]
struct EvaluateLazyVal {
context: Context,
expr: LocExpr,
- }
- impl Finalize for EvaluateLazyVal {}
- unsafe impl Trace for EvaluateLazyVal {
- custom_trace!(this, {
- mark(&this.context);
- mark(&this.expr);
- });
}
impl LazyValValue for EvaluateLazyVal {
fn get(self: Box<Self>) -> Result<Val> {
@@ -119,7 +114,8 @@
} else {
let body_ctx = body_ctx.clone();
let default = default.clone();
- #[derive(Trace, Finalize)]
+ #[derive(Trace)]
+ #[trivially_drop]
struct EvaluateLazyVal {
body_ctx: Option<Context>,
default: LocExpr,
crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/integrations/serde.rs
+++ b/crates/jrsonnet-evaluator/src/integrations/serde.rs
@@ -2,7 +2,7 @@
error::{Error::*, LocError, Result},
throw, LazyBinding, LazyVal, ObjMember, ObjValue, Val,
};
-use gc::Gc;
+use jrsonnet_gc::Gc;
use jrsonnet_parser::Visibility;
use rustc_hash::FxHasher;
use serde_json::{Map, Number, Value};
crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -25,8 +25,8 @@
use error::{Error::*, LocError, Result, StackTraceElement};
pub use evaluate::*;
pub use function::parse_function_call;
-use gc::{Finalize, Gc, Trace};
pub use import::*;
+use jrsonnet_gc::{Finalize, Gc, Trace};
pub use jrsonnet_interner::IStr;
use jrsonnet_parser::*;
use native::NativeCallback;
crates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/map.rs
+++ b/crates/jrsonnet-evaluator/src/map.rs
@@ -1,32 +1,29 @@
-use gc::{Finalize, Gc, Trace};
+use jrsonnet_gc::{Gc, Trace};
use jrsonnet_interner::IStr;
use rustc_hash::FxHashMap;
-pub struct LayeredHashMapInternals<V: Trace + Finalize + 'static> {
- parent: Option<LayeredHashMap<V>>,
- current: FxHashMap<IStr, V>,
-}
+use crate::LazyVal;
-unsafe impl<V: Trace + Finalize + 'static> Trace for LayeredHashMapInternals<V> {
- gc::custom_trace!(this, {
- mark(&this.parent);
- mark(&this.current);
- });
+#[derive(Trace)]
+#[trivially_drop]
+pub struct LayeredHashMapInternals {
+ parent: Option<LayeredHashMap>,
+ current: FxHashMap<IStr, LazyVal>,
}
-impl<V: Trace + Finalize + 'static> Finalize for LayeredHashMapInternals<V> {}
-#[derive(Trace, Finalize)]
-pub struct LayeredHashMap<V: Trace + Finalize + 'static>(Gc<LayeredHashMapInternals<V>>);
+#[derive(Trace)]
+#[trivially_drop]
+pub struct LayeredHashMap(Gc<LayeredHashMapInternals>);
-impl<V: Trace + 'static> LayeredHashMap<V> {
- pub fn extend(self, new_layer: FxHashMap<IStr, V>) -> Self {
+impl LayeredHashMap {
+ pub fn extend(self, new_layer: FxHashMap<IStr, LazyVal>) -> Self {
Self(Gc::new(LayeredHashMapInternals {
parent: Some(self),
current: new_layer,
}))
}
- pub fn get(&self, key: &IStr) -> Option<&V> {
+ pub fn get(&self, key: &IStr) -> Option<&LazyVal> {
(self.0)
.current
.get(key)
@@ -34,13 +31,13 @@
}
}
-impl<V: Trace + 'static> Clone for LayeredHashMap<V> {
+impl Clone for LayeredHashMap {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
-impl<V: Trace + 'static> Default for LayeredHashMap<V> {
+impl Default for LayeredHashMap {
fn default() -> Self {
Self(Gc::new(LayeredHashMapInternals {
parent: None,
crates/jrsonnet-evaluator/src/native.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/native.rs
+++ b/crates/jrsonnet-evaluator/src/native.rs
@@ -1,7 +1,7 @@
#![allow(clippy::type_complexity)]
use crate::{error::Result, Val};
-use gc::{Finalize, Trace};
+use jrsonnet_gc::Trace;
use jrsonnet_parser::ParamsDesc;
use std::fmt::Debug;
use std::path::Path;
@@ -11,7 +11,8 @@
fn call(&self, from: Option<Rc<Path>>, args: &[Val]) -> Result<Val>;
}
-#[derive(Trace, Finalize)]
+#[derive(Trace)]
+#[trivially_drop]
pub struct NativeCallback {
pub params: ParamsDesc,
handler: Box<dyn NativeCallbackHandler>,
crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj.rs
+++ b/crates/jrsonnet-evaluator/src/obj.rs
@@ -1,12 +1,13 @@
use crate::{evaluate_add_op, LazyBinding, Result, Val};
-use gc::{Finalize, Gc, GcCell, Trace};
+use jrsonnet_gc::{Gc, GcCell, Trace};
use jrsonnet_interner::IStr;
use jrsonnet_parser::{ExprLocation, Visibility};
use rustc_hash::{FxHashMap, FxHashSet};
use std::hash::{Hash, Hasher};
use std::{fmt::Debug, hash::BuildHasherDefault};
-#[derive(Debug, Trace, Finalize)]
+#[derive(Debug, Trace)]
+#[trivially_drop]
pub struct ObjMember {
pub add: bool,
pub visibility: Visibility,
@@ -20,7 +21,8 @@
// Field => This
type CacheKey = (IStr, ObjValue);
-#[derive(Trace, Finalize)]
+#[derive(Trace)]
+#[trivially_drop]
pub struct ObjValueInternals {
super_obj: Option<ObjValue>,
assertions: Gc<Vec<Box<dyn ObjectAssertion>>>,
@@ -30,7 +32,8 @@
value_cache: GcCell<FxHashMap<CacheKey, Option<Val>>>,
}
-#[derive(Clone, Trace, Finalize)]
+#[derive(Clone, Trace)]
+#[trivially_drop]
pub struct ObjValue(pub(crate) Gc<ObjValueInternals>);
impl Debug for ObjValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
crates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/typed.rs
+++ b/crates/jrsonnet-evaluator/src/typed.rs
@@ -4,7 +4,7 @@
error::{Error, LocError, Result},
push, Val,
};
-use gc::{Finalize, Trace};
+use jrsonnet_gc::Trace;
use jrsonnet_parser::ExprLocation;
use jrsonnet_types::{ComplexValType, ValType};
use thiserror::Error;
@@ -21,7 +21,8 @@
}};
}
-#[derive(Debug, Error, Clone, Trace, Finalize)]
+#[derive(Debug, Error, Clone, Trace)]
+#[trivially_drop]
pub enum TypeError {
#[error("expected {0}, got {1}")]
ExpectedGot(ComplexValType, ValType),
@@ -38,7 +39,8 @@
}
}
-#[derive(Debug, Clone, Trace, Finalize)]
+#[derive(Debug, Clone, Trace)]
+#[trivially_drop]
pub struct TypeLocError(Box<TypeError>, ValuePathStack);
impl From<TypeError> for TypeLocError {
fn from(e: TypeError) -> Self {
@@ -60,7 +62,8 @@
}
}
-#[derive(Debug, Clone, Trace, Finalize)]
+#[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 {
@@ -123,7 +126,8 @@
}
}
-#[derive(Clone, Debug, Trace, Finalize)]
+#[derive(Clone, Debug, Trace)]
+#[trivially_drop]
enum ValuePathItem {
Field(Rc<str>),
Index(u64),
@@ -138,7 +142,8 @@
}
}
-#[derive(Clone, Debug, Trace, Finalize)]
+#[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 {
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth1use crate::{2 builtin::{3 call_builtin,4 manifest::{manifest_json_ex, ManifestJsonOptions, ManifestType},5 },6 error::{Error::*, LocError},7 evaluate,8 function::{parse_function_call, parse_function_call_map, place_args},9 native::NativeCallback,10 throw, with_state, Context, ObjValue, Result,11};12use gc::{custom_trace, Finalize, Gc, GcCell, Trace};13use jrsonnet_interner::IStr;14use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, ExprLocation, LiteralType, LocExpr, ParamsDesc};15use jrsonnet_types::ValType;16use std::{collections::HashMap, fmt::Debug, rc::Rc};1718pub trait LazyValValue: Trace {19 fn get(self: Box<Self>) -> Result<Val>;20}2122enum LazyValInternals {23 Computed(Val),24 Errored(LocError),25 Waiting(Box<dyn LazyValValue>),26 Pending,27}28impl Finalize for LazyValInternals {}29unsafe impl Trace for LazyValInternals {30 custom_trace!(this, {31 match &this {32 LazyValInternals::Computed(v) => mark(v),33 LazyValInternals::Errored(e) => mark(e),34 LazyValInternals::Waiting(w) => mark(w),35 LazyValInternals::Pending => {}36 }37 });38}3940#[derive(Clone, Trace, Finalize)]41pub struct LazyVal(Gc<GcCell<LazyValInternals>>);42impl LazyVal {43 pub fn new(f: Box<dyn LazyValValue>) -> Self {44 Self(Gc::new(GcCell::new(LazyValInternals::Waiting(f))))45 }46 pub fn new_resolved(val: Val) -> Self {47 Self(Gc::new(GcCell::new(LazyValInternals::Computed(val))))48 }49 pub fn evaluate(&self) -> Result<Val> {50 match &*self.0.borrow() {51 LazyValInternals::Computed(v) => return Ok(v.clone()),52 LazyValInternals::Errored(e) => return Err(e.clone()),53 LazyValInternals::Pending => return Err(RecursiveLazyValueEvaluation.into()),54 _ => (),55 };56 let value = if let LazyValInternals::Waiting(value) =57 std::mem::replace(&mut *self.0.borrow_mut(), LazyValInternals::Pending)58 {59 value60 } else {61 unreachable!()62 };63 let new_value = match value.get() {64 Ok(v) => v,65 Err(e) => {66 *self.0.borrow_mut() = LazyValInternals::Errored(e.clone());67 return Err(e);68 }69 };70 *self.0.borrow_mut() = LazyValInternals::Computed(new_value.clone());71 Ok(new_value)72 }73}7475impl Debug for LazyVal {76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {77 write!(f, "Lazy")78 }79}80impl PartialEq for LazyVal {81 fn eq(&self, other: &Self) -> bool {82 Gc::ptr_eq(&self.0, &other.0)83 }84}8586#[derive(Debug, PartialEq, Trace, Finalize)]87pub struct FuncDesc {88 pub name: IStr,89 pub ctx: Context,90 pub params: ParamsDesc,91 pub body: LocExpr,92}9394#[derive(Debug, Trace, Finalize)]95pub enum FuncVal {96 /// Plain function implemented in jsonnet97 Normal(FuncDesc),98 /// Standard library function99 Intrinsic(IStr),100 /// Library functions implemented in native101 NativeExt(IStr, Gc<NativeCallback>),102}103104impl PartialEq for FuncVal {105 fn eq(&self, other: &Self) -> bool {106 match (self, other) {107 (Self::Normal(a), Self::Normal(b)) => a == b,108 (Self::Intrinsic(an), Self::Intrinsic(bn)) => an == bn,109 (Self::NativeExt(an, _), Self::NativeExt(bn, _)) => an == bn,110 (..) => false,111 }112 }113}114impl FuncVal {115 pub fn is_ident(&self) -> bool {116 matches!(&self, Self::Intrinsic(n) if n as &str == "id")117 }118 pub fn name(&self) -> IStr {119 match self {120 Self::Normal(normal) => normal.name.clone(),121 Self::Intrinsic(name) => format!("std.{}", name).into(),122 Self::NativeExt(n, _) => format!("native.{}", n).into(),123 }124 }125 pub fn evaluate(126 &self,127 call_ctx: Context,128 loc: Option<&ExprLocation>,129 args: &ArgsDesc,130 tailstrict: bool,131 ) -> Result<Val> {132 match self {133 Self::Normal(func) => {134 let ctx = parse_function_call(135 call_ctx,136 Some(func.ctx.clone()),137 &func.params,138 args,139 tailstrict,140 )?;141 evaluate(ctx, &func.body)142 }143 Self::Intrinsic(name) => call_builtin(call_ctx, loc, name, args),144 Self::NativeExt(_name, handler) => {145 let args = parse_function_call(call_ctx, None, &handler.params, args, true)?;146 let mut out_args = Vec::with_capacity(handler.params.len());147 for p in handler.params.0.iter() {148 out_args.push(args.binding(p.0.clone())?.evaluate()?);149 }150 Ok(handler.call(loc.map(|l| l.0.clone()), &out_args)?)151 }152 }153 }154155 pub fn evaluate_map(156 &self,157 call_ctx: Context,158 args: &HashMap<IStr, Val>,159 tailstrict: bool,160 ) -> Result<Val> {161 match self {162 Self::Normal(func) => {163 let ctx = parse_function_call_map(164 call_ctx,165 Some(func.ctx.clone()),166 &func.params,167 args,168 tailstrict,169 )?;170 evaluate(ctx, &func.body)171 }172 Self::Intrinsic(_) => todo!(),173 Self::NativeExt(_, _) => todo!(),174 }175 }176177 pub fn evaluate_values(&self, call_ctx: Context, args: &[Val]) -> Result<Val> {178 match self {179 Self::Normal(func) => {180 let ctx = place_args(call_ctx, Some(func.ctx.clone()), &func.params, args)?;181 evaluate(ctx, &func.body)182 }183 Self::Intrinsic(_) => todo!(),184 Self::NativeExt(_, _) => todo!(),185 }186 }187}188189#[derive(Clone)]190pub enum ManifestFormat {191 YamlStream(Box<ManifestFormat>),192 Yaml(usize),193 Json(usize),194 ToString,195 String,196}197198#[derive(Debug, Clone)]199pub enum ArrValue {200 Lazy(Gc<Vec<LazyVal>>),201 Eager(Gc<Vec<Val>>),202 Extended(Box<(Self, Self)>),203}204impl Finalize for ArrValue {}205unsafe impl Trace for ArrValue {206 custom_trace!(this, {207 match &this {208 ArrValue::Lazy(l) => mark(l),209 ArrValue::Eager(e) => mark(e),210 ArrValue::Extended(x) => mark(x),211 }212 });213}214impl ArrValue {215 pub fn new_eager() -> Self {216 Self::Eager(Gc::new(Vec::new()))217 }218219 pub fn len(&self) -> usize {220 match self {221 Self::Lazy(l) => l.len(),222 Self::Eager(e) => e.len(),223 Self::Extended(v) => v.0.len() + v.1.len(),224 }225 }226227 pub fn is_empty(&self) -> bool {228 self.len() == 0229 }230231 pub fn get(&self, index: usize) -> Result<Option<Val>> {232 match self {233 Self::Lazy(vec) => {234 if let Some(v) = vec.get(index) {235 Ok(Some(v.evaluate()?))236 } else {237 Ok(None)238 }239 }240 Self::Eager(vec) => Ok(vec.get(index).cloned()),241 Self::Extended(v) => {242 let a_len = v.0.len();243 if a_len > index {244 v.0.get(index)245 } else {246 v.1.get(index - a_len)247 }248 }249 }250 }251252 pub fn get_lazy(&self, index: usize) -> Option<LazyVal> {253 match self {254 Self::Lazy(vec) => vec.get(index).cloned(),255 Self::Eager(vec) => vec.get(index).cloned().map(LazyVal::new_resolved),256 Self::Extended(v) => {257 let a_len = v.0.len();258 if a_len > index {259 v.0.get_lazy(index)260 } else {261 v.1.get_lazy(index - a_len)262 }263 }264 }265 }266267 pub fn evaluated(&self) -> Result<Gc<Vec<Val>>> {268 Ok(match self {269 Self::Lazy(vec) => {270 let mut out = Vec::with_capacity(vec.len());271 for item in vec.iter() {272 out.push(item.evaluate()?);273 }274 Gc::new(out)275 }276 Self::Eager(vec) => vec.clone(),277 Self::Extended(_v) => {278 let mut out = Vec::with_capacity(self.len());279 for item in self.iter() {280 out.push(item?);281 }282 Gc::new(out)283 }284 })285 }286287 pub fn iter(&self) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {288 (0..self.len()).map(move |idx| match self {289 Self::Lazy(l) => l[idx].evaluate(),290 Self::Eager(e) => Ok(e[idx].clone()),291 Self::Extended(_) => self.get(idx).map(|e| e.unwrap()),292 })293 }294295 pub fn iter_lazy(&self) -> impl DoubleEndedIterator<Item = LazyVal> + '_ {296 (0..self.len()).map(move |idx| match self {297 Self::Lazy(l) => l[idx].clone(),298 Self::Eager(e) => LazyVal::new_resolved(e[idx].clone()),299 Self::Extended(_) => self.get_lazy(idx).unwrap(),300 })301 }302303 pub fn reversed(self) -> Self {304 match self {305 Self::Lazy(vec) => {306 let mut out = (&vec as &Vec<_>).clone();307 out.reverse();308 Self::Lazy(Gc::new(out))309 }310 Self::Eager(vec) => {311 let mut out = (&vec as &Vec<_>).clone();312 out.reverse();313 Self::Eager(Gc::new(out))314 }315 Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),316 }317 }318319 pub fn map(self, mapper: impl Fn(Val) -> Result<Val>) -> Result<Self> {320 let mut out = Vec::with_capacity(self.len());321322 for value in self.iter() {323 out.push(mapper(value?)?);324 }325326 Ok(Self::Eager(Gc::new(out)))327 }328329 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {330 let mut out = Vec::with_capacity(self.len());331332 for value in self.iter() {333 let value = value?;334 if filter(&value)? {335 out.push(value);336 }337 }338339 Ok(Self::Eager(Gc::new(out)))340 }341342 pub fn ptr_eq(a: &Self, b: &Self) -> bool {343 match (a, b) {344 (Self::Lazy(a), Self::Lazy(b)) => Gc::ptr_eq(a, b),345 (Self::Eager(a), Self::Eager(b)) => Gc::ptr_eq(a, b),346 _ => false,347 }348 }349}350351impl From<Vec<LazyVal>> for ArrValue {352 fn from(v: Vec<LazyVal>) -> Self {353 Self::Lazy(Gc::new(v))354 }355}356357impl From<Vec<Val>> for ArrValue {358 fn from(v: Vec<Val>) -> Self {359 Self::Eager(Gc::new(v))360 }361}362363#[derive(Debug)]364pub struct DebugGcTraceValue {365 name: IStr,366 pub value: Box<Val>,367}368impl DebugGcTraceValue {369 fn print(&self, action: &str) {370 println!("{} {}#{:?}", action, self.name, &*self.value as *const _)371 }372}373impl Finalize for DebugGcTraceValue {374 fn finalize(&self) {375 self.print("Garbage-collecting")376 }377}378impl Drop for DebugGcTraceValue {379 fn drop(&mut self) {380 self.print("Garbage-collected")381 }382}383unsafe impl Trace for DebugGcTraceValue {384 unsafe fn trace(&self) {385 self.print("Traced");386 self.value.trace()387 }388 unsafe fn root(&self) {389 self.print("Rooted");390 self.value.root()391 }392 unsafe fn unroot(&self) {393 self.print("Unrooted");394 self.value.unroot()395 }396 fn finalize_glue(&self) {397 Finalize::finalize(self)398 }399}400impl Clone for DebugGcTraceValue {401 fn clone(&self) -> Self {402 self.print("Cloned");403 let value = Self {404 name: self.name.clone(),405 value: self.value.clone(),406 };407 value.print("I'm clone");408 value409 }410}411impl DebugGcTraceValue {412 pub fn create(name: IStr, value: Val) -> Val {413 let value = Self {414 name,415 value: Box::new(value),416 };417 value.print("Constructed");418 Val::DebugGcTraceValue(value)419 }420}421422#[derive(Debug, Clone)]423pub enum Val {424 Bool(bool),425 Null,426 Str(IStr),427 Num(f64),428 Arr(ArrValue),429 Obj(ObjValue),430 Func(Gc<FuncVal>),431 DebugGcTraceValue(DebugGcTraceValue),432}433impl Finalize for Val {}434unsafe impl Trace for Val {435 custom_trace!(this, {436 match &this {437 Val::Bool(_) => {}438 Val::Null => {}439 Val::Str(_) => {}440 Val::Num(_) => {}441 Val::Arr(a) => mark(a),442 Val::Obj(o) => mark(o),443 Val::Func(f) => mark(f),444 Val::DebugGcTraceValue(v) => mark(v),445 }446 });447}448449macro_rules! matches_unwrap {450 ($e: expr, $p: pat, $r: expr) => {451 match $e {452 $p => $r,453 _ => panic!("no match"),454 }455 };456}457impl Val {458 /// Creates `Val::Num` after checking for numeric overflow.459 /// As numbers are `f64`, we can just check for their finity.460 pub fn new_checked_num(num: f64) -> Result<Self> {461 if num.is_finite() {462 Ok(Self::Num(num))463 } else {464 throw!(RuntimeError("overflow".into()))465 }466 }467468 pub fn assert_type(&self, context: &'static str, val_type: ValType) -> Result<()> {469 let this_type = self.value_type();470 if this_type != val_type {471 throw!(TypeMismatch(context, vec![val_type], this_type))472 } else {473 Ok(())474 }475 }476 pub fn unwrap_num(self) -> Result<f64> {477 Ok(matches_unwrap!(self, Self::Num(v), v))478 }479 pub fn unwrap_func(self) -> Result<Gc<FuncVal>> {480 Ok(matches_unwrap!(self, Self::Func(v), v))481 }482 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {483 self.assert_type(context, ValType::Bool)?;484 Ok(matches_unwrap!(self, Self::Bool(v), v))485 }486 pub fn try_cast_str(self, context: &'static str) -> Result<IStr> {487 self.assert_type(context, ValType::Str)?;488 Ok(matches_unwrap!(self, Self::Str(v), v))489 }490 pub fn try_cast_num(self, context: &'static str) -> Result<f64> {491 self.assert_type(context, ValType::Num)?;492 self.unwrap_num()493 }494 pub const fn value_type(&self) -> ValType {495 match self {496 Self::Str(..) => ValType::Str,497 Self::Num(..) => ValType::Num,498 Self::Arr(..) => ValType::Arr,499 Self::Obj(..) => ValType::Obj,500 Self::Bool(_) => ValType::Bool,501 Self::Null => ValType::Null,502 Self::Func(..) => ValType::Func,503 Self::DebugGcTraceValue(v) => v.value.value_type(),504 }505 }506507 pub fn to_string(&self) -> Result<IStr> {508 Ok(match self {509 Self::Bool(true) => "true".into(),510 Self::Bool(false) => "false".into(),511 Self::Null => "null".into(),512 Self::Str(s) => s.clone(),513 v => manifest_json_ex(514 v,515 &ManifestJsonOptions {516 padding: "",517 mtype: ManifestType::ToString,518 },519 )?520 .into(),521 })522 }523524 /// Expects value to be object, outputs (key, manifested value) pairs525 pub fn manifest_multi(&self, ty: &ManifestFormat) -> Result<Vec<(IStr, IStr)>> {526 let obj = match self {527 Self::Obj(obj) => obj,528 _ => throw!(MultiManifestOutputIsNotAObject),529 };530 let keys = obj.fields();531 let mut out = Vec::with_capacity(keys.len());532 for key in keys {533 let value = obj534 .get(key.clone())?535 .expect("item in object")536 .manifest(ty)?;537 out.push((key, value));538 }539 Ok(out)540 }541542 /// Expects value to be array, outputs manifested values543 pub fn manifest_stream(&self, ty: &ManifestFormat) -> Result<Vec<IStr>> {544 let arr = match self {545 Self::Arr(a) => a,546 _ => throw!(StreamManifestOutputIsNotAArray),547 };548 let mut out = Vec::with_capacity(arr.len());549 for i in arr.iter() {550 out.push(i?.manifest(ty)?);551 }552 Ok(out)553 }554555 pub fn manifest(&self, ty: &ManifestFormat) -> Result<IStr> {556 Ok(match ty {557 ManifestFormat::YamlStream(format) => {558 let arr = match self {559 Self::Arr(a) => a,560 _ => throw!(StreamManifestOutputIsNotAArray),561 };562 let mut out = String::new();563564 match format as &ManifestFormat {565 ManifestFormat::YamlStream(_) => throw!(StreamManifestOutputCannotBeRecursed),566 ManifestFormat::String => throw!(StreamManifestCannotNestString),567 _ => {}568 };569570 if !arr.is_empty() {571 for v in arr.iter() {572 out.push_str("---\n");573 out.push_str(&v?.manifest(format)?);574 out.push('\n');575 }576 out.push_str("...");577 }578579 out.into()580 }581 ManifestFormat::Yaml(padding) => self.to_yaml(*padding)?,582 ManifestFormat::Json(padding) => self.to_json(*padding)?,583 ManifestFormat::ToString => self.to_string()?,584 ManifestFormat::String => match self {585 Self::Str(s) => s.clone(),586 _ => throw!(StringManifestOutputIsNotAString),587 },588 })589 }590591 /// For manifestification592 pub fn to_json(&self, padding: usize) -> Result<IStr> {593 manifest_json_ex(594 self,595 &ManifestJsonOptions {596 padding: &" ".repeat(padding),597 mtype: if padding == 0 {598 ManifestType::Minify599 } else {600 ManifestType::Manifest601 },602 },603 )604 .map(|s| s.into())605 }606607 /// Calls `std.manifestJson`608 #[cfg(feature = "faster")]609 pub fn to_std_json(&self, padding: usize) -> Result<Rc<str>> {610 manifest_json_ex(611 self,612 &ManifestJsonOptions {613 padding: &" ".repeat(padding),614 mtype: ManifestType::Std,615 },616 )617 .map(|s| s.into())618 }619620 /// Calls `std.manifestJson`621 #[cfg(not(feature = "faster"))]622 pub fn to_std_json(&self, padding: usize) -> Result<Rc<str>> {623 with_state(|s| {624 let ctx = s625 .create_default_context()?626 .with_var("__tmp__to_json__".into(), self.clone())?;627 Ok(evaluate(628 ctx,629 &el!(Expr::Apply(630 el!(Expr::Index(631 el!(Expr::Var("std".into())),632 el!(Expr::Str("manifestJsonEx".into()))633 )),634 ArgsDesc(vec![635 Arg(None, el!(Expr::Var("__tmp__to_json__".into()))),636 Arg(None, el!(Expr::Str(" ".repeat(padding).into())))637 ]),638 false639 )),640 )?641 .try_cast_str("to json")?)642 })643 }644 pub fn to_yaml(&self, padding: usize) -> Result<IStr> {645 with_state(|s| {646 let ctx = s647 .create_default_context()648 .with_var("__tmp__to_json__".into(), self.clone());649 evaluate(650 ctx,651 &el!(Expr::Apply(652 el!(Expr::Index(653 el!(Expr::Var("std".into())),654 el!(Expr::Str("manifestYamlDoc".into()))655 )),656 ArgsDesc(vec![657 Arg(None, el!(Expr::Var("__tmp__to_json__".into()))),658 Arg(659 None,660 el!(Expr::Literal(if padding != 0 {661 LiteralType::True662 } else {663 LiteralType::False664 }))665 )666 ]),667 false668 )),669 )?670 .try_cast_str("to json")671 })672 }673}674675const fn is_function_like(val: &Val) -> bool {676 matches!(val, Val::Func(_))677}678679/// Native implementation of `std.primitiveEquals`680pub fn primitive_equals(val_a: &Val, val_b: &Val) -> Result<bool> {681 Ok(match (val_a, val_b) {682 (Val::Bool(a), Val::Bool(b)) => a == b,683 (Val::Null, Val::Null) => true,684 (Val::Str(a), Val::Str(b)) => a == b,685 (Val::Num(a), Val::Num(b)) => (a - b).abs() <= f64::EPSILON,686 (Val::Arr(_), Val::Arr(_)) => throw!(RuntimeError(687 "primitiveEquals operates on primitive types, got array".into(),688 )),689 (Val::Obj(_), Val::Obj(_)) => throw!(RuntimeError(690 "primitiveEquals operates on primitive types, got object".into(),691 )),692 (a, b) if is_function_like(a) && is_function_like(b) => {693 throw!(RuntimeError("cannot test equality of functions".into()))694 }695 (_, _) => false,696 })697}698699/// Native implementation of `std.equals`700pub fn equals(val_a: &Val, val_b: &Val) -> Result<bool> {701 if val_a.value_type() != val_b.value_type() {702 return Ok(false);703 }704 match (val_a, val_b) {705 (Val::Arr(a), Val::Arr(b)) => {706 if ArrValue::ptr_eq(a, b) {707 return Ok(true);708 }709 if a.len() != b.len() {710 return Ok(false);711 }712 for (a, b) in a.iter().zip(b.iter()) {713 if !equals(&a?, &b?)? {714 return Ok(false);715 }716 }717 Ok(true)718 }719 (Val::Obj(a), Val::Obj(b)) => {720 if ObjValue::ptr_eq(a, b) {721 return Ok(true);722 }723 let fields = a.fields();724 if fields != b.fields() {725 return Ok(false);726 }727 for field in fields {728 if !equals(&a.get(field.clone())?.unwrap(), &b.get(field)?.unwrap())? {729 return Ok(false);730 }731 }732 Ok(true)733 }734 (a, b) => Ok(primitive_equals(a, b)?),735 }736}1use crate::{2 builtin::{3 call_builtin,4 manifest::{manifest_json_ex, ManifestJsonOptions, ManifestType},5 },6 error::{Error::*, LocError},7 evaluate,8 function::{parse_function_call, parse_function_call_map, place_args},9 native::NativeCallback,10 throw, with_state, Context, ObjValue, Result,11};12use jrsonnet_gc::{Finalize, Gc, GcCell, Trace};13use jrsonnet_interner::IStr;14use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, ExprLocation, LiteralType, LocExpr, ParamsDesc};15use jrsonnet_types::ValType;16use std::{collections::HashMap, fmt::Debug, rc::Rc};1718pub trait LazyValValue: Trace {19 fn get(self: Box<Self>) -> Result<Val>;20}2122#[derive(Trace)]23#[trivially_drop]24enum LazyValInternals {25 Computed(Val),26 Errored(LocError),27 Waiting(Box<dyn LazyValValue>),28 Pending,29}3031#[derive(Clone, Trace)]32#[trivially_drop]33pub struct LazyVal(Gc<GcCell<LazyValInternals>>);34impl LazyVal {35 pub fn new(f: Box<dyn LazyValValue>) -> Self {36 Self(Gc::new(GcCell::new(LazyValInternals::Waiting(f))))37 }38 pub fn new_resolved(val: Val) -> Self {39 Self(Gc::new(GcCell::new(LazyValInternals::Computed(val))))40 }41 pub fn evaluate(&self) -> Result<Val> {42 match &*self.0.borrow() {43 LazyValInternals::Computed(v) => return Ok(v.clone()),44 LazyValInternals::Errored(e) => return Err(e.clone()),45 LazyValInternals::Pending => return Err(RecursiveLazyValueEvaluation.into()),46 _ => (),47 };48 let value = if let LazyValInternals::Waiting(value) =49 std::mem::replace(&mut *self.0.borrow_mut(), LazyValInternals::Pending)50 {51 value52 } else {53 unreachable!()54 };55 let new_value = match value.get() {56 Ok(v) => v,57 Err(e) => {58 *self.0.borrow_mut() = LazyValInternals::Errored(e.clone());59 return Err(e);60 }61 };62 *self.0.borrow_mut() = LazyValInternals::Computed(new_value.clone());63 Ok(new_value)64 }65}6667impl Debug for LazyVal {68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {69 write!(f, "Lazy")70 }71}72impl PartialEq for LazyVal {73 fn eq(&self, other: &Self) -> bool {74 Gc::ptr_eq(&self.0, &other.0)75 }76}7778#[derive(Debug, PartialEq, Trace)]79#[trivially_drop]80pub struct FuncDesc {81 pub name: IStr,82 pub ctx: Context,83 pub params: ParamsDesc,84 pub body: LocExpr,85}8687#[derive(Debug, Trace)]88#[trivially_drop]89pub enum FuncVal {90 /// Plain function implemented in jsonnet91 Normal(FuncDesc),92 /// Standard library function93 Intrinsic(IStr),94 /// Library functions implemented in native95 NativeExt(IStr, Gc<NativeCallback>),96}9798impl PartialEq for FuncVal {99 fn eq(&self, other: &Self) -> bool {100 match (self, other) {101 (Self::Normal(a), Self::Normal(b)) => a == b,102 (Self::Intrinsic(an), Self::Intrinsic(bn)) => an == bn,103 (Self::NativeExt(an, _), Self::NativeExt(bn, _)) => an == bn,104 (..) => false,105 }106 }107}108impl FuncVal {109 pub fn is_ident(&self) -> bool {110 matches!(&self, Self::Intrinsic(n) if n as &str == "id")111 }112 pub fn name(&self) -> IStr {113 match self {114 Self::Normal(normal) => normal.name.clone(),115 Self::Intrinsic(name) => format!("std.{}", name).into(),116 Self::NativeExt(n, _) => format!("native.{}", n).into(),117 }118 }119 pub fn evaluate(120 &self,121 call_ctx: Context,122 loc: Option<&ExprLocation>,123 args: &ArgsDesc,124 tailstrict: bool,125 ) -> Result<Val> {126 match self {127 Self::Normal(func) => {128 let ctx = parse_function_call(129 call_ctx,130 Some(func.ctx.clone()),131 &func.params,132 args,133 tailstrict,134 )?;135 evaluate(ctx, &func.body)136 }137 Self::Intrinsic(name) => call_builtin(call_ctx, loc, name, args),138 Self::NativeExt(_name, handler) => {139 let args = parse_function_call(call_ctx, None, &handler.params, args, true)?;140 let mut out_args = Vec::with_capacity(handler.params.len());141 for p in handler.params.0.iter() {142 out_args.push(args.binding(p.0.clone())?.evaluate()?);143 }144 Ok(handler.call(loc.map(|l| l.0.clone()), &out_args)?)145 }146 }147 }148149 pub fn evaluate_map(150 &self,151 call_ctx: Context,152 args: &HashMap<IStr, Val>,153 tailstrict: bool,154 ) -> Result<Val> {155 match self {156 Self::Normal(func) => {157 let ctx = parse_function_call_map(158 call_ctx,159 Some(func.ctx.clone()),160 &func.params,161 args,162 tailstrict,163 )?;164 evaluate(ctx, &func.body)165 }166 Self::Intrinsic(_) => todo!(),167 Self::NativeExt(_, _) => todo!(),168 }169 }170171 pub fn evaluate_values(&self, call_ctx: Context, args: &[Val]) -> Result<Val> {172 match self {173 Self::Normal(func) => {174 let ctx = place_args(call_ctx, Some(func.ctx.clone()), &func.params, args)?;175 evaluate(ctx, &func.body)176 }177 Self::Intrinsic(_) => todo!(),178 Self::NativeExt(_, _) => todo!(),179 }180 }181}182183#[derive(Clone)]184pub enum ManifestFormat {185 YamlStream(Box<ManifestFormat>),186 Yaml(usize),187 Json(usize),188 ToString,189 String,190}191192#[derive(Debug, Clone, Trace)]193#[trivially_drop]194pub enum ArrValue {195 Lazy(Gc<Vec<LazyVal>>),196 Eager(Gc<Vec<Val>>),197 Extended(Box<(Self, Self)>),198}199impl ArrValue {200 pub fn new_eager() -> Self {201 Self::Eager(Gc::new(Vec::new()))202 }203204 pub fn len(&self) -> usize {205 match self {206 Self::Lazy(l) => l.len(),207 Self::Eager(e) => e.len(),208 Self::Extended(v) => v.0.len() + v.1.len(),209 }210 }211212 pub fn is_empty(&self) -> bool {213 self.len() == 0214 }215216 pub fn get(&self, index: usize) -> Result<Option<Val>> {217 match self {218 Self::Lazy(vec) => {219 if let Some(v) = vec.get(index) {220 Ok(Some(v.evaluate()?))221 } else {222 Ok(None)223 }224 }225 Self::Eager(vec) => Ok(vec.get(index).cloned()),226 Self::Extended(v) => {227 let a_len = v.0.len();228 if a_len > index {229 v.0.get(index)230 } else {231 v.1.get(index - a_len)232 }233 }234 }235 }236237 pub fn get_lazy(&self, index: usize) -> Option<LazyVal> {238 match self {239 Self::Lazy(vec) => vec.get(index).cloned(),240 Self::Eager(vec) => vec.get(index).cloned().map(LazyVal::new_resolved),241 Self::Extended(v) => {242 let a_len = v.0.len();243 if a_len > index {244 v.0.get_lazy(index)245 } else {246 v.1.get_lazy(index - a_len)247 }248 }249 }250 }251252 pub fn evaluated(&self) -> Result<Gc<Vec<Val>>> {253 Ok(match self {254 Self::Lazy(vec) => {255 let mut out = Vec::with_capacity(vec.len());256 for item in vec.iter() {257 out.push(item.evaluate()?);258 }259 Gc::new(out)260 }261 Self::Eager(vec) => vec.clone(),262 Self::Extended(_v) => {263 let mut out = Vec::with_capacity(self.len());264 for item in self.iter() {265 out.push(item?);266 }267 Gc::new(out)268 }269 })270 }271272 pub fn iter(&self) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {273 (0..self.len()).map(move |idx| match self {274 Self::Lazy(l) => l[idx].evaluate(),275 Self::Eager(e) => Ok(e[idx].clone()),276 Self::Extended(_) => self.get(idx).map(|e| e.unwrap()),277 })278 }279280 pub fn iter_lazy(&self) -> impl DoubleEndedIterator<Item = LazyVal> + '_ {281 (0..self.len()).map(move |idx| match self {282 Self::Lazy(l) => l[idx].clone(),283 Self::Eager(e) => LazyVal::new_resolved(e[idx].clone()),284 Self::Extended(_) => self.get_lazy(idx).unwrap(),285 })286 }287288 pub fn reversed(self) -> Self {289 match self {290 Self::Lazy(vec) => {291 let mut out = (&vec as &Vec<_>).clone();292 out.reverse();293 Self::Lazy(Gc::new(out))294 }295 Self::Eager(vec) => {296 let mut out = (&vec as &Vec<_>).clone();297 out.reverse();298 Self::Eager(Gc::new(out))299 }300 Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),301 }302 }303304 pub fn map(self, mapper: impl Fn(Val) -> Result<Val>) -> Result<Self> {305 let mut out = Vec::with_capacity(self.len());306307 for value in self.iter() {308 out.push(mapper(value?)?);309 }310311 Ok(Self::Eager(Gc::new(out)))312 }313314 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {315 let mut out = Vec::with_capacity(self.len());316317 for value in self.iter() {318 let value = value?;319 if filter(&value)? {320 out.push(value);321 }322 }323324 Ok(Self::Eager(Gc::new(out)))325 }326327 pub fn ptr_eq(a: &Self, b: &Self) -> bool {328 match (a, b) {329 (Self::Lazy(a), Self::Lazy(b)) => Gc::ptr_eq(a, b),330 (Self::Eager(a), Self::Eager(b)) => Gc::ptr_eq(a, b),331 _ => false,332 }333 }334}335336impl From<Vec<LazyVal>> for ArrValue {337 fn from(v: Vec<LazyVal>) -> Self {338 Self::Lazy(Gc::new(v))339 }340}341342impl From<Vec<Val>> for ArrValue {343 fn from(v: Vec<Val>) -> Self {344 Self::Eager(Gc::new(v))345 }346}347348#[derive(Debug)]349pub struct DebugGcTraceValue {350 name: IStr,351 pub value: Box<Val>,352}353impl DebugGcTraceValue {354 fn print(&self, action: &str) {355 println!("{} {}#{:?}", action, self.name, &*self.value as *const _)356 }357}358impl Finalize for DebugGcTraceValue {359 fn finalize(&self) {360 self.print("Garbage-collecting")361 }362}363impl Drop for DebugGcTraceValue {364 fn drop(&mut self) {365 self.print("Garbage-collected")366 }367}368unsafe impl Trace for DebugGcTraceValue {369 unsafe fn trace(&self) {370 self.print("Traced");371 self.value.trace()372 }373 unsafe fn root(&self) {374 self.print("Rooted");375 self.value.root()376 }377 unsafe fn unroot(&self) {378 self.print("Unrooted");379 self.value.unroot()380 }381 fn finalize_glue(&self) {382 Finalize::finalize(self)383 }384}385impl Clone for DebugGcTraceValue {386 fn clone(&self) -> Self {387 self.print("Cloned");388 let value = Self {389 name: self.name.clone(),390 value: self.value.clone(),391 };392 value.print("I'm clone");393 value394 }395}396impl DebugGcTraceValue {397 pub fn create(name: IStr, value: Val) -> Val {398 let value = Self {399 name,400 value: Box::new(value),401 };402 value.print("Constructed");403 Val::DebugGcTraceValue(value)404 }405}406407#[derive(Debug, Clone, Trace)]408#[trivially_drop]409pub enum Val {410 Bool(bool),411 Null,412 Str(IStr),413 Num(f64),414 Arr(ArrValue),415 Obj(ObjValue),416 Func(Gc<FuncVal>),417 DebugGcTraceValue(DebugGcTraceValue),418}419420macro_rules! matches_unwrap {421 ($e: expr, $p: pat, $r: expr) => {422 match $e {423 $p => $r,424 _ => panic!("no match"),425 }426 };427}428impl Val {429 /// Creates `Val::Num` after checking for numeric overflow.430 /// As numbers are `f64`, we can just check for their finity.431 pub fn new_checked_num(num: f64) -> Result<Self> {432 if num.is_finite() {433 Ok(Self::Num(num))434 } else {435 throw!(RuntimeError("overflow".into()))436 }437 }438439 pub fn assert_type(&self, context: &'static str, val_type: ValType) -> Result<()> {440 let this_type = self.value_type();441 if this_type != val_type {442 throw!(TypeMismatch(context, vec![val_type], this_type))443 } else {444 Ok(())445 }446 }447 pub fn unwrap_num(self) -> Result<f64> {448 Ok(matches_unwrap!(self, Self::Num(v), v))449 }450 pub fn unwrap_func(self) -> Result<Gc<FuncVal>> {451 Ok(matches_unwrap!(self, Self::Func(v), v))452 }453 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {454 self.assert_type(context, ValType::Bool)?;455 Ok(matches_unwrap!(self, Self::Bool(v), v))456 }457 pub fn try_cast_str(self, context: &'static str) -> Result<IStr> {458 self.assert_type(context, ValType::Str)?;459 Ok(matches_unwrap!(self, Self::Str(v), v))460 }461 pub fn try_cast_num(self, context: &'static str) -> Result<f64> {462 self.assert_type(context, ValType::Num)?;463 self.unwrap_num()464 }465 pub const fn value_type(&self) -> ValType {466 match self {467 Self::Str(..) => ValType::Str,468 Self::Num(..) => ValType::Num,469 Self::Arr(..) => ValType::Arr,470 Self::Obj(..) => ValType::Obj,471 Self::Bool(_) => ValType::Bool,472 Self::Null => ValType::Null,473 Self::Func(..) => ValType::Func,474 Self::DebugGcTraceValue(v) => v.value.value_type(),475 }476 }477478 pub fn to_string(&self) -> Result<IStr> {479 Ok(match self {480 Self::Bool(true) => "true".into(),481 Self::Bool(false) => "false".into(),482 Self::Null => "null".into(),483 Self::Str(s) => s.clone(),484 v => manifest_json_ex(485 v,486 &ManifestJsonOptions {487 padding: "",488 mtype: ManifestType::ToString,489 },490 )?491 .into(),492 })493 }494495 /// Expects value to be object, outputs (key, manifested value) pairs496 pub fn manifest_multi(&self, ty: &ManifestFormat) -> Result<Vec<(IStr, IStr)>> {497 let obj = match self {498 Self::Obj(obj) => obj,499 _ => throw!(MultiManifestOutputIsNotAObject),500 };501 let keys = obj.fields();502 let mut out = Vec::with_capacity(keys.len());503 for key in keys {504 let value = obj505 .get(key.clone())?506 .expect("item in object")507 .manifest(ty)?;508 out.push((key, value));509 }510 Ok(out)511 }512513 /// Expects value to be array, outputs manifested values514 pub fn manifest_stream(&self, ty: &ManifestFormat) -> Result<Vec<IStr>> {515 let arr = match self {516 Self::Arr(a) => a,517 _ => throw!(StreamManifestOutputIsNotAArray),518 };519 let mut out = Vec::with_capacity(arr.len());520 for i in arr.iter() {521 out.push(i?.manifest(ty)?);522 }523 Ok(out)524 }525526 pub fn manifest(&self, ty: &ManifestFormat) -> Result<IStr> {527 Ok(match ty {528 ManifestFormat::YamlStream(format) => {529 let arr = match self {530 Self::Arr(a) => a,531 _ => throw!(StreamManifestOutputIsNotAArray),532 };533 let mut out = String::new();534535 match format as &ManifestFormat {536 ManifestFormat::YamlStream(_) => throw!(StreamManifestOutputCannotBeRecursed),537 ManifestFormat::String => throw!(StreamManifestCannotNestString),538 _ => {}539 };540541 if !arr.is_empty() {542 for v in arr.iter() {543 out.push_str("---\n");544 out.push_str(&v?.manifest(format)?);545 out.push('\n');546 }547 out.push_str("...");548 }549550 out.into()551 }552 ManifestFormat::Yaml(padding) => self.to_yaml(*padding)?,553 ManifestFormat::Json(padding) => self.to_json(*padding)?,554 ManifestFormat::ToString => self.to_string()?,555 ManifestFormat::String => match self {556 Self::Str(s) => s.clone(),557 _ => throw!(StringManifestOutputIsNotAString),558 },559 })560 }561562 /// For manifestification563 pub fn to_json(&self, padding: usize) -> Result<IStr> {564 manifest_json_ex(565 self,566 &ManifestJsonOptions {567 padding: &" ".repeat(padding),568 mtype: if padding == 0 {569 ManifestType::Minify570 } else {571 ManifestType::Manifest572 },573 },574 )575 .map(|s| s.into())576 }577578 /// Calls `std.manifestJson`579 #[cfg(feature = "faster")]580 pub fn to_std_json(&self, padding: usize) -> Result<Rc<str>> {581 manifest_json_ex(582 self,583 &ManifestJsonOptions {584 padding: &" ".repeat(padding),585 mtype: ManifestType::Std,586 },587 )588 .map(|s| s.into())589 }590591 /// Calls `std.manifestJson`592 #[cfg(not(feature = "faster"))]593 pub fn to_std_json(&self, padding: usize) -> Result<Rc<str>> {594 with_state(|s| {595 let ctx = s596 .create_default_context()?597 .with_var("__tmp__to_json__".into(), self.clone())?;598 Ok(evaluate(599 ctx,600 &el!(Expr::Apply(601 el!(Expr::Index(602 el!(Expr::Var("std".into())),603 el!(Expr::Str("manifestJsonEx".into()))604 )),605 ArgsDesc(vec![606 Arg(None, el!(Expr::Var("__tmp__to_json__".into()))),607 Arg(None, el!(Expr::Str(" ".repeat(padding).into())))608 ]),609 false610 )),611 )?612 .try_cast_str("to json")?)613 })614 }615 pub fn to_yaml(&self, padding: usize) -> Result<IStr> {616 with_state(|s| {617 let ctx = s618 .create_default_context()619 .with_var("__tmp__to_json__".into(), self.clone());620 evaluate(621 ctx,622 &el!(Expr::Apply(623 el!(Expr::Index(624 el!(Expr::Var("std".into())),625 el!(Expr::Str("manifestYamlDoc".into()))626 )),627 ArgsDesc(vec![628 Arg(None, el!(Expr::Var("__tmp__to_json__".into()))),629 Arg(630 None,631 el!(Expr::Literal(if padding != 0 {632 LiteralType::True633 } else {634 LiteralType::False635 }))636 )637 ]),638 false639 )),640 )?641 .try_cast_str("to json")642 })643 }644}645646const fn is_function_like(val: &Val) -> bool {647 matches!(val, Val::Func(_))648}649650/// Native implementation of `std.primitiveEquals`651pub fn primitive_equals(val_a: &Val, val_b: &Val) -> Result<bool> {652 Ok(match (val_a, val_b) {653 (Val::Bool(a), Val::Bool(b)) => a == b,654 (Val::Null, Val::Null) => true,655 (Val::Str(a), Val::Str(b)) => a == b,656 (Val::Num(a), Val::Num(b)) => (a - b).abs() <= f64::EPSILON,657 (Val::Arr(_), Val::Arr(_)) => throw!(RuntimeError(658 "primitiveEquals operates on primitive types, got array".into(),659 )),660 (Val::Obj(_), Val::Obj(_)) => throw!(RuntimeError(661 "primitiveEquals operates on primitive types, got object".into(),662 )),663 (a, b) if is_function_like(a) && is_function_like(b) => {664 throw!(RuntimeError("cannot test equality of functions".into()))665 }666 (_, _) => false,667 })668}669670/// Native implementation of `std.equals`671pub fn equals(val_a: &Val, val_b: &Val) -> Result<bool> {672 if val_a.value_type() != val_b.value_type() {673 return Ok(false);674 }675 match (val_a, val_b) {676 (Val::Arr(a), Val::Arr(b)) => {677 if ArrValue::ptr_eq(a, b) {678 return Ok(true);679 }680 if a.len() != b.len() {681 return Ok(false);682 }683 for (a, b) in a.iter().zip(b.iter()) {684 if !equals(&a?, &b?)? {685 return Ok(false);686 }687 }688 Ok(true)689 }690 (Val::Obj(a), Val::Obj(b)) => {691 if ObjValue::ptr_eq(a, b) {692 return Ok(true);693 }694 let fields = a.fields();695 if fields != b.fields() {696 return Ok(false);697 }698 for field in fields {699 if !equals(&a.get(field.clone())?.unwrap(), &b.get(field)?.unwrap())? {700 return Ok(false);701 }702 }703 Ok(true)704 }705 (a, b) => Ok(primitive_equals(a, b)?),706 }707}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"
-gc = { version = "0.4.1", features = ["derive"] }
+jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
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 gc::{unsafe_empty_trace, Finalize, Trace};
+use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use std::{
crates/jrsonnet-parser/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-parser/Cargo.toml
+++ b/crates/jrsonnet-parser/Cargo.toml
@@ -18,7 +18,7 @@
unescape = "0.1.0"
serde = { version = "1.0", features = ["derive", "rc"], optional = true }
-gc = { version = "0.4.1", features = ["derive"] }
+jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
[dev-dependencies]
jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.3.8" }
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 gc::{unsafe_empty_trace, Finalize, Trace};
+use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};
use jrsonnet_interner::IStr;
#[cfg(feature = "deserialize")]
use serde::Deserialize;
@@ -13,21 +13,19 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub enum FieldName {
/// {fixed: 2}
Fixed(IStr),
/// {["dyn"+"amic"]: 3}
Dyn(LocExpr),
}
-impl Finalize for FieldName {}
-unsafe impl Trace for FieldName {
- unsafe_empty_trace!();
-}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq, Trace)]
+#[trivially_drop]
pub enum Visibility {
/// :
Normal,
@@ -36,10 +34,6 @@
/// :::
Unhide,
}
-impl Finalize for Visibility {}
-unsafe impl Trace for Visibility {
- unsafe_empty_trace!();
-}
impl Visibility {
pub fn is_visible(&self) -> bool {
@@ -49,16 +43,14 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Trace)]
+#[trivially_drop]
pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);
-impl Finalize for AssertStmt {}
-unsafe impl Trace for AssertStmt {
- unsafe_empty_trace!();
-}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub struct FieldMember {
pub name: FieldName,
pub plus: bool,
@@ -66,36 +58,26 @@
pub visibility: Visibility,
pub value: LocExpr,
}
-impl Finalize for FieldMember {}
-unsafe impl Trace for FieldMember {
- unsafe_empty_trace!();
-}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub enum Member {
Field(FieldMember),
BindStmt(BindSpec),
AssertStmt(AssertStmt),
}
-impl Finalize for Member {}
-unsafe impl Trace for Member {
- unsafe_empty_trace!();
-}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq, Trace)]
+#[trivially_drop]
pub enum UnaryOpType {
Plus,
Minus,
BitNot,
Not,
-}
-impl Finalize for UnaryOpType {}
-unsafe impl Trace for UnaryOpType {
- unsafe_empty_trace!();
}
impl Display for UnaryOpType {
@@ -116,7 +98,8 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq, Trace)]
+#[trivially_drop]
pub enum BinaryOpType {
Mul,
Div,
@@ -145,10 +128,6 @@
And,
Or,
}
-impl Finalize for BinaryOpType {}
-unsafe impl Trace for BinaryOpType {
- unsafe_empty_trace!();
-}
impl Display for BinaryOpType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -183,22 +162,22 @@
/// name, default value
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub struct Param(pub IStr, pub Option<LocExpr>);
-impl Finalize for Param {}
-unsafe impl Trace for Param {
- unsafe_empty_trace!();
-}
/// Defined function parameters
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct ParamsDesc(pub Rc<Vec<Param>>);
-impl Finalize for ParamsDesc {}
+
+/// 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>;
@@ -209,21 +188,15 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub struct Arg(pub Option<String>, pub LocExpr);
-impl Finalize for Arg {}
-unsafe impl Trace for Arg {
- unsafe_empty_trace!();
-}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub struct ArgsDesc(pub Vec<Arg>);
-impl Finalize for ArgsDesc {}
-unsafe impl Trace for ArgsDesc {
- unsafe_empty_trace!();
-}
impl Deref for ArgsDesc {
type Target = Vec<Arg>;
@@ -234,50 +207,39 @@
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, Trace)]
+#[trivially_drop]
pub struct BindSpec {
pub name: IStr,
pub params: Option<ParamsDesc>,
pub value: LocExpr,
-}
-impl Finalize for BindSpec {}
-unsafe impl Trace for BindSpec {
- unsafe_empty_trace!();
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub struct IfSpecData(pub LocExpr);
-impl Finalize for IfSpecData {}
-unsafe impl Trace for IfSpecData {
- unsafe_empty_trace!();
-}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub struct ForSpecData(pub IStr, pub LocExpr);
-impl Finalize for ForSpecData {}
-unsafe impl Trace for ForSpecData {
- unsafe_empty_trace!();
-}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub enum CompSpec {
IfSpec(IfSpecData),
ForSpec(ForSpecData),
-}
-impl Finalize for CompSpec {}
-unsafe impl Trace for CompSpec {
- unsafe_empty_trace!();
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub struct ObjComp {
pub pre_locals: Vec<BindSpec>,
pub key: LocExpr,
@@ -285,26 +247,20 @@
pub post_locals: Vec<BindSpec>,
pub compspecs: Vec<CompSpec>,
}
-impl Finalize for ObjComp {}
-unsafe impl Trace for ObjComp {
- unsafe_empty_trace!();
-}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub enum ObjBody {
MemberList(Vec<Member>),
ObjComp(ObjComp),
-}
-impl Finalize for ObjBody {}
-unsafe impl Trace for ObjBody {
- unsafe_empty_trace!();
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq, Clone, Copy)]
+#[derive(Debug, PartialEq, Clone, Copy, Trace)]
+#[trivially_drop]
pub enum LiteralType {
This,
Super,
@@ -313,26 +269,20 @@
True,
False,
}
-impl Finalize for LiteralType {}
-unsafe impl Trace for LiteralType {
- unsafe_empty_trace!();
-}
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub struct SliceDesc {
pub start: Option<LocExpr>,
pub end: Option<LocExpr>,
pub step: Option<LocExpr>,
-}
-impl Finalize for SliceDesc {}
-unsafe impl Trace for SliceDesc {
- unsafe_empty_trace!();
}
/// Syntax base
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Trace)]
+#[trivially_drop]
pub enum Expr {
Literal(LiteralType),
@@ -396,20 +346,13 @@
cond_else: Option<LocExpr>,
},
}
-impl Finalize for Expr {}
-unsafe impl Trace for Expr {
- unsafe_empty_trace!();
-}
/// file, begin offset, end offset
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-#[derive(Clone, PartialEq)]
+#[derive(Clone, PartialEq, Trace)]
+#[trivially_drop]
pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);
-impl Finalize for ExprLocation {}
-unsafe impl Trace for ExprLocation {
- unsafe_empty_trace!();
-}
impl Debug for ExprLocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -422,10 +365,12 @@
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Clone, PartialEq)]
pub struct LocExpr(pub Rc<Expr>, pub Option<ExprLocation>);
-impl Finalize for LocExpr {}
+/// Safety:
+/// AST is acyclic, and there should be no gc pointers
unsafe impl Trace for LocExpr {
unsafe_empty_trace!();
}
+impl Finalize for LocExpr {}
impl Debug for LocExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
crates/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"
-gc = { version = "0.4.1", features = ["derive"] }
+jrsonnet-gc = { version = "0.4.2", features = ["derive"] }
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 gc::{unsafe_empty_trace, Finalize, Trace};
+use jrsonnet_gc::Trace;
use std::fmt::Display;
#[macro_export]
@@ -78,7 +78,8 @@
);
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]
+#[trivially_drop]
pub enum ValType {
Bool,
Null,
@@ -87,10 +88,6 @@
Arr,
Obj,
Func,
-}
-impl Finalize for ValType {}
-unsafe impl Trace for ValType {
- unsafe_empty_trace!();
}
impl ValType {
@@ -114,7 +111,8 @@
}
}
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, Trace)]
+#[trivially_drop]
pub enum ComplexValType {
Any,
Char,
@@ -127,10 +125,6 @@
UnionRef(&'static [ComplexValType]),
Sum(Vec<ComplexValType>),
SumRef(&'static [ComplexValType]),
-}
-impl Finalize for ComplexValType {}
-unsafe impl Trace for ComplexValType {
- unsafe_empty_trace!();
}
impl From<ValType> for ComplexValType {