From 2a3d49810482b36de9f2d3087e5064545183dbb3 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Wed, 12 Oct 2022 23:53:03 -0400 Subject: feat(tvix/eval): Validate closed formals Validate "closed formals" (formal parameters without an ellipsis) via a new ValidateClosedFormals op, which checks the arguments (in an attr set at the top of the stack) against the formal parameters on the Lambda in the current frame, and returns a new UnexpectedArgument error (including the span of the formals themselves!!) if any arguments aren't allowed Change-Id: Idcc47a59167a83be1832a6229f137d84e426c56c Reviewed-on: https://cl.tvl.fyi/c/depot/+/7002 Reviewed-by: tazjin Tested-by: BuildkiteCI --- tvix/eval/src/vm.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'tvix/eval/src/vm.rs') diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index 7fcdb9ea739b..65662ed555d3 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -500,6 +500,21 @@ impl<'o> VM<'o> { self.push(Value::Bool(result)); } + OpCode::OpValidateClosedFormals => { + let formals = self.frame().lambda.formals.as_ref().expect( + "OpValidateClosedFormals called within the frame of a lambda without formals", + ); + let args = self.peek(0).to_attrs().map_err(|err| self.error(err))?; + for arg in args.keys() { + if !formals.contains(arg) { + return Err(self.error(ErrorKind::UnexpectedArgument { + arg: arg.clone(), + formals_span: formals.span, + })); + } + } + } + OpCode::OpList(Count(count)) => { let list = NixList::construct(count, self.stack.split_off(self.stack.len() - count)); -- cgit 1.4.1