From 9eef1074f9ee54aad360c713e13ca5068cf8a17d Mon Sep 17 00:00:00 2001 From: kayomn Date: Wed, 30 Aug 2023 20:58:06 +0100 Subject: [PATCH] Simply Kym function argument retrieval in VM --- source/ona/app.zig | 2 +- source/ona/kym.zig | 428 +++++++++++++++++++---------------------- source/ona/kym/ast.zig | 14 +- 3 files changed, 201 insertions(+), 243 deletions(-) diff --git a/source/ona/app.zig b/source/ona/app.zig index fc3aa33..10ab8e1 100644 --- a/source/ona/app.zig +++ b/source/ona/app.zig @@ -13,7 +13,7 @@ pub const Manifest = struct { tick_rate: f32 = 60.0, pub fn load(self: *Manifest, env: *kym.RuntimeEnv) kym.RuntimeError!void { - const manifest = try env.expect(try env.import(file.Path.from(&.{"app.ona"}))); + const manifest = try env.import(file.Path.from(&.{"app.ona"})) orelse return; defer env.discard(manifest); diff --git a/source/ona/kym.zig b/source/ona/kym.zig index 1a34fc1..a310dc0 100644 --- a/source/ona/kym.zig +++ b/source/ona/kym.zig @@ -4,6 +4,24 @@ const coral = @import("coral"); const file = @import("./file.zig"); +pub const Frame = struct { + name: []const coral.io.Byte = "", + arg_count: u8, + locals_top: usize, + + pub fn args(self: *const Frame, env: *RuntimeEnv) []const ?*const RuntimeRef { + return env.locals.values[self.locals_top .. (self.locals_top + self.arg_count)]; + } + + pub fn get_arg(self: *const Frame, env: *RuntimeEnv, arg_index: u8) RuntimeError!*const RuntimeRef { + return self.has_arg(env, arg_index) orelse env.raise(error.BadOperation, "nil reference"); + } + + pub fn has_arg(self: *const Frame, env: *RuntimeEnv, arg_index: u8) ?*const RuntimeRef { + return if (arg_index >= self.arg_count) null else env.locals.values[self.locals_top + arg_index]; + } +}; + pub const Fixed = i32; pub const Float = f64; @@ -44,7 +62,6 @@ pub const RuntimeEnv = struct { push_false, push_const: u16, push_local: u8, - push_arg: u8, push_table: u32, push_builtin: Builtin, local_set: u8, @@ -73,7 +90,6 @@ pub const RuntimeEnv = struct { const OpcodeList = coral.list.Stack(Opcode); const CompilationUnit = struct { - args: []const []const coral.io.Byte, locals_buffer: [255]Local = [_]Local{.{}} ** 255, locals_count: u8 = 0, @@ -243,10 +259,6 @@ pub const RuntimeEnv = struct { return chunk.opcodes.push_one(.{.push_local = local.index}); } - if (self.resolve_arg(local_get.identifier)) |arg| { - return chunk.opcodes.push_one(.{.push_arg = arg}); - } - return chunk.env.raise(error.OutOfMemory, "undefined local"); }, @@ -317,16 +329,26 @@ pub const RuntimeEnv = struct { try self.compile_expression(chunk, declare.assigned_expression); - if (self.locals_count == self.locals_buffer.len) { - return chunk.env.raise(error.BadSyntax, "chunks may have a maximum of 255 locals"); + switch (declare.storage) { + .@"var" => { + if (!self.declare_local(.{ + .identifier = declare.identifier, + .is_readonly = false, + })) { + return chunk.env.raise(error.BadSyntax, "too many locals"); + } + }, + + .let => { + // TODO: investigate constant folding. + if (!self.declare_local(.{ + .identifier = declare.identifier, + .is_readonly = false, + })) { + return chunk.env.raise(error.BadSyntax, "too many locals"); + } + }, } - - self.locals_buffer[self.locals_count] = .{ - .identifier = declare.identifier, - .is_readonly = declare.storage != .variant, - }; - - self.locals_count += 1; }, .block => |block| { @@ -378,16 +400,15 @@ pub const RuntimeEnv = struct { } } - fn resolve_arg(self: *CompilationUnit, arg_identifier: []const coral.io.Byte) ?u8 { - var index = @as(u8, 0); - - while (index < self.args.len) { - if (coral.io.are_equal(self.args[index], arg_identifier)) { - return index; - } + fn declare_local(self: *CompilationUnit, local: Local) bool { + if (self.locals_count == self.locals_buffer.len) { + return false; } - return null; + self.locals_buffer[self.locals_count] = local; + self.locals_count += 1; + + return true; } fn resolve_local(self: *CompilationUnit, local_identifier: []const coral.io.Byte) ?ResolvedLocal { @@ -415,9 +436,18 @@ pub const RuntimeEnv = struct { }; fn compile(self: *Chunk, statements: []const ast.Statement, args: []const []const coral.io.Byte) RuntimeError!void { - var unit = CompilationUnit{.args = args}; + var unit = CompilationUnit{}; var has_returned = false; + for (args) |arg| { + if (!unit.declare_local(.{ + .is_readonly = true, + .identifier = arg, + })) { + return self.env.raise(error.BadSyntax, "too many arguments"); + } + } + for (statements) |statement| { try unit.compile_statement(self, statement); @@ -456,7 +486,7 @@ pub const RuntimeEnv = struct { return @intCast(self.constants.values.len - 1); } - fn execute(self: *Chunk) RuntimeError!?*RuntimeRef { + fn execute(self: *Chunk, frame: Frame) RuntimeError!?*RuntimeRef { var opcode_cursor = @as(u32, 0); while (opcode_cursor < self.opcodes.values.len) : (opcode_cursor += 1) { @@ -484,25 +514,13 @@ pub const RuntimeEnv = struct { return self.env.raise(error.IllegalState, "invalid local"); } - if (self.env.locals.values[push_local]) |local| { + if (self.env.locals.values[frame.locals_top + push_local]) |local| { try self.env.locals.push_one(try self.env.acquire(local)); } else { try self.env.locals.push_one(null); } }, - .push_arg => |push_arg| { - const arg = try self.env.acquire_arg(push_arg); - - errdefer { - if (arg) |ref| { - self.env.discard(ref); - } - } - - try self.env.locals.push_one(arg); - }, - .push_table => |push_table| { const table = try self.env.new_table(); @@ -511,25 +529,19 @@ pub const RuntimeEnv = struct { { const dynamic = table.object().payload.dynamic; const userdata = dynamic.userdata(); + const table_set = dynamic.typeinfo().set; var popped = @as(usize, 0); while (popped < push_table) : (popped += 1) { - const index = try self.env.expect(try self.pop_local()); + const index = try self.expect(try self.pop_local()); defer self.env.discard(index); - const maybe_value = try self.pop_local(); + if (try self.pop_local()) |value| { + defer self.env.discard(value); - defer { - if (maybe_value) |value| { - self.env.discard(value); - } + try table_set(self.env, userdata, index, value); } - - try dynamic.typeinfo().set(.{ - .userdata = userdata, - .env = self.env, - }, index, maybe_value); } } @@ -550,7 +562,7 @@ pub const RuntimeEnv = struct { }, .local_set => |local_set| { - const local = &self.env.locals.values[local_set]; + const local = &self.env.locals.values[frame.locals_top + local_set]; if (local.*) |previous_local| { self.env.discard(previous_local); @@ -560,11 +572,11 @@ pub const RuntimeEnv = struct { }, .object_get => { - const index = try self.env.expect(try self.pop_local()); + const index = try self.expect(try self.pop_local()); defer self.env.discard(index); - const indexable = try self.env.expect(try self.pop_local()); + const indexable = try self.expect(try self.pop_local()); defer self.env.discard(indexable); @@ -605,28 +617,17 @@ pub const RuntimeEnv = struct { .object_call => |object_call| { const result = call: { - const callable = try self.env.expect(try self.pop_local()); + const callable = try self.expect(try self.pop_local()); defer self.env.discard(callable); - try self.env.frames.push_one(.{ - .name = "", - .arg_count = object_call, - .locals_top = self.env.locals.values.len, - }); + const call_frame = try self.env.push_frame(object_call); - defer coral.debug.assert(self.env.frames.pop() != null); - - const payload = callable.object().payload; - - break: call try switch (payload) { - .syscall => |syscall| syscall(self.env), - - .dynamic => |dynamic| dynamic.typeinfo().call(.{ - .userdata = dynamic.userdata(), - .env = self.env, - }), + defer self.env.pop_frame(); + break: call try switch (callable.object().payload) { + .syscall => |syscall| syscall(self.env, call_frame), + .dynamic => |dynamic| dynamic.typeinfo().call(self.env, dynamic.userdata(), call_frame), else => self.env.raise(error.TypeMismatch, "object is not callable"), }; }; @@ -637,12 +638,6 @@ pub const RuntimeEnv = struct { } } - for (0 .. object_call) |_| { - if (try self.pop_local()) |popped_arg| { - self.env.discard(popped_arg); - } - } - try self.env.locals.push_one(result); }, @@ -657,7 +652,7 @@ pub const RuntimeEnv = struct { }, .neg => { - const value = try self.env.expect(try self.pop_local()); + const value = try self.expect(try self.pop_local()); defer self.env.discard(value); @@ -669,11 +664,11 @@ pub const RuntimeEnv = struct { }, .add => { - const rhs = try self.env.expect(try self.pop_local()); + const rhs = try self.expect(try self.pop_local()); defer self.env.discard(rhs); - const lhs = try self.env.expect(try self.pop_local()); + const lhs = try self.expect(try self.pop_local()); defer self.env.discard(lhs); @@ -709,11 +704,11 @@ pub const RuntimeEnv = struct { }, .sub => { - const rhs = try self.env.expect(try self.pop_local()); + const rhs = try self.expect(try self.pop_local()); defer self.env.discard(rhs); - const lhs = try self.env.expect(try self.pop_local()); + const lhs = try self.expect(try self.pop_local()); defer self.env.discard(lhs); @@ -749,11 +744,11 @@ pub const RuntimeEnv = struct { }, .mul => { - const rhs = try self.env.expect(try self.pop_local()); + const rhs = try self.expect(try self.pop_local()); defer self.env.discard(rhs); - const lhs = try self.env.expect(try self.pop_local()); + const lhs = try self.expect(try self.pop_local()); defer self.env.discard(lhs); @@ -789,11 +784,11 @@ pub const RuntimeEnv = struct { }, .div => { - const rhs = try self.env.expect(try self.pop_local()); + const rhs = try self.expect(try self.pop_local()); defer self.env.discard(rhs); - const lhs = try self.env.expect(try self.pop_local()); + const lhs = try self.expect(try self.pop_local()); defer self.env.discard(lhs); @@ -845,11 +840,11 @@ pub const RuntimeEnv = struct { }, .cgt => { - const rhs = try self.env.expect(try self.pop_local()); + const rhs = try self.expect(try self.pop_local()); defer self.env.discard(rhs); - const lhs = try self.env.expect(try self.pop_local()); + const lhs = try self.expect(try self.pop_local()); defer self.env.discard(lhs); @@ -871,11 +866,11 @@ pub const RuntimeEnv = struct { }, .clt => { - const rhs = try self.env.expect(try self.pop_local()); + const rhs = try self.expect(try self.pop_local()); defer self.env.discard(rhs); - const lhs = try self.env.expect(try self.pop_local()); + const lhs = try self.expect(try self.pop_local()); defer self.env.discard(lhs); @@ -897,11 +892,11 @@ pub const RuntimeEnv = struct { }, .cge => { - const rhs = try self.env.expect(try self.pop_local()); + const rhs = try self.expect(try self.pop_local()); defer self.env.discard(rhs); - const lhs = try self.env.expect(try self.pop_local()); + const lhs = try self.expect(try self.pop_local()); defer self.env.discard(lhs); @@ -923,11 +918,11 @@ pub const RuntimeEnv = struct { }, .cle => { - const rhs = try self.env.expect(try self.pop_local()); + const rhs = try self.expect(try self.pop_local()); defer self.env.discard(rhs); - const lhs = try self.env.expect(try self.pop_local()); + const lhs = try self.expect(try self.pop_local()); defer self.env.discard(lhs); @@ -977,6 +972,10 @@ pub const RuntimeEnv = struct { return self.pop_local(); } + fn expect(self: *Chunk, value: ?*RuntimeRef) RuntimeError!*RuntimeRef { + return value orelse self.env.raise(error.TypeMismatch, "nil reference"); + } + fn free(self: *Chunk) void { while (self.constants.pop()) |constant| { self.env.discard(constant); @@ -1001,28 +1000,26 @@ pub const RuntimeEnv = struct { return self.env.locals.pop() orelse self.env.raise(error.IllegalState, "stack underflow"); } - fn typeinfo_call(method: Typeinfo.Method) RuntimeError!?*RuntimeRef { - const chunk = @as(*Chunk, @ptrCast(@alignCast(method.userdata))); + fn typeinfo_call(env: *RuntimeEnv, userdata: []coral.io.Byte, frame: Frame) RuntimeError!?*RuntimeRef { + const chunk = @as(*Chunk, @ptrCast(@alignCast(userdata))); - if ((method.env.view_args() catch unreachable).len < chunk.arity) { - return method.env.raise(error.BadOperation, "expected more arguments"); + if (frame.arg_count < chunk.arity) { + return env.raise(error.BadOperation, "expected more arguments"); } - return chunk.execute(); + return chunk.execute(frame); } - fn typeinfo_destruct(method: Typeinfo.Method) void { - @as(*Chunk, @ptrCast(@alignCast(method.userdata))).free(); + fn typeinfo_destruct(env: *RuntimeEnv, userdata: []coral.io.Byte) void { + _ = env; + + @as(*Chunk, @ptrCast(@alignCast(userdata))).free(); } }; const ConstList = coral.list.Stack(*RuntimeRef); - const FrameStack = coral.list.Stack(struct { - name: []const coral.io.Byte, - arg_count: u8, - locals_top: usize, - }); + const FrameStack = coral.list.Stack(Frame); pub const Options = struct { import_access: file.Access = .null, @@ -1046,15 +1043,15 @@ pub const RuntimeEnv = struct { associative: RefTable, contiguous: RefList, - fn typeinfo_destruct(method: Typeinfo.Method) void { - const table = @as(*Table, @ptrCast(@alignCast(method.userdata))); + fn typeinfo_destruct(env: *RuntimeEnv, userdata: []coral.io.Byte) void { + const table = @as(*Table, @ptrCast(@alignCast(userdata))); { var field_iterable = table.associative.as_iterable(); while (field_iterable.next()) |entry| { - method.env.discard(entry.key); - method.env.discard(entry.value); + env.discard(entry.key); + env.discard(entry.value); } } @@ -1062,18 +1059,18 @@ pub const RuntimeEnv = struct { while (table.contiguous.pop()) |value| { if (value) |ref| { - method.env.discard(ref); + env.discard(ref); } } table.contiguous.free(); } - fn typeinfo_get(method: Typeinfo.Method, index: *const RuntimeRef) RuntimeError!?*RuntimeRef { - const table = @as(*Table, @ptrCast(@alignCast(method.userdata))); - const acquired_index = try method.env.acquire(index); + fn typeinfo_get(env: *RuntimeEnv, userdata: []coral.io.Byte, index: *const RuntimeRef) RuntimeError!?*RuntimeRef { + const table = @as(*Table, @ptrCast(@alignCast(userdata))); + const acquired_index = try env.acquire(index); - defer method.env.discard(acquired_index); + defer env.discard(acquired_index); if (acquired_index.is_fixed()) |fixed| { if (fixed < 0) { @@ -1082,22 +1079,22 @@ pub const RuntimeEnv = struct { } if (fixed < table.contiguous.values.len) { - return method.env.acquire(table.contiguous.values[@intCast(fixed)] orelse return null); + return env.acquire(table.contiguous.values[@intCast(fixed)] orelse return null); } } if (table.associative.lookup(acquired_index)) |value_ref| { - return method.env.acquire(value_ref); + return env.acquire(value_ref); } return null; } - fn typeinfo_set(method: Typeinfo.Method, index: *const RuntimeRef, value: ?*const RuntimeRef) RuntimeError!void { - const table = @as(*Table, @ptrCast(@alignCast(method.userdata))); - const acquired_index = try method.env.acquire(index); + fn typeinfo_set(env: *RuntimeEnv, userdata: []coral.io.Byte, index: *const RuntimeRef, value: ?*const RuntimeRef) RuntimeError!void { + const table = @as(*Table, @ptrCast(@alignCast(userdata))); + const acquired_index = try env.acquire(index); - errdefer method.env.discard(acquired_index); + errdefer env.discard(acquired_index); if (acquired_index.is_fixed()) |fixed| { if (fixed < 0) { @@ -1109,29 +1106,29 @@ pub const RuntimeEnv = struct { const maybe_replacing = &table.contiguous.values[@intCast(fixed)]; if (maybe_replacing.*) |replacing| { - method.env.discard(replacing); + env.discard(replacing); } - maybe_replacing.* = if (value) |ref| try method.env.acquire(ref) else null; + maybe_replacing.* = if (value) |ref| try env.acquire(ref) else null; return; } } - const acquired_value = try method.env.acquire(value orelse { + const acquired_value = try env.acquire(value orelse { if (table.associative.remove(acquired_index)) |removed| { - method.env.discard(removed.key); - method.env.discard(removed.value); + env.discard(removed.key); + env.discard(removed.value); } return; }); - errdefer method.env.discard(acquired_value); + errdefer env.discard(acquired_value); if (try table.associative.replace(acquired_index, acquired_value)) |replaced| { - method.env.discard(replaced.key); - method.env.discard(replaced.value); + env.discard(replaced.key); + env.discard(replaced.value); } } }; @@ -1146,30 +1143,15 @@ pub const RuntimeEnv = struct { return @ptrCast(object); } - pub fn acquire_arg(self: *RuntimeEnv, index: usize) RuntimeError!?*RuntimeRef { - 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 - frame.arg_count) + index]) |local| { - return self.acquire(local); - } + pub fn call(self: *RuntimeEnv, callable: *RuntimeRef, args: []const *RuntimeRef) RuntimeError!?*RuntimeRef { + // TODO: Handle errors. + for (args) |arg| { + try self.locals.push_one(try self.acquire(arg)); } - return null; - } + try self.push_frame(args.len); - pub fn call(self: *RuntimeEnv, callable: *RuntimeRef, args: []const *RuntimeRef) RuntimeError!?*RuntimeRef { - try self.locals.push_all(args); - - defer coral.io.assert(self.locals.drop(args.len)); - - try self.frames.push_one(.{ - .name = "", - .arg_count = args.len, - .locals_top = self.locals.values.len, - }); - - defer coral.io.assert(self.frames.pop() != null); + defer self.pop_frame(); return switch (callable.object().payload) { .syscall => |syscall| syscall(self.env), @@ -1201,10 +1183,7 @@ pub const RuntimeEnv = struct { .dynamic => |dynamic| { if (dynamic.typeinfo().destruct) |destruct| { - destruct(.{ - .userdata = dynamic.userdata(), - .env = self, - }); + destruct(self, dynamic.userdata()); } self.allocator.deallocate(dynamic.unpack()); @@ -1236,19 +1215,11 @@ pub const RuntimeEnv = struct { error.OutOfMemory => error.OutOfMemory, }, &.{}); - try self.frames.push_one(.{ - .name = file_name, - .arg_count = 0, - .locals_top = self.locals.values.len, - }); + const frame = try self.push_frame(0); - defer coral.debug.assert(self.frames.pop() != null); + defer self.pop_frame(); - return chunk.execute(); - } - - pub fn expect(self: *RuntimeEnv, value: ?*RuntimeRef) RuntimeError!*RuntimeRef { - return value orelse self.raise(error.TypeMismatch, "nil reference"); + return chunk.execute(frame); } pub fn free(self: *RuntimeEnv) void { @@ -1273,6 +1244,14 @@ pub const RuntimeEnv = struct { pub fn get(self: *RuntimeEnv, indexable: *RuntimeRef, index: *const RuntimeRef) RuntimeError!?*RuntimeRef { return switch (indexable.object().payload) { + .false => self.raise(error.TypeMismatch, "false is not get-indexable"), + .true => self.raise(error.TypeMismatch, "true is not get-indexable"), + .fixed => self.raise(error.TypeMismatch, "fixed is not get-indexable"), + .float => self.raise(error.TypeMismatch, "float is not get-indexable"), + .string => self.raise(error.TypeMismatch, "string is not get-indexable"), + .symbol => self.raise(error.TypeMismatch, "symbol is not get-indexable"), + .syscall => self.raise(error.TypeMismatch, "syscall is not get-indexable"), + .vector2 => |vector2| swizzle: { const swizzle_symbol = try self.unbox_symbol(index); var swizzle_buffer = [_]f32{0} ** 3; @@ -1324,12 +1303,7 @@ pub const RuntimeEnv = struct { } }, - .dynamic => |dynamic| dynamic.typeinfo().get(.{ - .userdata = dynamic.userdata(), - .env = self, - }, index), - - else => self.raise(error.TypeMismatch, "object is not get-indexable"), + .dynamic => |dynamic| dynamic.typeinfo().get(self, dynamic.userdata(), index), }; } @@ -1474,6 +1448,29 @@ pub const RuntimeEnv = struct { } } + fn pop_frame(self: *RuntimeEnv) void { + var to_pop = self.locals.values.len - (self.frames.pop() orelse unreachable).locals_top; + + while (to_pop != 0) { + if (self.locals.pop() orelse unreachable) |local| { + self.discard(local); + } + + to_pop -= 1; + } + } + + fn push_frame(self: *RuntimeEnv, arg_count: u8) RuntimeError!Frame { + const frame = Frame{ + .arg_count = arg_count, + .locals_top = self.locals.values.len - arg_count, + }; + + try self.frames.push_one(frame); + + return frame; + } + pub fn raise(self: *RuntimeEnv, error_value: RuntimeError, message: []const coral.io.Byte) RuntimeError { self.print_error(message); @@ -1494,11 +1491,7 @@ pub const RuntimeEnv = struct { pub fn set(self: *RuntimeEnv, indexable: *RuntimeRef, index: *const RuntimeRef, value: ?*const RuntimeRef) RuntimeError!void { return switch (indexable.object().payload) { - .dynamic => |dynamic| dynamic.typeinfo().set(.{ - .userdata = dynamic.userdata(), - .env = self, - }, index, value), - + .dynamic => |dynamic| dynamic.typeinfo().set(self, dynamic.userdata(), index, value), else => self.raise(error.TypeMismatch, "object is not set-indexable"), }; } @@ -1540,12 +1533,6 @@ pub const RuntimeEnv = struct { else => env.raise(error.TypeMismatch, "expected symbol object") }; } - - pub fn view_args(self: *RuntimeEnv) RuntimeError![]const ?*const RuntimeRef { - const frame = self.frames.peek() orelse return self.raise(error.IllegalState, "stack underflow"); - - return self.locals.values[(frame.locals_top - frame.arg_count) ..]; - } }; pub const RuntimeError = coral.io.AllocationError || error { @@ -1720,31 +1707,26 @@ pub const RuntimeRef = opaque { } }; -pub const Syscall = fn (env: *RuntimeEnv) RuntimeError!?*RuntimeRef; +pub const Syscall = fn (env: *RuntimeEnv, frame: Frame) RuntimeError!?*RuntimeRef; pub const Typeinfo = struct { name: []const coral.io.Byte, size: usize, - destruct: ?*const fn (method: Method) void = null, - call: *const fn (method: Method) RuntimeError!?*RuntimeRef = default_call, - get: *const fn (method: Method, index: *const RuntimeRef) RuntimeError!?*RuntimeRef = default_get, - set: *const fn (method: Method, value: *const RuntimeRef, value: ?*const RuntimeRef) RuntimeError!void = default_set, + destruct: ?*const fn (env: *RuntimeEnv, userdata: []coral.io.Byte) void = null, + call: *const fn (env: *RuntimeEnv, userdata: []coral.io.Byte, frame: Frame) RuntimeError!?*RuntimeRef = default_call, + get: *const fn (env: *RuntimeEnv, userdata: []coral.io.Byte, index: *const RuntimeRef) RuntimeError!?*RuntimeRef = default_get, + set: *const fn (env: *RuntimeEnv, userdata: []coral.io.Byte, value: *const RuntimeRef, value: ?*const RuntimeRef) RuntimeError!void = default_set, - pub const Method = struct { - env: *RuntimeEnv, - userdata: []coral.io.Byte, - }; - - fn default_call(method: Method) RuntimeError!?*RuntimeRef { - return method.env.raise(error.TypeMismatch, "object is not callable"); + fn default_call(env: *RuntimeEnv, _: []coral.io.Byte, _: Frame) RuntimeError!?*RuntimeRef { + return env.raise(error.BadOperation, "object is not callable"); } - fn default_get(method: Method, _: *const RuntimeRef) RuntimeError!?*RuntimeRef { - return method.env.raise(error.TypeMismatch, "object is not index-gettable"); + fn default_get(env: *RuntimeEnv, _: []coral.io.Byte, _: *const RuntimeRef) RuntimeError!?*RuntimeRef { + return env.raise(error.BadOperation, "object is not get-indexable"); } - fn default_set(method: Method, _: *const RuntimeRef, _: ?*const RuntimeRef) RuntimeError!void { - return method.env.raise(error.TypeMismatch, "object is not index-settable"); + fn default_set(env: *RuntimeEnv, _: []coral.io.Byte, _: *const RuntimeRef, _: ?*const RuntimeRef) RuntimeError!void { + return env.raise(error.BadOperation, "object is not set-indexable"); } }; @@ -1772,59 +1754,35 @@ pub fn get_key(env: *RuntimeEnv, indexable: *RuntimeRef, key: []const coral.io.B return env.get(indexable, key_string); } -fn syscall_import(env: *RuntimeEnv) RuntimeError!?*RuntimeRef { - const arg = try env.expect(try env.acquire_arg(0)); - - defer env.discard(arg); - - return env.import(file.Path.from(&.{try env.unbox_string(arg)})); +fn syscall_import(env: *RuntimeEnv, frame: Frame) RuntimeError!?*RuntimeRef { + return env.import(file.Path.from(&.{try env.unbox_string(try frame.get_arg(env, 0))})); } -fn syscall_print(env: *RuntimeEnv) RuntimeError!?*RuntimeRef { - const arg = try env.expect(try env.acquire_arg(0)); - - defer env.discard(arg); - - env.print(try env.unbox_string(arg)); +fn syscall_print(env: *RuntimeEnv, frame: Frame) RuntimeError!?*RuntimeRef { + env.print(try env.unbox_string(try frame.get_arg(env, 0))); 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); +fn syscall_vec2(env: *RuntimeEnv, frame: Frame) RuntimeError!?*RuntimeRef { + const x = @as(f32, @floatCast(try env.unbox_float(try frame.get_arg(env, 0)))); + if (frame.has_arg(env, 1)) |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)); +fn syscall_vec3(env: *RuntimeEnv, frame: Frame) RuntimeError!?*RuntimeRef { + const x = @as(f32, @floatCast(try env.unbox_float(try frame.get_arg(env, 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))); + if (frame.has_arg(env, 1)) |y| { + return env.new_vector3( + x, + @floatCast(try env.unbox_float(y)), + @floatCast(try env.unbox_float(try frame.get_arg(env, 2))), + ); } return env.new_vector3(x, x, x); diff --git a/source/ona/kym/ast.zig b/source/ona/kym/ast.zig index e3ba5f8..9b49978 100644 --- a/source/ona/kym/ast.zig +++ b/source/ona/kym/ast.zig @@ -134,11 +134,6 @@ pub const Expression = union (enum) { }); }; -pub const DeclarationStorage = enum { - variant, - readonly, -}; - const ExpressionBuilder = fn (self: *Tree) ParseError!Expression; const IdentifierList = coral.list.Stack([]const coral.io.Byte); @@ -171,6 +166,11 @@ pub const Statement = union (enum) { block: List, expression: Expression, + pub const DeclarationStorage = enum { + @"var", + let, + }; + const List = coral.list.Stack(Statement); }; @@ -740,7 +740,7 @@ pub const Tree = struct { return .{ .declare = .{ .assigned_expression = try self.parse_expression(), - .storage = .variant, + .storage = .@"var", .identifier = identifier, }, }; @@ -765,7 +765,7 @@ pub const Tree = struct { return .{ .declare = .{ .assigned_expression = try self.parse_expression(), - .storage = .readonly, + .storage = .let, .identifier = identifier, }, };