Add function calling
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
52a63a7066
commit
10bcd77040
5 changed files with 275 additions and 7 deletions
|
|
@ -7,6 +7,7 @@ use crate::Context;
|
|||
use crate::emit::Instruction;
|
||||
use crate::emit::VMInstructions;
|
||||
use crate::emit::VariableSlot;
|
||||
use crate::functions::FunctionMap;
|
||||
use crate::input::NomoInput;
|
||||
use crate::value::NomoValue;
|
||||
|
||||
|
|
@ -69,7 +70,11 @@ impl Scope {
|
|||
clippy::unnecessary_to_owned,
|
||||
reason = "We cannot do the suggested way as the lifetimes would not match up"
|
||||
)]
|
||||
pub fn execute(vm: &VMInstructions, global_context: &Context) -> Result<String, EvaluationError> {
|
||||
pub fn execute(
|
||||
available_functions: &FunctionMap,
|
||||
vm: &VMInstructions,
|
||||
global_context: &Context,
|
||||
) -> Result<String, EvaluationError> {
|
||||
let mut output = String::new();
|
||||
|
||||
let mut scopes = Scope {
|
||||
|
|
@ -208,7 +213,17 @@ pub fn execute(vm: &VMInstructions, global_context: &Context) -> Result<String,
|
|||
|
||||
scopes.insert_into_slot(*result_slot, result.unwrap());
|
||||
}
|
||||
Instruction::FunctionCall { .. } => todo!(),
|
||||
Instruction::FunctionCall { name, args, slot } => {
|
||||
let args = args.iter().map(|slot| scopes.get(slot)).cloned().collect();
|
||||
|
||||
let value = available_functions
|
||||
.get(name.as_str())
|
||||
.unwrap()
|
||||
.call(args)
|
||||
.unwrap();
|
||||
|
||||
scopes.insert_into_slot(*slot, value);
|
||||
}
|
||||
}
|
||||
|
||||
ip += 1;
|
||||
|
|
@ -221,6 +236,8 @@ pub fn execute(vm: &VMInstructions, global_context: &Context) -> Result<String,
|
|||
mod tests {
|
||||
use crate::Context;
|
||||
use crate::eval::execute;
|
||||
use crate::functions::FunctionMap;
|
||||
use crate::functions::NomoFunctionError;
|
||||
|
||||
#[test]
|
||||
fn check_simple_variable_interpolation() {
|
||||
|
|
@ -234,7 +251,7 @@ mod tests {
|
|||
|
||||
let mut context = Context::new();
|
||||
context.insert("world", "World");
|
||||
let output = execute(&emit, &context);
|
||||
let output = execute(&FunctionMap::default(), &emit, &context);
|
||||
|
||||
insta::assert_debug_snapshot!(output, @r#"
|
||||
Ok(
|
||||
|
|
@ -242,4 +259,31 @@ mod tests {
|
|||
)
|
||||
"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_method_call() {
|
||||
let input = "Hello {{= foo(world) }}";
|
||||
|
||||
let parsed = crate::parser::parse(input.into()).unwrap();
|
||||
|
||||
let ast = crate::ast::parse(parsed.tokens()).unwrap();
|
||||
|
||||
let emit = crate::emit::emit_machine(ast);
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("world", "World");
|
||||
let mut function_map = FunctionMap::default();
|
||||
|
||||
function_map.register("foo", |arg: String| -> Result<String, NomoFunctionError> {
|
||||
Ok(arg.to_uppercase())
|
||||
});
|
||||
|
||||
let output = execute(&function_map, &emit, &context);
|
||||
|
||||
insta::assert_debug_snapshot!(output, @r#"
|
||||
Ok(
|
||||
"Hello WORLD",
|
||||
)
|
||||
"#);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue