mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
feat: HIR instead of instructions
This commit is contained in:
parent
cb0efd3dd4
commit
4f97a39f86
|
@ -1,2 +1,2 @@
|
||||||
(def message str "Hello, World")
|
(def message "Hello, World")
|
||||||
(print message)
|
(print message)
|
1
example/if.vy
Normal file
1
example/if.vy
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(if (equal 1 1) (print "a"))
|
|
@ -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)?;
|
||||||
|
|
17
src/main.rs
17
src/main.rs
|
@ -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");
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
116
src/middle/hir.rs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
|
@ -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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +1 @@
|
||||||
pub mod instr;
|
pub mod hir;
|
||||||
pub mod gen;
|
|
Loading…
Reference in a new issue