Add Vector Types to Ona Script #34

Merged
kayomn merged 4 commits from kym-vector-types into main 2023-08-13 15:39:50 +02:00
5 changed files with 151 additions and 35 deletions

View File

@ -1,6 +1,8 @@
# Test comment.
pos = @vec3(10, 20, 0.3)
options = {
.title = "Afterglow",
.width = 1280,

View File

@ -207,6 +207,16 @@ pub fn Tag(comptime Element: type) type {
pub const Writer = Generator(?usize, []const Byte);
pub fn all_equals(target: []const Byte, match: Byte) bool {
for (0 .. target.len) |index| {
if (target[index] != match) {
return false;
}
}
return true;
}
pub fn allocate_copy(allocator: Allocator, source: []const Byte) AllocationError![]Byte {
const allocation = try allocator.actions.reallocate(allocator.context, @returnAddress(), null, source.len);
@ -265,6 +275,20 @@ pub fn allocate_string(allocator: Allocator, source: []const Byte) AllocationErr
return @ptrCast(allocation);
}
pub fn are_equal(target: []const Byte, match: []const Byte) bool {
if (target.len != match.len) {
return false;
}
for (0 .. target.len) |index| {
if (target[index] != match[index]) {
return false;
}
}
return true;
}
pub fn bytes_of(value: anytype) []const Byte {
const pointer_info = @typeInfo(@TypeOf(value)).Pointer;
@ -326,20 +350,6 @@ pub fn ends_with(target: []const Byte, match: []const Byte) bool {
return true;
}
pub fn equals(target: []const Byte, match: []const Byte) bool {
if (target.len != match.len) {
return false;
}
for (0 .. target.len) |index| {
if (target[index] != match[index]) {
return false;
}
}
return true;
}
pub fn find_first(haystack: []const Byte, needle: Byte) ?usize {
for (0 .. haystack.len) |i| {
if (haystack[i] == needle) {
@ -350,15 +360,23 @@ pub fn find_first(haystack: []const Byte, needle: Byte) ?usize {
return null;
}
var null_context = @as(usize, 0);
pub fn jenkins_hash(comptime int: std.builtin.Type.Int, bytes: []const Byte) math.Int(int) {
var hash = @as(math.Int(int), 0);
pub const null_writer = Writer.bind(usize, &null_context, struct {
fn write(context: *usize, buffer: []const u8) ?usize {
debug.assert(context.* == 0);
for (bytes) |byte| {
hash +%= byte;
hash +%= (hash << 10);
hash ^= (hash >> 6);
}
return buffer.len;
}
}.write);
hash +%= (hash << 3);
hash ^= (hash >> 11);
hash +%= (hash << 15);
return hash;
}
pub const null_writer = Writer.from(write_null);
pub fn slice_sentineled(comptime sen: anytype, ptr: [*:sen]const @TypeOf(sen)) [:sen]const @TypeOf(sen) {
var len = @as(usize, 0);
@ -374,6 +392,10 @@ pub fn tag_of(comptime value: anytype) Tag(@TypeOf(value)) {
return @as(Tag(@TypeOf(value)), value);
}
pub fn write_null(buffer: []const u8) ?usize {
return buffer.len;
}
pub fn zero(target: []Byte) void {
for (target) |*t| t.* = 0;
}

View File

@ -11,7 +11,7 @@ pub fn StringTable(comptime Value: type) type {
const Self = @This();
fn equals(key_a: []const io.Byte, key_b: []const io.Byte) bool {
return io.equals(key_a, key_b);
return io.are_equal(key_a, key_b);
}
fn hash(key: []const io.Byte) usize {

View File

@ -40,7 +40,7 @@ pub const DecimalFormat = struct {
},
else => {
if (self.delimiter.len == 0 or !io.equals(self.delimiter, utf8[index ..])) {
if (self.delimiter.len == 0 or !io.are_equal(self.delimiter, utf8[index ..])) {
return null;
}
},

View File

@ -24,6 +24,8 @@ pub const RuntimeEnv = struct {
const Builtin = enum {
import,
print,
vec2,
vec3,
};
const Constant = union (enum) {
@ -167,15 +169,33 @@ pub const RuntimeEnv = struct {
.builtin => |builtin| {
coral.debug.assert(builtin.len != 0);
const decoded_builtin = @as(?Builtin, switch (builtin[0]) {
'i' => if (coral.io.ends_with(builtin, "mport")) .import else null,
'p' => if (coral.io.ends_with(builtin, "rint")) .print else null,
else => null,
});
switch (builtin[0]) {
'i' => {
if (coral.io.ends_with(builtin, "mport")) {
return chunk.opcodes.push_one(.{.push_builtin = .import});
}
},
try chunk.opcodes.push_one(.{.push_builtin = decoded_builtin orelse {
return chunk.env.raise(error.BadSyntax, "unknown builtin");
}});
'p' => {
if (coral.io.ends_with(builtin, "rint")) {
return chunk.opcodes.push_one(.{.push_builtin = .print});
}
},
'v' => {
if (coral.io.ends_with(builtin, "ec2")) {
return chunk.opcodes.push_one(.{.push_builtin = .vec2});
}
if (coral.io.ends_with(builtin, "ec3")) {
return chunk.opcodes.push_one(.{.push_builtin = .vec3});
}
},
else => {},
}
return chunk.env.raise(error.BadSyntax, "unknown builtin");
},
.local_get => |local_get| {
@ -257,7 +277,7 @@ pub const RuntimeEnv = struct {
var index = @as(u8, self.local_identifiers_count - 1);
while (true) : (index -= 1) {
if (coral.io.equals(local_identifier, self.local_identifiers_buffer[index])) {
if (coral.io.are_equal(local_identifier, self.local_identifiers_buffer[index])) {
return index;
}
@ -361,6 +381,8 @@ pub const RuntimeEnv = struct {
const builtin_syscall = try self.env.new_syscall(switch (push_builtin) {
.import => syscall_import,
.print => syscall_print,
.vec2 => syscall_vec2,
.vec3 => syscall_vec3,
});
errdefer self.env.discard(builtin_syscall);
@ -934,7 +956,7 @@ pub const RuntimeEnv = struct {
const frame = self.frames.peek() orelse return self.raise(error.IllegalState, "stack underflow");
if (index < frame.arg_count) {
if (self.locals.values[frame.locals_top - (1 + index)]) |local| {
if (self.locals.values[(frame.locals_top - frame.arg_count) + index]) |local| {
return self.acquire(local);
}
}
@ -991,7 +1013,7 @@ pub const RuntimeEnv = struct {
if (object.ref_count == 0) {
switch (object.payload) {
.false, .true, .float, .fixed, .symbol, .syscall => {},
.false, .true, .float, .fixed, .symbol, .vector2, .vector3, .syscall => {},
.string => |string| {
coral.debug.assert(string.len >= 0);
@ -1190,6 +1212,20 @@ pub const RuntimeEnv = struct {
});
}
pub fn new_vector2(self: *RuntimeEnv, x: f32, y: f32) RuntimeError!*RuntimeRef {
return RuntimeRef.allocate(self.allocator, .{
.ref_count = 1,
.payload = .{.vector2 = .{x, y}},
});
}
pub fn new_vector3(self: *RuntimeEnv, x: f32, y: f32, z: f32) RuntimeError!*RuntimeRef {
return RuntimeRef.allocate(self.allocator, .{
.ref_count = 1,
.payload = .{.vector3 = .{x, y, z}},
});
}
pub fn print(self: *RuntimeEnv, buffer: []const coral.io.Byte) void {
if (self.options.print) |bound_print| {
bound_print(buffer);
@ -1287,6 +1323,8 @@ pub const RuntimeRef = opaque {
float: Float,
fixed: Fixed,
symbol: [*:0]const coral.io.Byte,
vector2: [2]f32,
vector3: [3]f32,
syscall: *const Syscall,
string: struct {
@ -1357,13 +1395,23 @@ pub const RuntimeRef = opaque {
else => false,
},
.vector2 => |self_vector| switch (other.object().payload) {
.vector2 => |other_vector| coral.io.are_equal(coral.io.bytes_of(&self_vector), coral.io.bytes_of(&other_vector)),
else => false,
},
.vector3 => |self_vector| switch (other.object().payload) {
.vector3 => |other_vector| coral.io.are_equal(coral.io.bytes_of(&self_vector), coral.io.bytes_of(&other_vector)),
else => false,
},
.syscall => |self_syscall| switch (other.object().payload) {
.syscall => |other_syscall| self_syscall == other_syscall,
else => false,
},
.string => |self_string| switch (other.object().payload) {
.string => |other_string| coral.io.equals(self_string.unpack(), other_string.unpack()),
.string => |other_string| coral.io.are_equal(self_string.unpack(), other_string.unpack()),
else => false,
},
@ -1384,6 +1432,8 @@ pub const RuntimeRef = opaque {
.float => |float| @bitCast(float),
.fixed => |fixed| @intCast(@as(u32, @bitCast(fixed))),
.symbol => |symbol| @intFromPtr(symbol),
.vector2 => |vector| @bitCast(vector),
.vector3 => |vector| coral.io.jenkins_hash(@typeInfo(usize).Int, coral.io.bytes_of(&vector)),
.syscall => |syscall| @intFromPtr(syscall),
.string => |string| coral.io.djb2_hash(@typeInfo(usize).Int, string.unpack()),
.dynamic => |dynamic| @intFromPtr(dynamic.typeinfo()) ^ @intFromPtr(dynamic.userdata().ptr),
@ -1404,6 +1454,8 @@ pub const RuntimeRef = opaque {
.float => |float| float != 0,
.fixed => |fixed| fixed != 0,
.symbol => true,
.vector2 => |vector| coral.io.all_equals(coral.io.bytes_of(&vector), 0),
.vector3 => |vector| coral.io.all_equals(coral.io.bytes_of(&vector), 0),
.syscall => true,
.string => |string| string.len != 0,
.dynamic => true,
@ -1480,3 +1532,43 @@ fn syscall_print(env: *RuntimeEnv) RuntimeError!?*RuntimeRef {
return null;
}
fn syscall_vec2(env: *RuntimeEnv) RuntimeError!?*RuntimeRef {
const x = decode: {
const value = try env.expect(try env.acquire_arg(0));
defer env.discard(value);
break: decode @as(f32, @floatCast(try env.unbox_float(value)));
};
if (try env.acquire_arg(1)) |y| {
defer env.discard(y);
return env.new_vector2(x, @floatCast(try env.unbox_float(y)));
}
return env.new_vector2(x, x);
}
fn syscall_vec3(env: *RuntimeEnv) RuntimeError!?*RuntimeRef {
const x = decode: {
const value = try env.expect(try env.acquire_arg(0));
defer env.discard(value);
break: decode @as(f32, @floatCast(try env.unbox_float(value)));
};
if (try env.acquire_arg(1)) |y| {
defer env.discard(y);
const z = try env.expect(try env.acquire_arg(2));
defer env.discard(z);
return env.new_vector3(x, @floatCast(try env.unbox_float(y)), @floatCast(try env.unbox_float(z)));
}
return env.new_vector3(x, x, x);
}