Files
zlox/src/values.zig

179 lines
4.3 KiB
Zig

const std = @import("std");
const debug = std.debug;
const Allocator = std.mem.Allocator;
const Obj = @import("./object.zig").Obj;
const ZloxAllocator = @import("./memory.zig").ZloxAllocator;
pub const ValueType = enum {
Bool,
Nil,
Number,
Obj,
};
pub const Value = struct {
value_type: ValueType,
as: union {
boolean: bool,
number: f64,
obj: *Obj,
},
pub fn bool_val(value: bool) Value {
return Value{
.value_type = ValueType.Bool,
.as = .{
.boolean = value,
},
};
}
pub fn nil_val() Value {
return Value{
.value_type = ValueType.Nil,
.as = .{
.boolean = false,
},
};
}
pub fn number_val(value: f64) Value {
return Value{
.value_type = ValueType.Number,
.as = .{
.number = value,
},
};
}
pub fn obj_val(obj: *Obj) Value {
return Value{
.value_type = ValueType.Obj,
.as = .{
.obj = obj,
},
};
}
pub fn as_bool(self: Value) bool {
return self.as.boolean;
}
pub fn as_number(self: Value) f64 {
return self.as.number;
}
pub fn as_obj(self: Value) *Obj {
return self.as.obj;
}
pub fn as_string(self: Value) *Obj.String {
const obj: *Obj.String = self.as_obj().as_string();
return obj;
}
pub fn as_cstring(self: Value) []const u8 {
const obj: *Obj.String = self.as_obj().as_string();
return obj.chars;
}
pub fn is_bool(self: Value) bool {
return self.value_type == ValueType.Bool;
}
pub fn is_number(self: Value) bool {
return self.value_type == ValueType.Number;
}
pub fn is_nil(self: Value) bool {
return self.value_type == ValueType.Nil;
}
pub fn is_obj(self: Value) bool {
return self.value_type == ValueType.Obj;
}
pub fn is_string(self: Value) bool {
return self.is_obj() and self.as_obj().is_string();
}
pub fn is_falsey(self: Value) bool {
return self.is_nil() or (self.is_bool() and !self.as_bool());
}
pub fn equals(self: Value, other: Value) bool {
if (self.value_type != other.value_type) {
return false;
}
return switch (self.value_type) {
ValueType.Nil => true,
ValueType.Bool => self.as_bool() == other.as_bool(),
ValueType.Number => self.as_number() == other.as_number(),
ValueType.Obj => self.as_obj() == other.as_obj(),
};
}
pub fn print(self: Value) void {
switch (self.value_type) {
ValueType.Nil => debug.print("nil", .{}),
ValueType.Bool => debug.print("{any}", .{self.as_bool()}),
ValueType.Number => debug.print("{d}", .{self.as_number()}),
ValueType.Obj => self.as_obj().print(),
}
}
pub fn type_print(self: Value) void {
switch (self.value_type) {
ValueType.Nil => debug.print("(nil)", .{}),
ValueType.Bool => debug.print("(bool)", .{}),
ValueType.Number => debug.print("(number)", .{}),
ValueType.Obj => debug.print("(obj)", .{}),
}
debug.print(" ", .{});
self.print();
}
};
pub const ValueArray = struct {
allocator: Allocator,
capacity: usize,
count: usize,
values: []Value,
pub fn new(allocator: Allocator) ValueArray {
return ValueArray{
.allocator = allocator,
.capacity = 0,
.count = 0,
.values = &.{},
};
}
pub fn write(self: *ValueArray, value: Value) !void {
if (self.capacity < self.count + 1) {
const old_capacity = self.capacity;
self.capacity = ZloxAllocator.grow_capacity(old_capacity);
self.values = try self.allocator.realloc(self.values, self.capacity);
}
self.values[self.count] = value;
self.count += 1;
}
pub fn destroy(self: *ValueArray) void {
if (self.capacity > 0) {
self.allocator.free(self.values);
}
}
};
pub fn print_value(value: Value) void {
value.print();
}