diff --git a/README.md b/README.md index a6a3b13..43296e4 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Programming language that compiles to C++! ```sml fun main: int = do @write("Hello, World!\n"); - return 0; + return 69; end; ``` diff --git a/crates/codegen/src/cpp.rs b/crates/codegen/src/cpp.rs index 4b08b15..6778a88 100644 --- a/crates/codegen/src/cpp.rs +++ b/crates/codegen/src/cpp.rs @@ -47,7 +47,7 @@ impl Codegen { } 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)) + format!("{} {}({}) {{\n{};\n}}\n", return_type_hint, name, args, self.gen_ir(body)) }, IRKind::Return { value } => { format!("return {};\n", self.gen_ir(value)) @@ -62,6 +62,12 @@ impl Codegen { 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)) }, + 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 } => { match value { @@ -71,6 +77,8 @@ impl Codegen { Value::Ident(value) => format!("{}", value), } }, + + #[allow(unreachable_patterns)] _ => { dbg!(ir); todo!() }, } } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index cf8db3a..a8e8c07 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -14,8 +14,9 @@ pub enum IRKind { Intrinsic { name: String, args: Vec }, Do { body: Vec }, If { cond: Box, body: Box, else_body: Box }, - Value { value: Value }, + Unary { op: String, right: Box }, Binary { op: String, left: Box, right: Box }, + Value { value: Value }, Return { value: Box }, } @@ -60,23 +61,26 @@ macro_rules! if_err_return { pub fn expr_to_ir(expr: &Expr) -> (Option, Option) { match expr { - Expr::Let { name, type_hint, value } => { - let value = expr_to_ir(&value.0); - if_err_return!(value.1); + Expr::Unary { op, rhs } => { + let rhs_ir = expr_to_ir(&rhs.0); + if_err_return!(rhs_ir.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); + return (Some(IRKind::Unary { op: op.to_string(), right: Box::new(rhs_ir.0.unwrap()) }), 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 } => { let name = match &name.0 { - 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) })); - } - } + Expr::Identifier(s) => s.clone(), // Should never happen because the parser should have caught this _ => 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, Option) { 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 } => { 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() })) }; let mut largs = Vec::new(); diff --git a/example/69.hz b/example/69.hz new file mode 100644 index 0000000..0602656 --- /dev/null +++ b/example/69.hz @@ -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; diff --git a/example/ex.hz b/example/ex.hz deleted file mode 100644 index 2f63cc1..0000000 --- a/example/ex.hz +++ /dev/null @@ -1,4 +0,0 @@ -fun main: int = do - @write("Hello, World!\n"); - return 0; -end; \ No newline at end of file diff --git a/example/hello_world.hz b/example/hello_world.hz new file mode 100644 index 0000000..83fef3f --- /dev/null +++ b/example/hello_world.hz @@ -0,0 +1,4 @@ +fun main: int = do + @writesss("Hello, World!\n"); + return 69; +end; \ No newline at end of file