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
before · crates/jsonnet-evaluator/src/error.rs
1use crate::ValType;2use jsonnet_parser::ExprLocation;3use std::{path::PathBuf, rc::Rc};45#[derive(Debug, Clone)]6pub enum Error {7	VariableIsNotDefined(String),8	TypeMismatch(&'static str, Vec<ValType>, ValType),9	NoSuchField(Rc<str>),1011	UnknownVariable(Rc<str>),1213	UnknownFunctionParameter(String),14	BindingParameterASecondTime(Rc<str>),15	TooManyArgsFunctionHas(usize),16	FunctionParameterNotBoundInCall(Rc<str>),1718	UndefinedExternalVariable(Rc<str>),1920	FieldMustBeStringGot(ValType),2122	AttemptedIndexAnArrayWithString(Rc<str>),23	ValueIndexMustBeTypeGot(ValType, ValType, ValType),24	CantIndexInto(ValType),2526	StandaloneSuper,2728	ImportFileNotFound(PathBuf, PathBuf),29	ResolvedFileNotFound(PathBuf),30	ImportBadFileUtf8(PathBuf),31	ImportNotSupported(PathBuf, PathBuf),32	ImportSyntaxError(jsonnet_parser::ParseError),3334	RuntimeError(Rc<str>),35	StackOverflow,36	FractionalIndex,37	DivisionByZero,38}3940#[derive(Clone, Debug)]41pub struct StackTraceElement(pub ExprLocation, pub String);42#[derive(Debug, Clone)]43pub struct StackTrace(pub Vec<StackTraceElement>);4445#[derive(Debug, Clone)]46pub struct LocError(pub Error, pub StackTrace);47pub type Result<V> = std::result::Result<V, LocError>;
after · crates/jsonnet-evaluator/src/error.rs
1use crate::ValType;2use jsonnet_parser::ExprLocation;3use std::{path::PathBuf, rc::Rc};45#[derive(Debug, Clone)]6pub enum Error {7	VariableIsNotDefined(String),8	TypeMismatch(&'static str, Vec<ValType>, ValType),9	IntristicArgumentReorderingIsNotSupportedYet,10	NoSuchField(Rc<str>),1112	UnknownVariable(Rc<str>),1314	UnknownFunctionParameter(String),15	BindingParameterASecondTime(Rc<str>),16	TooManyArgsFunctionHas(usize),17	FunctionParameterNotBoundInCall(Rc<str>),1819	UndefinedExternalVariable(Rc<str>),2021	FieldMustBeStringGot(ValType),2223	AttemptedIndexAnArrayWithString(Rc<str>),24	ValueIndexMustBeTypeGot(ValType, ValType, ValType),25	CantIndexInto(ValType),2627	StandaloneSuper,2829	ImportFileNotFound(PathBuf, PathBuf),30	ResolvedFileNotFound(PathBuf),31	ImportBadFileUtf8(PathBuf),32	ImportNotSupported(PathBuf, PathBuf),33	ImportSyntaxError(jsonnet_parser::ParseError),3435	RuntimeError(Rc<str>),36	StackOverflow,37	FractionalIndex,38	DivisionByZero,39}4041#[derive(Clone, Debug)]42pub struct StackTraceElement(pub ExprLocation, pub String);43#[derive(Debug, Clone)]44pub struct StackTrace(pub Vec<StackTraceElement>);4546#[derive(Debug, Clone)]47pub struct LocError(pub Error, pub StackTrace);48pub type Result<V> = std::result::Result<V, LocError>;
modifiedcrates/jsonnet-evaluator/src/function.rsdiffbeforeafterboth
--- a/crates/jsonnet-evaluator/src/function.rs
+++ b/crates/jsonnet-evaluator/src/function.rs
@@ -93,3 +93,63 @@
 
 	Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)
 }
+
+#[macro_export]
+macro_rules! parse_args {
+	($ctx: expr, $fn_name: expr, $args: expr, $total_args: expr, [
+		$($id: expr, $name: ident $(: [$($p: path)|+] $(!! $a: path)?)?, $nt: expr);+ $(;)?
+	], $handler:block) => {{
+		use crate::error::Error;
+		let args = $args;
+		if args.len() > $total_args {
+			create_error(Error::TooManyArgsFunctionHas($total_args))?;
+		}
+		$(
+			if args.len() <= $id {
+				create_error(Error::FunctionParameterNotBoundInCall(stringify!($name).into()))?;
+			}
+			let $name = &args[$id];
+			if $name.0.is_some() {
+				if $name.0.as_ref().unwrap() != stringify!($name) {
+					create_error(Error::IntristicArgumentReorderingIsNotSupportedYet)?;
+				}
+			}
+			let $name = evaluate($ctx.clone(), &$name.1)?;
+			$(
+				match $name {
+					$($p(_))|+ => {},
+					_ => create_error(Error::TypeMismatch(concat!($fn_name, " ", stringify!($id), "nd argument"), $nt, $name.value_type()?))?,
+				};
+				$(
+					let $name = match $name {
+						$a(v) => v,
+						_ => create_error(Error::TypeMismatch(concat!($fn_name, " ", stringify!($id), "nd argument"), $nt, $name.value_type()?))?,
+					};
+				)*
+			)*
+		)+
+		$handler
+	}};
+}
+
+#[test]
+fn test() -> Result<()> {
+	use jsonnet_parser::*;
+	use crate::val::ValType;
+	let state = crate::EvaluationState::default();
+	let evaluator = state.with_stdlib();
+	let ctx = evaluator.create_default_context()?;
+	evaluator.run_in_state(|| {
+		parse_args!(ctx, "test", ArgsDesc(vec![
+			Arg(None, el!(Expr::Num(2.0))),
+			Arg(Some("b".into()), el!(Expr::Num(1.0))),
+		]), 2, [
+			0, a: [Val::Num]!!Val::Num, vec![ValType::Num];
+			1, b: [Val::Num]!!Val::Num, vec![ValType::Num];
+		], {
+			assert!((a - 2.0).abs() <= f64::EPSILON);
+			assert!((b - 1.0).abs() <= f64::EPSILON);
+		});
+		Ok(())
+	})
+}