mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-28 06:53:42 +08:00
`Int32` from @scriptc/types now also annotates the element type of a declared number array (`Int32[]`, `readonly Int32[]`, `Array<Int32>`, `ReadonlyArray<Int32>`) on parameters, variables, class instance fields and function results. The contract promises that every element stored into the array, through any reference, is an int32 by construction. contracts/int32-elements.ts checks it over a whole-program flow graph of the places array references live (locals, parameters, globals, results, class field families, record fields, container element slots), with one node per allocation and per opaque origin. Allocations that can reach an annotated slot are constrained and every element store into an array that may be constrained must be range-proven an int32 (SC7002); element copies constrain their sources by fixpoint; arrays from or escaping to code the IR does not show refuse the contract (SC7003). Slots only constrained arrays reach are recorded as IrContracts.int32Elements. Element reads that find a value through those slots carry the int32 range, `getNumber` reads are integer-or-NaN operands of wrapping sums, and ToInt32 of any integer-or-NaN operand is branch-free. Holes, missing indices and length changes keep their JavaScript behavior. Integer kernels over a 2^20-element array: `(s + a[i]) | 0` 1086 -> 175 ms, `(Math.imul(h, 31) + a[i]) | 0` 602 -> 150 ms, prefix sums 575 -> 155 ms; programs without the annotation compile to identical binaries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
21 lines
654 B
TypeScript
21 lines
654 B
TypeScript
// Contract types are checked where they annotate a declaration directly
|
|
// (Int32 also as the element type of a declared array, Int32[]).
|
|
// Elsewhere they would promise something scriptc does not check, so the
|
|
// build reports them.
|
|
import type { Immutable, Int32, NoThrow } from "@scriptc/types";
|
|
|
|
type NodeId = Int32;
|
|
|
|
interface Point {
|
|
x: Int32;
|
|
}
|
|
|
|
const ids: Int32[][] = [[1, 2]];
|
|
const point: Point = { x: 1 };
|
|
const id: NodeId = 3;
|
|
const callback: (x: number) => NoThrow<number> = (x) => x;
|
|
const table: Map<string, Immutable<number[]>> = new Map();
|
|
let last: NoThrow<number> = 0;
|
|
|
|
console.log(ids, point.x, id, callback(1), table.size, last);
|