Skip to content

Commit

Permalink
fix: invalid capture cache
Browse files Browse the repository at this point in the history
If a capture was specified in a different branch of an if statement,
then we would incorrectly think that we had already loaded it in the
parent environment.
  • Loading branch information
sno2 committed Nov 7, 2024
1 parent de20e71 commit 9f9debc
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 5 deletions.
5 changes: 5 additions & 0 deletions examples/regression/regression1.tl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(let
((b: num 41))
((if #f
(lambda () (let ((k: num b)) k))
(lambda () b))))
2 changes: 2 additions & 0 deletions examples/regression/regression2.tl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(let ((a: (-> (-> num)) (lambda () (lambda () (- 16 ((lambda () 5))))))(b: (-> bool) (lambda () #f))(c: num 156)(d: List<bool> (list: bool #f (= (if #t (let ((a: num (/ 24 (* (- (+ 40 (if #f 89 316)) 95) (+ (* 470 194) (let ((a: num (- 46 293))(b: num (/ 374 217))) a)))))(b: num 15)) (((let ((c: num b)(d: num (+ (/ 56 122) (* 7 60)))) (lambda () (lambda () 6)))))) (+ 32 (- 398 24))) 62)))) (let ((e: Ref num (ref: num 19))(f: List<num> (list: num 169))(g: (-> num) (lambda () (if #t ((lambda () (if #t (let ((e: num (if #f 143 (/ 104 205)))(f: num 235)(g: num (let ((e: num ((lambda () 189)))(f: num ((lambda () 8)))(g: num 152)(h: num 21)) (let ((i: num 98)(j: num 92)) 326)))) 122) (* 90 (/ 11 (let ((e: num 26)(f: num 155)(g: num 11)(h: num 66)(i: num 124)) 20)))))) (* 384 102))))(h: num (/ (if (< 56 (- 75 58)) (if ((lambda () (= (let ((e: num c)(f: num 108)(g: num (* 141 65))(h: num 2)) 65) (- c 13)))) c 31) 38) ((lambda () (+ (if ((lambda () (= 49 75))) 208 38) (- (if (> 58 110) 14 c) 335))))))) 20))

5 changes: 5 additions & 0 deletions examples/test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ test "identifiers" {
try expectResult(@embedFile("identifiers.dl"), .definelang, "41.0");
}

test "regression" {
try expectResult(@embedFile("regression/regression1.tl"), .typelang, "41.0");
try expectResult(@embedFile("regression/regression2.tl"), .typelang, "20.0");
}

fn fuzzCodegen(initial_source: []const u8) !void {
const source = std.testing.allocator.dupeZ(u8, initial_source) catch return;
defer std.testing.allocator.free(source);
Expand Down
8 changes: 4 additions & 4 deletions src/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -339,11 +339,11 @@ fn genIdentifier(cg: *CodeGen, exe: *Executable, identifier: []const u8, comptim
});
if (!gop.found_existing) {
gop.value_ptr.* = try cg.allocCapture();
try parent.emit(.move_capture, .{
.local = local,
.capture = @intCast(gop.value_ptr.*),
}, null);
}
try parent.emit(.move_capture, .{
.local = local,
.capture = @intCast(gop.value_ptr.*),
}, null);
try exe.emit(.load_capture, @intCast(exe.captures.items.len), null);
try exe.captures.append(cg.gpa, gop.value_ptr.*);
if (is_typed) return parent.local_types.items[local];
Expand Down
6 changes: 6 additions & 0 deletions src/Executable.zig
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ pub const Instruction = union(enum(u8)) {
local: u16,
capture: u16,
},
move_capture_u8: struct {
local: u8,
capture: u8,
},
load_local: u16,
load_local_u8: u8,
load_define: u16,
Expand Down Expand Up @@ -105,6 +109,8 @@ pub fn emit(
return exe.emit(.move_local_u8, @intCast(payload), source_hint);
} else if (tag == .move_define and payload <= std.math.maxInt(u8)) {
return exe.emit(.move_define_u8, @intCast(payload), source_hint);
} else if (tag == .move_capture and payload.local <= std.math.maxInt(u8) and payload.capture <= std.math.maxInt(u8)) {
return exe.emit(.move_capture_u8, .{ .local = @intCast(payload.local), .capture = @intCast(payload.capture) }, source_hint);
} else if (tag == .push_list and payload <= std.math.maxInt(u8)) {
return exe.emit(.push_list_u8, @intCast(payload), source_hint);
} else if (tag == .call and payload <= std.math.maxInt(u8)) {
Expand Down
2 changes: 1 addition & 1 deletion src/Vm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ fn executeInner(vm: *Vm, cur: *StackInfo, program: *const Executable) ![]Value {
.move_define, .move_define_u8 => {
vm.stack.items[payload] = vm.stack.pop();
},
.move_capture => {
.move_capture, .move_capture_u8 => {
vm.stack.items[vm.captures_start + payload.capture] = vm.stack.items[cur.stack_start + payload.local];
},
.jump => {
Expand Down

0 comments on commit 9f9debc

Please sign in to comment.