Add new words and assembly emedding
This commit is contained in:
parent
053f3c09a2
commit
30b608e5aa
4 changed files with 504 additions and 19 deletions
|
@ -1,2 +1,13 @@
|
||||||
1 2 debug
|
asm"
|
||||||
1 pick debug
|
.std_get MEM_ALLOC_PTR
|
||||||
|
tls
|
||||||
|
dbg
|
||||||
|
pop
|
||||||
|
"
|
||||||
|
3 cells allot
|
||||||
|
asm"
|
||||||
|
.std_get MEM_ALLOC_PTR
|
||||||
|
tls
|
||||||
|
dbg
|
||||||
|
pop
|
||||||
|
"
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub struct Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Data {
|
impl Data {
|
||||||
pub fn new() -> Self {
|
pub fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
words: HashMap::new(),
|
words: HashMap::new(),
|
||||||
strings: IndexSet::new(),
|
strings: IndexSet::new(),
|
||||||
|
@ -35,13 +35,29 @@ impl Data {
|
||||||
|
|
||||||
pub fn generate_instructions(&mut self, body: parser::ast::Body) -> Result<Vec<Instruction>> {
|
pub fn generate_instructions(&mut self, body: parser::ast::Body) -> Result<Vec<Instruction>> {
|
||||||
let mut instructions: Vec<Instruction> = vec![];
|
let mut instructions: Vec<Instruction> = vec![];
|
||||||
for node in body {
|
let mut iter = body.into_iter().peekable();
|
||||||
|
while let Some(node) = iter.next() {
|
||||||
match node {
|
match node {
|
||||||
|
_ if iter.next_if_eq(&node).is_some() => {
|
||||||
|
let count = iter.by_ref().peeking_take_while(|n| *n == node).count() + 2;
|
||||||
|
instructions.push(Instruction::Multiple {
|
||||||
|
instruction: Box::new(
|
||||||
|
self.generate_instructions(vec![node])?
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
|
count,
|
||||||
|
});
|
||||||
|
}
|
||||||
parser::ast::Node::Comment(_) => {}
|
parser::ast::Node::Comment(_) => {}
|
||||||
parser::ast::Node::String { mode, string } => {
|
parser::ast::Node::String { mode, string } => {
|
||||||
let id = self.strings.insert_full(string).0;
|
|
||||||
instructions.push(match mode.as_str() {
|
instructions.push(match mode.as_str() {
|
||||||
"." => Instruction::DotQuote(id),
|
"." => {
|
||||||
|
let id = self.strings.insert_full(string).0;
|
||||||
|
Instruction::DotQuote(id)
|
||||||
|
}
|
||||||
|
"asm" => Instruction::AsmQuote(string),
|
||||||
_ => bail!("Unknown string mode: {}", mode),
|
_ => bail!("Unknown string mode: {}", mode),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -109,6 +125,17 @@ impl Data {
|
||||||
hence::arg::Arg::Variable("CORE_MEM_MEM".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_ALLOC_PTR".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,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
// macros
|
// macros
|
||||||
// stack_transfer_alu
|
// stack_transfer_alu
|
||||||
hence::parser::ast::Node::MacroCall {
|
hence::parser::ast::Node::MacroCall {
|
||||||
|
@ -195,6 +222,22 @@ impl Data {
|
||||||
name: "endmacro".to_string(),
|
name: "endmacro".to_string(),
|
||||||
args: vec![],
|
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
|
// jump_main
|
||||||
hence::parser::ast::Node::MacroCall {
|
hence::parser::ast::Node::MacroCall {
|
||||||
name: "jump_main".to_string(),
|
name: "jump_main".to_string(),
|
||||||
|
@ -262,7 +305,7 @@ impl Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(ast: parser::ast::AST) -> Result<hence::parser::ast::AST> {
|
pub fn compile(ast: parser::ast::AST) -> Result<hence::parser::ast::AST> {
|
||||||
let mut data = Data::new();
|
let mut data = Data::default();
|
||||||
let instructions = data.generate_instructions(ast.body)?;
|
let instructions = data.generate_instructions(ast.body)?;
|
||||||
|
|
||||||
Ok(hence::parser::ast::AST {
|
Ok(hence::parser::ast::AST {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use anyhow::{bail, Result};
|
||||||
|
|
||||||
use crate::compiler;
|
use crate::compiler;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
Nop,
|
Nop,
|
||||||
Debug,
|
Debug,
|
||||||
|
@ -63,6 +63,12 @@ pub enum Instruction {
|
||||||
Divide,
|
Divide,
|
||||||
Mod,
|
Mod,
|
||||||
Call(String),
|
Call(String),
|
||||||
|
AsmQuote(String),
|
||||||
|
|
||||||
|
Multiple {
|
||||||
|
instruction: Box<Self>,
|
||||||
|
count: usize,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instruction {
|
impl Instruction {
|
||||||
|
@ -291,11 +297,114 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
|
||||||
arg: None,
|
arg: None,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
Instruction::Rot => Ok(vec![]),
|
Instruction::Rot => Ok(vec![
|
||||||
Instruction::Nip => 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_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: "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: "tsr".to_string(),
|
||||||
|
arg: Some(hence::arg::Arg::Variable("CORE_REG_A".to_string())),
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
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: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
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::Nip => Ok(vec![
|
||||||
|
hence::parser::ast::Node::MacroCall {
|
||||||
|
name: "std_ld".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "pop".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
]),
|
||||||
Instruction::I => Ok(vec![]),
|
Instruction::I => Ok(vec![]),
|
||||||
Instruction::J => Ok(vec![]),
|
Instruction::J => Ok(vec![]),
|
||||||
Instruction::Tuck => Ok(vec![]),
|
Instruction::Tuck => 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_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::Call {
|
||||||
|
name: "tsr".to_string(),
|
||||||
|
arg: Some(hence::arg::Arg::Variable("CORE_REG_A".to_string())),
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
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: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "tsr".to_string(),
|
||||||
|
arg: Some(hence::arg::Arg::Variable("CORE_REG_A".to_string())),
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
]),
|
||||||
Instruction::Fetch => Ok(vec![
|
Instruction::Fetch => Ok(vec![
|
||||||
hence::parser::ast::Node::MacroCall {
|
hence::parser::ast::Node::MacroCall {
|
||||||
name: "std_ld".to_string(),
|
name: "std_ld".to_string(),
|
||||||
|
@ -310,12 +419,165 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
|
||||||
arg: None,
|
arg: None,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
Instruction::FetchPrint => Ok(vec![]),
|
Instruction::FetchPrint => Ok(vec![
|
||||||
Instruction::Store => Ok(vec![]),
|
hence::parser::ast::Node::MacroCall {
|
||||||
Instruction::PlusStore => Ok(vec![]),
|
name: "std_ld".to_string(),
|
||||||
Instruction::MinusStore => Ok(vec![]),
|
args: vec![],
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "get".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
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_set".to_string(),
|
||||||
|
args: vec![hence::arg::Arg::Variable("CORE_MEM_OUT".to_string())],
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
Instruction::Store => 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_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::Call {
|
||||||
|
name: "tsr".to_string(),
|
||||||
|
arg: Some(hence::arg::Arg::Variable("CORE_REG_B".to_string())),
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "set".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
Instruction::PlusStore => 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: "get".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
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_ADD".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_C".to_string())),
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "set".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
Instruction::MinusStore => 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: "get".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
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_SUB".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_C".to_string())),
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "set".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
]),
|
||||||
Instruction::Cells => Ok(vec![]),
|
Instruction::Cells => Ok(vec![]),
|
||||||
Instruction::Allot => Ok(vec![]),
|
Instruction::Allot => Ok(vec![
|
||||||
|
hence::parser::ast::Node::MacroCall {
|
||||||
|
name: "std_get".to_string(),
|
||||||
|
args: vec![hence::arg::Arg::Variable("MEM_ALLOC_PTR".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_ADD".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_set".to_string(),
|
||||||
|
args: vec![hence::arg::Arg::Variable("MEM_ALLOC_PTR".to_string())],
|
||||||
|
},
|
||||||
|
]),
|
||||||
Instruction::Dot => Ok(vec![
|
Instruction::Dot => Ok(vec![
|
||||||
hence::parser::ast::Node::MacroCall {
|
hence::parser::ast::Node::MacroCall {
|
||||||
name: "std_ld".to_string(),
|
name: "std_ld".to_string(),
|
||||||
|
@ -344,7 +606,19 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
|
||||||
args: vec![hence::arg::Arg::Variable("CORE_MEM_CHR".to_string())],
|
args: vec![hence::arg::Arg::Variable("CORE_MEM_CHR".to_string())],
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
Instruction::Space => Ok(vec![]),
|
Instruction::Space => Ok(vec![
|
||||||
|
hence::parser::ast::Node::MacroCall {
|
||||||
|
name: "std_rset".to_string(),
|
||||||
|
args: vec![
|
||||||
|
hence::arg::Arg::Variable("CORE_REG_A".to_string()),
|
||||||
|
hence::arg::Arg::Char('\n'),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::MacroCall {
|
||||||
|
name: "std_set".to_string(),
|
||||||
|
args: vec![hence::arg::Arg::Variable("CORE_MEM_CHR".to_string())],
|
||||||
|
},
|
||||||
|
]),
|
||||||
Instruction::Spaces => Ok(vec![]),
|
Instruction::Spaces => Ok(vec![]),
|
||||||
Instruction::Cr => Ok(vec![
|
Instruction::Cr => Ok(vec![
|
||||||
hence::parser::ast::Node::MacroCall {
|
hence::parser::ast::Node::MacroCall {
|
||||||
|
@ -622,6 +896,163 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
|
||||||
}
|
}
|
||||||
None => bail!("Unknown word: {}", x),
|
None => bail!("Unknown word: {}", x),
|
||||||
},
|
},
|
||||||
|
Instruction::AsmQuote(x) => {
|
||||||
|
Ok(hence::parser::parse(hence::lexer::lex(x.to_string())?)?.body)
|
||||||
|
}
|
||||||
|
Instruction::Multiple { instruction, count } => {
|
||||||
|
if *count == 0 {
|
||||||
|
Ok(vec![])
|
||||||
|
} else if *count == 1 {
|
||||||
|
Ok(instruction.compile(data)?)
|
||||||
|
} else {
|
||||||
|
match **instruction {
|
||||||
|
Instruction::Nop => Ok(Instruction::Nop.compile(data)?),
|
||||||
|
Instruction::Quit => Ok(Instruction::Quit.compile(data)?),
|
||||||
|
Instruction::Depth => Ok([
|
||||||
|
Instruction::Depth.compile(data)?,
|
||||||
|
Instruction::Multiple {
|
||||||
|
instruction: Box::new(Instruction::Dup),
|
||||||
|
count: count - 1,
|
||||||
|
}
|
||||||
|
.compile(data)?,
|
||||||
|
]
|
||||||
|
.concat()),
|
||||||
|
Instruction::Dup => Ok([
|
||||||
|
Instruction::Dup.compile(data)?,
|
||||||
|
[hence::parser::ast::Node::Call {
|
||||||
|
name: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
}]
|
||||||
|
.into_iter()
|
||||||
|
.cycle()
|
||||||
|
.take(count - 1)
|
||||||
|
.collect(),
|
||||||
|
]
|
||||||
|
.concat()),
|
||||||
|
Instruction::Swap => {
|
||||||
|
if count % 2 == 0 {
|
||||||
|
Ok(vec![])
|
||||||
|
} else {
|
||||||
|
Ok(Instruction::Swap.compile(data)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Instruction::Over => Ok([
|
||||||
|
Instruction::Over.compile(data)?,
|
||||||
|
(0..count - 1)
|
||||||
|
.flat_map(|n| {
|
||||||
|
if n % 2 == 0 {
|
||||||
|
vec![
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "tsr".to_string(),
|
||||||
|
arg: Some(hence::arg::Arg::Variable(
|
||||||
|
"CORE_REG_A".to_string(),
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
vec![
|
||||||
|
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: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
]
|
||||||
|
.concat()),
|
||||||
|
Instruction::Rot => match count % 3 {
|
||||||
|
0 => Ok(vec![]),
|
||||||
|
1 => Ok(Instruction::Rot.compile(data)?),
|
||||||
|
2 => 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_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_C".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::Call {
|
||||||
|
name: "tsr".to_string(),
|
||||||
|
arg: Some(hence::arg::Arg::Variable("CORE_REG_A".to_string())),
|
||||||
|
},
|
||||||
|
hence::parser::ast::Node::Call {
|
||||||
|
name: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
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: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
_ => bail!("Remainder of count % 3 cannot be higher than 3"),
|
||||||
|
},
|
||||||
|
Instruction::Nip => Ok([
|
||||||
|
vec![hence::parser::ast::Node::MacroCall {
|
||||||
|
name: "std_ld".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
}],
|
||||||
|
[hence::parser::ast::Node::Call {
|
||||||
|
name: "pop".to_string(),
|
||||||
|
arg: None,
|
||||||
|
}]
|
||||||
|
.into_iter()
|
||||||
|
.cycle()
|
||||||
|
.take(*count)
|
||||||
|
.collect(),
|
||||||
|
vec![hence::parser::ast::Node::Call {
|
||||||
|
name: "tls".to_string(),
|
||||||
|
arg: None,
|
||||||
|
}],
|
||||||
|
]
|
||||||
|
.concat()),
|
||||||
|
_ => {
|
||||||
|
let compiled = instruction.compile(data)?;
|
||||||
|
let len = compiled.len() * count;
|
||||||
|
Ok(compiled.into_iter().cycle().take(len).collect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use hence::assembler::ToCode;
|
use hence::assembler::ToCode;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct StackResult {
|
pub struct StackResult {
|
||||||
pub before: Vec<String>,
|
pub before: Vec<String>,
|
||||||
pub after: Vec<String>,
|
pub after: Vec<String>,
|
||||||
|
@ -25,7 +25,7 @@ impl ToCode for StackResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Node {
|
pub enum Node {
|
||||||
Comment(String),
|
Comment(String),
|
||||||
String {
|
String {
|
||||||
|
|
Loading…
Reference in a new issue