call-graph #1
5 changed files with 69 additions and 51 deletions
|
@ -264,8 +264,8 @@ pub fn parse_binary_expression_arg(tokens: &mut Vec<&lexer::Token>) -> Result<Ar
|
||||||
let mut args: Vec<_> = tokens.drain(..3).collect();
|
let mut args: Vec<_> = tokens.drain(..3).collect();
|
||||||
|
|
||||||
let mut bin_expr = Arg::BinaryExpression {
|
let mut bin_expr = Arg::BinaryExpression {
|
||||||
left: Box::new((&parse_args(vec![args[0]])?[0]).clone()),
|
left: Box::new(parse_args(vec![args[0]])?[0].clone()),
|
||||||
right: Box::new((&parse_args(vec![args[2]])?[0]).clone()),
|
right: Box::new(parse_args(vec![args[2]])?[0].clone()),
|
||||||
op: parse_binary_operation(args[1])?,
|
op: parse_binary_operation(args[1])?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ pub fn parse_binary_expression_arg(tokens: &mut Vec<&lexer::Token>) -> Result<Ar
|
||||||
args = tokens.drain(..2).collect();
|
args = tokens.drain(..2).collect();
|
||||||
bin_expr = Arg::BinaryExpression {
|
bin_expr = Arg::BinaryExpression {
|
||||||
left: Box::new(bin_expr),
|
left: Box::new(bin_expr),
|
||||||
right: Box::new((&parse_args(vec![args[1]])?[0]).clone()),
|
right: Box::new(parse_args(vec![args[1]])?[0].clone()),
|
||||||
op: parse_binary_operation(args[0])?,
|
op: parse_binary_operation(args[0])?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,7 +158,7 @@ impl Data {
|
||||||
bail!("First argument of define macro needs to be a variable")
|
bail!("First argument of define macro needs to be a variable")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.constants.insert(name.clone(), (&args[1]).clone());
|
self.constants.insert(name.clone(), args[1].clone());
|
||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ impl Data {
|
||||||
bail!("First argument of define macro needs to be a literal-like value")
|
bail!("First argument of define macro needs to be a literal-like value")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let args = (&args[1..])
|
let args = args[1..]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|a| match a {
|
.map(|a| match a {
|
||||||
arg::Arg::Variable(x) => Ok(x.clone()),
|
arg::Arg::Variable(x) => Ok(x.clone()),
|
||||||
|
@ -380,8 +380,7 @@ impl Data {
|
||||||
while !self.body_stack.is_empty() {
|
while !self.body_stack.is_empty() {
|
||||||
self.constants
|
self.constants
|
||||||
.insert(offset_name.clone(), arg::Arg::Number(self.offset));
|
.insert(offset_name.clone(), arg::Arg::Number(self.offset));
|
||||||
match self.resolve_node()? {
|
if let Some(x) = self.resolve_node()? {
|
||||||
Some(x) => {
|
|
||||||
if self.offset + (x.len() as u16) > 32 * 1024 {
|
if self.offset + (x.len() as u16) > 32 * 1024 {
|
||||||
bail!(
|
bail!(
|
||||||
"Offset out of bounds: 0x{} > 0x8000",
|
"Offset out of bounds: 0x{} > 0x8000",
|
||||||
|
@ -393,8 +392,6 @@ impl Data {
|
||||||
self.offset += 1;
|
self.offset += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.program)
|
Ok(self.program)
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub fn parse(tokens: Vec<lexer::Token>) -> Result<ast::AST> {
|
||||||
iter.next();
|
iter.next();
|
||||||
|
|
||||||
body.push(ast::Node::MacroCall {
|
body.push(ast::Node::MacroCall {
|
||||||
name: (&x[1..]).to_string(),
|
name: x[1..].to_string(),
|
||||||
args: arg::parse_args(
|
args: arg::parse_args(
|
||||||
iter.by_ref()
|
iter.by_ref()
|
||||||
.take_while(|t| !matches!(t, lexer::Token::Newline(_)))
|
.take_while(|t| !matches!(t, lexer::Token::Newline(_)))
|
||||||
|
|
|
@ -2,7 +2,7 @@ use anyhow::{bail, Context, Result};
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use petgraph::Graph;
|
use petgraph::{graph::NodeIndex, Graph};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::parser;
|
use crate::parser;
|
||||||
|
@ -10,7 +10,7 @@ use crate::parser;
|
||||||
mod instruction;
|
mod instruction;
|
||||||
pub use crate::compiler::instruction::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! {
|
lazy_static! {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -30,14 +30,14 @@ pub struct Word {
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
pub instructions: Vec<Instruction>,
|
pub instructions: Vec<Instruction>,
|
||||||
pub times_used: usize,
|
pub times_used: usize,
|
||||||
pub callable_graph_node: petgraph::graph::NodeIndex,
|
pub callable_graph_node: NodeIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[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>,
|
||||||
pub callable_graph_node: petgraph::graph::NodeIndex,
|
pub callable_graph_node: NodeIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -48,8 +48,6 @@ pub enum CallableId {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
// pub words: HashMap<String, Word>,
|
|
||||||
// pub conditions: IndexSet<Condition>,
|
|
||||||
pub strings: IndexSet<String>,
|
pub strings: IndexSet<String>,
|
||||||
pub callable_graph: Graph<CallableId, ()>,
|
pub callable_graph: Graph<CallableId, ()>,
|
||||||
pub words: HashMap<String, Word>,
|
pub words: HashMap<String, Word>,
|
||||||
|
@ -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<Instruction>) -> Result<()> {
|
||||||
|
for instruction in ins {
|
||||||
|
self.add_graph_edge(origin, instruction)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generate_instructions(
|
pub fn generate_instructions(
|
||||||
&mut self,
|
&mut self,
|
||||||
body: parser::ast::Body,
|
body: parser::ast::Body,
|
||||||
|
@ -135,45 +172,29 @@ impl Data {
|
||||||
.get_mut(&name)
|
.get_mut(&name)
|
||||||
.context(format!("Could not get word: {}", name))?
|
.context(format!("Could not get word: {}", name))?
|
||||||
.instructions = ins.clone();
|
.instructions = ins.clone();
|
||||||
|
self.add_graph_edges(origin, ins)?;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
parser::ast::Node::Condition { if_body, else_body } => {
|
parser::ast::Node::Condition { if_body, else_body } => {
|
||||||
let if_instructions = self.generate_instructions(if_body, optimize)?;
|
let if_instructions = self.generate_instructions(if_body, optimize)?;
|
||||||
let else_instructions = self.generate_instructions(else_body, optimize)?;
|
let else_instructions = self.generate_instructions(else_body, optimize)?;
|
||||||
let id = self.conditions.len();
|
let id = self.conditions.len();
|
||||||
|
let origin = self.callable_graph.add_node(CallableId::Condition(id));
|
||||||
self.conditions.push(Condition {
|
self.conditions.push(Condition {
|
||||||
if_instructions,
|
if_instructions: if_instructions.clone(),
|
||||||
else_instructions,
|
else_instructions: else_instructions.clone(),
|
||||||
callable_graph_node: self
|
callable_graph_node: origin,
|
||||||
.callable_graph
|
|
||||||
.add_node(CallableId::Condition(id)),
|
|
||||||
});
|
});
|
||||||
instructions.push(Instruction::Condition(id));
|
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) => {
|
parser::ast::Node::Word(x) => {
|
||||||
if let Some(ins) = Instruction::from_word(&x) {
|
if let Some(ins) = Instruction::from_word(&x) {
|
||||||
instructions.push(ins);
|
instructions.push(ins);
|
||||||
} else if let Some(w) = self.words.get_mut(&x) {
|
} else if let Some(w) = self.words.get_mut(&x) {
|
||||||
instructions.push(Instruction::Call(x));
|
|
||||||
w.times_used += 1;
|
w.times_used += 1;
|
||||||
|
instructions.push(Instruction::Call(x));
|
||||||
} else {
|
} else {
|
||||||
bail!("Word does not exist: {}", x);
|
bail!("Word does not exist: {}", x);
|
||||||
}
|
}
|
||||||
|
@ -229,7 +250,7 @@ impl Data {
|
||||||
// .collect::<Result<Vec<hence::parser::ast::Body>>>()
|
// .collect::<Result<Vec<hence::parser::ast::Body>>>()
|
||||||
// .unwrap()
|
// .unwrap()
|
||||||
// .into_iter()
|
// .into_iter()
|
||||||
// .flatten(),
|
// .flatten()
|
||||||
// );
|
// );
|
||||||
// x.push(hence::parser::ast::Node::MacroCall {
|
// x.push(hence::parser::ast::Node::MacroCall {
|
||||||
// name: "return_call_stack_jump".to_string(),
|
// name: "return_call_stack_jump".to_string(),
|
||||||
|
|
Loading…
Reference in a new issue