From 9ac5fccc2b71aea8fc8a2703dbf0e0ed72bb7449 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 2 Jun 2019 14:01:54 -0300 Subject: [PATCH] add objects and string comparison --- src/compiler.zig | 10 +++++++++- src/object.zig | 34 ++++++++++++++++++++++++++++++++++ src/value.zig | 14 ++++++++++++-- src/vm.zig | 5 +++++ 4 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 src/object.zig diff --git a/src/compiler.zig b/src/compiler.zig index 7b75e0e..2aaff70 100644 --- a/src/compiler.zig +++ b/src/compiler.zig @@ -4,6 +4,7 @@ const vm = @import("vm.zig"); const chunks = @import("chunk.zig"); const tokens = @import("token.zig"); const values = @import("value.zig"); +const objects = @import("object.zig"); const Allocator = std.mem.Allocator; const Scanner = scanner.Scanner; @@ -89,7 +90,7 @@ var rules = []ParseRule{ ParseRule{ .infix = Compiler.binary, .precedence = .Comparison }, ParseRule{}, - ParseRule{}, + ParseRule{ .prefix = Compiler.string }, ParseRule{ .prefix = Compiler.number }, ParseRule{ .precedence = .And }, ParseRule{}, @@ -228,6 +229,13 @@ pub const Compiler = struct { try self.emitConstant(values.NumberVal(value)); } + fn string(self: *Compiler) !void { + try self.emitConstant(values.ObjVal(try objects.copyString( + self.allocator, + self.parser.previous.lexeme, + ))); + } + /// Emits bytecode for a given unary. fn unary(self: *Compiler) !void { var ttype = self.parser.previous.ttype; diff --git a/src/object.zig b/src/object.zig new file mode 100644 index 0000000..0971fe3 --- /dev/null +++ b/src/object.zig @@ -0,0 +1,34 @@ +const std = @import("std"); + +const Allocator = std.mem.Allocator; + +pub const ObjType = enum { + String, +}; + +pub const ObjValue = struct { + String: []u8, +}; + +pub const Object = struct { + otype: ObjType, + value: ObjValue, +}; + +pub fn copyString(allocator: *Allocator, data: []const u8) !*Object { + var str = try allocator.alloc(u8, data.len); + std.mem.copy(u8, str, data); + + var obj = try allocator.create(Object); + obj.otype = ObjType.String; + obj.value = ObjValue{ .String = str }; + + return obj; +} + +pub fn printObject(stdout: var, obj: Object) !void { + switch (obj.otype) { + .String => try stdout.print("{}", obj.value.String), + else => unreachable, + } +} diff --git a/src/value.zig b/src/value.zig index 713c4b1..b1c927c 100644 --- a/src/value.zig +++ b/src/value.zig @@ -1,19 +1,20 @@ const std = @import("std"); +const objects = @import("object.zig"); const Allocator = std.mem.Allocator; -// NOTE: right now, only numbers. - pub const ValueType = enum(u8) { Bool, Nil, Number, + Object, }; pub const ValueValue = union(ValueType) { Bool: bool, Nil: void, Number: f64, + Object: *objects.Object, }; pub const Value = struct { @@ -34,11 +35,20 @@ pub fn NumberVal(val: f64) Value { return Value{ .vtype = .Number, .as = ValueValue{ .Number = val } }; } +pub fn ObjVal(val: *objects.Object) Value { + return Value{ .vtype = .Object, .as = ValueValue{ .Object = val } }; +} + +pub fn isObjType(val: Value, otype: objects.ObjType) bool { + return val.vtype == .Object and val.as.Object.otype == otype; +} + pub fn printValue(stdout: var, value: Value) !void { switch (value.as) { .Nil => try stdout.print("nil"), .Bool => try stdout.print("{}", value.as.Bool), .Number => try stdout.print("{}", value.as.Number), + .Object => try objects.printObject(stdout, value.as.Object.*), else => unreachable, } } diff --git a/src/vm.zig b/src/vm.zig index 1fbf0ac..302f371 100644 --- a/src/vm.zig +++ b/src/vm.zig @@ -27,6 +27,11 @@ fn valuesEqual(a: value.Value, b: value.Value) bool { .Nil => return true, .Bool => return a.as.Bool == b.as.Bool, .Number => return a.as.Number == b.as.Number, + .Object => blk: { + var aStr = a.as.Object.value.String; + var bStr = b.as.Object.value.String; + return std.mem.compare(u8, aStr, bStr) == .Equal; + }, } }