difftreelog
feat argument map function call
in: master
2 files changed
crates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth4};4};5use closure::closure;5use closure::closure;6use jrsonnet_parser::{ArgsDesc, ParamsDesc};6use jrsonnet_parser::{ArgsDesc, ParamsDesc};7use std::collections::HashMap;7use std::{collections::HashMap, rc::Rc};89const NO_DEFAULT_CONTEXT: &str =10 "no default context set for call with defined default parameter value";8119/// Creates correct [context](Context) for function body evaluation, returning error on invalid call12/// Creates correct [context](Context) for function body evaluation, returning error on invalid call10///13///45 let (ctx, expr) = if let Some(arg) = &positioned_args[id] {48 let (ctx, expr) = if let Some(arg) = &positioned_args[id] {46 (ctx.clone(), arg)49 (ctx.clone(), arg)47 } else if let Some(default) = &p.1 {50 } else if let Some(default) = &p.1 {48 (51 (body_ctx.clone().expect(NO_DEFAULT_CONTEXT), default)49 body_ctx50 .clone()51 .expect("no default context set for call with defined default parameter value"),52 default,53 )54 } else {52 } else {55 create_error_result(Error::FunctionParameterNotBoundInCall(p.0.clone()))?;53 create_error_result(Error::FunctionParameterNotBoundInCall(p.0.clone()))?;66 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)64 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)67}65}6667pub fn parse_function_call_map(68 ctx: Context,69 body_ctx: Option<Context>,70 params: &ParamsDesc,71 args: &HashMap<Rc<str>, Val>,72 tailstrict: bool,73) -> Result<Context> {74 let mut out = HashMap::new();75 let mut positioned_args = vec![None; params.0.len()];76 for (name, val) in args.iter() {77 let idx = params.iter().position(|p| *p.0 == **name).ok_or_else(|| {78 create_error(Error::UnknownFunctionParameter((&name as &str).to_owned()))79 })?;8081 if idx >= params.len() {82 create_error_result(Error::TooManyArgsFunctionHas(params.len()))?;83 }84 if positioned_args[idx].is_some() {85 create_error_result(Error::BindingParameterASecondTime(params[idx].0.clone()))?;86 }87 positioned_args[idx] = Some(val.clone());88 }89 // Fill defaults90 for (id, p) in params.iter().enumerate() {91 let val = if let Some(arg) = positioned_args[id].take() {92 resolved_lazy_val!(arg)93 } else if let Some(default) = &p.1 {94 if tailstrict {95 resolved_lazy_val!(evaluate(96 body_ctx.clone().expect(NO_DEFAULT_CONTEXT),97 default98 )?)99 } else {100 let body_ctx = body_ctx.clone();101 let default = default.clone();102 lazy_val!(move || {103 evaluate(body_ctx.clone().expect(NO_DEFAULT_CONTEXT), &default)104 })105 }106 } else {107 create_error_result(Error::FunctionParameterNotBoundInCall(p.0.clone()))?;108 unreachable!()109 };110 out.insert(p.0.clone(), val);111 }112113 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)114}6811569pub(crate) fn place_args(116pub(crate) fn place_args(70 ctx: Context,117 ctx: Context,crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -1,11 +1,12 @@
use crate::{
create_error_result, evaluate,
- function::{parse_function_call, place_args},
+ function::{parse_function_call, parse_function_call_map, place_args},
with_state, Context, Error, ObjValue, Result,
};
use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParamsDesc};
use std::{
cell::RefCell,
+ collections::HashMap,
fmt::{Debug, Display},
rc::Rc,
};
@@ -76,6 +77,22 @@
evaluate(ctx, &self.body)
}
+ pub fn evaluate_map(
+ &self,
+ call_ctx: Context,
+ args: &HashMap<Rc<str>, Val>,
+ tailstrict: bool,
+ ) -> Result<Val> {
+ let ctx = parse_function_call_map(
+ call_ctx,
+ Some(self.ctx.clone()),
+ &self.params,
+ args,
+ tailstrict,
+ )?;
+ evaluate(ctx, &self.body)
+ }
+
pub fn evaluate_values(&self, call_ctx: Context, args: &[Val]) -> Result<Val> {
let ctx = place_args(call_ctx, Some(self.ctx.clone()), &self.params, args)?;
evaluate(ctx, &self.body)