mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
Compare commits
2 commits
ebaee0ea0c
...
a19f118510
Author | SHA1 | Date | |
---|---|---|---|
Natapat Samutpong | a19f118510 | ||
Natapat Samutpong | 2035dd115d |
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -8,3 +8,7 @@ target/
|
||||||
|
|
||||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
*.pdb
|
*.pdb
|
||||||
|
|
||||||
|
# Generated by the compiler
|
||||||
|
/*.cpp
|
||||||
|
/*.out
|
|
@ -4,7 +4,7 @@ Programming language that compiles to C++!
|
||||||
```sml
|
```sml
|
||||||
fun main: int = do
|
fun main: int = do
|
||||||
@write("Hello, World!\n");
|
@write("Hello, World!\n");
|
||||||
return 0;
|
return 69;
|
||||||
end;
|
end;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen(&mut self, irs: Vec<IR>) {
|
pub fn gen(&mut self, irs: Vec<IR>) {
|
||||||
|
self.emit(format!("// Auto-generated by hazure compiler version {}\n", env!("CARGO_PKG_VERSION")));
|
||||||
|
|
||||||
for module in MODULE_INCLUDES {
|
for module in MODULE_INCLUDES {
|
||||||
self.emit(format!("#include {}\n", module));
|
self.emit(format!("#include {}\n", module));
|
||||||
}
|
}
|
||||||
|
@ -47,7 +49,7 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
IRKind::Fun { name, return_type_hint, args, body } => {
|
IRKind::Fun { name, return_type_hint, args, body } => {
|
||||||
let args = args.iter().map(|arg| format!("{} {}", arg.1, arg.0)).collect::<Vec<_>>().join(", ");
|
let args = args.iter().map(|arg| format!("{} {}", arg.1, arg.0)).collect::<Vec<_>>().join(", ");
|
||||||
format!("{} {}({}) {{\n{}}}\n", return_type_hint, name, args, self.gen_ir(body))
|
format!("{} {}({}) {{\n{};\n}}\n", return_type_hint, name, args, self.gen_ir(body))
|
||||||
},
|
},
|
||||||
IRKind::Return { value } => {
|
IRKind::Return { value } => {
|
||||||
format!("return {};\n", self.gen_ir(value))
|
format!("return {};\n", self.gen_ir(value))
|
||||||
|
@ -62,6 +64,12 @@ impl Codegen {
|
||||||
IRKind::If { cond, body, else_body } => {
|
IRKind::If { cond, body, else_body } => {
|
||||||
format!("if ({}) {{\n{}}} else {{\n{}}}\n", self.gen_ir(cond), self.gen_ir(body), self.gen_ir(else_body))
|
format!("if ({}) {{\n{}}} else {{\n{}}}\n", self.gen_ir(cond), self.gen_ir(body), self.gen_ir(else_body))
|
||||||
},
|
},
|
||||||
|
IRKind::Unary { op, right } => {
|
||||||
|
format!("{}{}", op, self.gen_ir(right))
|
||||||
|
},
|
||||||
|
IRKind::Binary { left, op, right } => {
|
||||||
|
format!("{} {} {}", self.gen_ir(left), op, self.gen_ir(right))
|
||||||
|
},
|
||||||
|
|
||||||
IRKind::Value { value } => {
|
IRKind::Value { value } => {
|
||||||
match value {
|
match value {
|
||||||
|
@ -71,6 +79,8 @@ impl Codegen {
|
||||||
Value::Ident(value) => format!("{}", value),
|
Value::Ident(value) => format!("{}", value),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
_ => { dbg!(ir); todo!() },
|
_ => { dbg!(ir); todo!() },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,9 @@ pub enum IRKind {
|
||||||
Intrinsic { name: String, args: Vec<Self> },
|
Intrinsic { name: String, args: Vec<Self> },
|
||||||
Do { body: Vec<Self> },
|
Do { body: Vec<Self> },
|
||||||
If { cond: Box<Self>, body: Box<Self>, else_body: Box<Self> },
|
If { cond: Box<Self>, body: Box<Self>, else_body: Box<Self> },
|
||||||
Value { value: Value },
|
Unary { op: String, right: Box<Self> },
|
||||||
Binary { op: String, left: Box<Self>, right: Box<Self> },
|
Binary { op: String, left: Box<Self>, right: Box<Self> },
|
||||||
|
Value { value: Value },
|
||||||
Return { value: Box<Self> },
|
Return { value: Box<Self> },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,23 +61,26 @@ macro_rules! if_err_return {
|
||||||
|
|
||||||
pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
|
pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Let { name, type_hint, value } => {
|
Expr::Unary { op, rhs } => {
|
||||||
let value = expr_to_ir(&value.0);
|
let rhs_ir = expr_to_ir(&rhs.0);
|
||||||
if_err_return!(value.1);
|
if_err_return!(rhs_ir.1);
|
||||||
|
|
||||||
let value = value.0.unwrap();
|
return (Some(IRKind::Unary { op: op.to_string(), right: Box::new(rhs_ir.0.unwrap()) }), None);
|
||||||
let ir_kind = IRKind::Define { name: name.clone(), type_hint: type_hint.clone(), value: Box::new(value) };
|
}
|
||||||
return (Some(ir_kind), None);
|
|
||||||
|
Expr::Binary { lhs, op, rhs } => {
|
||||||
|
let lhs_ir = expr_to_ir(&lhs.0);
|
||||||
|
if_err_return!(lhs_ir.1);
|
||||||
|
|
||||||
|
let rhs_ir = expr_to_ir(&rhs.0);
|
||||||
|
if_err_return!(rhs_ir.1);
|
||||||
|
|
||||||
|
return (Some(IRKind::Binary { op: op.to_string(), left: Box::new(lhs_ir.0.unwrap()), right: Box::new(rhs_ir.0.unwrap()) }), None)
|
||||||
},
|
},
|
||||||
|
|
||||||
Expr::Call { name, args } => {
|
Expr::Call { name, args } => {
|
||||||
let name = match &name.0 {
|
let name = match &name.0 {
|
||||||
Expr::Identifier(s) => {
|
Expr::Identifier(s) => s.clone(),
|
||||||
if INTRINSICS.contains(&s.as_str()) { s.clone() }
|
|
||||||
else {
|
|
||||||
return (None, Some(LoweringError { span: name.1.clone(), message: format!("Unknown intrinsic: {}", s) }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Should never happen because the parser should have caught this
|
// Should never happen because the parser should have caught this
|
||||||
_ => return (None, Some(LoweringError { span: name.1.clone(), message: "Expected identifier".to_string() }))
|
_ => return (None, Some(LoweringError { span: name.1.clone(), message: "Expected identifier".to_string() }))
|
||||||
};
|
};
|
||||||
|
@ -92,9 +96,23 @@ pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
|
||||||
return (Some(ir_kind), None);
|
return (Some(ir_kind), None);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Expr::Let { name, type_hint, value } => {
|
||||||
|
let value = expr_to_ir(&value.0);
|
||||||
|
if_err_return!(value.1);
|
||||||
|
|
||||||
|
let value = value.0.unwrap();
|
||||||
|
let ir_kind = IRKind::Define { name: name.clone(), type_hint: type_hint.clone(), value: Box::new(value) };
|
||||||
|
return (Some(ir_kind), None);
|
||||||
|
},
|
||||||
|
|
||||||
Expr::Intrinsic { name, args } => {
|
Expr::Intrinsic { name, args } => {
|
||||||
let name = match &name.0 {
|
let name = match &name.0 {
|
||||||
Expr::Identifier(s) => s.clone(),
|
Expr::Identifier(s) => {
|
||||||
|
if INTRINSICS.contains(&s.as_str()) { s.clone() }
|
||||||
|
else {
|
||||||
|
return (None, Some(LoweringError { span: name.1.clone(), message: format!("Unknown intrinsic: {}", s) }));
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => return (None, Some(LoweringError { span: name.1.clone(), message: "Expected identifier".to_string() }))
|
_ => return (None, Some(LoweringError { span: name.1.clone(), message: "Expected identifier".to_string() }))
|
||||||
};
|
};
|
||||||
let mut largs = Vec::new();
|
let mut largs = Vec::new();
|
||||||
|
|
14
example/69.hz
Normal file
14
example/69.hz
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
fun add2 (lhs: int) (rhs: int): int = do
|
||||||
|
return lhs + rhs;
|
||||||
|
end;
|
||||||
|
|
||||||
|
fun main: int = do
|
||||||
|
let result: int = add2(34, 35);
|
||||||
|
@write(result);
|
||||||
|
@write("\n");
|
||||||
|
if result == 69 then
|
||||||
|
@write("big cool")
|
||||||
|
else
|
||||||
|
@write("not cool")
|
||||||
|
end;
|
||||||
|
end;
|
|
@ -1,4 +0,0 @@
|
||||||
fun main: int = do
|
|
||||||
@write("Hello, World!\n");
|
|
||||||
return 0;
|
|
||||||
end;
|
|
4
example/hello_world.hz
Normal file
4
example/hello_world.hz
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
fun main: int = do
|
||||||
|
@writesss("Hello, World!\n");
|
||||||
|
return 69;
|
||||||
|
end;
|
Loading…
Reference in a new issue