summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen.zig28
-rw-r--r--src/parser.zig34
-rw-r--r--src/symtable.zig1
-rw-r--r--src/tokenize.zig4
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",