behavior-contracts 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/behavior.d.ts +47 -0
  2. package/dist/behavior.d.ts.map +1 -1
  3. package/dist/behavior.js.map +1 -1
  4. package/dist/generator/core.d.ts +1 -1
  5. package/dist/generator/core.d.ts.map +1 -1
  6. package/dist/generator/core.js.map +1 -1
  7. package/dist/generator/emit-straightline-go.d.ts +77 -0
  8. package/dist/generator/emit-straightline-go.d.ts.map +1 -0
  9. package/dist/generator/emit-straightline-go.js +592 -0
  10. package/dist/generator/emit-straightline-go.js.map +1 -0
  11. package/dist/generator/emit-straightline-php.d.ts +46 -0
  12. package/dist/generator/emit-straightline-php.d.ts.map +1 -0
  13. package/dist/generator/emit-straightline-php.js +501 -0
  14. package/dist/generator/emit-straightline-php.js.map +1 -0
  15. package/dist/generator/emit-straightline-python.d.ts +36 -0
  16. package/dist/generator/emit-straightline-python.d.ts.map +1 -0
  17. package/dist/generator/emit-straightline-python.js +441 -0
  18. package/dist/generator/emit-straightline-python.js.map +1 -0
  19. package/dist/generator/emit-straightline-rust.d.ts +78 -0
  20. package/dist/generator/emit-straightline-rust.d.ts.map +1 -0
  21. package/dist/generator/emit-straightline-rust.js +615 -0
  22. package/dist/generator/emit-straightline-rust.js.map +1 -0
  23. package/dist/generator/emit-straightline-typed-go.d.ts +39 -0
  24. package/dist/generator/emit-straightline-typed-go.d.ts.map +1 -0
  25. package/dist/generator/emit-straightline-typed-go.js +828 -0
  26. package/dist/generator/emit-straightline-typed-go.js.map +1 -0
  27. package/dist/generator/emit-straightline-typed-rust.d.ts +48 -0
  28. package/dist/generator/emit-straightline-typed-rust.d.ts.map +1 -0
  29. package/dist/generator/emit-straightline-typed-rust.js +823 -0
  30. package/dist/generator/emit-straightline-typed-rust.js.map +1 -0
  31. package/dist/generator/emit-straightline-typed-typescript.d.ts +49 -0
  32. package/dist/generator/emit-straightline-typed-typescript.d.ts.map +1 -0
  33. package/dist/generator/emit-straightline-typed-typescript.js +314 -0
  34. package/dist/generator/emit-straightline-typed-typescript.js.map +1 -0
  35. package/dist/generator/emit-straightline-typescript.d.ts +36 -0
  36. package/dist/generator/emit-straightline-typescript.d.ts.map +1 -0
  37. package/dist/generator/emit-straightline-typescript.js +397 -0
  38. package/dist/generator/emit-straightline-typescript.js.map +1 -0
  39. package/dist/generator/index.d.ts +13 -0
  40. package/dist/generator/index.d.ts.map +1 -1
  41. package/dist/generator/index.js +39 -0
  42. package/dist/generator/index.js.map +1 -1
  43. package/dist/generator/literal.d.ts +7 -0
  44. package/dist/generator/literal.d.ts.map +1 -1
  45. package/dist/generator/literal.js +41 -0
  46. package/dist/generator/literal.js.map +1 -1
  47. package/dist/generator/straightline.d.ts +147 -0
  48. package/dist/generator/straightline.d.ts.map +1 -0
  49. package/dist/generator/straightline.js +122 -0
  50. package/dist/generator/straightline.js.map +1 -0
  51. package/dist/generator/typed.d.ts +156 -0
  52. package/dist/generator/typed.d.ts.map +1 -0
  53. package/dist/generator/typed.js +108 -0
  54. package/dist/generator/typed.js.map +1 -0
  55. package/dist/guard.d.ts +18 -0
  56. package/dist/guard.d.ts.map +1 -1
  57. package/dist/guard.js +56 -0
  58. package/dist/guard.js.map +1 -1
  59. package/dist/index.d.ts +7 -4
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +10 -2
  62. package/dist/index.js.map +1 -1
  63. package/dist/primitives.d.ts +112 -0
  64. package/dist/primitives.d.ts.map +1 -0
  65. package/dist/primitives.js +206 -0
  66. package/dist/primitives.js.map +1 -0
  67. package/package.json +1 -1
@@ -0,0 +1,147 @@
1
+ /**
2
+ * straightline.ts — 共通 Generator の「直線 emit」枠(bc#37 / Layer A1)。
3
+ *
4
+ * typed-codegen.md §4.1(主経路・脱解釈・型なし)の language-neutral な骨組み。
5
+ * 既存のリテラル焼き込み emit(emit-typescript.ts の `bind` — endpoint 3-literal)と
6
+ * **併存**する additive な第2モード。component ごとに「plan を直呼び・各ノードの port 評価と
7
+ * handler 呼びを直線展開した」ネイティブ関数を emit する枠を提供する。
8
+ *
9
+ * この枠が消すもの(AC1): **`runBehavior` の tree-walk**——
10
+ * - `nodeKind` ディスパッチ(body ノード種の実行時分岐)
11
+ * - `evalPorts` の汎用ループ(未知 ports を毎回 `evaluateExpression` で歩く)
12
+ * - 汎用 `exec` closure + 汎用 output 評価
13
+ * これらを **IR から静的に展開した per-node の直線コード**に置き換える。プランのステージ
14
+ * 実行・Skip 伝播・Policy Kind は runtime primitive `runPlan` として維持する(意味論の
15
+ * SSoT を一本に保つ — typed-codegen.md §4.1 の「plan は primitive 維持」)。式演算子の
16
+ * 意味論も再実装せず、A0(#36)の式演算子 primitive(`ref`/`concat`/… を評価する SSoT
17
+ * ラッパ)を直呼びする。よって生成コードは:
18
+ * 1. `nodeKind` で分岐しない(各ノードの exec 分岐は生成時に確定・ハードコード)。
19
+ * 2. `evalPorts` で未知 ports を歩かない(各 port を名前付き primitive 呼びに展開)。
20
+ * 3. `runBehavior` を内部で呼ばない(=薄い束ねではない)。
21
+ *
22
+ * スコープ(A1 = read hot path): `componentRef` + `cond` + 単純 Expression Port のみ。
23
+ * `map`/`batched`/`concurrency`(A3)・hydration/relation stitching(A4)は **fail-closed**
24
+ * ({@link assertStraightlineSupported} が `GeneratorFailure(UNSUPPORTED_NODE_STRAIGHTLINE)`)。
25
+ * 黙って誤コード生成・部分生成をしない(スコープ境界を fail-closed に — AC5)。
26
+ *
27
+ * 言語 plugin IF(A2 で go/rust/python/php が同じ枠に乗る): {@link StraightlineDialect} が
28
+ * 「式ノード → その言語の primitive 呼び文字列」と「per-node/handler/output/module の綴じ方」を
29
+ * 供給する。language-neutral な走査(body 検査・op literal・scope 合成・fail-closed 判定)は
30
+ * ここで一度だけ実装する。
31
+ */
32
+ import type { ComponentGraphIR, Component, BodyNode } from "../behavior.js";
33
+ import type { EmitContext } from "./core.js";
34
+ /** 直線 emit が扱える body ノードか(componentRef + cond + map — A3 以降)。 */
35
+ export declare function isStraightlineNode(n: BodyNode): boolean;
36
+ /**
37
+ * assertStraightlineSupported — IR 全体が直線 emit のスコープに収まるか検査し、外れるノード種を
38
+ * 含むなら LOUD reject する(AC)。部分生成はしない。A3 時点で componentRef/cond/map は全て
39
+ * covered。将来の hydration/relation stitching(A4 #43)を静的展開する固有ノードが導入された
40
+ * 場合は、ここに fail-closed 判定を足す(現行 IR schema には無いため、未知ノード=
41
+ * componentRef/cond/map のいずれでもない形のみを拒否する)。
42
+ */
43
+ export declare function assertStraightlineSupported(ir: ComponentGraphIR): void;
44
+ /** 直線化された1ノードの実行分岐(言語中立の記述。dialect が本体を綴じる)。 */
45
+ export type StraightlineOp = {
46
+ kind: "componentRef";
47
+ /** body 内 index(ops リテラルの index と一致)。 */
48
+ index: number;
49
+ id: string;
50
+ /** catalog 名(handler 解決キー)。 */
51
+ component: string;
52
+ /** port 名 → 評価式(dialect が生成した primitive 呼び文字列)。宣言順保存。 */
53
+ ports: {
54
+ name: string;
55
+ expr: string;
56
+ }[];
57
+ } | {
58
+ kind: "cond";
59
+ index: number;
60
+ id: string;
61
+ /** `{cond:[if,then,else]}` を1式として評価する式(dialect 生成)。 */
62
+ expr: string;
63
+ } | {
64
+ kind: "map";
65
+ index: number;
66
+ id: string;
67
+ /** 各要素で呼ぶ catalog 名(handler 解決キー)。 */
68
+ component: string;
69
+ /** 要素束縛名(`map.as`。生成コードは per-element scope に `as`→要素値 を足す)。 */
70
+ as: string;
71
+ /**
72
+ * `over` 配列を評価する式(component scope で。dialect 生成)。要素反復の前に1回評価する。
73
+ * scope は component の scopeVar(要素束縛前)で解決される。
74
+ */
75
+ over: string;
76
+ /**
77
+ * per-element guard を `{cond:[when,true,false]}` へ lower した式(dialect 生成、要素 scope で
78
+ * 評価)。`when` 未指定なら undefined(全要素採用)。strict-bool 意味論は cond primitive/native。
79
+ */
80
+ guard?: string;
81
+ /** 各 port を要素 scope で評価する式(dialect 生成)。宣言順保存。batched でも同じ。 */
82
+ ports: {
83
+ name: string;
84
+ expr: string;
85
+ }[];
86
+ /** zip-attach キー(`map.into`)。未指定なら結果は collected リスト。 */
87
+ into?: string;
88
+ /** バッチ fan-out(`map.batched`)。true なら guard 通過全要素の ports を1回の handler 呼びへ。 */
89
+ batched: boolean;
90
+ };
91
+ /**
92
+ * 直線 emit の言語 dialect。language-neutral な走査({@link buildComponentPlan})が呼ぶ
93
+ * seam。式ノード → primitive 呼び文字列({@link emitExprCalls} を各言語の primitive 命名で
94
+ * 具体化)と、per-node/handler/output/module の綴じ方を供給する。
95
+ */
96
+ export interface StraightlineDialect {
97
+ /**
98
+ * Expression IR ノードを、この言語で「scope を受けて Value を返す」primitive 呼び式に
99
+ * emit する。leaf/演算子ノードを A0 primitive(`ref`/`concat`/…)へ落とす。
100
+ * `scopeVar` は生成コード内の scope 変数名。
101
+ */
102
+ emitExpr(node: unknown, scopeVar: string): string;
103
+ /**
104
+ * map ノード本体(over/guard/ports)の Expression IR を評価するときの scope 変数名。
105
+ * 各 dialect の map 展開が per-element scope をこの名前でローカルに組む(例 TS `mscope()`)。
106
+ * 要素束縛(`map.as`)を含んだ scope をこの名前で読める前提で {@link buildComponentPlan} が
107
+ * ports/guard の式を emit する。over は component の scopeVar(要素束縛前)で評価する。
108
+ */
109
+ mapScopeVar: string;
110
+ /**
111
+ * component 1つぶんの直線関数(ops リテラル・per-node exec 分岐・output 評価・runPlan 呼び)を
112
+ * 綴じる。{@link emitModule} が各 component ぶん呼ぶ。
113
+ */
114
+ emitComponent(plan: ComponentPlan, ctx: EmitContext): string;
115
+ /** モジュール全体(ヘッダ・import・定数・load-time 検査・各 component)を綴じる。 */
116
+ emitModule(plans: ComponentPlan[], ctx: EmitContext): string;
117
+ }
118
+ /** 1 component ぶんの直線化計画(language-neutral)。 */
119
+ export interface ComponentPlan {
120
+ name: string;
121
+ component: Component;
122
+ /** body ノード → OpSpec リテラル(parent は index に解決済み)。 */
123
+ opsLiteral: OpLiteral[];
124
+ /** 各ノードの直線 exec 分岐。 */
125
+ ops: StraightlineOp[];
126
+ }
127
+ /** OpSpec のリテラル形(runPlan に渡す ops 配列の1要素。behavior.ts buildOps と同規律)。 */
128
+ export interface OpLiteral {
129
+ id: string;
130
+ parent: number | null;
131
+ bindField?: string;
132
+ relationKind?: "single" | "connection";
133
+ policy?: "fail" | "retry" | "continue";
134
+ }
135
+ /**
136
+ * buildComponentPlan — 1 component を language-neutral な {@link ComponentPlan} に落とす。
137
+ * behavior.ts の `buildOps`(parent の id→index 解決)を鏡映しつつ、各ノードの exec 分岐を
138
+ * dialect の `emitExpr` で直線コード片へ展開する。ここが「nodeKind ディスパッチ」を
139
+ * **生成時に一度だけ**行い、生成コードには分岐を残さない核。
140
+ */
141
+ export declare function buildComponentPlan(comp: Component, dialect: StraightlineDialect, scopeVar: string): ComponentPlan;
142
+ /**
143
+ * emitStraightlineModule — dialect を使って IR 全体の直線モジュールを綴じる(公開 entry)。
144
+ * A1 スコープ検査(fail-closed)を先に走らせる。
145
+ */
146
+ export declare function emitStraightlineModule(ctx: EmitContext, dialect: StraightlineDialect, scopeVar: string): string;
147
+ //# sourceMappingURL=straightline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"straightline.d.ts","sourceRoot":"","sources":["../../src/generator/straightline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,QAAQ,EAAuC,MAAM,gBAAgB,CAAC;AACjH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAQ7C,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,CAIvD;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,EAAE,EAAE,gBAAgB,GAAG,IAAI,CAWtE;AAID,gDAAgD;AAChD,MAAM,MAAM,cAAc,GACtB;IACE,IAAI,EAAE,cAAc,CAAC;IACrB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACzC,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;CACd,GACD;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,EAAE,EAAE,MAAM,CAAC;IACX;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACxC,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEN;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAClD;;;;;OAKG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,WAAW,GAAG,MAAM,CAAC;IAC7D,2DAA2D;IAC3D,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,WAAW,GAAG,MAAM,CAAC;CAC9D;AAED,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;IACrB,oDAAoD;IACpD,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,uBAAuB;IACvB,GAAG,EAAE,cAAc,EAAE,CAAC;CACvB;AAED,uEAAuE;AACvE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;CACxC;AAUD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CA2DjH;AAQD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI/G"}
@@ -0,0 +1,122 @@
1
+ import { GeneratorFailure } from "./core.js";
2
+ // ── 直線 emit スコープ判定(fail-closed。hydration/relation stitching は A4)─────
3
+ // A3(#42)で map/batched/concurrency が covered になった。hydration(A4 #43)だけが
4
+ // 依然 out-of-scope。map ノードは自身の body 内 tree-walk(要素反復・guard・into・batched)を
5
+ // 各 dialect が直線展開し、plan.concurrency は plan primitive(bounded 並行)が保存する。
6
+ /** 直線 emit が扱える body ノードか(componentRef + cond + map — A3 以降)。 */
7
+ export function isStraightlineNode(n) {
8
+ if ("map" in n)
9
+ return true; // A3(#42): map/batched/concurrency covered
10
+ if ("cond" in n)
11
+ return true;
12
+ return "component" in n; // componentRef
13
+ }
14
+ /**
15
+ * assertStraightlineSupported — IR 全体が直線 emit のスコープに収まるか検査し、外れるノード種を
16
+ * 含むなら LOUD reject する(AC)。部分生成はしない。A3 時点で componentRef/cond/map は全て
17
+ * covered。将来の hydration/relation stitching(A4 #43)を静的展開する固有ノードが導入された
18
+ * 場合は、ここに fail-closed 判定を足す(現行 IR schema には無いため、未知ノード=
19
+ * componentRef/cond/map のいずれでもない形のみを拒否する)。
20
+ */
21
+ export function assertStraightlineSupported(ir) {
22
+ for (const comp of ir.components) {
23
+ for (const n of comp.body) {
24
+ if (!isStraightlineNode(n)) {
25
+ throw new GeneratorFailure("UNSUPPORTED_NODE_STRAIGHTLINE", `component '${comp.name}': node '${n.id ?? "?"}' is not a componentRef/cond/map — straight-line emit cannot cover it (fail-closed). Regenerate with the literal-emit path or extend the straight-line dialect.`);
26
+ }
27
+ }
28
+ }
29
+ }
30
+ // ── language-neutral な走査(buildOps と鏡映。ただし直線 exec を生成用に展開)──────────
31
+ function nodeKindOf(n) {
32
+ if ("map" in n)
33
+ return "map";
34
+ if ("cond" in n)
35
+ return "cond";
36
+ return "componentRef";
37
+ }
38
+ /**
39
+ * buildComponentPlan — 1 component を language-neutral な {@link ComponentPlan} に落とす。
40
+ * behavior.ts の `buildOps`(parent の id→index 解決)を鏡映しつつ、各ノードの exec 分岐を
41
+ * dialect の `emitExpr` で直線コード片へ展開する。ここが「nodeKind ディスパッチ」を
42
+ * **生成時に一度だけ**行い、生成コードには分岐を残さない核。
43
+ */
44
+ export function buildComponentPlan(comp, dialect, scopeVar) {
45
+ const idToIndex = new Map();
46
+ comp.body.forEach((n, i) => idToIndex.set(n.id, i));
47
+ const opsLiteral = comp.body.map((n) => {
48
+ const pid = nodeParentOf(n);
49
+ const parent = pid !== undefined ? idToIndex.get(pid) ?? null : null;
50
+ const lit = { id: n.id, parent };
51
+ if ("map" in n) {
52
+ // map/cond は bindField を持たない。map は relationKind/policy を map spec から取る。
53
+ const m = n.map;
54
+ if (m.relationKind !== undefined)
55
+ lit.relationKind = m.relationKind;
56
+ if (m.policy !== undefined)
57
+ lit.policy = m.policy;
58
+ }
59
+ else if (!("cond" in n)) {
60
+ const cr = n;
61
+ if (cr.bindField !== undefined)
62
+ lit.bindField = cr.bindField;
63
+ if (cr.relationKind !== undefined)
64
+ lit.relationKind = cr.relationKind;
65
+ if (cr.policy !== undefined)
66
+ lit.policy = cr.policy;
67
+ }
68
+ return lit;
69
+ });
70
+ const ops = comp.body.map((n, i) => {
71
+ const kind = nodeKindOf(n);
72
+ if (kind === "cond") {
73
+ const c = n.cond;
74
+ // Conditional は純 Expression。behavior.ts と同じく `{cond:[if,then,else]}` へ lower して
75
+ // cond primitive(短絡・strict bool は evaluate SSoT)で1式評価する。
76
+ return { kind: "cond", index: i, id: n.id, expr: dialect.emitExpr({ cond: [c.if, c.then, c.else] }, scopeVar) };
77
+ }
78
+ if (kind === "map") {
79
+ // map: over は component scope(要素束縛前)で、guard/ports は要素 scope(dialect.mapScopeVar)で
80
+ // emit する。要素束縛(as→要素値)を含んだ scope を生成コードが mapScopeVar 名で組む前提。
81
+ // guard は behavior.ts と同じく `{cond:[when,true,false]}` へ lower(strict-bool、fail-closed)。
82
+ const m = n.map;
83
+ const ms = dialect.mapScopeVar;
84
+ const ports = Object.keys(m.ports).map((name) => ({ name, expr: dialect.emitExpr(m.ports[name], ms) }));
85
+ const guard = m.when === undefined ? undefined : dialect.emitExpr({ cond: [m.when, true, false] }, ms);
86
+ return {
87
+ kind: "map",
88
+ index: i,
89
+ id: n.id,
90
+ component: m.component,
91
+ as: m.as,
92
+ over: dialect.emitExpr(m.over, scopeVar),
93
+ guard,
94
+ ports,
95
+ into: m.into,
96
+ batched: m.batched === true,
97
+ };
98
+ }
99
+ const cr = n;
100
+ // 各 port を名前付き primitive 呼びへ展開(evalPorts の汎用ループを消す)。宣言順保存。
101
+ const ports = Object.keys(cr.ports).map((name) => ({ name, expr: dialect.emitExpr(cr.ports[name], scopeVar) }));
102
+ return { kind: "componentRef", index: i, id: n.id, component: cr.component, ports };
103
+ });
104
+ return { name: comp.name, component: comp, opsLiteral, ops };
105
+ }
106
+ function nodeParentOf(n) {
107
+ if ("map" in n)
108
+ return n.map.parent;
109
+ if ("cond" in n)
110
+ return n.cond.parent;
111
+ return n.parent;
112
+ }
113
+ /**
114
+ * emitStraightlineModule — dialect を使って IR 全体の直線モジュールを綴じる(公開 entry)。
115
+ * A1 スコープ検査(fail-closed)を先に走らせる。
116
+ */
117
+ export function emitStraightlineModule(ctx, dialect, scopeVar) {
118
+ assertStraightlineSupported(ctx.ir);
119
+ const plans = ctx.ir.components.map((c) => buildComponentPlan(c, dialect, scopeVar));
120
+ return dialect.emitModule(plans, ctx);
121
+ }
122
+ //# sourceMappingURL=straightline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"straightline.js","sourceRoot":"","sources":["../../src/generator/straightline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * typed.ts — typed-emit の language-neutral フレームワーク(bc#46 / Layer B2)。
3
+ *
4
+ * typed-codegen.md §4.2/§4.3 の骨組み。可搬型記法(`PortableType`, B0/bc#44)を「各言語の型宣言/
5
+ * 型注釈へ落とせる language-neutral な型プラン」へ導出する枠と、直線 emit({@link StraightlineDialect})を
6
+ * typed に拡張する seam({@link TypedStraightlineDialect})を提供する。TS 具体化は
7
+ * `emit-straightline-typed-typescript.ts`(言語識別子 `typescript-typed`)。go/rust(#47/#48)が
8
+ * 同じ seam に乗る。
9
+ *
10
+ * 設計の核(§4.2「全ワイヤ型は SCP 構造の決定関数」):
11
+ * - 型はワイヤの導出プロパティ。consumer(graphddb, B1/#45)が lowering 時に各ノードへ確定型を
12
+ * `outType`/`outputType` として注記する。generator はレジストリを持たず、注記された型記法だけを
13
+ * 読む(DSL 非依存)。
14
+ * - **language-neutral 部(ここ)**: 型記法 → 「型プラン」(named struct/interface の集合 + 各注記点の
15
+ * 型参照)の導出。obj は決定的な名前を振って dedup(同形 obj は同一宣言を共有)。arr/opt/scalar は
16
+ * inline 参照。名前生成・走査順・dedup は言語非依存で一度だけ実装する(go/rust/ts 共通)。
17
+ * - **per-language 部(dialect seam)**: 型プランの各ノードを「その言語の型構文(TS interface /
18
+ * Go struct / Rust struct)」へ綴じる + typed materialization(scope/output を typed 値で組む・
19
+ * `ref` を typed field access で行う)を emit する。
20
+ *
21
+ * TS における位置づけ(oracle): TS は型消去のため **runtime 脱box は無い**(生成コードの runtime 挙動は
22
+ * straight-line と同一)。typed 経路は「`outType` から型付き interface/型注釈を emit → `tsc` clean +
23
+ * emit された型が `outType` と構造一致(構造 pin)」を権威づける検証用 oracle であり、raw→typed の
24
+ * 実 perf 脱box は go/rust(#47/#48 の materialization)+ graphddb #60(marshaller 実測)の責務。
25
+ */
26
+ import type { ComponentGraphIR, PortableType } from "../behavior.js";
27
+ /**
28
+ * TypeRef — 注記点(node.outType / component.outputType)の型を language-neutral に表す。
29
+ * - scalar: 5 種のスカラ型(そのまま各言語のスカラ型へ落ちる)。
30
+ * - opt: nullable(`T | null` / `Option<T>` / …)。
31
+ * - arr: 同種配列(要素型)。
32
+ * - named: obj を named struct/interface として宣言し、その名前を参照する(Go/Rust は無名ネスト
33
+ * struct を跨げないので named 化が必須。TS も可読性・dedup のため named interface を使う)。
34
+ */
35
+ export type TypeRef = {
36
+ kind: "scalar";
37
+ scalar: "string" | "int" | "float" | "bool" | "null";
38
+ } | {
39
+ kind: "opt";
40
+ inner: TypeRef;
41
+ } | {
42
+ kind: "arr";
43
+ elem: TypeRef;
44
+ } | {
45
+ kind: "named";
46
+ name: string;
47
+ };
48
+ /** named struct/interface 宣言(obj 型 1 つ)。fields はキー順保存(型記法の宣言順)。 */
49
+ export interface TypeDecl {
50
+ name: string;
51
+ fields: {
52
+ name: string;
53
+ type: TypeRef;
54
+ }[];
55
+ }
56
+ /**
57
+ * TypePlan — IR 全体から導出した型プラン。
58
+ * - decls: named 宣言(obj 型)を **決定的順序**(初出順)で並べたもの。同形 obj は 1 宣言に dedup。
59
+ * - node/output の各注記点の型参照は {@link deriveTypeRef} が都度返す(プラン共有の decls を参照)。
60
+ */
61
+ export interface TypePlan {
62
+ decls: TypeDecl[];
63
+ }
64
+ /**
65
+ * buildTypePlan — IR 全体を走査し、全注記点(body ノード `outType` / component `outputType`)の obj 型を
66
+ * named 宣言に dedup 収集した {@link TypePlan} を返す。注記が 1 つも無ければ decls は空(typed 化する
67
+ * ものが無い=呼び側は untyped straight-line にフォールバックする)。language-neutral・決定的。
68
+ */
69
+ export declare function buildTypePlan(ir: ComponentGraphIR): TypePlan;
70
+ /**
71
+ * deriveTypeRef — 単一の注記点の型記法を(buildTypePlan と同じ dedup 規律で)TypeRef へ落とす。
72
+ * ただし named 宣言の同定はプランの走査で既に確定しているため、ここでは同じ structuralKey で
73
+ * プラン内 decl を引く(プランに無い obj 型は渡されない前提 — buildTypePlan が全注記点を網羅する)。
74
+ */
75
+ export declare function deriveTypeRef(t: PortableType, plan: TypePlan): TypeRef;
76
+ /**
77
+ * TypedMaterializer — per-language の typed 具体化 seam。language-neutral な {@link TypePlan} と
78
+ * 各注記点の {@link TypeRef} を受け取り、その言語の「型宣言(interface/struct)」と typed
79
+ * materialization(scope/output を typed 値で組む・`ref` を typed field access で行う)を綴じる。
80
+ *
81
+ * ── decls 部(B2-ts / bc#46 で確立・型テキスト描画)──────────────────────────────
82
+ * `emitTypeDecls` / `renderTypeRef` は型記法 → その言語の型宣言テキスト(TS interface / Go struct /
83
+ * Rust struct)を綴じる。TS(`emit-straightline-typed-typescript.ts`)はこれと型消去 oracle だけで
84
+ * 完結する(runtime 脱box が無いため)。
85
+ *
86
+ * ── runtime-materialization 部(B2-go / bc#47 で co-design・**最初のコンパイル言語で拡張**)─────
87
+ * TS は型消去のため runtime typed materialization を持たない → decls 部だけでは **コンパイル言語の
88
+ * 実 de-box(raw Value → 具体 struct)を綴じられない**。そこで **最初のコンパイル言語(go)で seam を
89
+ * 拡張**し、以下の hook を足す(rust #48 が同じ形で乗る)。すべて **language-neutral な入力**
90
+ * ({@link TypePlan} / {@link TypeRef} / node id / field path / 生の raw 式テキスト)を受け、per-language が
91
+ * その言語の materialization 構文へ綴じる(型プラン導出=共有、materialization=per-lang)。
92
+ *
93
+ * - {@link emitMarshallers}: 型プランの各 named 宣言に対し「raw(動的 Value)→ その struct」の
94
+ * **monomorphized marshaller**(§4.4)を emit する。struct field を 1 つずつ typed に読み出して
95
+ * 具体 struct を組む(generic な Value 走査を exec 経路から除去する de-box の実体)。
96
+ * - {@link materializeExpr}: 「raw な Value 式(handler 結果 / scope 読み)」を、注記型 {@link TypeRef}
97
+ * の **具体 typed 値**(struct / scalar / slice)へ変換する式を emit する(marshaller 呼び / 直キャスト)。
98
+ * - {@link typedFieldAccess}: 既に typed な base 式(materialize 済みローカル)への **静的 field access**
99
+ * (struct field 直参照 — map lookup でない)を emit する。ネスト field path を辿る。
100
+ * - {@link serializeTyped}: 具体 typed 値を **canonical 直列化のための動的 Value へ戻す**式を emit する
101
+ * (観測等価 pin のため。exec は typed のまま進み、境界でだけ Value に戻して golden と突き合わせる)。
102
+ *
103
+ * decls-only の materializer(TS)は runtime hook 群を実装しなくてよい(optional)。コンパイル言語
104
+ * (go/rust)は実装する。呼び側(各 emitter)が hook の有無で typed exec を出すか oracle に留めるかを決める。
105
+ *
106
+ * ── struct-native exec の規律(bc#47 監査 rework・rust #48 も従う)──────────────────
107
+ * これらの hook を使う typed exec は **struct 空間で実行する**こと(LAYERED な Value-then-struct は不可):
108
+ * - handler 結果は **その場で**(境界で)`materializeExpr`/marshaller により outType の具体 struct へ
109
+ * de-box し、**typed scope(struct)** に格納する。動的 Value の node-result scope を組んではならない。
110
+ * - downstream の `ref`/field access は `typedFieldAccess`(struct field 直参照)で typed scope を読む。
111
+ * - component output は typed 値(struct/slice)として組み、`serializeTyped` で **最終 return 境界のみ**
112
+ * Value へ戻す(動的 Value output tree を組んではならない)。
113
+ * - plan 駆動・handler dispatch・operator 意味論(overflow/短絡)は既存 SSoT(runPlan/handler/A0 primitive)
114
+ * を再利用する(二重実装しない)。struct 空間へ移すのは **結果 materialization(handler 結果・scope・
115
+ * output)だけ**。localized な operand の Value 化(operator 被演算子など)は許容。
116
+ */
117
+ export interface TypedMaterializer {
118
+ /**
119
+ * 型プランの named 宣言群(obj 型)を、その言語の型宣言テキストへ綴じる(decls 順=決定的)。
120
+ * decls が空なら空文字(typed 化するものが無い)。
121
+ */
122
+ emitTypeDecls(plan: TypePlan): string;
123
+ /**
124
+ * 単一 TypeRef を、その言語の型注釈式(TS の型注釈・Go の型名・Rust の型名)へ綴じる。
125
+ */
126
+ renderTypeRef(ref: TypeRef): string;
127
+ /**
128
+ * emitMarshallers — 型プランの各 named 宣言に対する raw→typed marshaller 群を emit する(§4.4)。
129
+ * decls 順=決定的。decls が空 or 未実装なら空文字。marshaller は「動的 Value を受け、宣言の各
130
+ * field を typed に読み出して具体 struct を返す」monomorphized 関数(generic Value 走査を exec から除去)。
131
+ */
132
+ emitMarshallers?(plan: TypePlan): string;
133
+ /**
134
+ * materializeExpr — raw な Value 式(`rawExpr`)を、注記型 `ref` の具体 typed 値へ変換する式を返す。
135
+ * obj → marshaller 呼び、scalar → 型付きキャスト、arr → 要素 materialize、opt → null 分岐。
136
+ * これが exec 経路で「Value を struct に de-box する」実体(呼び側はこの式を typed ローカルへ束ねる)。
137
+ */
138
+ materializeExpr?(rawExpr: string, ref: TypeRef, plan: TypePlan): string;
139
+ /**
140
+ * typedFieldAccess — 既に typed な base 式(`baseExpr`、型 `baseRef`)に対し、field path(`fields`)を
141
+ * **静的 struct field access** で辿る式と、辿り着いた型 {@link TypeRef} を返す。map lookup でなく
142
+ * struct field 直参照であること(=de-box されている)が per-lang 実装の責務。
143
+ */
144
+ typedFieldAccess?(baseExpr: string, baseRef: TypeRef, fields: string[], plan: TypePlan): {
145
+ expr: string;
146
+ ref: TypeRef;
147
+ };
148
+ /**
149
+ * serializeTyped — 具体 typed 値式(`typedExpr`、型 `ref`)を、canonical 直列化のための動的 Value へ
150
+ * 戻す式を返す(観測等価 pin 用。exec は typed のまま進み、境界でだけ Value 化して golden と突き合わせる)。
151
+ */
152
+ serializeTyped?(typedExpr: string, ref: TypeRef, plan: TypePlan): string;
153
+ }
154
+ /** 型プランから named 宣言を名前で引く(per-language materializer の共有ヘルパ)。 */
155
+ export declare function findDecl(plan: TypePlan, name: string): TypeDecl | undefined;
156
+ //# sourceMappingURL=typed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typed.d.ts","sourceRoot":"","sources":["../../src/generator/typed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAa,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAIhF;;;;;;;GAOG;AACH,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;CAAE,GACxE;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpC,mEAAmE;AACnE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CAC3C;AAED;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAiDD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,gBAAgB,GAAG,QAAQ,CAU5D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAUtE;AAmBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACtC;;OAEG;IACH,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC;IAGpC;;;;OAIG;IACH,eAAe,CAAC,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzC;;;;OAIG;IACH,eAAe,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxE;;;;OAIG;IACH,gBAAgB,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,OAAO,CAAA;KAAE,CAAC;IACxH;;;OAGG;IACH,cAAc,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;CAC1E;AAED,+DAA+D;AAC/D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAE3E"}
@@ -0,0 +1,108 @@
1
+ /** obj 型の構造キー(dedup 用・決定的)。field 名(宣言順)+各 field 型の構造キーを連結する。 */
2
+ function structuralKey(t) {
3
+ if (typeof t === "string")
4
+ return t;
5
+ if ("opt" in t)
6
+ return `opt(${structuralKey(t.opt)})`;
7
+ if ("arr" in t)
8
+ return `arr(${structuralKey(t.arr)})`;
9
+ // obj: field 名は宣言順保存(key 順は型記法の意味の一部ではないが、決定性のため入力順で連結)。
10
+ const parts = Object.entries(t.obj).map(([k, v]) => `${k}:${structuralKey(v)}`);
11
+ return `obj{${parts.join(",")}}`;
12
+ }
13
+ /** 決定的 struct 名を組む(`T` + 連番)。同形は同名(dedup)。衝突しない一意名を返す。 */
14
+ function makeName(index) {
15
+ return `T${index}`;
16
+ }
17
+ /**
18
+ * TypePlanBuilder — IR を 1 度走査して named obj 宣言を dedup 収集する。language-neutral。
19
+ * 走査順(=decls の順)は「IR 宣言順(components → body → outType、component.outputType)」で
20
+ * 各注記点を深さ優先に辿った初出順。同一 IR → 同一プラン(決定的)。
21
+ */
22
+ class TypePlanBuilder {
23
+ byKey = new Map();
24
+ order = [];
25
+ /** PortableType を TypeRef へ落とす。obj は named 宣言を(初出なら)登録して named 参照を返す。 */
26
+ ref(t) {
27
+ if (typeof t === "string")
28
+ return { kind: "scalar", scalar: t };
29
+ if ("opt" in t)
30
+ return { kind: "opt", inner: this.ref(t.opt) };
31
+ if ("arr" in t)
32
+ return { kind: "arr", elem: this.ref(t.arr) };
33
+ // obj: dedup key で既登録を探す。無ければ新規宣言(fields を先に解決=ネストの初出順を保つ)。
34
+ const key = structuralKey(t);
35
+ const existing = this.byKey.get(key);
36
+ if (existing)
37
+ return { kind: "named", name: existing.name };
38
+ // 先に名前を確保して自己/相互参照でも安定させる(型記法は非再帰だが決定性のため確保順を固定)。
39
+ const name = makeName(this.order.length);
40
+ const decl = { name, fields: [] };
41
+ this.byKey.set(key, decl);
42
+ this.order.push(decl);
43
+ decl.fields = Object.entries(t.obj).map(([k, v]) => ({ name: k, type: this.ref(v) }));
44
+ return { kind: "named", name };
45
+ }
46
+ plan() {
47
+ return { decls: this.order };
48
+ }
49
+ }
50
+ /**
51
+ * buildTypePlan — IR 全体を走査し、全注記点(body ノード `outType` / component `outputType`)の obj 型を
52
+ * named 宣言に dedup 収集した {@link TypePlan} を返す。注記が 1 つも無ければ decls は空(typed 化する
53
+ * ものが無い=呼び側は untyped straight-line にフォールバックする)。language-neutral・決定的。
54
+ */
55
+ export function buildTypePlan(ir) {
56
+ const b = new TypePlanBuilder();
57
+ for (const comp of ir.components) {
58
+ for (const n of comp.body) {
59
+ const ot = n.outType;
60
+ if (ot !== undefined)
61
+ b.ref(ot);
62
+ }
63
+ if (comp.outputType !== undefined)
64
+ b.ref(comp.outputType);
65
+ }
66
+ return b.plan();
67
+ }
68
+ /**
69
+ * deriveTypeRef — 単一の注記点の型記法を(buildTypePlan と同じ dedup 規律で)TypeRef へ落とす。
70
+ * ただし named 宣言の同定はプランの走査で既に確定しているため、ここでは同じ structuralKey で
71
+ * プラン内 decl を引く(プランに無い obj 型は渡されない前提 — buildTypePlan が全注記点を網羅する)。
72
+ */
73
+ export function deriveTypeRef(t, plan) {
74
+ if (typeof t === "string")
75
+ return { kind: "scalar", scalar: t };
76
+ if ("opt" in t)
77
+ return { kind: "opt", inner: deriveTypeRef(t.opt, plan) };
78
+ if ("arr" in t)
79
+ return { kind: "arr", elem: deriveTypeRef(t.arr, plan) };
80
+ const key = structuralKey(t);
81
+ const decl = plan.decls.find((d) => structuralKey(objTypeOf(d, plan)) === key);
82
+ if (!decl)
83
+ // buildTypePlan が全注記点を網羅するので通常到達しない(fail-closed で silent 誤生成を防ぐ)。
84
+ throw new Error(`typed emit: obj type not found in the type plan (structuralKey=${key}) — buildTypePlan must cover every annotation point`);
85
+ return { kind: "named", name: decl.name };
86
+ }
87
+ /** TypeDecl を元の obj PortableType へ復元する(structuralKey 照合用・内部)。 */
88
+ function objTypeOf(d, plan) {
89
+ const obj = {};
90
+ for (const f of d.fields)
91
+ obj[f.name] = typeRefToPortable(f.type, plan);
92
+ return { obj };
93
+ }
94
+ function typeRefToPortable(r, plan) {
95
+ if (r.kind === "scalar")
96
+ return r.scalar;
97
+ if (r.kind === "opt")
98
+ return { opt: typeRefToPortable(r.inner, plan) };
99
+ if (r.kind === "arr")
100
+ return { arr: typeRefToPortable(r.elem, plan) };
101
+ const decl = plan.decls.find((d) => d.name === r.name);
102
+ return objTypeOf(decl, plan);
103
+ }
104
+ /** 型プランから named 宣言を名前で引く(per-language materializer の共有ヘルパ)。 */
105
+ export function findDecl(plan, name) {
106
+ return plan.decls.find((d) => d.name === name);
107
+ }
108
+ //# sourceMappingURL=typed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typed.js","sourceRoot":"","sources":["../../src/generator/typed.ts"],"names":[],"mappings":"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"}
package/dist/guard.d.ts CHANGED
@@ -30,6 +30,24 @@ export declare function assertPortable(value: unknown, path?: string): void;
30
30
  * として fail-closed で拒否する(component-graph の port 式・output・map.over/cond に適用)。
31
31
  */
32
32
  export declare const PORTABLE_EXPR_OPERATORS: ReadonlySet<string>;
33
+ /**
34
+ * 可搬型記法(Portable Type Notation, B0 / bc#44)のスカラ閉集合
35
+ * (scp-ir-architecture.md §5.2)。複合型は `{opt|arr|obj: …}` の単一キー object のみ。
36
+ * `assertPortableTypeNotation` はこの閉集合外の型ノード(未知スカラ・未知複合キー・
37
+ * 0/複数キー object・obj field の `__proto__`)を fail-closed で拒否する(`"any"` エスケープ無し)。
38
+ */
39
+ export declare const PORTABLE_SCALAR_TYPES: ReadonlySet<string>;
40
+ /**
41
+ * assertPortableTypeNotation — 可搬型記法(§5.2)を Expression IR と同じ強度で検証する。
42
+ * 型注記フィールド(body ノード `outType` / Component `outputType` / catalog `elemType`)に
43
+ * 使う。閉集合:
44
+ * - スカラ: 5 種の文字列リテラル(PORTABLE_SCALAR_TYPES)のみ。
45
+ * - `{opt: T}` / `{arr: T}`: 単一キー object・値は型 T(再帰)。
46
+ * - `{obj: {field: T, …}}`: 単一キー object・値は field→型の object(`__proto__` キー禁止)。
47
+ *
48
+ * @throws {PortabilityError} 閉集合外の型記法を検出したとき(fail-closed)。
49
+ */
50
+ export declare function assertPortableTypeNotation(node: unknown, path: string): void;
33
51
  /**
34
52
  * assertPortableComponentGraph — component-graph IR(scp-ir-architecture.md §5)の
35
53
  * 可搬性 Guard(P0-2)。generic な {@link assertPortable}(関数/Date/Promise 残存禁止)に加え、
@@ -1 +1 @@
1
- {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,IAAI,EAAE,MAAM,CAAC;gBACD,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK1C;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAM,GAAG,IAAI,CAa/D;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAKtD,CAAC;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,SAAM,GAAG,IAAI,CAQ1E"}
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,IAAI,EAAE,MAAM,CAAC;gBACD,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK1C;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAM,GAAG,IAAI,CAa/D;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAKtD,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,MAAM,CAEpD,CAAC;AAEH;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CA+C5E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,SAAM,GAAG,IAAI,CAQ1E"}