git.delta.rocks / jrsonnet / refs/commits / b14023b0be60

difftreelog

feat argument map function call

Лач2020-07-19parent: #be66091.patch.diff
in: master

2 files changed

modifiedcrates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth
4};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};
8
9const NO_DEFAULT_CONTEXT: &str =
10 "no default context set for call with defined default parameter value";
811
9/// 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 call
10///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_ctx
50 .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}
66
67pub 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 })?;
80
81 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 defaults
90 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 default
98 )?)
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 }
112
113 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)
114}
68115
69pub(crate) fn place_args(116pub(crate) fn place_args(
70 ctx: Context,117 ctx: Context,
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 create_error_result, evaluate,2 create_error_result, evaluate,
3 function::{parse_function_call, place_args},3 function::{parse_function_call, parse_function_call_map, place_args},
4 with_state, Context, Error, ObjValue, Result,4 with_state, Context, Error, ObjValue, Result,
5};5};
6use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParamsDesc};6use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParamsDesc};
7use std::{7use std::{
8 cell::RefCell,8 cell::RefCell,
9 collections::HashMap,
9 fmt::{Debug, Display},10 fmt::{Debug, Display},
10 rc::Rc,11 rc::Rc,
11};12};
76 evaluate(ctx, &self.body)77 evaluate(ctx, &self.body)
77 }78 }
79
80 pub fn evaluate_map(
81 &self,
82 call_ctx: Context,
83 args: &HashMap<Rc<str>, Val>,
84 tailstrict: bool,
85 ) -> Result<Val> {
86 let ctx = parse_function_call_map(
87 call_ctx,
88 Some(self.ctx.clone()),
89 &self.params,
90 args,
91 tailstrict,
92 )?;
93 evaluate(ctx, &self.body)
94 }
7895
79 pub fn evaluate_values(&self, call_ctx: Context, args: &[Val]) -> Result<Val> {96 pub fn evaluate_values(&self, call_ctx: Context, args: &[Val]) -> Result<Val> {
80 let ctx = place_args(call_ctx, Some(self.ctx.clone()), &self.params, args)?;97 let ctx = place_args(call_ctx, Some(self.ctx.clone()), &self.params, args)?;