aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Lexer.zig20
-rw-r--r--src/codegen.zig8
-rw-r--r--src/compile.zig8
-rw-r--r--src/main.zig7
-rw-r--r--src/parse.zig35
5 files changed, 71 insertions, 7 deletions
diff --git a/src/Lexer.zig b/src/Lexer.zig
index c938116..4665379 100644
--- a/src/Lexer.zig
+++ b/src/Lexer.zig
@@ -16,6 +16,10 @@ pub const Token = struct {
invalid,
eof,
identifier,
+ left_angle,
+ right_angle,
+ left_angle_equal,
+ right_angle_equal,
// Keywords
let,
@@ -79,6 +83,14 @@ fn getNext(self: *Self) Token {
'+' => self.create(.plus),
'-' => self.create(.minus),
'=' => self.create(.equal),
+ '<' => if (self.eatIfEqual('='))
+ self.create(.left_angle_equal)
+ else
+ self.create(.left_angle),
+ '>' => if (self.eatIfEqual('='))
+ self.create(.right_angle_equal)
+ else
+ self.create(.right_angle),
'#' => {
while ((self.eatChar() orelse '\n') != '\n') {}
self.start = self.pos;
@@ -134,6 +146,14 @@ fn create(self: *Self, ty: Token.Type) Token {
return .{ .loc = .{ .start = start, .end = self.pos }, .type = ty };
}
+fn eatIfEqual(self: *Self, char: u8) bool {
+ if (self.peekChar() == char) {
+ _ = self.eatChar();
+ return true;
+ }
+ return false;
+}
+
fn eatChar(self: *Self) ?u8 {
const token = self.peekChar();
if (token != null) self.pos += 1;
diff --git a/src/codegen.zig b/src/codegen.zig
index 7ade3fd..701a4e8 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -642,6 +642,14 @@ const Context = struct {
switch (bin_op.op) {
.add => try self.emit(.add(reg, lhs, rhs)),
.sub => try self.emit(.sub(reg, lhs, rhs)),
+ .less_than => try self.emit(.sltu(reg, lhs, rhs)),
+ .greater_than => try self.emit(.sltu(reg, rhs, lhs)),
+ .less_or_equal, .greater_or_equal => {
+ const l, const r = if (bin_op.op == .less_or_equal) .{ lhs, rhs } else .{ rhs, lhs };
+
+ try self.emit(.sltu(reg, r, l));
+ try self.emit(.xori(reg, reg, 1));
+ },
}
}
diff --git a/src/compile.zig b/src/compile.zig
index 93f240b..583be50 100644
--- a/src/compile.zig
+++ b/src/compile.zig
@@ -63,6 +63,10 @@ pub const Instr = struct {
const Op = enum {
add,
sub,
+ less_than,
+ greater_than,
+ less_or_equal,
+ greater_or_equal,
};
pub fn sources(self: BinOp) Sources {
@@ -390,6 +394,10 @@ const CompileContext = struct {
.op = switch (binop.op) {
.plus => .add,
.minus => .sub,
+ .left_angle => .less_than,
+ .right_angle => .greater_than,
+ .left_angle_equal => .less_or_equal,
+ .right_angle_equal => .greater_or_equal,
},
},
},
diff --git a/src/main.zig b/src/main.zig
index 5eda854..367edf8 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -37,10 +37,11 @@ pub fn main() !void {
const source =
\\{
\\ let x = 10
- \\ let y = 5
- \\ while y {
+ \\ let y = 0
+ \\ print(x > y)
+ \\ while y < 3 {
\\ x = x + x
- \\ y = y - 1
+ \\ y = y + 1
\\ }
\\ if x {
\\ # let x = read_int(0)
diff --git a/src/parse.zig b/src/parse.zig
index e675fbe..efb5c8e 100644
--- a/src/parse.zig
+++ b/src/parse.zig
@@ -96,11 +96,19 @@ pub const Expr = struct {
const Op = enum {
plus,
minus,
+ left_angle,
+ right_angle,
+ left_angle_equal,
+ right_angle_equal,
pub fn format(self: Op, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
- try writer.writeByte(switch (self) {
- .plus => '+',
- .minus => '-',
+ try writer.writeAll(switch (self) {
+ .plus => "+",
+ .minus => "-",
+ .left_angle => "<",
+ .right_angle => ">",
+ .left_angle_equal => "<=",
+ .right_angle_equal => ">=",
});
}
};
@@ -210,7 +218,26 @@ pub fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt {
}
pub fn expression(allocator: Allocator, lexer: *Lexer) ParseError!*Expr {
- return parseTerms(allocator, lexer);
+ return parseComparisons(allocator, lexer);
+}
+
+pub fn parseComparisons(allocator: Allocator, lexer: *Lexer) ParseError!*Expr {
+ const lhs = try parseTerms(allocator, lexer);
+
+ const op: Expr.Type.BinOp.Op = switch (lexer.peek().type) {
+ .left_angle => .left_angle,
+ .right_angle => .right_angle,
+ .left_angle_equal => .left_angle_equal,
+ .right_angle_equal => .right_angle_equal,
+ else => return lhs,
+ };
+ _ = lexer.next();
+
+ const rhs = try parseTerms(allocator, lexer);
+ return try allocate(Expr, allocator, .{
+ .loc = lhs.loc.combine(rhs.loc),
+ .type = .{ .bin_op = .{ .lhs = lhs, .op = op, .rhs = rhs } },
+ });
}
pub fn parseTerms(allocator: Allocator, lexer: *Lexer) !*Expr {