From 0dfdb124cf348e470f5446b28c23cdd99b93bbc7 Mon Sep 17 00:00:00 2001 From: Matt Paras Date: Mon, 18 Nov 2024 18:06:12 -0600 Subject: [PATCH] more general fixes --- crates/steel-core/src/compiler/code_gen.rs | 6 - crates/steel-core/src/compiler/compiler.rs | 10 +- crates/steel-core/src/compiler/program.rs | 6 + crates/steel-core/src/steel_vm/register_fn.rs | 340 ++++++++++++++---- crates/steel-core/src/steel_vm/vm.rs | 47 ++- 5 files changed, 332 insertions(+), 77 deletions(-) diff --git a/crates/steel-core/src/compiler/code_gen.rs b/crates/steel-core/src/compiler/code_gen.rs index 32530363a..69121476b 100644 --- a/crates/steel-core/src/compiler/code_gen.rs +++ b/crates/steel-core/src/compiler/code_gen.rs @@ -404,12 +404,6 @@ impl<'a> VisitorMut for CodeGenerator<'a> { // Just remove them otherwise self.push(LabeledInstruction::builder(OpCode::EDEF)); - // if let Some(elem) = self.instructions.get_mut(sidx) { - // (*elem).payload_size = defn_body_size; - // } else { - // stop!(Generic => "out of bounds closure len"); - // } - // println!("binding global: {}", name); self.push(LabeledInstruction::builder(OpCode::BIND).contents(name.syn.clone())); diff --git a/crates/steel-core/src/compiler/compiler.rs b/crates/steel-core/src/compiler/compiler.rs index d0e5d87b4..7f9f6ef50 100644 --- a/crates/steel-core/src/compiler/compiler.rs +++ b/crates/steel-core/src/compiler/compiler.rs @@ -1032,6 +1032,14 @@ impl Compiler { // println!(""); // steel_parser::ast::AstTools::pretty_print(&expanded_statements); + // log::info!( + // "{}", + // expanded_statements + // .iter() + // .map(|x| x.to_pretty(60)) + // .join("\n\n") + // ); + log::debug!(target: "expansion-phase", "Generating instructions"); let instructions = self.generate_instructions_for_executable(expanded_statements)?; @@ -1046,7 +1054,7 @@ impl Compiler { raw_program.apply_optimizations(); // Lets see everything that gets run! - // raw_program.debug_print(); + // raw_program.debug_print_log(); Ok(raw_program) } diff --git a/crates/steel-core/src/compiler/program.rs b/crates/steel-core/src/compiler/program.rs index 95f427484..044fe3ed1 100644 --- a/crates/steel-core/src/compiler/program.rs +++ b/crates/steel-core/src/compiler/program.rs @@ -945,6 +945,12 @@ impl RawProgramWithSymbols { .for_each(|i| println!("{}\n\n", crate::core::instructions::disassemble(i))) } + pub fn debug_print_log(&self) { + self.instructions + .iter() + .for_each(|i| log::info!("{}\n\n", crate::core::instructions::disassemble(i))) + } + /// Applies a peephole style optimization to the underlying instruction set pub fn with_optimization(&mut self, f: F) { for instructions in &mut self.instructions { diff --git a/crates/steel-core/src/steel_vm/register_fn.rs b/crates/steel-core/src/steel_vm/register_fn.rs index 865383018..f1bd6e5d5 100644 --- a/crates/steel-core/src/steel_vm/register_fn.rs +++ b/crates/steel-core/src/steel_vm/register_fn.rs @@ -166,7 +166,10 @@ impl RET + SendSyncStat stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 0, args.len())); } - let input = ::as_ref(&args[0])?; + let input = ::as_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&input); @@ -195,7 +198,10 @@ impl RET + SendS stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 1, args.len())); } - let mut input = ::as_mut_ref(&args[0])?; + let mut input = ::as_mut_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input); @@ -227,7 +233,10 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 1, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input); @@ -258,8 +267,14 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 2, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; - let mut area = ::as_mut_ref(&args[1])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut area = ::as_mut_ref(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, &mut area); @@ -290,8 +305,14 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 2, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; - let mut area = ::as_mut_ref(&args[1])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut area = ::as_mut_ref(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, &mut area); @@ -325,10 +346,22 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 4, args.len())); } - let mut input = ::as_mut_ref(&args[0])?; - let mut area = ::from_steelval(&args[1])?; - let mut frame = ::as_mut_ref_from_ref(&args[2])?; - let mut ctx = ::as_mut_ref_from_ref(&args[3])?; + let mut input = ::as_mut_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut area = ::from_steelval(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut frame = ::as_mut_ref_from_ref(&args[2]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut ctx = ::as_mut_ref_from_ref(&args[3]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, area, &mut frame, &mut ctx); @@ -361,10 +394,22 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 4, args.len())); } - let mut input = ::as_mut_ref(&args[0])?; - let mut area = ::from_steelval(&args[1])?; - let mut frame = ::as_mut_ref_from_ref(&args[2])?; - let mut ctx = ::as_mut_ref_from_ref(&args[3])?; + let mut input = ::as_mut_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut area = ::from_steelval(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut frame = ::as_mut_ref_from_ref(&args[2]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut ctx = ::as_mut_ref_from_ref(&args[3]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, area, &mut frame, &mut ctx); @@ -398,9 +443,18 @@ impl< let mut nursery = ::Nursery::default(); - let mut input = ::as_mut_ref(&args[0])?; - let mut area = ::as_ref(&args[1])?; - let mut ctx = ::as_mut_ref_from_ref(&args[2])?; + let mut input = ::as_mut_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut area = ::as_ref(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut ctx = ::as_mut_ref_from_ref(&args[2]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, &area, &mut ctx); @@ -434,9 +488,18 @@ impl< let mut nursery = ::Nursery::default(); - let mut input = ::as_ref(&args[0])?; - let mut area = ::from_steelval(&args[1])?; - let mut ctx = ::as_ref_from_ref(&args[2])?; + let mut input = ::as_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut area = ::from_steelval(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut ctx = ::as_ref_from_ref(&args[2]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&input, area, &ctx); @@ -471,9 +534,15 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 3, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; - let temp_res = INNER::as_ref_from_unsized(&args[1])?; + let temp_res = INNER::as_ref_from_unsized(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func( &mut input, @@ -504,9 +573,15 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 3, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; - let temp_res = INNER::as_ref_from_unsized(&args[1])?; + let temp_res = INNER::as_ref_from_unsized(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func( &mut input, @@ -543,9 +618,15 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 3, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; - let temp_res = INNER::as_ref_from_unsized(&args[1])?; + let temp_res = INNER::as_ref_from_unsized(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, temp_res.as_slice_repr()); @@ -572,9 +653,15 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 3, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; - let temp_res = INNER::as_ref_from_unsized(&args[1])?; + let temp_res = INNER::as_ref_from_unsized(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, temp_res.as_slice_repr()); @@ -607,9 +694,15 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 3, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; - let temp_res = INNER::as_ref_from_unsized(&args[1])?; + let temp_res = INNER::as_ref_from_unsized(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, temp_res.as_slice_repr()); @@ -634,9 +727,15 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 3, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; - let temp_res = INNER::as_ref_from_unsized(&args[1])?; + let temp_res = INNER::as_ref_from_unsized(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, temp_res.as_slice_repr()); @@ -679,7 +778,10 @@ impl< } // If this value is - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(input); @@ -760,7 +862,10 @@ impl< } // If this value is - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(input); @@ -835,8 +940,14 @@ impl< } // If this value is - let mut input = ::as_mut_ref_from_ref(&args[0])?; - let arg = ARG::from_steelval(&args[1])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let arg = ARG::from_steelval(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(input, arg); @@ -911,8 +1022,14 @@ impl< } // If this value is - let mut input = ::as_ref_from_ref(&args[0])?; - let arg = ARG::from_steelval(&args[1])?; + let mut input = ::as_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let arg = ARG::from_steelval(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(input, arg); @@ -979,7 +1096,10 @@ impl< } // If this value is - let mut input = ::as_ref_from_ref(&args[0])?; + let mut input = ::as_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(input); @@ -1043,9 +1163,18 @@ impl< let mut nursery = ::Nursery::default(); - let mut input = ::as_mut_ref(&args[0])?; - let mut area = ::as_ref(&args[1])?; - let mut ctx = ::as_mut_ref_from_ref(&args[2])?; + let mut input = ::as_mut_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut area = ::as_ref(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut ctx = ::as_mut_ref_from_ref(&args[2]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, &area, &mut ctx); @@ -1079,9 +1208,18 @@ impl< let mut nursery = ::Nursery::default(); - let mut input = ::as_ref(&args[0])?; - let mut area = ::from_steelval(&args[1])?; - let mut ctx = ::as_ref_from_ref(&args[2])?; + let mut input = ::as_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut area = ::from_steelval(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let mut ctx = ::as_ref_from_ref(&args[2]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&input, area, &ctx); @@ -1116,9 +1254,15 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 0, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; - let temp_res = INNER::as_ref_from_unsized(&args[1])?; + let temp_res = INNER::as_ref_from_unsized(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func( &mut input, @@ -1149,14 +1293,23 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 0, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; - let temp_res = INNER::as_ref_from_unsized(&args[1])?; + let temp_res = INNER::as_ref_from_unsized(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func( &mut input, temp_res.as_slice_repr(), - F::from_steelval(&args[2])?, + F::from_steelval(&args[2]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?, ); res.into_steelval() @@ -1199,7 +1352,10 @@ impl< } // If this value is - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(input); @@ -1280,7 +1436,10 @@ impl< } // If this value is - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(input); @@ -1359,8 +1518,14 @@ impl< } // If this value is - let mut input = ::as_mut_ref_from_ref(&args[0])?; - let arg = ARG::from_steelval(&args[1])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; + let arg = ARG::from_steelval(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(input, arg); @@ -1538,7 +1703,10 @@ impl RET + SendSyncStat let mut nursery = ::default(); - let input = ::as_ref(&args[0])?; + let input = ::as_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&input); @@ -1566,7 +1734,10 @@ impl RET + SendSyncStat let mut nursery = ::default(); - let input = ::as_ref(&args[0])?; + let input = ::as_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&input); @@ -1597,7 +1768,10 @@ impl RET + SendS stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 0, args.len())); } - let mut input = ::as_mut_ref(&args[0])?; + let mut input = ::as_mut_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input); @@ -1629,7 +1803,10 @@ impl< stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 0, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input); @@ -1656,7 +1833,10 @@ impl RET + SendS stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 0, args.len())); } - let mut input = ::as_ref_from_ref(&args[0])?; + let mut input = ::as_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input); @@ -1721,7 +1901,10 @@ impl RET + SendS stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, 0, args.len())); } - let mut input = ::as_ref_from_ref(&args[0])?; + let mut input = ::as_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input); @@ -1770,11 +1953,17 @@ impl< let mut nursery = ::default(); - let one = A::as_ref(&args[0])?; + let one = A::as_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let mut nursery = ::default(); - let two = B::as_ref(&args[1])?; + let two = B::as_ref(&args[1]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&one, &two); @@ -1960,7 +2149,10 @@ macro_rules! impl_register_fn_self { let mut nursery = ::default(); - let input = ::as_ref(&args[0])?; + let input = ::as_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&input, $(<$param>::from_steelval(&args[$idx]).map_err(|mut err| { err.prepend_message(":"); @@ -1995,7 +2187,10 @@ macro_rules! impl_register_fn_self { stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, $arg_count, args.len())); } - let mut input = ::as_mut_ref(&args[0])?; + let mut input = ::as_mut_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, $(<$param>::from_steelval(&args[$idx]).map_err(|mut err| { err.prepend_message(":"); @@ -2030,7 +2225,10 @@ macro_rules! impl_register_fn_self { stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, $arg_count, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; let res = func(&mut input, $(<$param>::from_steelval(&args[$idx]).map_err(|mut err| { err.prepend_message(":"); @@ -2061,9 +2259,15 @@ macro_rules! impl_register_fn_self { stop!(ArityMismatch => format!("{} expected {} argument, got {}", name, $arg_count, args.len())); } - let mut input = ::as_mut_ref_from_ref(&args[0])?; + let mut input = ::as_mut_ref_from_ref(&args[0]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?; - let res = func(&mut input, $(<$param>::from_steelval(&args[$idx])?,)*); + let res = func(&mut input, $(<$param>::from_steelval(&args[$idx]).map_err(|mut e| { + e.prepend_message(&format!("{}:", name)); + e + })?,)*); res.into_steelval() }; diff --git a/crates/steel-core/src/steel_vm/vm.rs b/crates/steel-core/src/steel_vm/vm.rs index 99b5b0f42..203dbda94 100644 --- a/crates/steel-core/src/steel_vm/vm.rs +++ b/crates/steel-core/src/steel_vm/vm.rs @@ -3,6 +3,7 @@ use crate::compiler::code_gen::fresh_function_id; use crate::compiler::compiler::Compiler; use crate::core::instructions::pretty_print_dense_instructions; +use crate::core::instructions::u24; use crate::gc::shared::MutContainer; use crate::gc::shared::ShareableMut; use crate::gc::shared::Shared; @@ -2110,6 +2111,8 @@ impl<'a> VmCore<'a> { let instr = self.instructions[self.ip]; + // dbg!(&instr); + match instr { // DenseInstruction { // op_code: OpCode::DynSuperInstruction, @@ -2850,6 +2853,14 @@ impl<'a> VmCore<'a> { self.thread.stack.push(val); self.ip += 1; } + + // DenseInstruction { + // op_code: OpCode::ECLOSURE, + // .. + // } => { + // self.ip += 1; + // } + // match_dynamic_super_instructions!() _ => { #[cfg(feature = "dynamic")] @@ -3111,8 +3122,6 @@ impl<'a> VmCore<'a> { } fn handle_pure_function(&mut self, offset: usize) { - // println!("Hitting start closure"); - // println!("Instruction: {:?}", self.instructions[self.ip]); // if self.instructions[self.ip].payload_size == 1 { @@ -4644,14 +4653,48 @@ fn eval_program(program: crate::compiler::program::Executable, ctx: &mut VmCore) } = program; let mut bytecode = Vec::new(); let mut new_spans = Vec::new(); + + // Rewrite relative jumps at the top level into absolute jumps. for (instr, span) in instructions.into_iter().zip(spans) { + let mut depth = 0; + + let offset = bytecode.len(); + new_spans.extend_from_slice(&span); bytecode.extend_from_slice(&instr); + bytecode .last_mut() .ok_or_else(throw!(Generic => "Compilation error: empty expression"))? .op_code = OpCode::POPSINGLE; + + for instruction in &mut bytecode[offset..] { + match instruction { + DenseInstruction { + op_code: OpCode::JMP | OpCode::IF, + payload_size, + } => { + if depth == 0 { + *payload_size = *payload_size + u24::from_usize(offset); + } + } + DenseInstruction { + op_code: OpCode::NEWSCLOSURE | OpCode::PUREFUNC, + .. + } => { + depth += 1; + } + DenseInstruction { + op_code: OpCode::ECLOSURE, + .. + } => { + depth -= 1; + } + _ => {} + } + } } + // TODO: Fix the unwrap here if let Some(last) = bytecode.last_mut() { last.op_code = OpCode::POPPURE;