Add function calling

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2026-03-15 11:27:25 +01:00
parent 52a63a7066
commit 10bcd77040
5 changed files with 275 additions and 7 deletions

View file

@ -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",
)
"#);
}
}