Fix problems with script-defined functions.

This commit is contained in:
Stephen Chung 2020-03-03 23:31:16 +08:00
parent 01bee6e16e
commit 3af421ae5f
4 changed files with 21 additions and 12 deletions

View File

@ -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). 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. Furthermore, functions can only be defined at the top level, never inside a block or another function.
```rust ```rust

View File

@ -144,11 +144,6 @@ impl Engine {
.map_err(|err| EvalAltResult::ErrorParsing(err)) .map_err(|err| EvalAltResult::ErrorParsing(err))
.and_then(|AST(ref os, ref fns)| { .and_then(|AST(ref os, ref fns)| {
for f in fns { for f in fns {
// FIX - Why are functions limited to 6 parameters?
if f.params.len() > 6 {
return Ok(());
}
self.script_fns.insert( self.script_fns.insert(
FnSpec { FnSpec {
ident: f.name.clone(), ident: f.name.clone(),

View File

@ -21,7 +21,7 @@ const KEYWORD_TYPE_OF: &'static str = "type_of";
pub enum EvalAltResult { pub enum EvalAltResult {
ErrorParsing(ParseError), ErrorParsing(ParseError),
ErrorFunctionNotFound(String, Position), ErrorFunctionNotFound(String, Position),
ErrorFunctionArgsMismatch(String, usize, Position), ErrorFunctionArgsMismatch(String, usize, usize, Position),
ErrorBooleanArgMismatch(String, Position), ErrorBooleanArgMismatch(String, Position),
ErrorArrayBounds(usize, i64, Position), ErrorArrayBounds(usize, i64, Position),
ErrorStringBounds(usize, i64, Position), ErrorStringBounds(usize, i64, Position),
@ -45,7 +45,7 @@ impl Error for EvalAltResult {
match self { match self {
Self::ErrorParsing(p) => p.description(), Self::ErrorParsing(p) => p.description(),
Self::ErrorFunctionNotFound(_, _) => "Function not found", Self::ErrorFunctionNotFound(_, _) => "Function not found",
Self::ErrorFunctionArgsMismatch(_, _, _) => { Self::ErrorFunctionArgsMismatch(_, _, _, _) => {
"Function call with wrong number of arguments" "Function call with wrong number of arguments"
} }
Self::ErrorBooleanArgMismatch(_, _) => "Boolean operator expects boolean operands", Self::ErrorBooleanArgMismatch(_, _) => "Boolean operator expects boolean operands",
@ -105,9 +105,11 @@ impl std::fmt::Display for EvalAltResult {
write!(f, "{} '{}': {}", desc, filename, err) write!(f, "{} '{}': {}", desc, filename, err)
} }
Self::ErrorParsing(p) => write!(f, "Syntax error: {}", p), Self::ErrorParsing(p) => write!(f, "Syntax error: {}", p),
Self::ErrorFunctionArgsMismatch(fun, n, pos) => { Self::ErrorFunctionArgsMismatch(fun, need, n, pos) => write!(
write!(f, "Function '{}' expects {} argument(s) ({})", fun, n, pos) f,
} "Function '{}' expects {} argument(s) but {} found ({})",
fun, need, n, pos
),
Self::ErrorBooleanArgMismatch(op, pos) => { Self::ErrorBooleanArgMismatch(op, pos) => {
write!(f, "{} operator expects boolean operands ({})", op, pos) write!(f, "{} operator expects boolean operands ({})", op, pos)
} }
@ -244,6 +246,15 @@ impl Engine {
.into_dynamic()) .into_dynamic())
} }
FnIntExt::Int(ref f) => { 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(); let mut scope = Scope::new();
scope.extend( scope.extend(

View File

@ -39,7 +39,7 @@ macro_rules! def_register {
const NUM_ARGS: usize = count_args!($($par)*); const NUM_ARGS: usize = count_args!($($par)*);
if args.len() != NUM_ARGS { 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 { } else {
#[allow(unused_variables, unused_mut)] #[allow(unused_variables, unused_mut)]
let mut drain = args.drain(..); let mut drain = args.drain(..);
@ -72,7 +72,7 @@ macro_rules! def_register {
const NUM_ARGS: usize = count_args!($($par)*); const NUM_ARGS: usize = count_args!($($par)*);
if args.len() != NUM_ARGS { 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 { } else {
#[allow(unused_variables, unused_mut)] #[allow(unused_variables, unused_mut)]
let mut drain = args.drain(..); let mut drain = args.drain(..);