diff --git a/CHANGELOG.md b/CHANGELOG.md index ccb4f568..3f9e2db8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ The Koto project adheres to ## [0.16.0] Unreleased +### Changed + +#### Language + +- Calls to functions with more arguments than expected by the function will now throw an error. + ### Fixed #### Core Library diff --git a/crates/runtime/src/error.rs b/crates/runtime/src/error.rs index c2f4b075..25556783 100644 --- a/crates/runtime/src/error.rs +++ b/crates/runtime/src/error.rs @@ -33,6 +33,8 @@ pub enum ErrorKind { expected: String, unexpected: Vec, }, + #[error("Too many arguments - expected {expected}, found {actual}")] + TooManyArguments { expected: u8, actual: u8 }, #[error("Unexpected type - expected: '{expected}', found: '{}'", unexpected.type_as_string())] UnexpectedType { expected: String, diff --git a/crates/runtime/src/vm.rs b/crates/runtime/src/vm.rs index 5e9c4602..8fcecded 100644 --- a/crates/runtime/src/vm.rs +++ b/crates/runtime/src/vm.rs @@ -2764,16 +2764,23 @@ impl KotoVm { f.arg_count }; - if f.variadic && call_info.arg_count >= expected_arg_count { - // The last defined arg is the start of the var_args, - // e.g. f = |x, y, z...| - // arg index 2 is the first vararg, and where the tuple will be placed - let arg_base = call_info.frame_base + 1; - let varargs_start = arg_base + expected_arg_count; - let varargs_count = call_info.arg_count - expected_arg_count; - let varargs = KValue::Tuple(self.register_slice(varargs_start, varargs_count).into()); - self.set_register(varargs_start, varargs); - // self.truncate_registers(varargs_start + 1); + if f.variadic { + if call_info.arg_count >= expected_arg_count { + // The last defined arg is the start of the var_args, + // e.g. f = |x, y, z...| + // arg index 2 is the first vararg, and where the tuple will be placed + let arg_base = call_info.frame_base + 1; + let varargs_start = arg_base + expected_arg_count; + let varargs_count = call_info.arg_count - expected_arg_count; + let varargs = + KValue::Tuple(self.register_slice(varargs_start, varargs_count).into()); + self.set_register(varargs_start, varargs); + } + } else if call_info.arg_count > expected_arg_count { + return runtime_error!(ErrorKind::TooManyArguments { + expected: expected_arg_count, + actual: call_info.arg_count + }); } // self is in the frame base register, arguments start from register frame_base + 1 diff --git a/crates/runtime/tests/vm_tests.rs b/crates/runtime/tests/vm_tests.rs index 56cd26a5..dcc51a0e 100644 --- a/crates/runtime/tests/vm_tests.rs +++ b/crates/runtime/tests/vm_tests.rs @@ -1150,15 +1150,6 @@ foo 42 check_script_output(script, KValue::Null); } - #[test] - fn call_with_extra_args() { - let script = " -foo = |a, b| a + b -foo 10, 20, 30, 40 -"; - check_script_output(script, 30); - } - #[test] fn nested_call_without_parens() { let script = "