Allow overloading of script functions.
This commit is contained in:
36
src/api.rs
36
src/api.rs
@@ -174,9 +174,15 @@ impl<'e> Engine<'e> {
|
||||
let statements = {
|
||||
let AST(statements, functions) = ast;
|
||||
|
||||
functions.iter().for_each(|f| {
|
||||
engine.script_functions.push(f.clone());
|
||||
});
|
||||
for f in functions {
|
||||
match engine
|
||||
.script_functions
|
||||
.binary_search_by(|fn_def| fn_def.compare(&f.name, f.params.len()))
|
||||
{
|
||||
Ok(n) => engine.script_functions[n] = f.clone(),
|
||||
Err(n) => engine.script_functions.insert(n, f.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
statements
|
||||
};
|
||||
@@ -253,9 +259,15 @@ impl<'e> Engine<'e> {
|
||||
let statements = {
|
||||
let AST(ref statements, ref functions) = ast;
|
||||
|
||||
functions.iter().for_each(|f| {
|
||||
self.script_functions.push(f.clone());
|
||||
});
|
||||
for f in functions {
|
||||
match self
|
||||
.script_functions
|
||||
.binary_search_by(|fn_def| fn_def.compare(&f.name, f.params.len()))
|
||||
{
|
||||
Ok(n) => self.script_functions[n] = f.clone(),
|
||||
Err(n) => self.script_functions.insert(n, f.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
statements
|
||||
};
|
||||
@@ -308,9 +320,15 @@ impl<'e> Engine<'e> {
|
||||
ast: &AST,
|
||||
args: FnCallArgs,
|
||||
) -> Result<Dynamic, EvalAltResult> {
|
||||
ast.1.iter().for_each(|f| {
|
||||
engine.script_functions.push(f.clone());
|
||||
});
|
||||
for f in &ast.1 {
|
||||
match engine
|
||||
.script_functions
|
||||
.binary_search_by(|fn_def| fn_def.compare(&f.name, f.params.len()))
|
||||
{
|
||||
Ok(n) => engine.script_functions[n] = f.clone(),
|
||||
Err(n) => engine.script_functions.insert(n, f.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
let result = engine.call_fn_raw(name, args, None, Position::none());
|
||||
|
||||
|
@@ -41,7 +41,7 @@ enum IndexSourceType {
|
||||
Expression,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
||||
pub struct FnSpec<'a> {
|
||||
pub name: Cow<'a, str>,
|
||||
pub args: Option<Vec<TypeId>>,
|
||||
@@ -82,10 +82,10 @@ impl Engine<'_> {
|
||||
pub fn new() -> Self {
|
||||
// User-friendly names for built-in types
|
||||
let type_names = [
|
||||
(type_name::<String>(), "string"),
|
||||
(type_name::<Dynamic>(), "dynamic"),
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
(type_name::<Array>(), "array"),
|
||||
(type_name::<String>(), "string"),
|
||||
(type_name::<Dynamic>(), "dynamic"),
|
||||
]
|
||||
.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
@@ -135,22 +135,11 @@ impl Engine<'_> {
|
||||
);
|
||||
|
||||
// First search in script-defined functions (can override built-in)
|
||||
if let Some(func) = self
|
||||
if let Ok(n) = self
|
||||
.script_functions
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|fn_def| fn_def.name == fn_name)
|
||||
.map(|fn_def| fn_def.clone())
|
||||
.binary_search_by(|f| f.compare(fn_name, args.len()))
|
||||
{
|
||||
// First check number of parameters
|
||||
if func.params.len() != args.len() {
|
||||
return Err(EvalAltResult::ErrorFunctionArgsMismatch(
|
||||
fn_name.into(),
|
||||
func.params.len(),
|
||||
args.len(),
|
||||
pos,
|
||||
));
|
||||
}
|
||||
let func = self.script_functions[n].clone();
|
||||
|
||||
let mut scope = Scope::new();
|
||||
|
||||
@@ -838,13 +827,9 @@ impl Engine<'_> {
|
||||
Expr::Array(contents, _) => {
|
||||
let mut arr = Vec::new();
|
||||
|
||||
contents
|
||||
.iter()
|
||||
.try_for_each::<_, Result<_, EvalAltResult>>(|item| {
|
||||
let arg = self.eval_expr(scope, item)?;
|
||||
arr.push(arg);
|
||||
Ok(())
|
||||
})?;
|
||||
for item in contents {
|
||||
arr.push(self.eval_expr(scope, item)?);
|
||||
}
|
||||
|
||||
Ok(Box::new(arr))
|
||||
}
|
||||
|
@@ -1944,7 +1944,15 @@ fn parse_top_level<'a>(
|
||||
while input.peek().is_some() {
|
||||
match input.peek() {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
Some(&(Token::Fn, _)) => functions.push(parse_fn(input)?),
|
||||
Some(&(Token::Fn, _)) => {
|
||||
let f = parse_fn(input)?;
|
||||
|
||||
// Ensure list is sorted
|
||||
match functions.binary_search_by(|fn_def| fn_def.compare(&f.name, f.params.len())) {
|
||||
Ok(n) => functions[n] = f, // Override previous definition
|
||||
Err(n) => functions.insert(n, f), // New function definition
|
||||
}
|
||||
}
|
||||
_ => statements.push(parse_stmt(input)?),
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user