[WIP] Add conditions
This commit is contained in:
parent
7943b1607b
commit
0530522847
8 changed files with 338 additions and 180 deletions
|
@ -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(),
|
||||
),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue