From 3af421ae5f1b0f0210e506bc45f1a06dadf5f615 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 3 Mar 2020 23:31:16 +0800 Subject: [PATCH] Fix problems with script-defined functions. --- README.md | 3 +++ src/api.rs | 5 ----- src/engine.rs | 21 ++++++++++++++++----- src/fn_register.rs | 4 ++-- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 20fb8d1e..a0fb6836 100644 --- a/README.md +++ b/README.md @@ -545,6 +545,9 @@ print(add(2, 3)); ``` Remember that functions defined in script always take `Dynamic` arguments (i.e. the arguments can be of any type). + +Arguments are passed by value, so all functions are _pure_ (i.e. they never modify their arguments). + Furthermore, functions can only be defined at the top level, never inside a block or another function. ```rust diff --git a/src/api.rs b/src/api.rs index 062d28cc..99054a31 100644 --- a/src/api.rs +++ b/src/api.rs @@ -144,11 +144,6 @@ impl Engine { .map_err(|err| EvalAltResult::ErrorParsing(err)) .and_then(|AST(ref os, ref fns)| { for f in fns { - // FIX - Why are functions limited to 6 parameters? - if f.params.len() > 6 { - return Ok(()); - } - self.script_fns.insert( FnSpec { ident: f.name.clone(), diff --git a/src/engine.rs b/src/engine.rs index 8388f2e5..dfdf0309 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -21,7 +21,7 @@ const KEYWORD_TYPE_OF: &'static str = "type_of"; pub enum EvalAltResult { ErrorParsing(ParseError), ErrorFunctionNotFound(String, Position), - ErrorFunctionArgsMismatch(String, usize, Position), + ErrorFunctionArgsMismatch(String, usize, usize, Position), ErrorBooleanArgMismatch(String, Position), ErrorArrayBounds(usize, i64, Position), ErrorStringBounds(usize, i64, Position), @@ -45,7 +45,7 @@ impl Error for EvalAltResult { match self { Self::ErrorParsing(p) => p.description(), Self::ErrorFunctionNotFound(_, _) => "Function not found", - Self::ErrorFunctionArgsMismatch(_, _, _) => { + Self::ErrorFunctionArgsMismatch(_, _, _, _) => { "Function call with wrong number of arguments" } Self::ErrorBooleanArgMismatch(_, _) => "Boolean operator expects boolean operands", @@ -105,9 +105,11 @@ impl std::fmt::Display for EvalAltResult { write!(f, "{} '{}': {}", desc, filename, err) } Self::ErrorParsing(p) => write!(f, "Syntax error: {}", p), - Self::ErrorFunctionArgsMismatch(fun, n, pos) => { - write!(f, "Function '{}' expects {} argument(s) ({})", fun, n, pos) - } + Self::ErrorFunctionArgsMismatch(fun, need, n, pos) => write!( + f, + "Function '{}' expects {} argument(s) but {} found ({})", + fun, need, n, pos + ), Self::ErrorBooleanArgMismatch(op, pos) => { write!(f, "{} operator expects boolean operands ({})", op, pos) } @@ -244,6 +246,15 @@ impl Engine { .into_dynamic()) } FnIntExt::Int(ref f) => { + if f.params.len() != args.len() { + return Err(EvalAltResult::ErrorFunctionArgsMismatch( + spec.ident, + f.params.len(), + args.len(), + pos, + )); + } + let mut scope = Scope::new(); scope.extend( diff --git a/src/fn_register.rs b/src/fn_register.rs index ee08dfd1..4e28b05f 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -39,7 +39,7 @@ macro_rules! def_register { const NUM_ARGS: usize = count_args!($($par)*); if args.len() != NUM_ARGS { - Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, pos)) + Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos)) } else { #[allow(unused_variables, unused_mut)] let mut drain = args.drain(..); @@ -72,7 +72,7 @@ macro_rules! def_register { const NUM_ARGS: usize = count_args!($($par)*); if args.len() != NUM_ARGS { - Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, pos)) + Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos)) } else { #[allow(unused_variables, unused_mut)] let mut drain = args.drain(..);