Add parsing for conditionals (cont.)
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
974086a877
commit
8afc2d1bde
29 changed files with 994 additions and 746 deletions
161
src/emit/mod.rs
161
src/emit/mod.rs
|
|
@ -24,11 +24,24 @@ pub struct VariableSlot {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub enum Instruction {
|
||||
AppendContent { content: NomoInput },
|
||||
LoadFromContextToSlot { name: NomoInput, slot: VariableSlot },
|
||||
EmitFromSlot { slot: VariableSlot },
|
||||
PushScope { inherit_parent: bool },
|
||||
AppendContent {
|
||||
content: NomoInput,
|
||||
},
|
||||
LoadFromContextToSlot {
|
||||
name: NomoInput,
|
||||
slot: VariableSlot,
|
||||
},
|
||||
EmitFromSlot {
|
||||
slot: VariableSlot,
|
||||
},
|
||||
PushScope {
|
||||
inherit_parent: bool,
|
||||
},
|
||||
Abort,
|
||||
JumpIfNotTrue {
|
||||
emit_slot: VariableSlot,
|
||||
jump: isize,
|
||||
},
|
||||
}
|
||||
|
||||
pub fn emit_machine(input: crate::ast::TemplateAst<'_>) -> Vec<Instruction> {
|
||||
|
|
@ -55,53 +68,110 @@ fn emit_ast_expr(
|
|||
});
|
||||
}
|
||||
TemplateAstExpr::Interpolation {
|
||||
prev_whitespace_content: prev_whitespace,
|
||||
wants_output,
|
||||
prev_whitespace_content,
|
||||
expression,
|
||||
post_whitespace_content: post_whitespace,
|
||||
post_whitespace_content,
|
||||
} => {
|
||||
if let Some(ws) = prev_whitespace {
|
||||
if let Some(ws) = prev_whitespace_content {
|
||||
eval.push(Instruction::AppendContent {
|
||||
content: ws.source().clone(),
|
||||
});
|
||||
}
|
||||
|
||||
let emit_slot = machine.reserve_slot();
|
||||
emit_expr(machine, eval, emit_slot, expression);
|
||||
emit_expr_load(machine, eval, emit_slot, expression);
|
||||
eval.push(Instruction::EmitFromSlot { slot: emit_slot });
|
||||
|
||||
if let Some(ws) = post_whitespace {
|
||||
if let Some(ws) = post_whitespace_content {
|
||||
eval.push(Instruction::AppendContent {
|
||||
content: ws.source().clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
TemplateAstExpr::Invalid { .. } | TemplateAstExpr::VariableAccess { .. } => {
|
||||
eval.push(Instruction::Abort)
|
||||
TemplateAstExpr::ConditionalChain { chain } => {
|
||||
let mut chain = chain.iter();
|
||||
let Some(TemplateAstExpr::IfConditional {
|
||||
if_block: expression,
|
||||
content,
|
||||
end_block,
|
||||
}) = chain.next()
|
||||
else {
|
||||
unreachable!("First element in conditional chain should be an IfConditional");
|
||||
};
|
||||
|
||||
let TemplateAstExpr::Block {
|
||||
prev_whitespace_content,
|
||||
expression,
|
||||
post_whitespace_content,
|
||||
} = expression.as_ref()
|
||||
else {
|
||||
unreachable!("The end of an IfConditional must be a Block");
|
||||
};
|
||||
|
||||
if let Some(ws) = prev_whitespace_content {
|
||||
eval.push(Instruction::AppendContent {
|
||||
content: ws.source().clone(),
|
||||
});
|
||||
}
|
||||
|
||||
let emit_slot = machine.reserve_slot();
|
||||
emit_expr_load(machine, eval, emit_slot, expression);
|
||||
|
||||
let index = eval.len();
|
||||
eval.push(Instruction::JumpIfNotTrue {
|
||||
emit_slot,
|
||||
jump: isize::MAX,
|
||||
});
|
||||
|
||||
if let Some(ws) = post_whitespace_content {
|
||||
eval.push(Instruction::AppendContent {
|
||||
content: ws.source().clone(),
|
||||
});
|
||||
}
|
||||
|
||||
for ast in content {
|
||||
emit_ast_expr(machine, eval, ast);
|
||||
}
|
||||
|
||||
let TemplateAstExpr::Block {
|
||||
prev_whitespace_content,
|
||||
post_whitespace_content,
|
||||
..
|
||||
} = end_block.as_ref()
|
||||
else {
|
||||
unreachable!("The end of an IfConditional must be a Block");
|
||||
};
|
||||
|
||||
if let Some(ws) = prev_whitespace_content {
|
||||
eval.push(Instruction::AppendContent {
|
||||
content: ws.source().clone(),
|
||||
});
|
||||
}
|
||||
|
||||
let jump = eval.len() - index - 1;
|
||||
eval[index] = Instruction::JumpIfNotTrue {
|
||||
emit_slot,
|
||||
jump: jump as isize,
|
||||
};
|
||||
|
||||
if let Some(ws) = post_whitespace_content {
|
||||
eval.push(Instruction::AppendContent {
|
||||
content: ws.source().clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
TemplateAstExpr::ConditionalChain { chain } => todo!(),
|
||||
TemplateAstExpr::ElseConditional { expression } => todo!(),
|
||||
TemplateAstExpr::Action {
|
||||
prev_whitespace_content,
|
||||
expression,
|
||||
post_whitespace_content,
|
||||
} => todo!(),
|
||||
TemplateAstExpr::EndBlock => todo!(),
|
||||
TemplateAstExpr::Block {
|
||||
prev_whitespace_content,
|
||||
expression,
|
||||
post_whitespace_content,
|
||||
} => todo!(),
|
||||
TemplateAstExpr::IfConditional {
|
||||
expression,
|
||||
content,
|
||||
end_block,
|
||||
} => todo!(),
|
||||
|
||||
TemplateAstExpr::Block { .. }
|
||||
| TemplateAstExpr::EndBlock
|
||||
| TemplateAstExpr::IfConditional { .. }
|
||||
| TemplateAstExpr::ElseConditional { .. }
|
||||
| TemplateAstExpr::Invalid { .. }
|
||||
| TemplateAstExpr::VariableAccess { .. } => eval.push(Instruction::Abort),
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_expr(
|
||||
machine: &mut EmitMachine,
|
||||
fn emit_expr_load(
|
||||
_machine: &mut EmitMachine,
|
||||
eval: &mut Vec<Instruction>,
|
||||
emit_slot: VariableSlot,
|
||||
expression: &TemplateAstExpr<'_>,
|
||||
|
|
@ -117,24 +187,11 @@ fn emit_expr(
|
|||
TemplateAstExpr::StaticContent { .. } | TemplateAstExpr::Interpolation { .. } => {
|
||||
unreachable!("Invalid AST here")
|
||||
}
|
||||
TemplateAstExpr::ConditionalChain { chain } => todo!(),
|
||||
TemplateAstExpr::ElseConditional { expression } => todo!(),
|
||||
TemplateAstExpr::Action {
|
||||
prev_whitespace_content,
|
||||
expression,
|
||||
post_whitespace_content,
|
||||
} => todo!(),
|
||||
TemplateAstExpr::ConditionalChain { .. } => todo!(),
|
||||
TemplateAstExpr::ElseConditional { .. } => todo!(),
|
||||
TemplateAstExpr::EndBlock => todo!(),
|
||||
TemplateAstExpr::Block {
|
||||
prev_whitespace_content,
|
||||
expression,
|
||||
post_whitespace_content,
|
||||
} => todo!(),
|
||||
TemplateAstExpr::IfConditional {
|
||||
expression,
|
||||
content,
|
||||
end_block,
|
||||
} => todo!(),
|
||||
TemplateAstExpr::Block { .. } => todo!(),
|
||||
TemplateAstExpr::IfConditional { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,13 +212,13 @@ mod tests {
|
|||
insta::assert_debug_snapshot!(emit, @r#"
|
||||
[
|
||||
AppendContent {
|
||||
content: "Hello",
|
||||
content: "Hello" (0..5),
|
||||
},
|
||||
AppendContent {
|
||||
content: " ",
|
||||
content: " " (5..6),
|
||||
},
|
||||
LoadFromContextToSlot {
|
||||
name: "world",
|
||||
name: "world" (10..15),
|
||||
slot: VariableSlot {
|
||||
index: 0,
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue