[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",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dependency-graph"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5143247629540606d0888beae9ca0e0b9a81a32151bfecd0b2be4a961155c24d"
|
||||||
|
dependencies = [
|
||||||
|
"petgraph",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -168,6 +177,12 @@ version = "0.3.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixedbitset"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.6"
|
version = "0.14.6"
|
||||||
|
@ -229,9 +244,11 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
|
"dependency-graph",
|
||||||
"hence",
|
"hence",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"itertools",
|
"itertools",
|
||||||
|
"lazy_static",
|
||||||
"parse_int",
|
"parse_int",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -263,6 +280,12 @@ dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.132"
|
version = "0.2.132"
|
||||||
|
@ -329,6 +352,16 @@ dependencies = [
|
||||||
"num-traits",
|
"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]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
|
|
|
@ -22,3 +22,6 @@ anyhow = { version = "1.0.62", features = ["backtrace"] }
|
||||||
itertools = "0.10.2"
|
itertools = "0.10.2"
|
||||||
parse_int = "0.6.0"
|
parse_int = "0.6.0"
|
||||||
indexmap = "1.9.1"
|
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 anyhow::{bail, Result};
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::parser;
|
use crate::parser;
|
||||||
|
@ -19,21 +20,45 @@ pub struct Word {
|
||||||
pub times_used: usize,
|
pub times_used: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Condition {
|
||||||
|
pub if_instructions: Vec<Instruction>,
|
||||||
|
pub else_instructions: Vec<Instruction>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
pub words: HashMap<String, Word>,
|
pub words: HashMap<String, Word>,
|
||||||
|
// pub word_graph:
|
||||||
|
pub conditions: IndexSet<Instruction>,
|
||||||
pub strings: IndexSet<String>,
|
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 {
|
impl Data {
|
||||||
pub fn default() -> Self {
|
pub fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
words: HashMap::new(),
|
words: HashMap::new(),
|
||||||
|
conditions: IndexSet::new(),
|
||||||
strings: 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 instructions: Vec<Instruction> = vec![];
|
||||||
let mut iter = body.into_iter().peekable();
|
let mut iter = body.into_iter().peekable();
|
||||||
while let Some(node) = iter.next() {
|
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) => {
|
parser::ast::Node::Word(x) => {
|
||||||
if let Some(ins) = Instruction::from_word(&x) {
|
if let Some(ins) = Instruction::from_word(&x) {
|
||||||
instructions.push(ins);
|
instructions.push(ins);
|
||||||
|
@ -106,174 +137,10 @@ impl Data {
|
||||||
Ok(instructions)
|
Ok(instructions)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn embed(&self, body: hence::parser::ast::Body) -> hence::parser::ast::Body {
|
pub fn embed(&self, body: hence::parser::ast::Body) -> Result<hence::parser::ast::Body> {
|
||||||
let mut x = vec![
|
let mut x = TEMPLATE.to_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()),
|
|
||||||
];
|
|
||||||
|
|
||||||
|
// strings
|
||||||
for (id, s) in self.strings.iter().enumerate() {
|
for (id, s) in self.strings.iter().enumerate() {
|
||||||
x.extend([
|
x.extend([
|
||||||
hence::parser::ast::Node::Label(format!("data_strings_{}", id)),
|
hence::parser::ast::Node::Label(format!("data_strings_{}", id)),
|
||||||
|
@ -286,7 +153,6 @@ impl Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
// words
|
// words
|
||||||
x.push(hence::parser::ast::Node::Label("words".to_string()));
|
|
||||||
for (name, word) in &self
|
for (name, word) in &self
|
||||||
.words
|
.words
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -308,7 +174,7 @@ impl Data {
|
||||||
.flatten(),
|
.flatten(),
|
||||||
);
|
);
|
||||||
x.push(hence::parser::ast::Node::MacroCall {
|
x.push(hence::parser::ast::Node::MacroCall {
|
||||||
name: "return_word".to_string(),
|
name: "return_call_stack_jump".to_string(),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -326,7 +192,7 @@ impl Data {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
});
|
});
|
||||||
|
|
||||||
x
|
Ok(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,6 +210,6 @@ pub fn compile(ast: parser::ast::AST, optimize: bool) -> Result<hence::parser::a
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,10 @@ pub enum Instruction {
|
||||||
Mod,
|
Mod,
|
||||||
Call(String),
|
Call(String),
|
||||||
AsmQuote(String),
|
AsmQuote(String),
|
||||||
|
Condition {
|
||||||
|
if_instructions: Vec<Self>,
|
||||||
|
else_instructions: Vec<Self>,
|
||||||
|
},
|
||||||
|
|
||||||
Multiple {
|
Multiple {
|
||||||
instruction: Box<Self>,
|
instruction: Box<Self>,
|
||||||
|
@ -926,8 +930,98 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
|
||||||
arg: None,
|
arg: None,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
Instruction::Min => Ok(vec![]),
|
Instruction::Min => Ok(vec![
|
||||||
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_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![
|
Instruction::Boolean => Ok(vec![
|
||||||
hence::parser::ast::Node::MacroCall {
|
hence::parser::ast::Node::MacroCall {
|
||||||
name: "std_ld".to_string(),
|
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) {
|
Instruction::Call(x) => match data.words.get(x) {
|
||||||
Some(w) => {
|
Some(w) => {
|
||||||
if w.times_used > 1 {
|
if w.times_used > 1 {
|
||||||
Ok(vec![hence::parser::ast::Node::MacroCall {
|
Ok(vec![
|
||||||
name: "call_word".to_string(),
|
hence::parser::ast::Node::MacroCall {
|
||||||
args: vec![hence::arg::Arg::Variable(format!("words_{}", w.id))],
|
name: "call_stack_jump".to_string(),
|
||||||
}])
|
args: vec![
|
||||||
|
hence::arg::Arg::Variable(format!("words_{}", w.id)),
|
||||||
|
hence::arg::Arg::Variable("OFFSET".to_string())
|
||||||
|
],
|
||||||
|
}
|
||||||
|
])
|
||||||
} else {
|
} else {
|
||||||
Ok(w.instructions
|
Ok(w.instructions
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1153,6 +1252,23 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
|
||||||
Instruction::AsmQuote(x) => {
|
Instruction::AsmQuote(x) => {
|
||||||
Ok(hence::parser::parse(hence::lexer::lex(x.to_string())?)?.body)
|
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 } => {
|
Instruction::Multiple { instruction, count } => {
|
||||||
if *count == 0 {
|
if *count == 0 {
|
||||||
Ok(vec![])
|
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,
|
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));
|
body.push(ast::Node::Word(x));
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,10 @@ pub enum Node {
|
||||||
stack: Option<StackResult>,
|
stack: Option<StackResult>,
|
||||||
body: Body,
|
body: Body,
|
||||||
},
|
},
|
||||||
|
Condition {
|
||||||
|
if_body: Body,
|
||||||
|
else_body: Body,
|
||||||
|
},
|
||||||
Word(String),
|
Word(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +60,17 @@ impl ToCode for Node {
|
||||||
},
|
},
|
||||||
body.iter().map(|x| x.to_code()).join(" ")
|
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(),
|
Node::Word(x) => x.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue