1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-09-28 07:17:41 +00:00

feat: HIR instead of instructions

This commit is contained in:
Natapat Samutpong 2022-02-11 21:22:10 +07:00
parent cb0efd3dd4
commit 4f97a39f86
8 changed files with 131 additions and 94 deletions

View file

@ -1,2 +1,2 @@
(def message str "Hello, World") (def message "Hello, World")
(print message) (print message)

1
example/if.vy Normal file
View file

@ -0,0 +1 @@
(if (equal 1 1) (print "a"))

View file

@ -20,12 +20,12 @@ pub enum Value {
impl fmt::Display for Value { impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
Value::True => write!(f, "#t"), Value::True => write!(f, "$True"),
Value::False => write!(f, "#f"), Value::False => write!(f, "$False"),
Value::Int(i) => write!(f, "{}", i), Value::Int(i) => write!(f, "${}", i),
Value::Float(fl) => write!(f, "{}", fl), Value::Float(fl) => write!(f, "${}", fl),
Value::String(s) => write!(f, "{}", s), Value::String(s) => write!(f, "$\"{}\"", s),
Value::Symbol(s) => write!(f, "{}", s), Value::Symbol(s) => write!(f, "${}", s),
Value::List(car, cdr) => { Value::List(car, cdr) => {
write!(f, "(")?; write!(f, "(")?;
write!(f, "{}", car)?; write!(f, "{}", car)?;

View file

@ -12,9 +12,9 @@ pub mod front;
use front::parser::parse; use front::parser::parse;
/// A middle-end for the compiler. /// A middle-end for the compiler.
/// Contains instructions generator. /// Contains high intermediate representation (HIR).
pub mod middle; pub mod middle;
use middle::gen::generate_instructions; use crate::middle::hir::to_hirs;
fn main() { fn main() {
let args = Args::parse(); let args = Args::parse();
@ -29,19 +29,14 @@ fn main() {
let mut checked_tree = Vec::new(); let mut checked_tree = Vec::new();
for node in tree { for node in tree {
match node { match node {
Ok(node) => checked_tree.push(node), Ok(node) => checked_tree.push(node.0),
Err(err) => println!("{:?}", err), Err(err) => println!("{:?}", err),
} }
}; };
// Generate instructions // Convert the tree to HIR
let instructions = generate_instructions(checked_tree.into_iter()); let hir = to_hirs(&checked_tree);
println!("{:#?}", hir);
// 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");
}
}, },
} }
}, },

View file

@ -1,56 +0,0 @@
use std::borrow::Borrow;
use crate::front::parser::Value;
use super::instr::Instructions;
pub fn generate_instructions(ast: impl Iterator<Item = (Value, (usize, usize))>) -> Vec<Instructions> {
let mut instructions: Vec<Instructions> = 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<str> = 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
}

116
src/middle/hir.rs Normal file
View file

@ -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<HIRLiteral>, Vec<HIRLiteral>),
}
#[derive(Debug, Clone)]
pub enum HIR {
Declare { name: String, value: HIRLiteral },
Set { name: String, value: HIRLiteral },
Let { bindings: Vec<(String, HIR)>, body: Vec<HIR> },
If { condition: Box<HIR>, then: Box<HIR>, else_: Option<Box<HIR>> },
Call { func: String, args: Rc<Vec<HIR>> },
Quoted { body: HIRLiteral },
Literal(HIRLiteral),
}
pub fn to_hirs(ast: &Vec<Value>) -> Vec<HIR> {
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<Value> = 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::<Vec<HIRLiteral>>();
HIRLiteral::List(Box::new(car_literal), cdr_literal)
},
Value::Nil => HIRLiteral::Nil,
}
}

View file

@ -1,18 +0,0 @@
use std::fmt;
use crate::front::parser::Value;
#[derive(Debug)]
pub enum Instructions {
Store { value: Value, name: Box<str> },
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),
}
}
}

View file

@ -1,2 +1 @@
pub mod instr; pub mod hir;
pub mod gen;