Skip to content

Commit 5bffe24

Browse files
committed
fix local capture.
1 parent cc6ba0b commit 5bffe24

5 files changed

Lines changed: 50 additions & 100 deletions

File tree

VirtualMachine/EVIL.Ceres/ExecutionEngine/Diagnostics/Chunk.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,16 @@ public static Chunk Deserialize(Stream stream, out byte version, out long timest
355355

356356
public Chunk Clone()
357357
{
358+
var contexts = new Dictionary<string, ClosureContext>();
359+
foreach (var kvp in _closureContexts)
360+
{
361+
contexts[kvp.Key] = new ClosureContext(kvp.Value.EnclosedFunctionName);
362+
foreach (var kvp2 in kvp.Value.Values)
363+
{
364+
contexts[kvp.Key].Values[kvp2.Key] = kvp2.Value;
365+
}
366+
}
367+
358368
var clone = new Chunk(
359369
Name,
360370
_code.ToArray(),
@@ -369,7 +379,7 @@ public Chunk Clone()
369379
IsSelfAware = IsSelfAware,
370380
_subChunks = new(_subChunks),
371381
_closures = new(_closures),
372-
_closureContexts = new(_closureContexts),
382+
_closureContexts = contexts,
373383
_labels = new(_labels),
374384
_attributes = new(_attributes),
375385
_parameterInitializers = new(_parameterInitializers),

VirtualMachine/EVIL.Ceres/ExecutionEngine/ExecutionUnit.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1088,7 +1088,18 @@ public void Step()
10881088
}
10891089
else
10901090
{
1091-
PushValue(targetFrame.Locals![closureInfo.EnclosedId]);
1091+
if (frame.Chunk.ClosureContexts.ContainsKey(closureInfo.EnclosedFunctionName))
1092+
{
1093+
PushValue(
1094+
frame.Chunk.ClosureContexts[
1095+
closureInfo.EnclosedFunctionName
1096+
].Values[closureInfo.EnclosedId]
1097+
);
1098+
}
1099+
else
1100+
{
1101+
PushValue(targetFrame.Locals![closureInfo.EnclosedId]);
1102+
}
10921103
}
10931104
}
10941105
else

VirtualMachine/Tests/EVIL.Ceres.LanguageTests/tests/000_regression.vil

Lines changed: 25 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,43 @@
1-
//#[test;disasm("always")]
2-
//fn for_loop_table_fill {
3-
// val t = {};
4-
//
5-
// for (rw val i = 0; i < 4; i++) {
6-
// t[i] = i;
7-
// }
8-
//
9-
// assert.equal(t[0], 0);
10-
// assert.equal(t[1], 1);
11-
// assert.equal(t[2], 2);
12-
// assert.equal(t[3], 3);
13-
//}
14-
//
15-
//#[test;disasm("always")]
16-
//fn for_loop_closure_capture {
17-
// val funcs = {};
18-
//
19-
// for (rw val i = 0; i < 3; i++) {
20-
// funcs[i] = fn -> i;
21-
// }
22-
//
23-
// assert.equal(funcs[0](), 0);
24-
// assert.equal(funcs[1](), 1);
25-
// assert.equal(funcs[2](), 2);
26-
//}
1+
#[test]
2+
fn for_loop_table_fill {
3+
val t = {};
274

28-
fn delay(ms) {
29-
val end = time.stamp.ms + ms;
30-
while(time.stamp.ms < end){}
5+
for (rw val i = 0; i < 4; i++) {
6+
t[i] = i;
7+
}
318

32-
ret 2.137;
9+
assert.equal(t[0], 0);
10+
assert.equal(t[1], 1);
11+
assert.equal(t[2], 2);
12+
assert.equal(t[3], 3);
3313
}
3414

15+
3516
#[test]
36-
fn yield_zombie {
37-
rw val outer_arg = nil;
38-
rw val zombified = false;
17+
fn for_loop_closure_capture {
18+
val funcs = {};
3919

40-
loc fn dies_and_rises(rw arg) {
41-
rw val zombified_2 = false;
42-
43-
loc fn dies_and_rises_2 {
44-
if (!zombified_2) {
45-
arg = 12;
46-
zombified_2 = true;
47-
yield<delay>(10);
48-
yield<dies_and_rises_2>();
49-
50-
throw arg;
51-
}
52-
}
20+
for (rw val i = 0; i < 3; i++) {
21+
funcs[i] = fn -> i;
22+
}
5323

54-
if (!zombified) {
55-
zombified = true;
56-
yield<delay>(10);
57-
yield<dies_and_rises>();
58-
59-
try {
60-
yield<dies_and_rises_2>();
61-
} catch (e) {
62-
outer_arg = e;
63-
}
64-
}
24+
assert.equal(funcs[0](), 0);
25+
assert.equal(funcs[1](), 1);
26+
assert.equal(funcs[2](), 2);
27+
}
6528

66-
ret "undead";
67-
}
29+
fn delay(ms) {
30+
val end = time.stamp.ms + ms;
31+
while(time.stamp.ms < end){}
6832

69-
zombified = false;
70-
val result = yield<dies_and_rises>();
71-
assert.equal(outer_arg, 12);
72-
assert.equal(result, "undead");
33+
ret 2.137;
7334
}
7435

7536
#[test]
7637
fn tonum_indexing {
7738
val data = { a: { b: { c: "1", d: "2", e: "3", f: "4" } } };
7839
val x = $data.a.b.c * $data.a.b.d;
79-
40+
8041
assert.equal(x, 2);
8142
}
8243

VirtualMachine/Tests/EVIL.Ceres.LanguageTests/tests/019_closures.vil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ fn many_subchunks_capture_same_local_no_change {
177177
}
178178

179179
#[test]
180-
fn many_subchunks_capture_same_local_after_change {
180+
fn many_subchunks_capture_local_value_after_change {
181181
rw val local_a = 11;
182182
val f1 = fn(x) -> local_a + x;
183183

@@ -192,7 +192,7 @@ fn many_subchunks_capture_same_local_after_change {
192192

193193
val result = f1(2) + f2(4) + f3(5) + f4(4);
194194

195-
assert.equal(result, 47);
195+
assert.equal(result, 59);
196196
}
197197

198198
fn invoke_func_out_of_scope(f) -> f();

VirtualMachine/Tests/EVIL.Ceres.LanguageTests/tests/099_yield.vil

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -226,36 +226,4 @@ fn catcher {
226226
fn yield_stack_unwind {
227227
val result = yield<catcher>();
228228
assert.equal(result, "caught: error mid-yield");
229-
}
230-
231-
#[test]
232-
fn yield_zombie {
233-
rw val zombified = false;
234-
235-
loc fn dies_and_rises {
236-
rw val zombified_2 = false;
237-
238-
loc fn dies_and_rises_2 {
239-
if (!zombified_2) {
240-
zombified_2 = true;
241-
yield<delay>(10);
242-
yield<dies_and_rises_2>();
243-
throw "aaa";
244-
}
245-
}
246-
247-
if (!zombified) {
248-
zombified = true;
249-
yield<delay>(10);
250-
yield<dies_and_rises>();
251-
252-
try yield<dies_and_rises_2>();
253-
}
254-
255-
ret "undead";
256-
}
257-
258-
zombified = false;
259-
val result = yield<dies_and_rises>();
260-
assert.equal(result, "undead");
261229
}

0 commit comments

Comments
 (0)