diff --git a/debug/app.ona b/debug/app.ona index f05118d..bb14b64 100644 --- a/debug/app.ona +++ b/debug/app.ona @@ -1,29 +1,18 @@ -let printer = lambda (): +let test_param = "monkey wrench" + +let printer = lambda (pfx): + @print(test_param) + return lambda (msg): - @print("This is a func call") + @print(pfx) @print(msg) end end -let pr = printer() -var i = 0 +let pr = printer("this is a final closure") -pr("test") - -while i < 5: - pr("hello, world") - - i = i + 1 -end - -if i > 6: - pr("`i` greater than `6`") -elif i == 4: - pr("`i` is equal to `4`") -else: - pr("i'unno") -end +pr("goodbye") return { .title = "Game", diff --git a/source/coral/utf8.zig b/source/coral/utf8.zig index dee3f8b..f7ddcc6 100644 --- a/source/coral/utf8.zig +++ b/source/coral/utf8.zig @@ -196,6 +196,8 @@ pub const HexadecimalFormat = struct { _ = self; _ = writer; _ = value; + + unreachable; } }; diff --git a/source/ona/app.zig b/source/ona/app.zig index 10ab8e1..0ef5952 100644 --- a/source/ona/app.zig +++ b/source/ona/app.zig @@ -21,7 +21,7 @@ pub const Manifest = struct { if (try kym.get_field(env, manifest, "width")) |ref| { defer env.discard(ref); - const fixed = try env.unbox_fixed(ref); + const fixed = try env.unwrap_fixed(ref); if (fixed > 0 and fixed < coral.math.max_int(@typeInfo(@TypeOf(self.width)).Int)) { break: get @intCast(fixed); @@ -35,7 +35,7 @@ pub const Manifest = struct { if (try kym.get_field(env, manifest, "height")) |ref| { defer env.discard(ref); - const fixed = try env.unbox_fixed(ref); + const fixed = try env.unwrap_fixed(ref); if (fixed > 0 and fixed < coral.math.max_int(@typeInfo(@TypeOf(self.height)).Int)) { break: get @intCast(fixed); @@ -49,7 +49,7 @@ pub const Manifest = struct { if (try kym.get_field(env, manifest, "tick_rate")) |ref| { defer env.discard(ref); - break: get @floatCast(try env.unbox_float(ref)); + break: get @floatCast(try env.unwrap_float(ref)); } break: get self.tick_rate; @@ -58,7 +58,7 @@ pub const Manifest = struct { if (try kym.get_field(env, manifest, "title")) |ref| { defer env.discard(ref); - const title_string = try env.unbox_string(ref); + const title_string = try env.unwrap_string(ref); const limited_title_len = @min(title_string.len, self.title.len); coral.io.copy(&self.title, title_string[0 .. limited_title_len]); diff --git a/source/ona/file.zig b/source/ona/file.zig index b05ae92..73a5b98 100644 --- a/source/ona/file.zig +++ b/source/ona/file.zig @@ -11,9 +11,9 @@ pub const Access = union (enum) { .null => return null, .sandboxed_path => |sandboxed_path| { - const readable_path_string = sandboxed_path.joined(readable_path).to_string() orelse return null; + const path_string = sandboxed_path.joined(readable_path).get_string(); - return @ptrCast(ext.SDL_RWFromFile(readable_path_string.ptr, "rb")); + return @ptrCast(ext.SDL_RWFromFile(path_string.ptr, "rb")); }, } } @@ -23,7 +23,7 @@ pub const Access = union (enum) { .null => return null, .sandboxed_path => |sandboxed_path| { - const path_string = sandboxed_path.joined(path).to_string() orelse return null; + const path_string = sandboxed_path.joined(path).get_string(); const rw_ops = ext.SDL_RWFromFile(path_string, "rb") orelse return null; const file_size = ext.SDL_RWseek(rw_ops, 0, ext.RW_SEEK_END); @@ -96,12 +96,8 @@ pub const Path = extern struct { return path; } - pub fn to_string(self: Path) ?[:0]const coral.io.Byte { - const last_index = self.data.len - 1; - - if (self.data[last_index] != 0) { - return null; - } + pub fn get_string(self: Path) [:0]const coral.io.Byte { + coral.debug.assert(self.data[self.data.len - 1] == 0); return coral.io.slice_sentineled(@as(coral.io.Byte, 0), @as([*:0]const coral.io.Byte, @ptrCast(&self.data))); } diff --git a/source/ona/kym.zig b/source/ona/kym.zig index d56c80f..5004f9c 100644 --- a/source/ona/kym.zig +++ b/source/ona/kym.zig @@ -2,10 +2,6 @@ const Chunk = @import("./kym/Chunk.zig"); const Table = @import("./kym/Table.zig"); -const app = @import("./app.zig"); - -const builtin = @import("builtin"); - const coral = @import("coral"); const file = @import("./file.zig"); @@ -15,7 +11,7 @@ const tokens = @import("./kym/tokens.zig"); const tree = @import("./kym/tree.zig"); pub const Frame = struct { - name: []const coral.io.Byte = "", + name_stringable: *RuntimeRef, arg_count: u8, locals_top: usize, @@ -23,8 +19,8 @@ pub const Frame = struct { 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 expect_arg(self: *const Frame, env: *RuntimeEnv, arg_index: u8) RuntimeError!*const RuntimeRef { + return self.has_arg(env, arg_index) orelse env.raise(error.TypeMismatch, "nil reference", .{}); } pub fn has_arg(self: *const Frame, env: *RuntimeEnv, arg_index: u8) ?*const RuntimeRef { @@ -69,16 +65,24 @@ pub const RuntimeEnv = struct { }, .float => |rhs_float| self.new_float(@as(Float, @floatFromInt(lhs_fixed)) + rhs_float), - else => self.raise(error.TypeMismatch, "right-hand object is not addable"), + + else => self.raise(error.TypeMismatch, "right-hand {typename} is not addable", .{ + .typename = rhs.typename(), + }), }, .float => |lhs_float| switch (rhs.object().payload) { .float => |rhs_float| self.new_float(lhs_float + rhs_float), .fixed => |rhs_fixed| self.new_float(lhs_float + @as(Float, @floatFromInt(rhs_fixed))), - else => self.raise(error.TypeMismatch, "right-hand object is not addable"), + + else => self.raise(error.TypeMismatch, "right-hand {typename} is not addable", .{ + .typename = rhs.typename(), + }), }, - else => self.raise(error.TypeMismatch, "left-hand object is not addable"), + else => self.raise(error.TypeMismatch, "left-hand {typename} is not addable", .{ + .typename = lhs.typename(), + }), }; } @@ -88,18 +92,18 @@ pub const RuntimeEnv = struct { try self.locals.push_one(try self.acquire(arg)); } - const frame = try self.push_frame(args.len); + const frame = try self.push_frame(callable, args.len); defer self.pop_frame(); - return self.call_frame(callable, frame); + return self.call_frame(frame); } pub fn call_frame(self: *RuntimeEnv, callable: *const RuntimeRef, frame: Frame) RuntimeError!?*RuntimeRef { return switch (callable.object().payload) { .syscall => |syscall| syscall(self, frame), .dynamic => |dynamic| dynamic.typeinfo().call(self, dynamic.userdata(), frame), - else => self.raise(error.TypeMismatch, "object is not callable"), + else => self.raise(error.TypeMismatch, "{typename} is not callable", .{.typename = callable.typename()}), }; } @@ -108,16 +112,24 @@ pub const RuntimeEnv = struct { .fixed => |lhs_fixed| switch (rhs.object().payload) { .fixed => |rhs_fixed| @as(Float, @floatFromInt(lhs_fixed)) - @as(Float, @floatFromInt(rhs_fixed)), .float => |rhs_float| @as(Float, @floatFromInt(lhs_fixed)) - rhs_float, - else => return self.raise(error.TypeMismatch, "right-hand object is not comparable"), + + else => return self.raise(error.TypeMismatch, "right-hand {typename} is not comparable", .{ + .typename = rhs.typename(), + }), }, .float => |lhs_float| switch (rhs.object().payload) { .float => |rhs_float| lhs_float - rhs_float, .fixed => |rhs_fixed| lhs_float - @as(Float, @floatFromInt(rhs_fixed)), - else => return self.raise(error.TypeMismatch, "right-hand object is not comparable"), + + else => return self.raise(error.TypeMismatch, "right-hand {typename} is not comparable", .{ + .typename = rhs.typename(), + }), }, - else => return self.raise(error.TypeMismatch, "left-hand object is not comparable"), + else => return self.raise(error.TypeMismatch, "left-hand {typename} is not comparable", .{ + .typename = lhs.typename(), + }), }; } @@ -132,6 +144,12 @@ pub const RuntimeEnv = struct { switch (object.payload) { .false, .true, .float, .fixed, .symbol, .vector2, .vector3, .syscall => {}, + .boxed => |*boxed| { + if (boxed.*) |boxed_value| { + self.discard(boxed_value); + } + }, + .string => |string| { coral.debug.assert(string.len >= 0); self.allocator.deallocate(string.ptr[0 .. @intCast(string.len)]); @@ -155,21 +173,29 @@ pub const RuntimeEnv = struct { .fixed => |lhs_fixed| switch (rhs.object().payload) { .fixed => |rhs_fixed| self.new_float(@as(Float, @floatFromInt(lhs_fixed)) / @as(Float, @floatFromInt(rhs_fixed))), .float => |rhs_float| self.new_float(@as(Float, @floatFromInt(lhs_fixed)) / rhs_float), - else => self.raise(error.TypeMismatch, "right-hand object is not divisible"), + + else => self.raise(error.TypeMismatch, "right-hand {typename} is not divisible", .{ + .typename = rhs.typename(), + }), }, .float => |lhs_float| switch (rhs.object().payload) { .float => |rhs_float| self.new_float(lhs_float / rhs_float), .fixed => |rhs_fixed| self.new_float(lhs_float / @as(Float, @floatFromInt(rhs_fixed))), - else => self.raise(error.TypeMismatch, "right-hand object is not divisible"), + + else => self.raise(error.TypeMismatch, "right-hand {typename} is not divisible", .{ + .typename = rhs.typename(), + }), }, - else => self.raise(error.TypeMismatch, "left-hand object is not divisible"), + else => self.raise(error.TypeMismatch, "left-hand {typename} is not divisible", .{ + .typename = lhs.typename(), + }), }; } pub fn expect(self: *RuntimeEnv, value: ?*RuntimeRef) RuntimeError!*RuntimeRef { - return value orelse self.raise(error.TypeMismatch, "nil reference"); + return value orelse self.raise(error.TypeMismatch, "nil reference", .{}); } pub fn free(self: *RuntimeEnv) void { @@ -194,16 +220,8 @@ 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); + const swizzle_symbol = try self.unwrap_symbol(index); var swizzle_buffer = [_]f32{0} ** 3; var swizzle_count = @as(usize, 0); @@ -228,7 +246,7 @@ pub const RuntimeEnv = struct { }, .vector3 => |vector3| swizzle: { - const swizzle_symbol = try self.unbox_symbol(index); + const swizzle_symbol = try self.unwrap_symbol(index); var swizzle_buffer = [_]f32{0} ** 3; var swizzle_count = @as(usize, 0); @@ -254,14 +272,22 @@ pub const RuntimeEnv = struct { }, .dynamic => |dynamic| dynamic.typeinfo().get(self, dynamic.userdata(), index), + + else => self.raise(error.TypeMismatch, "{typename} is not get-indexable", .{ + .typename = indexable.typename(), + }), }; } pub fn import(self: *RuntimeEnv, file_path: file.Path) RuntimeError!?*RuntimeRef { + const file_name = file_path.get_string(); + var chunk = make_chunk: { const file_data = (try file.allocate_and_load(self.allocator, self.options.import_access, file_path)) orelse { - return self.raise(error.BadOperation, "failed to open or read file specified"); + return self.raise(error.BadOperation, "failed to open or read `{name}`", .{ + .name = file_name, + }); }; defer self.allocator.deallocate(file_data); @@ -282,24 +308,21 @@ pub const RuntimeEnv = struct { }; } - break: make_chunk try Chunk.make(self, file_path.to_string() orelse "