Files
scriptc/tests/corpus/3078-forward-mutable-captures.ts
Chris Tate 8e95bcbe7f feat(compiler): advance native validator self-hosting (#492)
- Support mutable forward captures with correct initialization and exception behavior.
- Compile recursive literals, exhaustive bindings, and validator collection operations statically.
- Run validator control-flow analysis natively with C and LLVM differential coverage.
2026-09-27 12:14:06 -05:00

127 lines
3.4 KiB
TypeScript

export {};
function counters(): void {
const read = () => depth;
const step = () => depth++;
const next = () => ++depth;
const previous = () => --depth;
const assign = (value: number) => depth = value;
const add = (value: number) => { depth += value; };
let depth = 2;
console.log("counter", read(), step(), next(), previous(), read());
console.log("assign", assign(10), read());
add(3);
depth--;
console.log("shared", read(), depth);
}
counters();
function references(): void {
const read = () => state;
const set = (name: string) => state = { name, values: [name.length] };
const edit = () => { state.values.push(9); };
let state = { name: "initial", values: [1] };
const old = read();
const changed = set("replacement");
edit();
console.log("references", old.name, old.values.join(","), changed.name, read() === changed, changed.values.join(","));
}
references();
function flags(): void {
const get = () => flag;
const set = (value: boolean) => flag = value;
let flag = false;
console.log("flag", get(), set(true), get());
flag = false;
console.log("flag", get());
}
flags();
// The declaring frame can return while sibling closures keep sharing
// the same mutable cell. Intermediate closures must forward its flags.
function factory(): { read: () => number; update: (value: number) => number } {
const make = () => ({ read: () => value, update: (next: number) => value = next });
const pair = make();
let value = 1;
return pair;
}
const pair = factory();
console.log("escaped", pair.read(), pair.update(8), pair.read());
function walk(): number {
function enter(count: number): void {
depth++;
maximum = Math.max(maximum, depth);
if (count > 0) enter(count - 1);
depth--;
}
let depth = 0;
let maximum = 0;
enter(5);
console.log("walk", depth, maximum);
return maximum;
}
console.log(walk());
function replaceText(): void {
const append = () => text = text + "!";
const get = () => text;
let text = "hello";
console.log(append(), get());
text = "again";
console.log(append(), get());
}
replaceText();
let sum = 0;
for (let i = 0; i < 100; i++) {
const instance = factory();
sum += instance.update(i) + instance.read();
}
console.log("stress", sum);
// The forward capture is first discovered inside this very initializer.
let stored: () => number = () => 0;
function remember(read: () => number): number { stored = read; return 4; }
function recursiveInitializer(): void {
let value = remember(() => value);
console.log("self init", stored());
value = 10;
console.log("self replacement", stored());
}
recursiveInitializer();
console.log("self escaped", stored());
// Re-entering a block creates a fresh binding, while each iteration's
// reader/writer pair keeps sharing its own cell after the loop ends.
function iterations(): void {
const readers: (() => number)[] = [];
const writers: ((next: number) => void)[] = [];
for (let i = 0; i < 3; i++) {
const read = () => value;
const write = (next: number): void => { value = next; };
let value = i;
readers.push(read);
writers.push(write);
}
writers[0]!(10);
writers[2]!(20);
console.log("iterations", readers[0]!(), readers[1]!(), readers[2]!());
}
iterations();
function shadowed(): void {
const read = () => value;
let value = 1;
{
const change = (): void => { value = 4; };
let value = 2;
change();
console.log("inner", value);
}
value = 3;
console.log("outer", read());
}
shadowed();