diff --git a/crates/codegen/src/cpp.rs b/crates/codegen/src/cpp.rs index c3d094b..4bb34a2 100644 --- a/crates/codegen/src/cpp.rs +++ b/crates/codegen/src/cpp.rs @@ -2,6 +2,12 @@ use std::fmt::Display; use hir::{IR, IRKind, Value}; +const MODULE_INCLUDES: [&str; 3] = [ + "", + "", + "", +]; + pub struct Codegen { pub emitted: String, } @@ -16,14 +22,12 @@ impl Codegen { } pub fn gen(&mut self, irs: Vec) { - self.emit("#include \n"); - self.emit("#include \n"); - self.emit("#include \n"); - self.emit("int main() {\n"); + for module in MODULE_INCLUDES { + self.emit(format!("#include {}\n", module)); + } for ir in irs { self.emit(&self.gen_ir(&ir.kind)); } - self.emit("}"); } fn gen_ir(&self, ir: &IRKind) -> String { @@ -38,6 +42,21 @@ impl Codegen { _ => format!("{}({});\n", name, args.iter().map(|arg| self.gen_ir(arg)).collect::>().join(", ")), } }, + IRKind::Fun { name, return_type_hint, args, body } => { + let args = args.iter().map(|arg| format!("{} {}", arg.1, arg.0)).collect::>().join(", "); + format!("{} {}({}) {{\n{}}}\n", return_type_hint, name, args, self.gen_ir(body)) + }, + IRKind::Return { value } => { + format!("return {};\n", self.gen_ir(value)) + }, + IRKind::Do { body } => { + let mut out = String::new(); + for expr in body { + out.push_str(&self.gen_ir(&expr)); + } + out + } + IRKind::Value { value } => { match value { Value::Int(value) => format!("{}", value), diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index aa4b886..915849e 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -9,10 +9,11 @@ pub enum IRKind { Define { name: String, type_hint: String, value: Box }, Fun { name: String, return_type_hint: String, args: Vec<(String, String)>, body: Box }, Call { name: String, args: Vec }, - Do { body: Box }, + Do { body: Vec }, If { cond: Box, body: Box, else_body: Box }, Value { value: Value }, Binary { op: String, left: Box, right: Box }, + Return { value: Box }, } #[derive(Debug)] @@ -51,6 +52,19 @@ pub fn expr_to_ir(expr: &Expr) -> IRKind { let args = args.0.iter().map(|arg| expr_to_ir(&arg.0)).collect::>(); IRKind::Call { name, args } }, + Expr::Fun { name, type_hint, args, body } => { + let args = args.0.iter().map(|arg| (arg.0.0.clone(), gen_type_hint(&arg.1.0))).collect::>(); + let body = expr_to_ir(&body.0); + IRKind::Fun { name: name.to_string(), return_type_hint: gen_type_hint(type_hint), args, body: Box::new(body) } + }, + Expr::Return { expr } => { + let expr = expr_to_ir(&expr.0); + IRKind::Return { value: Box::new(expr) } + }, + Expr::Do { body } => { + let body = body.iter().map(|expr| expr_to_ir(&expr.0)).collect::>(); + IRKind::Do { body } + }, Expr::Int(value) => IRKind::Value { value: Value::Int(*value) }, Expr::Boolean(value) => IRKind::Value { value: Value::Boolean(*value) }, diff --git a/example/ex.hades b/example/ex.hades index 64179f7..0c1c9a9 100644 --- a/example/ex.hades +++ b/example/ex.hades @@ -1,4 +1,4 @@ -let foo: int = 1; -let baz: bool = true; -let qux: string = "Hello, World"; -write(qux); \ No newline at end of file +fun main: int = do + write("Hello, World!\n"); + return 0; +end; \ No newline at end of file