behavior-contracts 0.5.0 → 0.7.0

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 (112) hide show
  1. package/dist/behavior.d.ts +7 -0
  2. package/dist/behavior.d.ts.map +1 -1
  3. package/dist/behavior.js.map +1 -1
  4. package/dist/builder.d.ts.map +1 -1
  5. package/dist/builder.js +10 -3
  6. package/dist/builder.js.map +1 -1
  7. package/dist/generator/async-plan.d.ts +78 -0
  8. package/dist/generator/async-plan.d.ts.map +1 -0
  9. package/dist/generator/async-plan.js +116 -0
  10. package/dist/generator/async-plan.js.map +1 -0
  11. package/dist/generator/core.d.ts +30 -9
  12. package/dist/generator/core.d.ts.map +1 -1
  13. package/dist/generator/core.js.map +1 -1
  14. package/dist/generator/{emit-straightline-typed-go.d.ts → emit-shared-go-typed.d.ts} +11 -17
  15. package/dist/generator/emit-shared-go-typed.d.ts.map +1 -0
  16. package/dist/generator/emit-shared-go-typed.js +572 -0
  17. package/dist/generator/emit-shared-go-typed.js.map +1 -0
  18. package/dist/generator/emit-shared-go.d.ts +29 -0
  19. package/dist/generator/emit-shared-go.d.ts.map +1 -0
  20. package/dist/generator/{emit-straightline-go.js → emit-shared-go.js} +2 -34
  21. package/dist/generator/emit-shared-go.js.map +1 -0
  22. package/dist/generator/{emit-straightline-typed-rust.d.ts → emit-shared-rust-typed.d.ts} +11 -17
  23. package/dist/generator/emit-shared-rust-typed.d.ts.map +1 -0
  24. package/dist/generator/emit-shared-rust-typed.js +576 -0
  25. package/dist/generator/emit-shared-rust-typed.js.map +1 -0
  26. package/dist/generator/{emit-straightline-rust.d.ts → emit-shared-rust.d.ts} +1 -36
  27. package/dist/generator/emit-shared-rust.d.ts.map +1 -0
  28. package/dist/generator/{emit-straightline-rust.js → emit-shared-rust.js} +2 -16
  29. package/dist/generator/emit-shared-rust.js.map +1 -0
  30. package/dist/generator/emit-shared-typescript.d.ts +12 -0
  31. package/dist/generator/emit-shared-typescript.d.ts.map +1 -0
  32. package/dist/generator/{emit-straightline-typescript.js → emit-shared-typescript.js} +5 -20
  33. package/dist/generator/emit-shared-typescript.js.map +1 -0
  34. package/dist/generator/emit-straightline-typed-typescript.d.ts +1 -1
  35. package/dist/generator/emit-straightline-typed-typescript.d.ts.map +1 -1
  36. package/dist/generator/emit-straightline-typed-typescript.js +1 -1
  37. package/dist/generator/emit-straightline-typed-typescript.js.map +1 -1
  38. package/dist/generator/emit-typed-native-go.d.ts.map +1 -1
  39. package/dist/generator/emit-typed-native-go.js +546 -82
  40. package/dist/generator/emit-typed-native-go.js.map +1 -1
  41. package/dist/generator/emit-typed-native-rust.d.ts +2 -1
  42. package/dist/generator/emit-typed-native-rust.d.ts.map +1 -1
  43. package/dist/generator/emit-typed-native-rust.js +597 -110
  44. package/dist/generator/emit-typed-native-rust.js.map +1 -1
  45. package/dist/generator/index.d.ts +2 -12
  46. package/dist/generator/index.d.ts.map +1 -1
  47. package/dist/generator/index.js +10 -62
  48. package/dist/generator/index.js.map +1 -1
  49. package/dist/generator/native-expr.d.ts +120 -0
  50. package/dist/generator/native-expr.d.ts.map +1 -0
  51. package/dist/generator/native-expr.js +456 -0
  52. package/dist/generator/native-expr.js.map +1 -0
  53. package/dist/generator/typed.d.ts.map +1 -1
  54. package/dist/generator/typed.js +8 -0
  55. package/dist/generator/typed.js.map +1 -1
  56. package/dist/guard.js +14 -0
  57. package/dist/guard.js.map +1 -1
  58. package/dist/index.d.ts +2 -2
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +1 -1
  61. package/dist/index.js.map +1 -1
  62. package/dist/plan.d.ts +6 -2
  63. package/dist/plan.d.ts.map +1 -1
  64. package/dist/plan.js +4 -0
  65. package/dist/plan.js.map +1 -1
  66. package/package.json +1 -1
  67. package/dist/generator/emit-go.d.ts +0 -19
  68. package/dist/generator/emit-go.d.ts.map +0 -1
  69. package/dist/generator/emit-go.js +0 -79
  70. package/dist/generator/emit-go.js.map +0 -1
  71. package/dist/generator/emit-raw-abi-go.d.ts +0 -45
  72. package/dist/generator/emit-raw-abi-go.d.ts.map +0 -1
  73. package/dist/generator/emit-raw-abi-go.js +0 -346
  74. package/dist/generator/emit-raw-abi-go.js.map +0 -1
  75. package/dist/generator/emit-raw-abi-rust.d.ts +0 -45
  76. package/dist/generator/emit-raw-abi-rust.d.ts.map +0 -1
  77. package/dist/generator/emit-raw-abi-rust.js +0 -380
  78. package/dist/generator/emit-raw-abi-rust.js.map +0 -1
  79. package/dist/generator/emit-rust.d.ts +0 -25
  80. package/dist/generator/emit-rust.d.ts.map +0 -1
  81. package/dist/generator/emit-rust.js +0 -125
  82. package/dist/generator/emit-rust.js.map +0 -1
  83. package/dist/generator/emit-straightline-go.d.ts +0 -60
  84. package/dist/generator/emit-straightline-go.d.ts.map +0 -1
  85. package/dist/generator/emit-straightline-go.js.map +0 -1
  86. package/dist/generator/emit-straightline-native-go.d.ts +0 -54
  87. package/dist/generator/emit-straightline-native-go.d.ts.map +0 -1
  88. package/dist/generator/emit-straightline-native-go.js +0 -835
  89. package/dist/generator/emit-straightline-native-go.js.map +0 -1
  90. package/dist/generator/emit-straightline-native-rust.d.ts +0 -27
  91. package/dist/generator/emit-straightline-native-rust.d.ts.map +0 -1
  92. package/dist/generator/emit-straightline-native-rust.js +0 -624
  93. package/dist/generator/emit-straightline-native-rust.js.map +0 -1
  94. package/dist/generator/emit-straightline-php.d.ts +0 -46
  95. package/dist/generator/emit-straightline-php.d.ts.map +0 -1
  96. package/dist/generator/emit-straightline-php.js +0 -941
  97. package/dist/generator/emit-straightline-php.js.map +0 -1
  98. package/dist/generator/emit-straightline-python.d.ts +0 -36
  99. package/dist/generator/emit-straightline-python.d.ts.map +0 -1
  100. package/dist/generator/emit-straightline-python.js +0 -855
  101. package/dist/generator/emit-straightline-python.js.map +0 -1
  102. package/dist/generator/emit-straightline-rust.d.ts.map +0 -1
  103. package/dist/generator/emit-straightline-rust.js.map +0 -1
  104. package/dist/generator/emit-straightline-typed-go.d.ts.map +0 -1
  105. package/dist/generator/emit-straightline-typed-go.js +0 -1114
  106. package/dist/generator/emit-straightline-typed-go.js.map +0 -1
  107. package/dist/generator/emit-straightline-typed-rust.d.ts.map +0 -1
  108. package/dist/generator/emit-straightline-typed-rust.js +0 -1155
  109. package/dist/generator/emit-straightline-typed-rust.js.map +0 -1
  110. package/dist/generator/emit-straightline-typescript.d.ts +0 -47
  111. package/dist/generator/emit-straightline-typescript.d.ts.map +0 -1
  112. package/dist/generator/emit-straightline-typescript.js.map +0 -1
@@ -1,5 +1,7 @@
1
1
  /**
2
- * emit-straightline-typed-go.ts — Go typed 直線 emitter(bc#47 / Layer B2, 実 de-box)。
2
+ * emit-shared-go-typed.ts — Go typed 共有 emit エンジン(旧 emit-straightline-typed-go.ts, bc#47 / Layer B2)。
3
+ * #90/#99 で go-typed emitter plugin surface は撤去。この module は native(go) が消費する共有 typed
4
+ * ヘルパ(goTypedInternals: typedFieldAccess/materializeExpr/emitMarshallers/emitTypeDecls/serializeTyped 等)のみ。
3
5
  *
4
6
  * typed-codegen.md §4.3/§4.4 の Go 具体化。**最初のコンパイル言語の typed emitter**であり、B2-ts で
5
7
  * decls-only だった {@link TypedMaterializer} seam を **runtime-materialization 対応に拡張(co-design)**
@@ -27,9 +29,9 @@
27
29
  * `outType`/`outputType` が IR のどこにも無ければ typed 層は emit されず、出力は `go-straightline` と
28
30
  * byte-identical(後方互換 pin)。
29
31
  */
30
- import type { EmitContext, EmitterPlugin } from "./core.js";
31
- import { type TypePlan, type TypeRef, type TypedMaterializer } from "./typed.js";
32
- import { setGoForceRunPlanHelpers } from "./emit-straightline-go.js";
32
+ import type { EmitContext } from "./core.js";
33
+ import { type TypePlan, type TypeRef } from "./typed.js";
34
+ import { setGoForceRunPlanHelpers } from "./emit-shared-go.js";
33
35
  import type { Component } from "../behavior.js";
34
36
  /** 可搬スカラ → Go の具体型名(de-box 後の struct field 型)。int/float は int64/float64 で区別。 */
35
37
  declare function goScalar(scalar: "string" | "int" | "float" | "bool" | "null"): string;
@@ -67,7 +69,6 @@ declare function typedFieldAccess(baseExpr: string, baseRef: TypeRef, fields: st
67
69
  * そのまま Value、arr→要素 ser ループ helper、opt→null 分岐 helper。式一発で返せるよう helper を通す。
68
70
  */
69
71
  declare function serializeTyped(typedExpr: string, ref: TypeRef, _plan: TypePlan): string;
70
- export declare const goTypedMaterializer: TypedMaterializer;
71
72
  /** 各 named struct を canonical Value(*Obj, field は宣言順)へ戻す `ser_T*` + 汎用 arr/opt helper を emit。 */
72
73
  declare function emitSerializers(plan: TypePlan): string;
73
74
  /** component 名 → Go 関数名(straight-line と同規律)。 */
@@ -107,16 +108,10 @@ declare function emitMustHelpers(plan: TypePlan): string;
107
108
  */
108
109
  declare function emitArrOptNodeHelpers(ctx: EmitContext, plan: TypePlan): string;
109
110
  /**
110
- * goTypedEmitter言語識別子 `go-typed` emitter plugin(bc#47 B2, 実 de-box)。
111
- * go-straightline 本体(byte 同一)+ typed 層(struct/marshaller/serializer/typedView)。
112
- * `outType` 無し IR go-straightline と byte-identical(後方互換)。
113
- */
114
- export declare const goTypedEmitter: EmitterPlugin;
115
- /**
116
- * goTypedInternals — shared Go typed-emit helpers the RAW-ABI emitter (bc#76,
117
- * emit-raw-abi-go.ts) reuses so boxed and raw paths keep one implementation of the
118
- * type-plan/naming/serializer discipline (only the marshaller data plane and the handler
119
- * dispatch differ between them).
111
+ * goTypedInternalsshared Go typed-emit helpers the native emitter (emit-typed-native-go.ts)
112
+ * reuses so the native de-box path shares one implementation of the type-plan/naming/serializer/
113
+ * marshaller discipline. This module carries NO emitter plugin (#90/#99): the go-typed and
114
+ * go-straightline emitter surfaces were removed — go converges to the native target only.
120
115
  */
121
116
  export declare const goTypedInternals: {
122
117
  PKG: string;
@@ -143,7 +138,6 @@ export declare const goTypedInternals: {
143
138
  emitBehaviorPlanLiteral: (plan: unknown) => string;
144
139
  goPortVar: (name: string) => string;
145
140
  setGoForceRunPlanHelpers: typeof setGoForceRunPlanHelpers;
146
- goStraightlineEmitter: EmitterPlugin;
147
141
  };
148
142
  export {};
149
- //# sourceMappingURL=emit-straightline-typed-go.d.ts.map
143
+ //# sourceMappingURL=emit-shared-go-typed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit-shared-go-typed.d.ts","sourceRoot":"","sources":["../../src/generator/emit-shared-go-typed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,OAAO,EAEb,MAAM,YAAY,CAAC;AACpB,OAAO,EAA2B,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAGxF,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,gBAAgB,CAAC;AAO9D,gFAAgF;AAChF,iBAAS,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAc9E;AAED,yEAAyE;AACzE,iBAAS,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAY3C;AAED;8DAC8D;AAC9D,iBAAS,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAc7C;AAED,wFAAwF;AACxF,iBAAS,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOzC;AAED;;;;GAIG;AACH,iBAAS,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAG/C;AA8FD;;;;;GAKG;AACH,iBAAS,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,GAAG,MAAM,CAW/E;AAED;;;GAGG;AACH,iBAAS,gBAAgB,CACvB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,QAAQ,GACb;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAchC;AAED;;;;GAIG;AACH,iBAAS,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,GAAG,MAAM,CAYhF;AASD,iGAAiG;AACjG,iBAAS,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CA0B/C;AAID,gDAAgD;AAChD,iBAAS,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtC;AAED,oDAAoD;AACpD,iBAAS,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1C;AAYD;;;;;;;;;GASG;AACH,iBAAS,cAAc,CACrB,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,OAAO,GAAG,SAAS,EAC7B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,IAAI,EAAE,QAAQ,GACb;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,CA8D5C;AAoCD;;;GAGG;AACH,iBAAS,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAOhF;AAED,uCAAuC;AACvC,iBAAS,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAc1C;AAID,iBAAS,oBAAoB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAMvD;AAED,6CAA6C;AAC7C,iBAAS,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAGlD;AAED,qFAAqF;AACrF,iBAAS,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAgD/C;AAED;;;;GAIG;AACH,iBAAS,qBAAqB,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CA0CvE;AAkBD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;uCAoBQ,SAAS;;;;;CAM7C,CAAC"}
@@ -0,0 +1,572 @@
1
+ import { deriveTypeRef, findDecl, } from "./typed.js";
2
+ import { goStraightlineInternals, setGoForceRunPlanHelpers } from "./emit-shared-go.js";
3
+ import { buildComponentPlan } from "./straightline.js";
4
+ import { GeneratorFailure } from "./core.js";
5
+ /** runtime package alias(生成コード内)— straight-line と同じ `dslcontracts`。 */
6
+ const PKG = "dslcontracts";
7
+ // ── Go typed materializer(TypedMaterializer seam の Go 具体化 — 拡張 hook 実装)────
8
+ /** 可搬スカラ → Go の具体型名(de-box 後の struct field 型)。int/float は int64/float64 で区別。 */
9
+ function goScalar(scalar) {
10
+ switch (scalar) {
11
+ case "string":
12
+ return "string";
13
+ case "int":
14
+ return "int64";
15
+ case "float":
16
+ return "float64";
17
+ case "bool":
18
+ return "bool";
19
+ case "null":
20
+ // null 単独型は Go に無いので Value(nil のみ格納)。opt でラップされて現れるのが通常。
21
+ return `${PKG}.Value`;
22
+ }
23
+ }
24
+ /** TypeRef を Go の具体型名へ(named→struct 名、arr→slice、opt→ポインタ、scalar→具体型)。 */
25
+ function renderTypeRef(ref) {
26
+ switch (ref.kind) {
27
+ case "scalar":
28
+ return goScalar(ref.scalar);
29
+ case "opt":
30
+ // nullable は Go ポインタで表す(nil = null)。scalar/struct いずれも `*T`。
31
+ return `*${renderTypeRef(ref.inner)}`;
32
+ case "arr":
33
+ return `[]${renderTypeRef(ref.elem)}`;
34
+ case "named":
35
+ return ref.name;
36
+ }
37
+ }
38
+ /** 型プランの named obj を Go struct 宣言へ(decls 順=決定的)。field は宣言順・export 名。gofmt と同じ
39
+ * 列アラインで綴じる(field 名列・型列を最大幅に揃える — 生成物が gofmt clean になるよう)。 */
40
+ function emitTypeDecls(plan) {
41
+ if (plan.decls.length === 0)
42
+ return "";
43
+ return plan.decls
44
+ .map((d) => {
45
+ const names = d.fields.map((f) => goFieldName(f.name));
46
+ const types = d.fields.map((f) => renderTypeRef(f.type));
47
+ const nameW = Math.max(0, ...names.map((n) => n.length));
48
+ const typeW = Math.max(0, ...types.map((t) => t.length));
49
+ const fields = d.fields
50
+ .map((f, i) => `\t${names[i].padEnd(nameW)} ${types[i].padEnd(typeW)} // ${JSON.stringify(f.name)}`)
51
+ .join("\n");
52
+ return `type ${d.name} struct {\n${fields}\n}`;
53
+ })
54
+ .join("\n\n");
55
+ }
56
+ /** wire field 名 → Go の export struct field 名(決定的・一意)。元名は struct コメント/marshaller で保持。 */
57
+ function goFieldName(wire) {
58
+ // 先頭を大文字化して export(Go の struct field 参照可視性)。非識別子文字は `_`。衝突は元名一意で回避
59
+ // されないので、決定的に元名を base64url なしの安全化+先頭大文字で綴じ、marshaller が wire キーで対応づける。
60
+ const safe = wire.replace(/[^A-Za-z0-9_]/g, "_");
61
+ const head = safe.charAt(0);
62
+ const capitalized = /[a-z]/.test(head) ? head.toUpperCase() + safe.slice(1) : "F_" + safe;
63
+ return capitalized;
64
+ }
65
+ /**
66
+ * emitMarshallers — 各 named struct の raw→typed marshaller(§4.4)。動的 Value(`*Obj` 期待)を受け、
67
+ * 各 field を typed に読み出して具体 struct を組む。generic Value 走査を exec 経路から除去する de-box の実体。
68
+ * field 型ごとに再帰: named→marshal_T*、arr→要素ループ、opt→null 分岐、scalar→型 assert。
69
+ */
70
+ function emitMarshallers(plan) {
71
+ if (plan.decls.length === 0)
72
+ return "";
73
+ return plan.decls.map((d) => emitOneMarshaller(d, plan)).join("\n\n");
74
+ }
75
+ function emitOneMarshaller(d, plan) {
76
+ const lines = [];
77
+ lines.push(`func marshal_${d.name}(raw ${PKG}.Value) (${d.name}, error) {`);
78
+ lines.push(`\tvar out ${d.name}`);
79
+ lines.push(`\to, ok := raw.(*${PKG}.Obj)`);
80
+ lines.push(`\tif !ok {`);
81
+ lines.push(`\t\treturn out, ${PKG}.NewExprFailure("TYPE_MISMATCH", "typed marshal ${d.name}: expected obj, got "+${PKG}.TypeName(raw))`);
82
+ lines.push(`\t}`);
83
+ for (const f of d.fields) {
84
+ const goName = goFieldName(f.name);
85
+ const keyLit = JSON.stringify(f.name);
86
+ lines.push(`\t{`);
87
+ lines.push(`\t\tfv, present := o.Get(${keyLit})`);
88
+ lines.push(`\t\tif !present {`);
89
+ lines.push(`\t\t\treturn out, ${PKG}.NewExprFailure("MISSING_PROP", "typed marshal ${d.name}: missing property ."+${keyLit})`);
90
+ lines.push(`\t\t}`);
91
+ lines.push(emitFieldMaterialize(`out.${goName}`, "fv", f.type, plan, 2));
92
+ lines.push(`\t}`);
93
+ }
94
+ lines.push(`\treturn out, nil`);
95
+ lines.push(`}`);
96
+ return lines.join("\n");
97
+ }
98
+ /**
99
+ * emitFieldMaterialize — `target` (typed lvalue) に `src` (Value 式) を型 `ref` で materialize して代入する
100
+ * Go 文ブロックを返す(indent = タブ数)。scalar は型 assert、named は marshal_T* 呼び、arr は要素ループ、
101
+ * opt は null 分岐(ポインタ)。すべて具体 Go 型で組む(de-box)。fail は expr.go と同じ Failure code。
102
+ */
103
+ function emitFieldMaterialize(target, src, ref, plan, indent) {
104
+ const t = "\t".repeat(indent);
105
+ switch (ref.kind) {
106
+ case "scalar": {
107
+ if (ref.scalar === "null") {
108
+ return `${t}${target} = ${src}`;
109
+ }
110
+ const gt = goScalar(ref.scalar);
111
+ const assertType = ref.scalar === "int" ? "int64" : ref.scalar === "float" ? "float64" : gt;
112
+ return [
113
+ `${t}sv, sok := ${src}.(${assertType})`,
114
+ `${t}if !sok {`,
115
+ `${t}\treturn out, ${PKG}.NewExprFailure("TYPE_MISMATCH", "typed marshal: expected ${ref.scalar}, got "+${PKG}.TypeName(${src}))`,
116
+ `${t}}`,
117
+ `${t}${target} = sv`,
118
+ ].join("\n");
119
+ }
120
+ case "named": {
121
+ return [
122
+ `${t}mv, merr := marshal_${ref.name}(${src})`,
123
+ `${t}if merr != nil {`,
124
+ `${t}\treturn out, merr`,
125
+ `${t}}`,
126
+ `${t}${target} = mv`,
127
+ ].join("\n");
128
+ }
129
+ case "arr": {
130
+ const elemGo = renderTypeRef(ref.elem);
131
+ const inner = emitFieldMaterialize("elemOut", "elemRaw", ref.elem, plan, indent + 1);
132
+ return [
133
+ `${t}arr, aok := ${src}.([]${PKG}.Value)`,
134
+ `${t}if !aok {`,
135
+ `${t}\treturn out, ${PKG}.NewExprFailure("TYPE_MISMATCH", "typed marshal: expected arr, got "+${PKG}.TypeName(${src}))`,
136
+ `${t}}`,
137
+ `${t}slice := make([]${elemGo}, 0, len(arr))`,
138
+ `${t}for _, elemRaw := range arr {`,
139
+ `${t}\tvar elemOut ${elemGo}`,
140
+ inner,
141
+ `${t}\tslice = append(slice, elemOut)`,
142
+ `${t}}`,
143
+ `${t}${target} = slice`,
144
+ ].join("\n");
145
+ }
146
+ case "opt": {
147
+ const innerGo = renderTypeRef(ref.inner);
148
+ const inner = emitFieldMaterialize("optOut", src, ref.inner, plan, indent + 1);
149
+ return [
150
+ `${t}if ${src} == nil {`,
151
+ `${t}\t${target} = nil`,
152
+ `${t}} else {`,
153
+ `${t}\tvar optOut ${innerGo}`,
154
+ inner,
155
+ `${t}\t${target} = &optOut`,
156
+ `${t}}`,
157
+ ].join("\n");
158
+ }
159
+ }
160
+ }
161
+ /**
162
+ * materializeExpr — raw な Value 式 `rawExpr` を型 `ref` の具体 typed 値へ変換する **単一式**(exec 経路の
163
+ * de-box)。named→`mustMarshal_T*`(marshaller 経由で具体 struct へ)、scalar→型 assert helper、arr/opt→
164
+ * 具体 slice/pointer helper。呼び側(typed view の output assembly / node materialize)が typed ローカルへ束ねる。
165
+ * これが seam の runtime-materialization hook の Go 実装本体(rust #48 は同型の hook を返す)。
166
+ */
167
+ function materializeExpr(rawExpr, ref, _plan) {
168
+ switch (ref.kind) {
169
+ case "named":
170
+ return `mustMarshal_${ref.name}(${rawExpr})`;
171
+ case "scalar":
172
+ return `mustScalar_${ref.scalar}(${rawExpr})`;
173
+ case "arr":
174
+ return `mustArr_${arrHelperKey(ref)}(${rawExpr})`;
175
+ case "opt":
176
+ return `mustOpt_${arrHelperKey(ref)}(${rawExpr})`;
177
+ }
178
+ }
179
+ /**
180
+ * typedFieldAccess — typed base 式 `baseExpr`(型 `baseRef`)に field path を **struct field 直参照**で辿る。
181
+ * map lookup ではなく `.FieldName` 連結(=de-box されている証拠)。辿り着いた TypeRef も返す。
182
+ */
183
+ function typedFieldAccess(baseExpr, baseRef, fields, plan) {
184
+ let expr = baseExpr;
185
+ let ref = baseRef;
186
+ for (const f of fields) {
187
+ if (ref.kind !== "named") {
188
+ throw new Error(`typed go: field access '.${f}' on non-struct TypeRef ${JSON.stringify(ref)}`);
189
+ }
190
+ const decl = findDecl(plan, ref.name);
191
+ const fld = decl?.fields.find((x) => x.name === f);
192
+ if (!fld)
193
+ throw new Error(`typed go: field '${f}' not found on struct ${ref.name}`);
194
+ expr = `${expr}.${goFieldName(f)}`; // struct field 直参照(map lookup でない)
195
+ ref = fld.type;
196
+ }
197
+ return { expr, ref };
198
+ }
199
+ /**
200
+ * serializeTyped — 具体 typed 値式を canonical 直列化用の動的 Value へ戻す式(観測等価 pin)。exec は
201
+ * typed のまま進み、component 境界でだけ Value 化して golden と突き合わせる。named→ser_T*、scalar は
202
+ * そのまま Value、arr→要素 ser ループ helper、opt→null 分岐 helper。式一発で返せるよう helper を通す。
203
+ */
204
+ function serializeTyped(typedExpr, ref, _plan) {
205
+ switch (ref.kind) {
206
+ case "named":
207
+ return `ser_${ref.name}(${typedExpr})`;
208
+ case "scalar":
209
+ // 具体スカラは Value に代入可能(string/int64/float64/bool は Value=interface{})。
210
+ return `${PKG}.Value(${typedExpr})`;
211
+ case "arr":
212
+ return `serArr(${typedExpr}, func(e ${renderTypeRef(ref.elem)}) ${PKG}.Value { return ${serializeTyped("e", ref.elem, _plan)} })`;
213
+ case "opt":
214
+ return `serOpt(${typedExpr} == nil, func() ${PKG}.Value { return ${serializeTypedOptInner(ref.inner, typedExpr, _plan)} })`;
215
+ }
216
+ }
217
+ /** opt の非 nil 分岐: `*ptr` を deref して inner を serialize。 */
218
+ function serializeTypedOptInner(inner, ptrExpr, plan) {
219
+ return serializeTyped(`(*${ptrExpr})`, inner, plan);
220
+ }
221
+ // ── serializer helper(named struct → Value)を型プランから emit ────────────────────
222
+ /** 各 named struct を canonical Value(*Obj, field は宣言順)へ戻す `ser_T*` + 汎用 arr/opt helper を emit。 */
223
+ function emitSerializers(plan) {
224
+ const perStruct = plan.decls.map((d) => {
225
+ const sets = d.fields
226
+ .map((f) => {
227
+ const val = serializeTyped(`v.${goFieldName(f.name)}`, f.type, plan);
228
+ return `\to.Set(${JSON.stringify(f.name)}, ${val})`;
229
+ })
230
+ .join("\n");
231
+ return `func ser_${d.name}(v ${d.name}) ${PKG}.Value {\n\to := ${PKG}.NewObj()\n${sets}\n\treturn o\n}`;
232
+ });
233
+ // 汎用 arr/opt serialize helper(型パラメタで要素 serializer を受ける)。
234
+ const generic = `func serArr[T any](xs []T, ser func(T) ${PKG}.Value) ${PKG}.Value {
235
+ \tout := make([]${PKG}.Value, 0, len(xs))
236
+ \tfor _, x := range xs {
237
+ \t\tout = append(out, ser(x))
238
+ \t}
239
+ \treturn out
240
+ }
241
+
242
+ func serOpt(isNil bool, ser func() ${PKG}.Value) ${PKG}.Value {
243
+ \tif isNil {
244
+ \t\treturn nil
245
+ \t}
246
+ \treturn ser()
247
+ }`;
248
+ return perStruct.length === 0 ? generic : `${generic}\n\n${perStruct.join("\n\n")}`;
249
+ }
250
+ // ── typed view 関数(実 exec 経路 — 実 de-box)─────────────────────────────────────
251
+ /** component 名 → Go 関数名(straight-line と同規律)。 */
252
+ function sanitize(name) {
253
+ return name.replace(/[^A-Za-z0-9_]/g, "_");
254
+ }
255
+ /** 生成コード内の typed ローカル変数名(materialize 済み struct)。 */
256
+ function typedLocal(nodeId) {
257
+ return `t_${nodeId.replace(/[^A-Za-z0-9_]/g, "_")}`;
258
+ }
259
+ /** `ref` の path 配列(Expression IR)を取り出す。単純 ref ノードでなければ undefined。 */
260
+ function refPathOf(node) {
261
+ if (node === null || typeof node !== "object" || Array.isArray(node))
262
+ return undefined;
263
+ const keys = Object.keys(node);
264
+ if (keys.length !== 1 || keys[0] !== "ref")
265
+ return undefined;
266
+ const path = node.ref;
267
+ if (!Array.isArray(path) || !path.every((p) => typeof p === "string"))
268
+ return undefined;
269
+ return path;
270
+ }
271
+ /**
272
+ * emitTypedValue — output(Φ 合流式)IR を、期待型 `expected` の **具体 Go typed 値**式へ再帰 lower し、
273
+ * `{ expr, ref }` を返す。これが AC2 の「exec が具体 struct を保持」の実体:
274
+ * - `{ref:[typedNode, …fields]}` → typed struct field 直参照(typedFieldAccess — map lookup でない)。
275
+ * - `{ref:[input/非 typed node]}` → 型付け不能な生 Value。expected があれば materialize(de-box)。
276
+ * - `{obj:{…}}` → 具体 struct literal(expected が named のとき各 field を期待型で lower)。
277
+ * - `{arr:[…]}` → 具体 slice literal(要素は要素型で lower)。
278
+ * - scalar literal → 具体 Go 値。
279
+ * - 演算子(concat/…)→ straight-line 生値を expected へ materialize(意味論は SSoT が持つ)。
280
+ */
281
+ function emitTypedValue(node, expected, typedNodes, plan) {
282
+ const path = refPathOf(node);
283
+ if (path && path.length >= 1) {
284
+ const head = path[0];
285
+ if (typedNodes.has(head)) {
286
+ // typed node への参照: struct field 直参照で辿る(de-box された struct access)。
287
+ const baseRef = typedNodes.get(head);
288
+ const { expr, ref } = typedFieldAccess(typedLocal(head), baseRef, path.slice(1), plan);
289
+ return { expr, ref };
290
+ }
291
+ // input param 参照(非 typed node): input Value(portScope)を局所的に読み、expected へ materialize
292
+ // (de-box)。これは動的 Value tree の再構築ではなく input 境界値の 1 leaf 読み(許容される局所変換)。
293
+ // bc typed corpus の output は input を直参照しないので通常到達しないが、健全に処理する。
294
+ if (expected)
295
+ return { expr: materializeExpr(scopeRead(path), expected, plan), ref: expected };
296
+ return { expr: scopeRead(path), ref: undefined };
297
+ }
298
+ if (node !== null && typeof node === "object" && !Array.isArray(node)) {
299
+ const keys = Object.keys(node);
300
+ if (keys.length === 1 && keys[0] === "obj" && expected && expected.kind === "named") {
301
+ // 具体 struct literal を組む(de-box した output assembly)。
302
+ const decl = findDecl(plan, expected.name);
303
+ const fields = node.obj;
304
+ const inits = decl.fields.map((f) => {
305
+ const sub = emitTypedValue(fields[f.name], f.type, typedNodes, plan);
306
+ return `${goFieldName(f.name)}: ${sub.expr}`;
307
+ });
308
+ return { expr: `${expected.name}{${inits.join(", ")}}`, ref: expected };
309
+ }
310
+ if (keys.length === 1 && keys[0] === "arr" && expected && expected.kind === "arr") {
311
+ const elems = node.arr;
312
+ const items = elems.map((e) => emitTypedValue(e, expected.elem, typedNodes, plan).expr);
313
+ return { expr: `[]${renderTypeRef(expected.elem)}{${items.join(", ")}}`, ref: expected };
314
+ }
315
+ // concat 演算子: operand を **de-box された typed 値**(typed field access なら concrete string)で
316
+ // 読み、native string 連結する(go-straightline の slConcat と同じ native 化パターン — 意味論保存)。
317
+ // これで scalar-output-via-typed-field-access vector も **具体 struct field を経由した de-box** になる。
318
+ if (keys.length === 1 && keys[0] === "concat" && expected && expected.kind === "scalar" && expected.scalar === "string") {
319
+ const parts = node.concat;
320
+ const partExprs = parts.map((p) => {
321
+ const sub = emitTypedValue(p, { kind: "scalar", scalar: "string" }, typedNodes, plan);
322
+ return sub.expr;
323
+ });
324
+ return { expr: partExprs.join(" + "), ref: expected };
325
+ }
326
+ // その他単一キー = 別演算子(add/eq/…): struct-native exec では動的 Value output tree を組まない方針
327
+ // ゆえ、A0 primitive SSoT を呼ぶ経路(operand の局所 Value 化)を要する。bc typed corpus には output
328
+ // 位置の非 concat 演算子が無いので、ここは **LOUD fail-closed**(silent な Value フォールバックを禁ずる
329
+ // 監査指示に従う)。graphddb #60 / follow-up で primitive-at-boundary 経路を足す。
330
+ if (keys.length === 1) {
331
+ throw new GeneratorFailure("UNSUPPORTED_NODE_STRAIGHTLINE", `go-typed struct-native output: operator '${keys[0]}' at the output position is not supported in the struct-native de-box path yet (typed corpus covers only ref / obj / arr / concat outputs). Do not fall back to building the dynamic Value output tree.`);
332
+ }
333
+ }
334
+ // scalar literal(typed operand として現れる bare リテラル "!"): 具体 Go スカラ。
335
+ if (expected && expected.kind === "scalar") {
336
+ return { expr: litScalar(node, expected.scalar), ref: expected };
337
+ }
338
+ return { expr: litScalarUnknown(node), ref: undefined };
339
+ }
340
+ /** input/非 typed node の scope 読み(動的 Value 式)。slRef 相当のネスト walk を helper で。 */
341
+ function scopeRead(path) {
342
+ // portScope() = input params only(node 結果 *Obj scope は struct-native では存在しない)。
343
+ return `mustInputRef([]string{${path.map((p) => JSON.stringify(p)).join(", ")}}, portScope())`;
344
+ }
345
+ /** 期待スカラの Go リテラル(string/int/float/bool/null)。 */
346
+ function litScalar(node, scalar) {
347
+ if (scalar === "string" && typeof node === "string")
348
+ return JSON.stringify(node);
349
+ if (scalar === "bool" && typeof node === "boolean")
350
+ return node ? "true" : "false";
351
+ if (scalar === "int") {
352
+ if (node !== null && typeof node === "object" && typeof node.int === "string")
353
+ return `int64(${node.int})`;
354
+ if (typeof node === "number")
355
+ return `int64(${node})`;
356
+ }
357
+ if (scalar === "float") {
358
+ if (node !== null && typeof node === "object" && typeof node.float === "number")
359
+ return `float64(${node.float})`;
360
+ if (typeof node === "number")
361
+ return `float64(${node})`;
362
+ }
363
+ if (scalar === "null")
364
+ return "nil";
365
+ // 型が食い違う literal は fail-closed(型プランと不整合)。
366
+ throw new Error(`typed go: scalar literal ${JSON.stringify(node)} does not match expected ${scalar}`);
367
+ }
368
+ function litScalarUnknown(node) {
369
+ if (node === null)
370
+ return "nil";
371
+ if (typeof node === "boolean")
372
+ return node ? "true" : "false";
373
+ if (typeof node === "string")
374
+ return JSON.stringify(node);
375
+ return "nil";
376
+ }
377
+ const PORT_SCOPE = "portScope()";
378
+ /**
379
+ * collectTypedNodes — component の body ノードで outType を持つもの(componentRef / map / cond)を
380
+ * id → 結果 TypeRef に index 化する。map/cond も struct 空間で結果を保持する(#66 de-box 拡張)。
381
+ */
382
+ function collectTypedNodes(comp, plan) {
383
+ const typedNodes = new Map();
384
+ for (const n of comp.body) {
385
+ const ot = n.outType;
386
+ if (ot !== undefined)
387
+ typedNodes.set(n.id, deriveTypeRef(ot, plan));
388
+ }
389
+ return typedNodes;
390
+ }
391
+ /** arr/opt helper 名の決定的キー(要素型で一意化)。 */
392
+ function arrHelperKey(ref) {
393
+ const flat = (r) => {
394
+ switch (r.kind) {
395
+ case "scalar":
396
+ return r.scalar;
397
+ case "named":
398
+ return r.name;
399
+ case "arr":
400
+ return `arr_${flat(r.elem)}`;
401
+ case "opt":
402
+ return `opt_${flat(r.inner)}`;
403
+ }
404
+ };
405
+ return flat(ref);
406
+ }
407
+ // ── module 綴じ(straight-line 本体を scope 露出版で流用 + typed 層)──────────────────
408
+ function hasAnyTypeAnnotation(ctx) {
409
+ for (const comp of ctx.ir.components) {
410
+ if (comp.outputType !== undefined)
411
+ return true;
412
+ for (const n of comp.body)
413
+ if (n.outType !== undefined)
414
+ return true;
415
+ }
416
+ return false;
417
+ }
418
+ /** typed component(typedView 経路で駆動するもの)か。 */
419
+ function isTypedComponent(comp) {
420
+ if (comp.outputType !== undefined)
421
+ return true;
422
+ return comp.body.some((n) => n.outType !== undefined);
423
+ }
424
+ /** must 系 helper(struct-native exec の scalar/arr/opt/named de-box を単一式で使う)を emit。 */
425
+ function emitMustHelpers(plan) {
426
+ const parts = [];
427
+ // mustInputRef — output が input param を直参照する稀な場合に、input Value(portScope)から 1 leaf を
428
+ // 読む(動的 Value tree の再構築ではなく境界値の局所読み)。エラーは型プランが保証するので best-effort。
429
+ parts.push(`func mustInputRef(path []string, scope *${PKG}.Obj) ${PKG}.Value {
430
+ \tif len(path) == 0 {
431
+ \t\treturn nil
432
+ \t}
433
+ \tcur, ok := scope.Get(path[0])
434
+ \tif !ok {
435
+ \t\treturn nil
436
+ \t}
437
+ \tfor _, seg := range path[1:] {
438
+ \t\to, isObj := cur.(*${PKG}.Obj)
439
+ \t\tif !isObj {
440
+ \t\t\treturn nil
441
+ \t\t}
442
+ \t\tnext, present := o.Get(seg)
443
+ \t\tif !present {
444
+ \t\t\treturn nil
445
+ \t\t}
446
+ \t\tcur = next
447
+ \t}
448
+ \treturn cur
449
+ }`);
450
+ // scalar must helper(型 assert → 具体 Go 値。失敗は panic せず sentinel; 実際には型プランが保証)。
451
+ for (const scalar of ["string", "int", "float", "bool", "null"]) {
452
+ if (scalar === "null") {
453
+ parts.push(`func mustScalar_null(v ${PKG}.Value) ${PKG}.Value { return v }`);
454
+ continue;
455
+ }
456
+ const gt = goScalar(scalar);
457
+ const at = scalar === "int" ? "int64" : scalar === "float" ? "float64" : gt;
458
+ parts.push(`func mustScalar_${scalar}(v ${PKG}.Value) ${gt} {
459
+ \ts, _ := v.(${at})
460
+ \treturn s
461
+ }`);
462
+ }
463
+ // named must-marshal(単一式で使う: err は typed view の named node materialize が別途チェックするので
464
+ // ここでは best-effort。exec 経路の de-box は marshal_T* が担う)。
465
+ for (const d of plan.decls) {
466
+ parts.push(`func mustMarshal_${d.name}(v ${PKG}.Value) ${d.name} {
467
+ \tout, _ := marshal_${d.name}(v)
468
+ \treturn out
469
+ }`);
470
+ }
471
+ return parts.join("\n\n");
472
+ }
473
+ /**
474
+ * emitArrOptNodeHelpers — arr/opt を outType に持つ **node**(named でない node)用の materialize helper
475
+ * `mustArr_*` / `mustOpt_*` を、IR に現れる arr/opt node outType 集合から決定的に emit する。要素/inner が
476
+ * named なら marshaller を、scalar なら型 assert を、ネスト arr/opt なら再帰 helper を呼ぶ(具体 slice/ptr へ de-box)。
477
+ */
478
+ function emitArrOptNodeHelpers(ctx, plan) {
479
+ const seen = new Set();
480
+ const parts = [];
481
+ const need = (ref) => {
482
+ const key = arrHelperKey(ref);
483
+ if (ref.kind === "arr") {
484
+ // 要素が arr/opt なら先に要素 helper を用意する(ネスト de-box)。
485
+ if (ref.elem.kind === "arr" || ref.elem.kind === "opt")
486
+ need(ref.elem);
487
+ if (seen.has(`arr_${key}`))
488
+ return;
489
+ seen.add(`arr_${key}`);
490
+ const elemGo = renderTypeRef(ref.elem);
491
+ parts.push(`func mustArr_${key}(v ${PKG}.Value) []${elemGo} {
492
+ \tarr, _ := v.([]${PKG}.Value)
493
+ \tout := make([]${elemGo}, 0, len(arr))
494
+ \tfor _, e := range arr {
495
+ \t\tout = append(out, ${elemMaterializeExpr(ref.elem)})
496
+ \t}
497
+ \treturn out
498
+ }`);
499
+ }
500
+ else if (ref.kind === "opt") {
501
+ if (ref.inner.kind === "arr" || ref.inner.kind === "opt")
502
+ need(ref.inner);
503
+ if (seen.has(`opt_${key}`))
504
+ return;
505
+ seen.add(`opt_${key}`);
506
+ const innerGo = renderTypeRef(ref.inner);
507
+ parts.push(`func mustOpt_${key}(v ${PKG}.Value) *${innerGo} {
508
+ \tif v == nil {
509
+ \t\treturn nil
510
+ \t}
511
+ \tinner := ${elemMaterializeExpr(ref.inner, "v")}
512
+ \treturn &inner
513
+ }`);
514
+ }
515
+ };
516
+ for (const comp of ctx.ir.components) {
517
+ for (const n of comp.body) {
518
+ const ot = n.outType;
519
+ if (ot === undefined || !("component" in n))
520
+ continue;
521
+ const ref = deriveTypeRef(ot, plan);
522
+ if (ref.kind === "arr" || ref.kind === "opt")
523
+ need(ref);
524
+ }
525
+ }
526
+ return parts.join("\n\n");
527
+ }
528
+ /** arr/opt 要素の materialize 式(named→mustMarshal, scalar→mustScalar, arr/opt→ネスト helper)。 */
529
+ function elemMaterializeExpr(ref, varName = "e") {
530
+ switch (ref.kind) {
531
+ case "named":
532
+ return `mustMarshal_${ref.name}(${varName})`;
533
+ case "scalar":
534
+ return `mustScalar_${ref.scalar}(${varName})`;
535
+ case "arr":
536
+ case "opt":
537
+ return `mustArr_${arrHelperKey(ref)}(${varName})`.replace("mustArr_", ref.kind === "opt" ? "mustOpt_" : "mustArr_");
538
+ }
539
+ }
540
+ /**
541
+ * goTypedInternals — shared Go typed-emit helpers the native emitter (emit-typed-native-go.ts)
542
+ * reuses so the native de-box path shares one implementation of the type-plan/naming/serializer/
543
+ * marshaller discipline. This module carries NO emitter plugin (#90/#99): the go-typed and
544
+ * go-straightline emitter surfaces were removed — go converges to the native target only.
545
+ */
546
+ export const goTypedInternals = {
547
+ PKG,
548
+ sanitize,
549
+ goFieldName,
550
+ renderTypeRef,
551
+ goScalar,
552
+ typedLocal,
553
+ isTypedComponent,
554
+ collectTypedNodes,
555
+ hasAnyTypeAnnotation,
556
+ emitTypeDecls,
557
+ emitSerializers,
558
+ emitMarshallers,
559
+ materializeExpr,
560
+ serializeTyped,
561
+ typedFieldAccess,
562
+ emitTypedValue,
563
+ arrHelperKey,
564
+ emitMustHelpers,
565
+ emitArrOptNodeHelpers,
566
+ buildComponentPlanForTyped: (comp) => buildComponentPlan(comp, goStraightlineInternals.dialect, PORT_SCOPE),
567
+ emitOpsLiteral: goStraightlineInternals.emitOpsLiteral,
568
+ emitBehaviorPlanLiteral: goStraightlineInternals.emitBehaviorPlanLiteral,
569
+ goPortVar: goStraightlineInternals.goPortVar,
570
+ setGoForceRunPlanHelpers,
571
+ };
572
+ //# sourceMappingURL=emit-shared-go-typed.js.map