Add emitting of function calls

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2026-03-14 10:52:29 +01:00
parent cb55c00739
commit 52a63a7066
5 changed files with 116 additions and 11 deletions

View file

@ -270,7 +270,7 @@ pub enum TemplateAstExpr<'input> {
value: NomoValue, value: NomoValue,
}, },
FunctionCall { FunctionCall {
name: Box<TemplateAstExpr<'input>>, name: TemplateToken,
args: Vec<TemplateAstExpr<'input>>, args: Vec<TemplateAstExpr<'input>>,
}, },
} }
@ -568,9 +568,7 @@ fn parse_function<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'
trace( trace(
"variable_access", "variable_access",
( (
TokenKind::Ident TokenKind::Ident,
.map(TemplateAstExpr::VariableAccess)
.map(Box::new),
TokenKind::LeftArgList, TokenKind::LeftArgList,
separated(0.., parse_expression, TokenKind::ArgSeperator), separated(0.., parse_expression, TokenKind::ArgSeperator),
TokenKind::RightArgList, TokenKind::RightArgList,

View file

@ -7,9 +7,7 @@ TemplateAst {
Interpolation { Interpolation {
prev_whitespace_content: None, prev_whitespace_content: None,
expression: FunctionCall { expression: FunctionCall {
name: VariableAccess( name: [Ident]"foo" (4..7),
[Ident]"foo" (4..7),
),
args: [ args: [
Operation { Operation {
op: Times, op: Times,
@ -27,9 +25,7 @@ TemplateAst {
}, },
}, },
FunctionCall { FunctionCall {
name: VariableAccess( name: [Ident]"bar" (15..18),
[Ident]"bar" (15..18),
),
args: [ args: [
Operation { Operation {
op: Plus, op: Plus,

View file

@ -102,6 +102,11 @@ pub enum Instruction {
right_slot: VariableSlot, right_slot: VariableSlot,
result_slot: VariableSlot, result_slot: VariableSlot,
}, },
FunctionCall {
name: NomoInput,
args: Vec<VariableSlot>,
slot: VariableSlot,
},
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -456,11 +461,24 @@ fn emit_expr_load(
result_slot: emit_slot, result_slot: emit_slot,
}); });
} }
TemplateAstExpr::FunctionCall { name, args } => {
let mut arg_slots = vec![];
for arg in args {
let slot = machine.reserve_slot();
emit_expr_load(machine, eval, slot, arg);
arg_slots.push(slot);
}
eval.push(Instruction::FunctionCall {
name: name.source(),
args: arg_slots,
slot: emit_slot,
});
}
TemplateAstExpr::Invalid { .. } => eval.push(Instruction::Abort), TemplateAstExpr::Invalid { .. } => eval.push(Instruction::Abort),
TemplateAstExpr::StaticContent { .. } | TemplateAstExpr::Interpolation { .. } => { TemplateAstExpr::StaticContent { .. } | TemplateAstExpr::Interpolation { .. } => {
unreachable!("Invalid AST here") unreachable!("Invalid AST here")
} }
TemplateAstExpr::FunctionCall { .. } => todo!(),
TemplateAstExpr::ConditionalChain { .. } => todo!(), TemplateAstExpr::ConditionalChain { .. } => todo!(),
TemplateAstExpr::ElseConditional { .. } => todo!(), TemplateAstExpr::ElseConditional { .. } => todo!(),
TemplateAstExpr::EndBlock => todo!(), TemplateAstExpr::EndBlock => todo!(),
@ -526,4 +544,17 @@ mod tests {
insta::assert_debug_snapshot!(emit); insta::assert_debug_snapshot!(emit);
} }
#[test]
fn check_function_call() {
let input = "{{ if foo(23) }} bar {{ else }} foobar {{ end }}";
let parsed = crate::parser::parse(input.into()).unwrap();
let ast = crate::ast::parse(parsed.tokens()).unwrap();
let emit = emit_machine(ast);
insta::assert_debug_snapshot!(emit);
}
} }

View file

@ -0,0 +1,79 @@
---
source: src/emit/mod.rs
expression: emit
---
VMInstructions {
labels: {
LabelSlot {
index: 0,
}: 13,
LabelSlot {
index: 3,
}: 8,
},
instructions: [
LoadLiteralToSlot {
source: [Literal(Integer(23))]"23" (10..12),
value: Integer {
value: 23,
},
slot: VariableSlot {
index: 2,
},
},
FunctionCall {
name: "foo" (6..9),
args: [
VariableSlot {
index: 2,
},
],
slot: VariableSlot {
index: 1,
},
},
JumpIfNotTrue {
emit_slot: VariableSlot {
index: 1,
},
jump: LabelSlot {
index: 3,
},
},
AppendContent {
content: " " (16..17),
},
AppendContent {
content: "bar" (17..20),
},
AppendContent {
content: " " (20..21),
},
Jump {
jump: LabelSlot {
index: 0,
},
},
AppendContent {
content: " " (16..17),
},
AppendContent {
content: " " (31..32),
},
AppendContent {
content: "foobar" (32..38),
},
AppendContent {
content: " " (38..39),
},
Jump {
jump: LabelSlot {
index: 0,
},
},
AppendContent {
content: " " (31..32),
},
NoOp,
],
}

View file

@ -208,6 +208,7 @@ pub fn execute(vm: &VMInstructions, global_context: &Context) -> Result<String,
scopes.insert_into_slot(*result_slot, result.unwrap()); scopes.insert_into_slot(*result_slot, result.unwrap());
} }
Instruction::FunctionCall { .. } => todo!(),
} }
ip += 1; ip += 1;