/** * expr-operator-types.ts — 閉じた Expression IR オペレータ語彙の **型シグネチャ SSoT** * (expression-ir.md §3 の operator I/O 型を宣言的テーブルとして 1 箇所に固定する — #125/A3 owner 決定)。 * * ## なぜ SSoT か(C3 との整合) * * 全ノード型確定ゲート(type-gate.ts)が component の `output`(Φ 合成)型を合成するとき、operator ノード * (`concat`/`add`/`eq`/…)の結果型が要る。これを `resolveExprType` に **ad-hoc な per-operator 分岐**で * 埋め込むと「BC が型を推論している」ように見え、consumer-interface.md §2.1 C3「BC は明示注記を読むだけで * 推論しない」の**字義**と衝突する。そこで **operator の入出力型を語彙レベルで一度だけ明示宣言**し * (=この SSoT)、エンジンは leaf catalog 注記を読むのと**同じやり方でこの宣言を読む**。operator シグネチャが * 「明示注記」であり、結果型はその宣言の決定的な適用であって未知データ型の推論ではない。 * * ## テーブルの形(宣言的) * * 各エントリは operator 名 → {@link OperatorSignature}: 入力型制約(`operands`)と結果型ルール(`result`)。 * 結果型が被演算子に依存するもの(算術の int/float 伝播・`div` の常時 float・`coalesce`/`cond` の join)は * **宣言的なルール keyword**(`"arith-join"` / `"div-float"` / `"coalesce-join"` / `"cond-join"`)で表し、 * 固定結果(`concat→string`、比較/論理→`bool`、`len→int`)は固定 `PortableType` で表す。ルールの意味論も * この module 内の {@link resolveOperatorResult} 1 箇所に集約する(分岐を散らさない)。 * * ## 語彙の同期(cross-check) * * ここで宣言する operator 集合は guard.ts の `PORTABLE_EXPR_OPERATORS`(可搬 IR で許可される operator)と * authoring.ts の式ビルダ(index.ts が公開する `concat`/`add`/…/`opt`)に対応する。**値を生む operator** * (型シグネチャを持つもの)だけを載せる。構造/参照ノード(`ref`/`refOpt`/`obj`/`arr`/`int`/`float`)と * 制御ノード(`cond`)は operator ではなく resolver の構造規則側で扱う(下の {@link isValueOperator} 参照)。 * * > A6/#128 完了メモ: この SSoT は A6 で conformance vector-pin 済み(`SPEC_VERSIONS.guard` 1→2)。 * > operator-result の wire-observable な `outputType`(concat→string / arith→int·float / div→float / * > 比較・論理→bool / len→int)の accept/reject は guard.json(guard=2)が 5 言語で pin し、SSoT の * > rows→result-type の意味論(`resolveOperatorResult`)は `ts/test/expr-operator-types.test.ts` が pin する。 * > * > 重複メモ(A6・deferred with reason): native emitter 側(`generator/native-expr.ts`)は operand→result * > 型を **コード生成と同時に per-operand で計算**している(`binOp` が operand scalar を見て `addI64` か * > helper かを選ぶため、result scalar だけを本 SSoT から取っても operand scalar 計算は残る)。この計算は * > 本 SSoT と意味論上一致するが(arith-join / div-float / concat→string / 比較・論理→bool / len→int)、 * > 単一化は「result scalar のみ SSoT 参照・operand dispatch は据え置き」という marginal な dedup であり、 * > native codegen purity(whole-file de-box)が重厚に pin された hot path への高リスク改修になる。A6 の * > owner ガイダンス「risky refactor は強行しない」に従い**据え置き**、ここに重複を明示記録する。両者の * > 一致は golden の実行等価(生成 native ≡ interpreter)が実測で担保する(codegen-golden-corpus I4)。 */ import type { PortableType } from "./behavior.js"; /** * 結果型ルール — 被演算子に依存する結果型の**宣言的**表現(意味論は resolveOperatorResult に集約): * - `"arith-join"` 算術 2 項/単項: int×int→int / float×float→float(混在禁止・expression-ir.md §3)。 * - `"div-float"` `div` は常に float(TS セマンティクス・expression-ir.md §3「result is always float」)。 * - `"coalesce-join"` `a ?? b`: a の非 null 側の型と b が一致すれば確定(下記規則)。 * - `"cond-join"` `c ? t : e`: t/e 同型なら確定、片側 null なら他方を `{opt}` に(Φ の `: null` else 等)。 */ export type OperatorResultRule = "arith-join" | "div-float" | "coalesce-join" | "cond-join"; /** 入力オペランドの型制約(宣言的 SSoT)。型ゲート(type-gate `assertOperandConstraint`)が**全て読む**: * 各 operand core(expr-eval.ts)の throw 条件と 1:1 に enforce し、違反は generate 時に `BAD_OPERAND_TYPE` * で落とす(宣言はあるが読み手ゼロ=実行時 `TYPE_MISMATCH` になるだけの穴を残さない — #263/#268/#269)。 */ export type OperandConstraint = "string" | "bool" | "numeric" | "ordered" | "same" | "arr" | "any"; /** * OperatorSignature — 1 operator の宣言的型シグネチャ(SSoT の 1 行)。 * - `arity`: 引数個数(`"unary"`=1 / `"binary"`=2 / `"ternary"`=3 / `"variadic"`=2+)。 * - `operands`: 入力型制約(宣言のためのメタ。診断・A6 の conformance pin 用)。 * - `result`: 固定 `PortableType` か、被演算子依存の結果型ルール(`OperatorResultRule`)。 */ export interface OperatorSignature { arity: "unary" | "binary" | "ternary" | "variadic"; operands: OperandConstraint; result: PortableType | OperatorResultRule; } /** * OPERATOR_TYPE_SIGNATURES — 閉じた式語彙の型シグネチャ SSoT(expression-ir.md §3)。 * この 1 テーブルが operator I/O 型の唯一の宣言源。resolveExprType はこれを**読む**(ad-hoc 分岐を持たない)。 */ export declare const OPERATOR_TYPE_SIGNATURES: Readonly>; /** value-operator(型シグネチャを持つ operator)か。ref/refOpt/obj/arr/int/float/cond は resolver の構造規則側。 */ export declare function isValueOperator(op: string): boolean; /** operator の宣言シグネチャを引く(未知 operator は undefined — 呼び側が loud に扱う)。 */ export declare function operatorSignature(op: string): OperatorSignature | undefined; /** * PortableType の構造的同値(decl 順を無視した obj field 比較)。join ルールの型一致判定に使う * (type-gate.ts と同一意味論だが、operator 結果ルールの SSoT 側に置く — 結果型決定は 1 箇所に集約)。 */ export declare function sameType(a: PortableType, b: PortableType): boolean; /** * resolveOperatorResult — 宣言シグネチャの `result`(固定型 or ルール)に、解決済みオペランド型 * (`operandTypes`)を適用して operator ノードの結果 `PortableType` を返す。決定できないときは * `undefined`(呼び側が `UNTYPED_NODE` にする)。**operator 結果型の意味論はここ 1 箇所だけ**。 * * @param sig {@link operatorSignature} で引いた宣言シグネチャ。 * @param operandTypes 各オペランドの解決済み型(`resolveExprType` が構造規則で解決したもの。 * 未解決オペランドがあれば呼び側で弾いてから渡す)。 */ export declare function resolveOperatorResult(sig: OperatorSignature, operandTypes: readonly PortableType[]): PortableType | undefined; //# sourceMappingURL=expr-operator-types.d.ts.map