type checking on constructor arguments

This commit is contained in:
Shautvast 2025-11-10 15:24:31 +01:00
parent 0945d385d0
commit b83c4bb0cc
3 changed files with 37 additions and 21 deletions

View file

@ -160,21 +160,6 @@ impl Compiler {
registry: &mut HashMap<String, Chunk>, registry: &mut HashMap<String, Chunk>,
) -> Result<(), CompilerErrorAtLine> { ) -> Result<(), CompilerErrorAtLine> {
match expression { 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 { Expression::FunctionCall {
name, arguments, .. name, arguments, ..
} => { } => {
@ -281,7 +266,9 @@ impl Compiler {
} }
} }
Expression::Stop { .. } => {} Expression::Stop { .. } => {}
NamedParameter { value,.. } => {self.compile_expression(namespace, value, symbols, registry)?} NamedParameter { value, .. } => {
self.compile_expression(namespace, value, symbols, registry)?
}
Expression::ListGet { index, list } => { Expression::ListGet { index, list } => {
self.compile_expression(namespace, list, symbols, registry)?; self.compile_expression(namespace, list, symbols, registry)?;
self.compile_expression(namespace, index, symbols, registry)?; self.compile_expression(namespace, index, symbols, registry)?;
@ -305,11 +292,16 @@ impl Compiler {
) -> Result<(), CompilerErrorAtLine> { ) -> Result<(), CompilerErrorAtLine> {
for parameter in parameters { for parameter in parameters {
for argument in arguments { for argument in arguments {
if let NamedParameter { name, .. } = argument { if let NamedParameter { name, value, .. } = argument {
if name.lexeme == parameter.name.lexeme { if name.lexeme == parameter.name.lexeme {
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)?; self.compile_expression(namespace, argument, symbols, registry)?;
break; break;
} }
}
} else { } else {
self.compile_expression(namespace, argument, symbols, registry)?; self.compile_expression(namespace, argument, symbols, registry)?;
break; break;

View file

@ -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] #[test]
fn literal_map() { fn literal_map() {
let result = run(r#"{"name": "Dent", "age": 40 }"#); let result = run(r#"{"name": "Dent", "age": 40 }"#);

View file

@ -220,11 +220,20 @@ impl Vm {
if let Some(params) = constructor { if let Some(params) = constructor {
if params.len() != args.len() { 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![]; 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 { let new_instance = Value::ObjectType(Box::new(Object {
definition: function_name, definition: function_name,
fields, fields,