mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-23 06:10:02 +08:00
- 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.
127 lines
3.4 KiB
TypeScript
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();
|