difftreelog
feat FuncDesc helper for default context
in: master
2 files changed
crates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth23 }23 }24}24}2526#[derive(Trace)]27struct EvaluateNamedLazyVal {28 future_context: FutureWrapper<Context>,29 name: IStr,30 value: LocExpr,31}32impl LazyValValue for EvaluateNamedLazyVal {33 fn get(self: Box<Self>) -> Result<Val> {34 evaluate_named(self.future_context.unwrap(), &self.value, self.name)35 }36}253726pub trait ArgLike {38pub trait ArgLike {27 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<LazyVal>;39 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<LazyVal>;309 if filled_args < params.len() {321 if filled_args < params.len() {310 // Some args are unset, but maybe we have defaults for them322 // Some args are unset, but maybe we have defaults for them311 // Default values should be created in newly created context323 // Default values should be created in newly created context312 let future_context = FutureWrapper::<Context>::new();324 let future_context = Context::new_future();313 let mut defaults = GcHashMap::with_capacity(params.len() - filled_args);325 let mut defaults = GcHashMap::with_capacity(params.len() - filled_args);314326315 for param in params.iter().filter(|p| p.1.is_some()) {327 for param in params.iter().filter(|p| p.1.is_some()) {316 if passed_args.contains_key(¶m.0.clone()) {328 if passed_args.contains_key(¶m.0.clone()) {317 continue;329 continue;318 }330 }319 #[derive(Trace)]320 struct LazyNamedBinding {321 future_context: FutureWrapper<Context>,322 name: IStr,323 value: LocExpr,324 }325 impl LazyValValue for LazyNamedBinding {326 fn get(self: Box<Self>) -> Result<Val> {327 evaluate_named(self.future_context.unwrap(), &self.value, self.name)328 }329 }330 LazyVal::new(TraceBox(Box::new(LazyNamedBinding {331 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {331 future_context: future_context.clone(),332 future_context: future_context.clone(),332 name: param.0.clone(),333 name: param.0.clone(),333 value: param.1.clone().unwrap(),334 value: param.1.clone().unwrap(),334 })));335 })));335336336 defaults.insert(337 defaults.insert(337 param.0.clone(),338 param.0.clone(),338 LazyVal::new(TraceBox(Box::new(LazyNamedBinding {339 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {339 future_context: future_context.clone(),340 future_context: future_context.clone(),340 name: param.0.clone(),341 name: param.0.clone(),341 value: param.1.clone().unwrap(),342 value: param.1.clone().unwrap(),465 Ok(passed_args)466 Ok(passed_args)466}467}468469/// Creates Context, which has all argument default values applied470/// and with unbound values causing error to be returned471pub fn parse_default_function_call(body_ctx: Context, params: &ParamsDesc) -> Context {472 let ctx = Context::new_future();473474 let mut bindings = GcHashMap::new();475476 #[derive(Trace)]477 struct DependsOnUnbound(IStr);478 impl LazyValValue for DependsOnUnbound {479 fn get(self: Box<Self>) -> Result<Val> {480 Err(FunctionParameterNotBoundInCall(self.0.clone()).into())481 }482 }483484 for param in params.iter() {485 if let Some(v) = ¶m.1 {486 bindings.insert(487 param.0.clone(),488 LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {489 future_context: ctx.clone(),490 name: param.0.clone(),491 value: v.clone(),492 }))),493 );494 } else {495 bindings.insert(496 param.0.clone(),497 LazyVal::new(TraceBox(Box::new(DependsOnUnbound(param.0.clone())))),498 );499 }500 }501502 body_ctx.extend(bindings, None, None, None).into_future(ctx)503}467504crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -5,7 +5,9 @@
cc_ptr_eq,
error::{Error::*, LocError},
evaluate,
- function::{parse_function_call, ArgsLike, Builtin, StaticBuiltin},
+ function::{
+ parse_default_function_call, parse_function_call, ArgsLike, Builtin, StaticBuiltin,
+ },
gc::TraceBox,
throw, Context, ObjValue, Result,
};
@@ -84,6 +86,22 @@
pub params: ParamsDesc,
pub body: LocExpr,
}
+impl FuncDesc {
+ /// Create body context, but fill arguments without defaults with lazy error
+ pub fn default_body_context(&self) -> Context {
+ parse_default_function_call(self.ctx.clone(), &self.params)
+ }
+
+ /// Create context, with which body code will run
+ pub fn call_body_context(
+ &self,
+ call_ctx: Context,
+ args: &dyn ArgsLike,
+ tailstrict: bool,
+ ) -> Result<Context> {
+ parse_function_call(call_ctx, self.ctx.clone(), &self.params, args, tailstrict)
+ }
+}
#[derive(Trace, Clone)]
pub enum FuncVal {
@@ -140,16 +158,10 @@
) -> Result<Val> {
match self {
Self::Normal(func) => {
- let ctx = parse_function_call(
- call_ctx,
- func.ctx.clone(),
- &func.params,
- args,
- tailstrict,
- )?;
- evaluate(ctx, &func.body)
+ let body_ctx = func.call_body_context(call_ctx, args, tailstrict)?;
+ evaluate(body_ctx, &func.body)
}
- Self::StaticBuiltin(name) => name.call(call_ctx, loc, args),
+ Self::StaticBuiltin(b) => b.call(call_ctx, loc, args),
Self::Builtin(b) => b.call(call_ctx, loc, args),
}
}