diff options
| -rw-r--r-- | examples/test.nya | 7 | ||||
| -rw-r--r-- | examples/test1.gft | 3 | ||||
| -rw-r--r-- | src/codegen.zig | 114 | ||||
| -rw-r--r-- | src/main.zig | 3 | ||||
| -rw-r--r-- | src/parser.zig | 6 | ||||
| -rw-r--r-- | src/symtable.zig | 18 |
6 files changed, 90 insertions, 61 deletions
diff --git a/examples/test.nya b/examples/test.nya new file mode 100644 index 0000000..8e44c18 --- /dev/null +++ b/examples/test.nya @@ -0,0 +1,7 @@ +fn main() -> i32 { + var poggies = 120; + poggies = 5; + const poggers = poggies; + poggies = 0; + return poggies; +} diff --git a/examples/test1.gft b/examples/test1.gft deleted file mode 100644 index 1f4ac3b..0000000 --- a/examples/test1.gft +++ /dev/null @@ -1,3 +0,0 @@ -fn main() -> i32 { - return 7; -} diff --git a/src/codegen.zig b/src/codegen.zig index e2889a6..6dde45d 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -8,6 +8,7 @@ const target = llvm.target; const types = llvm.types; const CodegenError = error{ + Immutable, OutOfMemory, }; @@ -30,6 +31,7 @@ pub const Generator = struct { module: types.LLVMModuleRef, currentFunc: ?types.LLVMValueRef, currentFuncIsVoid: bool, + references: std.AutoHashMap(u32, types.LLVMValueRef), pub fn init(allocator: std.mem.Allocator, root: parse.NodeStmt) Generator { _ = target.LLVMInitializeNativeTarget(); @@ -48,6 +50,7 @@ pub const Generator = struct { .module = module, .currentFunc = null, .currentFuncIsVoid = false, + .references = std.AutoHashMap(u32, types.LLVMValueRef).init(allocator), }; } @@ -62,61 +65,63 @@ pub const Generator = struct { fn genExit(self: *Generator, exit: parse.NodeExit) !void { const expr = exit; - const val = core.LLVMConstInt(core.LLVMInt32Type(), switch (expr.kind) { - .intLit => |i| @intCast(i.intLit), - .ident => unreachable, - }, 0); + const val = self.genExpr(expr); _ = core.LLVMBuildRet(self.builder, val); } - fn genVar(self: *Generator, value: parse.NodeVar) !void { - const str = try std.fmt.allocPrint(self.allocator, - \\section .data - \\ {s}: dw {d} - \\ - , .{ value.ident.ident, switch (value.expr.kind) { - .intLit => |intlit| intlit.intLit, - else => return error.NotImplemented, - } }); - defer self.allocator.free(str); - try self.code.insertSlice(0, str); + fn genVar(self: *Generator, stmt: parse.NodeStmt) !void { + const nodeVar = stmt.kind.defVar; + + const table = stmt.symtable; + const symbol = table.getValue(nodeVar.ident.ident).?; + const value = self.genExpr(nodeVar.expr); + const ptr = try self.genAlloc(toLLVMtype(nodeVar.expr.typ.?, table).?, nodeVar.ident.ident); + _ = core.LLVMBuildStore(self.builder, value, ptr); + try self.references.put(symbol.id, ptr); + } + + fn genValue(self: *Generator, stmt: parse.NodeStmt) !void { + const nodeVar = stmt.kind.defValue; + + const table = stmt.symtable; + const symbol = table.getValue(nodeVar.ident.ident).?; + const ptr = try self.genAlloc(toLLVMtype(nodeVar.expr.typ.?, table), nodeVar.ident.ident); + const value = self.genExpr(nodeVar.expr); + _ = core.LLVMBuildStore(self.builder, value, ptr); + try self.references.put(symbol.id, ptr); } - fn genValue(self: *Generator, value: parse.NodeValue) !void { - const str = try std.fmt.allocPrint(self.allocator, - \\section .data - \\ {s}: dw {d} - \\ - , .{ value.ident.ident, switch (value.expr.kind) { - .intLit => |intlit| intlit.intLit, - else => return error.NotImplemented, - } }); - defer self.allocator.free(str); - try self.code.insertSlice(0, str); + fn genAlloc(self: *Generator, typ: types.LLVMTypeRef, ident: []const u8) !types.LLVMValueRef { + const builder = core.LLVMCreateBuilderInContext(self.context); + + const entryFunc = self.currentFunc.?; + const entry = core.LLVMGetFirstBasicBlock(entryFunc).?; + + if (core.LLVMGetFirstInstruction(entry)) |first| { + core.LLVMPositionBuilderBefore(builder, first); + } else { + core.LLVMPositionBuilderAtEnd(builder, entry); + } + + const str: [*:0]const u8 = try self.allocator.dupeZ(u8, ident); + return core.LLVMBuildAlloca(builder, typ, str); } - fn genAssign(self: *Generator, assign: parse.NodeAssign) !void { - const newCode = - switch (assign.expr.kind) { - .intLit => |intlit| try std.fmt.allocPrint(self.allocator, - \\ mov rax, {d} - \\ mov [{s}], rax - \\ - , .{ - intlit.intLit, - assign.ident.ident, - }), - .ident => |ident| try std.fmt.allocPrint(self.allocator, - \\ mov rax, [{s}] - \\ mov [{s}], rax - \\ - , .{ - ident.ident, - assign.ident.ident, - }), + fn asBasicType(typ: symb.SymbType) ?types.LLVMTypeKind { + return switch (typ) { + .Integer => types.LLVMTypeKind.LLVMIntegerTypeKind, + else => null, }; - try self.code.appendSlice(newCode); - self.allocator.free(newCode); + } + + fn genAssign(self: *Generator, stmt: parse.NodeStmt) !void { + std.debug.print("assign\n", .{}); + const table = stmt.symtable; + const symbol = table.get(stmt.kind.assignVar.ident.ident).?; + if (!symbol.Value.mut) return CodegenError.Immutable; + const ptr = self.references.get(symbol.Value.id).?; + const value = self.genExpr(stmt.kind.assignVar.expr); + _ = core.LLVMBuildStore(self.builder, value, ptr); } fn genBlock(self: *Generator, block: []const parse.NodeStmt) CodegenError!void { @@ -155,10 +160,25 @@ pub const Generator = struct { try switch (stmt.kind) { .exit => |expr| self.genExit(expr), .function => self.genFunc(stmt), + .defValue => self.genValue(stmt), + .defVar => self.genVar(stmt), + .assignVar => self.genAssign(stmt), else => {}, }; } + fn genExpr(self: *Generator, expr: parse.NodeExpr) types.LLVMValueRef { + return switch (expr.kind) { + .ident => blk: { + const table = expr.symtable; + const symbol = table.getValue(expr.kind.ident.ident).?; + const ptr = self.references.get(symbol.id).?; + break :blk core.LLVMBuildLoad2(self.builder, toLLVMtype(expr.typ.?, table), ptr, ""); + }, + .intLit => |int| core.LLVMConstInt(core.LLVMInt32TypeInContext(self.context), @intCast(int.intLit), 1), + }; + } + pub fn generate(self: *Generator) ![]const u8 { try switch (self.root.kind) { .block => |b| { diff --git a/src/main.zig b/src/main.zig index 248640b..d748461 100644 --- a/src/main.zig +++ b/src/main.zig @@ -53,8 +53,8 @@ pub fn main() !void { var parser = parse.Parser.init(allocator, tokens, symbTable); defer parser.deinit(); const tree = try parser.parse(); - var pop = symb.Populator.init(allocator); var treeNode = tree.asNode(); + var pop = symb.Populator.init(allocator); try pop.populateSymtable(&treeNode); // Codegen @@ -69,6 +69,7 @@ pub fn main() !void { const ldproc = try std.process.Child.run(.{ .argv = &ldargv, .allocator = allocator }); defer allocator.free(ldproc.stdout); defer allocator.free(ldproc.stderr); + std.debug.print("code: \n{s}", .{code}); } /// Get file extension based on filename diff --git a/src/parser.zig b/src/parser.zig index fa0acec..8cd539f 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -140,12 +140,8 @@ pub const Parser = struct { }, .ident => { const ident = (try self.tokens.consume(.ident)).?; - const symbType = if (self.top.get(ident.ident)) |sym| - sym.Type - else - return ParsingError.UnknownIdentifier; typ = TypeIdent{ - .ident = symbType.toString(), + .ident = "i32", .list = false, }; break :blk ExprKind{ .ident = ident }; diff --git a/src/symtable.zig b/src/symtable.zig index 72eecc7..f37ee12 100644 --- a/src/symtable.zig +++ b/src/symtable.zig @@ -159,8 +159,9 @@ pub const Populator = struct { switch (node.*) { .Stmt => |stmt| { const table: *SymbolTable = stmt.symtable; - try switch (stmt.kind) { + switch (stmt.kind) { .defVar => |variable| { + std.debug.print("Populated {s}\n", .{variable.ident.ident}); const symbol: Symbol = try self.buildValueSymb( table, if (variable.expr.typ) |typ| typ else pars.TypeIdent{ .ident = "i32", .list = false }, @@ -174,12 +175,17 @@ pub const Populator = struct { if (value.expr.typ) |typ| typ else pars.TypeIdent{ .ident = "i32", .list = false }, false, ); + std.debug.print("Populated {s}\n", .{value.ident.ident}); if (!try table.insert(value.ident.ident, symbol)) return error.FailedToInsert; }, .block => { const children = try stmt.children(self.allocator); defer self.allocator.free(children); - for (children) |child| try self.populateSymtable(&child); + std.debug.print("Populated Block\n", .{}); + for (children) |child| { + std.debug.print("Child: {d}\n", .{child.Stmt.id}); + try self.populateSymtable(&child); + } }, .function => |fun| { const symbol: Symbol = try self.buildFunctionSymb( @@ -187,12 +193,14 @@ pub const Populator = struct { fun.args, fun.retType, ); + std.debug.print("Populated Function {s}\n", .{fun.ident.ident}); if (!try table.insert(fun.ident.ident, symbol)) return error.FailedToInsert; + const children = try stmt.children(self.allocator); + for (children) |child| try self.populateSymtable(&child); }, - .exit => {}, - else => error.Unimplemented, - }; + else => {}, + } }, else => { for (try node.children(self.allocator)) |child| |
