Introduce JumpLabels instead of manually correct jump positions
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
e64256b65f
commit
7182024342
12 changed files with 485 additions and 381 deletions
|
|
@ -1,8 +1,11 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::ast::TemplateAstExpr;
|
use crate::ast::TemplateAstExpr;
|
||||||
use crate::input::NomoInput;
|
use crate::input::NomoInput;
|
||||||
|
|
||||||
pub struct EmitMachine {
|
pub struct EmitMachine {
|
||||||
current_index: usize,
|
current_index: usize,
|
||||||
|
labels: HashMap<LabelSlot, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmitMachine {
|
impl EmitMachine {
|
||||||
|
|
@ -15,6 +18,22 @@ impl EmitMachine {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reserve_label(&mut self) -> LabelSlot {
|
||||||
|
LabelSlot {
|
||||||
|
index: {
|
||||||
|
let val = self.current_index;
|
||||||
|
self.current_index += 1;
|
||||||
|
val
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assign_label(&mut self, slot: LabelSlot, idx: usize) {
|
||||||
|
let no_prev = self.labels.insert(slot, idx).is_none();
|
||||||
|
|
||||||
|
assert!(no_prev, "A label slot was already assigned")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
|
@ -22,7 +41,12 @@ pub struct VariableSlot {
|
||||||
index: usize,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub struct LabelSlot {
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: NomoInput,
|
content: NomoInput,
|
||||||
|
|
@ -40,24 +64,36 @@ pub enum Instruction {
|
||||||
Abort,
|
Abort,
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot,
|
emit_slot: VariableSlot,
|
||||||
jump: isize,
|
jump: LabelSlot,
|
||||||
},
|
},
|
||||||
Jump {
|
Jump {
|
||||||
jump: isize,
|
jump: LabelSlot,
|
||||||
},
|
},
|
||||||
NoOp,
|
NoOp,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_machine(input: crate::ast::TemplateAst<'_>) -> Vec<Instruction> {
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct VMInstructions {
|
||||||
|
pub labels: HashMap<LabelSlot, usize>,
|
||||||
|
pub instructions: Vec<Instruction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn emit_machine(input: crate::ast::TemplateAst<'_>) -> VMInstructions {
|
||||||
let mut eval = vec![];
|
let mut eval = vec![];
|
||||||
|
|
||||||
let mut machine = EmitMachine { current_index: 0 };
|
let mut machine = EmitMachine {
|
||||||
|
current_index: 0,
|
||||||
|
labels: HashMap::new(),
|
||||||
|
};
|
||||||
|
|
||||||
for ast in input.root() {
|
for ast in input.root() {
|
||||||
emit_ast_expr(&mut machine, &mut eval, ast);
|
emit_ast_expr(&mut machine, &mut eval, ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
eval
|
VMInstructions {
|
||||||
|
labels: machine.labels,
|
||||||
|
instructions: eval,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_ast_expr(
|
fn emit_ast_expr(
|
||||||
|
|
@ -95,10 +131,11 @@ fn emit_ast_expr(
|
||||||
TemplateAstExpr::ConditionalChain { chain } => {
|
TemplateAstExpr::ConditionalChain { chain } => {
|
||||||
let mut chain = chain.iter();
|
let mut chain = chain.iter();
|
||||||
|
|
||||||
|
let end_label = machine.reserve_label();
|
||||||
let mut end_indices = vec![];
|
let mut end_indices = vec![];
|
||||||
|
|
||||||
let mut previous_post_whitespace_content: &Option<crate::parser::TemplateToken> = &None;
|
let mut previous_post_whitespace_content: &Option<crate::parser::TemplateToken> = &None;
|
||||||
let mut previous_jump: Option<usize> = None;
|
let mut previous_jump: Option<LabelSlot> = None;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let next = chain.next().unwrap();
|
let next = chain.next().unwrap();
|
||||||
|
|
@ -114,7 +151,7 @@ fn emit_ast_expr(
|
||||||
}
|
}
|
||||||
|
|
||||||
end_indices.push(eval.len());
|
end_indices.push(eval.len());
|
||||||
eval.push(Instruction::Jump { jump: isize::MAX });
|
eval.push(Instruction::Jump { jump: end_label });
|
||||||
} else if let TemplateAstExpr::Block {
|
} else if let TemplateAstExpr::Block {
|
||||||
prev_whitespace_content,
|
prev_whitespace_content,
|
||||||
post_whitespace_content,
|
post_whitespace_content,
|
||||||
|
|
@ -139,20 +176,15 @@ fn emit_ast_expr(
|
||||||
let emit_slot = machine.reserve_slot();
|
let emit_slot = machine.reserve_slot();
|
||||||
emit_expr_load(machine, eval, emit_slot, expression);
|
emit_expr_load(machine, eval, emit_slot, expression);
|
||||||
|
|
||||||
previous_jump = Some(eval.len());
|
let jmp_label = machine.reserve_label();
|
||||||
|
previous_jump = Some(jmp_label);
|
||||||
eval.push(Instruction::JumpIfNotTrue {
|
eval.push(Instruction::JumpIfNotTrue {
|
||||||
emit_slot,
|
emit_slot,
|
||||||
jump: isize::MAX,
|
jump: jmp_label,
|
||||||
});
|
});
|
||||||
} else if let TemplateAstExpr::ElseConditional { expression } = &**expression {
|
} else if let TemplateAstExpr::ElseConditional { expression } = &**expression {
|
||||||
if let Some(previous_jump) = previous_jump.take() {
|
if let Some(previous_jump) = previous_jump.take() {
|
||||||
let new_jump = eval.len() - previous_jump - 1;
|
machine.assign_label(previous_jump, eval.len());
|
||||||
let Instruction::JumpIfNotTrue { jump, .. } = &mut eval[previous_jump]
|
|
||||||
else {
|
|
||||||
panic!("Jump slot had something that is not a jump?!");
|
|
||||||
};
|
|
||||||
|
|
||||||
*jump = new_jump as isize;
|
|
||||||
} else {
|
} else {
|
||||||
panic!("Got an else without a previous if?");
|
panic!("Got an else without a previous if?");
|
||||||
}
|
}
|
||||||
|
|
@ -161,10 +193,11 @@ fn emit_ast_expr(
|
||||||
let emit_slot = machine.reserve_slot();
|
let emit_slot = machine.reserve_slot();
|
||||||
emit_expr_load(machine, eval, emit_slot, expression);
|
emit_expr_load(machine, eval, emit_slot, expression);
|
||||||
|
|
||||||
previous_jump = Some(eval.len());
|
let jmp_label = machine.reserve_label();
|
||||||
|
previous_jump = Some(jmp_label);
|
||||||
eval.push(Instruction::JumpIfNotTrue {
|
eval.push(Instruction::JumpIfNotTrue {
|
||||||
emit_slot,
|
emit_slot,
|
||||||
jump: isize::MAX,
|
jump: jmp_label,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// We don't have to do anything in the else case
|
// We don't have to do anything in the else case
|
||||||
|
|
@ -176,13 +209,9 @@ fn emit_ast_expr(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(previous_jump) = previous_jump.take() {
|
if let Some(previous_jump) = previous_jump.take() {
|
||||||
let new_jump = eval.len() - previous_jump - 1;
|
machine.assign_label(previous_jump, eval.len());
|
||||||
let Instruction::JumpIfNotTrue { jump, .. } = &mut eval[previous_jump] else {
|
|
||||||
panic!("Jump slot had something that is not a jump?!");
|
|
||||||
};
|
|
||||||
|
|
||||||
*jump = new_jump as isize;
|
|
||||||
}
|
}
|
||||||
|
machine.assign_label(end_label, eval.len());
|
||||||
|
|
||||||
if let Some(ws) = previous_post_whitespace_content {
|
if let Some(ws) = previous_post_whitespace_content {
|
||||||
eval.push(Instruction::AppendContent {
|
eval.push(Instruction::AppendContent {
|
||||||
|
|
@ -191,13 +220,6 @@ fn emit_ast_expr(
|
||||||
} else {
|
} else {
|
||||||
eval.push(Instruction::NoOp);
|
eval.push(Instruction::NoOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
for index in end_indices {
|
|
||||||
let jump = eval.len() - index - 1;
|
|
||||||
eval[index] = Instruction::Jump {
|
|
||||||
jump: jump as isize,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateAstExpr::Block { .. }
|
TemplateAstExpr::Block { .. }
|
||||||
|
|
@ -258,7 +280,9 @@ mod tests {
|
||||||
let emit = emit_machine(ast);
|
let emit = emit_machine(ast);
|
||||||
|
|
||||||
insta::assert_debug_snapshot!(emit, @r#"
|
insta::assert_debug_snapshot!(emit, @r#"
|
||||||
[
|
VMInstructions {
|
||||||
|
labels: {},
|
||||||
|
instructions: [
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: "Hello" (0..5),
|
content: "Hello" (0..5),
|
||||||
},
|
},
|
||||||
|
|
@ -276,7 +300,8 @@ mod tests {
|
||||||
index: 0,
|
index: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
|
}
|
||||||
"#);
|
"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,32 @@
|
||||||
source: src/emit/mod.rs
|
source: src/emit/mod.rs
|
||||||
expression: emit
|
expression: emit
|
||||||
---
|
---
|
||||||
[
|
VMInstructions {
|
||||||
|
labels: {
|
||||||
|
LabelSlot {
|
||||||
|
index: 4,
|
||||||
|
}: 14,
|
||||||
|
LabelSlot {
|
||||||
|
index: 0,
|
||||||
|
}: 19,
|
||||||
|
LabelSlot {
|
||||||
|
index: 2,
|
||||||
|
}: 7,
|
||||||
|
},
|
||||||
|
instructions: [
|
||||||
LoadFromContextToSlot {
|
LoadFromContextToSlot {
|
||||||
name: "foo" (6..9),
|
name: "foo" (6..9),
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 0,
|
index: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
index: 0,
|
index: 1,
|
||||||
|
},
|
||||||
|
jump: LabelSlot {
|
||||||
|
index: 2,
|
||||||
},
|
},
|
||||||
jump: 5,
|
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: " " (12..13),
|
content: " " (12..13),
|
||||||
|
|
@ -25,7 +39,9 @@ expression: emit
|
||||||
content: " " (16..17),
|
content: " " (16..17),
|
||||||
},
|
},
|
||||||
Jump {
|
Jump {
|
||||||
jump: 14,
|
jump: LabelSlot {
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: " " (12..13),
|
content: " " (12..13),
|
||||||
|
|
@ -33,14 +49,16 @@ expression: emit
|
||||||
LoadFromContextToSlot {
|
LoadFromContextToSlot {
|
||||||
name: "bar" (28..31),
|
name: "bar" (28..31),
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
index: 1,
|
index: 3,
|
||||||
|
},
|
||||||
|
jump: LabelSlot {
|
||||||
|
index: 4,
|
||||||
},
|
},
|
||||||
jump: 5,
|
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: " " (34..35),
|
content: " " (34..35),
|
||||||
|
|
@ -52,7 +70,9 @@ expression: emit
|
||||||
content: " " (38..39),
|
content: " " (38..39),
|
||||||
},
|
},
|
||||||
Jump {
|
Jump {
|
||||||
jump: 7,
|
jump: LabelSlot {
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: " " (34..35),
|
content: " " (34..35),
|
||||||
|
|
@ -67,10 +87,13 @@ expression: emit
|
||||||
content: " " (56..57),
|
content: " " (56..57),
|
||||||
},
|
},
|
||||||
Jump {
|
Jump {
|
||||||
jump: 2,
|
jump: LabelSlot {
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: " " (49..50),
|
content: " " (49..50),
|
||||||
},
|
},
|
||||||
NoOp,
|
NoOp,
|
||||||
]
|
],
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use thiserror::Error;
|
||||||
|
|
||||||
use crate::Context;
|
use crate::Context;
|
||||||
use crate::emit::Instruction;
|
use crate::emit::Instruction;
|
||||||
|
use crate::emit::VMInstructions;
|
||||||
use crate::input::NomoInput;
|
use crate::input::NomoInput;
|
||||||
|
|
||||||
#[derive(Debug, Error, Display)]
|
#[derive(Debug, Error, Display)]
|
||||||
|
|
@ -17,24 +18,21 @@ pub enum EvaluationError {
|
||||||
**
|
**
|
||||||
** This is an internal error and is a bug that should be reported
|
** This is an internal error and is a bug that should be reported
|
||||||
*/
|
*/
|
||||||
InstructionPointerOverflow,
|
LabelNotFound,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(
|
pub fn execute(vm: &VMInstructions, global_context: &Context) -> Result<String, EvaluationError> {
|
||||||
instructions: &[Instruction],
|
|
||||||
global_context: &Context,
|
|
||||||
) -> Result<String, EvaluationError> {
|
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
|
||||||
let mut scopes: HashMap<crate::emit::VariableSlot, serde_json::Value> = HashMap::new();
|
let mut scopes: HashMap<crate::emit::VariableSlot, serde_json::Value> = HashMap::new();
|
||||||
|
|
||||||
let mut ip = 0;
|
let mut ip = 0;
|
||||||
loop {
|
loop {
|
||||||
if ip >= instructions.len() {
|
if ip >= vm.instructions.len() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let instr = instructions.get(ip).unwrap();
|
let instr = vm.instructions.get(ip).unwrap();
|
||||||
|
|
||||||
match instr {
|
match instr {
|
||||||
Instruction::NoOp => (),
|
Instruction::NoOp => (),
|
||||||
|
|
@ -58,27 +56,23 @@ pub fn execute(
|
||||||
if dont_jump {
|
if dont_jump {
|
||||||
// We are done
|
// We are done
|
||||||
} else {
|
} else {
|
||||||
let (new_ip, overflow) = ip.overflowing_add_signed(*jump);
|
let Some(new_ip) = vm.labels.get(jump) else {
|
||||||
|
return Err(EvaluationError::LabelNotFound);
|
||||||
|
};
|
||||||
|
|
||||||
if overflow {
|
ip = *new_ip;
|
||||||
return Err(EvaluationError::InstructionPointerOverflow);
|
|
||||||
} else {
|
|
||||||
ip = new_ip;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Instruction::Jump { jump } => {
|
Instruction::Jump { jump } => {
|
||||||
let (new_ip, overflow) = ip.overflowing_add_signed(*jump);
|
let Some(new_ip) = vm.labels.get(jump) else {
|
||||||
|
return Err(EvaluationError::LabelNotFound);
|
||||||
|
};
|
||||||
|
|
||||||
if overflow {
|
ip = *new_ip;
|
||||||
return Err(EvaluationError::InstructionPointerOverflow);
|
|
||||||
} else {
|
|
||||||
ip = new_ip;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ip += 1;
|
ip += 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use serde::Serialize;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::emit::Instruction;
|
use crate::emit::Instruction;
|
||||||
|
use crate::emit::VMInstructions;
|
||||||
use crate::input::NomoInput;
|
use crate::input::NomoInput;
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
|
|
@ -84,7 +85,7 @@ impl Nomo {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Template {
|
struct Template {
|
||||||
instructions: Vec<Instruction>,
|
instructions: VMInstructions,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,29 @@ source: tests/file_tests.rs
|
||||||
expression: emit
|
expression: emit
|
||||||
input_file: tests/cases/condition.nomo
|
input_file: tests/cases/condition.nomo
|
||||||
---
|
---
|
||||||
[
|
VMInstructions {
|
||||||
|
labels: {
|
||||||
|
LabelSlot {
|
||||||
|
index: 2,
|
||||||
|
}: 7,
|
||||||
|
LabelSlot {
|
||||||
|
index: 0,
|
||||||
|
}: 7,
|
||||||
|
},
|
||||||
|
instructions: [
|
||||||
LoadFromContextToSlot {
|
LoadFromContextToSlot {
|
||||||
name: "test" (6..10),
|
name: "test" (6..10),
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 0,
|
index: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
index: 0,
|
index: 1,
|
||||||
|
},
|
||||||
|
jump: LabelSlot {
|
||||||
|
index: 2,
|
||||||
},
|
},
|
||||||
jump: 5,
|
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: "\n " (13..18),
|
content: "\n " (13..18),
|
||||||
|
|
@ -26,7 +37,9 @@ input_file: tests/cases/condition.nomo
|
||||||
content: "\n" (30..31),
|
content: "\n" (30..31),
|
||||||
},
|
},
|
||||||
Jump {
|
Jump {
|
||||||
jump: 2,
|
jump: LabelSlot {
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: "\n " (13..18),
|
content: "\n " (13..18),
|
||||||
|
|
@ -37,12 +50,13 @@ input_file: tests/cases/condition.nomo
|
||||||
LoadFromContextToSlot {
|
LoadFromContextToSlot {
|
||||||
name: "stuff" (46..51),
|
name: "stuff" (46..51),
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@ source: tests/file_tests.rs
|
||||||
expression: emit
|
expression: emit
|
||||||
input_file: tests/cases/identifiers.nomo
|
input_file: tests/cases/identifiers.nomo
|
||||||
---
|
---
|
||||||
[
|
VMInstructions {
|
||||||
|
labels: {},
|
||||||
|
instructions: [
|
||||||
LoadFromContextToSlot {
|
LoadFromContextToSlot {
|
||||||
name: "_name" (4..9),
|
name: "_name" (4..9),
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
|
|
@ -85,4 +87,5 @@ input_file: tests/cases/identifiers.nomo
|
||||||
index: 5,
|
index: 5,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,32 @@ source: tests/file_tests.rs
|
||||||
expression: emit
|
expression: emit
|
||||||
input_file: tests/cases/if_else_if.nomo
|
input_file: tests/cases/if_else_if.nomo
|
||||||
---
|
---
|
||||||
[
|
VMInstructions {
|
||||||
|
labels: {
|
||||||
|
LabelSlot {
|
||||||
|
index: 2,
|
||||||
|
}: 7,
|
||||||
|
LabelSlot {
|
||||||
|
index: 4,
|
||||||
|
}: 14,
|
||||||
|
LabelSlot {
|
||||||
|
index: 0,
|
||||||
|
}: 14,
|
||||||
|
},
|
||||||
|
instructions: [
|
||||||
LoadFromContextToSlot {
|
LoadFromContextToSlot {
|
||||||
name: "test" (6..10),
|
name: "test" (6..10),
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 0,
|
index: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
index: 0,
|
index: 1,
|
||||||
|
},
|
||||||
|
jump: LabelSlot {
|
||||||
|
index: 2,
|
||||||
},
|
},
|
||||||
jump: 5,
|
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: "\n " (13..18),
|
content: "\n " (13..18),
|
||||||
|
|
@ -26,7 +40,9 @@ input_file: tests/cases/if_else_if.nomo
|
||||||
content: "\n" (37..38),
|
content: "\n" (37..38),
|
||||||
},
|
},
|
||||||
Jump {
|
Jump {
|
||||||
jump: 9,
|
jump: LabelSlot {
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: "\n " (13..18),
|
content: "\n " (13..18),
|
||||||
|
|
@ -34,14 +50,16 @@ input_file: tests/cases/if_else_if.nomo
|
||||||
LoadFromContextToSlot {
|
LoadFromContextToSlot {
|
||||||
name: "another_test" (49..61),
|
name: "another_test" (49..61),
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
index: 1,
|
index: 3,
|
||||||
|
},
|
||||||
|
jump: LabelSlot {
|
||||||
|
index: 4,
|
||||||
},
|
},
|
||||||
jump: 5,
|
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: "\n " (64..69),
|
content: "\n " (64..69),
|
||||||
|
|
@ -53,10 +71,13 @@ input_file: tests/cases/if_else_if.nomo
|
||||||
content: "\n" (81..82),
|
content: "\n" (81..82),
|
||||||
},
|
},
|
||||||
Jump {
|
Jump {
|
||||||
jump: 2,
|
jump: LabelSlot {
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: "\n " (64..69),
|
content: "\n " (64..69),
|
||||||
},
|
},
|
||||||
NoOp,
|
NoOp,
|
||||||
]
|
],
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@ source: tests/file_tests.rs
|
||||||
expression: emit
|
expression: emit
|
||||||
input_file: tests/cases/interpolation.nomo
|
input_file: tests/cases/interpolation.nomo
|
||||||
---
|
---
|
||||||
[
|
VMInstructions {
|
||||||
|
labels: {},
|
||||||
|
instructions: [
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: "Hello! I'm" (0..10),
|
content: "Hello! I'm" (0..10),
|
||||||
},
|
},
|
||||||
|
|
@ -21,4 +23,5 @@ input_file: tests/cases/interpolation.nomo
|
||||||
index: 0,
|
index: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@ source: tests/file_tests.rs
|
||||||
expression: emit
|
expression: emit
|
||||||
input_file: tests/cases/multiple.nomo
|
input_file: tests/cases/multiple.nomo
|
||||||
---
|
---
|
||||||
[
|
VMInstructions {
|
||||||
|
labels: {},
|
||||||
|
instructions: [
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: "Hi there! My name is" (0..20),
|
content: "Hi there! My name is" (0..20),
|
||||||
},
|
},
|
||||||
|
|
@ -35,4 +37,5 @@ input_file: tests/cases/multiple.nomo
|
||||||
index: 1,
|
index: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,11 @@ source: tests/file_tests.rs
|
||||||
expression: emit
|
expression: emit
|
||||||
input_file: tests/cases/simple.nomo
|
input_file: tests/cases/simple.nomo
|
||||||
---
|
---
|
||||||
[
|
VMInstructions {
|
||||||
|
labels: {},
|
||||||
|
instructions: [
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: "Hello World!" (0..12),
|
content: "Hello World!" (0..12),
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,29 @@ source: tests/file_tests.rs
|
||||||
expression: emit
|
expression: emit
|
||||||
input_file: tests/cases/trim_whitespace.nomo
|
input_file: tests/cases/trim_whitespace.nomo
|
||||||
---
|
---
|
||||||
[
|
VMInstructions {
|
||||||
|
labels: {
|
||||||
|
LabelSlot {
|
||||||
|
index: 2,
|
||||||
|
}: 7,
|
||||||
|
LabelSlot {
|
||||||
|
index: 0,
|
||||||
|
}: 7,
|
||||||
|
},
|
||||||
|
instructions: [
|
||||||
LoadFromContextToSlot {
|
LoadFromContextToSlot {
|
||||||
name: "test" (6..10),
|
name: "test" (6..10),
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 0,
|
index: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
JumpIfNotTrue {
|
JumpIfNotTrue {
|
||||||
emit_slot: VariableSlot {
|
emit_slot: VariableSlot {
|
||||||
index: 0,
|
index: 1,
|
||||||
|
},
|
||||||
|
jump: LabelSlot {
|
||||||
|
index: 2,
|
||||||
},
|
},
|
||||||
jump: 5,
|
|
||||||
},
|
},
|
||||||
AppendContent {
|
AppendContent {
|
||||||
content: "Hello" (19..24),
|
content: "Hello" (19..24),
|
||||||
|
|
@ -25,16 +36,19 @@ input_file: tests/cases/trim_whitespace.nomo
|
||||||
LoadFromContextToSlot {
|
LoadFromContextToSlot {
|
||||||
name: "stuff" (29..34),
|
name: "stuff" (29..34),
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
EmitFromSlot {
|
EmitFromSlot {
|
||||||
slot: VariableSlot {
|
slot: VariableSlot {
|
||||||
index: 1,
|
index: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Jump {
|
Jump {
|
||||||
jump: 1,
|
jump: LabelSlot {
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
NoOp,
|
NoOp,
|
||||||
]
|
],
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@ source: tests/file_tests.rs
|
||||||
expression: output
|
expression: output
|
||||||
input_file: tests/cases/if_else_if.nomo
|
input_file: tests/cases/if_else_if.nomo
|
||||||
---
|
---
|
||||||
"\n \n Hello World!\n"
|
"\n Hello World!\n"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue