Compare commits

..

No commits in common. "8c02dbd672e7624df982ac092fd489e6e20b68f7" and "474324726a740e1576a0b7b1930448d1d14564af" have entirely different histories.

8 changed files with 53 additions and 318 deletions

View file

@ -1,12 +1,9 @@
use thiserror::Error; use thiserror::Error;
use winnow::Parser; use winnow::Parser;
use winnow::RecoverableParser; use winnow::RecoverableParser;
use winnow::combinator::Infix::Left;
use winnow::combinator::alt; use winnow::combinator::alt;
use winnow::combinator::cut_err; use winnow::combinator::cut_err;
use winnow::combinator::delimited; use winnow::combinator::delimited;
use winnow::combinator::dispatch;
use winnow::combinator::expression;
use winnow::combinator::not; use winnow::combinator::not;
use winnow::combinator::opt; use winnow::combinator::opt;
use winnow::combinator::peek; use winnow::combinator::peek;
@ -27,9 +24,7 @@ use winnow::token::any;
use crate::SourceSpan; use crate::SourceSpan;
use crate::parser::TemplateToken; use crate::parser::TemplateToken;
use crate::parser::TokenKind; use crate::parser::TokenKind;
use crate::parser::TokenOperator;
use crate::resume_after_cut; use crate::resume_after_cut;
use crate::value::NomoValue;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct TemplateAst<'input> { pub struct TemplateAst<'input> {
@ -258,16 +253,7 @@ pub enum TemplateAstExpr<'input> {
expression: Option<Box<TemplateAstExpr<'input>>>, expression: Option<Box<TemplateAstExpr<'input>>>,
}, },
Invalid(&'input [TemplateToken]), Invalid(&'input [TemplateToken]),
Operation {
op: TokenOperator,
lhs: Box<TemplateAstExpr<'input>>,
rhs: Box<TemplateAstExpr<'input>>,
},
EndBlock, EndBlock,
Literal {
source: TemplateToken,
value: NomoValue,
},
} }
fn parse_asts<'input>(input: &mut Input<'input>) -> Result<Vec<TemplateAstExpr<'input>>, AstError> { fn parse_asts<'input>(input: &mut Input<'input>) -> Result<Vec<TemplateAstExpr<'input>>, AstError> {
@ -289,7 +275,7 @@ fn parse_interpolation<'input>(
input: &mut Input<'input>, input: &mut Input<'input>,
) -> Result<TemplateAstExpr<'input>, AstError> { ) -> Result<TemplateAstExpr<'input>, AstError> {
let expr_parser = resume_after_cut( let expr_parser = resume_after_cut(
parse_expression, parse_value_expression,
repeat_till( repeat_till(
0.., 0..,
any, any,
@ -411,7 +397,7 @@ fn parse_for_loop<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'
ws, ws,
TokenKind::In, TokenKind::In,
ws, ws,
parse_expression.map(Box::new), parse_value_expression.map(Box::new),
) )
.map(|(_, _for, _, value_ident, _, _in, _, value_expression)| { .map(|(_, _for, _, value_ident, _, _in, _, value_expression)| {
TemplateAstExpr::For { TemplateAstExpr::For {
@ -503,7 +489,7 @@ fn parse_conditional_if<'input>(
preceded( preceded(
TokenKind::ConditionalIf, TokenKind::ConditionalIf,
cut_err( cut_err(
surrounded(ws, parse_expression) surrounded(ws, parse_value_expression)
.map(Box::new) .map(Box::new)
.context(AstError::ctx().msg("Expected an expression after 'if'")), .context(AstError::ctx().msg("Expected an expression after 'if'")),
), ),
@ -524,7 +510,7 @@ fn parse_conditional_else<'input>(
surrounded(ws, TokenKind::ConditionalElse), surrounded(ws, TokenKind::ConditionalElse),
opt(preceded( opt(preceded(
TokenKind::ConditionalIf, TokenKind::ConditionalIf,
cut_err(surrounded(ws, parse_expression)).map(Box::new), cut_err(surrounded(ws, parse_value_expression)).map(Box::new),
)), )),
) )
.map(|else_expr| TemplateAstExpr::ElseConditional { .map(|else_expr| TemplateAstExpr::ElseConditional {
@ -559,6 +545,12 @@ fn parse_end<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'input
.parse_next(input) .parse_next(input)
} }
fn parse_value_expression<'input>(
input: &mut Input<'input>,
) -> Result<TemplateAstExpr<'input>, AstError> {
trace("value_expression", alt((parse_variable_access,))).parse_next(input)
}
fn parse_variable_access<'input>( fn parse_variable_access<'input>(
input: &mut Input<'input>, input: &mut Input<'input>,
) -> Result<TemplateAstExpr<'input>, AstError> { ) -> Result<TemplateAstExpr<'input>, AstError> {
@ -619,55 +611,6 @@ where
) )
} }
fn parse_operand<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'input>, AstError> {
trace("operand", alt((parse_variable_access, parse_literal))).parse_next(input)
}
fn parse_literal<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'input>, AstError> {
trace(
"literal",
any.verify_map(|token: &TemplateToken| match token.kind() {
TokenKind::Literal(literal) => Some(TemplateAstExpr::Literal {
source: token.clone(),
value: match literal {
crate::parser::TokenLiteral::Bool(bool) => NomoValue::Bool { value: bool },
crate::parser::TokenLiteral::Integer(int) => NomoValue::Integer { value: int },
},
}),
_ => None,
}),
)
.parse_next(input)
}
fn parse_operator<'input>(input: &mut Input<'input>) -> Result<TokenOperator, AstError> {
trace(
"operator",
any.verify_map(|t: &'input TemplateToken| match t.kind() {
TokenKind::Operator(op) => Some(op),
_ => None,
}),
)
.parse_next(input)
}
fn parse_expression<'input>(
input: &mut Input<'input>,
) -> Result<TemplateAstExpr<'input>, AstError> {
trace(
"expression",
expression(surrounded(ws, parse_operand)).infix(dispatch! { surrounded(ws, parse_operator);
TokenOperator::Plus => Left(5, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::Plus, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
TokenOperator::Minus => Left(5, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::Minus, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
TokenOperator::Times => Left(7, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::Times, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
TokenOperator::Divide => Left(7, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::Divide, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
TokenOperator::And => Left(7, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::And, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
TokenOperator::Or => Left(5, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::Or, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
}),
)
.parse_next(input)
}
fn ws<'input>(input: &mut Input<'input>) -> Result<(), AstError> { fn ws<'input>(input: &mut Input<'input>) -> Result<(), AstError> {
repeat(.., TokenKind::Whitespace).parse_next(input) repeat(.., TokenKind::Whitespace).parse_next(input)
} }
@ -969,15 +912,4 @@ mod tests {
insta::assert_debug_snapshot!(ast); insta::assert_debug_snapshot!(ast);
} }
#[test]
fn check_math_expression() {
let input = "{{= 5 * 3 + 2 / 3 }}";
let parsed = crate::parser::parse(input.into()).unwrap();
let ast = panic_pretty(input, parse(parsed.tokens()));
insta::assert_debug_snapshot!(ast);
}
} }

View file

@ -1,45 +0,0 @@
---
source: src/ast/mod.rs
expression: ast
---
TemplateAst {
root: [
Interpolation {
prev_whitespace_content: None,
expression: Operation {
op: Plus,
lhs: Operation {
op: Times,
lhs: Literal {
source: [Literal(Integer(5))]"5" (4..5),
value: Integer {
value: 5,
},
},
rhs: Literal {
source: [Literal(Integer(3))]"3" (8..9),
value: Integer {
value: 3,
},
},
},
rhs: Operation {
op: Divide,
lhs: Literal {
source: [Literal(Integer(2))]"2" (12..13),
value: Integer {
value: 2,
},
},
rhs: Literal {
source: [Literal(Integer(3))]"3" (16..17),
value: Integer {
value: 3,
},
},
},
},
post_whitespace_content: None,
},
],
}

View file

@ -402,8 +402,6 @@ fn emit_ast_expr(
| TemplateAstExpr::For { .. } | TemplateAstExpr::For { .. }
| TemplateAstExpr::ForElse | TemplateAstExpr::ForElse
| TemplateAstExpr::Invalid { .. } | TemplateAstExpr::Invalid { .. }
| TemplateAstExpr::Literal { .. }
| TemplateAstExpr::Operation { .. }
| TemplateAstExpr::VariableAccess { .. } => eval.push(Instruction::Abort), | TemplateAstExpr::VariableAccess { .. } => eval.push(Instruction::Abort),
} }
} }
@ -432,8 +430,6 @@ fn emit_expr_load(
TemplateAstExpr::ForChain { .. } => todo!(), TemplateAstExpr::ForChain { .. } => todo!(),
TemplateAstExpr::For { .. } => todo!(), TemplateAstExpr::For { .. } => todo!(),
TemplateAstExpr::ForElse => todo!(), TemplateAstExpr::ForElse => todo!(),
TemplateAstExpr::Operation { .. } => todo!(),
TemplateAstExpr::Literal { .. } => todo!(),
TemplateAstExpr::IfConditional { .. } => todo!(), TemplateAstExpr::IfConditional { .. } => todo!(),
TemplateAstExpr::ConditionalContent { .. } => todo!(), TemplateAstExpr::ConditionalContent { .. } => todo!(),

View file

@ -8,16 +8,11 @@ use thiserror::Error;
use winnow::LocatingSlice; use winnow::LocatingSlice;
use winnow::Parser; use winnow::Parser;
use winnow::RecoverableParser; use winnow::RecoverableParser;
use winnow::ascii::alpha1;
use winnow::ascii::digit1;
use winnow::ascii::multispace0; use winnow::ascii::multispace0;
use winnow::ascii::multispace1; use winnow::ascii::multispace1;
use winnow::combinator::alt; use winnow::combinator::alt;
use winnow::combinator::cut_err; use winnow::combinator::cut_err;
use winnow::combinator::dispatch;
use winnow::combinator::empty;
use winnow::combinator::eof; use winnow::combinator::eof;
use winnow::combinator::fail;
use winnow::combinator::not; use winnow::combinator::not;
use winnow::combinator::opt; use winnow::combinator::opt;
use winnow::combinator::peek; use winnow::combinator::peek;
@ -33,7 +28,6 @@ use winnow::stream::Location;
use winnow::stream::Recoverable; use winnow::stream::Recoverable;
use winnow::stream::Stream; use winnow::stream::Stream;
use winnow::token::any; use winnow::token::any;
use winnow::token::literal;
use winnow::token::one_of; use winnow::token::one_of;
use winnow::token::rest; use winnow::token::rest;
use winnow::token::take_until; use winnow::token::take_until;
@ -219,23 +213,11 @@ pub enum TokenKind {
In, In,
End, End,
Literal(TokenLiteral), Literal(TokenLiteral),
Operator(TokenOperator),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum TokenOperator {
Plus,
Minus,
Times,
Divide,
And,
Or,
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum TokenLiteral { pub enum TokenLiteral {
Bool(bool), Bool(bool),
Integer(u64),
} }
impl PartialEq<TokenKind> for TemplateToken { impl PartialEq<TokenKind> for TemplateToken {
@ -327,13 +309,6 @@ impl TemplateToken {
} }
} }
pub fn operator(operator: TokenOperator, source: NomoInput) -> Self {
TemplateToken {
kind: TokenKind::Operator(operator),
source,
}
}
pub fn kind(&self) -> TokenKind { pub fn kind(&self) -> TokenKind {
self.kind self.kind
} }
@ -410,7 +385,7 @@ fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<T
fn parse_block_token<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> { fn parse_block_token<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
trace( trace(
"parse_block_token", "parse_block_token",
alt((parse_ident, parse_keyword, parse_whitespace, parse_operator)), alt((parse_ident, parse_keyword, parse_whitespace)),
) )
.parse_next(input) .parse_next(input)
} }
@ -418,20 +393,13 @@ fn parse_block_token<'input>(input: &mut Input<'input>) -> PResult<'input, Templ
fn parse_literal<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> { fn parse_literal<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
trace( trace(
"parse_literal", "parse_literal",
alt((parse_boolean, parse_number)) alt((parse_boolean,))
.with_taken() .with_taken()
.map(|(lit, span)| TemplateToken::literal(lit, span)), .map(|(lit, span)| TemplateToken::literal(lit, span)),
) )
.parse_next(input) .parse_next(input)
} }
fn parse_number<'input>(input: &mut Input<'input>) -> PResult<'input, TokenLiteral> {
digit1
.verify_map(|digits: NomoInput| digits.parse::<u64>().ok())
.map(TokenLiteral::Integer)
.parse_next(input)
}
fn parse_boolean<'input>(input: &mut Input<'input>) -> PResult<'input, TokenLiteral> { fn parse_boolean<'input>(input: &mut Input<'input>) -> PResult<'input, TokenLiteral> {
alt(( alt((
"true".value(TokenLiteral::Bool(true)), "true".value(TokenLiteral::Bool(true)),
@ -506,44 +474,12 @@ fn parse_ident<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateTok
.parse_next(input) .parse_next(input)
} }
fn parse_operator<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
let (operator, source) = trace(
"operator",
dispatch! {any;
'+' => empty.value(TokenOperator::Plus),
'-' => empty.value(TokenOperator::Minus),
'*' => empty.value(TokenOperator::Times),
'/' => empty.value(TokenOperator::Divide),
'&' => alt((
"&".value(TokenOperator::And),
cut_err(fail),
)),
'|' => alt((
"|".value(TokenOperator::Or),
cut_err(fail),
)),
_ => fail,
},
)
.with_taken()
.parse_next(input)?;
Ok(TemplateToken::operator(operator, source))
}
fn ident<'input>(input: &mut Input<'input>) -> PResult<'input, NomoInput> { fn ident<'input>(input: &mut Input<'input>) -> PResult<'input, NomoInput> {
peek(not(parse_keyword)) peek(not(parse_keyword))
.context(ParseError::ctx().msg("Expected an ident, but found a literal instead")) .context(ParseError::ctx().msg("Expected an ident, but found a literal instead"))
.parse_next(input)?; .parse_next(input)?;
let literal_start = alt((alpha1, "_")); take_while(1.., |c: char| c.is_alphanumeric() || "_".contains(c)).parse_next(input)
(
literal_start,
take_while(0.., |c: char| c.is_alphanumeric() || "_".contains(c)),
)
.take()
.parse_next(input)
} }
fn bad_ident<'input>(input: &mut Input<'input>) -> PResult<'input, ()> { fn bad_ident<'input>(input: &mut Input<'input>) -> PResult<'input, ()> {
@ -744,61 +680,4 @@ mod tests {
) )
"#); "#);
} }
#[test]
fn parse_operations() {
let input = "{{= 5 * 14 + 3 / 2 - 1 }}{{ if foo && bar || baz }}{{ end }}";
let output = parse(input.into());
insta::assert_debug_snapshot!(output, @r#"
Ok(
ParsedTemplate {
tokens: [
[LeftDelim]"{{" (0..2),
[WantsOutput]"=" (2..3),
[Whitespace]" " (3..4),
[Literal(Integer(5))]"5" (4..5),
[Whitespace]" " (5..6),
[Operator(Times)]"*" (6..7),
[Whitespace]" " (7..8),
[Literal(Integer(14))]"14" (8..10),
[Whitespace]" " (10..11),
[Operator(Plus)]"+" (11..12),
[Whitespace]" " (12..13),
[Literal(Integer(3))]"3" (13..14),
[Whitespace]" " (14..15),
[Operator(Divide)]"/" (15..16),
[Whitespace]" " (16..17),
[Literal(Integer(2))]"2" (17..18),
[Whitespace]" " (18..19),
[Operator(Minus)]"-" (19..20),
[Whitespace]" " (20..21),
[Literal(Integer(1))]"1" (21..22),
[Whitespace]" " (22..23),
[RightDelim]"}}" (23..25),
[LeftDelim]"{{" (25..27),
[Whitespace]" " (27..28),
[ConditionalIf]"if" (28..30),
[Whitespace]" " (30..31),
[Ident]"foo" (31..34),
[Whitespace]" " (34..35),
[Operator(And)]"&&" (35..37),
[Whitespace]" " (37..38),
[Ident]"bar" (38..41),
[Whitespace]" " (41..42),
[Operator(Or)]"||" (42..44),
[Whitespace]" " (44..45),
[Ident]"baz" (45..48),
[Whitespace]" " (48..49),
[RightDelim]"}}" (49..51),
[LeftDelim]"{{" (51..53),
[Whitespace]" " (53..54),
[End]"end" (54..57),
[Whitespace]" " (57..58),
[RightDelim]"}}" (58..60),
],
},
)
"#);
}
} }

View file

@ -1,15 +1,6 @@
--- ---
source: tests/file_tests.rs source: tests/file_tests.rs
expression: parsed expression: parsed
info:
input: "{{= _name }}\n{{= a_name }}\n{{= name }}\n{{= _name1 }}\n{{= _namE }}\n{{= name1 }}"
context:
_namE: Foo
name1: Foo
name: Foo
_name: Foo
a_name: Foo
_name1: Foo
input_file: tests/cases/identifiers.nomo input_file: tests/cases/identifiers.nomo
--- ---
ParsedTemplate { ParsedTemplate {
@ -31,29 +22,29 @@ ParsedTemplate {
[LeftDelim]"{{" (27..29), [LeftDelim]"{{" (27..29),
[WantsOutput]"=" (29..30), [WantsOutput]"=" (29..30),
[Whitespace]" " (30..31), [Whitespace]" " (30..31),
[Ident]"name" (31..35), [Ident]"1name" (31..36),
[Whitespace]" " (35..36), [Whitespace]" " (36..37),
[RightDelim]"}}" (36..38), [RightDelim]"}}" (37..39),
[Whitespace]"\n" (38..39), [Whitespace]"\n" (39..40),
[LeftDelim]"{{" (39..41), [LeftDelim]"{{" (40..42),
[WantsOutput]"=" (41..42), [WantsOutput]"=" (42..43),
[Whitespace]" " (42..43), [Whitespace]" " (43..44),
[Ident]"_name1" (43..49), [Ident]"_name1" (44..50),
[Whitespace]" " (49..50), [Whitespace]" " (50..51),
[RightDelim]"}}" (50..52), [RightDelim]"}}" (51..53),
[Whitespace]"\n" (52..53), [Whitespace]"\n" (53..54),
[LeftDelim]"{{" (53..55), [LeftDelim]"{{" (54..56),
[WantsOutput]"=" (55..56), [WantsOutput]"=" (56..57),
[Whitespace]" " (56..57), [Whitespace]" " (57..58),
[Ident]"_namE" (57..62), [Ident]"_namE" (58..63),
[Whitespace]" " (62..63), [Whitespace]" " (63..64),
[RightDelim]"}}" (63..65), [RightDelim]"}}" (64..66),
[Whitespace]"\n" (65..66), [Whitespace]"\n" (66..67),
[LeftDelim]"{{" (66..68), [LeftDelim]"{{" (67..69),
[WantsOutput]"=" (68..69), [WantsOutput]"=" (69..70),
[Whitespace]" " (69..70), [Whitespace]" " (70..71),
[Ident]"name1" (70..75), [Ident]"name1" (71..76),
[Whitespace]" " (75..76), [Whitespace]" " (76..77),
[RightDelim]"}}" (76..78), [RightDelim]"}}" (77..79),
], ],
} }

View file

@ -1,15 +1,6 @@
--- ---
source: tests/file_tests.rs source: tests/file_tests.rs
expression: ast expression: ast
info:
input: "{{= _name }}\n{{= a_name }}\n{{= name }}\n{{= _name1 }}\n{{= _namE }}\n{{= name1 }}"
context:
_namE: Foo
name1: Foo
name: Foo
_name: Foo
a_name: Foo
_name1: Foo
input_file: tests/cases/identifiers.nomo input_file: tests/cases/identifiers.nomo
--- ---
TemplateAst { TemplateAst {
@ -35,34 +26,34 @@ TemplateAst {
Interpolation { Interpolation {
prev_whitespace_content: None, prev_whitespace_content: None,
expression: VariableAccess( expression: VariableAccess(
[Ident]"name" (31..35), [Ident]"1name" (31..36),
), ),
post_whitespace_content: Some( post_whitespace_content: Some(
[Whitespace]"\n" (38..39), [Whitespace]"\n" (39..40),
), ),
}, },
Interpolation { Interpolation {
prev_whitespace_content: None, prev_whitespace_content: None,
expression: VariableAccess( expression: VariableAccess(
[Ident]"_name1" (43..49), [Ident]"_name1" (44..50),
), ),
post_whitespace_content: Some( post_whitespace_content: Some(
[Whitespace]"\n" (52..53), [Whitespace]"\n" (53..54),
), ),
}, },
Interpolation { Interpolation {
prev_whitespace_content: None, prev_whitespace_content: None,
expression: VariableAccess( expression: VariableAccess(
[Ident]"_namE" (57..62), [Ident]"_namE" (58..63),
), ),
post_whitespace_content: Some( post_whitespace_content: Some(
[Whitespace]"\n" (65..66), [Whitespace]"\n" (66..67),
), ),
}, },
Interpolation { Interpolation {
prev_whitespace_content: None, prev_whitespace_content: None,
expression: VariableAccess( expression: VariableAccess(
[Ident]"name1" (70..75), [Ident]"name1" (71..76),
), ),
post_whitespace_content: None, post_whitespace_content: None,
}, },

View file

@ -1,15 +1,6 @@
--- ---
source: tests/file_tests.rs source: tests/file_tests.rs
expression: emit expression: emit
info:
input: "{{= _name }}\n{{= a_name }}\n{{= name }}\n{{= _name1 }}\n{{= _namE }}\n{{= name1 }}"
context:
_namE: Foo
name1: Foo
name: Foo
_name: Foo
a_name: Foo
_name1: Foo
input_file: tests/cases/identifiers.nomo input_file: tests/cases/identifiers.nomo
--- ---
VMInstructions { VMInstructions {
@ -44,7 +35,7 @@ VMInstructions {
content: "\n" (26..27), content: "\n" (26..27),
}, },
LoadFromContextToSlot { LoadFromContextToSlot {
name: "name" (31..35), name: "1name" (31..36),
slot: VariableSlot { slot: VariableSlot {
index: 2, index: 2,
}, },
@ -55,10 +46,10 @@ VMInstructions {
}, },
}, },
AppendContent { AppendContent {
content: "\n" (38..39), content: "\n" (39..40),
}, },
LoadFromContextToSlot { LoadFromContextToSlot {
name: "_name1" (43..49), name: "_name1" (44..50),
slot: VariableSlot { slot: VariableSlot {
index: 3, index: 3,
}, },
@ -69,10 +60,10 @@ VMInstructions {
}, },
}, },
AppendContent { AppendContent {
content: "\n" (52..53), content: "\n" (53..54),
}, },
LoadFromContextToSlot { LoadFromContextToSlot {
name: "_namE" (57..62), name: "_namE" (58..63),
slot: VariableSlot { slot: VariableSlot {
index: 4, index: 4,
}, },
@ -83,10 +74,10 @@ VMInstructions {
}, },
}, },
AppendContent { AppendContent {
content: "\n" (65..66), content: "\n" (66..67),
}, },
LoadFromContextToSlot { LoadFromContextToSlot {
name: "name1" (70..75), name: "name1" (71..76),
slot: VariableSlot { slot: VariableSlot {
index: 5, index: 5,
}, },

View file

@ -1,7 +1,7 @@
{ {
"_name": "Foo", "_name": "Foo",
"a_name": "Foo", "a_name": "Foo",
"name": "Foo", "1name": "Foo",
"_name1": "Foo", "_name1": "Foo",
"_namE": "Foo", "_namE": "Foo",
"name1": "Foo" "name1": "Foo"
@ -9,7 +9,7 @@
--- ---
{{= _name }} {{= _name }}
{{= a_name }} {{= a_name }}
{{= name }} {{= 1name }}
{{= _name1 }} {{= _name1 }}
{{= _namE }} {{= _namE }}
{{= name1 }} {{= name1 }}