diff options
| author | Nic Gaffney <gaffney_nic@protonmail.com> | 2025-02-19 18:28:18 -0600 |
|---|---|---|
| committer | Nic Gaffney <gaffney_nic@protonmail.com> | 2025-02-19 18:28:18 -0600 |
| commit | 4ea2876e8243a86276917e691a335caed7a8fd74 (patch) | |
| tree | 79554a528e70d0a810692560f659ca6270a77f50 /src | |
| parent | fe851bcb542dac5f3af312da02ff617aa817f118 (diff) | |
| download | calico-4ea2876e8243a86276917e691a335caed7a8fd74.tar.gz | |
Added while loop
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen.zig | 28 | ||||
| -rw-r--r-- | src/parser.zig | 34 | ||||
| -rw-r--r-- | src/symtable.zig | 1 | ||||
| -rw-r--r-- | src/tokenize.zig | 4 |
4 files changed, 66 insertions, 1 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index 49a07fe..ef65cf6 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -190,6 +190,32 @@ pub const Generator = struct { } } + fn genWhile(self: *Generator, stmt: parse.NodeStmt) CodegenError!void { + const whilekind = stmt.kind.whileStmt; + const block = whilekind.body; + const expr = whilekind.expr; + + const condition = try self.genExpr(expr); + const func = self.currentFunc.?; + + const then = core.LLVMAppendBasicBlock(func, "then"); + const elsebb = core.LLVMAppendBasicBlock(func, "elsebb"); + const cont = core.LLVMAppendBasicBlock(func, "continue"); + + _ = core.LLVMBuildCondBr(self.builder, condition, then, elsebb); + + _ = core.LLVMPositionBuilderAtEnd(self.builder, then); + try self.genStmt(block.*); + const newcondition = try self.genExpr(expr); + _ = core.LLVMBuildCondBr(self.builder, newcondition, then, elsebb); + _ = core.LLVMBuildBr(self.builder, cont); + + _ = core.LLVMPositionBuilderAtEnd(self.builder, elsebb); + _ = core.LLVMBuildBr(self.builder, cont); + + _ = core.LLVMPositionBuilderAtEnd(self.builder, cont); + } + fn genIf(self: *Generator, stmt: parse.NodeStmt) CodegenError!void { const ifkind = stmt.kind.ifstmt; const block = ifkind.body; @@ -223,6 +249,7 @@ pub const Generator = struct { .defVar => self.genVar(stmt), .assignVar => self.genAssign(stmt), .ifstmt => self.genIf(stmt), + .whileStmt => self.genWhile(stmt), .block => |blk| self.genBlock(blk), .expr => |expression| { _ = try self.genExpr(expression); @@ -270,6 +297,7 @@ pub const Generator = struct { .star => core.LLVMBuildMul(self.builder, lhs, rhs, "mul"), .slash => core.LLVMBuildSDiv(self.builder, lhs, rhs, "div"), .eqleql => core.LLVMBuildICmp(self.builder, types.LLVMIntPredicate.LLVMIntEQ, lhs, rhs, "eql"), + .lessthan => core.LLVMBuildICmp(self.builder, types.LLVMIntPredicate.LLVMIntSLT, lhs, rhs, "slt"), else => return error.Unimplemented, }; }, diff --git a/src/parser.zig b/src/parser.zig index b1581bb..ebd4b33 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -109,6 +109,7 @@ pub const NodeStmt = struct { for (blockChildren) |child| try childrenArray.append(child); }, .ifstmt => |ifstmt| try childrenArray.append(ifstmt.body.*.asNode()), + .whileStmt => |whilestmt| try childrenArray.append(whilestmt.body.*.asNode()), .function => |fun| if (fun.block == null) {} else try childrenArray.append(fun.block.?.asNode()), .expr => |expr| try childrenArray.append(expr.asNode()), } @@ -254,7 +255,7 @@ pub const Parser = struct { const precTable: []const []const tok.TokenType = &.{ &.{ .plus, .minus }, &.{ .star, .slash }, - &.{.eqleql}, + &.{ .eqleql, .lessthan }, }; return try self.genBinOp(precTable[0], typ, lhsptr) //. @@ -293,6 +294,7 @@ pub const Parser = struct { fn parseStmt(self: *Parser) ParsingError!NodeStmt { return switch (self.tokens.peek().?) { .ifstmt => try self.parseIf(), + .whilestmt => try self.parseWhile(), .exit => try self.parseExit(), .constant => try self.parseConstant(), .variable => try self.parseVariable(), @@ -318,6 +320,29 @@ pub const Parser = struct { }; } + fn parseWhile(self: *Parser) ParsingError!NodeStmt { + _ = try self.tokens.consume(.whilestmt); // if + + _ = try self.tokens.consume(.openParen); // ( + const expr = try self.parseExpr(); // EXPR + _ = try self.tokens.consume(.closeParen); // ) + + const body = try self.allocator.create(NodeStmt); + body.* = try self.parseStmt(); + + const kind = StmtKind{ + .whileStmt = .{ + .expr = expr, + .body = body, + }, + }; + return NodeStmt{ + .id = self.reserveId(), + .kind = kind, + .symtable = self.top, + }; + } + fn parseIf(self: *Parser) ParsingError!NodeStmt { _ = try self.tokens.consume(.ifstmt); // if @@ -340,6 +365,7 @@ pub const Parser = struct { .symtable = self.top, }; } + fn parseFunc(self: *Parser, external: bool) ParsingError!NodeStmt { if (external) _ = try self.tokens.consume(.import); var typ: ?TypeIdent = null; @@ -582,6 +608,11 @@ pub const NodeIf = struct { body: *NodeStmt, }; +pub const NodeWhile = struct { + expr: NodeExpr, + body: *NodeStmt, +}; + pub const NodeExit = NodeExpr; pub const NodeIntlit = Token; pub const NodeStringlit = Token; @@ -596,6 +627,7 @@ pub const NodeCall = struct { pub const StmtKind = union(enum) { ifstmt: NodeIf, + whileStmt: NodeWhile, function: NodeFunction, exit: NodeExit, defValue: NodeValue, diff --git a/src/symtable.zig b/src/symtable.zig index fdbc536..f426ef8 100644 --- a/src/symtable.zig +++ b/src/symtable.zig @@ -233,6 +233,7 @@ pub const Populator = struct { .exit => |exit| _ = try exit.inferType(self.allocator, table), .expr => {}, .ifstmt => for (try stmt.children(self.allocator)) |c| try self.populateSymtable(&c), + .whileStmt => for (try stmt.children(self.allocator)) |c| try self.populateSymtable(&c), // else => |unim| return errorblk: { // std.debug.print("Error: Unimplemented: {any}\n", .{unim}); diff --git a/src/tokenize.zig b/src/tokenize.zig index 038a4d3..93d1f87 100644 --- a/src/tokenize.zig +++ b/src/tokenize.zig @@ -20,6 +20,7 @@ pub const TokenType = enum { exit, fun, import, + whilestmt, // Operators plus, minus, @@ -55,6 +56,7 @@ pub const Token = union(TokenType) { exit, fun, import, + whilestmt, // Operators plus, minus, @@ -109,6 +111,7 @@ pub const Token = union(TokenType) { if (eql(u8, str, "fn")) return .fun; if (eql(u8, str, "if")) return .ifstmt; if (eql(u8, str, "import")) return .import; + if (eql(u8, str, "while")) return .whilestmt; return Token{ .ident = str }; } @@ -124,6 +127,7 @@ pub const Token = union(TokenType) { .exit => "EXIT", .fun => "FUN", .import => "IMPORT", + .whilestmt => "WHILESTMT", .plus => "PLUS", .minus => "MINUS", .star => "STAR", |
