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
1 pick debug
asm"
.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 {
pub fn new() -> Self {
pub fn default() -> Self {
Self {
words: HashMap::new(),
strings: IndexSet::new(),
@ -35,13 +35,29 @@ impl Data {
pub fn generate_instructions(&mut self, body: parser::ast::Body) -> Result<Vec<Instruction>> {
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 {
_ 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::String { mode, string } => {
let id = self.strings.insert_full(string).0;
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),
});
}
@ -109,6 +125,17 @@ impl Data {
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
// stack_transfer_alu
hence::parser::ast::Node::MacroCall {
@ -195,6 +222,22 @@ impl Data {
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(),
@ -262,7 +305,7 @@ impl Data {
}
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)?;
Ok(hence::parser::ast::AST {

View file

@ -2,7 +2,7 @@ use anyhow::{bail, Result};
use crate::compiler;
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone)]
pub enum Instruction {
Nop,
Debug,
@ -63,6 +63,12 @@ pub enum Instruction {
Divide,
Mod,
Call(String),
AsmQuote(String),
Multiple {
instruction: Box<Self>,
count: usize,
},
}
impl Instruction {
@ -291,11 +297,114 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
arg: None,
},
]),
Instruction::Rot => Ok(vec![]),
Instruction::Nip => Ok(vec![]),
Instruction::Rot => 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::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![
hence::parser::ast::Node::MacroCall {
name: "std_ld".to_string(),
@ -310,12 +419,165 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
arg: None,
},
]),
Instruction::FetchPrint => Ok(vec![]),
Instruction::Store => Ok(vec![]),
Instruction::PlusStore => Ok(vec![]),
Instruction::MinusStore => Ok(vec![]),
Instruction::FetchPrint => Ok(vec![
hence::parser::ast::Node::MacroCall {
name: "std_ld".to_string(),
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::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![
hence::parser::ast::Node::MacroCall {
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())],
},
]),
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::Cr => Ok(vec![
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),
},
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 itertools::Itertools;
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct StackResult {
pub before: Vec<String>,
pub after: Vec<String>,
@ -25,7 +25,7 @@ impl ToCode for StackResult {
}
}
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
pub enum Node {
Comment(String),
String {