diff --git a/examples/hello.ry b/examples/hello.ry index a8cfd08..35c51bc 100644 --- a/examples/hello.ry +++ b/examples/hello.ry @@ -1,16 +1,13 @@ // import std; -struct B { - field i32 +enum B { + a + b + c } -struct Awoo { - b B - other_field i32 -} - -fn test_function() Awoo { - return 1; +fn test_function() B { + return B.a; } fn multwo(num: i32, double_flag: bool) i32 { diff --git a/src/codegen.zig b/src/codegen.zig index 56837d4..c966043 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1,6 +1,8 @@ const std = @import("std"); const ast = @import("ast.zig"); const llvm = @import("llvm.zig"); +const comp = @import("comp_ctx.zig"); +const types = @import("types.zig"); fn sliceify(non_slice: ?[*]const u8) []const u8 { if (non_slice == null) return ""; @@ -13,19 +15,6 @@ pub const CompileError = error{ TypeError, }; -/// Does not account for custom types e.g structs, better type resolution -/// should be found -fn basicTypeToLLVM(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; - } -} - fn mkLLVMBool(val: bool) llvm.LLVMValueRef { if (val) { return llvm.LLVMConstInt(llvm.LLVMInt1Type(), 1, 1); @@ -36,9 +25,40 @@ fn mkLLVMBool(val: bool) llvm.LLVMValueRef { pub const Codegen = struct { allocator: *std.mem.Allocator, + ctx: *comp.CompilationContext, - pub fn init(allocator: *std.mem.Allocator) Codegen { - return Codegen{ .allocator = allocator }; + pub fn init(allocator: *std.mem.Allocator, ctx: *comp.CompilationContext) Codegen { + return Codegen{ .allocator = allocator, .ctx = ctx }; + } + + fn typeToLLVM(self: *@This(), typ: comp.SymbolUnderlyingType) !llvm.LLVMTypeRef { + return switch (typ) { + .Integer32 => llvm.LLVMInt32Type(), + .Integer64 => llvm.LLVMInt64Type(), + .Bool => llvm.LLVMInt1Type(), + + .OpaqueType => |val| { + std.debug.warn("Invalid return type: {}\n", val); + return CompileError.TypeError; + }, + + .Struct, .Enum => |lex| blk: { + var sym_data = self.ctx.symbol_table.get(lex).?.value; + break :blk switch (sym_data) { + .Struct => unreachable, + .Enum => llvm.LLVMInt32Type(), + else => { + std.debug.warn("Function {} is not a type\n", lex); + return CompileError.TypeError; + }, + }; + }, + + else => { + std.debug.warn("TODO handle {}\n", typ); + return CompileError.TypeError; + }, + }; } fn emitExpr(self: *Codegen, builder: var, expr: *const ast.Expr) anyerror!llvm.LLVMValueRef { @@ -191,16 +211,7 @@ pub const Codegen = struct { } } - fn emitBlock(self: *Codegen, builder: var, block: ast.Block) !llvm.LLVMValueRef { - var entry = llvm.LLVMAppendBasicBlock(func, entry_lbl_cstr.ptr); - - var builder = llvm.LLVMCreateBuilder(); - llvm.LLVMPositionBuilderAtEnd(builder, entry); - for (block.toSlice()) |stmt| { - try self.emitStmt(builder, &stmt); - } - } - + /// Emit LLVM ir for the given node. fn genNode( self: *Codegen, mod: llvm.LLVMModuleRef, @@ -210,21 +221,25 @@ pub const Codegen = struct { .Root => @panic("Should not have gotten Root"), .FnDecl => |decl| { const name = decl.func_name.lexeme; + + var fn_sym_search = self.ctx.symbol_table.get(name).?.value; + std.debug.assert(comp.SymbolType(fn_sym_search) == .Function); + var fn_sym = fn_sym_search.Function; + const name_cstr = try std.cstr.addNullByte(self.allocator, name); errdefer self.allocator.free(name_cstr); - 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 better type resolution - try param_types.append(try basicTypeToLLVM(param.typ.lexeme)); + try param_types.append(try self.typeToLLVM(fn_sym.parameters.get( + param.name.lexeme, + ).?.value)); } var llvm_ret_type = llvm.LLVMFunctionType( - try basicTypeToLLVM(fn_ret_type), + try self.typeToLLVM(fn_sym.return_type), param_types.toSlice().ptr, @intCast(c_uint, param_types.len), 0, @@ -257,7 +272,7 @@ pub const Codegen = struct { else => { std.debug.warn("TODO handle node type {}\n", @tagName(node.*)); - unreachable; + return; }, } } diff --git a/src/main.zig b/src/main.zig index 7f94c8a..517738b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -56,7 +56,7 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { std.debug.warn("symbol table\n"); printer.printContext(ctx); - var cgen = codegen.Codegen.init(allocator); + var cgen = codegen.Codegen.init(allocator, &ctx); try cgen.gen(root); return Result.Ok; diff --git a/src/types.zig b/src/types.zig index 609cf4d..661095b 100644 --- a/src/types.zig +++ b/src/types.zig @@ -149,7 +149,10 @@ pub const TypeSolver = struct { // TODO infer type of expr in const //.ConstDecl => {}, - else => unreachable, + else => { + std.debug.warn("TODO type analysis of {}\n", node.*); + return CompileError.TypeError; + }, } }