commit bb3007599d98231af265275281a7f824aa96a29c
parent 5db367d76d8508a2a93089780380792516d022af
Author: Szymon Mikulicz <szymon.mikulicz@aptiv.com>
Date: Thu, 8 Aug 2024 14:49:20 +0200
Split Obj subclasses into separate files
Diffstat:
9 files changed, 384 insertions(+), 342 deletions(-)
diff --git a/zlox/src/obj.zig b/zlox/src/obj.zig
@@ -1,287 +1,17 @@
const std = @import("std");
const utils = @import("comptime_utils.zig");
-const hash = @import("hash.zig");
-const table = @import("table.zig");
-const value = @import("value.zig");
-const chunk = @import("chunk.zig");
+const TableError = @import("table.zig").TableError;
pub const Obj = packed struct {
const Super = @This();
- pub const Error = table.TableError || error{ OutOfMemory, IllegalCastError, NotFound };
+ pub const Error = TableError || error{ OutOfMemory, IllegalCastError, NotFound };
type: Type,
- // pub const Template = packed struct {
- // const Self = @This();
- // pub const Arg = void;
- // obj: Super,
- // pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self {
- // _ = arg;
- // _ = allocator;
- // }
- // pub fn cast(self: *Self) *Super {
- // _ = self;
- // }
- // pub fn print(self: *const Self) void {
- // _ = self;
- // }
- // pub fn eql(self: *const Self, other: *const Self) bool {
- // _ = self;
- // _ = other;
- // }
- // pub fn free(self: *const Self, allocator: std.mem.Allocator) void {
- // _ = self;
- // _ = allocator;
- // }
- // };
-
- pub const List = struct {
- const Self = @This();
- const Element = struct {
- obj: *Super,
- next: ?*@This(),
- };
-
- tip: ?*Element,
- allocator: std.mem.Allocator,
- table: String.Table,
-
- pub fn init(allocator: std.mem.Allocator) Self {
- return Self{ .tip = null, .allocator = allocator, .table = String.Table.init(allocator) };
- }
-
- pub fn push(self: *Self, val: *Super) Error!void {
- var new_tip = try self.allocator.create(Element);
- new_tip.next = self.tip;
- new_tip.obj = val;
- self.tip = new_tip;
- }
-
- pub fn emplace(self: *Self, comptime tp: Type, arg: tp.get().Arg) Error!*Super {
- var newObj = true;
- const obj = switch (tp) {
- .String => (try String.intern(arg, &self.table, &newObj, self.allocator)).cast(),
- else => try Super.init(tp, arg, self.allocator),
- };
- if (newObj) try self.push(obj);
- return obj;
- }
-
- pub fn pop(self: *Self) ?*Element {
- if (self.tip) |tip| {
- self.tip = tip.next;
- tip.obj.free(self.allocator);
- return tip;
- }
- return null;
- }
-
- pub fn deinit(self: *Self) void {
- while (self.pop()) |tip| {
- self.allocator.destroy(tip);
- }
- self.table.deinit();
- }
- };
-
- pub const String = packed struct {
- const Self = @This();
- pub const Table = table.Table(*Self, void, hash.hash_t(*const Self), Self.eql);
- pub const Arg = []const []const u8;
-
- obj: Super,
- len: usize = 0,
- hash: u32,
-
- fn data(self: anytype) utils.copy_const(@TypeOf(self), [*]u8) {
- const p: utils.copy_const(@TypeOf(self), [*]u8) = @ptrCast(self);
- return p + @sizeOf(Self);
- }
- fn new(arg: Arg, params: ArgParams, allocator: std.mem.Allocator) Error!*Self {
- const ret: *Self = @ptrCast(try allocator.alignedAlloc(u8, @alignOf(Self), @sizeOf(Self) + params.len));
- ret.* = Self{
- .obj = Super{
- .type = Super.Type.String,
- },
- .hash = params.hash,
- };
- for (arg) |el| {
- @memcpy(ret.data() + ret.len, el);
- ret.len += el.len;
- }
- return ret;
- }
-
- pub fn slice(self: *const Self) []const u8 {
- return self.data()[0..self.len];
- }
- pub fn cast(self: *Self) *Super {
- return @ptrCast(self);
- }
- pub fn print(self: *const Self) void {
- std.debug.print("\"{s}\"", .{self.slice()});
- }
- pub fn eql(self: *const Self, other: *const Self) bool {
- return @intFromPtr(self) == @intFromPtr(other);
- }
- pub fn get(self: *const Self, index: value.Value) !value.Value {
- if (!index.is(value.Value.number) or index.number >= @as(value.Value.tagType(value.Value.number), @floatFromInt(self.len)) or index.number < 0) {
- return error.KeyError;
- }
- return value.Value.init(self.data()[@intFromFloat(index.number)]);
- }
-
- const ArgParams = struct { len: usize, hash: u32 };
-
- fn table_check(m_arg: Arg, m_params: ArgParams) struct {
- arg: Arg,
- params: ArgParams,
- pub fn check(self: *const @This(), k2: *const Self) bool {
- if (k2.hash == self.params.hash and k2.len == self.params.len) {
- var idx: usize = 0;
- for (self.arg) |el| {
- if (!std.mem.eql(u8, k2.data()[idx .. idx + el.len], el))
- return false;
- idx += el.len;
- }
- return true;
- }
- return false;
- }
- } {
- return @TypeOf(table_check(m_arg, m_params)){ .arg = m_arg, .params = m_params };
- }
-
- fn arg_params(arg: Arg) ArgParams {
- var ret = ArgParams{ .len = 0, .hash = hash.hash_t([]const u8)(&.{}) };
-
- for (arg) |el| {
- ret.len += el.len;
- ret.hash = hash.hash_append(ret.hash, el);
- }
- return ret;
- }
-
- pub fn intern(arg: Arg, tabl: *Self.Table, isNewKey: *bool, allocator: std.mem.Allocator) Error!*Self {
- const params = arg_params(arg);
-
- try tabl.checkCapacity();
- const entry = Self.Table.find_(tabl.entries, params.hash, table_check(arg, params));
- isNewKey.* = entry.* != Self.Table.Entry.some;
- if (isNewKey.*) {
- _ = tabl.set_(entry, try new(arg, params, allocator), {});
- }
- return entry.some.key;
- }
-
- pub fn init(_: Arg, _: std.mem.Allocator) Error!*Self {
- @compileError("The String Obj has to be interned");
- }
-
- pub fn free(self: *const Self, allocator: std.mem.Allocator) void {
- const p: [*]align(@alignOf(Self)) const u8 = @ptrCast(self);
- allocator.free(p[0 .. @sizeOf(Self) + self.len]);
- }
- };
-
- pub const Table = packed struct {
- const Self = @This();
- pub const Arg = void;
- const Table = table.Table(value.Value, value.Value, hash.hash_t(value.Value), value.Value.eql);
-
- obj: Super,
- table: *Self.Table,
- hash: u32,
-
- pub fn init(_: Arg, allocator: std.mem.Allocator) Error!*Self {
- const self: *Self = try allocator.create(Self);
- self.* = Self{
- .obj = Super{
- .type = Super.Type.Table,
- },
- .table = try allocator.create(Self.Table),
- .hash = 0,
- };
- self.table.* = Self.Table.init(allocator);
- return self;
- }
- pub fn cast(self: *Self) *Super {
- return @ptrCast(self);
- }
-
- pub fn set(self: *Self, key: value.Value, val: value.Value) !bool {
- self.hash +%= hash.hash(key) +% hash.hash(val);
- return self.table.set(key, val);
- }
-
- pub fn get(self: *Self, key: value.Value) !value.Value {
- return self.table.get(key);
- }
-
- pub fn delete(self: *Self, key: value.Value) void {
- const val = self.table.get(key) catch return;
- self.hash -%= hash.hash(key) -% hash.hash(val);
- _ = self.table.delete(key);
- }
-
- fn print_element(key: value.Value, val: value.Value) void {
- key.print();
- std.debug.print(":", .{});
- val.print();
- std.debug.print(",", .{});
-
- }
- pub fn print(self: *const Self) void {
- std.debug.print("[", .{});
- self.table.for_each(Self.print_element);
- std.debug.print("]", .{});
- }
- pub fn eql(self: *const Self, other: *const Self) bool {
- return self.table.eql(other.table, value.Value.eql);
- }
- pub fn free(self: *const Self, allocator: std.mem.Allocator) void {
- self.table.deinit();
- allocator.destroy(self.table);
- allocator.destroy(self);
- }
-
- };
-
- pub const Function = packed struct {
- const Self = @This();
- pub const Arg = void;
-
- obj: Super,
- arity: u8,
- chunk: *chunk.Chunk,
- name: *String,
-
- pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self {
- _ = arg;
- _ = allocator;
- return error.OutOfMemory;
- }
-
- pub fn cast(self: *Self) *Super {
- return @ptrCast(self);
- }
-
- pub fn print(self: *const Self) void {
- _ = self;
- }
-
- pub fn eql(self: *const Self, other: *const Self) bool {
- _ = self;
- _ = other;
- return false;
- }
-
- pub fn free(self: *const Self, allocator: std.mem.Allocator) void {
- _ = self;
- _ = allocator;
- }
-
- };
+ pub const List = @import("obj/list.zig").List;
+ pub const String = @import("obj/string.zig").String;
+ pub const Table = @import("obj/table.zig").Table;
+ pub const Function = @import("obj/function.zig").Function;
pub const Type = enum(u8) {
String,
diff --git a/zlox/src/obj/function.zig b/zlox/src/obj/function.zig
@@ -0,0 +1,42 @@
+const std = @import("std");
+const chunk = @import("../chunk.zig");
+
+const Super = @import("../obj.zig").Obj;
+const Error = Super.Error;
+const String = Super.String;
+
+pub const Function = packed struct {
+ const Self = @This();
+ pub const Arg = void;
+
+ obj: Super,
+ arity: u8,
+ chunk: *chunk.Chunk,
+ name: *String,
+
+ pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self {
+ _ = arg;
+ _ = allocator;
+ return error.OutOfMemory;
+ }
+
+ pub fn cast(self: *Self) *Super {
+ return @ptrCast(self);
+ }
+
+ pub fn print(self: *const Self) void {
+ _ = self;
+ }
+
+ pub fn eql(self: *const Self, other: *const Self) bool {
+ _ = self;
+ _ = other;
+ return false;
+ }
+
+ pub fn free(self: *const Self, allocator: std.mem.Allocator) void {
+ _ = self;
+ _ = allocator;
+ }
+
+};
diff --git a/zlox/src/obj/list.zig b/zlox/src/obj/list.zig
@@ -0,0 +1,55 @@
+const std = @import("std");
+
+const Super = @import("../obj.zig").Obj;
+const Error = Super.Error;
+const String = Super.String;
+const Type = Super.Type;
+
+pub const List = struct {
+ const Self = @This();
+ const Element = struct {
+ obj: *Super,
+ next: ?*@This(),
+ };
+
+ tip: ?*Element,
+ allocator: std.mem.Allocator,
+ table: String.Table,
+
+ pub fn init(allocator: std.mem.Allocator) Self {
+ return Self{ .tip = null, .allocator = allocator, .table = String.Table.init(allocator) };
+ }
+
+ pub fn push(self: *Self, val: *Super) Error!void {
+ var new_tip = try self.allocator.create(Element);
+ new_tip.next = self.tip;
+ new_tip.obj = val;
+ self.tip = new_tip;
+ }
+
+ pub fn emplace(self: *Self, comptime tp: Type, arg: tp.get().Arg) Error!*Super {
+ var newObj = true;
+ const obj = switch (tp) {
+ .String => (try String.intern(arg, &self.table, &newObj, self.allocator)).cast(),
+ else => try Super.init(tp, arg, self.allocator),
+ };
+ if (newObj) try self.push(obj);
+ return obj;
+ }
+
+ pub fn pop(self: *Self) ?*Element {
+ if (self.tip) |tip| {
+ self.tip = tip.next;
+ tip.obj.free(self.allocator);
+ return tip;
+ }
+ return null;
+ }
+
+ pub fn deinit(self: *Self) void {
+ while (self.pop()) |tip| {
+ self.allocator.destroy(tip);
+ }
+ self.table.deinit();
+ }
+};
diff --git a/zlox/src/obj/string.zig b/zlox/src/obj/string.zig
@@ -0,0 +1,108 @@
+const std = @import("std");
+const table = @import("../table.zig");
+const hash = @import("../hash.zig");
+const utils = @import("../comptime_utils.zig");
+const value = @import("../value.zig");
+
+const Super = @import("../obj.zig").Obj;
+const Error = Super.Error;
+
+pub const String = packed struct {
+ const Self = @This();
+ pub const Table = table.Table(*Self, void, hash.hash_t(*const Self), Self.eql);
+ pub const Arg = []const []const u8;
+
+ obj: Super,
+ len: usize = 0,
+ hash: u32,
+
+ fn data(self: anytype) utils.copy_const(@TypeOf(self), [*]u8) {
+ const p: utils.copy_const(@TypeOf(self), [*]u8) = @ptrCast(self);
+ return p + @sizeOf(Self);
+ }
+ fn new(arg: Arg, params: ArgParams, allocator: std.mem.Allocator) Error!*Self {
+ const ret: *Self = @ptrCast(try allocator.alignedAlloc(u8, @alignOf(Self), @sizeOf(Self) + params.len));
+ ret.* = Self{
+ .obj = Super{
+ .type = Super.Type.String,
+ },
+ .hash = params.hash,
+ };
+ for (arg) |el| {
+ @memcpy(ret.data() + ret.len, el);
+ ret.len += el.len;
+ }
+ return ret;
+ }
+
+ pub fn slice(self: *const Self) []const u8 {
+ return self.data()[0..self.len];
+ }
+ pub fn cast(self: *Self) *Super {
+ return @ptrCast(self);
+ }
+ pub fn print(self: *const Self) void {
+ std.debug.print("\"{s}\"", .{self.slice()});
+ }
+ pub fn eql(self: *const Self, other: *const Self) bool {
+ return @intFromPtr(self) == @intFromPtr(other);
+ }
+ pub fn get(self: *const Self, index: value.Value) !value.Value {
+ if (!index.is(value.Value.number) or index.number >= @as(value.Value.tagType(value.Value.number), @floatFromInt(self.len)) or index.number < 0) {
+ return error.KeyError;
+ }
+ return value.Value.init(self.data()[@intFromFloat(index.number)]);
+ }
+
+ const ArgParams = struct { len: usize, hash: u32 };
+
+ fn table_check(m_arg: Arg, m_params: ArgParams) struct {
+ arg: Arg,
+ params: ArgParams,
+ pub fn check(self: *const @This(), k2: *const Self) bool {
+ if (k2.hash == self.params.hash and k2.len == self.params.len) {
+ var idx: usize = 0;
+ for (self.arg) |el| {
+ if (!std.mem.eql(u8, k2.data()[idx .. idx + el.len], el))
+ return false;
+ idx += el.len;
+ }
+ return true;
+ }
+ return false;
+ }
+ } {
+ return @TypeOf(table_check(m_arg, m_params)){ .arg = m_arg, .params = m_params };
+ }
+
+ fn arg_params(arg: Arg) ArgParams {
+ var ret = ArgParams{ .len = 0, .hash = hash.hash_t([]const u8)(&.{}) };
+
+ for (arg) |el| {
+ ret.len += el.len;
+ ret.hash = hash.hash_append(ret.hash, el);
+ }
+ return ret;
+ }
+
+ pub fn intern(arg: Arg, tabl: *Self.Table, isNewKey: *bool, allocator: std.mem.Allocator) Error!*Self {
+ const params = arg_params(arg);
+
+ try tabl.checkCapacity();
+ const entry = Self.Table.find_(tabl.entries, params.hash, table_check(arg, params));
+ isNewKey.* = entry.* != Self.Table.Entry.some;
+ if (isNewKey.*) {
+ _ = tabl.set_(entry, try new(arg, params, allocator), {});
+ }
+ return entry.some.key;
+ }
+
+ pub fn init(_: Arg, _: std.mem.Allocator) Error!*Self {
+ @compileError("The String Obj has to be interned");
+ }
+
+ pub fn free(self: *const Self, allocator: std.mem.Allocator) void {
+ const p: [*]align(@alignOf(Self)) const u8 = @ptrCast(self);
+ allocator.free(p[0 .. @sizeOf(Self) + self.len]);
+ }
+};
diff --git a/zlox/src/obj/table.zig b/zlox/src/obj/table.zig
@@ -0,0 +1,70 @@
+const std = @import("std");
+const table = @import("../table.zig");
+const hash = @import("../hash.zig");
+const value = @import("../value.zig");
+
+const Super = @import("../obj.zig").Obj;
+const Error = Super.Error;
+
+pub const Table = packed struct {
+ const Self = @This();
+ pub const Arg = void;
+ const Table = table.Table(value.Value, value.Value, hash.hash_t(value.Value), value.Value.eql);
+
+ obj: Super,
+ table: *Self.Table,
+ hash: u32,
+
+ pub fn init(_: Arg, allocator: std.mem.Allocator) Error!*Self {
+ const self: *Self = try allocator.create(Self);
+ self.* = Self{
+ .obj = Super{
+ .type = Super.Type.Table,
+ },
+ .table = try allocator.create(Self.Table),
+ .hash = 0,
+ };
+ self.table.* = Self.Table.init(allocator);
+ return self;
+ }
+ pub fn cast(self: *Self) *Super {
+ return @ptrCast(self);
+ }
+
+ pub fn set(self: *Self, key: value.Value, val: value.Value) !bool {
+ self.hash +%= hash.hash(key) +% hash.hash(val);
+ return self.table.set(key, val);
+ }
+
+ pub fn get(self: *Self, key: value.Value) !value.Value {
+ return self.table.get(key);
+ }
+
+ pub fn delete(self: *Self, key: value.Value) void {
+ const val = self.table.get(key) catch return;
+ self.hash -%= hash.hash(key) -% hash.hash(val);
+ _ = self.table.delete(key);
+ }
+
+ fn print_element(key: value.Value, val: value.Value) void {
+ key.print();
+ std.debug.print(":", .{});
+ val.print();
+ std.debug.print(",", .{});
+
+ }
+ pub fn print(self: *const Self) void {
+ std.debug.print("[", .{});
+ self.table.for_each(Self.print_element);
+ std.debug.print("]", .{});
+ }
+ pub fn eql(self: *const Self, other: *const Self) bool {
+ return self.table.eql(other.table, value.Value.eql);
+ }
+ pub fn free(self: *const Self, allocator: std.mem.Allocator) void {
+ self.table.deinit();
+ allocator.destroy(self.table);
+ allocator.destroy(self);
+ }
+
+};
diff --git a/zlox/src/obj/template.zig b/zlox/src/obj/template.zig
@@ -0,0 +1,37 @@
+const std = @import("std");
+
+const Super = @import("../obj.zig").Obj;
+const Error = Super.Error;
+
+pub const Template = packed struct {
+ const Self = @This();
+
+ pub const Arg = void;
+
+ obj: Super,
+ pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self {
+ _ = arg;
+ _ = allocator;
+ return error.OutOfMemory;
+ }
+
+ pub fn cast(self: *Self) *Super {
+ return @ptrCast(self);
+ }
+
+ pub fn print(self: *const Self) void {
+ _ = self;
+ }
+
+ pub fn eql(self: *const Self, other: *const Self) bool {
+ _ = self;
+ _ = other;
+ return false;
+ }
+
+ pub fn free(self: *const Self, allocator: std.mem.Allocator) void {
+ _ = self;
+ _ = allocator;
+ }
+};
+
diff --git a/zlox/src/vm.zig b/zlox/src/vm.zig
@@ -5,7 +5,7 @@ const std = @import("std");
const debug = @import("debug.zig");
const compiler = @import("compiler.zig");
const Obj = @import("obj.zig").Obj;
-const Callback = @import("vm_callbacks.zig");
+const Callback = @import("vm/callbacks.zig");
const table = @import("table.zig");
const hash = @import("hash.zig");
diff --git a/zlox/src/vm/callbacks.zig b/zlox/src/vm/callbacks.zig
@@ -0,0 +1,65 @@
+const std = @import("std");
+const Obj = @import("../obj.zig").Obj;
+const Value = @import("../value.zig").Value;
+
+const Number = Value.tagType(.number);
+const Bool = Value.tagType(.bool);
+
+pub const Error = Obj.Error;
+
+pub fn Type(comptime in_tag: anytype, comptime out_tag: anytype) type {
+ if (@TypeOf(in_tag) == Obj.Type) {
+ return struct {
+ objects: *Obj.List,
+ _call: *const fn (self: *const @This(), Value.tagType(in_tag), Value.tagType(in_tag)) Error!Value.tagType(out_tag),
+ pub fn call(self: *const @This(), a: Value.tagType(in_tag), b: Value.tagType(in_tag)) Error!Value.tagType(out_tag) {
+ return self._call(self, a, b);
+ }
+ };
+ } else {
+ return struct {
+ call: fn (Value.tagType(in_tag), Value.tagType(in_tag)) callconv(.Inline) Error!Value.tagType(out_tag),
+ };
+ }
+}
+
+pub fn concatenate(objects: *Obj.List) Type(Obj.Type.String, Obj.Type.String) {
+ const Ret = Type(Obj.Type.String, Obj.Type.String);
+ const ret = Ret{ .objects = objects, ._call = struct {
+ pub fn concatenate(self: *const Ret, lhs: *Obj, rhs: *Obj) Error!*Obj {
+ return try self.objects.emplace(.String, &.{ (lhs.cast(.String) catch unreachable).slice(), (rhs.cast(.String) catch unreachable).slice() });
+ }
+ }.concatenate };
+ return ret;
+}
+
+pub const add = Type(Value.number, Value.number){ .call = struct {
+ pub inline fn add(a: Number, b: Number) Error!Number {
+ return a + b;
+ }
+}.add };
+pub const mul = Type(Value.number, Value.number){ .call = struct {
+ pub inline fn mul(a: Number, b: Number) Error!Number {
+ return a * b;
+ }
+}.mul };
+pub const sub = Type(Value.number, Value.number){ .call = struct {
+ pub inline fn sub(a: Number, b: Number) Error!Number {
+ return a - b;
+ }
+}.sub };
+pub const div = Type(Value.number, Value.number){ .call = struct {
+ pub inline fn div(a: Number, b: Number) Error!Number {
+ return a / b;
+ }
+}.div };
+pub const less = Type(Value.number, Value.bool){ .call = struct {
+ pub inline fn less(a: Number, b: Number) Error!Bool {
+ return a < b;
+ }
+}.less };
+pub const more = Type(Value.number, Value.bool){ .call = struct {
+ pub inline fn more(a: Number, b: Number) Error!Bool {
+ return a > b;
+ }
+}.more };
diff --git a/zlox/src/vm_callbacks.zig b/zlox/src/vm_callbacks.zig
@@ -1,65 +0,0 @@
-const Value = @import("value.zig").Value;
-const std = @import("std");
-const Obj = @import("obj.zig").Obj;
-
-const Number = Value.tagType(.number);
-const Bool = Value.tagType(.bool);
-
-pub const Error = Obj.Error;
-
-pub fn Type(comptime in_tag: anytype, comptime out_tag: anytype) type {
- if (@TypeOf(in_tag) == Obj.Type) {
- return struct {
- objects: *Obj.List,
- _call: *const fn (self: *const @This(), Value.tagType(in_tag), Value.tagType(in_tag)) Error!Value.tagType(out_tag),
- pub fn call(self: *const @This(), a: Value.tagType(in_tag), b: Value.tagType(in_tag)) Error!Value.tagType(out_tag) {
- return self._call(self, a, b);
- }
- };
- } else {
- return struct {
- call: fn (Value.tagType(in_tag), Value.tagType(in_tag)) callconv(.Inline) Error!Value.tagType(out_tag),
- };
- }
-}
-
-pub fn concatenate(objects: *Obj.List) Type(Obj.Type.String, Obj.Type.String) {
- const Ret = Type(Obj.Type.String, Obj.Type.String);
- const ret = Ret{ .objects = objects, ._call = struct {
- pub fn concatenate(self: *const Ret, lhs: *Obj, rhs: *Obj) Error!*Obj {
- return try self.objects.emplace(.String, &.{ (lhs.cast(.String) catch unreachable).slice(), (rhs.cast(.String) catch unreachable).slice() });
- }
- }.concatenate };
- return ret;
-}
-
-pub const add = Type(Value.number, Value.number){ .call = struct {
- pub inline fn add(a: Number, b: Number) Error!Number {
- return a + b;
- }
-}.add };
-pub const mul = Type(Value.number, Value.number){ .call = struct {
- pub inline fn mul(a: Number, b: Number) Error!Number {
- return a * b;
- }
-}.mul };
-pub const sub = Type(Value.number, Value.number){ .call = struct {
- pub inline fn sub(a: Number, b: Number) Error!Number {
- return a - b;
- }
-}.sub };
-pub const div = Type(Value.number, Value.number){ .call = struct {
- pub inline fn div(a: Number, b: Number) Error!Number {
- return a / b;
- }
-}.div };
-pub const less = Type(Value.number, Value.bool){ .call = struct {
- pub inline fn less(a: Number, b: Number) Error!Bool {
- return a < b;
- }
-}.less };
-pub const more = Type(Value.number, Value.bool){ .call = struct {
- pub inline fn more(a: Number, b: Number) Error!Bool {
- return a > b;
- }
-}.more };