diff --git a/debug/app.ona b/debug/app.ona index 54676d5..d25f721 100644 --- a/debug/app.ona +++ b/debug/app.ona @@ -14,8 +14,12 @@ options = { [42] = "42", } -options["foo"] = "rab" -options[42] = "24" +if pos.y > 0 do + options["foo"] = "rab" + options[42] = "24" + + @print("Conditional hit!") +end @print(options.title) @print(options["foo"]) diff --git a/source/ona/kym.zig b/source/ona/kym.zig index 3a7a437..4019bcc 100644 --- a/source/ona/kym.zig +++ b/source/ona/kym.zig @@ -61,6 +61,9 @@ pub const RuntimeEnv = struct { clt, cge, cle, + + jt: u32, + jf: u32, }; const OpcodeList = coral.list.Stack(Opcode); @@ -265,6 +268,22 @@ pub const RuntimeEnv = struct { } }, + .@"if" => |@"if"| { + try self.compile_expression(chunk, @"if".condition_expression); + try chunk.opcodes.push_one(.{.jf = 0}); + + const jump_opcode = &chunk.opcodes.values[chunk.opcodes.values.len - 1]; + + for (@"if".block_statements.values) |block_statement| { + try self.compile_statement(chunk, block_statement); + } + + coral.debug.assert(jump_opcode.* == .jf); + coral.debug.assert(chunk.opcodes.values.len < coral.math.max_int(@typeInfo(u32).Int)); + + jump_opcode.jf = @intCast(chunk.opcodes.values.len); + }, + .expression => |expression| try self.compile_expression(chunk, expression), } } @@ -288,10 +307,10 @@ pub const RuntimeEnv = struct { } }; - fn compile(self: *Chunk, ast: Ast) RuntimeError!void { + fn compile(self: *Chunk, statements: *const Ast.Statement.List) RuntimeError!void { var unit = CompilationUnit{}; - for (ast.list_statements()) |statement| { + for (statements.values) |statement| { try unit.compile_statement(self, statement); } } @@ -322,8 +341,10 @@ pub const RuntimeEnv = struct { defer coral.debug.assert(self.env.frames.pop() != null); - for (self.opcodes.values) |opcode| { - switch (opcode) { + var opcode_cursor = @as(u32, 0); + + while (opcode_cursor < self.opcodes.values.len) : (opcode_cursor += 1) { + switch (self.opcodes.values[opcode_cursor]) { .push_nil => try self.env.locals.push_one(null), .push_true => try self.env.locals.push_one(try self.env.new_boolean(true)), .push_false => try self.env.locals.push_one(try self.env.new_boolean(false)), @@ -791,6 +812,29 @@ pub const RuntimeEnv = struct { })); }, + .jf => |jf| { + const condition = (try self.pop_local()) orelse { + opcode_cursor = jf; + + continue; + }; + + self.env.discard(condition); + + if (!condition.is_truthy()) { + opcode_cursor = jf; + } + }, + + .jt => |jt| { + const condition = (try self.pop_local()) orelse continue; + + self.env.discard(condition); + + if (condition.is_truthy()) { + opcode_cursor = jt; + } + }, } } @@ -1044,20 +1088,18 @@ pub const RuntimeEnv = struct { defer self.allocator.deallocate(file_data); const file_name = file_path.to_string() orelse "