/** * Minimal type inference for Tier 2 semantic diagnostics. NOT a full type * system — the language is dynamically typed and many programs return * legitimately heterogeneous values. The goal here is just to catch * type-confused literal/binding usage with zero false positives. * * Conservative rules: * * - `unknown` is compatible with every expected type (suppresses errors). * - A union type is compatible iff AT LEAST ONE member is compatible. So * `if cond then 1 else "x"` (number | string) does not fire when used in * a numeric position — the user might know the actual branch. * - We do not track record field types or array element types beyond * "array" / "record" buckets. */ import type { Expression, ParameterSpec, Statement } from './program'; export type Type = { kind: 'number'; } | { kind: 'boolean'; } | { kind: 'string'; } | { kind: 'array'; } | { kind: 'record'; } | { kind: 'union'; members: readonly Type[]; } | { kind: 'unknown'; }; export declare const TY_NUMBER: Type; export declare const TY_BOOLEAN: Type; export declare const TY_STRING: Type; export declare const TY_ARRAY: Type; export declare const TY_RECORD: Type; export declare const TY_UNKNOWN: Type; export declare function typeName(t: Type): string; /** Flatten and dedupe union members. Returns the singleton if only one * member remains. */ export declare function unionOf(types: readonly Type[]): Type; /** True if `inferred` is compatible with `expected`. `unknown` is always * compatible. For unions, at least one member must be compatible. */ export declare function isCompatible(expected: Type, inferred: Type): boolean; /** Type environment: `$name` → static type. Mirrors the scope chain. */ export declare class TypeEnv { readonly parent: TypeEnv | null; private bindings; constructor(parent?: TypeEnv | null); set(name: string, t: Type): void; get(name: string): Type; } export declare function parameterType(spec: ParameterSpec, env: TypeEnv): Type; /** * Infer a static type for `expr` under `env`. Always returns a value; * `unknown` indicates "we couldn't tell." Never throws. */ export declare function inferType(expr: Expression, env: TypeEnv): Type; /** * Apply a top-level statement to a type environment. Mutates `env` for * `assignment` and `parameter-declaration`. */ export declare function applyStatementToEnv(stmt: Statement, env: TypeEnv): void;