From 4f97a39f86823c1f4d20371a9068845540a98f9b Mon Sep 17 00:00:00 2001 From: Natapat Samutpong Date: Fri, 11 Feb 2022 21:22:10 +0700 Subject: [PATCH] feat: HIR instead of instructions --- example/hello_world.vy | 2 +- example/if.vy | 1 + src/front/parser.rs | 12 ++--- src/main.rs | 17 +++--- src/middle/gen.rs | 56 -------------------- src/middle/hir.rs | 116 +++++++++++++++++++++++++++++++++++++++++ src/middle/instr.rs | 18 ------- src/middle/mod.rs | 3 +- 8 files changed, 131 insertions(+), 94 deletions(-) create mode 100644 example/if.vy delete mode 100644 src/middle/gen.rs create mode 100644 src/middle/hir.rs delete mode 100644 src/middle/instr.rs diff --git a/example/hello_world.vy b/example/hello_world.vy index cb86a30..1e099b6 100644 --- a/example/hello_world.vy +++ b/example/hello_world.vy @@ -1,2 +1,2 @@ -(def message str "Hello, World") +(def message "Hello, World") (print message) \ No newline at end of file diff --git a/example/if.vy b/example/if.vy new file mode 100644 index 0000000..f7a5ebe --- /dev/null +++ b/example/if.vy @@ -0,0 +1 @@ +(if (equal 1 1) (print "a")) \ No newline at end of file diff --git a/src/front/parser.rs b/src/front/parser.rs index 5960f92..b45c0d6 100644 --- a/src/front/parser.rs +++ b/src/front/parser.rs @@ -20,12 +20,12 @@ pub enum Value { impl fmt::Display for Value { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Value::True => write!(f, "#t"), - Value::False => write!(f, "#f"), - Value::Int(i) => write!(f, "{}", i), - Value::Float(fl) => write!(f, "{}", fl), - Value::String(s) => write!(f, "{}", s), - Value::Symbol(s) => write!(f, "{}", s), + Value::True => write!(f, "$True"), + Value::False => write!(f, "$False"), + Value::Int(i) => write!(f, "${}", i), + Value::Float(fl) => write!(f, "${}", fl), + Value::String(s) => write!(f, "$\"{}\"", s), + Value::Symbol(s) => write!(f, "${}", s), Value::List(car, cdr) => { write!(f, "(")?; write!(f, "{}", car)?; diff --git a/src/main.rs b/src/main.rs index f468160..48a9cd7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,9 +12,9 @@ pub mod front; use front::parser::parse; /// A middle-end for the compiler. -/// Contains instructions generator. +/// Contains high intermediate representation (HIR). pub mod middle; -use middle::gen::generate_instructions; +use crate::middle::hir::to_hirs; fn main() { let args = Args::parse(); @@ -29,19 +29,14 @@ fn main() { let mut checked_tree = Vec::new(); for node in tree { match node { - Ok(node) => checked_tree.push(node), + Ok(node) => checked_tree.push(node.0), Err(err) => println!("{:?}", err), } }; - // Generate instructions - let instructions = generate_instructions(checked_tree.into_iter()); - - // Write instructions to file - let mut file = File::create(format!("{}.vyir" , input.file_stem().unwrap().to_str().unwrap())).unwrap(); - for instruction in instructions { - file.write_all(instruction.to_string().as_bytes()).expect("Failed to write instructions to file"); - } + // Convert the tree to HIR + let hir = to_hirs(&checked_tree); + println!("{:#?}", hir); }, } }, diff --git a/src/middle/gen.rs b/src/middle/gen.rs deleted file mode 100644 index 3f50ab4..0000000 --- a/src/middle/gen.rs +++ /dev/null @@ -1,56 +0,0 @@ -use std::borrow::Borrow; - -use crate::front::parser::Value; -use super::instr::Instructions; - -pub fn generate_instructions(ast: impl Iterator) -> Vec { - let mut instructions: Vec = Vec::new(); - for (value, _) in ast { - match value { - Value::List(car, cdr) => { - match &*car.borrow() { - Value::Symbol(ref function_name) => { - match function_name.as_str() { - "def" => { - let name: Box = match &cdr[0].borrow() { - Value::Symbol(name) => name.clone().into(), - _ => panic!("Expected symbol as first argument of define"), - }; - - match &cdr[1].borrow() { - Value::Int(value) => instructions.push(Instructions::Store { - value: Value::Int(*value), - name, - }), - Value::Float(value) => instructions.push(Instructions::Store { - value: Value::Float(*value), - name, - }), - Value::String(value) => instructions.push(Instructions::Store { - value: Value::String(value.clone()), - name, - }), - _ => todo!(), - }; - }, - _ => { - dbg!(function_name); - todo!(); - } - } // --- End match `function_name` --- - }, - _ => { - dbg!(car); - todo!(); - } - } // --- End match `car` --- - } - _ => { - dbg!(value); - todo!(); - } - } // --- End match `value` --- - } - - instructions -} \ No newline at end of file diff --git a/src/middle/hir.rs b/src/middle/hir.rs new file mode 100644 index 0000000..56bb513 --- /dev/null +++ b/src/middle/hir.rs @@ -0,0 +1,116 @@ +use std::{rc::Rc, borrow::Borrow}; + +use crate::front::parser::Value; + +#[derive(Debug, Clone)] +pub enum HIRLiteral { + True, False, Nil, + Int(i64), Float(f64), + String(String), Symbol(String), + List(Box, Vec), +} + +#[derive(Debug, Clone)] +pub enum HIR { + Declare { name: String, value: HIRLiteral }, + Set { name: String, value: HIRLiteral }, + Let { bindings: Vec<(String, HIR)>, body: Vec }, + If { condition: Box, then: Box, else_: Option> }, + Call { func: String, args: Rc> }, + + Quoted { body: HIRLiteral }, + Literal(HIRLiteral), +} + +pub fn to_hirs(ast: &Vec) -> Vec { + let mut hir = Vec::new(); + for node in ast { + match node { + Value::List(car, cdr) => { + match &*car.borrow() { + Value::Symbol(ref function) => { + match function.as_str() { + + "quote" => { + hir.push(HIR::Quoted { body: to_hir_literal(&cdr[0].clone()) }); + }, + + "if" => { + let cond = to_hir_single(&cdr[0].clone()); + let then = to_hir_single(&cdr[1].clone()); + let else_ = if cdr.len() > 2 { Some(Box::new(to_hir_single(&cdr[2].clone()))) } + else { None }; + + hir.push(HIR::If { condition: Box::new(cond), then: Box::new(then), else_ }); + } + + "def" => { + let name: String = match &cdr[0].clone() { + Value::Symbol(name) => name.clone(), + _ => panic!("def expects a symbol as first argument"), + }; + let value = &cdr[1].clone(); + + hir.push(HIR::Declare { name, value: to_hir_literal(value) }); + }, + + "print" => { + let value = &cdr[0].clone(); + + hir.push(HIR::Call { func: "print".to_string(), args: Rc::new(vec![to_hir_single(value)]) }); + }, + + "equal" => { + let left = &cdr[0].clone(); + let right = &cdr[1].clone(); + + hir.push(HIR::Call { func: "equal".to_string(), args: Rc::new(vec![to_hir_single(left), to_hir_single(right)]) }); + }, + + _ => { + dbg!(function); + todo!(); + } + } // --- End match `function` --- + }, + _ => { + dbg!(car); + todo!(); + } // --- End match `car` --- + } + }, + _ => hir.push(to_hir_single(node)), + } // --- End match `node` --- + } + hir +} + +fn to_hir_single(value: &Value) -> HIR { + match value { + Value::List(car, cdr) => { + let mut vec: Vec = Vec::new(); + let list: Value = Value::List(car.clone(), cdr.clone()); + vec.push(list); + let result = to_hirs(&vec)[0].clone(); + result + }, + _ => HIR::Literal(to_hir_literal(value)), + } +} + +fn to_hir_literal(value: &Value) -> HIRLiteral { + match value { + Value::True => HIRLiteral::True, + Value::False => HIRLiteral::False, + Value::Int(i) => HIRLiteral::Int(*i), + Value::Float(fl) => HIRLiteral::Float(*fl), + Value::String(s) => HIRLiteral::String(s.clone()), + Value::Symbol(s) => HIRLiteral::Symbol(s.clone()), + Value::List(car, cdr) => { + let car_literal = to_hir_literal(&car); + let cdr_literal = cdr.iter().map(|a| to_hir_literal(a)).collect::>(); + HIRLiteral::List(Box::new(car_literal), cdr_literal) + }, + Value::Nil => HIRLiteral::Nil, + } +} \ No newline at end of file diff --git a/src/middle/instr.rs b/src/middle/instr.rs deleted file mode 100644 index 2911922..0000000 --- a/src/middle/instr.rs +++ /dev/null @@ -1,18 +0,0 @@ -use std::fmt; - -use crate::front::parser::Value; - -#[derive(Debug)] -pub enum Instructions { - Store { value: Value, name: Box }, - Push { value: Value }, -} - -impl fmt::Display for Instructions { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Instructions::Store { value, name } => write!(f, "store {} {}", value, name), - Instructions::Push { value } => write!(f, "push {}", value), - } - } -} \ No newline at end of file diff --git a/src/middle/mod.rs b/src/middle/mod.rs index 35d35e8..9e3b3d7 100644 --- a/src/middle/mod.rs +++ b/src/middle/mod.rs @@ -1,2 +1 @@ -pub mod instr; -pub mod gen; \ No newline at end of file +pub mod hir; \ No newline at end of file