diff --git a/crates/oxide_compiler/src/emitter.rs b/crates/oxide_compiler/src/emitter.rs index d79047f..9af1e2a 100644 --- a/crates/oxide_compiler/src/emitter.rs +++ b/crates/oxide_compiler/src/emitter.rs @@ -908,7 +908,9 @@ impl Compiler { AssignmentOperator::Division => OpCode::COMPOUND_MEMBER_DIV, AssignmentOperator::Remainder => OpCode::COMPOUND_MEMBER_MOD, AssignmentOperator::Exponential => OpCode::COMPOUND_MEMBER_EXP, - _ => unreachable!(), + _ => { + return Err(format!("compound assignment operator {:?} not supported", assign.operator)) + } }; ctx.emit(opcode::encode(op, obj_reg, val_reg, key_reg)); ctx.emit(0); @@ -947,7 +949,12 @@ impl Compiler { AssignmentOperator::Division => OpCode::COMPOUND_DIV, AssignmentOperator::Remainder => OpCode::COMPOUND_MOD, AssignmentOperator::Exponential => OpCode::COMPOUND_EXP, - _ => unreachable!(), + _ => { + return Err(format!( + "compound assignment operator {:?} not supported", + assign.operator + )) + } }; ctx.emit(opcode::encode(op, var_reg, rhs, 0)); Ok(var_reg) diff --git a/crates/oxide_compiler/tests/compile_expr_tests.rs b/crates/oxide_compiler/tests/compile_expr_tests.rs index 838141f..44c6cfe 100644 --- a/crates/oxide_compiler/tests/compile_expr_tests.rs +++ b/crates/oxide_compiler/tests/compile_expr_tests.rs @@ -9,6 +9,16 @@ fn compile_source(source: &str) -> oxide_compiler::module::CompiledModule { compiler.compile(&program).expect("compile failed") } +fn compile_source_err(source: &str) -> String { + let allocator = Allocator::default(); + let program = oxide_parser::parse(&allocator, source).expect("parse failed"); + let compiler = Compiler::new(); + match compiler.compile(&program) { + Ok(_) => panic!("compile should fail"), + Err(err) => err, + } +} + #[test] fn compile_simple_expr() { let module = compile_source("1 + 2"); @@ -20,6 +30,20 @@ fn compile_simple_expr() { assert_eq!(last, OpCode::HALT); } +#[test] +fn unsupported_logical_assignment_returns_compile_error() { + let err = compile_source_err("let x = 0; x ||= 1;"); + assert!(err.contains("compound assignment operator")); + assert!(err.contains("not supported")); +} + +#[test] +fn unsupported_member_logical_assignment_returns_compile_error() { + let err = compile_source_err("let obj = { x: 0 }; obj.x ||= 1;"); + assert!(err.contains("compound assignment operator")); + assert!(err.contains("not supported")); +} + #[test] fn compile_constants() { let module = compile_source("42");