mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-22 05:59:31 +08:00
- Reduce allocation and reference-management overhead in native array loops. - Enable vectorization while preserving numeric behavior. - Preserve live tuple iteration and cover reference lifetimes and missing values.
135 lines
3.7 KiB
TypeScript
135 lines
3.7 KiB
TypeScript
class Cell {
|
|
x: number;
|
|
y: number;
|
|
constructor(x: number) { this.x = x; this.y = x + 1; }
|
|
}
|
|
|
|
function read(values: Cell[], index: number): number {
|
|
const value = values[index];
|
|
return value.x + value.y;
|
|
}
|
|
function missing(values: Cell[], index: number): void {
|
|
try { console.log(read(values, index)); }
|
|
catch (error) { if (error instanceof Error) console.log(error.name, error.message); }
|
|
}
|
|
const values = [new Cell(2)];
|
|
console.log(read(values, 0), read(values, -0));
|
|
values[0.5] = new Cell(7);
|
|
values[-1] = new Cell(9);
|
|
values[NaN] = new Cell(11);
|
|
values[Infinity] = new Cell(13);
|
|
values[4_000_000_000] = new Cell(15);
|
|
console.log(read(values, 0.5), read(values, -1), read(values, NaN), read(values, Infinity), read(values, 4_000_000_000));
|
|
missing(values, 1);
|
|
missing(values, 2);
|
|
missing(values, -2);
|
|
values.length = 0;
|
|
missing(values, 0);
|
|
|
|
function truncate(values: Cell[]): number {
|
|
const value = values[0];
|
|
values.length = 0;
|
|
value.x += 3;
|
|
return value.x;
|
|
}
|
|
function replace(values: Cell[]): Cell {
|
|
const value = values[0];
|
|
values[0] = new Cell(99);
|
|
return value;
|
|
}
|
|
console.log(truncate([new Cell(17)]), replace([new Cell(19)]).x);
|
|
|
|
function nestedLength(values: number[][], index: number): number {
|
|
const value = values[index];
|
|
values.length = 0;
|
|
return value === undefined ? -1 : value.length;
|
|
}
|
|
console.log(nestedLength([], 0), nestedLength([[1, 2]], 0));
|
|
|
|
let changing = [new Cell(23)];
|
|
function changeIndex(): number { changing = [new Cell(200)]; return 0; }
|
|
function ordered(): number {
|
|
const value = changing[changeIndex()];
|
|
return value.x;
|
|
}
|
|
console.log(ordered(), changing[0].x);
|
|
|
|
function delayedThrow(values: Cell[]): void {
|
|
const value = values[1];
|
|
console.log("before missing use");
|
|
value.x += 1;
|
|
}
|
|
try { delayedThrow([new Cell(29)]); }
|
|
catch (error) { if (error instanceof Error) console.log(error.name, error.message); }
|
|
|
|
function escaped(values: Cell[]): () => number {
|
|
const value = values[0];
|
|
return () => value.x;
|
|
}
|
|
const escapeArray = [new Cell(31)];
|
|
const closure = escaped(escapeArray);
|
|
escapeArray.length = 0;
|
|
console.log(closure());
|
|
|
|
function pairs(values: Cell[]): number {
|
|
let total = 0;
|
|
for (let i = 0; i < values.length; i++) {
|
|
const a = values[i];
|
|
for (let j = i + 1; j < values.length; j++) {
|
|
const b = values[j];
|
|
a.x += b.y;
|
|
b.x += a.y;
|
|
total += a.x + b.x;
|
|
}
|
|
}
|
|
return total;
|
|
}
|
|
const shared = new Cell(3);
|
|
console.log(pairs([shared, shared, new Cell(5)]), shared.x);
|
|
|
|
function throwingLoops(values: Cell[]): number {
|
|
let total = 0;
|
|
for (let i = 0; i < values.length; i++) {
|
|
try {
|
|
const value = values[i];
|
|
if (i === 0) continue;
|
|
total += value.x;
|
|
} catch { total += 100; }
|
|
finally { total += 1; }
|
|
}
|
|
return total;
|
|
}
|
|
const holes = [new Cell(37)];
|
|
holes[2] = new Cell(43);
|
|
console.log(throwingLoops(holes));
|
|
|
|
function growing(values: Cell[]): number {
|
|
let total = 0;
|
|
for (let i = 0; i < values.length; i++) {
|
|
const value = values[i];
|
|
if (i === 0) values.push(new Cell(47));
|
|
total += value.x;
|
|
if (i === 1) values.length = 1;
|
|
}
|
|
return total;
|
|
}
|
|
console.log(growing([new Cell(2)]));
|
|
|
|
// An effectful RHS must keep the compound receiver's original owner alive.
|
|
let receiver = new Cell(53);
|
|
const original = receiver;
|
|
function replaceReceiver(): number { receiver = new Cell(59); return 7; }
|
|
receiver.x += replaceReceiver();
|
|
console.log(original.x, receiver.x);
|
|
|
|
// Different static views of an inherited field must still alias.
|
|
class Derived extends Cell { extra: number = 1; }
|
|
function inherited(base: Cell, derived: Derived): number {
|
|
const old = base.x;
|
|
derived.x += 3;
|
|
derived.y += 4;
|
|
return old + base.x + base.y;
|
|
}
|
|
const derived = new Derived(61);
|
|
console.log(inherited(derived, derived));
|