git.delta.rocks / jrsonnet / refs/commits / 6435abec6b9f

difftreelog

feat(evaluator) argument parsing macro

Лач2020-06-27parent: #cfd7ffe.patch.diff
in: master

2 files changed

modifiedcrates/jsonnet-evaluator/src/error.rsdiffbeforeafterboth
--- a/crates/jsonnet-evaluator/src/error.rs
+++ b/crates/jsonnet-evaluator/src/error.rs
@@ -6,6 +6,7 @@
 pub enum Error {
 	VariableIsNotDefined(String),
 	TypeMismatch(&'static str, Vec<ValType>, ValType),
+	IntristicArgumentReorderingIsNotSupportedYet,
 	NoSuchField(Rc<str>),
 
 	UnknownVariable(Rc<str>),
modifiedcrates/jsonnet-evaluator/src/function.rsdiffbeforeafterboth
94 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)94 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)
95}95}
96
97#[macro_export]
98macro_rules! parse_args {
99 ($ctx: expr, $fn_name: expr, $args: expr, $total_args: expr, [
100 $($id: expr, $name: ident $(: [$($p: path)|+] $(!! $a: path)?)?, $nt: expr);+ $(;)?
101 ], $handler:block) => {{
102 use crate::error::Error;
103 let args = $args;
104 if args.len() > $total_args {
105 create_error(Error::TooManyArgsFunctionHas($total_args))?;
106 }
107 $(
108 if args.len() <= $id {
109 create_error(Error::FunctionParameterNotBoundInCall(stringify!($name).into()))?;
110 }
111 let $name = &args[$id];
112 if $name.0.is_some() {
113 if $name.0.as_ref().unwrap() != stringify!($name) {
114 create_error(Error::IntristicArgumentReorderingIsNotSupportedYet)?;
115 }
116 }
117 let $name = evaluate($ctx.clone(), &$name.1)?;
118 $(
119 match $name {
120 $($p(_))|+ => {},
121 _ => create_error(Error::TypeMismatch(concat!($fn_name, " ", stringify!($id), "nd argument"), $nt, $name.value_type()?))?,
122 };
123 $(
124 let $name = match $name {
125 $a(v) => v,
126 _ => create_error(Error::TypeMismatch(concat!($fn_name, " ", stringify!($id), "nd argument"), $nt, $name.value_type()?))?,
127 };
128 )*
129 )*
130 )+
131 $handler
132 }};
133}
134
135#[test]
136fn test() -> Result<()> {
137 use jsonnet_parser::*;
138 use crate::val::ValType;
139 let state = crate::EvaluationState::default();
140 let evaluator = state.with_stdlib();
141 let ctx = evaluator.create_default_context()?;
142 evaluator.run_in_state(|| {
143 parse_args!(ctx, "test", ArgsDesc(vec![
144 Arg(None, el!(Expr::Num(2.0))),
145 Arg(Some("b".into()), el!(Expr::Num(1.0))),
146 ]), 2, [
147 0, a: [Val::Num]!!Val::Num, vec![ValType::Num];
148 1, b: [Val::Num]!!Val::Num, vec![ValType::Num];
149 ], {
150 assert!((a - 2.0).abs() <= f64::EPSILON);
151 assert!((b - 1.0).abs() <= f64::EPSILON);
152 });
153 Ok(())
154 })
155}
96156