diff --git a/src/chunk.zig b/src/chunk.zig index eb002d6..31985eb 100644 --- a/src/chunk.zig +++ b/src/chunk.zig @@ -20,6 +20,11 @@ const AllOpcodes = struct { pub False: u8 = 10, pub Not: u8 = 11, + + // comparison op codes! + pub Equal: u8 = 12, + pub Greater: u8 = 13, + pub Less: u8 = 14, }; pub const OpCode = AllOpcodes{}; diff --git a/src/compiler.zig b/src/compiler.zig index 5928b95..17b8a0b 100644 --- a/src/compiler.zig +++ b/src/compiler.zig @@ -77,16 +77,16 @@ var rules = []ParseRule{ // as the token enum says, those are 1/2 char tokens. ParseRule{ .prefix = Compiler.unary }, // this is specifically for the != operator - ParseRule{ .precedence = .Equality }, + ParseRule{ .infix = Compiler.binary, .precedence = .Equality }, ParseRule{}, // this is specifically for the == operator - ParseRule{ .precedence = .Equality }, + ParseRule{ .infix = Compiler.binary, .precedence = .Equality }, // all the comparison ones - ParseRule{ .precedence = .Comparison }, - ParseRule{ .precedence = .Comparison }, - ParseRule{ .precedence = .Comparison }, - ParseRule{ .precedence = .Comparison }, + ParseRule{ .infix = Compiler.binary, .precedence = .Comparison }, + ParseRule{ .infix = Compiler.binary, .precedence = .Comparison }, + ParseRule{ .infix = Compiler.binary, .precedence = .Comparison }, + ParseRule{ .infix = Compiler.binary, .precedence = .Comparison }, ParseRule{}, ParseRule{}, @@ -190,7 +190,7 @@ pub const Compiler = struct { try self.currentChunk().write(byte, self.parser.previous.line); } - fn emitBytes(self: *Compiler, byte1: u8, byte2: u82) !void { + fn emitBytes(self: *Compiler, byte1: u8, byte2: u8) !void { try self.emitByte(byte1); try self.emitByte(byte2); } @@ -251,6 +251,15 @@ pub const Compiler = struct { .MINUS => try self.emitByte(OpCode.Subtract), .STAR => try self.emitByte(OpCode.Multiply), .SLASH => try self.emitByte(OpCode.Divide), + + .EQUAL_EQUAL => try self.emitByte(OpCode.Equal), + .GREATER => try self.emitByte(OpCode.Greater), + .LESS => try self.emitByte(OpCode.Less), + + .BANG_EQUAL => try self.emitBytes(OpCode.Equal, OpCode.Not), + .GREATER_EQUAL => try self.emitBytes(OpCode.Less, OpCode.Not), + .LESS_EQUAL => try self.emitBytes(OpCode.Greater, OpCode.Not), + else => unreachable, } } diff --git a/src/vm.zig b/src/vm.zig index 5b89051..d712897 100644 --- a/src/vm.zig +++ b/src/vm.zig @@ -20,6 +20,16 @@ fn isFalsey(val: value.Value) bool { return val.vtype == .Nil or (val.vtype == .Bool and !val.as.Bool); } +fn valuesEqual(a: value.Value, b: value.Value) bool { + if (a.vtype != b.vtype) return false; + + switch (a.vtype) { + .Nil => return true, + .Bool => return a.as.Bool == b.as.Bool, + .Number => return a.as.Number == b.as.Number, + } +} + pub const VM = struct { chk: *Chunk = undefined, src: []const u8, @@ -170,6 +180,12 @@ pub const VM = struct { chunk.OpCode.True => try self.push(values.BoolVal(true)), chunk.OpCode.False => try self.push(values.BoolVal(false)), + chunk.OpCode.Equal => blk: { + var a = self.pop(); + var b = self.pop(); + try self.push(values.BoolVal(valuesEqual(a, b))); + }, + chunk.OpCode.Add => try self.doAdd(), chunk.OpCode.Subtract => try self.doSub(), chunk.OpCode.Multiply => try self.doMul(), @@ -177,6 +193,7 @@ pub const VM = struct { chunk.OpCode.Not => blk: { try self.push(values.BoolVal(isFalsey(self.pop()))); }, + chunk.OpCode.Negate => blk: { var val = self.peek(0); if (val.vtype != .Bool) {