Update henceforth

This commit is contained in:
Dominic Grimm 2023-03-24 21:13:40 +01:00
parent d6f7a51e11
commit cdd5b8855a
No known key found for this signature in database
GPG key ID: 12EFFCAEA9E620BF
14 changed files with 683 additions and 314 deletions

View file

@ -6,20 +6,21 @@ use std::collections::HashMap;
use crate::parser;
mod instruction;
pub mod instruction;
pub mod templates;
pub use instruction::Instruction;
pub const TEMPLATE_ASM: &str = include_str!("compiler/templates/default.asm");
// pub const TEMPLATE_ASM: &str = include_str!("compiler/templates/default.asm");
lazy_static! {
#[derive(Debug)]
pub static ref TEMPLATE: hence::parser::ast::Body = hence::parser::parse(
hence::lexer::lex(TEMPLATE_ASM).unwrap()
)
.unwrap()
.body;
}
// lazy_static! {
// #[derive(Debug)]
// pub static ref TEMPLATE: hence::parser::ast::Body = hence::parser::parse(
// hence::lexer::lex(TEMPLATE_ASM).unwrap()
// )
// .unwrap()
// .body;
// }
pub trait Compilable<T, U> {
fn compile(&self, data: &T) -> Result<U>;
@ -54,8 +55,6 @@ pub struct Compiler {
impl Compiler {
pub fn default() -> Self {
Self {
// words: HashMap::new(),
// conditions: IndexSet::new(),
strings: IndexSet::new(),
words: HashMap::new(),
conditions: vec![],
@ -123,22 +122,16 @@ impl Compiler {
);
}
parser::ast::Node::Condition { if_body, else_body } => {
// let if_instructions = self.generate_instructions(if_body, optimize)?;
// let else_instructions = self.generate_instructions(else_body, optimize)?;
// let id = self.conditions.len();
// let origin = self.callable_graph.add_node(CallableId::Condition(id));
// self.conditions.push(Condition {
// if_instructions: if_instructions.clone(),
// else_instructions: else_instructions.clone(),
// callable_graph_node: origin,
// });
// instructions.push(Instruction::Condition(id));
// self.add_graph_edges(origin, if_instructions)?;
// self.add_graph_edges(origin, else_instructions)?;
// dbg!(&self);
let if_instructions = self.generate_instructions(if_body, optimize)?;
let else_instructions = self.generate_instructions(else_body, optimize)?;
let id = self.conditions.len();
self.conditions.push(Condition {
if_instructions: if_instructions.clone(),
else_instructions: else_instructions.clone(),
});
instructions.push(Instruction::Condition(id));
}
parser::ast::Node::Word(x) => {
dbg!(&self.words, &x);
if let Some(ins) = Instruction::from_word(&x) {
instructions.push(ins);
} else if let Some(w) = self.words.get_mut(&x) {
@ -154,106 +147,162 @@ impl Compiler {
Ok(instructions)
}
pub fn embed(&self, body: hence::parser::ast::Body) -> Result<hence::parser::ast::Body> {
let mut x = TEMPLATE.to_vec();
pub fn embed(&self, body: hence::parser::ast::Body) -> Result<String> {
let strings = self
.strings
.iter()
.enumerate()
.map(|(id, s)| templates::IdLike {
id,
data: s.to_owned(),
})
.collect();
dbg!(&self.strings);
// for (id, s) in self.strings.iter().enumerate() {
// x.extend([
// hence::parser::ast::Node::Label(format!("data_strings_{}", id)),
// hence::parser::ast::Node::MacroCall {
// name: "bytes".to_string(),
// args: vec![hence::arg::Arg::String(s.to_string())],
// },
// hence::parser::ast::Node::Label(format!("data_strings_end_{}", id)),
// ]);
// }
// strings
for (id, s) in self.strings.iter().enumerate() {
x.extend([
hence::parser::ast::Node::Label(format!("data_strings_{}", id)),
hence::parser::ast::Node::MacroCall {
name: "bytes".to_string(),
args: vec![hence::arg::Arg::String(s.to_string())],
},
hence::parser::ast::Node::Label(format!("data_strings_end_{}", id)),
]);
}
// for (id, c) in self.conditions.iter().enumerate() {
// x.push(hence::parser::ast::Node::Label(format!(
// "conditions_if_{}",
// id
// )));
// x.extend(
// c.if_instructions
// .iter()
// .map(|ins| ins.compile(self))
// .collect::<Result<Vec<_>>>()?
// .into_iter()
// .flatten(),
// );
// x.push(hence::parser::ast::Node::Label(format!(
// "conditions_else_{}",
// id
// )));
// x.extend(
// c.else_instructions
// .iter()
// .map(|ins| ins.compile(self))
// .collect::<Result<Vec<_>>>()?
// .into_iter()
// .flatten(),
// );
// }
let conditions = self
.conditions
.iter()
.enumerate()
.map(|(id, c)| {
Ok(templates::IdLike {
id,
data: (
c.if_instructions
.iter()
.map(|ins| ins.compile(self))
.collect::<Result<Vec<_>>>()?
.into_iter()
.flatten()
.collect(),
c.else_instructions
.iter()
.map(|ins| ins.compile(self))
.collect::<Result<Vec<_>>>()?
.into_iter()
.flatten()
.collect(),
),
})
})
.collect::<Result<Vec<_>>>()?;
// conditions
for (id, c) in self.conditions.iter().enumerate() {
x.push(hence::parser::ast::Node::Label(format!(
"conditions_if_{}",
id
)));
x.extend(
c.if_instructions
.iter()
.map(|ins| ins.compile(self))
.collect::<Result<Vec<_>>>()?
.into_iter()
.flatten(),
);
x.push(hence::parser::ast::Node::Label(format!(
"conditions_else_{}",
id
)));
x.extend(
c.else_instructions
.iter()
.map(|ins| ins.compile(self))
.collect::<Result<Vec<_>>>()?
.into_iter()
.flatten(),
);
}
// words
for (name, word) in &self
// for (name, word) in &self
// .words
// .iter()
// .filter(|(_, w)| w.times_used > 1)
// .sorted_by(|a, b| Ord::cmp(&a.1.id, &b.1.id))
// .collect::<Vec<_>>()
// {
// x.extend(vec![
// hence::parser::ast::Node::Label(format!("words_{}", word.id)),
// hence::parser::ast::Node::Comment(format!("word: \"{}\"", name)),
// ]);
// x.extend(
// word.instructions
// .iter()
// .map(|ins| ins.compile(self))
// .collect::<Result<Vec<hence::parser::ast::Body>>>()
// .unwrap()
// .into_iter()
// .flatten(),
// );
// x.push(hence::parser::ast::Node::MacroCall {
// name: "return_call_stack_jump".to_string(),
// args: vec![],
// });
// }
let words = self
.words
.iter()
.filter(|(_, w)| w.times_used > 1)
.sorted_by(|a, b| Ord::cmp(&a.1.id, &b.1.id))
.collect::<Vec<_>>()
{
x.extend(vec![
hence::parser::ast::Node::Label(format!("words_{}", word.id)),
hence::parser::ast::Node::Comment(format!("word: \"{}\"", name)),
]);
x.extend(
word.instructions
.iter()
.map(|ins| ins.compile(self))
.collect::<Result<Vec<hence::parser::ast::Body>>>()
.unwrap()
.into_iter()
.flatten(),
);
x.push(hence::parser::ast::Node::MacroCall {
name: "return_call_stack_jump".to_string(),
args: vec![],
});
.map(|(name, w)| {
Ok(templates::IdLike {
id: w.id,
data: (
name.to_owned(),
w.instructions
.iter()
.map(|ins| ins.compile(self))
.collect::<Result<Vec<_>>>()?
.into_iter()
.flatten()
.collect(),
),
})
})
.collect::<Result<Vec<_>>>()?;
// x.extend([
// hence::parser::ast::Node::Label("main".to_string()),
// hence::parser::ast::Node::MacroCall {
// name: "main".to_string(),
// args: vec![hence::arg::Arg::Variable("main".to_string())],
// },
// ]);
// x.extend(body);
// x.push(hence::parser::ast::Node::MacroCall {
// name: "std_stop".to_string(),
// args: vec![],
// });
Ok(templates::DefaultTemplate {
strings,
conditions,
words,
main: body,
}
x.extend([
hence::parser::ast::Node::Label("main".to_string()),
hence::parser::ast::Node::MacroCall {
name: "main".to_string(),
args: vec![hence::arg::Arg::Variable("main".to_string())],
},
]);
x.extend(body);
x.push(hence::parser::ast::Node::MacroCall {
name: "std_stop".to_string(),
args: vec![],
});
Ok(x)
.to_string())
}
}
pub fn compile(ast: parser::ast::AST, optimize: bool) -> Result<hence::parser::ast::AST> {
pub fn compile(ast: parser::ast::AST, optimize: bool) -> Result<String> {
let mut data = Compiler::default();
let instructions = data.generate_instructions(ast.body, optimize)?;
Ok(hence::parser::ast::AST {
body: data.embed(
instructions
.iter()
.map(|ins| ins.compile(&data))
.collect::<Result<Vec<hence::parser::ast::Body>>>()?
.into_iter()
.flatten()
.collect(),
)?,
})
Ok(data.embed(
instructions
.iter()
.map(|ins| ins.compile(&data))
.collect::<Result<Vec<hence::parser::ast::Body>>>()?
.into_iter()
.flatten()
.collect(),
)?)
}

View file

@ -1249,7 +1249,7 @@ impl compiler::Compilable<compiler::Compiler, hence::parser::ast::Body> for Inst
Instruction::AsmQuote(x) => Ok(hence::parser::parse(hence::lexer::lex(x)?)?.body),
// Instruction::Condition(x) => Ok(vec![]),
Instruction::Condition(x) => {
dbg!(x);
// dbg!(x);
Ok(vec![])
}

View file

@ -0,0 +1,16 @@
use askama::Template;
use hence::assembler::ToCode;
pub struct IdLike<T, U> {
pub id: T,
pub data: U,
}
#[derive(Template)]
#[template(path = "default.asm", escape = "none")]
pub struct DefaultTemplate {
pub strings: Vec<IdLike<usize, String>>,
pub conditions: Vec<IdLike<usize, (hence::parser::ast::Body, hence::parser::ast::Body)>>,
pub words: Vec<IdLike<usize, (String, hence::parser::ast::Body)>>,
pub main: hence::parser::ast::Body,
}

View file

@ -1,67 +0,0 @@
.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_LEN, 16
.define MEM_CALL_STACK_PTR, (MEM_LOOP_J + 1)
.define MEM_CALL_STACK_END, (MEM_CALL_STACK_PTR + MEM_CALL_STACK_LEN)
.define MEM_ALLOC_PTR, MEM_CALL_STACK_END
.macro stack_transfer_alu
.std_ld
tlr CORE_REG_B
.std_ld
tlr CORE_REG_A
.endmacro
.macro call_stack_jump, call_stack_jump_arg_0_label, call_stack_jump_arg_1_offset
.std_rset CORE_REG_C, call_stack_jump_arg_0_label
.std_rset CORE_REG_D, (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

View file

@ -1,6 +1,5 @@
use anyhow::Result;
use clap::{Parser, Subcommand};
use hence::assembler::ToCode;
use std::fs;
use henceforth::*;
@ -64,8 +63,7 @@ fn main() -> Result<()> {
let source = fs::read_to_string(&src)?;
let tokens = lexer::lex(&source)?;
let ast = parser::parse(tokens)?;
let ast = compiler::compile(ast, optimize.unwrap_or(true))?;
let assembly = format!("{}\n", ast.to_code());
let assembly = format!("{}\n", compiler::compile(ast, optimize.unwrap_or(true))?);
if dump {
print!("{}", assembly);

View file

@ -36,7 +36,10 @@ pub fn parse(tokens: Vec<lexer::Token>) -> Result<ast::AST> {
body.push(ast::Node::Comment(x.trim().to_string()));
}
lexer::Token::StringLiteral { mode, string } => {
body.push(ast::Node::String { mode, string });
body.push(ast::Node::String {
mode,
string: snailquote::unescape(&format!("\"{}\"", string))?,
});
}
lexer::Token::Number(x) => body.push(ast::Node::Number(parse_int::parse(&x)?)),
lexer::Token::Word(x) => match x.as_str() {