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.
- package/dist/behavior.d.ts +47 -0
- package/dist/behavior.d.ts.map +1 -1
- package/dist/behavior.js.map +1 -1
- package/dist/generator/core.d.ts +1 -1
- package/dist/generator/core.d.ts.map +1 -1
- package/dist/generator/core.js.map +1 -1
- package/dist/generator/emit-straightline-go.d.ts +77 -0
- package/dist/generator/emit-straightline-go.d.ts.map +1 -0
- package/dist/generator/emit-straightline-go.js +592 -0
- package/dist/generator/emit-straightline-go.js.map +1 -0
- package/dist/generator/emit-straightline-php.d.ts +46 -0
- package/dist/generator/emit-straightline-php.d.ts.map +1 -0
- package/dist/generator/emit-straightline-php.js +501 -0
- package/dist/generator/emit-straightline-php.js.map +1 -0
- package/dist/generator/emit-straightline-python.d.ts +36 -0
- package/dist/generator/emit-straightline-python.d.ts.map +1 -0
- package/dist/generator/emit-straightline-python.js +441 -0
- package/dist/generator/emit-straightline-python.js.map +1 -0
- package/dist/generator/emit-straightline-rust.d.ts +78 -0
- package/dist/generator/emit-straightline-rust.d.ts.map +1 -0
- package/dist/generator/emit-straightline-rust.js +615 -0
- package/dist/generator/emit-straightline-rust.js.map +1 -0
- package/dist/generator/emit-straightline-typed-go.d.ts +39 -0
- package/dist/generator/emit-straightline-typed-go.d.ts.map +1 -0
- package/dist/generator/emit-straightline-typed-go.js +828 -0
- package/dist/generator/emit-straightline-typed-go.js.map +1 -0
- package/dist/generator/emit-straightline-typed-rust.d.ts +48 -0
- package/dist/generator/emit-straightline-typed-rust.d.ts.map +1 -0
- package/dist/generator/emit-straightline-typed-rust.js +823 -0
- package/dist/generator/emit-straightline-typed-rust.js.map +1 -0
- package/dist/generator/emit-straightline-typed-typescript.d.ts +49 -0
- package/dist/generator/emit-straightline-typed-typescript.d.ts.map +1 -0
- package/dist/generator/emit-straightline-typed-typescript.js +314 -0
- package/dist/generator/emit-straightline-typed-typescript.js.map +1 -0
- package/dist/generator/emit-straightline-typescript.d.ts +36 -0
- package/dist/generator/emit-straightline-typescript.d.ts.map +1 -0
- package/dist/generator/emit-straightline-typescript.js +397 -0
- package/dist/generator/emit-straightline-typescript.js.map +1 -0
- package/dist/generator/index.d.ts +13 -0
- package/dist/generator/index.d.ts.map +1 -1
- package/dist/generator/index.js +39 -0
- package/dist/generator/index.js.map +1 -1
- package/dist/generator/literal.d.ts +7 -0
- package/dist/generator/literal.d.ts.map +1 -1
- package/dist/generator/literal.js +41 -0
- package/dist/generator/literal.js.map +1 -1
- package/dist/generator/straightline.d.ts +147 -0
- package/dist/generator/straightline.d.ts.map +1 -0
- package/dist/generator/straightline.js +122 -0
- package/dist/generator/straightline.js.map +1 -0
- package/dist/generator/typed.d.ts +156 -0
- package/dist/generator/typed.d.ts.map +1 -0
- package/dist/generator/typed.js +108 -0
- package/dist/generator/typed.js.map +1 -0
- package/dist/guard.d.ts +18 -0
- package/dist/guard.d.ts.map +1 -1
- package/dist/guard.js +56 -0
- package/dist/guard.js.map +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/primitives.d.ts +112 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +206 -0
- package/dist/primitives.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
import { emitDocLiteral, emitDocLiteralCompact } from "./literal.js";
|
|
2
|
+
import { emitStraightlineModule, } from "./straightline.js";
|
|
3
|
+
/** primitive クラスを保持する生成コード内変数(可変クラス名で静的呼び — namespace 非依存)。 */
|
|
4
|
+
const P = "$__P";
|
|
5
|
+
/**
|
|
6
|
+
* plan runtime クラス(`Plan::runPlan`)を保持する変数。runPlan は式演算子 primitive ではなく
|
|
7
|
+
* runtime top-level の実行 SSoT(TS oracle が top-level `runPlan` を import するのと同じ位置づけ)。
|
|
8
|
+
*/
|
|
9
|
+
const PLAN = "$__plan";
|
|
10
|
+
/** ref/refOpt/concat の native 化 helper(生成モジュール内クロージャ変数)。 */
|
|
11
|
+
const REF = "$__sl_ref";
|
|
12
|
+
const REF_OPT = "$__sl_ref_opt";
|
|
13
|
+
const CONCAT = "$__sl_concat";
|
|
14
|
+
/**
|
|
15
|
+
* scope 式(生成コード内)。scope は「input + それまでの ok 結果」のその時点のスナップで
|
|
16
|
+
* あり、runBehavior の baseScope() と同じく呼び時点の $results を読む(決定的)。
|
|
17
|
+
*/
|
|
18
|
+
const SCOPE = "$scope()";
|
|
19
|
+
/**
|
|
20
|
+
* map 本体(over/guard/ports)の要素 scope 式(生成コード内)。runBehavior の map と同じく
|
|
21
|
+
* `array_merge($scope(), [$as => $el])` を per-element で組む(生成コードは map arm 内で
|
|
22
|
+
* `$mscope` クロージャをローカル定義し、port/guard 式はそれを呼ぶ)。
|
|
23
|
+
*/
|
|
24
|
+
const MAP_SCOPE = "$mscope()";
|
|
25
|
+
/** IR リテラルを PHP 式として emit(primitive 被演算子・path 用の単一行リテラル)。 */
|
|
26
|
+
function lit(node) {
|
|
27
|
+
return emitDocLiteralCompact(node, "php");
|
|
28
|
+
}
|
|
29
|
+
/** args 配列を要素ごとに IR リテラルへ落として `, ` 連結(二項/単項 primitive 用)。 */
|
|
30
|
+
function argList(arg) {
|
|
31
|
+
return arg.map((a) => lit(a)).join(", ");
|
|
32
|
+
}
|
|
33
|
+
const OP_EMITTERS = {
|
|
34
|
+
// リテラルラッパ(int は文字列, float は number)— 範囲/有限性検査は primitive SSoT。
|
|
35
|
+
int: (arg, s) => `${P}::intLit(${lit(arg)}, ${s})`,
|
|
36
|
+
float: (arg, s) => `${P}::floatLit(${lit(arg)}, ${s})`,
|
|
37
|
+
// 構築(fields/elements は未評価 IR)
|
|
38
|
+
obj: (arg, s) => `${P}::obj(${lit(arg)}, ${s})`,
|
|
39
|
+
arr: (arg, s) => `${P}::arr(${lit(arg)}, ${s})`,
|
|
40
|
+
// 数値(二項は [a,b]・単項は [a])
|
|
41
|
+
add: (arg, s) => `${P}::add(${argList(arg)}, ${s})`,
|
|
42
|
+
sub: (arg, s) => `${P}::sub(${argList(arg)}, ${s})`,
|
|
43
|
+
mul: (arg, s) => `${P}::mul(${argList(arg)}, ${s})`,
|
|
44
|
+
neg: (arg, s) => `${P}::neg(${argList(arg)}, ${s})`,
|
|
45
|
+
div: (arg, s) => `${P}::div(${argList(arg)}, ${s})`,
|
|
46
|
+
mod: (arg, s) => `${P}::mod(${argList(arg)}, ${s})`,
|
|
47
|
+
// 比較(二項)
|
|
48
|
+
eq: (arg, s) => `${P}::eq(${argList(arg)}, ${s})`,
|
|
49
|
+
ne: (arg, s) => `${P}::ne(${argList(arg)}, ${s})`,
|
|
50
|
+
lt: (arg, s) => `${P}::lt(${argList(arg)}, ${s})`,
|
|
51
|
+
le: (arg, s) => `${P}::le(${argList(arg)}, ${s})`,
|
|
52
|
+
gt: (arg, s) => `${P}::gt(${argList(arg)}, ${s})`,
|
|
53
|
+
ge: (arg, s) => `${P}::ge(${argList(arg)}, ${s})`,
|
|
54
|
+
// bool/null(短絡: 被演算子は未評価 IR で渡す — primitive 内 evaluate が短絡)
|
|
55
|
+
and: (arg, s) => `${P}::and(${argList(arg)}, ${s})`,
|
|
56
|
+
or: (arg, s) => `${P}::or(${argList(arg)}, ${s})`,
|
|
57
|
+
not: (arg, s) => `${P}::not(${argList(arg)}, ${s})`,
|
|
58
|
+
coalesce: (arg, s) => `${P}::coalesce(${argList(arg)}, ${s})`,
|
|
59
|
+
cond: (arg, s) => {
|
|
60
|
+
const a = arg;
|
|
61
|
+
return `${P}::cond(${lit(a[0])}, ${lit(a[1])}, ${lit(a[2])}, ${s})`;
|
|
62
|
+
},
|
|
63
|
+
len: (arg, s) => `${P}::len(${argList(arg)}, ${s})`,
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* emitExpr — Expression IR ノードを PHP の評価式へ落とす(A2 = 脱解釈)。context-free。
|
|
67
|
+
*
|
|
68
|
+
* NATIVE-IZE(式ツリーの evaluate 解釈を単純式で消す — AC2):
|
|
69
|
+
* - `ref`/`refOpt` → native helper 呼び(`$__sl_ref(path, scope)`)。path は静的 array リテラル。
|
|
70
|
+
* `ExprEval::evaluate` を経由せず PHP array/stdClass アクセスで直接解決する。
|
|
71
|
+
* - `concat` → native helper 呼び(`$__sl_concat([<各 part を再帰 emit>], scope)`)。
|
|
72
|
+
* 各 part は再帰的に emitExpr するので、part 内の ref も native になる(純 concat(ref…) は
|
|
73
|
+
* evaluate/primitive を一切踏まない)。
|
|
74
|
+
* - string/bool/null のむき出しリテラル → PHP リテラル直書き(evaluate は scalar を素通しする
|
|
75
|
+
* だけなので値等価。ネイティブ化で primitive 呼びも消える)。
|
|
76
|
+
*
|
|
77
|
+
* ROUTE-TO-PRIMITIVE(fail-closed 意味論の SSoT を再実装しない):
|
|
78
|
+
* - overflow/短絡/比較/構築/リテラルラッパ演算子 → {@link OP_EMITTERS}(A0 primitive 直呼び)。
|
|
79
|
+
* - bare number(安全整数域・有限性の検査が要る)や未知の形 → `$__P::evalExpr`(同一 SSoT)。
|
|
80
|
+
*
|
|
81
|
+
* Portability Guard を通過済み(生成時検査)なので未知 operator はここに来ない。
|
|
82
|
+
*/
|
|
83
|
+
function emitExpr(node, scopeVar) {
|
|
84
|
+
// むき出しスカラ(string/bool/null)は PHP リテラル直書きで native 化(値等価・primitive 消去)。
|
|
85
|
+
if (node === null)
|
|
86
|
+
return "null";
|
|
87
|
+
if (typeof node === "boolean")
|
|
88
|
+
return node ? "true" : "false";
|
|
89
|
+
if (typeof node === "string")
|
|
90
|
+
return lit(node);
|
|
91
|
+
if (typeof node === "object" && !Array.isArray(node)) {
|
|
92
|
+
const keys = Object.keys(node);
|
|
93
|
+
if (keys.length === 1) {
|
|
94
|
+
const op = keys[0];
|
|
95
|
+
const arg = node[op];
|
|
96
|
+
// ── native 化する単純式(AC2)─────────────────────────────────────────
|
|
97
|
+
if (op === "ref")
|
|
98
|
+
return `${REF}(${lit(arg)}, ${scopeVar})`;
|
|
99
|
+
if (op === "refOpt")
|
|
100
|
+
return `${REF_OPT}(${lit(arg)}, ${scopeVar})`;
|
|
101
|
+
if (op === "concat") {
|
|
102
|
+
const parts = arg.map((p) => emitExpr(p, scopeVar));
|
|
103
|
+
return `${CONCAT}([${parts.join(", ")}], ${scopeVar})`;
|
|
104
|
+
}
|
|
105
|
+
// ── overflow/短絡/比較/構築 → A0 primitive SSoT(fail-closed 意味論)──────
|
|
106
|
+
const em = OP_EMITTERS[op];
|
|
107
|
+
if (em)
|
|
108
|
+
return em(arg, scopeVar);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// bare number(範囲/有限性検査)・その他 → evaluate SSoT(同一意味論)へ委譲。
|
|
112
|
+
return `${P}::evalExpr(${lit(node)}, ${scopeVar})`;
|
|
113
|
+
}
|
|
114
|
+
// ── per-node exec 分岐 / component クロージャ / module の綴じ方 ──────────────────
|
|
115
|
+
/** ops リテラル(runPlan に渡す OpSpec[] の PHP array リテラル)を綴じる。 */
|
|
116
|
+
function emitOpsLiteral(plan) {
|
|
117
|
+
const rows = plan.opsLiteral.map((o) => {
|
|
118
|
+
const parts = [`'id' => ${lit(o.id)}`, `'parent' => ${o.parent === null ? "null" : String(o.parent)}`];
|
|
119
|
+
if (o.bindField !== undefined)
|
|
120
|
+
parts.push(`'bindField' => ${lit(o.bindField)}`);
|
|
121
|
+
if (o.relationKind !== undefined)
|
|
122
|
+
parts.push(`'relationKind' => ${lit(o.relationKind)}`);
|
|
123
|
+
if (o.policy !== undefined)
|
|
124
|
+
parts.push(`'policy' => ${lit(o.policy)}`);
|
|
125
|
+
return ` [${parts.join(", ")}],`;
|
|
126
|
+
});
|
|
127
|
+
return `[\n${rows.join("\n")}\n ]`;
|
|
128
|
+
}
|
|
129
|
+
/** map arm の要素 ports リテラル(要素 scope `$mscope()` で評価)。 */
|
|
130
|
+
function emitMapPorts(op) {
|
|
131
|
+
if (op.ports.length === 0)
|
|
132
|
+
return "[]";
|
|
133
|
+
return `[\n${op.ports
|
|
134
|
+
.map((p) => ` ${lit(p.name)} => ${p.expr},`)
|
|
135
|
+
.join("\n")}\n ]`;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* emitMapArm — map ノードの直線展開(要素反復・guard skip・per-element/batched handler・into
|
|
139
|
+
* zip-attach)。Behavior.php の map 分岐を生成 PHP へ直線展開する。op-log 等価のため handler は
|
|
140
|
+
* runBehavior と同じ ctx(非 batched は bound 付き、batched は無し)・同じ ports 形で呼ぶ。guard は
|
|
141
|
+
* Primitives::cond(strict-bool SSoT)、into は inline zip-attach(MAP_INTO_ELEMENT_NOT_OBJECT
|
|
142
|
+
* fail-closed で runBehavior と Failure code 一致)。要素反復は宣言どおり逐次。
|
|
143
|
+
*/
|
|
144
|
+
function emitMapArm(op) {
|
|
145
|
+
const comp = lit(op.component);
|
|
146
|
+
const nodeId = lit(op.id);
|
|
147
|
+
const asKey = lit(op.as);
|
|
148
|
+
const guardCheck = op.guard === undefined ? "" : `\n if (${op.guard} !== true) { continue; }`;
|
|
149
|
+
const intoTail = op.into === undefined
|
|
150
|
+
? " return ['ok' => $collected];"
|
|
151
|
+
: ` $augmented = [];
|
|
152
|
+
$mk = 0;
|
|
153
|
+
foreach ($over as $mj => $oel) {
|
|
154
|
+
if ($mk < count($keptIdx) && $keptIdx[$mk] === $mj) {
|
|
155
|
+
if (!($oel instanceof \\stdClass)) {
|
|
156
|
+
$__bhFail::raise('MAP_INTO_ELEMENT_NOT_OBJECT', "map '${op.id}': 'into' requires object elements (element {$mj} is not an object)");
|
|
157
|
+
}
|
|
158
|
+
$aug = clone $oel;
|
|
159
|
+
$aug->{${lit(op.into)}} = $collected[$mk];
|
|
160
|
+
$augmented[] = $aug;
|
|
161
|
+
$mk++;
|
|
162
|
+
} else {
|
|
163
|
+
$augmented[] = $oel;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return ['ok' => $augmented];`;
|
|
167
|
+
const body = op.batched
|
|
168
|
+
? ` $items = [];
|
|
169
|
+
foreach ($over as $mi => $el) {
|
|
170
|
+
$mscope = static function () use ($scope, $el): array { return array_merge($scope(), [${asKey} => $el]); };
|
|
171
|
+
$mscope; // bound by port/guard exprs${guardCheck}
|
|
172
|
+
$items[] = ${emitMapPorts(op)};
|
|
173
|
+
$keptIdx[] = $mi;
|
|
174
|
+
}
|
|
175
|
+
if (count($items) === 0) {
|
|
176
|
+
$collected = [];
|
|
177
|
+
} else {
|
|
178
|
+
if (!isset($handlers[${comp}])) {
|
|
179
|
+
$__bhFail::raise('UNKNOWN_COMPONENT', "component '${op.component}' has no handler (fail-closed)");
|
|
180
|
+
}
|
|
181
|
+
$h = $handlers[${comp}];
|
|
182
|
+
$outcome = $h(['items' => $items], ['nodeId' => ${nodeId}, 'component' => ${comp}]);
|
|
183
|
+
if (array_key_exists('error', $outcome)) { return $outcome; }
|
|
184
|
+
$r = $outcome['ok'];
|
|
185
|
+
if (!is_array($r) || !array_is_list($r) || count($r) !== count($items)) {
|
|
186
|
+
$__bhFail::raise('MAP_BATCH_RESULT_MISMATCH', "map '${op.id}': batched handler must return a list aligned to items (want " . count($items) . ')');
|
|
187
|
+
}
|
|
188
|
+
$collected = $r;
|
|
189
|
+
}
|
|
190
|
+
${intoTail}`
|
|
191
|
+
: ` $collected = [];
|
|
192
|
+
if (!isset($handlers[${comp}])) {
|
|
193
|
+
$__bhFail::raise('UNKNOWN_COMPONENT', "component '${op.component}' has no handler (fail-closed)");
|
|
194
|
+
}
|
|
195
|
+
$h = $handlers[${comp}];
|
|
196
|
+
foreach ($over as $mi => $el) {
|
|
197
|
+
$mscope = static function () use ($scope, $el): array { return array_merge($scope(), [${asKey} => $el]); };
|
|
198
|
+
$mscope; // bound by port/guard exprs${guardCheck}
|
|
199
|
+
$ports = ${emitMapPorts(op)};
|
|
200
|
+
$outcome = $h($ports, ['nodeId' => ${nodeId}, 'component' => ${comp}, 'bound' => $el]);
|
|
201
|
+
if (array_key_exists('error', $outcome)) { return $outcome; }
|
|
202
|
+
$collected[] = $outcome['ok'];
|
|
203
|
+
$keptIdx[] = $mi;
|
|
204
|
+
}
|
|
205
|
+
${intoTail}`;
|
|
206
|
+
return ` if ($i === ${op.index}) {
|
|
207
|
+
$over = ${op.over};
|
|
208
|
+
if (!is_array($over)) {
|
|
209
|
+
$__bhFail::raise('MAP_OVER_NOT_ARRAY', "map '${op.id}': 'over' did not evaluate to an array");
|
|
210
|
+
}
|
|
211
|
+
$keptIdx = [];
|
|
212
|
+
${body}
|
|
213
|
+
}`;
|
|
214
|
+
}
|
|
215
|
+
/** 1ノードの exec 分岐本体(index で分岐 — nodeKind ディスパッチではない)。 */
|
|
216
|
+
function emitExecArm(op) {
|
|
217
|
+
if (op.kind === "cond") {
|
|
218
|
+
// cond は純 Expression。scope を渡して1式評価(handler は呼ばない)。
|
|
219
|
+
return ` if ($i === ${op.index}) return ['ok' => ${op.expr}];`;
|
|
220
|
+
}
|
|
221
|
+
if (op.kind === "map")
|
|
222
|
+
return emitMapArm(op);
|
|
223
|
+
// componentRef: 各 port を名前付き native/primitive 評価 → handler 注入呼び。
|
|
224
|
+
const portLines = op.ports.length === 0
|
|
225
|
+
? " $ports = [];"
|
|
226
|
+
: ` $ports = [\n${op.ports
|
|
227
|
+
.map((p) => ` ${lit(p.name)} => ${p.expr},`)
|
|
228
|
+
.join("\n")}\n ];`;
|
|
229
|
+
return ` if ($i === ${op.index}) {
|
|
230
|
+
${portLines}
|
|
231
|
+
if (!isset($handlers[${lit(op.component)}])) {
|
|
232
|
+
$__bhFail::raise('UNKNOWN_COMPONENT', "component '${op.component}' has no handler (fail-closed)");
|
|
233
|
+
}
|
|
234
|
+
$h = $handlers[${lit(op.component)}];
|
|
235
|
+
return $h($ports, ['nodeId' => ${lit(op.id)}, 'component' => ${lit(op.component)}]);
|
|
236
|
+
}`;
|
|
237
|
+
}
|
|
238
|
+
/** component 名をクロージャキーに使える形へ(決定的・名前一意は DUPLICATE_COMPONENT で保証)。 */
|
|
239
|
+
function sanitize(name) {
|
|
240
|
+
return name.replace(/[^A-Za-z0-9_]/g, "_");
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* emitPlanSpec — plan を `Plan::runPlan(?array $plan, …)` が受ける **PHP array**(stdClass ではない)
|
|
244
|
+
* として綴じる。Behavior.php の `$planSpec`(`['groups'=>…, 'concurrency'=>…]`)と鏡映。plan 不在は
|
|
245
|
+
* `null`(1 op = 1 stage の逐次 fallback)。groups は int の list of list(IR リテラルをそのまま)。
|
|
246
|
+
*/
|
|
247
|
+
function emitPlanSpec(plan) {
|
|
248
|
+
if (plan === null || plan === undefined)
|
|
249
|
+
return "null";
|
|
250
|
+
const p = plan;
|
|
251
|
+
const groups = p.groups === undefined ? "[]" : lit(p.groups);
|
|
252
|
+
const concurrency = typeof p.concurrency === "number" ? String(p.concurrency) : "1";
|
|
253
|
+
return `['groups' => ${groups}, 'concurrency' => ${concurrency}]`;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* emitComponentClosure — 1 component の直線クロージャを綴じる。runBehavior の実行フロー
|
|
257
|
+
* (results 蓄積 + baseScope + runPlan + writeUnproduced + output 評価)を **生成コードに直線
|
|
258
|
+
* 展開**する(汎用 exec/nodeKind/evalPorts は無い。各 exec 分岐は index で確定・ハードコード)。
|
|
259
|
+
* native helper($__sl_*)・primitive クラス名($__P)・failure クラス($__bhFail)を `use` で
|
|
260
|
+
* 捕捉し、handler 注入を受けて1回の実行を driving する。
|
|
261
|
+
*/
|
|
262
|
+
function emitComponentClosure(plan) {
|
|
263
|
+
const arms = plan.ops.map(emitExecArm).join("\n");
|
|
264
|
+
const planLiteral = emitPlanSpec(plan.component.plan);
|
|
265
|
+
const output = emitExpr(plan.component.output, SCOPE);
|
|
266
|
+
const relationKinds = plan.opsLiteral.map((o) => (o.relationKind === "connection" ? "'connection'" : "null"));
|
|
267
|
+
return ` ${lit(sanitize(plan.name))} => static function (array $handlers, array $input) use (${P}, ${PLAN}, ${REF}, ${REF_OPT}, ${CONCAT}, $__bhFail): mixed {
|
|
268
|
+
$ops = ${emitOpsLiteral(plan)};
|
|
269
|
+
$results = [];
|
|
270
|
+
$scope = static function () use ($input, &$results): array {
|
|
271
|
+
return array_merge($input, $results);
|
|
272
|
+
};
|
|
273
|
+
$relationKinds = [${relationKinds.join(", ")}];
|
|
274
|
+
$exec = static function (array $op, mixed $bound) use ($ops, $handlers, $scope, ${P}, ${REF}, ${REF_OPT}, ${CONCAT}, $__bhFail): array {
|
|
275
|
+
$i = null;
|
|
276
|
+
foreach ($ops as $k => $o) {
|
|
277
|
+
if ($o['id'] === $op['id']) { $i = $k; break; }
|
|
278
|
+
}
|
|
279
|
+
${arms}
|
|
280
|
+
$__bhFail::raise('UNKNOWN_NODE_KIND', "op '{$op['id']}' has no generated exec arm (fail-closed)");
|
|
281
|
+
};
|
|
282
|
+
$wrappedExec = static function (array $op, mixed $bound) use ($exec, &$results): array {
|
|
283
|
+
$outcome = $exec($op, $bound);
|
|
284
|
+
if (array_key_exists('ok', $outcome)) {
|
|
285
|
+
$results[$op['id']] = $outcome['ok'];
|
|
286
|
+
}
|
|
287
|
+
return $outcome;
|
|
288
|
+
};
|
|
289
|
+
$run = ${PLAN}::runPlan(${planLiteral}, $ops, $wrappedExec);
|
|
290
|
+
foreach ($run['states'] as $idx => $st) {
|
|
291
|
+
if ($st !== null && ($st['status'] ?? null) === 'skipped') {
|
|
292
|
+
$results[$ops[$idx]['id']] = ${P}::unproducedValue($relationKinds[$idx]);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return ${output};
|
|
296
|
+
}`;
|
|
297
|
+
}
|
|
298
|
+
function emitComponent(plan, _ctx) {
|
|
299
|
+
return emitComponentClosure(plan);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* native helper($__sl_ref/$__sl_ref_opt/$__sl_concat)の生成テキスト。
|
|
303
|
+
* `ExprEval::evalRef` / `ExprEval::evaluate(concat)` の意味論を native PHP で完全再現する
|
|
304
|
+
* (evaluate を経由しない = 脱解釈の実体)。Failure code は ExprEval と一致。
|
|
305
|
+
*/
|
|
306
|
+
function emitNativeHelpers() {
|
|
307
|
+
return `// ── native-ized simple-expression helpers (bc#41 A2 de-interpretation) ──────────────
|
|
308
|
+
// These resolve ref/refOpt/concat by DIRECT php array/stdClass access + '.' concat,
|
|
309
|
+
// WITHOUT the ExprEval interpreter tree-walk (the point of the straight-line path). Their
|
|
310
|
+
// semantics + Failure codes match the ExprEval ref/concat evaluation exactly.
|
|
311
|
+
${REF} = static function (array $path, array $scope) use ($__exprFail): mixed {
|
|
312
|
+
// == ExprEval::evalRef('ref', ...) の native 版(中間 null は NULL_REF)。
|
|
313
|
+
if (count($path) === 0) {
|
|
314
|
+
$__exprFail::raise('INVALID_NODE', 'ref expects a non-empty string path');
|
|
315
|
+
}
|
|
316
|
+
foreach ($path as $p) {
|
|
317
|
+
if (!is_string($p)) {
|
|
318
|
+
$__exprFail::raise('INVALID_NODE', 'ref expects a non-empty string path');
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
$head = $path[0];
|
|
322
|
+
if (!array_key_exists($head, $scope)) {
|
|
323
|
+
$__exprFail::raise('UNKNOWN_BINDING', "unknown binding: {$head}");
|
|
324
|
+
}
|
|
325
|
+
$cur = $scope[$head];
|
|
326
|
+
for ($k = 1; $k < count($path); $k++) {
|
|
327
|
+
$seg = $path[$k];
|
|
328
|
+
if ($cur === null) {
|
|
329
|
+
$__exprFail::raise('NULL_REF', "null intermediate at .{$seg}(?. を使う)");
|
|
330
|
+
}
|
|
331
|
+
if (!($cur instanceof \\stdClass)) {
|
|
332
|
+
$__exprFail::raise('TYPE_MISMATCH', "cannot access .{$seg} on " . gettype($cur));
|
|
333
|
+
}
|
|
334
|
+
$props = get_object_vars($cur);
|
|
335
|
+
if (!array_key_exists($seg, $props)) {
|
|
336
|
+
$__exprFail::raise('MISSING_PROP', "missing property .{$seg}");
|
|
337
|
+
}
|
|
338
|
+
$cur = $props[$seg];
|
|
339
|
+
}
|
|
340
|
+
return $cur;
|
|
341
|
+
};
|
|
342
|
+
${REF_OPT} = static function (array $path, array $scope) use ($__exprFail): mixed {
|
|
343
|
+
// == ExprEval::evalRef('refOpt', ...) の native 版(中間 null は null 伝播)。
|
|
344
|
+
if (count($path) === 0) {
|
|
345
|
+
$__exprFail::raise('INVALID_NODE', 'refOpt expects a non-empty string path');
|
|
346
|
+
}
|
|
347
|
+
foreach ($path as $p) {
|
|
348
|
+
if (!is_string($p)) {
|
|
349
|
+
$__exprFail::raise('INVALID_NODE', 'refOpt expects a non-empty string path');
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
$head = $path[0];
|
|
353
|
+
if (!array_key_exists($head, $scope)) {
|
|
354
|
+
$__exprFail::raise('UNKNOWN_BINDING', "unknown binding: {$head}");
|
|
355
|
+
}
|
|
356
|
+
$cur = $scope[$head];
|
|
357
|
+
for ($k = 1; $k < count($path); $k++) {
|
|
358
|
+
$seg = $path[$k];
|
|
359
|
+
if ($cur === null) {
|
|
360
|
+
return null; // ?. の null 伝播
|
|
361
|
+
}
|
|
362
|
+
if (!($cur instanceof \\stdClass)) {
|
|
363
|
+
$__exprFail::raise('TYPE_MISMATCH', "cannot access .{$seg} on " . gettype($cur));
|
|
364
|
+
}
|
|
365
|
+
$props = get_object_vars($cur);
|
|
366
|
+
if (!array_key_exists($seg, $props)) {
|
|
367
|
+
$__exprFail::raise('MISSING_PROP', "missing property .{$seg}");
|
|
368
|
+
}
|
|
369
|
+
$cur = $props[$seg];
|
|
370
|
+
}
|
|
371
|
+
return $cur;
|
|
372
|
+
};
|
|
373
|
+
${CONCAT} = static function (array $parts, array $scope) use ($__exprFail): string {
|
|
374
|
+
// == ExprEval concat の native 版(n-ary, min 2, string のみ, php '.' で結合)。
|
|
375
|
+
// parts は emitExpr で各 part を native 評価済みの値配列(part 内 ref も native)。
|
|
376
|
+
if (count($parts) < 2) {
|
|
377
|
+
$__exprFail::raise('INVALID_NODE', 'concat expects >= 2 args, got ' . count($parts));
|
|
378
|
+
}
|
|
379
|
+
$out = '';
|
|
380
|
+
foreach ($parts as $p) {
|
|
381
|
+
if (!is_string($p)) {
|
|
382
|
+
$__exprFail::raise('TYPE_MISMATCH', 'concat: string のみ(got ' . gettype($p) . ')');
|
|
383
|
+
}
|
|
384
|
+
$out .= $p;
|
|
385
|
+
}
|
|
386
|
+
return $out;
|
|
387
|
+
};`;
|
|
388
|
+
}
|
|
389
|
+
function emitModule(plans, ctx) {
|
|
390
|
+
const { fingerprint, specVersions, componentNames, runtimeImport } = ctx;
|
|
391
|
+
const names = componentNames.map((n) => lit(n)).join(", ");
|
|
392
|
+
const irLiteral = emitDocLiteral(ctx.ir, "php");
|
|
393
|
+
const closures = plans.map((p) => emitComponent(p, ctx)).join(",\n");
|
|
394
|
+
const dispatchArms = plans
|
|
395
|
+
.map((p) => ` if ($name === ${lit(p.name)}) return ($componentFns[${lit(sanitize(p.name))}])($handlers, $input);`)
|
|
396
|
+
.join("\n");
|
|
397
|
+
return `<?php
|
|
398
|
+
|
|
399
|
+
// GENERATED by behavior-contracts common generator (bc#41, straight-line) — DO NOT EDIT.
|
|
400
|
+
// Input: portable component-graph IR only (scp-ir-architecture.md §5/§7.4).
|
|
401
|
+
// This is the STRAIGHT-LINE codegen endpoint (typed-codegen.md §4.1 / bc#41 A2-php): each
|
|
402
|
+
// component is emitted as a native PHP closure that drives the plan via the runPlan
|
|
403
|
+
// primitive. Simple expressions are NATIVE-IZED (ref/refOpt via direct array/stdClass
|
|
404
|
+
// access, concat via php '.'), removing the ExprEval::evaluate tree-walk for them; only
|
|
405
|
+
// overflow/short-circuit ops route through the A0 Primitives SSoT (#36). It does NOT go
|
|
406
|
+
// through Behavior::runBehavior's tree-walk (no nodeKind dispatch / no evalPorts loop /
|
|
407
|
+
// no generic exec). Scope: componentRef + cond + simple Expression ports
|
|
408
|
+
// (map/batched/concurrency → A3, hydration → A4). Handlers are ALWAYS injected at the
|
|
409
|
+
// boundary; they are never generated.
|
|
410
|
+
// irFingerprint: ${fingerprint}
|
|
411
|
+
|
|
412
|
+
declare(strict_types=1);
|
|
413
|
+
|
|
414
|
+
// Spec versions baked at generation time (fail-closed constant comparison at require).
|
|
415
|
+
$expectedSpecVersions = ['behavior' => ${specVersions.behavior}, 'expression' => ${specVersions.expression}, 'plan' => ${specVersions.plan}];
|
|
416
|
+
|
|
417
|
+
// FNV-1a 64 fingerprint of the source portable IR (canonical-json discipline, #208).
|
|
418
|
+
$irFingerprint = ${lit(fingerprint)};
|
|
419
|
+
|
|
420
|
+
// Component names exposed by bind(), in IR declaration order.
|
|
421
|
+
$componentNames = [${names}];
|
|
422
|
+
|
|
423
|
+
// The portable component-graph IR, embedded as a native literal (for the require-time
|
|
424
|
+
// fingerprint self-check only — the straight-line closures do NOT walk it).
|
|
425
|
+
$ir = ${irLiteral};
|
|
426
|
+
|
|
427
|
+
// Require-time fail-closed checks (#208 prepared-artifact discipline).
|
|
428
|
+
$runtimeSpecVersions = [
|
|
429
|
+
'behavior' => \\${runtimeImport}\\SpecVersions::BEHAVIOR,
|
|
430
|
+
'expression' => \\${runtimeImport}\\SpecVersions::EXPRESSION,
|
|
431
|
+
'plan' => \\${runtimeImport}\\SpecVersions::PLAN,
|
|
432
|
+
];
|
|
433
|
+
foreach ($expectedSpecVersions as $specKey => $specWant) {
|
|
434
|
+
$specGot = $runtimeSpecVersions[$specKey] ?? null;
|
|
435
|
+
if ($specGot !== $specWant) {
|
|
436
|
+
throw new \\RuntimeException("behavior-contracts generated module: spec-version skew for '{$specKey}' (generated={$specWant}, runtime={$specGot}) — regenerate against this runtime (fail-closed)");
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
$gotFingerprint = \\${runtimeImport}\\Fingerprint::componentGraph($ir);
|
|
440
|
+
if ($gotFingerprint !== $irFingerprint) {
|
|
441
|
+
throw new \\RuntimeException("behavior-contracts generated module: IR fingerprint mismatch (baked={$irFingerprint}, embedded literal={$gotFingerprint}) — the generated code was modified or corrupted (fail-closed)");
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Bound symbols used by the straight-line closures (primitive class + failure classes as
|
|
445
|
+
// variable class-names, so the closures stay namespace-agnostic).
|
|
446
|
+
${P} = '\\${runtimeImport}\\Primitives';
|
|
447
|
+
${PLAN} = '\\${runtimeImport}\\Plan';
|
|
448
|
+
$__bhFail = '\\${runtimeImport}\\BehaviorFailure';
|
|
449
|
+
$__exprFail = '\\${runtimeImport}\\ExprFailure';
|
|
450
|
+
|
|
451
|
+
${emitNativeHelpers()}
|
|
452
|
+
|
|
453
|
+
// ── straight-line component closures (no runBehavior tree-walk) ─────────────────────
|
|
454
|
+
$componentFns = [
|
|
455
|
+
${closures},
|
|
456
|
+
];
|
|
457
|
+
|
|
458
|
+
// bind — inject handlers (boundary injection; catalog name → implementation) and get one
|
|
459
|
+
// executor closure per component. Each callable runs the straight-line closure for that
|
|
460
|
+
// component (plan via runPlan primitive + native/primitive port eval + injected handler)
|
|
461
|
+
// — NOT the runBehavior tree-walk. Observationally equivalent to the runBehavior path:
|
|
462
|
+
// same values, same emitted op sequence, same Failure code.
|
|
463
|
+
return (object) [
|
|
464
|
+
'EXPECTED_SPEC_VERSIONS' => $expectedSpecVersions,
|
|
465
|
+
'IR_FINGERPRINT' => $irFingerprint,
|
|
466
|
+
'COMPONENT_NAMES' => $componentNames,
|
|
467
|
+
'IR' => $ir,
|
|
468
|
+
'bind' => static function (array $handlers) use ($componentNames, $componentFns, $__bhFail): array {
|
|
469
|
+
$bound = [];
|
|
470
|
+
foreach ($componentNames as $name) {
|
|
471
|
+
$bound[$name] = static function (array $input = []) use ($name, $handlers, $componentFns, $__bhFail): mixed {
|
|
472
|
+
${dispatchArms}
|
|
473
|
+
$__bhFail::raise('UNKNOWN_ENTRY', "component '{$name}' not found in this module (fail-closed)");
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
return $bound;
|
|
477
|
+
},
|
|
478
|
+
];
|
|
479
|
+
`;
|
|
480
|
+
}
|
|
481
|
+
const dialect = {
|
|
482
|
+
emitExpr,
|
|
483
|
+
mapScopeVar: MAP_SCOPE,
|
|
484
|
+
emitComponent,
|
|
485
|
+
emitModule,
|
|
486
|
+
};
|
|
487
|
+
function emit(ctx) {
|
|
488
|
+
return emitStraightlineModule(ctx, dialect, SCOPE);
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* phpStraightlineEmitter — 言語識別子 `"php-straightline"` の emitter plugin。
|
|
492
|
+
* 既存の `php`(リテラル焼き込み・runBehavior 委譲)と併存する additive な第2モード。
|
|
493
|
+
*/
|
|
494
|
+
export const phpStraightlineEmitter = {
|
|
495
|
+
language: "php-straightline",
|
|
496
|
+
fileExtension: ".php",
|
|
497
|
+
defaultRuntimeImport: "BehaviorContracts",
|
|
498
|
+
filenameHint: "behaviors.straightline.generated.php",
|
|
499
|
+
emit,
|
|
500
|
+
};
|
|
501
|
+
//# sourceMappingURL=emit-straightline-php.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-straightline-php.js","sourceRoot":"","sources":["../../src/generator/emit-straightline-php.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* emit-straightline-python.ts — Python 直線 emitter(bc#40 / Layer A2)。
|
|
3
|
+
*
|
|
4
|
+
* typed-codegen.md §4.1 の Python 具体化。language-neutral な {@link StraightlineDialect} を実装し、
|
|
5
|
+
* component ごとに「plan を `run_plan` primitive で直呼び・各ノードの port 評価と handler 呼びを
|
|
6
|
+
* 直線展開した」ネイティブ **python** 関数を emit する。生成コードは `run_plan` +注入 handler +
|
|
7
|
+
* A0(#36)の式演算子 primitive(`behavior_contracts.primitives`)を直呼びし、**`run_behavior` の
|
|
8
|
+
* tree-walk(nodeKind ディスパッチ / eval_ports / 汎用 output 評価)を経由しない**。
|
|
9
|
+
*
|
|
10
|
+
* 脱解釈(AC#2 — python 版で最重要):
|
|
11
|
+
* TS emitter は「意味論 SSoT を再実装しない oracle」なので全式を primitive(内部 `evaluate`)へ
|
|
12
|
+
* 落とすが、**python では単純式を native 化して `evaluate` の解釈を消すのが本 issue の目的**である。
|
|
13
|
+
* よって {@link emitExpr} は次で分岐する:
|
|
14
|
+
* - `concat` → **native python 文字列結合**(module-local `_sl_concat` — str-only TYPE_MISMATCH
|
|
15
|
+
* と arity>=2 を native チェック。`evaluate` の再帰 dispatch を通さない)。
|
|
16
|
+
* - `ref` / `refOpt` → **native scope/field アクセス**(module-local `_sl_ref` / `_sl_ref_opt` —
|
|
17
|
+
* UNKNOWN_BINDING / NULL_REF / TYPE_MISMATCH / MISSING_PROP を native に静的展開)。
|
|
18
|
+
* - スカラリテラル(str/bool/None/int/float。int/float は portability guard 済みで安全域内)→
|
|
19
|
+
* **native python リテラル**。
|
|
20
|
+
* これらは `evaluate()` も A0 primitive(`cgp.*`)も呼ばない純 native コードで、Failure クラス
|
|
21
|
+
* (`ExprFailure`)だけを runtime から借りる(Failure code の SSoT は一本のまま)。
|
|
22
|
+
* overflow / 短絡 / fail-closed 意味論を持つ演算子(`add`/`sub`/`mul`/`div`/`mod`/`neg`/`and`/`or`/
|
|
23
|
+
* `not`/`coalesce`/`cond`/比較/`obj`/`arr`/`int`/`float`/`len`)は意味論 SSoT のため A0 primitive
|
|
24
|
+
* (被演算子は**未評価 IR リテラル**で渡す — 短絡は primitive 内 `evaluate` が保存)へ落とす。
|
|
25
|
+
* 単純式を primitive/`evaluate` へ丸投げしないことが構造的証明(grep)で pin される。
|
|
26
|
+
*
|
|
27
|
+
* go/rust/php は別 A2 issue で同じ {@link StraightlineDialect} 枠に乗る。
|
|
28
|
+
*/
|
|
29
|
+
import type { EmitterPlugin } from "./core.js";
|
|
30
|
+
/**
|
|
31
|
+
* pythonStraightlineEmitter — 言語識別子 `"python-straightline"` の emitter plugin。
|
|
32
|
+
* 既存の `python`(リテラル焼き込み・endpoint 3-literal → run_behavior)と併存する additive な
|
|
33
|
+
* 第2モード(単純式を native 化し `evaluate` 解釈を消す脱解釈経路 — typed-codegen.md §4.1)。
|
|
34
|
+
*/
|
|
35
|
+
export declare const pythonStraightlineEmitter: EmitterPlugin;
|
|
36
|
+
//# sourceMappingURL=emit-straightline-python.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-straightline-python.d.ts","sourceRoot":"","sources":["../../src/generator/emit-straightline-python.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,WAAW,CAAC;AA8b5D;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,aAMvC,CAAC"}
|