add objects and string comparison
This commit is contained in:
parent
44c27f43b7
commit
9ac5fccc2b
4 changed files with 60 additions and 3 deletions
|
@ -4,6 +4,7 @@ const vm = @import("vm.zig");
|
||||||
const chunks = @import("chunk.zig");
|
const chunks = @import("chunk.zig");
|
||||||
const tokens = @import("token.zig");
|
const tokens = @import("token.zig");
|
||||||
const values = @import("value.zig");
|
const values = @import("value.zig");
|
||||||
|
const objects = @import("object.zig");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const Scanner = scanner.Scanner;
|
const Scanner = scanner.Scanner;
|
||||||
|
@ -89,7 +90,7 @@ var rules = []ParseRule{
|
||||||
ParseRule{ .infix = Compiler.binary, .precedence = .Comparison },
|
ParseRule{ .infix = Compiler.binary, .precedence = .Comparison },
|
||||||
|
|
||||||
ParseRule{},
|
ParseRule{},
|
||||||
ParseRule{},
|
ParseRule{ .prefix = Compiler.string },
|
||||||
ParseRule{ .prefix = Compiler.number },
|
ParseRule{ .prefix = Compiler.number },
|
||||||
ParseRule{ .precedence = .And },
|
ParseRule{ .precedence = .And },
|
||||||
ParseRule{},
|
ParseRule{},
|
||||||
|
@ -228,6 +229,13 @@ pub const Compiler = struct {
|
||||||
try self.emitConstant(values.NumberVal(value));
|
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.
|
/// Emits bytecode for a given unary.
|
||||||
fn unary(self: *Compiler) !void {
|
fn unary(self: *Compiler) !void {
|
||||||
var ttype = self.parser.previous.ttype;
|
var ttype = self.parser.previous.ttype;
|
||||||
|
|
34
src/object.zig
Normal file
34
src/object.zig
Normal file
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +1,20 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const objects = @import("object.zig");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
// NOTE: right now, only numbers.
|
|
||||||
|
|
||||||
pub const ValueType = enum(u8) {
|
pub const ValueType = enum(u8) {
|
||||||
Bool,
|
Bool,
|
||||||
Nil,
|
Nil,
|
||||||
Number,
|
Number,
|
||||||
|
Object,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ValueValue = union(ValueType) {
|
pub const ValueValue = union(ValueType) {
|
||||||
Bool: bool,
|
Bool: bool,
|
||||||
Nil: void,
|
Nil: void,
|
||||||
Number: f64,
|
Number: f64,
|
||||||
|
Object: *objects.Object,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Value = struct {
|
pub const Value = struct {
|
||||||
|
@ -34,11 +35,20 @@ pub fn NumberVal(val: f64) Value {
|
||||||
return Value{ .vtype = .Number, .as = ValueValue{ .Number = val } };
|
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 {
|
pub fn printValue(stdout: var, value: Value) !void {
|
||||||
switch (value.as) {
|
switch (value.as) {
|
||||||
.Nil => try stdout.print("nil"),
|
.Nil => try stdout.print("nil"),
|
||||||
.Bool => try stdout.print("{}", value.as.Bool),
|
.Bool => try stdout.print("{}", value.as.Bool),
|
||||||
.Number => try stdout.print("{}", value.as.Number),
|
.Number => try stdout.print("{}", value.as.Number),
|
||||||
|
.Object => try objects.printObject(stdout, value.as.Object.*),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,11 @@ fn valuesEqual(a: value.Value, b: value.Value) bool {
|
||||||
.Nil => return true,
|
.Nil => return true,
|
||||||
.Bool => return a.as.Bool == b.as.Bool,
|
.Bool => return a.as.Bool == b.as.Bool,
|
||||||
.Number => return a.as.Number == b.as.Number,
|
.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;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue