[WIP] Add conditions
This commit is contained in:
parent
7943b1607b
commit
0530522847
8 changed files with 338 additions and 180 deletions
33
Cargo.lock
generated
33
Cargo.lock
generated
|
@ -147,6 +147,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dependency-graph"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5143247629540606d0888beae9ca0e0b9a81a32151bfecd0b2be4a961155c24d"
|
||||
dependencies = [
|
||||
"petgraph",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
|
@ -168,6 +177,12 @@ version = "0.3.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.6"
|
||||
|
@ -229,9 +244,11 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"dependency-graph",
|
||||
"hence",
|
||||
"indexmap",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"parse_int",
|
||||
]
|
||||
|
||||
|
@ -263,6 +280,12 @@ dependencies = [
|
|||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.132"
|
||||
|
@ -329,6 +352,16 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
|
|
|
@ -22,3 +22,6 @@ anyhow = { version = "1.0.62", features = ["backtrace"] }
|
|||
itertools = "0.10.2"
|
||||
parse_int = "0.6.0"
|
||||
indexmap = "1.9.1"
|
||||
lazy_static = "1.4.0"
|
||||
dependency-graph = "0.1.5"
|
||||
|
||||
|
|
|
@ -1,2 +1,7 @@
|
|||
0 @ @ debug
|
||||
\ 1 1 = debug
|
||||
\ if 69 else 42 then debug
|
||||
|
||||
: test 42 ;
|
||||
test debug drop
|
||||
test test debug
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use anyhow::{bail, Result};
|
||||
use indexmap::IndexSet;
|
||||
use itertools::Itertools;
|
||||
use lazy_static::lazy_static;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::parser;
|
||||
|
@ -19,21 +20,45 @@ pub struct Word {
|
|||
pub times_used: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Condition {
|
||||
pub if_instructions: Vec<Instruction>,
|
||||
pub else_instructions: Vec<Instruction>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Data {
|
||||
pub words: HashMap<String, Word>,
|
||||
// pub word_graph:
|
||||
pub conditions: IndexSet<Instruction>,
|
||||
pub strings: IndexSet<String>,
|
||||
}
|
||||
|
||||
pub const TEMPLATE_ASM: &str = include_str!("compiler/template.asm");
|
||||
|
||||
lazy_static! {
|
||||
#[derive(Debug)]
|
||||
pub static ref TEMPLATE: hence::parser::ast::Body = hence::parser::parse(
|
||||
hence::lexer::lex(TEMPLATE_ASM.to_string()).unwrap()
|
||||
)
|
||||
.unwrap()
|
||||
.body;
|
||||
}
|
||||
|
||||
impl Data {
|
||||
pub fn default() -> Self {
|
||||
Self {
|
||||
words: HashMap::new(),
|
||||
conditions: IndexSet::new(),
|
||||
strings: IndexSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_instructions(&mut self, body: parser::ast::Body, optimize: bool) -> Result<Vec<Instruction>> {
|
||||
pub fn generate_instructions(
|
||||
&mut self,
|
||||
body: parser::ast::Body,
|
||||
optimize: bool,
|
||||
) -> Result<Vec<Instruction>> {
|
||||
let mut instructions: Vec<Instruction> = vec![];
|
||||
let mut iter = body.into_iter().peekable();
|
||||
while let Some(node) = iter.next() {
|
||||
|
@ -90,6 +115,12 @@ impl Data {
|
|||
},
|
||||
);
|
||||
}
|
||||
parser::ast::Node::Condition { if_body, else_body } => {
|
||||
instructions.push(Instruction::Condition {
|
||||
if_instructions: self.generate_instructions(if_body, optimize)?,
|
||||
else_instructions: self.generate_instructions(else_body, optimize)?,
|
||||
});
|
||||
}
|
||||
parser::ast::Node::Word(x) => {
|
||||
if let Some(ins) = Instruction::from_word(&x) {
|
||||
instructions.push(ins);
|
||||
|
@ -106,174 +137,10 @@ impl Data {
|
|||
Ok(instructions)
|
||||
}
|
||||
|
||||
pub fn embed(&self, body: hence::parser::ast::Body) -> hence::parser::ast::Body {
|
||||
let mut x = vec![
|
||||
// includes
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "include".to_string(),
|
||||
args: vec![hence::arg::Arg::String("$lib/core.asm".to_string())],
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "include".to_string(),
|
||||
args: vec![hence::arg::Arg::String("$lib/std.asm".to_string())],
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "include".to_string(),
|
||||
args: vec![hence::arg::Arg::String("$lib/main.asm".to_string())],
|
||||
},
|
||||
// constants
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "define".to_string(),
|
||||
args: vec![
|
||||
hence::arg::Arg::Variable("MEM_CALL_STACK".to_string()),
|
||||
hence::arg::Arg::Variable("CORE_MEM_MEM".to_string()),
|
||||
],
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "define".to_string(),
|
||||
args: vec![
|
||||
hence::arg::Arg::Variable("MEM_LOOP_I".to_string()),
|
||||
hence::arg::Arg::BinaryExpression {
|
||||
left: Box::new(hence::arg::Arg::Variable("CORE_MEM_MEM".to_string())),
|
||||
right: Box::new(hence::arg::Arg::Number(16)),
|
||||
op: hence::arg::BinaryExpressionOperator::Add,
|
||||
},
|
||||
],
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "define".to_string(),
|
||||
args: vec![
|
||||
hence::arg::Arg::Variable("MEM_LOOP_J".to_string()),
|
||||
hence::arg::Arg::BinaryExpression {
|
||||
left: Box::new(hence::arg::Arg::Variable("MEM_LOOP_I".to_string())),
|
||||
right: Box::new(hence::arg::Arg::Number(1)),
|
||||
op: hence::arg::BinaryExpressionOperator::Add,
|
||||
},
|
||||
],
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "define".to_string(),
|
||||
args: vec![
|
||||
hence::arg::Arg::Variable("MEM_ALLOC_PTR".to_string()),
|
||||
hence::arg::Arg::BinaryExpression {
|
||||
left: Box::new(hence::arg::Arg::Variable("MEM_LOOP_J".to_string())),
|
||||
right: Box::new(hence::arg::Arg::Number(1)),
|
||||
op: hence::arg::BinaryExpressionOperator::Add,
|
||||
},
|
||||
],
|
||||
},
|
||||
// macros
|
||||
// stack_transfer_alu
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "macro".to_string(),
|
||||
args: vec![hence::arg::Arg::Variable("stack_transfer_alu".to_string())],
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_ld".to_string(),
|
||||
args: vec![],
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_B".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_ld".to_string(),
|
||||
args: vec![],
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_A".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "endmacro".to_string(),
|
||||
args: vec![],
|
||||
},
|
||||
// call_word
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "macro".to_string(),
|
||||
args: vec![
|
||||
hence::arg::Arg::Variable("call_word".to_string()),
|
||||
hence::arg::Arg::Variable("call_word_arg_0_label".to_string()),
|
||||
],
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "ts".to_string(),
|
||||
arg: Some(hence::arg::Arg::BinaryExpression {
|
||||
left: Box::new(hence::arg::Arg::Variable("OFFSET".to_string())),
|
||||
right: Box::new(hence::arg::Arg::Number(3 + 3 + 3 + 1 + 3 + 1)),
|
||||
op: hence::arg::BinaryExpressionOperator::Add,
|
||||
}),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_A".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "ts".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("MEM_CALL_STACK".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "set".to_string(),
|
||||
arg: None,
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "ts".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable(
|
||||
"call_word_arg_0_label".to_string(),
|
||||
)),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
// tlr CORE_REG_PC -> tlr 0 -> tlr
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_PC".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "endmacro".to_string(),
|
||||
args: vec![],
|
||||
},
|
||||
// return_word
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "macro".to_string(),
|
||||
args: vec![hence::arg::Arg::Variable("return_word".to_string())],
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_get".to_string(),
|
||||
args: vec![hence::arg::Arg::Variable("MEM_CALL_STACK".to_string())],
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_PC".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "endmacro".to_string(),
|
||||
args: vec![],
|
||||
},
|
||||
// setup
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_rset".to_string(),
|
||||
args: vec![
|
||||
hence::arg::Arg::Variable("CORE_REG_A".to_string()),
|
||||
hence::arg::Arg::BinaryExpression {
|
||||
left: Box::new(hence::arg::Arg::Variable("MEM_ALLOC_PTR".to_string())),
|
||||
right: Box::new(hence::arg::Arg::Number(1)),
|
||||
op: hence::arg::BinaryExpressionOperator::Add,
|
||||
},
|
||||
],
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_set".to_string(),
|
||||
args: vec![hence::arg::Arg::Variable("MEM_ALLOC_PTR".to_string())],
|
||||
},
|
||||
// jump_main
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "jump_main".to_string(),
|
||||
args: vec![],
|
||||
},
|
||||
// data
|
||||
hence::parser::ast::Node::Label("data".to_string()),
|
||||
hence::parser::ast::Node::Label("data_strings".to_string()),
|
||||
];
|
||||
pub fn embed(&self, body: hence::parser::ast::Body) -> Result<hence::parser::ast::Body> {
|
||||
let mut x = TEMPLATE.to_vec();
|
||||
|
||||
// strings
|
||||
for (id, s) in self.strings.iter().enumerate() {
|
||||
x.extend([
|
||||
hence::parser::ast::Node::Label(format!("data_strings_{}", id)),
|
||||
|
@ -286,7 +153,6 @@ impl Data {
|
|||
}
|
||||
|
||||
// words
|
||||
x.push(hence::parser::ast::Node::Label("words".to_string()));
|
||||
for (name, word) in &self
|
||||
.words
|
||||
.iter()
|
||||
|
@ -308,7 +174,7 @@ impl Data {
|
|||
.flatten(),
|
||||
);
|
||||
x.push(hence::parser::ast::Node::MacroCall {
|
||||
name: "return_word".to_string(),
|
||||
name: "return_call_stack_jump".to_string(),
|
||||
args: vec![],
|
||||
});
|
||||
}
|
||||
|
@ -326,7 +192,7 @@ impl Data {
|
|||
args: vec![],
|
||||
});
|
||||
|
||||
x
|
||||
Ok(x)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,6 +210,6 @@ pub fn compile(ast: parser::ast::AST, optimize: bool) -> Result<hence::parser::a
|
|||
.into_iter()
|
||||
.flatten()
|
||||
.collect(),
|
||||
),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -66,6 +66,10 @@ pub enum Instruction {
|
|||
Mod,
|
||||
Call(String),
|
||||
AsmQuote(String),
|
||||
Condition {
|
||||
if_instructions: Vec<Self>,
|
||||
else_instructions: Vec<Self>,
|
||||
},
|
||||
|
||||
Multiple {
|
||||
instruction: Box<Self>,
|
||||
|
@ -926,8 +930,98 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
|
|||
arg: None,
|
||||
},
|
||||
]),
|
||||
Instruction::Min => Ok(vec![]),
|
||||
Instruction::Max => Ok(vec![]),
|
||||
Instruction::Min => Ok(vec![
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_ld".to_string(),
|
||||
args: vec![],
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_C".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_A".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_ld".to_string(),
|
||||
args: vec![],
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_B".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_alu".to_string(),
|
||||
args: vec![hence::arg::Arg::Variable("CORE_ALU_GT".to_string())],
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_A".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tsr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_B".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlrc".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_C".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tsr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_C".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tls".to_string(),
|
||||
arg: None,
|
||||
},
|
||||
]),
|
||||
Instruction::Max => Ok(vec![
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_ld".to_string(),
|
||||
args: vec![],
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_C".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_A".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_ld".to_string(),
|
||||
args: vec![],
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_B".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_alu".to_string(),
|
||||
args: vec![hence::arg::Arg::Variable("CORE_ALU_LT".to_string())],
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_A".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tsr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_B".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tlrc".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_C".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tsr".to_string(),
|
||||
arg: Some(hence::arg::Arg::Variable("CORE_REG_C".to_string())),
|
||||
},
|
||||
hence::parser::ast::Node::Call {
|
||||
name: "tls".to_string(),
|
||||
arg: None,
|
||||
},
|
||||
]),
|
||||
Instruction::Boolean => Ok(vec![
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "std_ld".to_string(),
|
||||
|
@ -1134,10 +1228,15 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
|
|||
Instruction::Call(x) => match data.words.get(x) {
|
||||
Some(w) => {
|
||||
if w.times_used > 1 {
|
||||
Ok(vec![hence::parser::ast::Node::MacroCall {
|
||||
name: "call_word".to_string(),
|
||||
args: vec![hence::arg::Arg::Variable(format!("words_{}", w.id))],
|
||||
}])
|
||||
Ok(vec![
|
||||
hence::parser::ast::Node::MacroCall {
|
||||
name: "call_stack_jump".to_string(),
|
||||
args: vec![
|
||||
hence::arg::Arg::Variable(format!("words_{}", w.id)),
|
||||
hence::arg::Arg::Variable("OFFSET".to_string())
|
||||
],
|
||||
}
|
||||
])
|
||||
} else {
|
||||
Ok(w.instructions
|
||||
.iter()
|
||||
|
@ -1153,6 +1252,23 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
|
|||
Instruction::AsmQuote(x) => {
|
||||
Ok(hence::parser::parse(hence::lexer::lex(x.to_string())?)?.body)
|
||||
}
|
||||
Instruction::Condition {
|
||||
if_instructions,
|
||||
else_instructions,
|
||||
} => {
|
||||
let if_compiled = if_instructions
|
||||
.iter()
|
||||
.map(|ins| ins.compile(data))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
let else_compiled = else_instructions
|
||||
.iter()
|
||||
.map(|ins| ins.compile(data))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
dbg!(if_compiled, else_compiled);
|
||||
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
Instruction::Multiple { instruction, count } => {
|
||||
if *count == 0 {
|
||||
Ok(vec![])
|
||||
|
@ -1418,4 +1534,3 @@ impl Instruction {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
64
henceforth/src/lib/compiler/template.asm
Normal file
64
henceforth/src/lib/compiler/template.asm
Normal file
|
@ -0,0 +1,64 @@
|
|||
.include "$lib/core.asm"
|
||||
.include "$lib/std.asm"
|
||||
.include "$lib/main.asm"
|
||||
|
||||
.define MEM_LOOP_I, CORE_MEM_MEM
|
||||
.define MEM_LOOP_J, (MEM_LOOP_I + 1)
|
||||
.define MEM_CALL_STACK_PTR, (MEM_LOOP_J + 1)
|
||||
.define MEM_ALLOC_PTR, (MEM_CALL_STACK_PTR + 16)
|
||||
|
||||
.macro stack_transfer_alu
|
||||
.std_ld
|
||||
tlr CORE_REG_B
|
||||
.std_ld
|
||||
tlr CORE_REG_A
|
||||
.endmacro
|
||||
|
||||
.macro call_stack_jump, prep_call_stack_jump_arg_0_label, prep_call_stack_jump_arg_1_offset
|
||||
.std_rset CORE_REG_C, prep_call_stack_jump_arg_0_label
|
||||
.std_rset CORE_REG_D, (prep_call_stack_jump_arg_1_offset + 7)
|
||||
ts call_stack_jump
|
||||
tlr CORE_REG_PC
|
||||
.endmacro
|
||||
|
||||
.macro return_call_stack_jump
|
||||
.std_jump return_call_stack_jump
|
||||
.endmacro
|
||||
|
||||
.std_rset CORE_REG_A, MEM_CALL_STACK_PTR
|
||||
.std_set MEM_CALL_STACK_PTR
|
||||
|
||||
.std_rset CORE_REG_A, (MEM_ALLOC_PTR + 1)
|
||||
.std_set MEM_ALLOC_PTR
|
||||
|
||||
.jump_main
|
||||
|
||||
call_stack_jump:
|
||||
.std_get MEM_CALL_STACK_PTR
|
||||
tlr CORE_REG_A
|
||||
.std_rset CORE_REG_B, 1
|
||||
.std_alu CORE_ALU_ADD
|
||||
tlr CORE_REG_A
|
||||
tlr CORE_REG_B
|
||||
.std_set MEM_CALL_STACK_PTR
|
||||
|
||||
tsr CORE_REG_D
|
||||
tlr CORE_REG_A
|
||||
tsr CORE_REG_B
|
||||
set
|
||||
tsr CORE_REG_C
|
||||
tlr CORE_REG_PC
|
||||
|
||||
return_call_stack_jump:
|
||||
.std_get MEM_CALL_STACK_PTR
|
||||
tlr CORE_REG_A
|
||||
tlr CORE_REG_C
|
||||
.std_rset CORE_REG_B, 1
|
||||
.std_alu CORE_ALU_SUB
|
||||
tlr CORE_REG_A
|
||||
.std_set MEM_CALL_STACK_PTR
|
||||
|
||||
tsr CORE_REG_C
|
||||
get
|
||||
tlr CORE_REG_PC
|
||||
|
|
@ -100,6 +100,63 @@ pub fn parse(tokens: Vec<lexer::Token>) -> Result<ast::AST> {
|
|||
body: parse(content.collect())?.body,
|
||||
});
|
||||
}
|
||||
"if" => {
|
||||
let mut depth: usize = 1;
|
||||
let mut else_used = false;
|
||||
let if_toks: Vec<_> = iter
|
||||
.by_ref()
|
||||
.take_while(|t| match t {
|
||||
lexer::Token::Word(x) => match x.as_str() {
|
||||
"if" => {
|
||||
depth += 1;
|
||||
true
|
||||
}
|
||||
"else" => {
|
||||
if depth == 1 {
|
||||
else_used = true;
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
"then" => {
|
||||
depth -= 1;
|
||||
depth != 0
|
||||
}
|
||||
_ => true,
|
||||
},
|
||||
_ => true,
|
||||
})
|
||||
.collect();
|
||||
let else_toks: Vec<_> = if else_used {
|
||||
iter.by_ref()
|
||||
.take_while(|t| match t {
|
||||
lexer::Token::Word(x) => match x.as_str() {
|
||||
"if" => {
|
||||
depth += 1;
|
||||
true
|
||||
}
|
||||
"then" => {
|
||||
depth -= 1;
|
||||
depth != 0
|
||||
}
|
||||
_ => true,
|
||||
},
|
||||
_ => true,
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
if depth != 0 {
|
||||
bail!("Unbalanced conditions");
|
||||
}
|
||||
|
||||
body.push(ast::Node::Condition {
|
||||
if_body: parse(if_toks)?.body,
|
||||
else_body: parse(else_toks)?.body,
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
body.push(ast::Node::Word(x));
|
||||
}
|
||||
|
|
|
@ -38,6 +38,10 @@ pub enum Node {
|
|||
stack: Option<StackResult>,
|
||||
body: Body,
|
||||
},
|
||||
Condition {
|
||||
if_body: Body,
|
||||
else_body: Body,
|
||||
},
|
||||
Word(String),
|
||||
}
|
||||
|
||||
|
@ -56,6 +60,17 @@ impl ToCode for Node {
|
|||
},
|
||||
body.iter().map(|x| x.to_code()).join(" ")
|
||||
),
|
||||
Node::Condition { if_body, else_body } => {
|
||||
if else_body.is_empty() {
|
||||
format!("if {} then", if_body.iter().map(|x| x.to_code()).join(" "))
|
||||
} else {
|
||||
format!(
|
||||
"if {} else {} then",
|
||||
if_body.iter().map(|x| x.to_code()).join(" "),
|
||||
else_body.iter().map(|x| x.to_code()).join(" ")
|
||||
)
|
||||
}
|
||||
}
|
||||
Node::Word(x) => x.clone(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue