Files
scriptc/packages/types
Malte Ubl 73ee5e17e9 Acyclic: a dedicated default interface; shortest cycle in explanations
`implements Acyclic` resolved to Record<never, never>, and the frontend
indexes implemented types as class protocols by symbol, so every Record
value in the program took checked identity (on tsc-ts: Int32 field
contracts failed with SC7003). The default is now AcyclicObject, an empty
interface only @scriptc/types declares, and type arguments in heritage
clauses are reported (they would make a class implement its own type).
Corpus 4642 stores an Acyclic class with an Int32 field in a Record.

explainCycle picks the shortest cycle through the unit and a mutable
edge (BFS distances forward and backward within the component): on
tsc-ts `Node.parent -> Node` instead of a 20-step path through the
checker.
2026-10-11 16:30:25 -07:00
..
2026-10-11 11:17:17 -07:00

@scriptc/types

Contract types for scriptc: type aliases with no meaning in TypeScript or Node.js that scriptc checks as extra promises. Import them with import type, which TypeScript erases, so Node.js never loads this package.

import type { Immutable, Int32, NoThrow } from "@scriptc/types";

const KEYWORDS: Immutable<Map<string, number>> = new Map([["const", 1]]);

class Token {
  pos: Int32 = 0;
}

function isLetter(ch: number): NoThrow<boolean> {
  return (ch >= 97 && ch <= 122) || (ch >= 65 && ch <= 90);
}

Contracts

  • NoThrow<T> on a function's return type: the function never throws. Callers need no exception checks.
  • Int32 on a parameter, variable, class instance field or function result: every stored value is a signed 32-bit integer by construction (an integer literal in range, a bitwise result such as x | 0, Math.imul, another Int32, or arithmetic scriptc can bound). The slot is stored as a 32-bit integer.
  • Immutable<T> on a parameter, variable, class instance field or function result: a deep read-only view, and no code writes to the value through any reference. A module constant built from literals becomes immortal data.
  • Acyclic on a class (class C implements Acyclic), interface (interface I extends Acyclic) or object type alias (type T = Acyclic<{ ... }>): no chain of references can lead from such an object back to itself. Its objects carry no cycle-collector header.

scriptc proves each contract or rejects the program with a diagnostic (SC7001-SC7007) that explains why it does not hold. A program that compiles behaves exactly as under Node.js. See https://scriptc.dev/docs/contracts.