[WIP] Add conditions

This commit is contained in:
Dominic Grimm 2022-09-11 19:32:05 +02:00
parent 0530522847
commit 2e71d9e99e
No known key found for this signature in database
GPG key ID: A6C051C716D2CE65
10 changed files with 51 additions and 62 deletions

View file

@ -47,14 +47,14 @@ fn main() -> Result<()> {
match args.commands { match args.commands {
Commands::Lex { src } => { Commands::Lex { src } => {
let assembly = fs::read_to_string(src)?; let assembly = fs::read_to_string(src)?;
let tokens = lexer::lex(assembly)?; let tokens = lexer::lex(&assembly)?;
dbg!(tokens); dbg!(tokens);
Ok(()) Ok(())
} }
Commands::Parse { src } => { Commands::Parse { src } => {
let assembly = fs::read_to_string(src)?; let assembly = fs::read_to_string(src)?;
let tokens = lexer::lex(assembly)?; let tokens = lexer::lex(&assembly)?;
let ast = parser::parse(tokens)?; let ast = parser::parse(tokens)?;
dbg!(ast); dbg!(ast);
@ -62,7 +62,7 @@ fn main() -> Result<()> {
} }
Commands::Assemble { src, bin, dump } => { Commands::Assemble { src, bin, dump } => {
let assembly = fs::read_to_string(&src)?; let assembly = fs::read_to_string(&src)?;
let tokens = lexer::lex(assembly)?; let tokens = lexer::lex(&assembly)?;
let ast = parser::parse(tokens)?; let ast = parser::parse(tokens)?;
let mut data = assembler::Data::new( let mut data = assembler::Data::new(

View file

@ -337,7 +337,7 @@ impl Data {
}; };
self.includes.insert(arg); self.includes.insert(arg);
let body = parser::parse(lexer::lex(source)?)?.body; let body = parser::parse(lexer::lex(&source)?)?.body;
self.body_stack self.body_stack
.extend(body.into_iter().rev().collect::<Vec<_>>()); .extend(body.into_iter().rev().collect::<Vec<_>>());

View file

@ -89,7 +89,7 @@ impl assembler::ToCode for Token {
} }
} }
pub fn lex(source: String) -> Result<Vec<Token>> { pub fn lex(source: &str) -> Result<Vec<Token>> {
let mut chars = source.chars().peekable(); let mut chars = source.chars().peekable();
let mut tokens: Vec<Token> = vec![]; let mut tokens: Vec<Token> = vec![];

View file

@ -1,7 +1,3 @@
\ 1 1 = debug 1 1 = debug
\ if 69 else 42 then debug if 69 else 42 then debug
: test 42 ;
test debug drop
test test debug

View file

@ -42,14 +42,14 @@ fn main() -> Result<()> {
match args.commands { match args.commands {
Commands::Lex { src } => { Commands::Lex { src } => {
let source = fs::read_to_string(src)?; let source = fs::read_to_string(src)?;
let tokens = lexer::lex(source)?; let tokens = lexer::lex(&source)?;
dbg!(tokens); dbg!(tokens);
Ok(()) Ok(())
} }
Commands::Parse { src } => { Commands::Parse { src } => {
let source = fs::read_to_string(src)?; let source = fs::read_to_string(src)?;
let tokens = lexer::lex(source)?; let tokens = lexer::lex(&source)?;
let body = parser::parse(tokens)?; let body = parser::parse(tokens)?;
dbg!(body); dbg!(body);
@ -62,7 +62,7 @@ fn main() -> Result<()> {
dump, dump,
} => { } => {
let source = fs::read_to_string(&src)?; let source = fs::read_to_string(&src)?;
let tokens = lexer::lex(source)?; let tokens = lexer::lex(&source)?;
let ast = parser::parse(tokens)?; let ast = parser::parse(tokens)?;
let ast = compiler::compile(ast, optimize.unwrap_or(true))?; let ast = compiler::compile(ast, optimize.unwrap_or(true))?;
let assembly = ast.to_code(); let assembly = ast.to_code();

View file

@ -20,17 +20,17 @@ pub struct Word {
pub times_used: usize, pub times_used: usize,
} }
#[derive(Debug)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct Condition { pub struct Condition {
pub if_instructions: Vec<Instruction>, pub if_instructions: Vec<Instruction>,
pub else_instructions: Vec<Instruction>, pub else_instructions: Vec<Instruction>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Data { pub struct Data {
pub words: HashMap<String, Word>, pub words: HashMap<String, Word>,
// pub word_graph: // pub word_graph:
pub conditions: IndexSet<Instruction>, pub conditions: IndexSet<Condition>,
pub strings: IndexSet<String>, pub strings: IndexSet<String>,
} }
@ -39,7 +39,7 @@ pub const TEMPLATE_ASM: &str = include_str!("compiler/template.asm");
lazy_static! { lazy_static! {
#[derive(Debug)] #[derive(Debug)]
pub static ref TEMPLATE: hence::parser::ast::Body = hence::parser::parse( pub static ref TEMPLATE: hence::parser::ast::Body = hence::parser::parse(
hence::lexer::lex(TEMPLATE_ASM.to_string()).unwrap() hence::lexer::lex(TEMPLATE_ASM).unwrap()
) )
.unwrap() .unwrap()
.body; .body;
@ -116,10 +116,16 @@ impl Data {
); );
} }
parser::ast::Node::Condition { if_body, else_body } => { parser::ast::Node::Condition { if_body, else_body } => {
instructions.push(Instruction::Condition { let if_instructions = self.generate_instructions(if_body, optimize)?;
if_instructions: self.generate_instructions(if_body, optimize)?, let else_instructions = self.generate_instructions(else_body, optimize)?;
else_instructions: self.generate_instructions(else_body, optimize)?, let id = self
}); .conditions
.insert_full(Condition {
if_instructions,
else_instructions,
})
.0;
instructions.push(Instruction::Condition(id));
} }
parser::ast::Node::Word(x) => { parser::ast::Node::Word(x) => {
if let Some(ins) = Instruction::from_word(&x) { if let Some(ins) = Instruction::from_word(&x) {
@ -152,6 +158,14 @@ impl Data {
]); ]);
} }
// conditions
for (id, c) in self.conditions.iter().enumerate() {
x.push(hence::parser::ast::Node::Label(format!("conditions_{}", id)));
x.extend(
);
}
// words // words
for (name, word) in &self for (name, word) in &self
.words .words

View file

@ -2,7 +2,7 @@ use anyhow::{bail, Result};
use crate::compiler; use crate::compiler;
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Instruction { pub enum Instruction {
Nop, Nop,
Debug, Debug,
@ -66,10 +66,7 @@ pub enum Instruction {
Mod, Mod,
Call(String), Call(String),
AsmQuote(String), AsmQuote(String),
Condition { Condition(usize),
if_instructions: Vec<Self>,
else_instructions: Vec<Self>,
},
Multiple { Multiple {
instruction: Box<Self>, instruction: Box<Self>,
@ -1228,15 +1225,10 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
Instruction::Call(x) => match data.words.get(x) { Instruction::Call(x) => match data.words.get(x) {
Some(w) => { Some(w) => {
if w.times_used > 1 { if w.times_used > 1 {
Ok(vec![ Ok(vec![hence::parser::ast::Node::MacroCall {
hence::parser::ast::Node::MacroCall { name: "call_stack_jump".to_string(),
name: "call_stack_jump".to_string(), args: vec![hence::arg::Arg::Variable(format!("words_{}", w.id))],
args: vec![ }])
hence::arg::Arg::Variable(format!("words_{}", w.id)),
hence::arg::Arg::Variable("OFFSET".to_string())
],
}
])
} else { } else {
Ok(w.instructions Ok(w.instructions
.iter() .iter()
@ -1249,25 +1241,11 @@ impl compiler::Compilable<compiler::Data, hence::parser::ast::Body> for Instruct
} }
None => bail!("Unknown word: {}", x), None => bail!("Unknown word: {}", x),
}, },
Instruction::AsmQuote(x) => { Instruction::AsmQuote(x) => Ok(hence::parser::parse(hence::lexer::lex(x)?)?.body),
Ok(hence::parser::parse(hence::lexer::lex(x.to_string())?)?.body) Instruction::Condition(x) => Ok(vec![hence::parser::ast::Node::MacroCall {
} name: "call_stack_jump".to_string(),
Instruction::Condition { args: vec![hence::arg::Arg::Variable(format!("conditions_{}", x))],
if_instructions, }]),
else_instructions,
} => {
let if_compiled = if_instructions
.iter()
.map(|ins| ins.compile(data))
.collect::<Result<Vec<_>>>()?;
let else_compiled = else_instructions
.iter()
.map(|ins| ins.compile(data))
.collect::<Result<Vec<_>>>()?;
dbg!(if_compiled, else_compiled);
Ok(vec![])
}
Instruction::Multiple { instruction, count } => { Instruction::Multiple { instruction, count } => {
if *count == 0 { if *count == 0 {

View file

@ -14,9 +14,10 @@
tlr CORE_REG_A tlr CORE_REG_A
.endmacro .endmacro
.macro call_stack_jump, prep_call_stack_jump_arg_0_label, prep_call_stack_jump_arg_1_offset .macro call_stack_jump, call_stack_jump_arg_0_label
.std_rset CORE_REG_C, prep_call_stack_jump_arg_0_label .define call_stack_jump_local_offset, OFFSET
.std_rset CORE_REG_D, (prep_call_stack_jump_arg_1_offset + 7) .std_rset CORE_REG_C, call_stack_jump_arg_0_label
.std_rset CORE_REG_D, (call_stack_jump_local_offset + 7)
ts call_stack_jump ts call_stack_jump
tlr CORE_REG_PC tlr CORE_REG_PC
.endmacro .endmacro

View file

@ -33,7 +33,7 @@ pub fn is_space(c: char) -> bool {
c.is_whitespace() || c == '\n' c.is_whitespace() || c == '\n'
} }
pub fn lex(source: String) -> Result<Vec<Token>> { pub fn lex(source: &str) -> Result<Vec<Token>> {
let mut chars = source.chars().peekable(); let mut chars = source.chars().peekable();
let mut tokens: Vec<Token> = vec![]; let mut tokens: Vec<Token> = vec![];

View file

@ -14,7 +14,7 @@ pub fn parse_stack_state(s: Option<&str>) -> Vec<String> {
} }
} }
pub fn parse_stack_result(s: String) -> ast::StackResult { pub fn parse_stack_result(s: &str) -> ast::StackResult {
let mut splitter = s.splitn(2, "--"); let mut splitter = s.splitn(2, "--");
ast::StackResult { ast::StackResult {
@ -83,7 +83,7 @@ pub fn parse(tokens: Vec<lexer::Token>) -> Result<ast::AST> {
lexer::Token::ParenComment(x) lexer::Token::ParenComment(x)
| lexer::Token::BackslashComment(x) | lexer::Token::BackslashComment(x)
| lexer::Token::DoubleDashComment(x) => { | lexer::Token::DoubleDashComment(x) => {
let y = x.to_string(); let y = &x.to_string();
content.next(); content.next();
break Some(parse_stack_result(y)); break Some(parse_stack_result(y));
} }