Skip to content

Commit

Permalink
Add inferred empty else to switch states
Browse files Browse the repository at this point in the history
  • Loading branch information
bgk- committed Jun 12, 2024
1 parent 6bcce25 commit 0edb3ea
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 13 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.idea
.DS_Store
zig-cache
.zig-cache
zig-out
*.topib
*.topib
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ and [LoLa](https://github.com/MasterQ32/LoLa/tree/master) both of which are cred

## Contributing

Download and install [Zig](https://ziglang.org). Currently Topiary uses version `0.12.0`
Download and install [Zig](https://ziglang.org). Currently Topiary uses version `0.13.0`

```
git clone https://github.com/peartreegames/topiary
Expand Down
8 changes: 4 additions & 4 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{});

_ = b.addModule("topi", .{
.root_source_file = .{ .path = "src/topi.zig" },
.root_source_file = b.path("src/topi.zig"),
});

const topidll = b.addSharedLibrary(.{
.name = "topi",
.root_source_file = .{ .path = "src/export.zig" },
.root_source_file = b.path("src/export.zig"),
.target = target,
.optimize = optimize,
});
Expand All @@ -19,7 +19,7 @@ pub fn build(b: *std.Build) void {

const exe = b.addExecutable(.{
.name = "topi",
.root_source_file = .{ .path = "src/cli.zig" },
.root_source_file = b.path("src/cli.zig"),
.target = target,
.optimize = optimize,
});
Expand All @@ -36,7 +36,7 @@ pub fn build(b: *std.Build) void {
run_step.dependOn(&run_cmd.step);

const tests = b.addTest(.{
.root_source_file = .{ .path = "src/vm.zig" },
.root_source_file = b.path("src/vm.zig"),
.target = target,
.optimize = optimize,
});
Expand Down
2 changes: 1 addition & 1 deletion build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.{
.name = "topiary",
.version = "0.13.1",
.version = "0.13.2",
.paths = .{""},
.dependencies = .{},
}
2 changes: 1 addition & 1 deletion src/cli.zig
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub fn main() !void {
}

const is_run = std.mem.eql(u8, cmd, "run");
const is_test = std.mem.eql(u8, cmd, "auto");
const is_test = std.mem.eql(u8, cmd, "test");
const is_compile = std.mem.eql(u8, cmd, "compile");
const is_loc = std.mem.eql(u8, cmd, "loc");
if (!is_run and !is_test and !is_compile and !is_loc) return usage("Unknown command");
Expand Down
21 changes: 21 additions & 0 deletions src/compiler.zig
Original file line number Diff line number Diff line change
Expand Up @@ -345,20 +345,31 @@ pub const Compiler = struct {
const start = self.instructionPos();
try self.compileExpression(&s.capture);
var prong_jumps = try self.allocator.alloc(usize, s.prongs.len);
var inferred_else_jump: ?usize = null;
defer self.allocator.free(prong_jumps);
// compile expressions and jumps
var has_else = false;
for (s.prongs, 0..) |prong_stmt, i| {
const prong = prong_stmt.type.switch_prong;
if (prong.values) |p| {
for (p) |value| {
try self.compileExpression(&value);
}
} else {
has_else = true;
}
try self.writeOp(.prong, prong_stmt.token);
const prong_jump = try self.writeInt(OpCode.Size(.jump), PRONG_HOLDER, prong_stmt.token);
_ = try self.writeInt(u8, @as(u8, @intCast(if (prong.values) |p| p.len else 0)), prong_stmt.token);
prong_jumps[i] = prong_jump;
}
// add an empty else if none found
if (!has_else) {
try self.writeOp(.prong, token);
const prong_jump = try self.writeInt(OpCode.Size(.jump), PRONG_HOLDER, token);
_ = try self.writeInt(u8, 0, token);
inferred_else_jump = prong_jump;
}

// replace jumps and compile body
for (s.prongs, 0..) |prong_stmt, i| {
Expand All @@ -370,6 +381,16 @@ pub const Compiler = struct {
_ = try self.writeInt(OpCode.Size(.jump), SWITCH_END_HOLDER, prong_stmt.token);
try self.exitScope();
}

if (inferred_else_jump) |jump| {
try self.replaceValue(jump, OpCode.Size(.jump), self.instructionPos());
try self.enterScope(.local);
try self.compileBlock(&[_]ast.Statement{});
try self.writeOp(.jump, token);
_ = try self.writeInt(OpCode.Size(.jump), SWITCH_END_HOLDER, token);
try self.exitScope();
}

try replaceJumps(self.chunk.instructions.items[start..], SWITCH_END_HOLDER, self.instructionPos());
try self.writeOp(.pop, token);
},
Expand Down
2 changes: 1 addition & 1 deletion src/token.zig
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub const TokenType = enum {
illegal,
};

pub const Keywords = std.ComptimeStringMap(TokenType, .{
pub const Keywords = std.StaticStringMap(TokenType).initComptime(.{
.{ "and", .@"and" },
.{ "bough", .bough },
.{ "break", .@"break" },
Expand Down
18 changes: 16 additions & 2 deletions src/vm.test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ pub const TestRunner = struct {

var test_runner = TestRunner.init();
pub fn initTestVm(source: []const u8, mod: *Module, debug: bool) !Vm {
const errWriter = std.io.getStdErr().writer();
var bytecode = compileSource(source, mod) catch |err| {
const errWriter = std.io.getStdErr().writer();
try mod.writeErrors(errWriter);
return err;
};
Expand Down Expand Up @@ -1414,6 +1414,7 @@ test "Switch" {
\\ 0: i = 0,
\\ 1: i = 1
\\ }
\\ assert(i == 1, "{i} == 1");
\\ i
,
.value = 1.0,
Expand All @@ -1425,6 +1426,7 @@ test "Switch" {
\\ 0: i = 0,
\\ 1: i = 1
\\ }
\\ assert(i == -1, "{i} == -1");
\\ i
,
.value = -1.0,
Expand All @@ -1436,6 +1438,7 @@ test "Switch" {
\\ 0: i = 0,
\\ 1: i = 1,
\\ }
\\ assert(i == 1, "{i} == 1");
\\ i
,
.value = 1.0,
Expand All @@ -1448,6 +1451,7 @@ test "Switch" {
\\ 1: i = 1,
\\ else: i = 5
\\ }
\\ assert(i == 1, "{i} == 1");
\\ i
,
.value = 1.0,
Expand All @@ -1460,6 +1464,7 @@ test "Switch" {
\\ 1: i = 1,
\\ else: i = 5
\\ }
\\ assert(i == 5, "{i} == 5");
\\ i
,
.value = 5.0,
Expand All @@ -1472,6 +1477,7 @@ test "Switch" {
\\ 4,5,6,7: i = 4,
\\ else: i = 5
\\ }
\\ assert(i == 4, "{i} == 4");
\\ i
,
.value = 4.0,
Expand All @@ -1484,6 +1490,7 @@ test "Switch" {
\\ 4..7: i = 4,
\\ else: i = 5
\\ }
\\ assert(i == 4, "{i} == 4");
\\ i
,
.value = 4.0,
Expand All @@ -1496,6 +1503,7 @@ test "Switch" {
\\ "two": i = 4,
\\ "test": i = 5
\\ }
\\ assert(i == 5, "{i} == 5");
\\ i
,
.value = 5.0,
Expand All @@ -1508,7 +1516,10 @@ test "Switch" {
var vm = try initTestVm(case.input, &mod, false);
defer vm.deinit();
defer vm.bytecode.free(testing.allocator);
try vm.interpret();
vm.interpret() catch |err| {
vm.err.print(std.io.getStdErr().writer());
return err;
};
}
}

Expand All @@ -1534,6 +1545,9 @@ test "Externs and Subscribers" {
const Listener = struct {
pub fn onChange(name: []const u8, value: Value) void {
std.debug.print("\nListener \"{s}\"::{}\n", .{ name, value });
testing.expectEqual(case.value, value.number) catch {
std.debug.print("Unexpected listener value", .{});
};
}
};
try vm.setExtern("value", .{ .number = 2 });
Expand Down
3 changes: 2 additions & 1 deletion src/vm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1057,10 +1057,11 @@ pub const Vm = struct {

fn prongIsMatch(self: *Vm, capture: Value, case: Value) bool {
_ = self;
return switch (case) {
const result = switch (case) {
.range => |r| @as(i32, @intFromFloat(capture.number)) >= r.start and @as(i32, @intFromFloat(capture.number)) <= r.end,
else => capture.eql(case),
};
return result;
}

fn push(self: *Vm, value: Value) !void {
Expand Down

0 comments on commit 0edb3ea

Please sign in to comment.