diff --git a/examples/hello.ry b/examples/hello.ry index 35c51bc..a8cfd08 100644 --- a/examples/hello.ry +++ b/examples/hello.ry @@ -1,13 +1,16 @@ // import std; -enum B { - a - b - c +struct B { + field i32 } -fn test_function() B { - return B.a; +struct Awoo { + b B + other_field i32 +} + +fn test_function() Awoo { + return 1; } fn multwo(num: i32, double_flag: bool) i32 { diff --git a/src/ast.zig b/src/ast.zig index ed5c56b..6663958 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -280,9 +280,6 @@ pub const Struct = struct { pub const Enum = struct { name: Token, - - // TODO allow custom values for the enum fields - // just like c enums can skip values fields: TokenList, }; diff --git a/src/ast_printer.zig b/src/ast_printer.zig index 423d448..f2e6076 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -351,7 +351,8 @@ fn prettyType(typ: SymbolUnderlyingType) []const u8 { .OpaqueType => |ident| retWithName("opaque", ident), .Struct => |ident| retWithName("struct", ident), - .Enum => |ident| retWithName("enum", ident), + + else => unreachable, }; } @@ -394,21 +395,7 @@ pub fn printContext(ctx: CompilationContext) void { kv.key, kv.value, ), - - .Enum => |identmap| { - std.debug.warn("enum {}:", kv.key); - - var mapit = identmap.iterator(); - - while (mapit.next()) |field_kv| { - std.debug.warn("\t{} => {}\n", field_kv.key, field_kv.value); - } - }, - - else => { - std.debug.warn("TODO handle print of {}\n", kv.value); - unreachable; - }, + else => unreachable, } } } diff --git a/src/codegen.zig b/src/codegen.zig index 236740b..56837d4 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1,8 +1,6 @@ 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 ""; @@ -15,6 +13,19 @@ 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); @@ -25,40 +36,9 @@ fn mkLLVMBool(val: bool) llvm.LLVMValueRef { pub const Codegen = struct { allocator: *std.mem.Allocator, - ctx: *comp.CompilationContext, - 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; - }, - }; + pub fn init(allocator: *std.mem.Allocator) Codegen { + return Codegen{ .allocator = allocator }; } fn emitExpr(self: *Codegen, builder: var, expr: *const ast.Expr) anyerror!llvm.LLVMValueRef { @@ -211,7 +191,16 @@ pub const Codegen = struct { } } - /// Emit LLVM ir for the given node. + 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); + } + } + fn genNode( self: *Codegen, mod: llvm.LLVMModuleRef, @@ -221,25 +210,21 @@ 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| { - try param_types.append(try self.typeToLLVM(fn_sym.parameters.get( - param.name.lexeme, - ).?.value)); + // TODO better type resolution + try param_types.append(try basicTypeToLLVM(param.typ.lexeme)); } var llvm_ret_type = llvm.LLVMFunctionType( - try self.typeToLLVM(fn_sym.return_type), + try basicTypeToLLVM(fn_ret_type), param_types.toSlice().ptr, @intCast(c_uint, param_types.len), 0, @@ -270,12 +255,9 @@ pub const Codegen = struct { std.debug.warn("cgen: generated function '{}'\n", name); }, - // NOTE: enums don't have specific llvm ir code generated for them - .Enum => {}, - else => { std.debug.warn("TODO handle node type {}\n", @tagName(node.*)); - return; + unreachable; }, } } diff --git a/src/comp_ctx.zig b/src/comp_ctx.zig index 12fc5d4..8914cfd 100644 --- a/src/comp_ctx.zig +++ b/src/comp_ctx.zig @@ -59,8 +59,8 @@ pub const FunctionSymbol = struct { // structs are hashmaps pointing to SymbolUnderlyingType pub const UnderlyingTypeMap = std.hash_map.StringHashMap(SymbolUnderlyingType); -// enums have maps from fields to u32s -pub const IdentifierMap = std.StringHashMap(u32); +// enums have lists of identifiers +pub const IdentifierList = std.ArrayList([]const u8); // TODO const pub const SymbolType = enum { @@ -73,7 +73,7 @@ pub const SymbolType = enum { pub const SymbolData = union(SymbolType) { Function: FunctionSymbol, Struct: UnderlyingTypeMap, - Enum: IdentifierMap, + Enum: IdentifierList, // variables (parameters and variables), for the type system // only have types @@ -161,18 +161,4 @@ pub const CompilationContext = struct { }, }); } - - pub fn insertEnum(self: *@This(), enu: ast.Enum) !void { - var ident_map = IdentifierMap.init(self.allocator); - errdefer ident_map.deinit(); - - // TODO change this when enums get support for custom values - for (enu.fields.toSlice()) |token, idx| { - _ = try ident_map.put(token.lexeme, @intCast(u32, idx)); - } - - _ = try self.symbol_table.put(enu.name.lexeme, SymbolData{ - .Enum = ident_map, - }); - } }; diff --git a/src/main.zig b/src/main.zig index 517738b..7f94c8a 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, &ctx); + var cgen = codegen.Codegen.init(allocator); try cgen.gen(root); return Result.Ok; diff --git a/src/types.zig b/src/types.zig index 951bdaf..609cf4d 100644 --- a/src/types.zig +++ b/src/types.zig @@ -143,18 +143,13 @@ pub const TypeSolver = struct { try ctx.insertStruct(struc, types); }, - // TODO change enums to u32 - .Enum => |enu| { - try ctx.insertEnum(enu); - }, + // TODO enums are u32 + //.Enum => {}, // TODO infer type of expr in const //.ConstDecl => {}, - else => { - std.debug.warn("TODO type analysis of {}\n", node.*); - return CompileError.TypeError; - }, + else => unreachable, } }