From 2c67dba4d732f7ad4e0943495993977fe3734cc8 Mon Sep 17 00:00:00 2001 From: Dominic Grimm Date: Fri, 30 Sep 2022 17:43:55 +0200 Subject: [PATCH] [WIP] Fix assembler --- hence/src/lib/arg.rs | 6 +- hence/src/lib/assembler.rs | 27 +++--- hence/src/lib/parser.rs | 2 +- henceforth/src/lib/compiler.rs | 85 ++++++++++++------- .../{template.asm => templates/default.asm} | 0 5 files changed, 69 insertions(+), 51 deletions(-) rename henceforth/src/lib/compiler/{template.asm => templates/default.asm} (100%) diff --git a/hence/src/lib/arg.rs b/hence/src/lib/arg.rs index 8e9a70b..36dc012 100644 --- a/hence/src/lib/arg.rs +++ b/hence/src/lib/arg.rs @@ -264,8 +264,8 @@ pub fn parse_binary_expression_arg(tokens: &mut Vec<&lexer::Token>) -> Result = tokens.drain(..3).collect(); let mut bin_expr = Arg::BinaryExpression { - left: Box::new((&parse_args(vec![args[0]])?[0]).clone()), - right: Box::new((&parse_args(vec![args[2]])?[0]).clone()), + left: Box::new(parse_args(vec![args[0]])?[0].clone()), + right: Box::new(parse_args(vec![args[2]])?[0].clone()), op: parse_binary_operation(args[1])?, }; @@ -273,7 +273,7 @@ pub fn parse_binary_expression_arg(tokens: &mut Vec<&lexer::Token>) -> Result Ok(x.clone()), @@ -380,20 +380,17 @@ impl Data { while !self.body_stack.is_empty() { self.constants .insert(offset_name.clone(), arg::Arg::Number(self.offset)); - match self.resolve_node()? { - Some(x) => { - if self.offset + (x.len() as u16) > 32 * 1024 { - bail!( - "Offset out of bounds: 0x{} > 0x8000", - radix(self.offset, 16) - ); - } - for byte in x { - self.program[self.offset as usize] = byte; - self.offset += 1; - } + if let Some(x) = self.resolve_node()? { + if self.offset + (x.len() as u16) > 32 * 1024 { + bail!( + "Offset out of bounds: 0x{} > 0x8000", + radix(self.offset, 16) + ); + } + for byte in x { + self.program[self.offset as usize] = byte; + self.offset += 1; } - None => {} } } diff --git a/hence/src/lib/parser.rs b/hence/src/lib/parser.rs index ba9fead..e21abc1 100644 --- a/hence/src/lib/parser.rs +++ b/hence/src/lib/parser.rs @@ -20,7 +20,7 @@ pub fn parse(tokens: Vec) -> Result { iter.next(); body.push(ast::Node::MacroCall { - name: (&x[1..]).to_string(), + name: x[1..].to_string(), args: arg::parse_args( iter.by_ref() .take_while(|t| !matches!(t, lexer::Token::Newline(_))) diff --git a/henceforth/src/lib/compiler.rs b/henceforth/src/lib/compiler.rs index 5e373a3..b6f7898 100644 --- a/henceforth/src/lib/compiler.rs +++ b/henceforth/src/lib/compiler.rs @@ -2,7 +2,7 @@ use anyhow::{bail, Context, Result}; use indexmap::IndexSet; use itertools::Itertools; use lazy_static::lazy_static; -use petgraph::Graph; +use petgraph::{graph::NodeIndex, Graph}; use std::collections::HashMap; use crate::parser; @@ -10,7 +10,7 @@ use crate::parser; mod instruction; pub use crate::compiler::instruction::Instruction; -pub const TEMPLATE_ASM: &str = include_str!("compiler/template.asm"); +pub const TEMPLATE_ASM: &str = include_str!("compiler/templates/default.asm"); lazy_static! { #[derive(Debug)] @@ -30,14 +30,14 @@ pub struct Word { pub id: usize, pub instructions: Vec, pub times_used: usize, - pub callable_graph_node: petgraph::graph::NodeIndex, + pub callable_graph_node: NodeIndex, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct Condition { pub if_instructions: Vec, pub else_instructions: Vec, - pub callable_graph_node: petgraph::graph::NodeIndex, + pub callable_graph_node: NodeIndex, } #[derive(Debug)] @@ -48,8 +48,6 @@ pub enum CallableId { #[derive(Debug)] pub struct Data { - // pub words: HashMap, - // pub conditions: IndexSet, pub strings: IndexSet, pub callable_graph: Graph, pub words: HashMap, @@ -68,6 +66,45 @@ impl Data { } } + pub fn add_graph_edge(&mut self, origin: NodeIndex, instruction: Instruction) -> Result<()> { + match instruction { + Instruction::Call(x) => { + self.callable_graph.add_edge( + origin, + self.words + .get(&x) + .context(format!("Could not get referenced word: {}", x))? + .callable_graph_node, + (), + ); + } + Instruction::Condition(x) => { + self.callable_graph.add_edge( + origin, + self.conditions + .get(x) + .context(format!("Could not get referenced condition: {}", x))? + .callable_graph_node, + (), + ); + } + Instruction::Multiple { instruction, count: _ } => { + self.add_graph_edge(origin, *instruction)?; + } + _ => {} + } + + Ok(()) + } + + pub fn add_graph_edges(&mut self, origin: NodeIndex, ins: Vec) -> Result<()> { + for instruction in ins { + self.add_graph_edge(origin, instruction)?; + } + + Ok(()) + } + pub fn generate_instructions( &mut self, body: parser::ast::Body, @@ -135,45 +172,29 @@ impl Data { .get_mut(&name) .context(format!("Could not get word: {}", name))? .instructions = ins.clone(); - - for instruction in ins { - match instruction { - Instruction::Call(x) => { - self.callable_graph.add_edge( - origin, - self.words - .get(&x) - .context(format!("Could not get referenced word: {}", x))? - .callable_graph_node, - (), - ); - } - Instruction::Condition(x) => {} - _ => {} - } - } - dbg!(&self); + self.add_graph_edges(origin, ins)?; } 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, - else_instructions, - callable_graph_node: self - .callable_graph - .add_node(CallableId::Condition(id)), + if_instructions: if_instructions.clone(), + else_instructions: else_instructions.clone(), + callable_graph_node: origin, }); instructions.push(Instruction::Condition(id)); - self.callable_graph.add_node(CallableId::Condition(id)); + self.add_graph_edges(origin, if_instructions)?; + self.add_graph_edges(origin, else_instructions)?; + dbg!(&self); } parser::ast::Node::Word(x) => { if let Some(ins) = Instruction::from_word(&x) { instructions.push(ins); } else if let Some(w) = self.words.get_mut(&x) { - instructions.push(Instruction::Call(x)); w.times_used += 1; + instructions.push(Instruction::Call(x)); } else { bail!("Word does not exist: {}", x); } @@ -229,7 +250,7 @@ impl Data { // .collect::>>() // .unwrap() // .into_iter() - // .flatten(), + // .flatten() // ); // x.push(hence::parser::ast::Node::MacroCall { // name: "return_call_stack_jump".to_string(), diff --git a/henceforth/src/lib/compiler/template.asm b/henceforth/src/lib/compiler/templates/default.asm similarity index 100% rename from henceforth/src/lib/compiler/template.asm rename to henceforth/src/lib/compiler/templates/default.asm