/** * The contract the analyzer publishes and the emitter and the extension * protocol consume: the compiler-owned member keys behind `@dispose:` and * `@iterate:`, the `LoweringHints` side tables the emitter reads, and the * class, analysis-context, and initialization-read shapes the project driver * and the extension protocol name. * * D114 R1a: these declarations lived in `analyzer.ts`, which made * `emitter.ts -> analyzer.ts` a value edge of the five-module import ring * (`analyzer -> emitter -> extension -> parser -> lexer`). They are a contract * between stages, not analyzer state, so they live in their own module and * `analyzer.ts` re-exports every one of them: nothing that imported a name * from `./analyzer.ts` has to change. */ import { type Expression, type Statement } from "./ast.ts"; import { type PermanentNamespaceName } from "./core-vocabulary.ts"; import { type Span } from "./source.ts"; import { type BinaryStorageKind, type EnumInfo, type ExtensionTypeSyntaxResolver, type ExtensionValueType, type GenericApplication, type GenericTypeInfo, type TypeParameterBound, type ValueType } from "./types.ts"; export interface ClassField { readonly mutable: boolean; readonly type: ValueType; } export interface ClassInfo { readonly identity?: string; /** * D55 rule 120 layer two: the class's own type parameters, present on the * declaration entry and absent from every instantiation of it. Their absence * is what tells a written `Stack` from the type constructor `Stack`, * which is not a type at all (rule 126). */ readonly typeParameterNames?: readonly string[]; readonly typeParameterBounds?: readonly (TypeParameterBound | null)[]; /** * The application this entry is — `Stack` records the declaration it * instantiates and the arguments it applied, so substitution, the module * interface, and the emitted `instanceof` receiver all read one place. */ readonly application?: GenericApplication; /** * The application this class's `extends` writes, when the base is generic. * `base` is already the instantiated key; this keeps the parts so * instantiating *this* class can rebuild the base key with the arguments * substituted (`class MyStack extends Stack` at `T := number`). */ readonly baseApplication?: GenericApplication; /** D43 item 69: the class declares `@dispose:`, and whether releasing awaits. */ readonly dispose?: "sync" | "async"; /** * D68 rule 177: the collection the class's own `@iterate:` block answers * with. Absent when the class declares no block — a derived class reads its * base's answer instead of copying it, because overriding replaces rather * than composes. */ readonly iterate?: ValueType; /** * D90 R18: the element the class's asynchronous `@iterate:` form answers * with. The block is the declared spelling of the pull contract `async for` * consumes — pulled once per element, it may await, it answers `T?`, and * null is exhaustion. A class declares one form or the other; the answer's * shape (a collection against `T?`) is what tells them apart. */ readonly iterateAsync?: ValueType; readonly parameters: readonly ValueType[]; readonly parameterNames?: readonly string[]; readonly requiredParameters: number; readonly constructorRest?: ValueType; /** * D114 F6b(e) / ER-I1: the declaration was refused for the missing * constructor a derived class needs to forward its base's arguments. The * class then takes no construction arguments, which is true and is not the * author's mistake — theirs was the missing constructor, already reported at * the declaration — so every `Name(...)` after it withholds the arity error * rather than saying one thing twice. */ readonly constructorRefused?: boolean; readonly base: string | null; readonly abstract: boolean; readonly fields: ReadonlyMap; readonly getters: ReadonlySet; readonly abstractGetters: ReadonlySet; readonly methods: ReadonlyMap; readonly abstractMethods: ReadonlySet; readonly staticFields: ReadonlyMap; readonly staticGetters: ReadonlySet; readonly staticMethods: ReadonlyMap; } export type CollectionRuntimeKind = "list" | "map" | "set" | "record"; export type CollectionOperation = "listGet" | "mapGet" | "recordGet" | "slice" | "listAppend" | "listExtend" | "listInsert" | "listRemove" | "listPop" | "listClear" | "listCopy" | "listHas" | "listCount" | "listIndex" | "listFind" | "listSome" | "listEvery" | "listMap" | "listFilter" | "listFlatMap" | "listReduce" | "listJoin" | "listSorted" | "listReversed" | "listSum" | "listMin" | "listMax" | "listUnique" | "listCompact" | "listFlatten" | "listChunk" | "listPartition" | "listGroupBy" | "listKeyBy" | "listCountBy" | "listZip" | "listRepeat" | "setAdd" | "setUpdate" | "setHas" | "setRemove" | "setClear" | "setValues" | "setCopy" | "setUnion" | "setIntersection" | "setDifference" | "mapSet" | "mapGetOrSet" | "mapGetOrSetWith" | "mapUpdate" | "mapHas" | "mapRemove" | "mapClear" | "mapIterator" | "mapKeys" | "mapValues" | "mapEntries" | "mapCopy" | "recordSet" | "recordHas" | "recordRemove" | "recordClear" | "recordKeys" | "recordValues" | "recordEntries" | "recordCopy"; export type PrimitiveOperation = "stringTrim" | "stringUpper" | "stringLower" | "stringSlice" | "stringChar" | "stringHas" | "stringIndex" | "stringCount" | "stringStartsWith" | "stringEndsWith" | "stringSplit" | "stringReplace" | "stringReplaceAll" | "stringPadStart" | "stringPadEnd" | "stringRepeat" | "stringIsBlank" | "numberAbs" | "numberRound" | "numberFloor" | "numberCeil" | "numberSign" | "numberTrunc" | "numberToFixed" | "numberIsInteger" | "numberIsSafeInteger" | "numberIsNaN" | "numberIsFinite"; export interface FormReadField { readonly name: string; readonly kind: "string" | "number" | "bool" | "enum" | "strings"; readonly optional: boolean; readonly enumValues?: readonly string[]; } export interface RecordTypeField { readonly name: string; readonly type: ValueType; } export interface RecordFromHint { readonly target: string; readonly fields: readonly { readonly name: string; readonly optional: boolean; }[]; } /** Concrete `Target.mapFrom(source, transform)` calls lowered as mapped record projections. */ export type RecordMapFromHint = RecordFromHint; export interface LoweringHints { readonly collectionCalls: ReadonlyMap; readonly collectionSizes: ReadonlyMap; readonly collectionIndexes: ReadonlyMap; readonly collectionMemberships: ReadonlyMap; readonly collectionIterations: ReadonlyMap; /** Concrete `Target.from(source, overrides?)` calls lowered as exact record projections. */ readonly recordFromCalls: ReadonlyMap; /** Concrete `Target.mapFrom(source, transform)` calls lowered as mapped record projections. */ readonly recordMapFromCalls: ReadonlyMap; /** Binary members and indexes lower directly against their typed-array storage. */ readonly binaryCalls: ReadonlyMap; readonly binarySizes: ReadonlyMap; readonly binaryIndexes: ReadonlyMap; readonly primitiveCalls: ReadonlyMap; readonly stringSizes: ReadonlySet; readonly constructorCalls: ReadonlySet; readonly javaScriptCallBoundaries: ReadonlySet; readonly classChecks: ReadonlySet; readonly privateMembers: ReadonlySet; readonly classNames: ReadonlySet; /** Class names whose chain reaches the builtin Error — their lowering stamps `.name` (audit 4 micro-ruling). */ readonly errorSubclassNames: ReadonlySet; readonly enumNames: ReadonlySet; /** * Module-scope bindings that hold runtime Type objects: local `type` * declarations and aliases, plus imported ones. A narrowing recheck for any * of these names may call `Name.is(value)` — the exporting module always * emits the validator object for an exported type. Names outside this set * (erased generics, extension host types such as DOM interfaces) have no * such binding and keep the presence-only recheck. */ readonly runtimeTypeObjectNames: ReadonlySet; readonly runtimeTypeIdentities?: ReadonlyMap; readonly moduleNamespaceExports?: ReadonlyMap; readonly moduleNamespaceReferences?: ReadonlySet; /** Compiler-private JavaScript exports required by project signature consumers. */ readonly runtimeTypeExports?: ReadonlyMap; readonly runtimeTypeReExports?: readonly { readonly source: string; readonly imported: string; readonly exported: string; readonly accessor?: boolean; readonly dynamic?: boolean; readonly alternatives?: readonly { readonly source: string; readonly exported: string; readonly accessor?: boolean; readonly dynamic?: boolean; }[]; }[]; /** Importable runtime owners for types reached through signatures, keyed by canonical identity. */ readonly runtimeTypeImports?: ReadonlyMap; /** * D55 rule 121: module-scope names bound to a generic record's instantiation * factory, local or imported. A generic name is *not* a Type object — it * answers `.of(...)`, never `.is(...)` — so the emitter has to tell the two * apart before it writes either into the output. */ readonly genericTypeNames: ReadonlySet; /** Complete inherited-plus-local record fields for each `type` declaration, keyed by declaration start. */ readonly typeDeclarationFields: ReadonlyMap; readonly optionalMembers: ReadonlySet; readonly optionalCalls: ReadonlySet; readonly optionalIndexes: ReadonlySet; readonly optionalCallees: ReadonlySet; readonly truthConditions: ReadonlySet; readonly normalizedNullResults: ReadonlySet; readonly normalizedPromiseValues: ReadonlySet; readonly asyncResolvedValues: ReadonlySet; readonly asyncForStatements: ReadonlySet; /** Direct, unshadowed `for name in range(...)` loops that can use a counted loop. */ readonly nativeRangeForStatements: ReadonlySet; readonly normalizedUndefinedExpressions: ReadonlySet; readonly instanceFieldReads: ReadonlySet; readonly errorCodeReads: ReadonlySet; readonly privateInstanceFieldReads: ReadonlySet; readonly staticFieldReads: ReadonlyMap; /** * Member spans that read a class method as a value rather than calling it. * Methods live on the prototype, so these emit as receiver-evaluated-once * plus a bind at the reference site (charter sections 8 and 18). */ readonly classMethodReferences: ReadonlySet; readonly optionalBindingEntries: ReadonlySet; readonly reactiveReferences: ReadonlyMap; readonly enumValueBindings: ReadonlyMap; readonly exhaustiveMatches: ReadonlySet; readonly formReads: ReadonlyMap; readonly namedArgumentOrders: ReadonlyMap; readonly extensionLiterals: ReadonlyMap; readonly extensionCalls: ReadonlyMap; /** Prelude and permanent-namespace reads, keyed by span so lexical shadows win. */ readonly builtinValueReferences: ReadonlyMap; readonly runtimeNarrowings: ReadonlyMap; /** * Span identities of `==`/`!=` operations (and comparison-chain links) * whose operands may both be NaN at runtime. These lower to SameValueZero; * every other equality elides the repair and emits plain `===` (D36 item 41). */ readonly sameValueZeroEqualities: ReadonlySet; /** * Span identities of match value candidates that must compare by * SameValueZero — the subject and the candidate can both be NaN — so * `case box.nan:` agrees with `==` (ENM-D2, charter section 8). Everything * else keeps plain `===`. */ readonly sameValueZeroMatchValues: ReadonlySet; /** Span identities of calls to the prelude's equals(a, b) (D47 rule 81). */ readonly equalsCalls: ReadonlySet; /** * Span identities of ordered comparisons (`< <= > >=`, including * comparison-chain links) whose operands are strings. These lower through * the code-point comparator so string order is code-point order everywhere * (TXT-D1); number comparisons keep the plain operator. */ readonly stringOrderings: ReadonlySet; /** * Span identities of ordered comparisons between `Comparable`-bounded type * parameters (D41 item 61). The runtime category is not known statically, * so these lower through the dispatching comparator, which keeps a string * pair in code-point order exactly as a monomorphic string comparison is. */ readonly dynamicOrderings: ReadonlySet; /** * How each `using` statement releases its value, keyed by the statement's * span identity (D43 item 69). The analyzer resolves the contract because it * is the only stage that knows the value's type. */ readonly usingDisposals: ReadonlyMap; /** * Class declarations whose `@dispose:` must forward to an inherited one * (D51 rule 102), keyed by the declaration's span identity. The value is the * inherited release's async-ness, which decides whether the forward awaits. */ readonly classDisposeChains: ReadonlyMap; /** * D68 rule 177: span identities of the expressions a consumer iterates * through a class's `@iterate:` contract — the eight sites that consume an * iterable. The emitter projects each one through the contract member, so * what the runtime receives is the List, Set, Map, or Record the block * returns and every consumer keeps the lowering it already had. */ readonly iterationContracts: ReadonlySet; /** * D90 R18: start offsets of `async for` statements whose source's class * declares the asynchronous `@iterate:` form. The emitter pulls these * through the declared member instead of capturing a structural `next`. */ readonly asyncIterationStatements: ReadonlySet; /** * D90 R18: span identities of the `@iterate:` blocks that are the * asynchronous pull form, keyed by their keyword span, so the emitter lands * each one as an async method under its own key. */ readonly asyncIterateBlocks: ReadonlySet; /** * Span identities of JavaScript-boundary calls in synchronous * module-initialization position. A non-Error value thrown there would * reach the host uncaught and unnormalized — the last unowned failure * shape at the bridge — so these sites rethrow through the owned Error * normalization channel (BRG-U10). */ readonly moduleTopLevelHostCalls: ReadonlySet; } export interface RuntimeNarrowingGuard { readonly expected: ValueType; readonly description: string; } export interface AnalysisContext { /** Runtime owners of declared types reachable through imported signatures. */ readonly runtimeTypeImports?: LoweringHints["runtimeTypeImports"]; readonly runtimeTypeExports?: LoweringHints["runtimeTypeExports"]; readonly runtimeTypeReExports?: LoweringHints["runtimeTypeReExports"]; readonly moduleNamespaceExports?: LoweringHints["moduleNamespaceExports"]; /** The module source, used only to withhold mechanical rewrites that would erase comments. */ readonly sourceText?: string; readonly imports?: ReadonlyMap; readonly dynamicImports?: ReadonlyMap; readonly reactiveImports?: ReadonlyMap; readonly namedTypes?: ReadonlyMap>; readonly namedTypeReadonlyFields?: ReadonlyMap>; readonly namedTypeIdentities?: ReadonlyMap; /** Direct record inheritance edges by local name or canonical identity. */ readonly namedTypeBases?: ReadonlyMap; /** D55: imported generic record declarations, by the name this module writes. */ readonly genericTypes?: ReadonlyMap; readonly typeAliases?: ReadonlyMap; readonly enums?: ReadonlyMap; readonly classes?: ReadonlyMap; readonly extensionImports?: ReadonlyMap>; readonly extensionModules?: ReadonlyMap; /** * The project manifest's extension sections, by extension id, as each * extension's own `velarProjectExtension.parse` returned them. Present only * when a project manifest was read, so an extension can tell "this project * declares nothing here" from "there is no project": a build input the * compile can see is a build input the compile can check, which is what lets * `publicConfig(Type)` be proved instead of left to the first paint. */ readonly extensionProjectConfig?: ReadonlyMap; readonly resources?: ReadonlyMap; /** Compiler-owned seeds used while omitted function results converge. */ readonly inferredFunctionResults?: ReadonlyMap; /** True only for the final semantic pass after result inference converges. */ readonly finalizeFunctionResultInference?: boolean; /** The module's own path; `test "name":` is only declared in a `*.test.vel` module. */ readonly path?: string; /** 当前模块是否是一次程序编译的执行入口;普通依赖仍检查 `@main`,但不把它当作模块初始化。 */ readonly executeMain?: boolean; } /** * A direct read of an imported binding from a module-initialization position * (top-level initializers and expression statements, static class fields, * extension top-level initializers). The project driver combines these with * the module graph to reject import cycles whose source module has not * evaluated when the read runs (D31 item 23). */ export interface InitializationImportRead { readonly local: string; readonly source: string; /** * The name the source module exports, which may differ from `local`. The * project driver follows it through re-export barrels to the module that * actually declares the binding; a namespace import has no single name and * records null. */ readonly imported: string | null; readonly span: Span; } /** * The emitted member behind a class's `@dispose:` block. The key is not a * source-shaped identifier, so no author member can collide with it: * `@dispose` is compiler-owned, not part of the author's namespace. */ export declare const disposeMemberKey = "__velar:dispose"; /** * The emitted member behind a class's `@iterate:` block, under the same kind of * key and for the same reason: `@iterate` is compiler-owned, so no author * member can answer it by accident and no author call can reach it. */ export declare const iterateMemberKey = "__velar:iterate"; /** * The emitted member behind the asynchronous `@iterate:` form (D90 R18). It is * a separate key because the two forms answer different questions — the * synchronous member returns the finished collection once, this one is an * async method `async for` pulls once per element — so no lowering can confuse * one for the other. */ export declare const iterateAsyncMemberKey = "__velar:iterateAsync"; /** How a `using` binding releases its value at scope exit. */ export interface DisposalContract { readonly member: string; readonly asynchronous: boolean; readonly owner: "class" | "capability"; } /** * D114 R1c: the analysis half of the extension protocol — * `CompilerAnalysisExtension`, the retired-namespace migration it carries, and * the intrinsic context an extension's `inferIntrinsic` hook is handed. These * were declared in `extension.ts`, which also re-exports the `Analyzer` class * *value*; that made every analysis collaborator that named one of these types * a member of the compiler's import ring. They are a contract between the * analyzer and a target extension, not part of the extension module's own * assembly, so they live here beside the other cross-stage contracts and * `extension.ts` re-exports all three as types: nothing that imported a name * from `./extension.ts` has to change. */ export interface CompilerAnalysisExtension { readonly primitiveTypes?: ReadonlySet; readonly primitiveParents?: ReadonlyMap>; readonly primitiveMutableFields?: ReadonlyMap>; readonly globals?: ReadonlyMap; readonly reservedBindings?: ReadonlySet; readonly globalGuidance?: ReadonlyMap; /** * Guidance that replaces `globalGuidance` inside a module whose path ends * with the keyed suffix. The right door for a reserved global depends on * where the author is standing: `document` inside a component means JSX and * refs, and inside a `.browser.test.vel` it means `velar/web-test`. */ readonly globalGuidanceByPathSuffix?: ReadonlyMap>; /** * D52 rule 114: a namespace prefix the language invented and then withdrew, * keyed by the retired name. It is `permanentNamespace` run backwards — that * one turns an import into a prefix, this one turns a prefix back into the * import — so the migration teaches the named import that replaced it and * carries the mechanical rewrite (drop the prefix, add the import) with it. */ readonly retiredNamespaces?: ReadonlyMap; /** Resolve target-owned type syntax without teaching Core the target's types. */ readonly resolveTypeSyntax?: ExtensionTypeSyntaxResolver; /** Decide compatibility inside a target-owned type family. */ readonly isTypeAssignable?: (actual: ExtensionValueType, expected: ExtensionValueType, assign: (actual: ValueType, expected: ValueType) => boolean) => boolean | undefined; /** Resolve target-owned runtime members; null means the target owns the type but the member is absent. */ readonly memberType?: (type: ExtensionValueType, property: string) => ValueType | null | undefined; /** * Declare whether a target-owned value has a total, hook-free text form. * `true` admits the value to f-strings and `str()`, `false` records an owned * rejection, and `undefined` leaves the type for another extension or Core. */ readonly textForm?: (type: ValueType) => boolean | undefined; /** * Replace a refused positional intrinsic call's generic arity sentence with * owner guidance. This hook cannot infer arguments or accept the call: Core * still owns shape validation, independent argument errors and invalidType. */ readonly intrinsicArityGuidance?: (intrinsic: Extract, arguments_: readonly Expression[]) => string | undefined; readonly inferIntrinsic?: (context: CompilerIntrinsicAnalysisContext) => ValueType | undefined; /** Frame-aware traversal for expression nodes owned by this extension. */ readonly directAwaitExpression?: (expression: Expression, contains: (expression: Expression) => boolean) => boolean | undefined; /** Frame-aware traversal for statement nodes owned by this extension. */ readonly directAwaitStatement?: (statement: Statement, containsExpression: (expression: Expression) => boolean, containsBlock: (statements: readonly Statement[]) => boolean) => boolean | undefined; /** * Decide whether an extension-owned expression is a stable per-item value * projection for Core's collection canonicalization advisories. Returning * `true` says constructing the expression cannot mutate the iterated List; * `false` owns and rejects the expression, and `undefined` leaves it to * another extension. Nested Core expressions must be delegated to `pure`. */ readonly canonicalCollectionProjection?: (expression: Expression, pure: (expression: Expression) => boolean) => boolean | undefined; } /** The module a retired namespace's members moved back to, and which names moved. */ export interface RetiredNamespace { readonly module: string; readonly members: ReadonlySet; } export interface CompilerIntrinsicAnalysisContext { readonly intrinsic: Extract; readonly argumentAt: (index: number) => Expression | null; readonly callSpan: Span; readonly arity: (minimum?: number, maximum?: number) => void; readonly inferAt: (index: number, expected?: ValueType) => ValueType; readonly callbackAt: (index: number, parameters: readonly ValueType[], result: ValueType) => ValueType; readonly runtimeTypeAt: (index: number) => ValueType; readonly typeError: (message: string, span: Span) => void; readonly isAssignable: (actual: ValueType, expected: ValueType) => boolean; readonly expandAliases: (type: ValueType) => ValueType; readonly jsonSerializable: (type: ValueType) => boolean | null; readonly isHttpFormBody: (type: ValueType) => boolean; readonly declaredFieldsOf: (identity: string) => ReadonlyMap | null; readonly formReadField: (name: string, type: ValueType, span: Span) => FormReadField | null; readonly recordFormRead: (sourceSpan: Span, fields: readonly FormReadField[]) => void; } //# sourceMappingURL=contracts.d.ts.map