Add new words and assembly emedding

This commit is contained in:
Dominic Grimm 2022-09-09 21:08:24 +02:00
parent 053f3c09a2
commit 30b608e5aa
No known key found for this signature in database
GPG key ID: A6C051C716D2CE65
4 changed files with 504 additions and 19 deletions

View file

@ -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
"

View file

@ -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 {

View file

@ -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())
}
}
}
}
} }
} }
} }

View file

@ -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 {