Compare commits
No commits in common. "ffd9baf90f56fac6530dfed1274443a3e4039a6d" and "9940881e46881209835e769d78d58f9e570cf3dc" have entirely different histories.
ffd9baf90f
...
9940881e46
15 changed files with 36 additions and 766 deletions
|
|
@ -108,20 +108,6 @@ pub enum Instruction {
|
||||||
args: Vec<VariableSlot>,
|
args: Vec<VariableSlot>,
|
||||||
slot: VariableSlot,
|
slot: VariableSlot,
|
||||||
},
|
},
|
||||||
LoadFromSlotToSlot {
|
|
||||||
from_slot: VariableSlot,
|
|
||||||
to_slot: VariableSlot,
|
|
||||||
},
|
|
||||||
JumpIfUndefined {
|
|
||||||
slot: VariableSlot,
|
|
||||||
jump: LabelSlot,
|
|
||||||
},
|
|
||||||
IndexSlotToSlot {
|
|
||||||
name: NomoInput,
|
|
||||||
from_slot: VariableSlot,
|
|
||||||
to_slot: VariableSlot,
|
|
||||||
fail_on_not_found: bool,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -438,9 +424,8 @@ fn emit_ast_expr(
|
||||||
| TemplateAstExpr::Invalid { .. }
|
| TemplateAstExpr::Invalid { .. }
|
||||||
| TemplateAstExpr::Literal { .. }
|
| TemplateAstExpr::Literal { .. }
|
||||||
| TemplateAstExpr::FunctionCall { .. }
|
| TemplateAstExpr::FunctionCall { .. }
|
||||||
| TemplateAstExpr::MathOperation { .. }
|
| TemplateAstExpr::Operation { .. }
|
||||||
| TemplateAstExpr::ConditionalAccess { .. }
|
| TemplateAstExpr::ConditionalAccess { .. }
|
||||||
| TemplateAstExpr::AccessOperation { .. }
|
|
||||||
| TemplateAstExpr::VariableAccess { .. } => eval.push(Instruction::Abort),
|
| TemplateAstExpr::VariableAccess { .. } => eval.push(Instruction::Abort),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -466,63 +451,6 @@ fn emit_expr_load(
|
||||||
fail_on_not_found: false,
|
fail_on_not_found: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
TemplateAstExpr::AccessOperation { op, lhs, rhs } => {
|
|
||||||
assert_eq!(
|
|
||||||
op,
|
|
||||||
&TokenOperator::Dot,
|
|
||||||
"Only dot can be used to access variables, this is a bug"
|
|
||||||
);
|
|
||||||
fn inner_access_op(
|
|
||||||
eval: &mut Vec<Instruction>,
|
|
||||||
end_label: LabelSlot,
|
|
||||||
current_slot: VariableSlot,
|
|
||||||
next: &TemplateAstExpr<'_>,
|
|
||||||
) {
|
|
||||||
match next {
|
|
||||||
TemplateAstExpr::ConditionalAccess(template_token)
|
|
||||||
| TemplateAstExpr::VariableAccess(template_token) => {
|
|
||||||
eval.push(Instruction::IndexSlotToSlot {
|
|
||||||
name: template_token.source().clone(),
|
|
||||||
from_slot: current_slot,
|
|
||||||
to_slot: current_slot,
|
|
||||||
fail_on_not_found: matches!(
|
|
||||||
next,
|
|
||||||
TemplateAstExpr::VariableAccess { .. }
|
|
||||||
),
|
|
||||||
});
|
|
||||||
eval.push(Instruction::JumpIfUndefined {
|
|
||||||
slot: current_slot,
|
|
||||||
jump: end_label,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
TemplateAstExpr::AccessOperation { op, lhs, rhs } => {
|
|
||||||
assert_eq!(
|
|
||||||
op,
|
|
||||||
&TokenOperator::Dot,
|
|
||||||
"Only dot can be used to access variables, this is a bug"
|
|
||||||
);
|
|
||||||
|
|
||||||
inner_access_op(eval, end_label, current_slot, lhs);
|
|
||||||
inner_access_op(eval, end_label, current_slot, rhs);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let end_label = machine.reserve_label();
|
|
||||||
let start_slot = machine.reserve_slot();
|
|
||||||
emit_expr_load(machine, eval, start_slot, lhs);
|
|
||||||
eval.push(Instruction::JumpIfUndefined {
|
|
||||||
slot: start_slot,
|
|
||||||
jump: end_label,
|
|
||||||
});
|
|
||||||
inner_access_op(eval, end_label, start_slot, rhs);
|
|
||||||
machine.assign_label(end_label, eval.len());
|
|
||||||
eval.push(Instruction::LoadFromSlotToSlot {
|
|
||||||
from_slot: start_slot,
|
|
||||||
to_slot: emit_slot,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
TemplateAstExpr::Literal { source, value } => {
|
TemplateAstExpr::Literal { source, value } => {
|
||||||
eval.push(Instruction::LoadLiteralToSlot {
|
eval.push(Instruction::LoadLiteralToSlot {
|
||||||
source: source.clone(),
|
source: source.clone(),
|
||||||
|
|
@ -530,7 +458,7 @@ fn emit_expr_load(
|
||||||
slot: emit_slot,
|
slot: emit_slot,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
TemplateAstExpr::MathOperation { op, lhs, rhs } => {
|
TemplateAstExpr::Operation { op, lhs, rhs } => {
|
||||||
let left_slot = machine.reserve_slot();
|
let left_slot = machine.reserve_slot();
|
||||||
emit_expr_load(machine, eval, left_slot, lhs);
|
emit_expr_load(machine, eval, left_slot, lhs);
|
||||||
let right_slot = machine.reserve_slot();
|
let right_slot = machine.reserve_slot();
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ pub fn execute(
|
||||||
} else if matches!(value, NomoValue::Undefined) {
|
} else if matches!(value, NomoValue::Undefined) {
|
||||||
String::new()
|
String::new()
|
||||||
} else {
|
} else {
|
||||||
panic!("Could not print out value {value:?}");
|
panic!("Unknown variable");
|
||||||
};
|
};
|
||||||
|
|
||||||
output.push_str(&value);
|
output.push_str(&value);
|
||||||
|
|
@ -243,46 +243,6 @@ pub fn execute(
|
||||||
|
|
||||||
scopes.insert_into_slot(*slot, value);
|
scopes.insert_into_slot(*slot, value);
|
||||||
}
|
}
|
||||||
Instruction::LoadFromSlotToSlot { from_slot, to_slot } => {
|
|
||||||
let value = scopes.get(from_slot);
|
|
||||||
scopes.insert_into_slot(*to_slot, value.clone());
|
|
||||||
}
|
|
||||||
Instruction::JumpIfUndefined { slot, jump } => {
|
|
||||||
let is_undefined = matches!(scopes.get(slot), NomoValue::Undefined);
|
|
||||||
if is_undefined {
|
|
||||||
let Some(new_ip) = vm.labels.get(jump) else {
|
|
||||||
return Err(EvaluationError::LabelNotFound);
|
|
||||||
};
|
|
||||||
|
|
||||||
ip = *new_ip;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IndexSlotToSlot {
|
|
||||||
name,
|
|
||||||
from_slot,
|
|
||||||
to_slot,
|
|
||||||
fail_on_not_found,
|
|
||||||
} => {
|
|
||||||
let value = scopes.get(from_slot);
|
|
||||||
|
|
||||||
match value {
|
|
||||||
NomoValue::Object { value } => {
|
|
||||||
let value = value.get(name.as_str());
|
|
||||||
|
|
||||||
let value = if let Some(value) = value {
|
|
||||||
value.clone()
|
|
||||||
} else if *fail_on_not_found {
|
|
||||||
panic!("Could not index");
|
|
||||||
} else {
|
|
||||||
NomoValue::Undefined
|
|
||||||
};
|
|
||||||
|
|
||||||
scopes.insert_into_slot(dbg!(*to_slot), dbg!(value));
|
|
||||||
}
|
|
||||||
_ => panic!("Invalid indexing"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ip += 1;
|
ip += 1;
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,6 @@ pub enum TokenOperator {
|
||||||
Lesser,
|
Lesser,
|
||||||
LesserOrEqual,
|
LesserOrEqual,
|
||||||
QuestionMark,
|
QuestionMark,
|
||||||
Dot,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
|
@ -570,7 +569,6 @@ fn parse_operator<'input>(input: &mut Input<'input>) -> PResult<'input, Template
|
||||||
cut_err(fail),
|
cut_err(fail),
|
||||||
)),
|
)),
|
||||||
'?' => empty.value(TokenOperator::QuestionMark),
|
'?' => empty.value(TokenOperator::QuestionMark),
|
||||||
'.' => empty.value(TokenOperator::Dot),
|
|
||||||
_ => fail,
|
_ => fail,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
@ -932,28 +930,4 @@ mod tests {
|
||||||
)
|
)
|
||||||
"#);
|
"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parse_dot() {
|
|
||||||
let input = "{{= foo?.bar }}";
|
|
||||||
let output = parse(input.into());
|
|
||||||
|
|
||||||
insta::assert_debug_snapshot!(output, @r#"
|
|
||||||
Ok(
|
|
||||||
ParsedTemplate {
|
|
||||||
tokens: [
|
|
||||||
[LeftDelim]"{{" (0..2),
|
|
||||||
[WantsOutput]"=" (2..3),
|
|
||||||
[Whitespace]" " (3..4),
|
|
||||||
[Ident]"foo" (4..7),
|
|
||||||
[Operator(QuestionMark)]"?" (7..8),
|
|
||||||
[Operator(Dot)]"." (8..9),
|
|
||||||
[Ident]"bar" (9..12),
|
|
||||||
[Whitespace]" " (12..13),
|
|
||||||
[RightDelim]"}}" (13..15),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
"#);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -262,12 +262,7 @@ pub enum TemplateAstExpr<'input> {
|
||||||
expression: Option<Box<TemplateAstExpr<'input>>>,
|
expression: Option<Box<TemplateAstExpr<'input>>>,
|
||||||
},
|
},
|
||||||
Invalid(&'input [TemplateToken]),
|
Invalid(&'input [TemplateToken]),
|
||||||
MathOperation {
|
Operation {
|
||||||
op: TokenOperator,
|
|
||||||
lhs: Box<TemplateAstExpr<'input>>,
|
|
||||||
rhs: Box<TemplateAstExpr<'input>>,
|
|
||||||
},
|
|
||||||
AccessOperation {
|
|
||||||
op: TokenOperator,
|
op: TokenOperator,
|
||||||
lhs: Box<TemplateAstExpr<'input>>,
|
lhs: Box<TemplateAstExpr<'input>>,
|
||||||
rhs: Box<TemplateAstExpr<'input>>,
|
rhs: Box<TemplateAstExpr<'input>>,
|
||||||
|
|
@ -686,10 +681,10 @@ fn parse_expression<'input>(
|
||||||
input: &mut Input<'input>,
|
input: &mut Input<'input>,
|
||||||
) -> Result<TemplateAstExpr<'input>, AstError> {
|
) -> Result<TemplateAstExpr<'input>, AstError> {
|
||||||
macro_rules! infix {
|
macro_rules! infix {
|
||||||
($parser:expr => [ $($side:tt $op:tt $val:tt => $prec:expr),* $(,)? ]) => {
|
($parser:expr => [ $($side:tt $val:tt => $prec:expr),* $(,)? ]) => {
|
||||||
dispatch! { surrounded(ws, parse_operator);
|
dispatch! { surrounded(ws, parse_operator);
|
||||||
$(
|
$(
|
||||||
TokenOperator::$val => $side($prec, |_, lhs, rhs| Ok(TemplateAstExpr::$op {
|
TokenOperator::$val => $side($prec, |_, lhs, rhs| Ok(TemplateAstExpr::Operation {
|
||||||
op: TokenOperator::$val,
|
op: TokenOperator::$val,
|
||||||
lhs: Box::new(lhs),
|
lhs: Box::new(lhs),
|
||||||
rhs: Box::new(rhs)
|
rhs: Box::new(rhs)
|
||||||
|
|
@ -703,22 +698,21 @@ fn parse_expression<'input>(
|
||||||
"expression",
|
"expression",
|
||||||
expression(surrounded(ws, parse_operand)).infix(infix! {
|
expression(surrounded(ws, parse_operand)).infix(infix! {
|
||||||
surrounded(ws, parse_operator) => [
|
surrounded(ws, parse_operator) => [
|
||||||
Left MathOperation Plus => 18,
|
Left Plus => 18,
|
||||||
Left MathOperation Minus => 18,
|
Left Minus => 18,
|
||||||
Left MathOperation Times => 20,
|
Left Times => 20,
|
||||||
Left MathOperation Divide => 20,
|
Left Divide => 20,
|
||||||
Left MathOperation And => 10,
|
Left And => 10,
|
||||||
Left MathOperation Or => 7,
|
Left Or => 7,
|
||||||
Left MathOperation Equal => 12,
|
Left Equal => 12,
|
||||||
Left MathOperation NotEqual => 12,
|
Left NotEqual => 12,
|
||||||
Left MathOperation Greater => 15,
|
Left Greater => 15,
|
||||||
Left MathOperation GreaterOrEqual => 15,
|
Left GreaterOrEqual => 15,
|
||||||
Left MathOperation Lesser => 15,
|
Left Lesser => 15,
|
||||||
Left MathOperation LesserOrEqual => 15,
|
Left LesserOrEqual => 15,
|
||||||
Left AccessOperation Dot => 22,
|
|
||||||
]
|
]
|
||||||
}).postfix(dispatch! { surrounded(ws, parse_operator);
|
}).postfix(dispatch! { surrounded(ws, parse_operator);
|
||||||
TokenOperator::QuestionMark => Postfix(23, |input, rhs| {
|
TokenOperator::QuestionMark => Postfix(22, |input, rhs| {
|
||||||
match rhs {
|
match rhs {
|
||||||
TemplateAstExpr::VariableAccess(access) => Ok(TemplateAstExpr::ConditionalAccess(access)),
|
TemplateAstExpr::VariableAccess(access) => Ok(TemplateAstExpr::ConditionalAccess(access)),
|
||||||
_ => Err(AstError::from_input(input)),
|
_ => Err(AstError::from_input(input)),
|
||||||
|
|
@ -1077,15 +1071,4 @@ mod tests {
|
||||||
|
|
||||||
insta::assert_debug_snapshot!(ast);
|
insta::assert_debug_snapshot!(ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn check_access_operator() {
|
|
||||||
let input = "{{= foo?.bar }}";
|
|
||||||
|
|
||||||
let parsed = crate::lexer::parse(input.into()).unwrap();
|
|
||||||
|
|
||||||
let ast = panic_pretty(input, parse(parsed.tokens()));
|
|
||||||
|
|
||||||
insta::assert_debug_snapshot!(ast);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
---
|
|
||||||
source: src/parser/mod.rs
|
|
||||||
expression: ast
|
|
||||||
---
|
|
||||||
TemplateAst {
|
|
||||||
root: [
|
|
||||||
Interpolation {
|
|
||||||
prev_whitespace_content: None,
|
|
||||||
expression: AccessOperation {
|
|
||||||
op: Dot,
|
|
||||||
lhs: ConditionalAccess(
|
|
||||||
[Ident]"foo" (4..7),
|
|
||||||
),
|
|
||||||
rhs: VariableAccess(
|
|
||||||
[Ident]"bar" (9..12),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
post_whitespace_content: None,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
@ -9,7 +9,7 @@ TemplateAst {
|
||||||
expression: FunctionCall {
|
expression: FunctionCall {
|
||||||
name: [Ident]"foo" (4..7),
|
name: [Ident]"foo" (4..7),
|
||||||
args: [
|
args: [
|
||||||
MathOperation {
|
Operation {
|
||||||
op: Times,
|
op: Times,
|
||||||
lhs: Literal {
|
lhs: Literal {
|
||||||
source: [Literal(Integer(2))]"2" (8..9),
|
source: [Literal(Integer(2))]"2" (8..9),
|
||||||
|
|
@ -27,7 +27,7 @@ TemplateAst {
|
||||||
FunctionCall {
|
FunctionCall {
|
||||||
name: [Ident]"bar" (15..18),
|
name: [Ident]"bar" (15..18),
|
||||||
args: [
|
args: [
|
||||||
MathOperation {
|
Operation {
|
||||||
op: Plus,
|
op: Plus,
|
||||||
lhs: Literal {
|
lhs: Literal {
|
||||||
source: [Literal(Integer(2))]"2" (19..20),
|
source: [Literal(Integer(2))]"2" (19..20),
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ TemplateAst {
|
||||||
root: [
|
root: [
|
||||||
Interpolation {
|
Interpolation {
|
||||||
prev_whitespace_content: None,
|
prev_whitespace_content: None,
|
||||||
expression: MathOperation {
|
expression: Operation {
|
||||||
op: Or,
|
op: Or,
|
||||||
lhs: MathOperation {
|
lhs: Operation {
|
||||||
op: And,
|
op: And,
|
||||||
lhs: Literal {
|
lhs: Literal {
|
||||||
source: [Literal(Bool(true))]"true" (4..8),
|
source: [Literal(Bool(true))]"true" (4..8),
|
||||||
|
|
@ -23,9 +23,9 @@ TemplateAst {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rhs: MathOperation {
|
rhs: Operation {
|
||||||
op: And,
|
op: And,
|
||||||
lhs: MathOperation {
|
lhs: Operation {
|
||||||
op: GreaterOrEqual,
|
op: GreaterOrEqual,
|
||||||
lhs: Literal {
|
lhs: Literal {
|
||||||
source: [Literal(Integer(3))]"3" (21..22),
|
source: [Literal(Integer(3))]"3" (21..22),
|
||||||
|
|
@ -40,7 +40,7 @@ TemplateAst {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rhs: MathOperation {
|
rhs: Operation {
|
||||||
op: Equal,
|
op: Equal,
|
||||||
lhs: Literal {
|
lhs: Literal {
|
||||||
source: [Literal(Integer(5))]"5" (31..32),
|
source: [Literal(Integer(5))]"5" (31..32),
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ TemplateAst {
|
||||||
root: [
|
root: [
|
||||||
Interpolation {
|
Interpolation {
|
||||||
prev_whitespace_content: None,
|
prev_whitespace_content: None,
|
||||||
expression: MathOperation {
|
expression: Operation {
|
||||||
op: Plus,
|
op: Plus,
|
||||||
lhs: MathOperation {
|
lhs: Operation {
|
||||||
op: Times,
|
op: Times,
|
||||||
lhs: Literal {
|
lhs: Literal {
|
||||||
source: [Literal(Integer(5))]"5" (4..5),
|
source: [Literal(Integer(5))]"5" (4..5),
|
||||||
|
|
@ -23,7 +23,7 @@ TemplateAst {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rhs: MathOperation {
|
rhs: Operation {
|
||||||
op: Divide,
|
op: Divide,
|
||||||
lhs: Literal {
|
lhs: Literal {
|
||||||
source: [Literal(Integer(2))]"2" (12..13),
|
source: [Literal(Integer(2))]"2" (12..13),
|
||||||
|
|
|
||||||
11
src/value.rs
11
src/value.rs
|
|
@ -54,8 +54,6 @@ impl NomoValue {
|
||||||
pub fn as_bool(&self) -> Option<bool> {
|
pub fn as_bool(&self) -> Option<bool> {
|
||||||
if let Self::Bool { value } = self {
|
if let Self::Bool { value } = self {
|
||||||
Some(*value)
|
Some(*value)
|
||||||
} else if let Self::Undefined = self {
|
|
||||||
Some(false)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -440,14 +438,7 @@ impl TryFrom<serde_json::Value> for NomoValue {
|
||||||
.map(TryInto::try_into)
|
.map(TryInto::try_into)
|
||||||
.collect::<Result<_, _>>()?,
|
.collect::<Result<_, _>>()?,
|
||||||
}),
|
}),
|
||||||
serde_json::Value::Object(map) => {
|
serde_json::Value::Object(_map) => todo!(),
|
||||||
let value = map
|
|
||||||
.into_iter()
|
|
||||||
.map(|(key, value)| Ok((key, NomoValue::try_from(value)?)))
|
|
||||||
.collect::<Result<_, _>>()?;
|
|
||||||
|
|
||||||
Ok(NomoValue::Object { value })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
---
|
|
||||||
source: tests/file_tests.rs
|
|
||||||
expression: parsed
|
|
||||||
info:
|
|
||||||
input: "{{ if world?.active }}\nHello {{= world.name }}\n{{ end }}\n\n{{ if world?.foo?.bar?.active }}\n Weird!\n{{ else }}\n Deep access is working :)\n{{ end }}"
|
|
||||||
context:
|
|
||||||
world:
|
|
||||||
active: true
|
|
||||||
name: World!
|
|
||||||
---
|
|
||||||
ParsedTemplate {
|
|
||||||
tokens: [
|
|
||||||
[LeftDelim]"{{" (0..2),
|
|
||||||
[Whitespace]" " (2..3),
|
|
||||||
[ConditionalIf]"if" (3..5),
|
|
||||||
[Whitespace]" " (5..6),
|
|
||||||
[Ident]"world" (6..11),
|
|
||||||
[Operator(QuestionMark)]"?" (11..12),
|
|
||||||
[Operator(Dot)]"." (12..13),
|
|
||||||
[Ident]"active" (13..19),
|
|
||||||
[Whitespace]" " (19..20),
|
|
||||||
[RightDelim]"}}" (20..22),
|
|
||||||
[Whitespace]"\n" (22..23),
|
|
||||||
[Content]"Hello" (23..28),
|
|
||||||
[Whitespace]" " (28..29),
|
|
||||||
[LeftDelim]"{{" (29..31),
|
|
||||||
[WantsOutput]"=" (31..32),
|
|
||||||
[Whitespace]" " (32..33),
|
|
||||||
[Ident]"world" (33..38),
|
|
||||||
[Operator(Dot)]"." (38..39),
|
|
||||||
[Ident]"name" (39..43),
|
|
||||||
[Whitespace]" " (43..44),
|
|
||||||
[RightDelim]"}}" (44..46),
|
|
||||||
[Whitespace]"\n" (46..47),
|
|
||||||
[LeftDelim]"{{" (47..49),
|
|
||||||
[Whitespace]" " (49..50),
|
|
||||||
[End]"end" (50..53),
|
|
||||||
[Whitespace]" " (53..54),
|
|
||||||
[RightDelim]"}}" (54..56),
|
|
||||||
[Whitespace]"\n\n" (56..58),
|
|
||||||
[LeftDelim]"{{" (58..60),
|
|
||||||
[Whitespace]" " (60..61),
|
|
||||||
[ConditionalIf]"if" (61..63),
|
|
||||||
[Whitespace]" " (63..64),
|
|
||||||
[Ident]"world" (64..69),
|
|
||||||
[Operator(QuestionMark)]"?" (69..70),
|
|
||||||
[Operator(Dot)]"." (70..71),
|
|
||||||
[Ident]"foo" (71..74),
|
|
||||||
[Operator(QuestionMark)]"?" (74..75),
|
|
||||||
[Operator(Dot)]"." (75..76),
|
|
||||||
[Ident]"bar" (76..79),
|
|
||||||
[Operator(QuestionMark)]"?" (79..80),
|
|
||||||
[Operator(Dot)]"." (80..81),
|
|
||||||
[Ident]"active" (81..87),
|
|
||||||
[Whitespace]" " (87..88),
|
|
||||||
[RightDelim]"}}" (88..90),
|
|
||||||
[Whitespace]"\n " (90..95),
|
|
||||||
[Content]"Weird!" (95..101),
|
|
||||||
[Whitespace]"\n" (101..102),
|
|
||||||
[LeftDelim]"{{" (102..104),
|
|
||||||
[Whitespace]" " (104..105),
|
|
||||||
[ConditionalElse]"else" (105..109),
|
|
||||||
[Whitespace]" " (109..110),
|
|
||||||
[RightDelim]"}}" (110..112),
|
|
||||||
[Whitespace]"\n " (112..117),
|
|
||||||
[Content]"Deep access is working :)" (117..142),
|
|
||||||
[Whitespace]"\n" (142..143),
|
|
||||||
[LeftDelim]"{{" (143..145),
|
|
||||||
[Whitespace]" " (145..146),
|
|
||||||
[End]"end" (146..149),
|
|
||||||
[Whitespace]" " (149..150),
|
|
||||||
[RightDelim]"}}" (150..152),
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
@ -1,131 +0,0 @@
|
||||||
---
|
|
||||||
source: tests/file_tests.rs
|
|
||||||
expression: ast
|
|
||||||
info:
|
|
||||||
input: "{{ if world?.active }}\nHello {{= world.name }}\n{{ end }}\n\n{{ if world?.foo?.bar?.active }}\n Weird!\n{{ else }}\n Deep access is working :)\n{{ end }}"
|
|
||||||
context:
|
|
||||||
world:
|
|
||||||
active: true
|
|
||||||
name: World!
|
|
||||||
---
|
|
||||||
TemplateAst {
|
|
||||||
root: [
|
|
||||||
ConditionalChain {
|
|
||||||
chain: [
|
|
||||||
Block {
|
|
||||||
prev_whitespace_content: None,
|
|
||||||
expression: IfConditional {
|
|
||||||
expression: AccessOperation {
|
|
||||||
op: Dot,
|
|
||||||
lhs: ConditionalAccess(
|
|
||||||
[Ident]"world" (6..11),
|
|
||||||
),
|
|
||||||
rhs: VariableAccess(
|
|
||||||
[Ident]"active" (13..19),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
post_whitespace_content: Some(
|
|
||||||
[Whitespace]"\n" (22..23),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
ConditionalContent {
|
|
||||||
content: [
|
|
||||||
StaticContent(
|
|
||||||
[Content]"Hello" (23..28),
|
|
||||||
),
|
|
||||||
Interpolation {
|
|
||||||
prev_whitespace_content: Some(
|
|
||||||
[Whitespace]" " (28..29),
|
|
||||||
),
|
|
||||||
expression: AccessOperation {
|
|
||||||
op: Dot,
|
|
||||||
lhs: VariableAccess(
|
|
||||||
[Ident]"world" (33..38),
|
|
||||||
),
|
|
||||||
rhs: VariableAccess(
|
|
||||||
[Ident]"name" (39..43),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
post_whitespace_content: Some(
|
|
||||||
[Whitespace]"\n" (46..47),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Block {
|
|
||||||
prev_whitespace_content: None,
|
|
||||||
expression: EndBlock,
|
|
||||||
post_whitespace_content: Some(
|
|
||||||
[Whitespace]"\n\n" (56..58),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
ConditionalChain {
|
|
||||||
chain: [
|
|
||||||
Block {
|
|
||||||
prev_whitespace_content: None,
|
|
||||||
expression: IfConditional {
|
|
||||||
expression: AccessOperation {
|
|
||||||
op: Dot,
|
|
||||||
lhs: AccessOperation {
|
|
||||||
op: Dot,
|
|
||||||
lhs: AccessOperation {
|
|
||||||
op: Dot,
|
|
||||||
lhs: ConditionalAccess(
|
|
||||||
[Ident]"world" (64..69),
|
|
||||||
),
|
|
||||||
rhs: ConditionalAccess(
|
|
||||||
[Ident]"foo" (71..74),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
rhs: ConditionalAccess(
|
|
||||||
[Ident]"bar" (76..79),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
rhs: VariableAccess(
|
|
||||||
[Ident]"active" (81..87),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
post_whitespace_content: Some(
|
|
||||||
[Whitespace]"\n " (90..95),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
ConditionalContent {
|
|
||||||
content: [
|
|
||||||
StaticContent(
|
|
||||||
[Content]"Weird!" (95..101),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Block {
|
|
||||||
prev_whitespace_content: Some(
|
|
||||||
[Whitespace]"\n" (101..102),
|
|
||||||
),
|
|
||||||
expression: ElseConditional {
|
|
||||||
expression: None,
|
|
||||||
},
|
|
||||||
post_whitespace_content: Some(
|
|
||||||
[Whitespace]"\n " (112..117),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
ConditionalContent {
|
|
||||||
content: [
|
|
||||||
StaticContent(
|
|
||||||
[Content]"Deep access is working :)" (117..142),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Block {
|
|
||||||
prev_whitespace_content: Some(
|
|
||||||
[Whitespace]"\n" (142..143),
|
|
||||||
),
|
|
||||||
expression: EndBlock,
|
|
||||||
post_whitespace_content: None,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
@ -1,313 +0,0 @@
|
||||||
---
|
|
||||||
source: tests/file_tests.rs
|
|
||||||
expression: emit
|
|
||||||
info:
|
|
||||||
input: "{{ if world?.active }}\nHello {{= world.name }}\n{{ end }}\n\n{{ if world?.foo?.bar?.active }}\n Weird!\n{{ else }}\n Deep access is working :)\n{{ end }}"
|
|
||||||
context:
|
|
||||||
world:
|
|
||||||
active: true
|
|
||||||
name: World!
|
|
||||||
---
|
|
||||||
VMInstructions {
|
|
||||||
labels: {
|
|
||||||
LabelSlot {
|
|
||||||
index: 0,
|
|
||||||
}: 18,
|
|
||||||
LabelSlot {
|
|
||||||
index: 2,
|
|
||||||
}: 4,
|
|
||||||
LabelSlot {
|
|
||||||
index: 4,
|
|
||||||
}: 18,
|
|
||||||
LabelSlot {
|
|
||||||
index: 6,
|
|
||||||
}: 13,
|
|
||||||
LabelSlot {
|
|
||||||
index: 8,
|
|
||||||
}: 43,
|
|
||||||
LabelSlot {
|
|
||||||
index: 10,
|
|
||||||
}: 31,
|
|
||||||
LabelSlot {
|
|
||||||
index: 12,
|
|
||||||
}: 27,
|
|
||||||
LabelSlot {
|
|
||||||
index: 14,
|
|
||||||
}: 23,
|
|
||||||
LabelSlot {
|
|
||||||
index: 16,
|
|
||||||
}: 38,
|
|
||||||
},
|
|
||||||
instructions: [
|
|
||||||
LoadFromContextToSlot {
|
|
||||||
name: "world" (6..11),
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 3,
|
|
||||||
},
|
|
||||||
fail_on_not_found: false,
|
|
||||||
},
|
|
||||||
JumpIfUndefined {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 3,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
IndexSlotToSlot {
|
|
||||||
name: "active" (13..19),
|
|
||||||
from_slot: VariableSlot {
|
|
||||||
index: 3,
|
|
||||||
},
|
|
||||||
to_slot: VariableSlot {
|
|
||||||
index: 3,
|
|
||||||
},
|
|
||||||
fail_on_not_found: true,
|
|
||||||
},
|
|
||||||
JumpIfUndefined {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 3,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
LoadFromSlotToSlot {
|
|
||||||
from_slot: VariableSlot {
|
|
||||||
index: 3,
|
|
||||||
},
|
|
||||||
to_slot: VariableSlot {
|
|
||||||
index: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
JumpIfNotTrue {
|
|
||||||
emit_slot: VariableSlot {
|
|
||||||
index: 1,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 4,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "\n" (22..23),
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "Hello" (23..28),
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: " " (28..29),
|
|
||||||
},
|
|
||||||
LoadFromContextToSlot {
|
|
||||||
name: "world" (33..38),
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 7,
|
|
||||||
},
|
|
||||||
fail_on_not_found: true,
|
|
||||||
},
|
|
||||||
JumpIfUndefined {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 7,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 6,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
IndexSlotToSlot {
|
|
||||||
name: "name" (39..43),
|
|
||||||
from_slot: VariableSlot {
|
|
||||||
index: 7,
|
|
||||||
},
|
|
||||||
to_slot: VariableSlot {
|
|
||||||
index: 7,
|
|
||||||
},
|
|
||||||
fail_on_not_found: true,
|
|
||||||
},
|
|
||||||
JumpIfUndefined {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 7,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 6,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
LoadFromSlotToSlot {
|
|
||||||
from_slot: VariableSlot {
|
|
||||||
index: 7,
|
|
||||||
},
|
|
||||||
to_slot: VariableSlot {
|
|
||||||
index: 5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
EmitFromSlot {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "\n" (46..47),
|
|
||||||
},
|
|
||||||
Jump {
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "\n" (22..23),
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "\n\n" (56..58),
|
|
||||||
},
|
|
||||||
LoadFromContextToSlot {
|
|
||||||
name: "world" (64..69),
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 15,
|
|
||||||
},
|
|
||||||
fail_on_not_found: false,
|
|
||||||
},
|
|
||||||
JumpIfUndefined {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 15,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 14,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
IndexSlotToSlot {
|
|
||||||
name: "foo" (71..74),
|
|
||||||
from_slot: VariableSlot {
|
|
||||||
index: 15,
|
|
||||||
},
|
|
||||||
to_slot: VariableSlot {
|
|
||||||
index: 15,
|
|
||||||
},
|
|
||||||
fail_on_not_found: false,
|
|
||||||
},
|
|
||||||
JumpIfUndefined {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 15,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 14,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
LoadFromSlotToSlot {
|
|
||||||
from_slot: VariableSlot {
|
|
||||||
index: 15,
|
|
||||||
},
|
|
||||||
to_slot: VariableSlot {
|
|
||||||
index: 13,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
JumpIfUndefined {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 13,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 12,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
IndexSlotToSlot {
|
|
||||||
name: "bar" (76..79),
|
|
||||||
from_slot: VariableSlot {
|
|
||||||
index: 13,
|
|
||||||
},
|
|
||||||
to_slot: VariableSlot {
|
|
||||||
index: 13,
|
|
||||||
},
|
|
||||||
fail_on_not_found: false,
|
|
||||||
},
|
|
||||||
JumpIfUndefined {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 13,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 12,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
LoadFromSlotToSlot {
|
|
||||||
from_slot: VariableSlot {
|
|
||||||
index: 13,
|
|
||||||
},
|
|
||||||
to_slot: VariableSlot {
|
|
||||||
index: 11,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
JumpIfUndefined {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 11,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
IndexSlotToSlot {
|
|
||||||
name: "active" (81..87),
|
|
||||||
from_slot: VariableSlot {
|
|
||||||
index: 11,
|
|
||||||
},
|
|
||||||
to_slot: VariableSlot {
|
|
||||||
index: 11,
|
|
||||||
},
|
|
||||||
fail_on_not_found: true,
|
|
||||||
},
|
|
||||||
JumpIfUndefined {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 11,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
LoadFromSlotToSlot {
|
|
||||||
from_slot: VariableSlot {
|
|
||||||
index: 11,
|
|
||||||
},
|
|
||||||
to_slot: VariableSlot {
|
|
||||||
index: 9,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
JumpIfNotTrue {
|
|
||||||
emit_slot: VariableSlot {
|
|
||||||
index: 9,
|
|
||||||
},
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 16,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "\n " (90..95),
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "Weird!" (95..101),
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "\n" (101..102),
|
|
||||||
},
|
|
||||||
Jump {
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 8,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "\n " (90..95),
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "\n " (112..117),
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "Deep access is working :)" (117..142),
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "\n" (142..143),
|
|
||||||
},
|
|
||||||
Jump {
|
|
||||||
jump: LabelSlot {
|
|
||||||
index: 8,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "\n " (112..117),
|
|
||||||
},
|
|
||||||
NoOp,
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
---
|
|
||||||
source: tests/file_tests.rs
|
|
||||||
expression: output
|
|
||||||
info:
|
|
||||||
input: "{{ if world?.active }}\nHello {{= world.name }}\n{{ end }}\n\n{{ if world?.foo?.bar?.active }}\n Weird!\n{{ else }}\n Deep access is working :)\n{{ end }}"
|
|
||||||
context:
|
|
||||||
world:
|
|
||||||
active: true
|
|
||||||
name: World!
|
|
||||||
---
|
|
||||||
"\nHello World!\n\n\n\n Deep access is working :)\n"
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"world": {
|
|
||||||
"active": true,
|
|
||||||
"name": "World!"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
---
|
|
||||||
{{ if world?.active }}
|
|
||||||
Hello {{= world.name }}
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{ if world?.foo?.bar?.active }}
|
|
||||||
Weird!
|
|
||||||
{{ else }}
|
|
||||||
Deep access is working :)
|
|
||||||
{{ end }}
|
|
||||||
|
|
@ -9,7 +9,7 @@ TemplateAst {
|
||||||
root: [
|
root: [
|
||||||
Interpolation {
|
Interpolation {
|
||||||
prev_whitespace_content: None,
|
prev_whitespace_content: None,
|
||||||
expression: MathOperation {
|
expression: Operation {
|
||||||
op: Times,
|
op: Times,
|
||||||
lhs: Literal {
|
lhs: Literal {
|
||||||
source: [Literal(Integer(5))]"5" (4..5),
|
source: [Literal(Integer(5))]"5" (4..5),
|
||||||
|
|
@ -30,9 +30,9 @@ TemplateAst {
|
||||||
},
|
},
|
||||||
Interpolation {
|
Interpolation {
|
||||||
prev_whitespace_content: None,
|
prev_whitespace_content: None,
|
||||||
expression: MathOperation {
|
expression: Operation {
|
||||||
op: Plus,
|
op: Plus,
|
||||||
lhs: MathOperation {
|
lhs: Operation {
|
||||||
op: Times,
|
op: Times,
|
||||||
lhs: Literal {
|
lhs: Literal {
|
||||||
source: [Literal(Integer(2))]"2" (17..18),
|
source: [Literal(Integer(2))]"2" (17..18),
|
||||||
|
|
@ -47,7 +47,7 @@ TemplateAst {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rhs: MathOperation {
|
rhs: Operation {
|
||||||
op: Times,
|
op: Times,
|
||||||
lhs: Literal {
|
lhs: Literal {
|
||||||
source: [Literal(Integer(4))]"4" (25..26),
|
source: [Literal(Integer(4))]"4" (25..26),
|
||||||
|
|
@ -69,9 +69,9 @@ TemplateAst {
|
||||||
},
|
},
|
||||||
Interpolation {
|
Interpolation {
|
||||||
prev_whitespace_content: None,
|
prev_whitespace_content: None,
|
||||||
expression: MathOperation {
|
expression: Operation {
|
||||||
op: Plus,
|
op: Plus,
|
||||||
lhs: MathOperation {
|
lhs: Operation {
|
||||||
op: Divide,
|
op: Divide,
|
||||||
lhs: Literal {
|
lhs: Literal {
|
||||||
source: [Literal(Integer(3))]"3" (38..39),
|
source: [Literal(Integer(3))]"3" (38..39),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue