diff --git a/concept-code/exceptions/nestedTry.vsm b/concept-code/exceptions/nestedTry.vsm index aba1af3..251ac8a 100644 --- a/concept-code/exceptions/nestedTry.vsm +++ b/concept-code/exceptions/nestedTry.vsm @@ -14,11 +14,11 @@ export @_anon0 {} set_catch :catch0 %error jmp :catch_end1 // } catch (error) { - :catch1 + catch1: set_catch :catch0 %error sub %error_0 "message" %_tmp0 subcall %logs "push" [%_tmp0] %ignore - :catch_end1 + catch_end1: // } new $Error ["boom"] %_tmp0 @@ -27,10 +27,10 @@ export @_anon0 {} unset_catch jmp :catch_end0 // } catch (error) { - :catch0 + catch0: sub %error "message" %_tmp0 subcall %logs "push" [%_tmp0] %ignore - :catch_end0 + catch_end0: // } mov %logs %return diff --git a/concept-code/exceptions/tryCatch.vsm b/concept-code/exceptions/tryCatch.vsm index 564e58f..4e0c737 100644 --- a/concept-code/exceptions/tryCatch.vsm +++ b/concept-code/exceptions/tryCatch.vsm @@ -6,8 +6,8 @@ export @_anon0 {} throw %_tmp0 unset_catch jmp :catch_end0 -:catch0 +catch0: mov %error %return end -:catch_end0 +catch_end0: } diff --git a/concept-code/exceptions/tryFinally.vsm b/concept-code/exceptions/tryFinally.vsm index 8cea3c8..94c04d3 100644 --- a/concept-code/exceptions/tryFinally.vsm +++ b/concept-code/exceptions/tryFinally.vsm @@ -5,7 +5,7 @@ export @_anon0 {} new $Error ["Something went wrong"] %_tmp1 throw %_tmp1 unset_catch -:finally0 +finally0: op+ 1 1 %ignore throw %_tmp0 // doesn't throw if register contains void } diff --git a/concept-code/exceptions/tryReturnFinallyReturn.vsm b/concept-code/exceptions/tryReturnFinallyReturn.vsm index 15e12ae..f50e59b 100644 --- a/concept-code/exceptions/tryReturnFinallyReturn.vsm +++ b/concept-code/exceptions/tryReturnFinallyReturn.vsm @@ -7,10 +7,10 @@ export @_anon0 {} unset_catch jmp :finally0 unset_catch -:finally0 +finally0: mov 42 %return end throw %_tmp0 jmpif %_is_returning :end -:end +end: } diff --git a/valuescript_common/src/instruction_byte.rs b/valuescript_common/src/instruction_byte.rs index 89df0cf..5a85b37 100644 --- a/valuescript_common/src/instruction_byte.rs +++ b/valuescript_common/src/instruction_byte.rs @@ -47,6 +47,8 @@ pub enum InstructionByte { Throw = 0x2c, Import = 0x2d, ImportStar = 0x2e, + SetCatch = 0x2f, + UnsetCatch = 0x30, } impl InstructionByte { @@ -101,6 +103,8 @@ impl InstructionByte { 0x2c => Throw, 0x2d => Import, 0x2e => ImportStar, + 0x2f => SetCatch, + 0x30 => UnsetCatch, _ => panic!("Unrecognized instruction: {}", byte), }; diff --git a/valuescript_compiler/src/asm.rs b/valuescript_compiler/src/asm.rs index 8c7d9f9..f4549c0 100644 --- a/valuescript_compiler/src/asm.rs +++ b/valuescript_compiler/src/asm.rs @@ -285,6 +285,8 @@ pub enum Instruction { Throw(Value), Import(Value, Register), ImportStar(Value, Register), + SetCatch(LabelRef, Register), + UnsetCatch, } impl std::fmt::Display for Instruction { @@ -421,6 +423,10 @@ impl std::fmt::Display for Instruction { Instruction::ImportStar(value, register) => { write!(f, "import* {} {}", value, register) } + Instruction::SetCatch(label, register) => { + write!(f, "set_catch {} {}", label, register) + } + Instruction::UnsetCatch => write!(f, "unset_catch"), } } } @@ -478,6 +484,8 @@ impl Instruction { Throw(..) => InstructionByte::Throw, Import(..) => InstructionByte::Import, ImportStar(..) => InstructionByte::ImportStar, + SetCatch(..) => InstructionByte::SetCatch, + UnsetCatch => InstructionByte::UnsetCatch, } } } diff --git a/valuescript_compiler/src/assembler.rs b/valuescript_compiler/src/assembler.rs index 4252b63..2450a0b 100644 --- a/valuescript_compiler/src/assembler.rs +++ b/valuescript_compiler/src/assembler.rs @@ -160,7 +160,7 @@ impl Assembler { self.output.push(instruction.byte() as u8); match instruction { - End => {} + End | UnsetCatch => {} OpInc(dst) | OpDec(dst) => { self.register(dst); } @@ -226,6 +226,10 @@ impl Assembler { Throw(value) => { self.value(value); } + SetCatch(label_ref, register) => { + self.label_ref(label_ref); + self.register(register); + } } } diff --git a/valuescript_compiler/src/assembly_parser.rs b/valuescript_compiler/src/assembly_parser.rs index b8efc0e..f8d06ec 100644 --- a/valuescript_compiler/src/assembly_parser.rs +++ b/valuescript_compiler/src/assembly_parser.rs @@ -222,6 +222,8 @@ impl<'a> AssemblyParser<'a> { ("throw", InstructionByte::Throw), ("import", InstructionByte::Import), ("import*", InstructionByte::ImportStar), + ("set_catch", InstructionByte::SetCatch), + ("unset_catch", InstructionByte::UnsetCatch), ]); for (word, instruction) in instruction_word_map { @@ -665,6 +667,8 @@ impl<'a> AssemblyParser<'a> { Throw => Instruction::Throw(self.assemble_value()), Import => Instruction::Import(self.assemble_value(), self.assemble_register()), ImportStar => Instruction::ImportStar(self.assemble_value(), self.assemble_register()), + SetCatch => Instruction::SetCatch(self.assemble_label_read(), self.assemble_register()), + UnsetCatch => Instruction::UnsetCatch, } } diff --git a/valuescript_compiler/src/link_module.rs b/valuescript_compiler/src/link_module.rs index 6379bfa..a3b7d93 100644 --- a/valuescript_compiler/src/link_module.rs +++ b/valuescript_compiler/src/link_module.rs @@ -234,8 +234,7 @@ where use Instruction::*; match instruction { - End => {} - OpInc(_) | OpDec(_) => {} + End | UnsetCatch | OpInc(..) | OpDec(..) | Jmp(..) | SetCatch(..) => {} Mov(arg, _) | OpNot(arg, _) | OpBitNot(arg, _) @@ -286,7 +285,6 @@ where self.value(Some(owner), arg2); self.value(Some(owner), arg3); } - Jmp(_) => {} JmpIf(arg, _) => { self.value(Some(owner), arg); } diff --git a/valuescript_vm/src/bytecode_stack_frame.rs b/valuescript_vm/src/bytecode_stack_frame.rs index ecf45c1..2c4e1b1 100644 --- a/valuescript_vm/src/bytecode_stack_frame.rs +++ b/valuescript_vm/src/bytecode_stack_frame.rs @@ -20,6 +20,12 @@ pub struct BytecodeStackFrame { pub param_end: usize, pub this_target: Option, pub return_target: Option, + pub catch_setting: Option, +} + +pub struct CatchSetting { + pub pos: usize, + pub register: Option, } impl BytecodeStackFrame { @@ -404,6 +410,17 @@ impl StackFrameTrait for BytecodeStackFrame { Import | ImportStar => { panic!("TODO: Dynamic imports") } + + SetCatch => { + self.catch_setting = Some(CatchSetting { + pos: self.decoder.decode_pos(), + register: self.decoder.decode_register_index(), + }); + } + + UnsetCatch => { + self.catch_setting = None; + } }; Ok(FrameStepOk::Continue) diff --git a/valuescript_vm/src/vs_function.rs b/valuescript_vm/src/vs_function.rs index 7f6c3d2..d100d87 100644 --- a/valuescript_vm/src/vs_function.rs +++ b/valuescript_vm/src/vs_function.rs @@ -50,11 +50,12 @@ impl VsFunction { data: self.bytecode.clone(), pos: self.start, }, - registers: registers, + registers, param_start: self.binds.len() + 2, param_end: self.parameter_count + 2, this_target: None, return_target: None, + catch_setting: None, }); } }