feat: cheaper runtime value type, float and int arithmetic rules
This commit is contained in:
parent
9b5cd4038f
commit
92e8bcd866
13 changed files with 630 additions and 448 deletions
|
|
@ -1,5 +1,6 @@
|
|||
const std = @import("std");
|
||||
const Story = @import("../Story.zig");
|
||||
const Value = Story.Value;
|
||||
const Object = Story.Object;
|
||||
const Opcode = Story.Opcode;
|
||||
const assert = std.debug.assert;
|
||||
|
|
@ -21,6 +22,8 @@ fn dumpByteInst(
|
|||
op: Opcode,
|
||||
) !usize {
|
||||
const code = knot.code;
|
||||
const constants_pool = &self.story.constants_pool;
|
||||
|
||||
assert(code.bytecode.len > offset + 1);
|
||||
const arg = code.bytecode[offset + 1];
|
||||
if (op == .load_const) {
|
||||
|
|
@ -28,9 +31,9 @@ fn dumpByteInst(
|
|||
try w.writeAll(" (");
|
||||
if (code.constants.len > arg) {
|
||||
const constant_index = code.constants[arg];
|
||||
if (self.story.constants_pool.items.len > constant_index) {
|
||||
const global_constant = self.story.constants_pool.items[constant_index];
|
||||
try self.dumpObject(w, global_constant);
|
||||
if (constants_pool.items.len > constant_index) {
|
||||
const global_constant = &constants_pool.items[constant_index];
|
||||
try self.dumpValue(w, global_constant);
|
||||
} else {
|
||||
try w.writeAll("invalid!");
|
||||
}
|
||||
|
|
@ -52,15 +55,24 @@ fn dumpGlobalInst(
|
|||
op: Opcode,
|
||||
) !usize {
|
||||
const code = knot.code;
|
||||
const constants_pool = &self.story.constants_pool;
|
||||
|
||||
assert(code.bytecode.len > offset + 1);
|
||||
const arg = code.bytecode[offset + 1];
|
||||
assert(code.constants.len > arg);
|
||||
const constant_index = code.constants[arg];
|
||||
const global_constant = self.story.constants_pool.items[constant_index];
|
||||
assert(global_constant.tag == .string);
|
||||
const global_name: *Object.String = @ptrCast(global_constant);
|
||||
const name_bytes = global_name.bytes[0..global_name.length];
|
||||
try w.print("{s} {x} '{s}'\n", .{ @tagName(op), arg, name_bytes });
|
||||
const global_constant = constants_pool.items[constant_index];
|
||||
switch (global_constant) {
|
||||
.object => |object| switch (object.tag) {
|
||||
.string => {
|
||||
const global_name: *Object.String = @ptrCast(object);
|
||||
const name_bytes = global_name.bytes[0..global_name.length];
|
||||
try w.print("{s} {x} '{s}'\n", .{ @tagName(op), arg, name_bytes });
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
|
|
@ -265,40 +277,108 @@ pub fn dumpKnot(self: *Dumper, w: *std.Io.Writer, knot: *const Object.Knot) !voi
|
|||
return w.flush();
|
||||
}
|
||||
|
||||
pub fn dumpObject(_: Dumper, w: *std.Io.Writer, obj: *const Object) !void {
|
||||
const type_string = obj.tag.toStr();
|
||||
switch (obj.tag) {
|
||||
.number => {
|
||||
const typed_object: *const Object.Number = @ptrCast(obj);
|
||||
switch (typed_object.data) {
|
||||
.boolean => |value| try w.print("<type={s} value={s}, address={*}>", .{
|
||||
type_string,
|
||||
if (value) "true" else "false",
|
||||
obj,
|
||||
}),
|
||||
.floating => |value| try w.print("<type={s} value={d}, address={*}>", .{
|
||||
type_string,
|
||||
value,
|
||||
obj,
|
||||
}),
|
||||
.integer => |value| try w.print("<type={s} value={d}, address={*}>", .{
|
||||
type_string,
|
||||
value,
|
||||
obj,
|
||||
}),
|
||||
}
|
||||
},
|
||||
.string => {
|
||||
const typed_object: *const Object.String = @ptrCast(obj);
|
||||
const string_bytes = typed_object.bytes[0..typed_object.length];
|
||||
try w.print("<type={s} value=\"{s}\", address={*}>", .{
|
||||
type_string,
|
||||
string_bytes,
|
||||
obj,
|
||||
});
|
||||
},
|
||||
.code, .knot => {
|
||||
try w.print("<type={s} address={*}>", .{ type_string, obj });
|
||||
pub fn dumpValue(_: Dumper, w: *std.Io.Writer, value: *const Value) !void {
|
||||
switch (value.*) {
|
||||
.bool => |boolean| try w.print("<{s} value={s}>", .{
|
||||
value.tagBytes(),
|
||||
if (boolean) "true" else "false",
|
||||
}),
|
||||
.int => |int| try w.print("<{s} value={d}, address={*}>", .{
|
||||
value.tagBytes(),
|
||||
int,
|
||||
value,
|
||||
}),
|
||||
.float => |float| try w.print("<{s} value={d}, address={*}>", .{
|
||||
value.tagBytes(),
|
||||
float,
|
||||
value,
|
||||
}),
|
||||
.object => |object| switch (object.tag) {
|
||||
.string => {
|
||||
const typed_object: *const Object.String = @ptrCast(object);
|
||||
const string_bytes = typed_object.bytes[0..typed_object.length];
|
||||
try w.print("<{s} value=\"{s}\", address={*}>", .{
|
||||
object.tag.tagBytes(),
|
||||
string_bytes,
|
||||
object,
|
||||
});
|
||||
},
|
||||
else => try w.print("<{s} address={*}>", .{ object.tag.tagBytes(), object }),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump(story: *Story, writer: *std.Io.Writer) !void {
|
||||
var story_dumper: Dumper = .{ .story = story };
|
||||
|
||||
try writer.writeAll("=== Constants ===\n");
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < story.constants_pool.items.len) : (i += 1) {
|
||||
const global_constant = &story.constants_pool.items[i];
|
||||
try story_dumper.dumpValue(writer, global_constant);
|
||||
try writer.writeAll("\n");
|
||||
}
|
||||
|
||||
try writer.writeAll("\n");
|
||||
try writer.writeAll("=== Globals ===\n");
|
||||
|
||||
var global_iter = story.globals.iterator();
|
||||
while (global_iter.next()) |entry| {
|
||||
try writer.print("{s} => ...\n", .{entry.key_ptr.*});
|
||||
}
|
||||
|
||||
try writer.writeAll("\n");
|
||||
try writer.writeAll("=== Knots ===\n");
|
||||
try writer.flush();
|
||||
|
||||
var knots_iter = story.globals.iterator();
|
||||
while (knots_iter.next()) |entry| {
|
||||
if (entry.value_ptr.*) |global| {
|
||||
switch (global) {
|
||||
.object => |object| switch (object.tag) {
|
||||
.knot => {
|
||||
try writer.writeAll("*");
|
||||
story_dumper.indent_level += 2;
|
||||
try story_dumper.dumpKnot(writer, @ptrCast(object));
|
||||
story_dumper.indent_level -= 2;
|
||||
},
|
||||
else => {},
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trace(story: *Story, writer: *std.Io.Writer, frame: *Story.CallFrame) !void {
|
||||
var dumper: Dumper = .{ .story = story };
|
||||
const stack = &story.stack;
|
||||
const stack_top = story.stack.items.len;
|
||||
|
||||
try writer.print("\tStack => stack_pointer={d}, objects=[", .{frame.sp});
|
||||
|
||||
if (stack_top > 0) {
|
||||
// FIXME: There has to be a better way to do this.
|
||||
if (stack_top > 1) {
|
||||
var i: usize = frame.sp;
|
||||
while (i < stack.items.len - 1) : (i += 1) {
|
||||
if (stack.items[i]) |*value| {
|
||||
try dumper.dumpValue(writer, value);
|
||||
} else {
|
||||
try writer.writeAll("null");
|
||||
}
|
||||
try writer.writeAll(", ");
|
||||
}
|
||||
}
|
||||
if (stack.items[stack.items.len - 1]) |*object| {
|
||||
try dumper.dumpValue(writer, object);
|
||||
} else {
|
||||
try writer.writeAll("null");
|
||||
}
|
||||
}
|
||||
|
||||
try writer.writeAll("]\n");
|
||||
_ = try dumper.dumpInst(writer, frame.callee, frame.ip, true);
|
||||
return writer.flush();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue