difftreelog
feat FuncDesc helper for default context
in: master
2 files changed
crates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function.rs
+++ b/crates/jrsonnet-evaluator/src/function.rs
@@ -23,6 +23,18 @@
}
}
+#[derive(Trace)]
+struct EvaluateNamedLazyVal {
+ future_context: FutureWrapper<Context>,
+ name: IStr,
+ value: LocExpr,
+}
+impl LazyValValue for EvaluateNamedLazyVal {
+ fn get(self: Box<Self>) -> Result<Val> {
+ evaluate_named(self.future_context.unwrap(), &self.value, self.name)
+ }
+}
+
pub trait ArgLike {
fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<LazyVal>;
}
@@ -309,25 +321,14 @@
if filled_args < params.len() {
// Some args are unset, but maybe we have defaults for them
// Default values should be created in newly created context
- let future_context = FutureWrapper::<Context>::new();
+ let future_context = Context::new_future();
let mut defaults = GcHashMap::with_capacity(params.len() - filled_args);
for param in params.iter().filter(|p| p.1.is_some()) {
if passed_args.contains_key(¶m.0.clone()) {
continue;
}
- #[derive(Trace)]
- struct LazyNamedBinding {
- future_context: FutureWrapper<Context>,
- name: IStr,
- value: LocExpr,
- }
- impl LazyValValue for LazyNamedBinding {
- fn get(self: Box<Self>) -> Result<Val> {
- evaluate_named(self.future_context.unwrap(), &self.value, self.name)
- }
- }
- LazyVal::new(TraceBox(Box::new(LazyNamedBinding {
+ LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {
future_context: future_context.clone(),
name: param.0.clone(),
value: param.1.clone().unwrap(),
@@ -335,7 +336,7 @@
defaults.insert(
param.0.clone(),
- LazyVal::new(TraceBox(Box::new(LazyNamedBinding {
+ LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {
future_context: future_context.clone(),
name: param.0.clone(),
value: param.1.clone().unwrap(),
@@ -464,3 +465,39 @@
}
Ok(passed_args)
}
+
+/// Creates Context, which has all argument default values applied
+/// and with unbound values causing error to be returned
+pub fn parse_default_function_call(body_ctx: Context, params: &ParamsDesc) -> Context {
+ let ctx = Context::new_future();
+
+ let mut bindings = GcHashMap::new();
+
+ #[derive(Trace)]
+ struct DependsOnUnbound(IStr);
+ impl LazyValValue for DependsOnUnbound {
+ fn get(self: Box<Self>) -> Result<Val> {
+ Err(FunctionParameterNotBoundInCall(self.0.clone()).into())
+ }
+ }
+
+ for param in params.iter() {
+ if let Some(v) = ¶m.1 {
+ bindings.insert(
+ param.0.clone(),
+ LazyVal::new(TraceBox(Box::new(EvaluateNamedLazyVal {
+ future_context: ctx.clone(),
+ name: param.0.clone(),
+ value: v.clone(),
+ }))),
+ );
+ } else {
+ bindings.insert(
+ param.0.clone(),
+ LazyVal::new(TraceBox(Box::new(DependsOnUnbound(param.0.clone())))),
+ );
+ }
+ }
+
+ body_ctx.extend(bindings, None, None, None).into_future(ctx)
+}
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth6 error::{Error::*, LocError},6 error::{Error::*, LocError},7 evaluate,7 evaluate,8 function::{parse_function_call, ArgsLike, Builtin, StaticBuiltin},8 function::{9 parse_default_function_call, parse_function_call, ArgsLike, Builtin, StaticBuiltin,10 },9 gc::TraceBox,11 gc::TraceBox,10 throw, Context, ObjValue, Result,12 throw, Context, ObjValue, Result,84 pub params: ParamsDesc,86 pub params: ParamsDesc,85 pub body: LocExpr,87 pub body: LocExpr,86}88}89impl FuncDesc {90 /// Create body context, but fill arguments without defaults with lazy error91 pub fn default_body_context(&self) -> Context {92 parse_default_function_call(self.ctx.clone(), &self.params)93 }9495 /// Create context, with which body code will run96 pub fn call_body_context(97 &self,98 call_ctx: Context,99 args: &dyn ArgsLike,100 tailstrict: bool,101 ) -> Result<Context> {102 parse_function_call(call_ctx, self.ctx.clone(), &self.params, args, tailstrict)103 }104}8710588#[derive(Trace, Clone)]106#[derive(Trace, Clone)]89pub enum FuncVal {107pub enum FuncVal {140 ) -> Result<Val> {158 ) -> Result<Val> {141 match self {159 match self {142 Self::Normal(func) => {160 Self::Normal(func) => {143 let ctx = parse_function_call(161 let body_ctx = func.call_body_context(call_ctx, args, tailstrict)?;144 call_ctx,145 func.ctx.clone(),146 &func.params,147 args,148 tailstrict,149 )?;150 evaluate(ctx, &func.body)162 evaluate(body_ctx, &func.body)151 }163 }152 Self::StaticBuiltin(name) => name.call(call_ctx, loc, args),164 Self::StaticBuiltin(b) => b.call(call_ctx, loc, args),153 Self::Builtin(b) => b.call(call_ctx, loc, args),165 Self::Builtin(b) => b.call(call_ctx, loc, args),154 }166 }155 }167 }