diff options
author | Adam Joseph <adam@westernsemico.com> | 2023-12-12T07·14-0800 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2023-12-12T15·55+0000 |
commit | 52b68c053987c1567bacb6f14dad8ba92cd01afe (patch) | |
tree | 820236145cd5d9ff0e158d37a7db3a2baada78a2 | |
parent | e516046ed28d6b85fc683cfe39d2b4035e68d975 (diff) |
fix(tvix/eval): fix catchables in named formals r/7186
Fixes b/348. Change-Id: I5e8d56b5fd26a19eac32ec5e11baf93765691dc8 Reviewed-on: https://cl.tvl.fyi/c/depot/+/10296 Autosubmit: Adam Joseph <adam@westernsemico.com> Reviewed-by: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI
-rw-r--r-- | tvix/eval/src/compiler/mod.rs | 38 | ||||
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-catchable-passed-to-function-with-formals.exp (renamed from tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-catchable-passed-to-function-with-formals.exp) | 0 | ||||
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-catchable-passed-to-function-with-formals.nix (renamed from tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-catchable-passed-to-function-with-formals.nix) | 0 |
3 files changed, 27 insertions, 11 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs index 211fd079a047..b6b5bc6860f9 100644 --- a/tvix/eval/src/compiler/mod.rs +++ b/tvix/eval/src/compiler/mod.rs @@ -957,7 +957,7 @@ impl Compiler<'_> { /// by the caller. We need to take this into account and skip any /// operations specific to the expression like thunk finalisation in such /// cases. - fn compile_param_pattern(&mut self, pattern: &ast::Pattern) -> Formals { + fn compile_param_pattern(&mut self, pattern: &ast::Pattern) -> (Formals, CodeIdx) { let span = self.span_for(pattern); let set_idx = match pattern.pat_bind() { Some(name) => self.declare_local(&name, name.ident().unwrap().to_string()), @@ -967,6 +967,7 @@ impl Compiler<'_> { // At call time, the attribute set is already at the top of the stack. self.scope_mut().mark_initialised(set_idx); self.emit_force(pattern); + let throw_idx = self.push_op(OpCode::OpJumpIfCatchable(JumpOffset(0)), pattern); // Evaluation fails on a type error, even if the argument(s) are unused. self.push_op(OpCode::OpAssertAttrs, pattern); @@ -1106,14 +1107,17 @@ impl Compiler<'_> { } } - Formals { - arguments, - ellipsis, - span, - } + ( + (Formals { + arguments, + ellipsis, + span, + }), + throw_idx, + ) } - fn compile_lambda(&mut self, slot: LocalIdx, node: &ast::Lambda) { + fn compile_lambda(&mut self, slot: LocalIdx, node: &ast::Lambda) -> Option<CodeIdx> { // Compile the function itself, recording its formal arguments (if any) // for later use let formals = match node.param().unwrap() { @@ -1135,7 +1139,13 @@ impl Compiler<'_> { }; self.compile(slot, node.body().unwrap()); - self.context_mut().lambda.formals = formals; + if let Some((formals, throw_idx)) = formals { + self.context_mut().lambda.formals = Some(formals); + Some(throw_idx) + } else { + self.context_mut().lambda.formals = None; + None + } } fn thunk<N, F>(&mut self, outer_slot: LocalIdx, node: &N, content: F) @@ -1143,7 +1153,10 @@ impl Compiler<'_> { N: ToSpan, F: FnOnce(&mut Compiler, LocalIdx), { - self.compile_lambda_or_thunk(true, outer_slot, node, content) + self.compile_lambda_or_thunk(true, outer_slot, node, |comp, idx| { + content(comp, idx); + None + }) } /// Mark the current thunk as redundant, i.e. possible to merge directly @@ -1161,7 +1174,7 @@ impl Compiler<'_> { content: F, ) where N: ToSpan, - F: FnOnce(&mut Compiler, LocalIdx), + F: FnOnce(&mut Compiler, LocalIdx) -> Option<CodeIdx>, { let name = self.scope()[outer_slot].name(); self.new_context(); @@ -1174,8 +1187,11 @@ impl Compiler<'_> { let slot = self.scope_mut().declare_phantom(span, false); self.scope_mut().begin_scope(); - content(self, slot); + let throw_idx = content(self, slot); self.cleanup_scope(node); + if let Some(throw_idx) = throw_idx { + self.patch_jump(throw_idx); + } // TODO: determine and insert enclosing name, if available. diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-catchable-passed-to-function-with-formals.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-catchable-passed-to-function-with-formals.exp index c508d5366f70..c508d5366f70 100644 --- a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-catchable-passed-to-function-with-formals.exp +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-catchable-passed-to-function-with-formals.exp diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-catchable-passed-to-function-with-formals.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-catchable-passed-to-function-with-formals.nix index df6726db76d6..df6726db76d6 100644 --- a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-catchable-passed-to-function-with-formals.nix +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-catchable-passed-to-function-with-formals.nix |