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

difftreelog

feat(jrsonnet-evaluator) implement gc

Yaroslav Bolyukin2021-06-05parent: #e2e1f7b.patch.diff
in: master
Some manual Trace/Finalize implementations can be replaced with derives
with https://github.com/Manishearth/rust-gc/pull/116 getting merged

17 files changed

modifiedcrates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth
30jrsonnet-types = { path = "../jrsonnet-types", version = "0.3.7" }30jrsonnet-types = { path = "../jrsonnet-types", version = "0.3.7" }
31pathdiff = "0.2.0"31pathdiff = "0.2.0"
32
33closure = "0.3.0"
3432
35md5 = "0.7.0"33md5 = "0.7.0"
36base64 = "0.13.0"34base64 = "0.13.0"
37rustc-hash = "1.1.0"35rustc-hash = "1.1.0"
3836
39thiserror = "1.0"37thiserror = "1.0"
38gc = { version = "0.4.1", features = ["derive"] }
4039
41[dependencies.anyhow]40[dependencies.anyhow]
42version = "1.0"41version = "1.0"
modifiedcrates/jrsonnet-evaluator/src/builtin/format.rsdiffbeforeafterboth
2#![allow(clippy::too_many_arguments)]2#![allow(clippy::too_many_arguments)]
33
4use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val};4use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val};
5use gc::{Finalize, Trace};
5use jrsonnet_interner::IStr;6use jrsonnet_interner::IStr;
6use jrsonnet_types::ValType;7use jrsonnet_types::ValType;
7use thiserror::Error;8use thiserror::Error;
89
9#[derive(Debug, Clone, Error)]10#[derive(Debug, Clone, Error, Trace, Finalize)]
10pub enum FormatError {11pub enum FormatError {
11 #[error("truncated format code")]12 #[error("truncated format code")]
12 TruncatedFormatCode,13 TruncatedFormatCode,
modifiedcrates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth
126 buf.push('}');126 buf.push('}');
127 }127 }
128 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),128 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),
129 Val::DebugGcTraceValue(v) => manifest_json_ex_buf(&v.value, buf, cur_padding, options)?,
129 };130 };
130 Ok(())131 Ok(())
131}132}
modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 equals,2 equals,
3 error::{Error::*, Result},3 error::{Error::*, Result},
4 parse_args, primitive_equals, push, throw, with_state, ArrValue, Context, EvaluationState,4 parse_args, primitive_equals, push, throw, with_state, ArrValue, Context, DebugGcTraceValue,
5 FuncVal, LazyVal, Val,5 EvaluationState, FuncVal, LazyVal, Val,
6};6};
7use format::{format_arr, format_obj};7use format::{format_arr, format_obj};
8use gc::Gc;
8use jrsonnet_interner::IStr;9use jrsonnet_interner::IStr;
9use jrsonnet_parser::{ArgsDesc, BinaryOpType, ExprLocation};10use jrsonnet_parser::{ArgsDesc, BinaryOpType, ExprLocation};
10use jrsonnet_types::ty;11use jrsonnet_types::ty;
68 ("md5".into(), builtin_md5),69 ("md5".into(), builtin_md5),
69 ("base64".into(), builtin_base64),70 ("base64".into(), builtin_base64),
70 ("trace".into(), builtin_trace),71 ("trace".into(), builtin_trace),
72 ("gc".into(), builtin_gc),
73 ("gcTrace".into(), builtin_gc_trace),
71 ("join".into(), builtin_join),74 ("join".into(), builtin_join),
72 ("escapeStringJson".into(), builtin_escape_string_json),75 ("escapeStringJson".into(), builtin_escape_string_json),
73 ("manifestJsonEx".into(), builtin_manifest_json_ex),76 ("manifestJsonEx".into(), builtin_manifest_json_ex),
301 parse_args!(context, "native", args, 1, [304 parse_args!(context, "native", args, 1, [
302 0, x: ty!(string) => Val::Str;305 0, x: ty!(string) => Val::Str;
303 ], {306 ], {
304 Ok(with_state(|s| s.settings().ext_natives.get(&x).cloned()).map(|v| Val::Func(Rc::new(FuncVal::NativeExt(x.clone(), v)))).ok_or(UndefinedExternalFunction(x))?)307 Ok(with_state(|s| s.settings().ext_natives.get(&x).cloned()).map(|v| Val::Func(Gc::new(FuncVal::NativeExt(x.clone(), v)))).ok_or(UndefinedExternalFunction(x))?)
305 })308 })
306}309}
307310
446 })449 })
447}450}
451
452fn builtin_gc(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
453 parse_args!(context, "gc", args, 1, [
454 0, rest: ty!(any);
455 ], {
456 println!("GC start");
457 gc::force_collect();
458 println!("GC done");
459
460 Ok(rest)
461 })
462}
463
464fn builtin_gc_trace(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
465 parse_args!(context, "gcTrace", args, 2, [
466 0, name: ty!(string) => Val::Str;
467 1, rest: ty!(any);
468 ], {
469
470 Ok(DebugGcTraceValue::new(name, rest))
471 })
472}
448473
449fn builtin_base64(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {474fn builtin_base64(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
450 parse_args!(context, "base64", args, 1, [475 parse_args!(context, "base64", args, 1, [
modifiedcrates/jrsonnet-evaluator/src/builtin/sort.rsdiffbeforeafterboth
2 error::{Error, LocError, Result},2 error::{Error, LocError, Result},
3 throw, Context, FuncVal, Val,3 throw, Context, FuncVal, Val,
4};4};
5use std::rc::Rc;5use gc::{Finalize, Gc, Trace};
66
7#[derive(Debug, Clone, thiserror::Error)]7#[derive(Debug, Clone, thiserror::Error, Trace, Finalize)]
8pub enum SortError {8pub enum SortError {
9 #[error("sort key should be string or number")]9 #[error("sort key should be string or number")]
10 SortKeyShouldBeStringOrNumber,10 SortKeyShouldBeStringOrNumber,
59 Ok(sort_type)59 Ok(sort_type)
60}60}
6161
62pub fn sort(ctx: Context, mut values: Rc<Vec<Val>>, key_getter: &FuncVal) -> Result<Rc<Vec<Val>>> {62pub fn sort(ctx: Context, values: Gc<Vec<Val>>, key_getter: &FuncVal) -> Result<Gc<Vec<Val>>> {
63 if values.len() <= 1 {63 if values.len() <= 1 {
64 return Ok(values);64 return Ok(values);
65 }65 }
66 if key_getter.is_ident() {66 if key_getter.is_ident() {
67 let mvalues = Rc::make_mut(&mut values);67 let mut mvalues = (*values).clone();
68 let sort_type = get_sort_type(mvalues, |k| k)?;68 let sort_type = get_sort_type(&mut mvalues, |k| k)?;
69 match sort_type {69 match sort_type {
70 SortKeyType::Number => mvalues.sort_by_key(|v| match v {70 SortKeyType::Number => mvalues.sort_by_key(|v| match v {
71 Val::Num(n) => NonNaNf64(*n),71 Val::Num(n) => NonNaNf64(*n),
77 }),77 }),
78 SortKeyType::Unknown => unreachable!(),78 SortKeyType::Unknown => unreachable!(),
79 };79 };
80 Ok(values)80 Ok(Gc::new(mvalues))
81 } else {81 } else {
82 let mut vk = Vec::with_capacity(values.len());82 let mut vk = Vec::with_capacity(values.len());
83 for value in values.iter() {83 for value in values.iter() {
98 }),98 }),
99 SortKeyType::Unknown => unreachable!(),99 SortKeyType::Unknown => unreachable!(),
100 };100 };
101 Ok(Rc::new(vk.into_iter().map(|v| v.0).collect()))101 Ok(Gc::new(vk.into_iter().map(|v| v.0).collect()))
102 }102 }
103}103}
104104
modifiedcrates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 error::Error::*, map::LayeredHashMap, resolved_lazy_val, FutureWrapper, LazyBinding, LazyVal,2 error::Error::*, map::LayeredHashMap, FutureWrapper, LazyBinding, LazyVal, ObjValue, Result,
3 ObjValue, Result, Val,3 Val,
4};4};
5use gc::{Finalize, Gc, Trace};
5use jrsonnet_interner::IStr;6use jrsonnet_interner::IStr;
6use rustc_hash::FxHashMap;7use rustc_hash::FxHashMap;
7use std::hash::BuildHasherDefault;8use std::fmt::Debug;
8use std::{fmt::Debug, rc::Rc};9use std::hash::BuildHasherDefault;
910
10#[derive(Clone)]11#[derive(Clone, Trace, Finalize)]
11pub struct ContextCreator(pub Context, pub FutureWrapper<FxHashMap<IStr, LazyBinding>>);12pub struct ContextCreator(pub Context, pub FutureWrapper<FxHashMap<IStr, LazyBinding>>);
12impl ContextCreator {13impl ContextCreator {
13 pub fn create(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<Context> {14 pub fn create(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<Context> {
20 }21 }
21}22}
2223
24#[derive(Trace, Finalize)]
23struct ContextInternals {25struct ContextInternals {
24 dollar: Option<ObjValue>,26 dollar: Option<ObjValue>,
25 this: Option<ObjValue>,27 this: Option<ObjValue>,
29impl Debug for ContextInternals {31impl Debug for ContextInternals {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 f.debug_struct("Context")33 f.debug_struct("Context").finish()
32 .field("this", &self.this.as_ref().map(|e| Rc::as_ptr(&e.0)))
33 .field("bindings", &self.bindings)
34 .finish()
35 }34 }
36}35}
3736
38#[derive(Debug, Clone)]37#[derive(Debug, Clone, Trace, Finalize)]
39pub struct Context(Rc<ContextInternals>);38pub struct Context(Gc<ContextInternals>);
40impl Context {39impl Context {
41 pub fn new_future() -> FutureWrapper<Self> {40 pub fn new_future() -> FutureWrapper<Self> {
42 FutureWrapper::new()41 FutureWrapper::new()
55 }54 }
5655
57 pub fn new() -> Self {56 pub fn new() -> Self {
58 Self(Rc::new(ContextInternals {57 Self(Gc::new(ContextInternals {
59 dollar: None,58 dollar: None,
60 this: None,59 this: None,
61 super_obj: None,60 super_obj: None,
81 pub fn with_var(self, name: IStr, value: Val) -> Self {80 pub fn with_var(self, name: IStr, value: Val) -> Self {
82 let mut new_bindings =81 let mut new_bindings =
83 FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());82 FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());
84 new_bindings.insert(name, resolved_lazy_val!(value));83 new_bindings.insert(name, LazyVal::new_resolved(value));
85 self.extend(new_bindings, None, None, None)84 self.extend(new_bindings, None, None, None)
86 }85 }
8786
96 new_this: Option<ObjValue>,95 new_this: Option<ObjValue>,
97 new_super_obj: Option<ObjValue>,96 new_super_obj: Option<ObjValue>,
98 ) -> Self {97 ) -> Self {
99 match Rc::try_unwrap(self.0) {
100 Ok(mut ctx) => {
101 // Extended context aren't used by anything else, we can freely mutate it without cloning
102 if let Some(dollar) = new_dollar {98 let ctx = &self.0;
103 ctx.dollar = Some(dollar);
104 }
105 if let Some(this) = new_this {
106 ctx.this = Some(this);
107 }
108 if let Some(super_obj) = new_super_obj {
109 ctx.super_obj = Some(super_obj);
110 }
111 if !new_bindings.is_empty() {
112 ctx.bindings = ctx.bindings.extend(new_bindings);
113 }
114 Self(Rc::new(ctx))
115 }
116 Err(ctx) => {
117 let dollar = new_dollar.or_else(|| ctx.dollar.clone());99 let dollar = new_dollar.or_else(|| ctx.dollar.clone());
118 let this = new_this.or_else(|| ctx.this.clone());100 let this = new_this.or_else(|| ctx.this.clone());
119 let super_obj = new_super_obj.or_else(|| ctx.super_obj.clone());101 let super_obj = new_super_obj.or_else(|| ctx.super_obj.clone());
122 } else {104 } else {
123 ctx.bindings.clone().extend(new_bindings)105 ctx.bindings.clone().extend(new_bindings)
124 };106 };
125 Self(Rc::new(ContextInternals {107 Self(Gc::new(ContextInternals {
126 dollar,108 dollar,
127 this,109 this,
128 super_obj,110 super_obj,
129 bindings,111 bindings,
130 }))112 }))
131 }
132 }
133 }113 }
134 pub fn extend_bound(self, new_bindings: FxHashMap<IStr, LazyVal>) -> Self {114 pub fn extend_bound(self, new_bindings: FxHashMap<IStr, LazyVal>) -> Self {
135 let new_this = self.0.this.clone();115 let new_this = self.0.this.clone();
166146
167impl PartialEq for Context {147impl PartialEq for Context {
168 fn eq(&self, other: &Self) -> bool {148 fn eq(&self, other: &Self) -> bool {
169 Rc::ptr_eq(&self.0, &other.0)149 Gc::ptr_eq(&self.0, &other.0)
170 }150 }
171}151}
172
173#[cfg(feature = "unstable")]
174#[derive(Debug, Clone)]
175pub struct WeakContext(std::rc::Weak<ContextInternals>);
176#[cfg(feature = "unstable")]
177impl WeakContext {
178 pub fn upgrade(&self) -> Context {
179 Context(self.0.upgrade().expect("context is removed"))
180 }
181}
182#[cfg(feature = "unstable")]
183impl PartialEq for WeakContext {
184 fn eq(&self, other: &Self) -> bool {
185 self.0.ptr_eq(&other.0)
186 }
187}
188152
modifiedcrates/jrsonnet-evaluator/src/dynamic.rsdiffbeforeafterboth
1use std::{cell::RefCell, rc::Rc};1use gc::{Finalize, Gc, GcCell, Trace};
22
3#[derive(Clone)]3#[derive(Clone, Trace, Finalize)]
4pub struct FutureWrapper<V>(pub Rc<RefCell<Option<V>>>);4pub struct FutureWrapper<V: Trace + 'static>(pub Gc<GcCell<Option<V>>>);
5impl<T> FutureWrapper<T> {5impl<T: Trace + 'static> FutureWrapper<T> {
6 pub fn new() -> Self {6 pub fn new() -> Self {
7 Self(Rc::new(RefCell::new(None)))7 Self(Gc::new(GcCell::new(None)))
8 }8 }
9 pub fn fill(self, value: T) {9 pub fn fill(self, value: T) {
10 assert!(self.0.borrow().is_none(), "wrapper is filled already");10 assert!(self.0.borrow().is_none(), "wrapper is filled already");
11 self.0.borrow_mut().replace(value);11 self.0.borrow_mut().replace(value);
12 }12 }
13}13}
14impl<T: Clone> FutureWrapper<T> {14impl<T: Clone + Trace + 'static> FutureWrapper<T> {
15 pub fn unwrap(&self) -> T {15 pub fn unwrap(&self) -> T {
16 self.0.borrow().as_ref().cloned().unwrap()16 self.0.borrow().as_ref().cloned().unwrap()
17 }17 }
18}18}
1919
20impl<T> Default for FutureWrapper<T> {20impl<T: Trace + 'static> Default for FutureWrapper<T> {
21 fn default() -> Self {21 fn default() -> Self {
22 Self::new()22 Self::new()
23 }23 }
modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
2 builtin::{format::FormatError, sort::SortError},2 builtin::{format::FormatError, sort::SortError},
3 typed::TypeLocError,3 typed::TypeLocError,
4};4};
5use gc::{Finalize, Trace};
5use jrsonnet_interner::IStr;6use jrsonnet_interner::IStr;
6use jrsonnet_parser::{BinaryOpType, ExprLocation, UnaryOpType};7use jrsonnet_parser::{BinaryOpType, ExprLocation, UnaryOpType};
7use jrsonnet_types::ValType;8use jrsonnet_types::ValType;
8use std::{path::PathBuf, rc::Rc};9use std::{path::PathBuf, rc::Rc};
9use thiserror::Error;10use thiserror::Error;
1011
11#[derive(Error, Debug, Clone)]12#[derive(Error, Debug, Clone, Trace, Finalize)]
12pub enum Error {13pub enum Error {
13 #[error("intrinsic not found: {0}")]14 #[error("intrinsic not found: {0}")]
14 IntrinsicNotFound(IStr),15 IntrinsicNotFound(IStr),
88 ImportSyntaxError {89 ImportSyntaxError {
89 path: Rc<PathBuf>,90 path: Rc<PathBuf>,
90 source_code: IStr,91 source_code: IStr,
92 #[unsafe_ignore_trace]
91 error: Box<jrsonnet_parser::ParseError>,93 error: Box<jrsonnet_parser::ParseError>,
92 },94 },
9395
94 #[error("runtime error: {0}")]96 #[error("runtime error: {0}")]
95 RuntimeError(IStr),97 RuntimeError(IStr),
96 #[error("stack overflow, try to reduce recursion, or set --max-stack to bigger value")]98 #[error("stack overflow, try to reduce recursion, or set --max-stack to bigger value")]
97 StackOverflow,99 StackOverflow,
100 #[error("infinite recursion detected")]
101 RecursiveLazyValueEvaluation,
98 #[error("tried to index by fractional value")]102 #[error("tried to index by fractional value")]
99 FractionalIndex,103 FractionalIndex,
100 #[error("attempted to divide by zero")]104 #[error("attempted to divide by zero")]
142 }146 }
143}147}
144148
145#[derive(Clone, Debug)]149#[derive(Clone, Debug, Trace, Finalize)]
146pub struct StackTraceElement {150pub struct StackTraceElement {
147 pub location: Option<ExprLocation>,151 pub location: Option<ExprLocation>,
148 pub desc: String,152 pub desc: String,
149}153}
150#[derive(Debug, Clone)]154#[derive(Debug, Clone, Trace, Finalize)]
151pub struct StackTrace(pub Vec<StackTraceElement>);155pub struct StackTrace(pub Vec<StackTraceElement>);
152156
153#[derive(Debug, Clone)]157#[derive(Debug, Clone, Trace, Finalize)]
154pub struct LocError(Box<(Error, StackTrace)>);158pub struct LocError(Box<(Error, StackTrace)>);
155impl LocError {159impl LocError {
156 pub fn new(e: Error) -> Self {160 pub fn new(e: Error) -> Self {
modifiedcrates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 equals, error::Error::*, lazy_val, push, throw, with_state, ArrValue, Context, ContextCreator,2 equals, error::Error::*, push, throw, with_state, ArrValue, Bindable, Context, ContextCreator,
3 FuncDesc, FuncVal, FutureWrapper, LazyBinding, LazyVal, ObjMember, ObjValue, Result, Val,3 FuncDesc, FuncVal, FutureWrapper, LazyBinding, LazyVal, LazyValValue, ObjMember, ObjValue,
4 ObjectAssertion, Result, Val,
4};5};
5use closure::closure;6use gc::{custom_trace, Finalize, Gc, Trace};
6use jrsonnet_interner::IStr;7use jrsonnet_interner::IStr;
7use jrsonnet_parser::{8use jrsonnet_parser::{
8 ArgsDesc, AssertStmt, BinaryOpType, BindSpec, CompSpec, Expr, ExprLocation, FieldMember,9 ArgsDesc, AssertStmt, BinaryOpType, BindSpec, CompSpec, Expr, ExprLocation, FieldMember,
21 if let Some(params) = &b.params {22 if let Some(params) = &b.params {
22 let params = params.clone();23 let params = params.clone();
24
25 struct LazyMethodBinding {
26 context_creator: FutureWrapper<Context>,
27 name: IStr,
28 params: ParamsDesc,
29 value: LocExpr,
30 }
31 impl Finalize for LazyMethodBinding {}
32 unsafe impl Trace for LazyMethodBinding {
33 custom_trace!(this, {
34 mark(&this.context_creator);
35 mark(&this.name);
36 mark(&this.params);
37 mark(&this.value);
38 });
39 }
40 impl LazyValValue for LazyMethodBinding {
41 fn get(self: Box<Self>) -> Result<Val> {
42 Ok(evaluate_method(
43 self.context_creator.unwrap(),
44 self.name,
45 self.params,
46 self.value,
47 ))
48 }
49 }
50
23 LazyVal::new(Box::new(move || {51 LazyVal::new(Box::new(LazyMethodBinding {
24 Ok(evaluate_method(
25 context_creator.unwrap(),52 context_creator,
26 b.name.clone(),53 name: b.name.clone(),
27 params.clone(),54 params,
28 b.value.clone(),55 value: b.value.clone(),
29 ))
30 }))56 }))
31 } else {57 } else {
58 struct LazyNamedBinding {
59 context_creator: FutureWrapper<Context>,
60 name: IStr,
61 value: LocExpr,
62 }
63 impl Finalize for LazyNamedBinding {}
64 unsafe impl Trace for LazyNamedBinding {
65 custom_trace!(this, {
66 mark(&this.context_creator);
67 mark(&this.name);
68 mark(&this.value);
69 });
70 }
71 impl LazyValValue for LazyNamedBinding {
72 fn get(self: Box<Self>) -> Result<Val> {
73 evaluate_named(self.context_creator.unwrap(), &self.value, self.name)
74 }
75 }
32 LazyVal::new(Box::new(move || {76 LazyVal::new(Box::new(LazyNamedBinding {
33 evaluate_named(context_creator.unwrap(), &b.value, b.name.clone())77 context_creator,
78 name: b.name.clone(),
79 value: b.value,
34 }))80 }))
35 }81 }
36}82}
40 if let Some(params) = &b.params {86 if let Some(params) = &b.params {
41 let params = params.clone();87 let params = params.clone();
88
89 struct BindableMethodLazyVal {
90 this: Option<ObjValue>,
91 super_obj: Option<ObjValue>,
92
93 context_creator: ContextCreator,
94 name: IStr,
95 params: ParamsDesc,
96 value: LocExpr,
97 }
98 impl Finalize for BindableMethodLazyVal {}
99 unsafe impl Trace for BindableMethodLazyVal {
100 custom_trace!(this, {
101 mark(&this.this);
102 mark(&this.super_obj);
103 mark(&this.context_creator);
104 mark(&this.name);
105 mark(&this.params);
106 mark(&this.value);
107 });
108 }
109 impl LazyValValue for BindableMethodLazyVal {
110 fn get(self: Box<Self>) -> Result<Val> {
111 Ok(evaluate_method(
112 self.context_creator.create(self.this, self.super_obj)?,
113 self.name,
114 self.params,
115 self.value,
116 ))
117 }
118 }
119
120 #[derive(Trace, Finalize)]
121 struct BindableMethod {
122 context_creator: ContextCreator,
123 name: IStr,
124 params: ParamsDesc,
125 value: LocExpr,
126 }
127 impl Bindable for BindableMethod {
128 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {
129 Ok(LazyVal::new(Box::new(BindableMethodLazyVal {
130 this: this.clone(),
131 super_obj: super_obj.clone(),
132
133 context_creator: self.context_creator.clone(),
134 name: self.name.clone(),
135 params: self.params.clone(),
136 value: self.value.clone(),
137 })))
138 }
139 }
140
42 (141 (
43 b.name.clone(),142 b.name.clone(),
44 LazyBinding::Bindable(Rc::new(move |this, super_obj| {143 LazyBinding::Bindable(Gc::new(Box::new(BindableMethod {
45 Ok(lazy_val!(
46 closure!(clone b, clone params, clone context_creator, || Ok(evaluate_method(144 context_creator,
47 context_creator.create(this.clone(), super_obj.clone())?,
48 b.name.clone(),145 name: b.name.clone(),
49 params.clone(),146 params,
50 b.value.clone(),147 value: b.value.clone(),
51 )))
52 ))148 }))),
53 })),
54 )149 )
55 } else {150 } else {
151 struct BindableNamedLazyVal {
152 this: Option<ObjValue>,
153 super_obj: Option<ObjValue>,
154
155 context_creator: ContextCreator,
156 name: IStr,
157 value: LocExpr,
158 }
159 impl Finalize for BindableNamedLazyVal {}
160 unsafe impl Trace for BindableNamedLazyVal {
161 custom_trace!(this, {
162 mark(&this.this);
163 mark(&this.super_obj);
164 mark(&this.context_creator);
165 mark(&this.name);
166 mark(&this.value);
167 });
168 }
169 impl LazyValValue for BindableNamedLazyVal {
170 fn get(self: Box<Self>) -> Result<Val> {
171 evaluate_named(
172 self.context_creator.create(self.this, self.super_obj)?,
173 &self.value,
174 self.name,
175 )
176 }
177 }
178
179 #[derive(Trace, Finalize)]
180 struct BindableNamed {
181 context_creator: ContextCreator,
182 name: IStr,
183 value: LocExpr,
184 }
185 impl Bindable for BindableNamed {
186 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {
187 Ok(LazyVal::new(Box::new(BindableNamedLazyVal {
188 this,
189 super_obj,
190
191 context_creator: self.context_creator.clone(),
192 name: self.name.clone(),
193 value: self.value.clone(),
194 })))
195 }
196 }
197
56 (198 (
57 b.name.clone(),199 b.name.clone(),
58 LazyBinding::Bindable(Rc::new(move |this, super_obj| {200 LazyBinding::Bindable(Gc::new(Box::new(BindableNamed {
59 Ok(lazy_val!(closure!(clone context_creator, clone b, ||201 context_creator,
60 evaluate_named(
61 context_creator.create(this.clone(), super_obj.clone())?,202 name: b.name.clone(),
62 &b.value,203 value: b.value.clone(),
63 b.name.clone()
64 )
65 )))204 }))),
66 })),
67 )205 )
68 }206 }
69}207}
70208
71pub fn evaluate_method(ctx: Context, name: IStr, params: ParamsDesc, body: LocExpr) -> Val {209pub fn evaluate_method(ctx: Context, name: IStr, params: ParamsDesc, body: LocExpr) -> Val {
72 Val::Func(Rc::new(FuncVal::Normal(FuncDesc {210 Val::Func(Gc::new(FuncVal::Normal(FuncDesc {
73 name,211 name,
74 ctx,212 ctx,
75 params,213 params,
105243
106pub fn evaluate_add_op(a: &Val, b: &Val) -> Result<Val> {244pub fn evaluate_add_op(a: &Val, b: &Val) -> Result<Val> {
107 Ok(match (a, b) {245 Ok(match (a, b) {
246 (Val::DebugGcTraceValue(v1), Val::DebugGcTraceValue(v2)) => {
247 evaluate_add_op(&v1.value, &v2.value)?
248 }
108 (Val::Str(v1), Val::Str(v2)) => Val::Str(((**v1).to_owned() + v2).into()),249 (Val::Str(v1), Val::Str(v2)) => Val::Str(((**v1).to_owned() + v2).into()),
109250
110 // Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)251 // Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)
257 }398 }
258399
259 let mut new_members = FxHashMap::default();400 let mut new_members = FxHashMap::default();
260 let mut assertions = Vec::new();401 let mut assertions: Vec<Box<dyn ObjectAssertion>> = Vec::new();
261 for member in members.iter() {402 for member in members.iter() {
262 match member {403 match member {
263 Member::Field(FieldMember {404 Member::Field(FieldMember {
273 }414 }
274 let name = name.unwrap();415 let name = name.unwrap();
416
417 #[derive(Trace, Finalize)]
418 struct ObjMemberBinding {
419 context_creator: ContextCreator,
420 value: LocExpr,
421 name: IStr,
422 }
423 impl Bindable for ObjMemberBinding {
424 fn bind(
425 &self,
426 this: Option<ObjValue>,
427 super_obj: Option<ObjValue>,
428 ) -> Result<LazyVal> {
429 Ok(LazyVal::new_resolved(evaluate_named(
430 self.context_creator.create(this, super_obj)?,
431 &self.value,
432 self.name.clone(),
433 )?))
434 }
435 }
275 new_members.insert(436 new_members.insert(
276 name.clone(),437 name.clone(),
277 ObjMember {438 ObjMember {
278 add: *plus,439 add: *plus,
279 visibility: *visibility,440 visibility: *visibility,
280 invoke: LazyBinding::Bindable(Rc::new(441 invoke: LazyBinding::Bindable(Gc::new(Box::new(ObjMemberBinding {
281 closure!(clone name, clone value, clone context_creator, |this, super_obj| {442 context_creator: context_creator.clone(),
282 Ok(LazyVal::new_resolved(evaluate_named(
283 context_creator.create(this, super_obj)?,
284 &value,443 value: value.clone(),
285 name.clone(),444 name,
286 )?))
287 }),445 }))),
288 )),
289 location: value.1.clone(),446 location: value.1.clone(),
290 },447 },
301 continue;458 continue;
302 }459 }
303 let name = name.unwrap();460 let name = name.unwrap();
461 #[derive(Trace, Finalize)]
462 struct ObjMemberBinding {
463 context_creator: ContextCreator,
464 value: LocExpr,
465 params: ParamsDesc,
466 name: IStr,
467 }
468 impl Bindable for ObjMemberBinding {
469 fn bind(
470 &self,
471 this: Option<ObjValue>,
472 super_obj: Option<ObjValue>,
473 ) -> Result<LazyVal> {
474 Ok(LazyVal::new_resolved(evaluate_method(
475 self.context_creator.create(this, super_obj)?,
476 self.name.clone(),
477 self.params.clone(),
478 self.value.clone(),
479 )))
480 }
481 }
304 new_members.insert(482 new_members.insert(
305 name.clone(),483 name.clone(),
306 ObjMember {484 ObjMember {
307 add: false,485 add: false,
308 visibility: Visibility::Hidden,486 visibility: Visibility::Hidden,
309 invoke: LazyBinding::Bindable(Rc::new(487 invoke: LazyBinding::Bindable(Gc::new(Box::new(ObjMemberBinding {
310 closure!(clone value, clone context_creator, clone params, clone name, |this, super_obj| {488 context_creator: context_creator.clone(),
311 // TODO: Assert
312 Ok(LazyVal::new_resolved(evaluate_method(
313 context_creator.create(this, super_obj)?,
314 name.clone(),489 value: value.clone(),
315 params.clone(),490 params: params.clone(),
316 value.clone(),491 name,
317 )))
318 }),492 }))),
319 )),
320 location: value.1.clone(),493 location: value.1.clone(),
321 },494 },
322 );495 );
323 }496 }
324 Member::BindStmt(_) => {}497 Member::BindStmt(_) => {}
325 Member::AssertStmt(stmt) => {498 Member::AssertStmt(stmt) => {
499 struct ObjectAssert {
500 context_creator: ContextCreator,
501 assert: AssertStmt,
502 }
503 impl Finalize for ObjectAssert {}
504 unsafe impl Trace for ObjectAssert {
505 custom_trace!(this, {
506 mark(&this.context_creator);
507 mark(&this.assert);
508 });
509 }
510 impl ObjectAssertion for ObjectAssert {
511 fn run(
512 &self,
513 this: Option<ObjValue>,
514 super_obj: Option<ObjValue>,
515 ) -> Result<()> {
516 let ctx = self.context_creator.create(this, super_obj)?;
517 evaluate_assert(ctx, &self.assert)
518 }
519 }
326 assertions.push(stmt.clone());520 assertions.push(Box::new(ObjectAssert {
521 context_creator: context_creator.clone(),
522 assert: stmt.clone(),
523 }));
327 }524 }
328 }525 }
329 }526 }
330 let this = ObjValue::new(context, None, Rc::new(new_members), Rc::new(assertions));527 let this = ObjValue::new(None, Gc::new(new_members), Gc::new(assertions));
331 future_this.fill(this.clone());528 future_this.fill(this.clone());
332 Ok(this)529 Ok(this)
333}530}
361 match key {558 match key {
362 Val::Null => {}559 Val::Null => {}
363 Val::Str(n) => {560 Val::Str(n) => {
561 #[derive(Trace, Finalize)]
562 struct ObjCompBinding {
563 context: Context,
564 value: LocExpr,
565 }
566 impl Bindable for ObjCompBinding {
567 fn bind(
568 &self,
569 this: Option<ObjValue>,
570 _super_obj: Option<ObjValue>,
571 ) -> Result<LazyVal> {
572 Ok(LazyVal::new_resolved(evaluate(
573 self.context.clone().extend(
574 FxHashMap::default(),
575 None,
576 this,
577 None,
578 ),
579 &self.value,
580 )?))
581 }
582 }
364 new_members.insert(583 new_members.insert(
365 n,584 n,
366 ObjMember {585 ObjMember {
367 add: false,586 add: false,
368 visibility: Visibility::Normal,587 visibility: Visibility::Normal,
369 invoke: LazyBinding::Bindable(Rc::new(588 invoke: LazyBinding::Bindable(Gc::new(Box::new(ObjCompBinding {
370 closure!(clone ctx, clone obj.value, |this, _super_obj| {589 context: ctx.clone(),
371 Ok(LazyVal::new_resolved(evaluate(ctx.clone().extend(FxHashMap::default(), None, this, None), &value)?))590 value: obj.value.clone(),
372 }),591 }))),
373 )),
374 location: obj.value.1.clone(),592 location: obj.value.1.clone(),
375 },593 },
381 Ok(())599 Ok(())
382 })?;600 })?;
383601
384 let this = ObjValue::new(context, None, Rc::new(new_members), Rc::new(Vec::new()));602 let this = ObjValue::new(None, Gc::new(new_members), Gc::new(Vec::new()));
385 future_this.fill(this.clone());603 future_this.fill(this.clone());
386 this604 this
387 }605 }
486 if let Some(v) = v.get(s.clone())? {704 if let Some(v) = v.get(s.clone())? {
487 Ok(v)705 Ok(v)
488 } else if v.get("__intrinsic_namespace__".into())?.is_some() {706 } else if v.get("__intrinsic_namespace__".into())?.is_some() {
489 Ok(Val::Func(Rc::new(FuncVal::Intrinsic(s))))707 Ok(Val::Func(Gc::new(FuncVal::Intrinsic(s))))
490 } else {708 } else {
491 throw!(NoSuchField(s))709 throw!(NoSuchField(s))
492 }710 }
549 Arr(items) => {767 Arr(items) => {
550 let mut out = Vec::with_capacity(items.len());768 let mut out = Vec::with_capacity(items.len());
551 for item in items {769 for item in items {
770 // TODO: Implement ArrValue::Lazy with same context for every element?
771 struct ArrayElement {
772 context: Context,
773 item: LocExpr,
774 }
775 impl Finalize for ArrayElement {}
776 unsafe impl Trace for ArrayElement {
777 custom_trace!(this, {
778 mark(&this.context);
779 mark(&this.item);
780 });
781 }
782 impl LazyValValue for ArrayElement {
783 fn get(self: Box<Self>) -> Result<Val> {
784 evaluate(self.context, &self.item)
785 }
786 }
552 out.push(LazyVal::new(Box::new(787 out.push(LazyVal::new(Box::new(ArrayElement {
553 closure!(clone context, clone item, || {788 context: context.clone(),
554 evaluate(context.clone(), &item)789 item: item.clone(),
555 }),
556 )));790 })));
557 }791 }
558 Val::Arr(out.into())792 Val::Arr(out.into())
559 }793 }
563 out.push(evaluate(ctx, expr)?);797 out.push(evaluate(ctx, expr)?);
564 Ok(())798 Ok(())
565 })?;799 })?;
566 Val::Arr(ArrValue::Eager(Rc::new(out)))800 Val::Arr(ArrValue::Eager(Gc::new(out)))
567 }801 }
568 Obj(body) => Val::Obj(evaluate_object(context, body)?),802 Obj(body) => Val::Obj(evaluate_object(context, body)?),
569 ObjExtend(s, t) => evaluate_add_op(803 ObjExtend(s, t) => evaluate_add_op(
576 Function(params, body) => {810 Function(params, body) => {
577 evaluate_method(context, "anonymous".into(), params.clone(), body.clone())811 evaluate_method(context, "anonymous".into(), params.clone(), body.clone())
578 }812 }
579 Intrinsic(name) => Val::Func(Rc::new(FuncVal::Intrinsic(name.clone()))),813 Intrinsic(name) => Val::Func(Gc::new(FuncVal::Intrinsic(name.clone()))),
580 AssertExpr(assert, returned) => {814 AssertExpr(assert, returned) => {
581 evaluate_assert(context.clone(), assert)?;815 evaluate_assert(context.clone(), assert)?;
582 evaluate(context, returned)?816 evaluate(context, returned)?
modifiedcrates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth
1use crate::{error::Error::*, evaluate, lazy_val, resolved_lazy_val, throw, Context, Result, Val};1use crate::{error::Error::*, evaluate, throw, Context, LazyVal, LazyValValue, Result, Val};
2use closure::closure;2use gc::{custom_trace, Finalize, Trace};
3use jrsonnet_interner::IStr;3use jrsonnet_interner::IStr;
4use jrsonnet_parser::{ArgsDesc, ParamsDesc};4use jrsonnet_parser::{ArgsDesc, LocExpr, ParamsDesc};
5use rustc_hash::FxHashMap;5use rustc_hash::FxHashMap;
6use std::{collections::HashMap, hash::BuildHasherDefault};6use std::{collections::HashMap, hash::BuildHasherDefault};
77
53 throw!(FunctionParameterNotBoundInCall(p.0.clone()));53 throw!(FunctionParameterNotBoundInCall(p.0.clone()));
54 };54 };
55 let val = if tailstrict {55 let val = if tailstrict {
56 resolved_lazy_val!(evaluate(ctx, expr)?)56 LazyVal::new_resolved(evaluate(ctx, expr)?)
57 } else {57 } else {
58 struct EvaluateLazyVal {
59 context: Context,
60 expr: LocExpr,
61 }
62 impl Finalize for EvaluateLazyVal {}
63 unsafe impl Trace for EvaluateLazyVal {
64 custom_trace!(this, {
65 mark(&this.context);
66 mark(&this.expr);
67 });
68 }
69 impl LazyValValue for EvaluateLazyVal {
70 fn get(self: Box<Self>) -> Result<Val> {
71 evaluate(self.context, &self.expr)
72 }
73 }
74
58 lazy_val!(closure!(clone ctx, clone expr, ||evaluate(ctx.clone(), &expr)))75 LazyVal::new(Box::new(EvaluateLazyVal {
76 context: ctx.clone(),
77 expr: expr.clone(),
78 }))
59 };79 };
60 out.insert(p.0.clone(), val);80 out.insert(p.0.clone(), val);
61 }81 }
89 // Fill defaults109 // Fill defaults
90 for (id, p) in params.iter().enumerate() {110 for (id, p) in params.iter().enumerate() {
91 let val = if let Some(arg) = positioned_args[id].take() {111 let val = if let Some(arg) = positioned_args[id].take() {
92 resolved_lazy_val!(arg)112 LazyVal::new_resolved(arg)
93 } else if let Some(default) = &p.1 {113 } else if let Some(default) = &p.1 {
94 if tailstrict {114 if tailstrict {
95 resolved_lazy_val!(evaluate(115 LazyVal::new_resolved(evaluate(
96 body_ctx.clone().expect(NO_DEFAULT_CONTEXT),116 body_ctx.clone().expect(NO_DEFAULT_CONTEXT),
97 default117 default,
98 )?)118 )?)
99 } else {119 } else {
100 let body_ctx = body_ctx.clone();120 let body_ctx = body_ctx.clone();
101 let default = default.clone();121 let default = default.clone();
122 #[derive(Trace, Finalize)]
123 struct EvaluateLazyVal {
124 body_ctx: Option<Context>,
125 default: LocExpr,
126 }
127 impl LazyValValue for EvaluateLazyVal {
102 lazy_val!(move || {128 fn get(self: Box<Self>) -> Result<Val> {
103 evaluate(body_ctx.clone().expect(NO_DEFAULT_CONTEXT), &default)129 evaluate(
130 self.body_ctx.clone().expect(NO_DEFAULT_CONTEXT),
131 &self.default,
132 )
104 })133 }
134 }
135 LazyVal::new(Box::new(EvaluateLazyVal { body_ctx, default }))
105 }136 }
106 } else {137 } else {
107 throw!(FunctionParameterNotBoundInCall(p.0.clone()));138 throw!(FunctionParameterNotBoundInCall(p.0.clone()));
135 } else {166 } else {
136 throw!(FunctionParameterNotBoundInCall(p.0.clone()));167 throw!(FunctionParameterNotBoundInCall(p.0.clone()));
137 };168 };
138 out.insert(p.0.clone(), resolved_lazy_val!(val));169 out.insert(p.0.clone(), LazyVal::new_resolved(val));
139 }170 }
140171
141 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))172 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))
modifiedcrates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth
2 error::{Error::*, LocError, Result},2 error::{Error::*, LocError, Result},
3 throw, Context, LazyBinding, LazyVal, ObjMember, ObjValue, Val,3 throw, Context, LazyBinding, LazyVal, ObjMember, ObjValue, Val,
4};4};
5use gc::Gc;
5use jrsonnet_parser::Visibility;6use jrsonnet_parser::Visibility;
6use rustc_hash::FxHasher;7use rustc_hash::FxHasher;
7use serde_json::{Map, Number, Value};8use serde_json::{Map, Number, Value};
8use std::{9use std::{
9 collections::HashMap,10 collections::HashMap,
10 convert::{TryFrom, TryInto},11 convert::{TryFrom, TryInto},
11 hash::BuildHasherDefault,12 hash::BuildHasherDefault,
12 rc::Rc,
13};13};
1414
15impl TryFrom<&Val> for Value {15impl TryFrom<&Val> for Value {
42 Self::Object(out)42 Self::Object(out)
43 }43 }
44 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),44 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),
45 Val::DebugGcTraceValue(v) => Value::try_from(&*v.value as &Val)?,
45 })46 })
46 }47 }
47}48}
76 },77 },
77 );78 );
78 }79 }
79 Self::Obj(ObjValue::new(80 Self::Obj(ObjValue::new(None, Gc::new(entries), Gc::new(Vec::new())))
80 Context::new(),
81 None,
82 Rc::new(entries),
83 Rc::new(Vec::new()),
84 ))
85 }81 }
86 }82 }
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
25use error::{Error::*, LocError, Result, StackTraceElement};25use error::{Error::*, LocError, Result, StackTraceElement};
26pub use evaluate::*;26pub use evaluate::*;
27pub use function::parse_function_call;27pub use function::parse_function_call;
28use gc::{Finalize, Gc, Trace};
28pub use import::*;29pub use import::*;
29use jrsonnet_interner::IStr;30use jrsonnet_interner::IStr;
30use jrsonnet_parser::*;31use jrsonnet_parser::*;
42use trace::{offset_to_location, CodeLocation, CompactFormat, TraceFormat};43use trace::{offset_to_location, CodeLocation, CompactFormat, TraceFormat};
43pub use val::*;44pub use val::*;
4445
46pub trait Bindable: Trace {
45type BindableFn = dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Result<LazyVal>;47 fn bind(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal>;
48}
46#[derive(Clone)]49#[derive(Trace, Finalize, Clone)]
47pub enum LazyBinding {50pub enum LazyBinding {
48 Bindable(Rc<BindableFn>),51 Bindable(Gc<Box<dyn Bindable>>),
49 Bound(LazyVal),52 Bound(LazyVal),
50}53}
5154
57impl LazyBinding {60impl LazyBinding {
58 pub fn evaluate(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {61 pub fn evaluate(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {
59 match self {62 match self {
60 Self::Bindable(v) => v(this, super_obj),63 Self::Bindable(v) => v.bind(this, super_obj),
61 Self::Bound(v) => Ok(v.clone()),64 Self::Bound(v) => Ok(v.clone()),
62 }65 }
63 }66 }
71 /// Used for s`td.extVar`74 /// Used for s`td.extVar`
72 pub ext_vars: HashMap<IStr, Val>,75 pub ext_vars: HashMap<IStr, Val>,
73 /// Used for ext.native76 /// Used for ext.native
74 pub ext_natives: HashMap<IStr, Rc<NativeCallback>>,77 pub ext_natives: HashMap<IStr, Gc<NativeCallback>>,
75 /// TLA vars78 /// TLA vars
76 pub tla_vars: HashMap<IStr, Val>,79 pub tla_vars: HashMap<IStr, Val>,
77 /// Global variables are inserted in default context80 /// Global variables are inserted in default context
270 let mut new_bindings: FxHashMap<IStr, LazyVal> =273 let mut new_bindings: FxHashMap<IStr, LazyVal> =
271 FxHashMap::with_capacity_and_hasher(globals.len(), BuildHasherDefault::default());274 FxHashMap::with_capacity_and_hasher(globals.len(), BuildHasherDefault::default());
272 for (name, value) in globals.iter() {275 for (name, value) in globals.iter() {
273 new_bindings.insert(name.clone(), resolved_lazy_val!(value.clone()));276 new_bindings.insert(name.clone(), LazyVal::new_resolved(value.clone()));
274 }277 }
275 Context::new().extend_bound(new_bindings)278 Context::new().extend_bound(new_bindings)
276 }279 }
449 self.settings_mut().import_resolver = resolver;452 self.settings_mut().import_resolver = resolver;
450 }453 }
451454
452 pub fn add_native(&self, name: IStr, cb: Rc<NativeCallback>) {455 pub fn add_native(&self, name: IStr, cb: Gc<NativeCallback>) {
453 self.settings_mut().ext_natives.insert(name, cb);456 self.settings_mut().ext_natives.insert(name, cb);
454 }457 }
455458
modifiedcrates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth
1use gc::{Finalize, Gc, Trace};
1use jrsonnet_interner::IStr;2use jrsonnet_interner::IStr;
2use rustc_hash::FxHashMap;3use rustc_hash::FxHashMap;
3use std::rc::Rc;4
4
5#[derive(Default, Debug)]
6struct LayeredHashMapInternals<V> {5pub struct LayeredHashMapInternals<V: Trace + Finalize + 'static> {
7 parent: Option<LayeredHashMap<V>>,6 parent: Option<LayeredHashMap<V>>,
8 current: FxHashMap<IStr, V>,7 current: FxHashMap<IStr, V>,
9}8}
9
10unsafe impl<V: Trace + Finalize + 'static> Trace for LayeredHashMapInternals<V> {
11 gc::custom_trace!(this, {
12 mark(&this.parent);
13 mark(&this.current);
14 });
15}
16impl<V: Trace + Finalize + 'static> Finalize for LayeredHashMapInternals<V> {}
1017
11#[derive(Debug)]18#[derive(Trace, Finalize)]
12pub struct LayeredHashMap<V>(Rc<LayeredHashMapInternals<V>>);19pub struct LayeredHashMap<V: Trace + Finalize + 'static>(Gc<LayeredHashMapInternals<V>>);
1320
14impl<V> LayeredHashMap<V> {21impl<V: Trace + 'static> LayeredHashMap<V> {
15 pub fn extend(self, new_layer: FxHashMap<IStr, V>) -> Self {22 pub fn extend(self, new_layer: FxHashMap<IStr, V>) -> Self {
16 match Rc::try_unwrap(self.0) {
17 Ok(mut map) => {
18 map.current.extend(new_layer);
19 Self(Rc::new(map))
20 }
21 Err(this) => Self(Rc::new(LayeredHashMapInternals {23 Self(Gc::new(LayeredHashMapInternals {
22 parent: Some(Self(this)),24 parent: Some(self),
23 current: new_layer,25 current: new_layer,
24 })),26 }))
25 }
26 }27 }
2728
28 pub fn get(&self, key: &IStr) -> Option<&V> {29 pub fn get(&self, key: &IStr) -> Option<&V> {
33 }34 }
34}35}
3536
36impl<V> Clone for LayeredHashMap<V> {37impl<V: Trace + 'static> Clone for LayeredHashMap<V> {
37 fn clone(&self) -> Self {38 fn clone(&self) -> Self {
38 Self(self.0.clone())39 Self(self.0.clone())
39 }40 }
40}41}
4142
42impl<V> Default for LayeredHashMap<V> {43impl<V: Trace + 'static> Default for LayeredHashMap<V> {
43 fn default() -> Self {44 fn default() -> Self {
44 Self(Rc::new(LayeredHashMapInternals {45 Self(Gc::new(LayeredHashMapInternals {
45 parent: None,46 parent: None,
46 current: FxHashMap::default(),47 current: FxHashMap::default(),
47 }))48 }))
modifiedcrates/jrsonnet-evaluator/src/native.rsdiffbeforeafterboth
1#![allow(clippy::type_complexity)]1#![allow(clippy::type_complexity)]
22
3use crate::{error::Result, Val};3use crate::{error::Result, Val};
4use gc::{Finalize, Trace};
4use jrsonnet_parser::ParamsDesc;5use jrsonnet_parser::ParamsDesc;
5use std::fmt::Debug;6use std::fmt::Debug;
6use std::path::PathBuf;7use std::path::PathBuf;
7use std::rc::Rc;8use std::rc::Rc;
89
10pub trait NativeCallbackHandler: Trace {
11 fn call(&self, from: Option<Rc<PathBuf>>, args: &[Val]) -> Result<Val>;
12}
13
14#[derive(Trace, Finalize)]
9pub struct NativeCallback {15pub struct NativeCallback {
10 pub params: ParamsDesc,16 pub params: ParamsDesc,
11 handler: Box<dyn Fn(Option<Rc<PathBuf>>, &[Val]) -> Result<Val>>,17 handler: Box<dyn NativeCallbackHandler>,
12}18}
13impl NativeCallback {19impl NativeCallback {
14 pub fn new(20 pub fn new(params: ParamsDesc, handler: Box<dyn NativeCallbackHandler>) -> Self {
15 params: ParamsDesc,
16 handler: impl Fn(Option<Rc<PathBuf>>, &[Val]) -> Result<Val> + 'static,
17 ) -> Self {
18 Self {21 Self { params, handler }
19 params,
20 handler: Box::new(handler),
21 }
22 }22 }
23 pub fn call(&self, caller: Option<Rc<PathBuf>>, args: &[Val]) -> Result<Val> {23 pub fn call(&self, caller: Option<Rc<PathBuf>>, args: &[Val]) -> Result<Val> {
24 (self.handler)(caller, args)24 self.handler.call(caller, args)
25 }25 }
26}26}
27impl Debug for NativeCallback {27impl Debug for NativeCallback {
modifiedcrates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth
1use crate::{evaluate_add_op, evaluate_assert, Context, LazyBinding, Result, Val};1use crate::{evaluate_add_op, evaluate_assert, Context, LazyBinding, Result, Val};
2use gc::{Finalize, Gc, GcCell, Trace};
2use jrsonnet_interner::IStr;3use jrsonnet_interner::IStr;
3use jrsonnet_parser::{AssertStmt, ExprLocation, Visibility};4use jrsonnet_parser::{AssertStmt, ExprLocation, Visibility};
4use rustc_hash::{FxHashMap, FxHashSet};5use rustc_hash::{FxHashMap, FxHashSet};
5use std::hash::{Hash, Hasher};6use std::hash::{Hash, Hasher};
6use std::{cell::RefCell, fmt::Debug, hash::BuildHasherDefault, rc::Rc};7use std::{fmt::Debug, hash::BuildHasherDefault};
78
8#[derive(Debug)]9#[derive(Debug, Trace, Finalize)]
9pub struct ObjMember {10pub struct ObjMember {
10 pub add: bool,11 pub add: bool,
11 pub visibility: Visibility,12 pub visibility: Visibility,
12 pub invoke: LazyBinding,13 pub invoke: LazyBinding,
13 pub location: Option<ExprLocation>,14 pub location: Option<ExprLocation>,
14}15}
16
17pub trait ObjectAssertion: Trace {
18 fn run(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<()>;
19}
1520
16// Field => This21// Field => This
17type CacheKey = (IStr, ObjValue);22type CacheKey = (IStr, ObjValue);
18#[derive(Debug)]23#[derive(Trace, Finalize)]
19pub struct ObjValueInternals {24pub struct ObjValueInternals {
20 context: Context,
21 super_obj: Option<ObjValue>,25 super_obj: Option<ObjValue>,
22 assertions: Rc<Vec<AssertStmt>>,26 assertions: Gc<Vec<Box<dyn ObjectAssertion>>>,
23 assertions_ran: RefCell<FxHashSet<ObjValue>>,27 assertions_ran: GcCell<FxHashSet<ObjValue>>,
24 this_obj: Option<ObjValue>,28 this_obj: Option<ObjValue>,
25 this_entries: Rc<FxHashMap<IStr, ObjMember>>,29 this_entries: Gc<FxHashMap<IStr, ObjMember>>,
26 value_cache: RefCell<FxHashMap<CacheKey, Option<Val>>>,30 value_cache: GcCell<FxHashMap<CacheKey, Option<Val>>>,
27}31}
2832
29#[derive(Clone)]33#[derive(Clone, Trace, Finalize)]
30pub struct ObjValue(pub(crate) Rc<ObjValueInternals>);34pub struct ObjValue(pub(crate) Gc<ObjValueInternals>);
31impl Debug for ObjValue {35impl Debug for ObjValue {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 if let Some(super_obj) = self.0.super_obj.as_ref() {37 if let Some(super_obj) = self.0.super_obj.as_ref() {
5559
56impl ObjValue {60impl ObjValue {
57 pub fn new(61 pub fn new(
58 context: Context,
59 super_obj: Option<Self>,62 super_obj: Option<Self>,
60 this_entries: Rc<FxHashMap<IStr, ObjMember>>,63 this_entries: Gc<FxHashMap<IStr, ObjMember>>,
61 assertions: Rc<Vec<AssertStmt>>,64 assertions: Gc<Vec<Box<dyn ObjectAssertion>>>,
62 ) -> Self {65 ) -> Self {
63 Self(Rc::new(ObjValueInternals {66 Self(Gc::new(ObjValueInternals {
64 context,
65 super_obj,67 super_obj,
66 assertions,68 assertions,
67 assertions_ran: RefCell::new(FxHashSet::default()),69 assertions_ran: GcCell::new(FxHashSet::default()),
68 this_obj: None,70 this_obj: None,
69 this_entries,71 this_entries,
70 value_cache: RefCell::new(FxHashMap::default()),72 value_cache: GcCell::new(FxHashMap::default()),
71 }))73 }))
72 }74 }
73 pub fn new_empty() -> Self {75 pub fn new_empty() -> Self {
74 Self::new(76 Self::new(None, Gc::new(FxHashMap::default()), Gc::new(Vec::new()))
75 Context::new(),
76 None,
77 Rc::new(FxHashMap::default()),
78 Rc::new(Vec::new()),
79 )
80 }77 }
81 pub fn extend_from(&self, super_obj: Self) -> Self {78 pub fn extend_from(&self, super_obj: Self) -> Self {
82 match &self.0.super_obj {79 match &self.0.super_obj {
83 None => Self::new(80 None => Self::new(
84 self.0.context.clone(),
85 Some(super_obj),81 Some(super_obj),
86 self.0.this_entries.clone(),82 self.0.this_entries.clone(),
87 self.0.assertions.clone(),83 self.0.assertions.clone(),
88 ),84 ),
89 Some(v) => Self::new(85 Some(v) => Self::new(
90 self.0.context.clone(),
91 Some(v.extend_from(super_obj)),86 Some(v.extend_from(super_obj)),
92 self.0.this_entries.clone(),87 self.0.this_entries.clone(),
93 self.0.assertions.clone(),88 self.0.assertions.clone(),
94 ),89 ),
95 }90 }
96 }91 }
97 pub fn with_this(&self, this_obj: Self) -> Self {92 pub fn with_this(&self, this_obj: Self) -> Self {
98 Self(Rc::new(ObjValueInternals {93 Self(Gc::new(ObjValueInternals {
99 context: self.0.context.clone(),
100 super_obj: self.0.super_obj.clone(),94 super_obj: self.0.super_obj.clone(),
101 assertions: self.0.assertions.clone(),95 assertions: self.0.assertions.clone(),
102 assertions_ran: RefCell::new(FxHashSet::default()),96 assertions_ran: GcCell::new(FxHashSet::default()),
103 this_obj: Some(this_obj),97 this_obj: Some(this_obj),
104 this_entries: self.0.this_entries.clone(),98 this_entries: self.0.this_entries.clone(),
105 value_cache: RefCell::new(FxHashMap::default()),99 value_cache: GcCell::new(FxHashMap::default()),
106 }))100 }))
107 }101 }
108102
203 pub fn extend_with_field(self, key: IStr, value: ObjMember) -> Self {197 pub fn extend_with_field(self, key: IStr, value: ObjMember) -> Self {
204 let mut new = FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());198 let mut new = FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());
205 new.insert(key, value);199 new.insert(key, value);
206 Self::new(200 Self::new(Some(self), Gc::new(new), Gc::new(Vec::new()))
207 Context::new(),
208 Some(self),
209 Rc::new(new),
210 Rc::new(Vec::new()),
211 )
212 }201 }
213202
249 fn run_assertions_raw(&self, real_this: &Self) -> Result<()> {238 fn run_assertions_raw(&self, real_this: &Self) -> Result<()> {
250 if self.0.assertions_ran.borrow_mut().insert(real_this.clone()) {239 if self.0.assertions_ran.borrow_mut().insert(real_this.clone()) {
251 for assertion in self.0.assertions.iter() {240 for assertion in self.0.assertions.iter() {
252 if let Err(e) = evaluate_assert(241 if let Err(e) = assertion.run(Some(real_this.clone()), self.0.super_obj.clone()) {
253 self.0
254 .context
255 .clone()
256 .with_this_super(real_this.clone(), self.0.super_obj.clone()),
257 assertion,
258 ) {
259 self.0.assertions_ran.borrow_mut().remove(real_this);242 self.0.assertions_ran.borrow_mut().remove(real_this);
260 return Err(e);243 return Err(e);
261 }244 }
271 }254 }
272255
273 pub fn ptr_eq(a: &Self, b: &Self) -> bool {256 pub fn ptr_eq(a: &Self, b: &Self) -> bool {
274 Rc::ptr_eq(&a.0, &b.0)257 Gc::ptr_eq(&a.0, &b.0)
275 }258 }
276}259}
277260
278impl PartialEq for ObjValue {261impl PartialEq for ObjValue {
279 fn eq(&self, other: &Self) -> bool {262 fn eq(&self, other: &Self) -> bool {
280 Rc::ptr_eq(&self.0, &other.0)263 Gc::ptr_eq(&self.0, &other.0)
281 }264 }
282}265}
283266
284impl Eq for ObjValue {}267impl Eq for ObjValue {}
285impl Hash for ObjValue {268impl Hash for ObjValue {
286 fn hash<H: Hasher>(&self, state: &mut H) {269 fn hash<H: Hasher>(&self, hasher: &mut H) {
287 state.write_usize(Rc::as_ptr(&self.0) as usize)270 hasher.write_usize(&*self.0 as *const _ as usize)
288 }271 }
289}272}
290273
modifiedcrates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth
4 error::{Error, LocError, Result},4 error::{Error, LocError, Result},
5 push, Val,5 push, Val,
6};6};
7use gc::{Finalize, Trace};
7use jrsonnet_parser::ExprLocation;8use jrsonnet_parser::ExprLocation;
8use jrsonnet_types::{ComplexValType, ValType};9use jrsonnet_types::{ComplexValType, ValType};
9use thiserror::Error;10use thiserror::Error;
20 }};21 }};
21}22}
2223
23#[derive(Debug, Error, Clone)]24#[derive(Debug, Error, Clone, Trace, Finalize)]
24pub enum TypeError {25pub enum TypeError {
25 #[error("expected {0}, got {1}")]26 #[error("expected {0}, got {1}")]
26 ExpectedGot(ComplexValType, ValType),27 ExpectedGot(ComplexValType, ValType),
37 }38 }
38}39}
3940
40#[derive(Debug, Clone)]41#[derive(Debug, Clone, Trace, Finalize)]
41pub struct TypeLocError(Box<TypeError>, ValuePathStack);42pub struct TypeLocError(Box<TypeError>, ValuePathStack);
42impl From<TypeError> for TypeLocError {43impl From<TypeError> for TypeLocError {
43 fn from(e: TypeError) -> Self {44 fn from(e: TypeError) -> Self {
59 }60 }
60}61}
6162
62#[derive(Debug, Clone)]63#[derive(Debug, Clone, Trace, Finalize)]
63pub struct TypeLocErrorList(Vec<TypeLocError>);64pub struct TypeLocErrorList(Vec<TypeLocError>);
64impl Display for TypeLocErrorList {65impl Display for TypeLocErrorList {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 }123 }
123}124}
124125
125#[derive(Clone, Debug)]126#[derive(Clone, Debug, Trace, Finalize)]
126enum ValuePathItem {127enum ValuePathItem {
127 Field(Rc<str>),128 Field(Rc<str>),
128 Index(u64),129 Index(u64),
137 }138 }
138}139}
139140
140#[derive(Clone, Debug)]141#[derive(Clone, Debug, Trace, Finalize)]
141struct ValuePathStack(Vec<ValuePathItem>);142struct ValuePathStack(Vec<ValuePathItem>);
142impl Display for ValuePathStack {143impl Display for ValuePathStack {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {144 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
3 call_builtin,3 call_builtin,
4 manifest::{manifest_json_ex, ManifestJsonOptions, ManifestType},4 manifest::{manifest_json_ex, ManifestJsonOptions, ManifestType},
5 },5 },
6 error::Error::*,6 error::{Error::*, LocError},
7 evaluate,7 evaluate,
8 function::{parse_function_call, parse_function_call_map, place_args},8 function::{parse_function_call, parse_function_call_map, place_args},
9 native::NativeCallback,9 native::NativeCallback,
10 throw, with_state, Context, ObjValue, Result,10 throw, with_state, Context, ObjValue, Result,
11};11};
12use gc::{custom_trace, Finalize, Gc, GcCell, Trace};
12use jrsonnet_interner::IStr;13use jrsonnet_interner::IStr;
13use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, ExprLocation, LiteralType, LocExpr, ParamsDesc};14use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, ExprLocation, LiteralType, LocExpr, ParamsDesc};
14use jrsonnet_types::ValType;15use jrsonnet_types::ValType;
15use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};16use std::{collections::HashMap, fmt::Debug, rc::Rc};
17
18pub trait LazyValValue: Trace {
19 fn get(self: Box<Self>) -> Result<Val>;
20}
1621
17enum LazyValInternals {22enum LazyValInternals {
18 Computed(Val),23 Computed(Val),
24 Errored(LocError),
19 Waiting(Box<dyn Fn() -> Result<Val>>),25 Waiting(Box<dyn LazyValValue>),
26 Pending,
20}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}
39
21#[derive(Clone)]40#[derive(Clone, Trace, Finalize)]
22pub struct LazyVal(Rc<RefCell<LazyValInternals>>);41pub struct LazyVal(Gc<GcCell<LazyValInternals>>);
23impl LazyVal {42impl LazyVal {
24 pub fn new(f: Box<dyn Fn() -> Result<Val>>) -> Self {43 pub fn new(f: Box<dyn LazyValValue>) -> Self {
25 Self(Rc::new(RefCell::new(LazyValInternals::Waiting(f))))44 Self(Gc::new(GcCell::new(LazyValInternals::Waiting(f))))
26 }45 }
27 pub fn new_resolved(val: Val) -> Self {46 pub fn new_resolved(val: Val) -> Self {
28 Self(Rc::new(RefCell::new(LazyValInternals::Computed(val))))47 Self(Gc::new(GcCell::new(LazyValInternals::Computed(val))))
29 }48 }
30 pub fn evaluate(&self) -> Result<Val> {49 pub fn evaluate(&self) -> Result<Val> {
31 let new_value = match &*self.0.borrow() {50 match &*self.0.borrow() {
32 LazyValInternals::Computed(v) => return Ok(v.clone()),51 LazyValInternals::Computed(v) => return Ok(v.clone()),
33 LazyValInternals::Waiting(f) => f()?,52 LazyValInternals::Errored(e) => return Err(e.clone().into()),
53 LazyValInternals::Pending => return Err(RecursiveLazyValueEvaluation.into()),
54 _ => (),
34 };55 };
56 let value = if let LazyValInternals::Waiting(value) =
57 std::mem::replace(&mut *self.0.borrow_mut(), LazyValInternals::Pending)
58 {
59 value
60 } 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 };
35 *self.0.borrow_mut() = LazyValInternals::Computed(new_value.clone());70 *self.0.borrow_mut() = LazyValInternals::Computed(new_value.clone());
36 Ok(new_value)71 Ok(new_value)
37 }72 }
38}73}
3974
40#[macro_export]
41macro_rules! lazy_val {
42 ($f: expr) => {
43 $crate::LazyVal::new(Box::new($f))
44 };
45}
46#[macro_export]
47macro_rules! resolved_lazy_val {
48 ($f: expr) => {
49 $crate::LazyVal::new_resolved($f)
50 };
51}
52impl Debug for LazyVal {75impl Debug for LazyVal {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 write!(f, "Lazy")77 write!(f, "Lazy")
55 }78 }
56}79}
57impl PartialEq for LazyVal {80impl PartialEq for LazyVal {
58 fn eq(&self, other: &Self) -> bool {81 fn eq(&self, other: &Self) -> bool {
59 Rc::ptr_eq(&self.0, &other.0)82 Gc::ptr_eq(&self.0, &other.0)
60 }83 }
61}84}
6285
63#[derive(Debug, PartialEq)]86#[derive(Debug, PartialEq, Trace, Finalize)]
64pub struct FuncDesc {87pub struct FuncDesc {
65 pub name: IStr,88 pub name: IStr,
66 pub ctx: Context,89 pub ctx: Context,
67 pub params: ParamsDesc,90 pub params: ParamsDesc,
68 pub body: LocExpr,91 pub body: LocExpr,
69}92}
7093
71#[derive(Debug)]94#[derive(Debug, Trace, Finalize)]
72pub enum FuncVal {95pub enum FuncVal {
73 /// Plain function implemented in jsonnet96 /// Plain function implemented in jsonnet
74 Normal(FuncDesc),97 Normal(FuncDesc),
75 /// Standard library function98 /// Standard library function
76 Intrinsic(IStr),99 Intrinsic(IStr),
77 /// Library functions implemented in native100 /// Library functions implemented in native
78 NativeExt(IStr, Rc<NativeCallback>),101 NativeExt(IStr, Gc<NativeCallback>),
79}102}
80103
81impl PartialEq for FuncVal {104impl PartialEq for FuncVal {
174197
175#[derive(Debug, Clone)]198#[derive(Debug, Clone)]
176pub enum ArrValue {199pub enum ArrValue {
177 Lazy(Rc<Vec<LazyVal>>),200 Lazy(Gc<Vec<LazyVal>>),
178 Eager(Rc<Vec<Val>>),201 Eager(Gc<Vec<Val>>),
179 Extended(Box<(Self, Self)>),202 Extended(Box<(Self, Self)>),
180}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}
181impl ArrValue {214impl ArrValue {
182 pub fn new_eager() -> Self {215 pub fn new_eager() -> Self {
183 Self::Eager(Rc::new(Vec::new()))216 Self::Eager(Gc::new(Vec::new()))
184 }217 }
185218
186 pub fn len(&self) -> usize {219 pub fn len(&self) -> usize {
231 }264 }
232 }265 }
233266
234 pub fn evaluated(&self) -> Result<Rc<Vec<Val>>> {267 pub fn evaluated(&self) -> Result<Gc<Vec<Val>>> {
235 Ok(match self {268 Ok(match self {
236 Self::Lazy(vec) => {269 Self::Lazy(vec) => {
237 let mut out = Vec::with_capacity(vec.len());270 let mut out = Vec::with_capacity(vec.len());
238 for item in vec.iter() {271 for item in vec.iter() {
239 out.push(item.evaluate()?);272 out.push(item.evaluate()?);
240 }273 }
241 Rc::new(out)274 Gc::new(out)
242 }275 }
243 Self::Eager(vec) => vec.clone(),276 Self::Eager(vec) => vec.clone(),
244 Self::Extended(_v) => {277 Self::Extended(_v) => {
245 let mut out = Vec::with_capacity(self.len());278 let mut out = Vec::with_capacity(self.len());
246 for item in self.iter() {279 for item in self.iter() {
247 out.push(item?);280 out.push(item?);
248 }281 }
249 Rc::new(out)282 Gc::new(out)
250 }283 }
251 })284 })
252 }285 }
272 Self::Lazy(vec) => {305 Self::Lazy(vec) => {
273 let mut out = (&vec as &Vec<_>).clone();306 let mut out = (&vec as &Vec<_>).clone();
274 out.reverse();307 out.reverse();
275 Self::Lazy(Rc::new(out))308 Self::Lazy(Gc::new(out))
276 }309 }
277 Self::Eager(vec) => {310 Self::Eager(vec) => {
278 let mut out = (&vec as &Vec<_>).clone();311 let mut out = (&vec as &Vec<_>).clone();
279 out.reverse();312 out.reverse();
280 Self::Eager(Rc::new(out))313 Self::Eager(Gc::new(out))
281 }314 }
282 Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),315 Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),
283 }316 }
290 out.push(mapper(value?)?);323 out.push(mapper(value?)?);
291 }324 }
292325
293 Ok(Self::Eager(Rc::new(out)))326 Ok(Self::Eager(Gc::new(out)))
294 }327 }
295328
296 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {329 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {
303 }336 }
304 }337 }
305338
306 Ok(Self::Eager(Rc::new(out)))339 Ok(Self::Eager(Gc::new(out)))
307 }340 }
308341
309 pub fn ptr_eq(a: &Self, b: &Self) -> bool {342 pub fn ptr_eq(a: &Self, b: &Self) -> bool {
310 match (a, b) {343 match (a, b) {
311 (Self::Lazy(a), Self::Lazy(b)) => Rc::ptr_eq(a, b),344 (Self::Lazy(a), Self::Lazy(b)) => Gc::ptr_eq(a, b),
312 (Self::Eager(a), Self::Eager(b)) => Rc::ptr_eq(a, b),345 (Self::Eager(a), Self::Eager(b)) => Gc::ptr_eq(a, b),
313 _ => false,346 _ => false,
314 }347 }
315 }348 }
316}349}
317350
318impl From<Vec<LazyVal>> for ArrValue {351impl From<Vec<LazyVal>> for ArrValue {
319 fn from(v: Vec<LazyVal>) -> Self {352 fn from(v: Vec<LazyVal>) -> Self {
320 Self::Lazy(Rc::new(v))353 Self::Lazy(Gc::new(v))
321 }354 }
322}355}
323356
324impl From<Vec<Val>> for ArrValue {357impl From<Vec<Val>> for ArrValue {
325 fn from(v: Vec<Val>) -> Self {358 fn from(v: Vec<Val>) -> Self {
326 Self::Eager(Rc::new(v))359 Self::Eager(Gc::new(v))
327 }360 }
328}361}
362
363#[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 = DebugGcTraceValue {
404 name: self.name.clone(),
405 value: self.value.clone(),
406 };
407 value.print("I'm clone");
408 value
409 }
410}
411impl DebugGcTraceValue {
412 pub fn new(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}
329421
330#[derive(Debug, Clone)]422#[derive(Debug, Clone)]
331pub enum Val {423pub enum Val {
335 Num(f64),427 Num(f64),
336 Arr(ArrValue),428 Arr(ArrValue),
337 Obj(ObjValue),429 Obj(ObjValue),
338 Func(Rc<FuncVal>),430 Func(Gc<FuncVal>),
431 DebugGcTraceValue(DebugGcTraceValue),
339}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}
340448
341macro_rules! matches_unwrap {449macro_rules! matches_unwrap {
342 ($e: expr, $p: pat, $r: expr) => {450 ($e: expr, $p: pat, $r: expr) => {
368 pub fn unwrap_num(self) -> Result<f64> {476 pub fn unwrap_num(self) -> Result<f64> {
369 Ok(matches_unwrap!(self, Self::Num(v), v))477 Ok(matches_unwrap!(self, Self::Num(v), v))
370 }478 }
371 pub fn unwrap_func(self) -> Result<Rc<FuncVal>> {479 pub fn unwrap_func(self) -> Result<Gc<FuncVal>> {
372 Ok(matches_unwrap!(self, Self::Func(v), v))480 Ok(matches_unwrap!(self, Self::Func(v), v))
373 }481 }
374 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {482 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {
392 Self::Bool(_) => ValType::Bool,500 Self::Bool(_) => ValType::Bool,
393 Self::Null => ValType::Null,501 Self::Null => ValType::Null,
394 Self::Func(..) => ValType::Func,502 Self::Func(..) => ValType::Func,
503 Self::DebugGcTraceValue(v) => v.value.value_type(),
395 }504 }
396 }505 }
397506