difftreelog
feat(jrsonnet-evaluator) implement gc
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
crates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth30jrsonnet-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"3233closure = "0.3.0"343235md5 = "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"383639thiserror = "1.0"37thiserror = "1.0"38gc = { version = "0.4.1", features = ["derive"] }403941[dependencies.anyhow]40[dependencies.anyhow]42version = "1.0"41version = "1.0"crates/jrsonnet-evaluator/src/builtin/format.rsdiffbeforeafterboth2#![allow(clippy::too_many_arguments)]2#![allow(clippy::too_many_arguments)]334use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val};4use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val};5use 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;899#[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,crates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth126 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}crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth1use 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}307310446 })449 })447}450}451452fn 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");459460 Ok(rest)461 })462}463464fn 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 ], {469470 Ok(DebugGcTraceValue::new(name, rest))471 })472}448473449fn 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, [crates/jrsonnet-evaluator/src/builtin/sort.rsdiffbeforeafterboth2 error::{Error, LocError, Result},2 error::{Error, LocError, Result},3 throw, Context, FuncVal, Val,3 throw, Context, FuncVal, Val,4};4};5use std::rc::Rc;5use gc::{Finalize, Gc, Trace};667#[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}616162pub 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}104104crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth1use 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;91010#[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}222324#[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}373638#[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 }565557 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 }878696 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 cloning102 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();166146167impl 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}172173#[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}188152crates/jrsonnet-evaluator/src/dynamic.rsdiffbeforeafterboth1use std::{cell::RefCell, rc::Rc};1use gc::{Finalize, Gc, GcCell, Trace};223#[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}191920impl<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 }crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth2 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;101111#[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 },939594 #[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}144148145#[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>);152156153#[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 {crates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth1use 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();2425 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 }5023 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();8889 struct BindableMethodLazyVal {90 this: Option<ObjValue>,91 super_obj: Option<ObjValue>,9293 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 }119120 #[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(),132133 context_creator: self.context_creator.clone(),134 name: self.name.clone(),135 params: self.params.clone(),136 value: self.value.clone(),137 })))138 }139 }14042 (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>,154155 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 }178179 #[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,190191 context_creator: self.context_creator.clone(),192 name: self.name.clone(),193 value: self.value.clone(),194 })))195 }196 }19756 (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}7020871pub 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,105243106pub 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()),109250110 // 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 }258399259 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();416417 #[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: Assert312 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 })?;383601384 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 this387 }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)?crates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth1use 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};7753 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 }7458 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 defaults90 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 }140171141 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))172 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth2 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};141415impl 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 }crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth25use error::{Error::*, LocError, Result, StackTraceElement};25use error::{Error::*, LocError, Result, StackTraceElement};26pub use evaluate::*;26pub use evaluate::*;27pub use function::parse_function_call;27pub use function::parse_function_call;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::*;444546pub 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}515457impl 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.native74 pub ext_natives: HashMap<IStr, Rc<NativeCallback>>,77 pub ext_natives: HashMap<IStr, Gc<NativeCallback>>,75 /// TLA vars78 /// TLA vars76 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 context270 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 }451454452 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 }455458crates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth1use gc::{Finalize, Gc, Trace};1use jrsonnet_interner::IStr;2use jrsonnet_interner::IStr;2use rustc_hash::FxHashMap;3use rustc_hash::FxHashMap;3use std::rc::Rc;445#[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}910unsafe 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> {}101711#[derive(Debug)]18#[derive(Trace, Finalize)]12pub struct LayeredHashMap<V>(Rc<LayeredHashMapInternals<V>>);19pub struct LayeredHashMap<V: Trace + Finalize + 'static>(Gc<LayeredHashMapInternals<V>>);132014impl<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 }272828 pub fn get(&self, key: &IStr) -> Option<&V> {29 pub fn get(&self, key: &IStr) -> Option<&V> {33 }34 }34}35}353636impl<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}414242impl<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 }))crates/jrsonnet-evaluator/src/native.rsdiffbeforeafterboth1#![allow(clippy::type_complexity)]1#![allow(clippy::type_complexity)]223use 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;8910pub trait NativeCallbackHandler: Trace {11 fn call(&self, from: Option<Rc<PathBuf>>, args: &[Val]) -> Result<Val>;12}1314#[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 {crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth1use 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};788#[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}1617pub trait ObjectAssertion: Trace {18 fn run(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<()>;19}152016// Field => This21// Field => This17type 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}283229#[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() {555956impl 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 }108102203 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 }213202249 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.0254 .context255 .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 }272255273 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}277260278impl 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}283266284impl 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}290273crates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth4 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}222323#[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}394040#[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}616262#[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}124125125#[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}139140140#[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 {crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth3 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};1718pub trait LazyValValue: Trace {19 fn get(self: Box<Self>) -> Result<Val>;20}162117enum 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}3921#[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 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 };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}397440#[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}628563#[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}709371#[derive(Debug)]94#[derive(Debug, Trace, Finalize)]72pub enum FuncVal {95pub enum FuncVal {73 /// Plain function implemented in jsonnet96 /// Plain function implemented in jsonnet74 Normal(FuncDesc),97 Normal(FuncDesc),75 /// Standard library function98 /// Standard library function76 Intrinsic(IStr),99 Intrinsic(IStr),77 /// Library functions implemented in native100 /// Library functions implemented in native78 NativeExt(IStr, Rc<NativeCallback>),101 NativeExt(IStr, Gc<NativeCallback>),79}102}8010381impl PartialEq for FuncVal {104impl PartialEq for FuncVal {174197175#[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 }185218186 pub fn len(&self) -> usize {219 pub fn len(&self) -> usize {231 }264 }232 }265 }233266234 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 }292325293 Ok(Self::Eager(Rc::new(out)))326 Ok(Self::Eager(Gc::new(out)))294 }327 }295328296 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 }305338306 Ok(Self::Eager(Rc::new(out)))339 Ok(Self::Eager(Gc::new(out)))307 }340 }308341309 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}317350318impl 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}323356324impl 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}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 = DebugGcTraceValue {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 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}329421330#[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}340448341macro_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