diff --git a/examples/hello.ry b/examples/hello.ry index debd7e6..a5ec0cf 100644 --- a/examples/hello.ry +++ b/examples/hello.ry @@ -1,7 +1,11 @@ // import std; fn add() i32 { - return 1 + 1; + return 69 + 69; +} + +fn and_fn() bool { + return true and false; } // type is void by default diff --git a/src/ast.zig b/src/ast.zig index 9b432d7..6663958 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -80,13 +80,6 @@ pub const UnaryExpr = struct { right: *Expr, }; -// looks like a BinaryExpr, but is not a BinaryExpr -pub const LogicalExpr = struct { - left: *Expr, - op: Token, - right: *Expr, -}; - pub const LiteralExpr = union(enum) { Bool: bool, Integer: []const u8, @@ -108,7 +101,6 @@ pub const ExprType = enum { Binary, Unary, - Logical, Literal, Variable, Call, @@ -159,7 +151,6 @@ pub const Expr = union(ExprType) { Binary: BinaryExpr, Unary: UnaryExpr, - Logical: LogicalExpr, Literal: LiteralExpr, Struct: StructExpr, diff --git a/src/ast_printer.zig b/src/ast_printer.zig index ee9fb61..4f9ced9 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -184,12 +184,8 @@ fn binOpToStr(op: BinaryOperator) ?[]const u8 { return null; } -fn printBinOp(inner: var, comptime is_binop: bool) void { - if (is_binop) { - std.debug.warn("({}", binOpToStr(inner.op)); - } else { - std.debug.warn("({}", inner.op.lexeme); - } +fn printBinOp(inner: var) void { + std.debug.warn("({}", binOpToStr(inner.op)); printTwoExprs(inner.left, inner.right); std.debug.warn(")"); } @@ -202,8 +198,7 @@ fn printSingleOp(tok: []const u8, applied: *const Expr) void { pub fn printExpr(expr: *const Expr) void { switch (expr.*) { - .Binary => |binary| printBinOp(binary, true), - .Logical => |logical| printBinOp(logical, false), + .Binary => |binary| printBinOp(binary), .Unary => |unary| printSingleOp(unary.op.lexeme, unary.right), .Grouping => |expr_ptr| printSingleOp("group", expr_ptr), diff --git a/src/codegen.zig b/src/codegen.zig index b5a2e45..ae306fa 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -10,8 +10,20 @@ fn sliceify(non_slice: ?[*]const u8) []const u8 { pub const CompileError = error{ LLVMError, EmitError, + TypeError, }; +fn retTypeToLLVM(ret_type: []const u8) !llvm.LLVMTypeRef { + if (std.mem.eql(u8, ret_type, "i32")) { + return llvm.LLVMInt32Type(); + } else if (std.mem.eql(u8, ret_type, "bool")) { + return llvm.LLVMInt1Type(); + } else { + std.debug.warn("Invalid return type: {}\n", ret_type); + return CompileError.TypeError; + } +} + pub const Codegen = struct { allocator: *std.mem.Allocator, @@ -41,9 +53,17 @@ pub const Codegen = struct { var val_cstr = try std.cstr.addNullByte(self.allocator, val); break :blk2 llvm.LLVMConstRealOfString(llvm.LLVMDoubleType(), val_cstr.ptr); }, + .Bool => |val| blk2: { + if (val) { + break :blk2 llvm.LLVMConstInt(llvm.LLVMInt1Type(), 1, 1); + } else { + break :blk2 llvm.LLVMConstInt(llvm.LLVMInt1Type(), 0, 1); + } + }, else => unreachable, }; }, + .Binary => |binary| { var left = try self.emitExpr(builder, binary.left); var right = try self.emitExpr(builder, binary.right); @@ -54,6 +74,8 @@ pub const Codegen = struct { .Mul => llvm.LLVMBuildMul(builder, left, right, c"multmp"), //.Div => llvm.LLVMBuildDiv(builder, left, right, c"divtmp"), + .And => llvm.LLVMBuildAnd(builder, left, right, c"andtmp"), + .Or => llvm.LLVMBuildOr(builder, left, right, c"ortmp"), else => { std.debug.warn("Unexpected binary operator: '{}'\n", binary.op); @@ -96,23 +118,24 @@ pub const Codegen = struct { const name_cstr = try std.cstr.addNullByte(self.allocator, name); errdefer self.allocator.free(name_cstr); - //const ret_type = decl.return_type.lexeme; + const fn_ret_type = decl.return_type.lexeme; var param_types = llvm.LLVMTypeList.init(self.allocator); errdefer param_types.deinit(); for (decl.params.toSlice()) |param| { + // TODO solve type with cute enums etc try param_types.append(llvm.LLVMInt32Type()); } - var ret_type = llvm.LLVMFunctionType( - llvm.LLVMInt32Type(), + var llvm_ret_type = llvm.LLVMFunctionType( + try retTypeToLLVM(fn_ret_type), param_types.toSlice().ptr, @intCast(c_uint, param_types.len), 0, ); - var func = llvm.LLVMAddFunction(mod, name_cstr.ptr, ret_type); + var func = llvm.LLVMAddFunction(mod, name_cstr.ptr, llvm_ret_type); var entry = llvm.LLVMAppendBasicBlock(func, c"entry"); var builder = llvm.LLVMCreateBuilder(); diff --git a/src/parsers.zig b/src/parsers.zig index b2156e6..0a192e1 100644 --- a/src/parsers.zig +++ b/src/parsers.zig @@ -267,19 +267,6 @@ pub const Parser = struct { return expr; } - fn mkLogical(self: *Parser, left: *Expr, op: Token, right: *Expr) !*Expr { - var expr = try self.allocator.create(Expr); - expr.* = Expr{ - .Logical = ast.LogicalExpr{ - .left = left, - .op = op, - .right = right, - }, - }; - - return expr; - } - fn mkAssign(self: *Parser, name: Token, value: *Expr) !*Expr { var expr = try self.allocator.create(Expr); expr.* = Expr{ @@ -934,7 +921,7 @@ pub const Parser = struct { _ = try self.nextToken(); var right = try self.parseAnd(); - expr = try self.mkLogical(expr, op, right); + expr = try self.mkBinary(expr, try toBinaryOperator(op), right); } return expr; @@ -948,7 +935,7 @@ pub const Parser = struct { _ = try self.nextToken(); var right = try self.parseEquality(); - expr = try self.mkLogical(expr, op, right); + expr = try self.mkBinary(expr, try toBinaryOperator(op), right); } return expr; diff --git a/src/scanners.zig b/src/scanners.zig index ced1da8..5271235 100644 --- a/src/scanners.zig +++ b/src/scanners.zig @@ -52,6 +52,8 @@ const keywords = [_][]const u8{ "println", "loop", "pub", + "and", + "or", }; const keyword_ttypes = [_]TokenType{ @@ -82,6 +84,8 @@ const keyword_ttypes = [_]TokenType{ .Println, .Loop, .Pub, + .And, + .Or, }; fn getKeyword(keyword: []const u8) ?TokenType {