--- a/bindings/jsonnet/src/native.rs +++ b/bindings/jsonnet/src/native.rs @@ -35,7 +35,7 @@ vm.add_native( name, - Rc::new(NativeCallback::new(params, move |args| { + Rc::new(NativeCallback::new(params, move |_caller, args| { let mut n_args = Vec::new(); for a in args { n_args.push(Some(Box::new(a.clone()))); --- a/crates/jrsonnet-evaluator/src/evaluate.rs +++ b/crates/jrsonnet-evaluator/src/evaluate.rs @@ -540,7 +540,9 @@ &evaluate(context.clone(), s)?, &Val::Obj(evaluate_object(context, t)?), )?, - Apply(value, args, tailstrict) => evaluate_apply(context, value, args, loc.as_ref(), *tailstrict)?, + Apply(value, args, tailstrict) => { + evaluate_apply(context, value, args, loc.as_ref(), *tailstrict)? + } Function(params, body) => { evaluate_method(context, "anonymous".into(), params.clone(), body.clone()) } --- a/crates/jrsonnet-evaluator/src/lib.rs +++ b/crates/jrsonnet-evaluator/src/lib.rs @@ -886,14 +886,20 @@ Param("a".into(), None), Param("b".into(), None), ])), - |args| match (&args[0], &args[1]) { - (Val::Num(a), Val::Num(b)) => Ok(Val::Num(a + b)), - (_, _) => todo!(), + |caller, args| { + assert_eq!( + caller.unwrap(), + Rc::new(PathBuf::from("native_caller.jsonnet")) + ); + match (&args[0], &args[1]) { + (Val::Num(a), Val::Num(b)) => Ok(Val::Num(a + b)), + (_, _) => unreachable!(), + } }, )), ); evaluator.evaluate_snippet_raw( - Rc::new(PathBuf::from("test.jsonnet")), + Rc::new(PathBuf::from("native_caller.jsonnet")), "std.assertEqual(std.native(\"native_add\")(1, 2), 3)".into(), )?; Ok(()) --- a/crates/jrsonnet-evaluator/src/native.rs +++ b/crates/jrsonnet-evaluator/src/native.rs @@ -1,20 +1,25 @@ use crate::{error::Result, Val}; use jrsonnet_parser::ParamsDesc; use std::fmt::Debug; +use std::path::PathBuf; +use std::rc::Rc; pub struct NativeCallback { pub params: ParamsDesc, - handler: Box Result>, + handler: Box>, &[Val]) -> Result>, } impl NativeCallback { - pub fn new(params: ParamsDesc, handler: impl Fn(&[Val]) -> Result + 'static) -> Self { + pub fn new( + params: ParamsDesc, + handler: impl Fn(Option>, &[Val]) -> Result + 'static, + ) -> Self { Self { params, handler: Box::new(handler), } } - pub fn call(&self, args: &[Val]) -> Result { - (self.handler)(args) + pub fn call(&self, caller: Option>, args: &[Val]) -> Result { + (self.handler)(caller, args) } } impl Debug for NativeCallback { --- a/crates/jrsonnet-evaluator/src/val.rs +++ b/crates/jrsonnet-evaluator/src/val.rs @@ -124,7 +124,7 @@ for p in handler.params.0.iter() { out_args.push(args.binding(p.0.clone())?.evaluate()?); } - Ok(handler.call(&out_args)?) + Ok(handler.call(loc.clone().map(|l| l.0.clone()), &out_args)?) } } }