behavior-contracts 0.1.2 → 0.2.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.
- package/README.md +8 -2
- package/dist/authoring.d.ts +202 -0
- package/dist/authoring.d.ts.map +1 -0
- package/dist/authoring.js +787 -0
- package/dist/authoring.js.map +1 -0
- package/dist/behavior.d.ts +201 -0
- package/dist/behavior.d.ts.map +1 -0
- package/dist/behavior.js +373 -0
- package/dist/behavior.js.map +1 -0
- package/dist/builder.d.ts +154 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +574 -0
- package/dist/builder.js.map +1 -0
- package/dist/canonical.d.ts +1 -1
- package/dist/canonical.d.ts.map +1 -1
- package/dist/canonical.js +13 -1
- package/dist/canonical.js.map +1 -1
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +7 -1
- package/dist/codec.js.map +1 -1
- package/dist/expr-eval.d.ts +9 -1
- package/dist/expr-eval.d.ts.map +1 -1
- package/dist/expr-eval.js +21 -3
- package/dist/expr-eval.js.map +1 -1
- package/dist/generator/core.d.ts +89 -0
- package/dist/generator/core.d.ts.map +1 -0
- package/dist/generator/core.js +124 -0
- package/dist/generator/core.js.map +1 -0
- package/dist/generator/emit-go.d.ts +19 -0
- package/dist/generator/emit-go.d.ts.map +1 -0
- package/dist/generator/emit-go.js +79 -0
- package/dist/generator/emit-go.js.map +1 -0
- package/dist/generator/emit-php.d.ts +20 -0
- package/dist/generator/emit-php.d.ts.map +1 -0
- package/dist/generator/emit-php.js +76 -0
- package/dist/generator/emit-php.js.map +1 -0
- package/dist/generator/emit-python.d.ts +10 -0
- package/dist/generator/emit-python.d.ts.map +1 -0
- package/dist/generator/emit-python.js +75 -0
- package/dist/generator/emit-python.js.map +1 -0
- package/dist/generator/emit-rust.d.ts +25 -0
- package/dist/generator/emit-rust.d.ts.map +1 -0
- package/dist/generator/emit-rust.js +125 -0
- package/dist/generator/emit-rust.js.map +1 -0
- package/dist/generator/emit-typescript.d.ts +11 -0
- package/dist/generator/emit-typescript.d.ts.map +1 -0
- package/dist/generator/emit-typescript.js +68 -0
- package/dist/generator/emit-typescript.js.map +1 -0
- package/dist/generator/fingerprint.d.ts +14 -0
- package/dist/generator/fingerprint.d.ts.map +1 -0
- package/dist/generator/fingerprint.js +74 -0
- package/dist/generator/fingerprint.js.map +1 -0
- package/dist/generator/index.d.ts +9 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +25 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/literal.d.ts +8 -0
- package/dist/generator/literal.d.ts.map +1 -0
- package/dist/generator/literal.js +191 -0
- package/dist/generator/literal.js.map +1 -0
- package/dist/guard.d.ts +18 -0
- package/dist/guard.d.ts.map +1 -1
- package/dist/guard.js +130 -0
- package/dist/guard.js.map +1 -1
- package/dist/index.d.ts +17 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -5
- package/dist/index.js.map +1 -1
- package/dist/plan.d.ts +36 -0
- package/dist/plan.d.ts.map +1 -1
- package/dist/plan.js +152 -14
- package/dist/plan.js.map +1 -1
- package/package.json +6 -3
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { emitDocLiteral } from "./literal.js";
|
|
2
|
+
/** PHP 単一引用符リテラル(識別子・fingerprint 用 — ASCII 前提)。 */
|
|
3
|
+
function phpSq(s) {
|
|
4
|
+
return `'${s.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
5
|
+
}
|
|
6
|
+
function emit(ctx) {
|
|
7
|
+
const { fingerprint, specVersions, componentNames, runtimeImport } = ctx;
|
|
8
|
+
const names = componentNames.map(phpSq).join(", ");
|
|
9
|
+
const irLiteral = emitDocLiteral(ctx.ir, "php");
|
|
10
|
+
return `<?php
|
|
11
|
+
|
|
12
|
+
// GENERATED by behavior-contracts common generator (bc#13) — DO NOT EDIT.
|
|
13
|
+
// Input: portable component-graph IR only (scp-ir-architecture.md §5/§7.4).
|
|
14
|
+
// This module is the codegen endpoint (§7.3 endpoint 3): the IR is embedded as a
|
|
15
|
+
// native stdClass/array literal and handed to the EXISTING runtime core
|
|
16
|
+
// (Behavior::runBehavior) — no execution logic is generated. Handlers are ALWAYS
|
|
17
|
+
// injected at the boundary (IR + {effects,config,hooks} — concept.md §4.4); they
|
|
18
|
+
// are never generated.
|
|
19
|
+
// irFingerprint: ${fingerprint}
|
|
20
|
+
|
|
21
|
+
declare(strict_types=1);
|
|
22
|
+
|
|
23
|
+
// Spec versions baked at generation time (fail-closed constant comparison at require).
|
|
24
|
+
$expectedSpecVersions = ['behavior' => ${specVersions.behavior}, 'expression' => ${specVersions.expression}, 'plan' => ${specVersions.plan}];
|
|
25
|
+
|
|
26
|
+
// FNV-1a 64 fingerprint of the source portable IR (canonical-json discipline, #208).
|
|
27
|
+
$irFingerprint = ${phpSq(fingerprint)};
|
|
28
|
+
|
|
29
|
+
// Component names exposed by bind(), in IR declaration order.
|
|
30
|
+
$componentNames = [${names}];
|
|
31
|
+
|
|
32
|
+
// The portable component-graph IR, embedded as a native literal (no JSON parse at require).
|
|
33
|
+
$ir = ${irLiteral};
|
|
34
|
+
|
|
35
|
+
// Require-time fail-closed checks (#208 prepared-artifact discipline).
|
|
36
|
+
$runtimeSpecVersions = [
|
|
37
|
+
'behavior' => \\${runtimeImport}\\SpecVersions::BEHAVIOR,
|
|
38
|
+
'expression' => \\${runtimeImport}\\SpecVersions::EXPRESSION,
|
|
39
|
+
'plan' => \\${runtimeImport}\\SpecVersions::PLAN,
|
|
40
|
+
];
|
|
41
|
+
foreach ($expectedSpecVersions as $specKey => $specWant) {
|
|
42
|
+
$specGot = $runtimeSpecVersions[$specKey] ?? null;
|
|
43
|
+
if ($specGot !== $specWant) {
|
|
44
|
+
throw new \\RuntimeException("behavior-contracts generated module: spec-version skew for '{$specKey}' (generated={$specWant}, runtime={$specGot}) — regenerate against this runtime (fail-closed)");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
$gotFingerprint = \\${runtimeImport}\\Fingerprint::componentGraph($ir);
|
|
48
|
+
if ($gotFingerprint !== $irFingerprint) {
|
|
49
|
+
throw new \\RuntimeException("behavior-contracts generated module: IR fingerprint mismatch (baked={$irFingerprint}, embedded literal={$gotFingerprint}) — the generated code was modified or corrupted (fail-closed)");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// bind — inject handlers (boundary injection; catalog name → implementation) and
|
|
53
|
+
// get one executor closure per component. Each call delegates to the runtime
|
|
54
|
+
// core's Behavior::runBehavior over the embedded IR (dynamic-path equivalent — §7.3).
|
|
55
|
+
return (object) [
|
|
56
|
+
'EXPECTED_SPEC_VERSIONS' => $expectedSpecVersions,
|
|
57
|
+
'IR_FINGERPRINT' => $irFingerprint,
|
|
58
|
+
'COMPONENT_NAMES' => $componentNames,
|
|
59
|
+
'IR' => $ir,
|
|
60
|
+
'bind' => static function (array $handlers) use ($ir, $componentNames): array {
|
|
61
|
+
$bound = [];
|
|
62
|
+
foreach ($componentNames as $name) {
|
|
63
|
+
$bound[$name] = static fn (array $input = []): mixed => \\${runtimeImport}\\Behavior::runBehavior($ir, $handlers, $input, $name);
|
|
64
|
+
}
|
|
65
|
+
return $bound;
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
export const phpEmitter = {
|
|
71
|
+
language: "php",
|
|
72
|
+
fileExtension: ".php",
|
|
73
|
+
defaultRuntimeImport: "BehaviorContracts",
|
|
74
|
+
emit,
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=emit-php.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-php.js","sourceRoot":"","sources":["../../src/generator/emit-php.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,mDAAmD;AACnD,SAAS,KAAK,CAAC,CAAS;IACtB,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;AAC9D,CAAC;AAED,SAAS,IAAI,CAAC,GAAgB;IAC5B,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,GAAG,CAAC;IACzE,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAChD,OAAO;;;;;;;;;oBASW,WAAW;;;;;yCAKU,YAAY,CAAC,QAAQ,qBAAqB,YAAY,CAAC,UAAU,eAAe,YAAY,CAAC,IAAI;;;mBAGvH,KAAK,CAAC,WAAW,CAAC;;;qBAGhB,KAAK;;;QAGlB,SAAS;;;;sBAIK,aAAa;wBACX,aAAa;kBACnB,aAAa;;;;;;;;sBAQT,aAAa;;;;;;;;;;;;;;;;wEAgBqC,aAAa;;;;;CAKpF,CAAC;AACF,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAkB;IACvC,QAAQ,EAAE,KAAK;IACf,aAAa,EAAE,MAAM;IACrB,oBAAoB,EAAE,mBAAmB;IACzC,IAAI;CACL,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* emit-python.ts — Python emitter(共通 Generator, bc#13 SP1)。
|
|
3
|
+
*
|
|
4
|
+
* 生成物: 可搬 IR を **dict リテラル**として埋め込み、`behavior_contracts.run_behavior` に
|
|
5
|
+
* handler 注入で渡す薄い accessor(`bind`)を公開する .py モジュール。TS emitter と同形:
|
|
6
|
+
* spec-version / fingerprint 定数の焼き込み + ロード時 fail-closed 検査。
|
|
7
|
+
*/
|
|
8
|
+
import type { EmitterPlugin } from "./core.js";
|
|
9
|
+
export declare const pythonEmitter: EmitterPlugin;
|
|
10
|
+
//# sourceMappingURL=emit-python.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-python.d.ts","sourceRoot":"","sources":["../../src/generator/emit-python.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,WAAW,CAAC;AAwE5D,eAAO,MAAM,aAAa,EAAE,aAK3B,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { emitDocLiteral } from "./literal.js";
|
|
2
|
+
/** Python 文字列リテラル(JSON エスケープは Python でも合法)。 */
|
|
3
|
+
function pyStr(s) {
|
|
4
|
+
return JSON.stringify(s);
|
|
5
|
+
}
|
|
6
|
+
function emit(ctx) {
|
|
7
|
+
const { fingerprint, specVersions, componentNames, runtimeImport } = ctx;
|
|
8
|
+
const names = componentNames.map(pyStr).join(", ");
|
|
9
|
+
const namesTuple = componentNames.length === 1 ? `(${names},)` : `(${names})`;
|
|
10
|
+
const irLiteral = emitDocLiteral(ctx.ir, "py");
|
|
11
|
+
return `# GENERATED by behavior-contracts common generator (bc#13) — DO NOT EDIT.
|
|
12
|
+
# Input: portable component-graph IR only (scp-ir-architecture.md §5/§7.4).
|
|
13
|
+
# This module is the codegen endpoint (§7.3 endpoint 3): the IR is embedded as a
|
|
14
|
+
# native dict literal and handed to the EXISTING runtime core (run_behavior) —
|
|
15
|
+
# no execution logic is generated. Handlers are ALWAYS injected at the boundary
|
|
16
|
+
# (IR + {effects,config,hooks}); they are never generated.
|
|
17
|
+
# irFingerprint: ${fingerprint}
|
|
18
|
+
from ${runtimeImport} import SPEC_VERSIONS, fingerprint_component_graph, run_behavior
|
|
19
|
+
|
|
20
|
+
# Spec versions baked at generation time (fail-closed constant comparison at load).
|
|
21
|
+
EXPECTED_SPEC_VERSIONS = {"behavior": ${specVersions.behavior}, "expression": ${specVersions.expression}, "plan": ${specVersions.plan}}
|
|
22
|
+
|
|
23
|
+
# FNV-1a 64 fingerprint of the source portable IR (canonical_json discipline, #208).
|
|
24
|
+
IR_FINGERPRINT = ${pyStr(fingerprint)}
|
|
25
|
+
|
|
26
|
+
# Component names exposed by bind(), in IR declaration order.
|
|
27
|
+
COMPONENT_NAMES = ${namesTuple}
|
|
28
|
+
|
|
29
|
+
# The portable component-graph IR, embedded as a native dict literal (no JSON parse at runtime).
|
|
30
|
+
IR = ${irLiteral}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _check_generated_module() -> None:
|
|
34
|
+
# load-time fail-closed checks (#208 prepared-artifact discipline).
|
|
35
|
+
for _k, _want in EXPECTED_SPEC_VERSIONS.items():
|
|
36
|
+
_got = SPEC_VERSIONS.get(_k)
|
|
37
|
+
if _got != _want:
|
|
38
|
+
raise RuntimeError(
|
|
39
|
+
"behavior-contracts generated module: spec-version skew for '%s' "
|
|
40
|
+
"(generated=%s, runtime=%s) — regenerate against this runtime (fail-closed)"
|
|
41
|
+
% (_k, _want, _got)
|
|
42
|
+
)
|
|
43
|
+
_got_fp = fingerprint_component_graph(IR)
|
|
44
|
+
if _got_fp != IR_FINGERPRINT:
|
|
45
|
+
raise RuntimeError(
|
|
46
|
+
"behavior-contracts generated module: IR fingerprint mismatch "
|
|
47
|
+
"(baked=%s, embedded literal=%s) — the generated code was modified or corrupted (fail-closed)"
|
|
48
|
+
% (IR_FINGERPRINT, _got_fp)
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
_check_generated_module()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def bind(handlers):
|
|
56
|
+
"""Inject handlers (boundary injection; catalog name -> implementation) and get
|
|
57
|
+
one callable per component. Each call delegates to the runtime core's
|
|
58
|
+
run_behavior over the embedded IR (dynamic-path equivalent — §7.3)."""
|
|
59
|
+
|
|
60
|
+
def _make(name):
|
|
61
|
+
def _call(input=None):
|
|
62
|
+
return run_behavior(IR, handlers, dict(input or {}), name)
|
|
63
|
+
|
|
64
|
+
return _call
|
|
65
|
+
|
|
66
|
+
return {name: _make(name) for name in COMPONENT_NAMES}
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
export const pythonEmitter = {
|
|
70
|
+
language: "python",
|
|
71
|
+
fileExtension: ".py",
|
|
72
|
+
defaultRuntimeImport: "behavior_contracts",
|
|
73
|
+
emit,
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=emit-python.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-python.js","sourceRoot":"","sources":["../../src/generator/emit-python.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,+CAA+C;AAC/C,SAAS,KAAK,CAAC,CAAS;IACtB,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,IAAI,CAAC,GAAgB;IAC5B,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,GAAG,CAAC;IACzE,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC;IAC9E,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC/C,OAAO;;;;;;mBAMU,WAAW;OACvB,aAAa;;;wCAGoB,YAAY,CAAC,QAAQ,mBAAmB,YAAY,CAAC,UAAU,aAAa,YAAY,CAAC,IAAI;;;mBAGlH,KAAK,CAAC,WAAW,CAAC;;;oBAGjB,UAAU;;;OAGvB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCf,CAAC;AACF,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,QAAQ,EAAE,QAAQ;IAClB,aAAa,EAAE,KAAK;IACpB,oBAAoB,EAAE,oBAAoB;IAC1C,IAAI;CACL,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* emit-rust.ts — Rust emitter(共通 Generator, bc#13 SP2)。
|
|
3
|
+
*
|
|
4
|
+
* 生成物: 可搬 IR を **`serde_json::json!` マクロのネイティブ構築コード**として埋め込み
|
|
5
|
+
* (JSON テキストの実行時パースなし・構文はコンパイル時検査)、runtime-core の
|
|
6
|
+
* `run_behavior` に handler 注入で渡す accessor(`bind` → `Bound::call`)を公開する
|
|
7
|
+
* .rs モジュール。
|
|
8
|
+
*
|
|
9
|
+
* **「true const」からの正直な逸脱(SP1 audit の SP2 指針 (c))**:
|
|
10
|
+
* Rust runtime は IR を `serde_json::Value` で消費するが、`Value` は const 構築
|
|
11
|
+
* できない。そのため IR は `std::sync::LazyLock`(std, Rust >= 1.80)で**初回使用時に
|
|
12
|
+
* 一度だけ**ネイティブ構築される(以後は共有参照)。実行時 JSON パースは行わず、
|
|
13
|
+
* 構築コストは初回 1 回のみ。const-friendly な型付き IR 受け皿を runtime に足す案は
|
|
14
|
+
* runtime 再設計を伴うため将来 issue(本 SP のスコープ外)。
|
|
15
|
+
*
|
|
16
|
+
* ロード時検査は **first-use 時**: `IR` の LazyLock 初期化子の中で spec-version /
|
|
17
|
+
* fingerprint を検査し、skew は panic で LOUD reject(`bind()` が最初に force する)。
|
|
18
|
+
*
|
|
19
|
+
* 出力は rustfmt-clean(rustfmt は json! マクロ本体を触らないため、emitter の
|
|
20
|
+
* レイアウトが不動点になる)— fixture byte-drift ゲートと `cargo fmt --check` 系
|
|
21
|
+
* ゲートの両立のため。
|
|
22
|
+
*/
|
|
23
|
+
import type { EmitterPlugin } from "./core.js";
|
|
24
|
+
export declare const rustEmitter: EmitterPlugin;
|
|
25
|
+
//# sourceMappingURL=emit-rust.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-rust.d.ts","sourceRoot":"","sources":["../../src/generator/emit-rust.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,WAAW,CAAC;AAyH5D,eAAO,MAAM,WAAW,EAAE,aAMzB,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { emitDocLiteral } from "./literal.js";
|
|
2
|
+
function rustStrLit(s) {
|
|
3
|
+
// 識別子・fingerprint 用(ASCII 前提だが JSON エスケープで安全側に倒す)。
|
|
4
|
+
return JSON.stringify(s);
|
|
5
|
+
}
|
|
6
|
+
/** rustfmt の fits-on-one-line 規則を模倣した COMPONENT_NAMES 配列 emit。 */
|
|
7
|
+
function componentNamesConst(names) {
|
|
8
|
+
const items = names.map(rustStrLit);
|
|
9
|
+
const oneLine = `pub const COMPONENT_NAMES: [&str; ${names.length}] = [${items.join(", ")}];`;
|
|
10
|
+
if (oneLine.length <= 100)
|
|
11
|
+
return oneLine;
|
|
12
|
+
return `pub const COMPONENT_NAMES: [&str; ${names.length}] = [\n${items.map((s) => ` ${s},`).join("\n")}\n];`;
|
|
13
|
+
}
|
|
14
|
+
function emit(ctx) {
|
|
15
|
+
const { fingerprint, specVersions, componentNames, runtimeImport } = ctx;
|
|
16
|
+
const irLiteral = emitDocLiteral(ctx.ir, "rust", 1);
|
|
17
|
+
return `// GENERATED by behavior-contracts common generator (bc#13) — DO NOT EDIT.
|
|
18
|
+
// Input: portable component-graph IR only (scp-ir-architecture.md §5/§7.4).
|
|
19
|
+
// This module is the codegen endpoint (§7.3 endpoint 3): the IR is embedded as
|
|
20
|
+
// NATIVE json! constructor code (compile-time checked; no JSON-text parsing at
|
|
21
|
+
// runtime) and handed to the EXISTING runtime core (run_behavior) — no execution
|
|
22
|
+
// logic is generated. Handlers are ALWAYS injected at the boundary
|
|
23
|
+
// (IR + {effects,config,hooks} — concept.md §4.4); they are never generated.
|
|
24
|
+
//
|
|
25
|
+
// Const deviation (documented): serde_json::Value is not const-constructible, so
|
|
26
|
+
// the IR is built ONCE on first use behind std::sync::LazyLock (requires Rust
|
|
27
|
+
// >= 1.80). The first-use fail-closed checks (#208 prepared-artifact discipline)
|
|
28
|
+
// run inside the initializer: a spec-version skew or fingerprint mismatch panics
|
|
29
|
+
// LOUDLY before any behavior can run.
|
|
30
|
+
// irFingerprint: ${fingerprint}
|
|
31
|
+
|
|
32
|
+
use ${runtimeImport}::{
|
|
33
|
+
fingerprint_component_graph, run_behavior, BehaviorError, ComponentExec, SpecVersions, Value,
|
|
34
|
+
};
|
|
35
|
+
use serde_json::{json, Value as J};
|
|
36
|
+
use std::sync::LazyLock;
|
|
37
|
+
|
|
38
|
+
/// Spec versions baked at generation time (fail-closed comparison on first use).
|
|
39
|
+
pub const EXPECTED_SPEC_VERSIONS: [(&str, i64); 3] =
|
|
40
|
+
[("behavior", ${specVersions.behavior}), ("expression", ${specVersions.expression}), ("plan", ${specVersions.plan})];
|
|
41
|
+
|
|
42
|
+
/// FNV-1a 64 fingerprint of the source portable IR (canonical_json discipline, #208).
|
|
43
|
+
pub const IR_FINGERPRINT: &str = ${rustStrLit(fingerprint)};
|
|
44
|
+
|
|
45
|
+
/// Component names exposed by bind(), in IR declaration order.
|
|
46
|
+
${componentNamesConst(componentNames)}
|
|
47
|
+
|
|
48
|
+
/// The portable component-graph IR, built once on first use from native json!
|
|
49
|
+
/// constructor code (no JSON-text parsing at runtime; see the const-deviation
|
|
50
|
+
/// note in the module header).
|
|
51
|
+
pub static IR: LazyLock<J> = LazyLock::new(|| {
|
|
52
|
+
let ir = json!(${irLiteral});
|
|
53
|
+
check_generated_module(&ir);
|
|
54
|
+
ir
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
fn runtime_spec_version(key: &str) -> i64 {
|
|
58
|
+
match key {
|
|
59
|
+
"behavior" => SpecVersions::BEHAVIOR,
|
|
60
|
+
"expression" => SpecVersions::EXPRESSION,
|
|
61
|
+
"plan" => SpecVersions::PLAN,
|
|
62
|
+
other => {
|
|
63
|
+
panic!("behavior-contracts generated module: unknown spec key '{other}' (fail-closed)")
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// First-use fail-closed checks (#208 prepared-artifact discipline).
|
|
69
|
+
fn check_generated_module(ir: &J) {
|
|
70
|
+
for (key, want) in EXPECTED_SPEC_VERSIONS {
|
|
71
|
+
let got = runtime_spec_version(key);
|
|
72
|
+
if got != want {
|
|
73
|
+
panic!("behavior-contracts generated module: spec-version skew for '{key}' (generated={want}, runtime={got}) — regenerate against this runtime (fail-closed)");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
for name in COMPONENT_NAMES {
|
|
77
|
+
let found = ir["components"]
|
|
78
|
+
.as_array()
|
|
79
|
+
.is_some_and(|cs| cs.iter().any(|c| c["name"] == name));
|
|
80
|
+
if !found {
|
|
81
|
+
panic!("behavior-contracts generated module: component '{name}' missing from the embedded IR — the generated code was modified or corrupted (fail-closed)");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
let got_fp = fingerprint_component_graph(ir).unwrap_or_else(|e| {
|
|
85
|
+
panic!(
|
|
86
|
+
"behavior-contracts generated module: fingerprint recompute failed: {e} (fail-closed)"
|
|
87
|
+
)
|
|
88
|
+
});
|
|
89
|
+
if got_fp != IR_FINGERPRINT {
|
|
90
|
+
panic!("behavior-contracts generated module: IR fingerprint mismatch (baked={IR_FINGERPRINT}, embedded literal={got_fp}) — the generated code was modified or corrupted (fail-closed)");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/// Injected-handler accessor over the embedded IR (see [\`bind\`]). Rust ownership
|
|
95
|
+
/// makes a map of per-component closures sharing one \`&mut handlers\` impractical,
|
|
96
|
+
/// so the per-component executor surface is \`call(name, input)\` with the
|
|
97
|
+
/// component name checked against [\`COMPONENT_NAMES\`] by the runtime core.
|
|
98
|
+
pub struct Bound<H: ComponentExec> {
|
|
99
|
+
handlers: H,
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/// bind — inject handlers (boundary injection; catalog name → implementation)
|
|
103
|
+
/// and get an executor over the embedded IR. Each \`call\` delegates to the
|
|
104
|
+
/// runtime core's run_behavior (dynamic-path equivalent — §7.3). Forces the
|
|
105
|
+
/// first-use fail-closed checks.
|
|
106
|
+
pub fn bind<H: ComponentExec>(handlers: H) -> Bound<H> {
|
|
107
|
+
LazyLock::force(&IR);
|
|
108
|
+
Bound { handlers }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
impl<H: ComponentExec> Bound<H> {
|
|
112
|
+
pub fn call(&mut self, name: &str, input: &[(String, Value)]) -> Result<Value, BehaviorError> {
|
|
113
|
+
run_behavior(&IR, &mut self.handlers, input, Some(name))
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
export const rustEmitter = {
|
|
119
|
+
language: "rust",
|
|
120
|
+
fileExtension: ".rs",
|
|
121
|
+
defaultRuntimeImport: "behavior_contracts",
|
|
122
|
+
filenameHint: "behaviors_generated.rs",
|
|
123
|
+
emit,
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=emit-rust.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-rust.js","sourceRoot":"","sources":["../../src/generator/emit-rust.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,SAAS,UAAU,CAAC,CAAS;IAC3B,mDAAmD;IACnD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED,kEAAkE;AAClE,SAAS,mBAAmB,CAAC,KAAe;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,qCAAqC,KAAK,CAAC,MAAM,QAAQ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAC9F,IAAI,OAAO,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,OAAO,CAAC;IAC1C,OAAO,qCAAqC,KAAK,CAAC,MAAM,UAAU,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;AACnH,CAAC;AAED,SAAS,IAAI,CAAC,GAAgB;IAC5B,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,GAAG,CAAC;IACzE,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACpD,OAAO;;;;;;;;;;;;;oBAaW,WAAW;;MAEzB,aAAa;;;;;;;;oBAQC,YAAY,CAAC,QAAQ,qBAAqB,YAAY,CAAC,UAAU,eAAe,YAAY,CAAC,IAAI;;;mCAGlF,UAAU,CAAC,WAAW,CAAC;;;EAGxD,mBAAmB,CAAC,cAAc,CAAC;;;;;;qBAMhB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgE7B,CAAC;AACF,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAkB;IACxC,QAAQ,EAAE,MAAM;IAChB,aAAa,EAAE,KAAK;IACpB,oBAAoB,EAAE,oBAAoB;IAC1C,YAAY,EAAE,wBAAwB;IACtC,IAAI;CACL,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* emit-typescript.ts — TS emitter(共通 Generator, bc#13 SP1)。
|
|
3
|
+
*
|
|
4
|
+
* 生成物: 可搬 IR を **型付き const リテラル**(`ComponentGraphIR`)として埋め込み、
|
|
5
|
+
* runtime-core の `runBehavior` / `runBehaviorAsync` に handler 注入で渡す薄い accessor
|
|
6
|
+
* (`bind` / `bindAsync`)を公開する TS モジュール。実行ロジックは一切生成しない。
|
|
7
|
+
* 型付けにより runtime API / IR / generator のドリフトはコンパイルエラーになる(目的2)。
|
|
8
|
+
*/
|
|
9
|
+
import type { EmitterPlugin } from "./core.js";
|
|
10
|
+
export declare const typescriptEmitter: EmitterPlugin;
|
|
11
|
+
//# sourceMappingURL=emit-typescript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-typescript.d.ts","sourceRoot":"","sources":["../../src/generator/emit-typescript.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,WAAW,CAAC;AAgE5D,eAAO,MAAM,iBAAiB,EAAE,aAK/B,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { emitDocLiteral } from "./literal.js";
|
|
2
|
+
function emit(ctx) {
|
|
3
|
+
const { fingerprint, specVersions, componentNames, runtimeImport } = ctx;
|
|
4
|
+
const spec = runtimeImport;
|
|
5
|
+
const names = componentNames.map((n) => JSON.stringify(n)).join(", ");
|
|
6
|
+
const irLiteral = emitDocLiteral(ctx.ir, "ts");
|
|
7
|
+
return `// GENERATED by behavior-contracts common generator (bc#13) — DO NOT EDIT.
|
|
8
|
+
// Input: portable component-graph IR only (scp-ir-architecture.md §5/§7.4).
|
|
9
|
+
// This module is the codegen endpoint (§7.3 endpoint 3): the IR is embedded as a
|
|
10
|
+
// typed native literal and handed to the EXISTING runtime core (runBehavior) —
|
|
11
|
+
// no execution logic is generated. Handlers are ALWAYS injected at the boundary
|
|
12
|
+
// (IR + {effects,config,hooks} — concept.md §4.4); they are never generated.
|
|
13
|
+
// irFingerprint: ${fingerprint}
|
|
14
|
+
import { SPEC_VERSIONS, fingerprintComponentGraph, runBehavior, runBehaviorAsync } from ${JSON.stringify(spec)};
|
|
15
|
+
import type { AsyncHandlers, ComponentGraphIR, Handlers, Scope, Value } from ${JSON.stringify(spec)};
|
|
16
|
+
|
|
17
|
+
/** Spec versions baked at generation time (fail-closed constant comparison at load). */
|
|
18
|
+
export const EXPECTED_SPEC_VERSIONS = { behavior: ${specVersions.behavior}, expression: ${specVersions.expression}, plan: ${specVersions.plan} } as const;
|
|
19
|
+
|
|
20
|
+
/** FNV-1a 64 fingerprint of the source portable IR (canonicalJson discipline, #208). */
|
|
21
|
+
export const IR_FINGERPRINT = ${JSON.stringify(fingerprint)};
|
|
22
|
+
|
|
23
|
+
/** Component names exposed by bind()/bindAsync(), in IR declaration order. */
|
|
24
|
+
export const COMPONENT_NAMES: readonly string[] = [${names}];
|
|
25
|
+
|
|
26
|
+
/** The portable component-graph IR, embedded as a typed native literal (no JSON parse at runtime). */
|
|
27
|
+
export const IR: ComponentGraphIR = ${irLiteral};
|
|
28
|
+
|
|
29
|
+
// ── load-time fail-closed checks (#208 prepared-artifact discipline) ─────────
|
|
30
|
+
for (const [k, want] of Object.entries(EXPECTED_SPEC_VERSIONS)) {
|
|
31
|
+
const got = (SPEC_VERSIONS as Record<string, number>)[k];
|
|
32
|
+
if (got !== want)
|
|
33
|
+
throw new Error(
|
|
34
|
+
\`behavior-contracts generated module: spec-version skew for '\${k}' (generated=\${want}, runtime=\${got}) — regenerate against this runtime (fail-closed)\`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
if (fingerprintComponentGraph(IR) !== IR_FINGERPRINT)
|
|
38
|
+
throw new Error(
|
|
39
|
+
\`behavior-contracts generated module: IR fingerprint mismatch (baked=\${IR_FINGERPRINT}, embedded literal=\${fingerprintComponentGraph(IR)}) — the generated code was modified or corrupted (fail-closed)\`,
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* bind — inject handlers (boundary injection; catalog name → implementation) and
|
|
44
|
+
* get one callable per component. Each call delegates to the runtime core's
|
|
45
|
+
* runBehavior over the embedded IR (dynamic-path equivalent — §7.3).
|
|
46
|
+
*/
|
|
47
|
+
export function bind(handlers: Handlers): Record<string, (input?: Scope) => Value> {
|
|
48
|
+
const bound: Record<string, (input?: Scope) => Value> = {};
|
|
49
|
+
for (const name of COMPONENT_NAMES) bound[name] = (input: Scope = {}) => runBehavior(IR, handlers, input, name);
|
|
50
|
+
return bound;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** bindAsync — as bind, over runBehaviorAsync (bounded stage parallelism per plan.concurrency). */
|
|
54
|
+
export function bindAsync(handlers: AsyncHandlers): Record<string, (input?: Scope) => Promise<Value>> {
|
|
55
|
+
const bound: Record<string, (input?: Scope) => Promise<Value>> = {};
|
|
56
|
+
for (const name of COMPONENT_NAMES)
|
|
57
|
+
bound[name] = (input: Scope = {}) => runBehaviorAsync(IR, handlers, input, name);
|
|
58
|
+
return bound;
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
62
|
+
export const typescriptEmitter = {
|
|
63
|
+
language: "typescript",
|
|
64
|
+
fileExtension: ".ts",
|
|
65
|
+
defaultRuntimeImport: "behavior-contracts",
|
|
66
|
+
emit,
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=emit-typescript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-typescript.js","sourceRoot":"","sources":["../../src/generator/emit-typescript.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,SAAS,IAAI,CAAC,GAAgB;IAC5B,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,GAAG,CAAC;IACzE,MAAM,IAAI,GAAG,aAAa,CAAC;IAC3B,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC/C,OAAO;;;;;;oBAMW,WAAW;0FAC2D,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;+EAC/B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;;;oDAG/C,YAAY,CAAC,QAAQ,iBAAiB,YAAY,CAAC,UAAU,WAAW,YAAY,CAAC,IAAI;;;gCAG7G,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;;;qDAGN,KAAK;;;sCAGpB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiC9C,CAAC;AACF,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAkB;IAC9C,QAAQ,EAAE,YAAY;IACtB,aAAa,EAAE,KAAK;IACpB,oBAAoB,EAAE,oBAAoB;IAC1C,IAAI;CACL,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** fingerprint 入力の不変条件違反(fail-closed)。 */
|
|
2
|
+
export declare class FingerprintFailure extends Error {
|
|
3
|
+
code: "UNSAFE_NUMBER" | "INVALID_VALUE";
|
|
4
|
+
constructor(code: "UNSAFE_NUMBER" | "INVALID_VALUE", message: string);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* fingerprintComponentGraph — 可搬 IR ドキュメントの決定的 fingerprint。
|
|
8
|
+
*
|
|
9
|
+
* `"fnv1a64:<16hex>"` を返す。同一構造の IR(キー順・整数/整数値float の表記差を除く)は
|
|
10
|
+
* 言語(TS/Python)を跨いで同一の fingerprint になる。生成モジュールのロード時
|
|
11
|
+
* 自己検査・consumer 側の「live IR ↔ 生成コード」照合(#208 の prepared-loader と同型)に使う。
|
|
12
|
+
*/
|
|
13
|
+
export declare function fingerprintComponentGraph(doc: unknown): string;
|
|
14
|
+
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/generator/fingerprint.ts"],"names":[],"mappings":"AAuBA,0CAA0C;AAC1C,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,IAAI,EAAE,eAAe,GAAG,eAAe,CAAC;gBAC5B,IAAI,EAAE,eAAe,GAAG,eAAe,EAAE,OAAO,EAAE,MAAM;CAKrE;AA8DD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAG9D"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { canonicalJson } from "../canonical.js";
|
|
2
|
+
/** fingerprint 入力の不変条件違反(fail-closed)。 */
|
|
3
|
+
export class FingerprintFailure extends Error {
|
|
4
|
+
code;
|
|
5
|
+
constructor(code, message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.name = "FingerprintFailure";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* JSON ドキュメント → Value ドメイン(整数値 number は int=bigint へ正準化)。
|
|
13
|
+
* canonicalJson の値モデル(bigint=int / number=float)に合わせる。
|
|
14
|
+
*/
|
|
15
|
+
function toValueDomain(doc, path) {
|
|
16
|
+
if (doc === null || typeof doc === "boolean" || typeof doc === "string")
|
|
17
|
+
return doc;
|
|
18
|
+
if (typeof doc === "number") {
|
|
19
|
+
if (Number.isInteger(doc) && !Object.is(doc, -0)) {
|
|
20
|
+
if (Math.abs(doc) >= 2 ** 53)
|
|
21
|
+
throw new FingerprintFailure("UNSAFE_NUMBER", `integral number ${doc} at ${path} exceeds float64-exact range; portable IR must use {int:"..."} (fail-closed)`);
|
|
22
|
+
return BigInt(doc);
|
|
23
|
+
}
|
|
24
|
+
return doc; // 非整数 / -0.0 は float(canonicalJson が pyFloatRepr で直列化)
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(doc))
|
|
27
|
+
return doc.map((v, i) => toValueDomain(v, `${path}[${i}]`));
|
|
28
|
+
if (typeof doc === "object") {
|
|
29
|
+
const out = {};
|
|
30
|
+
for (const [k, v] of Object.entries(doc))
|
|
31
|
+
out[k] = toValueDomain(v, `${path}.${k}`);
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
throw new FingerprintFailure("INVALID_VALUE", `value of type ${typeof doc} at ${path} cannot appear in a portable IR document (fail-closed)`);
|
|
35
|
+
}
|
|
36
|
+
/** UTF-8 エンコード(依存ゼロ・決定的。lib 制約により TextEncoder を使わない)。 */
|
|
37
|
+
function utf8Bytes(s) {
|
|
38
|
+
const out = [];
|
|
39
|
+
for (const ch of s) {
|
|
40
|
+
const cp = ch.codePointAt(0);
|
|
41
|
+
if (cp <= 0x7f)
|
|
42
|
+
out.push(cp);
|
|
43
|
+
else if (cp <= 0x7ff)
|
|
44
|
+
out.push(0xc0 | (cp >> 6), 0x80 | (cp & 0x3f));
|
|
45
|
+
else if (cp <= 0xffff)
|
|
46
|
+
out.push(0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));
|
|
47
|
+
else
|
|
48
|
+
out.push(0xf0 | (cp >> 18), 0x80 | ((cp >> 12) & 0x3f), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
/** FNV-1a 64(offset 0xcbf29ce484222325, prime 0x100000001b3)→ 16桁小文字 hex。 */
|
|
53
|
+
function fnv1a64(bytes) {
|
|
54
|
+
let h = 0xcbf29ce484222325n;
|
|
55
|
+
const prime = 0x100000001b3n;
|
|
56
|
+
const mask = 0xffffffffffffffffn;
|
|
57
|
+
for (const b of bytes) {
|
|
58
|
+
h ^= BigInt(b);
|
|
59
|
+
h = (h * prime) & mask;
|
|
60
|
+
}
|
|
61
|
+
return h.toString(16).padStart(16, "0");
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* fingerprintComponentGraph — 可搬 IR ドキュメントの決定的 fingerprint。
|
|
65
|
+
*
|
|
66
|
+
* `"fnv1a64:<16hex>"` を返す。同一構造の IR(キー順・整数/整数値float の表記差を除く)は
|
|
67
|
+
* 言語(TS/Python)を跨いで同一の fingerprint になる。生成モジュールのロード時
|
|
68
|
+
* 自己検査・consumer 側の「live IR ↔ 生成コード」照合(#208 の prepared-loader と同型)に使う。
|
|
69
|
+
*/
|
|
70
|
+
export function fingerprintComponentGraph(doc) {
|
|
71
|
+
const s = canonicalJson(toValueDomain(doc, "$"));
|
|
72
|
+
return "fnv1a64:" + fnv1a64(utf8Bytes(s));
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/generator/fingerprint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { generateModule, registerEmitter, registeredLanguages, GeneratorFailure, } from "./core.js";
|
|
2
|
+
export type { GenerateOptions, GeneratedModule, EmitContext, EmitterPlugin, GeneratorFailureCode, } from "./core.js";
|
|
3
|
+
export { fingerprintComponentGraph, FingerprintFailure } from "./fingerprint.js";
|
|
4
|
+
export { typescriptEmitter } from "./emit-typescript.js";
|
|
5
|
+
export { pythonEmitter } from "./emit-python.js";
|
|
6
|
+
export { goEmitter } from "./emit-go.js";
|
|
7
|
+
export { rustEmitter } from "./emit-rust.js";
|
|
8
|
+
export { phpEmitter } from "./emit-php.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,eAAe,EACf,eAAe,EACf,WAAW,EACX,aAAa,EACb,oBAAoB,GACrB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generator/index.ts — 共通 Generator の公開面(bc#13 SP1 + SP2)。
|
|
3
|
+
*
|
|
4
|
+
* 組み込み emitter(typescript / python / go / rust / php)を登録して公開する。
|
|
5
|
+
* 追加言語は emitter plugin を登録するだけでよい(core は言語中立)。
|
|
6
|
+
*/
|
|
7
|
+
import { registerEmitter } from "./core.js";
|
|
8
|
+
import { typescriptEmitter } from "./emit-typescript.js";
|
|
9
|
+
import { pythonEmitter } from "./emit-python.js";
|
|
10
|
+
import { goEmitter } from "./emit-go.js";
|
|
11
|
+
import { rustEmitter } from "./emit-rust.js";
|
|
12
|
+
import { phpEmitter } from "./emit-php.js";
|
|
13
|
+
registerEmitter(typescriptEmitter);
|
|
14
|
+
registerEmitter(pythonEmitter);
|
|
15
|
+
registerEmitter(goEmitter);
|
|
16
|
+
registerEmitter(rustEmitter);
|
|
17
|
+
registerEmitter(phpEmitter);
|
|
18
|
+
export { generateModule, registerEmitter, registeredLanguages, GeneratorFailure, } from "./core.js";
|
|
19
|
+
export { fingerprintComponentGraph, FingerprintFailure } from "./fingerprint.js";
|
|
20
|
+
export { typescriptEmitter } from "./emit-typescript.js";
|
|
21
|
+
export { pythonEmitter } from "./emit-python.js";
|
|
22
|
+
export { goEmitter } from "./emit-go.js";
|
|
23
|
+
export { rustEmitter } from "./emit-rust.js";
|
|
24
|
+
export { phpEmitter } from "./emit-php.js";
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,eAAe,CAAC,iBAAiB,CAAC,CAAC;AACnC,eAAe,CAAC,aAAa,CAAC,CAAC;AAC/B,eAAe,CAAC,SAAS,CAAC,CAAC;AAC3B,eAAe,CAAC,WAAW,CAAC,CAAC;AAC7B,eAAe,CAAC,UAAU,CAAC,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,WAAW,CAAC;AAQnB,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type LiteralStyle = "ts" | "py" | "go" | "rust" | "php";
|
|
2
|
+
/**
|
|
3
|
+
* emitDocLiteral — ドキュメントを言語ネイティブのリテラル式として emit する。
|
|
4
|
+
* インデント 1 段 = dialect の indentUnit(ts/py 2 space・go tab・rust/php 4 space)・
|
|
5
|
+
* 複数行(JSON.stringify(v, null, indent) と同じレイアウト規則)。
|
|
6
|
+
*/
|
|
7
|
+
export declare function emitDocLiteral(doc: unknown, style: LiteralStyle, indent?: number, path?: string): string;
|
|
8
|
+
//# sourceMappingURL=literal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"literal.d.ts","sourceRoot":"","sources":["../../src/generator/literal.ts"],"names":[],"mappings":"AA6BA,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC;AAoJ/D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,SAAI,EAAE,IAAI,SAAM,GAAG,MAAM,CA0BhG"}
|