From b83c4bb0cc6e410d96a1a99332ad124cae089ed3 Mon Sep 17 00:00:00 2001 From: Shautvast Date: Mon, 10 Nov 2025 15:24:31 +0100 Subject: [PATCH] type checking on constructor arguments --- src/bytecode_compiler.rs | 30 +++++++++++------------------- src/compiler_tests.rs | 15 +++++++++++++++ src/vm.rs | 13 +++++++++++-- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/bytecode_compiler.rs b/src/bytecode_compiler.rs index 796cb00..60949e4 100644 --- a/src/bytecode_compiler.rs +++ b/src/bytecode_compiler.rs @@ -160,21 +160,6 @@ impl Compiler { registry: &mut HashMap, ) -> Result<(), CompilerErrorAtLine> { match expression { - // Expression::FunctionCall { - // name, arguments, .. - // } => { - // let qname = format!("{}.{}", namespace, name); - // let name_index = self - // .chunk - // .find_constant(&qname) - // .unwrap_or_else(|| self.chunk.add_constant(Value::String(qname))); - // - // for argument in arguments { - // self.compile_expression(namespace, argument, registry)?; - // } - // self.emit_bytes(OP_CALL, name_index as u16); - // self.emit_byte(arguments.len() as u16); - // } Expression::FunctionCall { name, arguments, .. } => { @@ -281,7 +266,9 @@ impl Compiler { } } Expression::Stop { .. } => {} - NamedParameter { value,.. } => {self.compile_expression(namespace, value, symbols, registry)?} + NamedParameter { value, .. } => { + self.compile_expression(namespace, value, symbols, registry)? + } Expression::ListGet { index, list } => { self.compile_expression(namespace, list, symbols, registry)?; self.compile_expression(namespace, index, symbols, registry)?; @@ -305,10 +292,15 @@ impl Compiler { ) -> Result<(), CompilerErrorAtLine> { for parameter in parameters { for argument in arguments { - if let NamedParameter { name, .. } = argument { + if let NamedParameter { name, value, .. } = argument { if name.lexeme == parameter.name.lexeme { - self.compile_expression(namespace, argument, symbols, registry)?; - break; + let value_type = infer_type(value, symbols); + if parameter.var_type != value_type { + return Err(CompilerErrorAtLine::raise(CompilerError::IncompatibleTypes(parameter.var_type.clone(), value_type), argument.line())); + } else { + self.compile_expression(namespace, argument, symbols, registry)?; + break; + } } } else { self.compile_expression(namespace, argument, symbols, registry)?; diff --git a/src/compiler_tests.rs b/src/compiler_tests.rs index e225127..bd2bf12 100644 --- a/src/compiler_tests.rs +++ b/src/compiler_tests.rs @@ -147,6 +147,21 @@ p"#); ); } + #[test] + fn declare_and_instantiate_object_wrong_type() { + let r = run(r#" +object Person: + name: string + +let p = Person(name: 0x42) +p"#); + assert!(r.is_err()); + assert_eq!( + r#"Compilation failed: error at line 5, Expected string, found integer"#, + format!("{}", r.unwrap_err().to_string()) + ); + } + #[test] fn literal_map() { let result = run(r#"{"name": "Dent", "age": 40 }"#); diff --git a/src/vm.rs b/src/vm.rs index e515b34..8a96f34 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -220,11 +220,20 @@ impl Vm { if let Some(params) = constructor { if params.len() != args.len() { - return Err(RuntimeError::IllegalArgumentsException(function_name, params.len(), args.len())); + return Err(RuntimeError::IllegalArgumentsException( + function_name, + params.len(), + args.len(), + )); } let mut fields = vec![]; - params.iter().zip(args.into_iter()).for_each(|(param, arg)| {fields.push((param.name.lexeme.clone(), arg))}); + params + .iter() + .zip(args.into_iter()) + .for_each(|(param, arg)| { + fields.push((param.name.lexeme.clone(), arg)) + }); let new_instance = Value::ObjectType(Box::new(Object { definition: function_name, fields,