Add conditional value emitting
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
662e574588
commit
9940881e46
10 changed files with 82 additions and 11 deletions
|
|
@ -57,6 +57,7 @@ pub enum Instruction {
|
||||||
LoadFromContextToSlot {
|
LoadFromContextToSlot {
|
||||||
name: NomoInput,
|
name: NomoInput,
|
||||||
slot: VariableSlot,
|
slot: VariableSlot,
|
||||||
|
fail_on_not_found: bool,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot,
|
slot: VariableSlot,
|
||||||
|
|
@ -440,6 +441,14 @@ fn emit_expr_load(
|
||||||
eval.push(Instruction::LoadFromContextToSlot {
|
eval.push(Instruction::LoadFromContextToSlot {
|
||||||
name: template_token.source().clone(),
|
name: template_token.source().clone(),
|
||||||
slot: emit_slot,
|
slot: emit_slot,
|
||||||
|
fail_on_not_found: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
TemplateAstExpr::ConditionalAccess(template_token) => {
|
||||||
|
eval.push(Instruction::LoadFromContextToSlot {
|
||||||
|
name: template_token.source().clone(),
|
||||||
|
slot: emit_slot,
|
||||||
|
fail_on_not_found: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
TemplateAstExpr::Literal { source, value } => {
|
TemplateAstExpr::Literal { source, value } => {
|
||||||
|
|
@ -476,7 +485,6 @@ fn emit_expr_load(
|
||||||
slot: emit_slot,
|
slot: emit_slot,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
TemplateAstExpr::ConditionalAccess { .. } => todo!(),
|
|
||||||
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")
|
||||||
|
|
@ -523,6 +531,7 @@ mod tests {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 0,
|
index: 0,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 1,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
|
|
@ -51,6 +52,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 3,
|
index: 3,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
|
|
|
||||||
|
|
@ -93,15 +93,34 @@ pub fn execute(
|
||||||
match instr {
|
match instr {
|
||||||
Instruction::NoOp => (),
|
Instruction::NoOp => (),
|
||||||
Instruction::AppendContent { content } => output.push_str(content),
|
Instruction::AppendContent { content } => output.push_str(content),
|
||||||
Instruction::LoadFromContextToSlot { name, slot } => {
|
Instruction::LoadFromContextToSlot {
|
||||||
let value = scopes
|
name,
|
||||||
.get_scoped(name)
|
slot,
|
||||||
.ok_or(EvaluationError::UnknownVariable(name.clone()))?;
|
fail_on_not_found,
|
||||||
|
} => {
|
||||||
|
let value = scopes.get_scoped(name);
|
||||||
|
|
||||||
|
let value = if let Some(val) = value {
|
||||||
|
val
|
||||||
|
} else {
|
||||||
|
if *fail_on_not_found {
|
||||||
|
return Err(EvaluationError::UnknownVariable(name.clone()));
|
||||||
|
} else {
|
||||||
|
&NomoValue::Undefined
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
scopes.insert_into_slot(*slot, value.clone());
|
scopes.insert_into_slot(*slot, value.clone());
|
||||||
}
|
}
|
||||||
Instruction::EmitFromSlot { slot } => {
|
Instruction::EmitFromSlot { slot } => {
|
||||||
let value = scopes.get(slot).try_to_string().unwrap();
|
let value = scopes.get(slot);
|
||||||
|
let value = if let Some(value) = value.try_to_string() {
|
||||||
|
value
|
||||||
|
} else if matches!(value, NomoValue::Undefined) {
|
||||||
|
String::new()
|
||||||
|
} else {
|
||||||
|
panic!("Unknown variable");
|
||||||
|
};
|
||||||
|
|
||||||
output.push_str(&value);
|
output.push_str(&value);
|
||||||
}
|
}
|
||||||
|
|
@ -286,4 +305,26 @@ mod tests {
|
||||||
)
|
)
|
||||||
"#);
|
"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_conditional_access() {
|
||||||
|
let input = "Hello {{= unknown? }}";
|
||||||
|
|
||||||
|
let parsed = crate::lexer::parse(input.into()).unwrap();
|
||||||
|
|
||||||
|
let ast = crate::parser::parse(parsed.tokens()).unwrap();
|
||||||
|
|
||||||
|
let emit = crate::compiler::emit_machine(ast);
|
||||||
|
|
||||||
|
let context = Context::new();
|
||||||
|
let function_map = FunctionMap::default();
|
||||||
|
|
||||||
|
let output = execute(&function_map, &emit, &context);
|
||||||
|
|
||||||
|
insta::assert_debug_snapshot!(output, @r#"
|
||||||
|
Ok(
|
||||||
|
"Hello ",
|
||||||
|
)
|
||||||
|
"#);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 1,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
|
|
@ -56,6 +57,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 3,
|
index: 3,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ expression: emit
|
||||||
info:
|
info:
|
||||||
input: "{{= _name }}\n{{= a_name }}\n{{= name }}\n{{= _name1 }}\n{{= _namE }}\n{{= name1 }}"
|
input: "{{= _name }}\n{{= a_name }}\n{{= name }}\n{{= _name1 }}\n{{= _namE }}\n{{= name1 }}"
|
||||||
context:
|
context:
|
||||||
name1: Foo
|
|
||||||
_name: Foo
|
|
||||||
_namE: Foo
|
|
||||||
a_name: Foo
|
a_name: Foo
|
||||||
name: Foo
|
_name: Foo
|
||||||
_name1: Foo
|
_name1: Foo
|
||||||
|
_namE: Foo
|
||||||
|
name1: Foo
|
||||||
|
name: Foo
|
||||||
---
|
---
|
||||||
VMInstructions {
|
VMInstructions {
|
||||||
labels: {},
|
labels: {},
|
||||||
|
|
@ -19,6 +19,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 0,
|
index: 0,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
@ -33,6 +34,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 1,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
@ -47,6 +49,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 2,
|
index: 2,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
@ -61,6 +64,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 3,
|
index: 3,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
@ -75,6 +79,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 4,
|
index: 4,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
@ -89,6 +94,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 5,
|
index: 5,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 1,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
|
|
@ -57,6 +58,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 3,
|
index: 3,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 0,
|
index: 0,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 0,
|
index: 0,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
@ -35,6 +36,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 1,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 4,
|
index: 4,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
CreateIteratorFromSlotToSlot {
|
CreateIteratorFromSlotToSlot {
|
||||||
iterator_slot: VariableSlot {
|
iterator_slot: VariableSlot {
|
||||||
|
|
@ -78,6 +79,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 6,
|
index: 6,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
@ -104,6 +106,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 11,
|
index: 11,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
CreateIteratorFromSlotToSlot {
|
CreateIteratorFromSlotToSlot {
|
||||||
iterator_slot: VariableSlot {
|
iterator_slot: VariableSlot {
|
||||||
|
|
@ -143,6 +146,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 13,
|
index: 13,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ expression: emit
|
||||||
info:
|
info:
|
||||||
input: "{{ if test -}}\n Hello {{= stuff -}}\n{{- end }}"
|
input: "{{ if test -}}\n Hello {{= stuff -}}\n{{- end }}"
|
||||||
context:
|
context:
|
||||||
stuff: Hemera
|
|
||||||
test: true
|
test: true
|
||||||
|
stuff: Hemera
|
||||||
---
|
---
|
||||||
VMInstructions {
|
VMInstructions {
|
||||||
labels: {
|
labels: {
|
||||||
|
|
@ -22,6 +22,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 1,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
|
|
@ -42,6 +43,7 @@ VMInstructions {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 3,
|
index: 3,
|
||||||
},
|
},
|
||||||
|
fail_on_not_found: true,
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue