Skip to content

Commit

Permalink
Merge pull request #7 from hyouteki/reduce-ast
Browse files Browse the repository at this point in the history
Reduce ast
  • Loading branch information
hyouteki authored Aug 11, 2024
2 parents 8e042c2 + 0d65b0d commit 1a5038b
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 54 deletions.
17 changes: 0 additions & 17 deletions .gitlab-ci.yml

This file was deleted.

2 changes: 2 additions & 0 deletions eg/test.irl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ function fib, 1
a = t
i = i + 1
goto begin
d = 0
d = d + 1
// label hello
// ret 3
label end
Expand Down
33 changes: 33 additions & 0 deletions eg/test.irl.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
digraph "./eg/test.irl.dot" {
subgraph cluster_fib {
label="fib";
graph [style=filled];
fib_ENTRY [label="ENTRY"];
fib_EXIT [label="EXIT"];
fib_ENTRY -> fib_BB0;
fib_BB0 [shape=record label="[0]\n"];
fib_BB0 -> fib_BB1;
fib_BB1 [shape=record label="[1]\na = 0\lb = 1\li = 1\l"];
fib_BB1 -> fib_BB2;
fib_BB2 [shape=record label="[2 - begin]\n"];
fib_BB2 -> fib_BB3;
fib_BB2 -> fib_BB4;
fib_BB3 [shape=record label="[3 - end]\nret b\l"];
fib_BB3 -> fib_EXIT;
fib_BB4 [shape=record label="[4]\nt = b\lb = a + b\la = t\li = i + 1\l"];
fib_BB4 -> fib_BB2;
}

subgraph cluster_main {
label="main";
graph [style=filled];
main_ENTRY [label="ENTRY"];
main_EXIT [label="EXIT"];
main_ENTRY -> main_BB0;
main_BB0 [shape=record label="[0]\n"];
main_BB0 -> main_BB1;
main_BB1 [shape=record label="[1]\nparam 3\la = call fib, 1\lret a\l"];
main_BB1 -> main_EXIT;
}

}
23 changes: 23 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
use clap::{Arg, Command, ArgAction};

pub struct CliOptions {
pub filepath: String,
pub cfg: bool,
pub debug: bool,
pub verbose: bool,
}

impl CliOptions {
pub fn new() -> Self {
let match_result = cli().get_matches();
let compile_args = match_result.subcommand_matches("compile");
Self {
filepath: compile_args.unwrap().get_one::<String>("filepath").unwrap().to_string(),
cfg: *compile_args.unwrap().get_one::<bool>("cfg").unwrap(),
debug: *compile_args.unwrap().get_one::<bool>("debug").unwrap(),
verbose: *compile_args.unwrap().get_one::<bool>("verbose").unwrap(),
}
}
pub fn verbose_message(&self, message: String) {
if self.verbose {println!("{}: info: {}", self.filepath, message);}
}
}

pub fn cli() -> Command {
Command::new("irl")
.about("Intermediate Representation Language: Minimal implementation of LLVM")
Expand Down
80 changes: 76 additions & 4 deletions src/fe/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ pub struct IdenAstNode {
pub loc: Loc,
}

impl PartialEq for IdenAstNode {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}

impl IdenAstNode {
fn print(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.name)
Expand All @@ -25,6 +31,12 @@ pub struct NumAstNode {
pub loc: Loc,
}

impl PartialEq for NumAstNode {
fn eq(&self, other: &Self) -> bool {
self.num == other.num
}
}

impl NumAstNode {
fn print(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.num)
Expand All @@ -39,6 +51,12 @@ pub struct CallAstNode {
pub loc: Loc,
}

impl PartialEq for CallAstNode {
fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.params == other.params
}
}

impl CallAstNode {
fn print(&self, f: &mut std::fmt::Formatter, indent_sz: usize) -> std::fmt::Result {
for param in self.params.iter() {
Expand All @@ -50,7 +68,7 @@ impl CallAstNode {
}
}

#[derive(Clone)]
#[derive(Clone, PartialEq)]
pub enum ArithOp {
Sum, Sub, Mul, Div,
}
Expand Down Expand Up @@ -91,13 +109,19 @@ pub struct ArithAstNode {
pub loc: Loc,
}

impl PartialEq for ArithAstNode {
fn eq(&self, other: &Self) -> bool {
self.lhs == other.lhs && self.op == other.op && self.rhs == other.rhs
}
}

impl ArithAstNode {
fn print(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{} {} {}", self.lhs, self.op, self.rhs)
}
}

#[derive(Clone)]
#[derive(Clone, PartialEq)]
pub enum RelOp {
Eq, Neq, Gt, Lt, Ge, Le,
}
Expand Down Expand Up @@ -142,13 +166,19 @@ pub struct RelopAstNode {
pub loc: Loc,
}

impl PartialEq for RelopAstNode {
fn eq(&self, other: &Self) -> bool {
self.lhs == other.lhs && self.op == other.op && self.rhs == other.rhs
}
}

impl RelopAstNode {
fn print(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{} {} {}", self.lhs, self.op, self.rhs)
}
}

#[derive(Clone)]
#[derive(Clone, PartialEq)]
pub enum UnaryOp {
Neg,
}
Expand Down Expand Up @@ -180,6 +210,12 @@ pub struct UnaryAstNode {
pub loc: Loc,
}

impl PartialEq for UnaryAstNode {
fn eq(&self, other: &Self) -> bool {
self.var == other.var && self.op == other.op
}
}

impl UnaryAstNode {
fn print(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}{}", self.op, self.var)
Expand All @@ -194,6 +230,12 @@ pub struct FunctionAstNode {
pub loc: Loc,
}

impl PartialEq for FunctionAstNode {
fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.args == other.args && self.body == other.body
}
}

impl FunctionAstNode {
fn print(&self, f: &mut std::fmt::Formatter, indent_sz: usize) -> std::fmt::Result {
print_indent(f, indent_sz);
Expand All @@ -216,6 +258,12 @@ pub struct AssignmentAstNode {
pub loc: Loc,
}

impl PartialEq for AssignmentAstNode {
fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.var == other.var
}
}

impl AssignmentAstNode {
fn print(&self, f: &mut std::fmt::Formatter, indent_sz: usize) -> std::fmt::Result {
print_indent(f, indent_sz);
Expand All @@ -229,6 +277,12 @@ pub struct GotoAstNode {
pub loc: Loc,
}

impl PartialEq for GotoAstNode {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}

impl GotoAstNode {
fn print(&self, f: &mut std::fmt::Formatter, indent_sz: usize) -> std::fmt::Result {
print_indent(f, indent_sz);
Expand All @@ -243,6 +297,12 @@ pub struct LabelAstNode {
pub loc: Loc,
}

impl PartialEq for LabelAstNode {
fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.body == other.body
}
}

impl LabelAstNode {
fn print(&self, f: &mut std::fmt::Formatter, indent_sz: usize) -> std::fmt::Result {
print_indent(f, indent_sz);
Expand All @@ -261,6 +321,12 @@ pub struct IfAstNode {
pub loc: Loc,
}

impl PartialEq for IfAstNode {
fn eq(&self, other: &Self) -> bool {
self.condition == other.condition && self.label == other.label
}
}

impl IfAstNode {
fn print(&self, f: &mut std::fmt::Formatter, indent_sz: usize) -> std::fmt::Result {
print_indent(f, indent_sz);
Expand All @@ -274,6 +340,12 @@ pub struct RetAstNode {
pub loc: Loc,
}

impl PartialEq for RetAstNode {
fn eq(&self, other: &Self) -> bool {
self.var == other.var
}
}

impl RetAstNode {
fn print(&self, f: &mut std::fmt::Formatter, indent_sz: usize) -> std::fmt::Result {
print_indent(f, indent_sz);
Expand All @@ -299,7 +371,7 @@ pub fn value_join(v1: Value, v2: Value) -> Value {
}
}

#[derive(Clone)]
#[derive(Clone, PartialEq)]
pub enum AstNode {
Iden(IdenAstNode),
Num(NumAstNode),
Expand Down
5 changes: 3 additions & 2 deletions src/fe/loc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ impl Loc {
pub fn new(row: usize, col: usize, filepath: String) -> Self {
Self{row, col, filepath}
}

pub fn error(&self, message: String) {
eprintln!("{}: error: {}", self, message);
std::process::exit(1);
}

pub fn message(&self, message: String) {
eprintln!("{}: {}", self, message);
}
pub fn null() -> Self {
Self{row: 0, col: 0, filepath: String::from("")}
}
Expand Down
69 changes: 41 additions & 28 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::fe::{lexer::Lexer, parser::Parser};
use crate::fe::{lexer::Lexer, parser::Parser, ast::AstNode};
use crate::mw::default_ast_pass_manager::*;
use crate::opt::{default_compiler_pass_manager::*, cfg::*};
use crate::cli::cli;
use crate::cli::CliOptions;
use std::process::Command;

pub mod fe;
Expand All @@ -10,41 +10,54 @@ pub mod opt;
pub mod cli;

fn main() {
let match_result = cli().get_matches();
let compile_args = match_result.subcommand_matches("compile");
let filepath: String = compile_args.unwrap().get_one::<String>("filepath").unwrap().to_string();
let cfg: bool = *compile_args.unwrap().get_one::<bool>("cfg").unwrap();
let debug: bool = *compile_args.unwrap().get_one::<bool>("debug").unwrap();
let verbose: bool = *compile_args.unwrap().get_one::<bool>("verbose").unwrap();

let lexer = Lexer::new(filepath.clone());
let mut parser = Parser::new(lexer.tokens);
run_default_ast_pass_manager(&mut parser.nodes);
let options: CliOptions = CliOptions::new();

if debug {
for node in parser.nodes.iter() {
// module: fe
let lexer = Lexer::new(options.filepath.clone());
options.verbose_message(String::from("lexing complete"));
let parser = Parser::new(lexer.tokens);
options.verbose_message(String::from("parsing complete"));
let mut ast: Vec<AstNode> = parser.nodes;
if options.debug {
println!("Initial AST");
println!("===========");
for node in ast.iter() {
println!("{}", node);
}
}
options.verbose_message(String::from("FE over"));

let mut cfg_table: Vec<ControlFlowGraph> = cfg_table_from_program(&parser.nodes);

run_default_compiler_pass_manager(&mut cfg_table);
// module: mw
run_default_ast_pass_manager(&mut ast);
options.verbose_message(String::from("MW over"));
if options.debug {
println!("MW Optimized AST");
println!("===========");
for node in ast.iter() {
println!("{}", node);
}
}

if cfg {
let dot_filepath: String = format!("{}.dot", filepath.clone());
// module: opt
let mut cfg_table: Vec<ControlFlowGraph> = cfg_table_from_program(&ast);
run_default_compiler_pass_manager(&mut cfg_table);
if options.cfg {
let dot_filepath: String = format!("{}.dot", options.filepath.clone());
dump_cfg_table_to_svg(&cfg_table, dot_filepath.clone());
Command::new("dot").arg("-Tsvg").arg("-O").arg(dot_filepath.clone());
if verbose {
println!("info: created control flow graph svg '{}'", dot_filepath.clone());
}
options.verbose_message(format!("created control flow graph svg '{}'", dot_filepath));
}

if debug {
println!("converted AST");
for cfg in cfg_table.iter() {
println!("{}", cfg.generate_ast());
println!("");
options.verbose_message(format!("OPT over"));

ast.clear();
for cfg in cfg_table.iter() {
ast.push(cfg.generate_ast());
}
if options.debug {
println!("OPT Optimized AST");
println!("===========");
for node in ast.iter() {
println!("{}", node);
}
}
}
Loading

0 comments on commit 1a5038b

Please sign in to comment.