difftreelog
fix(evaluator) indirect_self bug
in: master
4 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,9 +1,16 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
+name = "closure"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6173fd61b610d15a7566dd7b7620775627441c4ab9dac8906e17cb93a24b782"
+
+[[package]]
name = "jsonnet-evaluator"
version = "0.1.0"
dependencies = [
+ "closure",
"jsonnet-parser",
"jsonnet-stdlib",
]
crates/jsonnet-evaluator/src/ctx.rsdiffbeforeafterboth1use crate::{future_wrapper, rc_fn_helper, Binding, ObjValue};2use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};34rc_fn_helper!(5 ContextCreator,6 context_creator,7 dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Context8);910future_wrapper!(Context, FutureContext);1112#[derive(Debug)]13struct ContextInternals {14 dollar: Option<ObjValue>,15 this: Option<ObjValue>,16 super_obj: Option<ObjValue>,17 bindings: Rc<RefCell<HashMap<String, Binding>>>,18}19pub struct Context(Rc<ContextInternals>);20impl Debug for Context {21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {22 f.debug_struct("Context")23 .field("this", &self.0.this.clone().map(|e| Rc::as_ptr(&e.0)))24 .finish()25 }26}27impl Context {28 pub fn new_future() -> FutureContext {29 FutureContext(Rc::new(RefCell::new(None)))30 }3132 pub fn dollar(&self) -> &Option<ObjValue> {33 &self.0.dollar34 }3536 pub fn this(&self) -> &Option<ObjValue> {37 &self.0.this38 }3940 pub fn super_obj(&self) -> &Option<ObjValue> {41 &self.0.super_obj42 }4344 pub fn new() -> Context {45 Context(Rc::new(ContextInternals {46 dollar: None,47 this: None,48 super_obj: None,49 bindings: Rc::new(RefCell::new(HashMap::new())),50 }))51 }5253 pub fn binding(&self, name: &str) -> Binding {54 self.055 .bindings56 .borrow()57 .get(name)58 .cloned()59 .unwrap_or_else(|| {60 panic!("can't find {} in {:?}", name, self);61 })62 }63 pub fn into_future(self, ctx: FutureContext) -> Context {64 {65 ctx.0.borrow_mut().replace(self);66 }67 ctx.unwrap()68 }6970 pub fn extend(71 &self,72 new_bindings: HashMap<String, Binding>,73 new_dollar: Option<ObjValue>,74 new_this: Option<ObjValue>,75 new_super_obj: Option<ObjValue>,76 ) -> Context {77 println!("Extend with {:?} {:?}", new_dollar, new_this);78 let dollar = new_dollar.or_else(|| self.0.dollar.clone());79 let this = new_this.or_else(|| self.0.this.clone());80 let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());81 let bindings = if new_bindings.is_empty() {82 self.0.bindings.clone()83 } else {84 let new = self.0.bindings.clone();85 for (k, v) in new_bindings.into_iter() {86 new.borrow_mut().insert(k, v);87 }88 new89 };90 Context(Rc::new(ContextInternals {91 dollar,92 this,93 super_obj,94 bindings,95 }))96 }97}9899impl Default for Context {100 fn default() -> Self {101 Self::new()102 }103}104105impl PartialEq for Context {106 fn eq(&self, other: &Self) -> bool {107 Rc::ptr_eq(&self.0, &other.0)108 }109}110111impl Clone for Context {112 fn clone(&self) -> Self {113 Context(self.0.clone())114 }115}crates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/evaluate.rs
+++ b/crates/jsonnet-evaluator/src/evaluate.rs
@@ -29,9 +29,8 @@
} else {
(
b.name.clone(),
- binding!(move |this, super_obj| {
- println!("Evaluating binding");
- Val::Lazy(lazy_val!(
+ binding!(move |this, super_obj| {
+ Val::Lazy(lazy_val!(
closure!(clone context_creator, clone b, || evaluate(
context_creator.0(this.clone(), super_obj.clone()),
&b.value
@@ -137,12 +136,11 @@
let future_bindings = FutureNewBindings::new();
let future_this = FutureObjValue::new();
let context_creator = context_creator!(
- closure!(clone context, clone future_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
- println!("Context created");
+ closure!(clone context, clone future_bindings, clone future_this, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
context.clone().extend(
future_bindings.clone().unwrap(),
context.clone().dollar().clone().or_else(||this.clone()),
- this,
+ Some(future_this.clone().unwrap()),
super_obj
)
})
@@ -154,15 +152,12 @@
Member::BindStmt(b) => Some(b.clone()),
_ => None,
})
- .map(|b| {
- evaluate_binding(&b, context_creator.clone())
- })
+ .map(|b| evaluate_binding(&b, context_creator.clone()))
{
bindings.insert(n, b);
}
future_bindings.fill(bindings);
- println!("Bindings filled");
let mut new_members = BTreeMap::new();
for member in members.into_iter() {
match member {
@@ -180,8 +175,7 @@
add: plus,
visibility: visibility.clone(),
invoke: binding!(
- closure!(clone value, clone context_creator, clone future_this, |this, super_obj| {
- // FIXME: I should take "this" instead of "future_this" there?
+ closure!(clone value, clone context_creator, |this, super_obj| {
// TODO: Assert
evaluate(
context_creator.0(this, super_obj),
@@ -205,8 +199,7 @@
add: false,
visibility: Visibility::Hidden,
invoke: binding!(
- closure!(clone value, clone context_creator, clone future_this, |this, super_obj| {
- // FIXME: I should take "this" instead of "future_this" there?
+ closure!(clone value, clone context_creator, |this, super_obj| {
// TODO: Assert
evaluate_method(
context_creator.0(this, super_obj),
@@ -231,15 +224,12 @@
pub fn evaluate(context: Context, expr: &Expr) -> Val {
use Expr::*;
match &*expr {
- Literal(LiteralType::This) => {
- println!("{:?}", context.this());
- Val::Obj(
- context
- .this()
- .clone()
- .unwrap_or_else(|| panic!("this not found")),
- )
- }
+ Literal(LiteralType::This) => Val::Obj(
+ context
+ .this()
+ .clone()
+ .unwrap_or_else(|| panic!("this not found")),
+ ),
Literal(LiteralType::Super) => Val::Obj(
context
.super_obj()
crates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/lib.rs
+++ b/crates/jsonnet-evaluator/src/lib.rs
@@ -193,7 +193,7 @@
// referenced from field
eval_stdlib!(
r#"{
- local me = std.trace("test", self),
+ local me = self,
b: me,
}.b"#
);