Phase 22.1 WIP: SSOT resolver + TLV infrastructure + Hako MIR builder setup

Setup infrastructure for Phase 22.1 (TLV C shim & Resolver SSOT):

Core changes:
- Add nyash_tlv, nyash_c_core, nyash_kernel_min_c crates (opt-in)
- Implement SSOT resolver bridge (src/using/ssot_bridge.rs)
- Add HAKO_USING_SSOT=1 / HAKO_USING_SSOT_HAKO=1 env support
- Add HAKO_TLV_SHIM=1 infrastructure (requires --features tlv-shim)

MIR builder improvements:
- Fix using/alias consistency in Hako MIR builder
- Add hako.mir.builder.internal.{prog_scan,pattern_util} to nyash.toml
- Normalize LLVM extern calls: nyash.console.* → nyash_console_*

Smoke tests:
- Add phase2211 tests (using_ssot_hako_parity_canary_vm.sh)
- Add phase2220, phase2230, phase2231 test structure
- Add phase2100 S3 backend selector tests
- Improve test_runner.sh with quiet/timeout controls

Documentation:
- Add docs/ENV_VARS.md (Phase 22.1 env vars reference)
- Add docs/development/runtime/C_CORE_ABI.md
- Update de-rust-roadmap.md with Phase 22.x details

Tools:
- Add tools/hakorune_emit_mir.sh (Hako-first MIR emission wrapper)
- Add tools/tlv_roundtrip_smoke.sh placeholder
- Improve ny_mir_builder.sh with better backend selection

Known issues (to be fixed):
- Parser infinite loop in static method parameter parsing
- Stage-B output contamination with "RC: 0" (needs NYASH_JSON_ONLY=1)
- phase2211/using_ssot_hako_parity_canary_vm.sh fork bomb (needs recursion guard)

Next steps: Fix parser infinite loop + Stage-B quiet mode for green tests
This commit is contained in:
nyash-codex
2025-11-09 15:11:18 +09:00
parent 5d2cd5bad0
commit 981ddd890c
62 changed files with 1981 additions and 103 deletions

View File

@ -7,9 +7,12 @@
// - emit_from_program_json_v0(program_json: String, opts: Map|Null) -> String|Null
// Returns MIR(JSON v0) on success, or prints a tag and returns null on failure/skip.
//
// Toggles (delegate first):
// - HAKO_MIR_BUILDER_DELEGATE=1 — implementation delegated to Runner (--program-json-to-mir).
// In this initial stub, we only indicate delegation via a stable tag.
// Toggles
// - HAKO_MIR_BUILDER_DELEGATE=1 — delegate to Runner (--program-json-to-mir)
// - HAKO_MIR_BUILDER_INTERNAL=0/1 — internal lowers gate既定=1
// - HAKO_MIR_BUILDER_REGISTRY=0/1 — pattern registry gate既定=1
//
// Phase 22.0: Hakofirstregistryを既定ONにする。必要なら 0 を明示して無効化する。
static box MirBuilderBox {
// Availability probe (for canaries)
@ -32,16 +35,18 @@ static box MirBuilderBox {
print("[mirbuilder/input/invalid] missing version/kind keys")
return null
}
// Internal minimal path (guarded) — const(int)+ret, or const+const+binop+ret (Phase 20.34 B step)
// Toggle: HAKO_MIR_BUILDER_INTERNAL=1
// Internal path既定ON — const(int)+ret, binop+ret ほか、registry 優先の lowering
// Disable with: HAKO_MIR_BUILDER_INTERNAL=0
{
local internal = env.get("HAKO_MIR_BUILDER_INTERNAL")
if internal != null && ("" + internal) == "1" {
local internal_on = (internal == null) || (("" + internal) == "1")
if internal_on == 1 {
// Optional: registry-driven lowering (scaffold). When HAKO_MIR_BUILDER_REGISTRY=1,
// iterate PatternRegistryBox.candidates() and dispatch by name.
// NOTE: using/alias は prelude で解決される(位置に依存しない)。
local use_reg = env.get("HAKO_MIR_BUILDER_REGISTRY")
if use_reg != null && ("" + use_reg) == "1" {
local reg_on = (use_reg == null) || (("" + use_reg) == "1")
if reg_on == 1 {
// Registry list
using "hako.mir.builder.pattern_registry" as PatternRegistryBox
// Lowers needed by registry dispatchusing は prelude で集約される)
@ -55,7 +60,7 @@ static box MirBuilderBox {
using "hako.mir.builder.internal.lower_return_string" as LowerReturnStringBox
using "hako.mir.builder.internal.lower_return_float" as LowerReturnFloatBox
using "hako.mir.builder.internal.lower_return_bool" as LowerReturnBoolBox
using "hako.mir.builder.internal.lower_return_logical" as LowerReturnLogicalBox
using "hako.mir.builder.internal.lower.logical" as LowerReturnLogicalBox
using "hako.mir.builder.internal.lower_return_binop_varint" as LowerReturnBinOpVarIntBox
using "hako.mir.builder.internal.lower_return_binop_varvar" as LowerReturnBinOpVarVarBox
using "hako.mir.builder.internal.lower_return_binop" as LowerReturnBinOpBox
@ -86,11 +91,6 @@ static box MirBuilderBox {
// Boxified lowers via using+alias (prefer using over include; VM include unsupported)
using "hako.mir.builder.internal.lower_if_then_else_following_return" as LowerIfThenElseFollowingReturnBox
using "hako.mir.builder.internal.lower_if_nested" as LowerIfNestedBox
using "hako.mir.builder.internal.lower_if_compare" as LowerIfCompareBox
using "hako.mir.builder.internal.lower_if_compare_fold_binints" as LowerIfCompareFoldBinIntsBox
using "hako.mir.builder.internal.lower_if_compare_fold_varint" as LowerIfCompareFoldVarIntBox
using "hako.mir.builder.internal.lower_if_compare_varint" as LowerIfCompareVarIntBox
using "hako.mir.builder.internal.lower_if_compare_varvar" as LowerIfCompareVarVarBox
using "hako.mir.builder.internal.lower_loop_sum_bc" as LowerLoopSumBcBox
using "hako.mir.builder.internal.lower_newbox_constructor" as LowerNewboxConstructorBox
using "hako.mir.builder.internal.lower_method_array_size" as LowerMethodArraySizeBox
@ -103,16 +103,6 @@ static box MirBuilderBox {
using "hako.mir.builder.internal.lower_typeop_cast" as LowerTypeOpCastBox
using "hako.mir.builder.internal.lower_loop_count_param" as LowerLoopCountParamBox
using "hako.mir.builder.internal.lower_loop_simple" as LowerLoopSimpleBox
using "hako.mir.builder.internal.lower_return_var_local" as LowerReturnVarLocalBox
using "hako.mir.builder.internal.lower_return_string" as LowerReturnStringBox
using "hako.mir.builder.internal.lower_return_float" as LowerReturnFloatBox
using "hako.mir.builder.internal.lower_return_logical" as LowerReturnLogicalBox
using "hako.mir.builder.internal.lower_return_method_array_map" as LowerReturnMethodArrayMapBox
using "hako.mir.builder.internal.lower_return_bool" as LowerReturnBoolBox
using "hako.mir.builder.internal.lower_return_binop_varint" as LowerReturnBinOpVarIntBox
using "hako.mir.builder.internal.lower_return_binop_varvar" as LowerReturnBinOpVarVarBox
using "hako.mir.builder.internal.lower_return_binop" as LowerReturnBinOpBox
using "hako.mir.builder.internal.lower_return_int" as LowerReturnIntBox
// Prefer New(Constructor) minimal first to avoid unresolved nested lowers in inline runs
{ local out_newc = LowerNewboxConstructorBox.try_lower(s); if out_newc != null { return out_newc } }
{ local out_arr_size = LowerMethodArraySizeBox.try_lower(s); if out_arr_size != null { return out_arr_size } }

View File

@ -1,11 +1,10 @@
// lower_loop_count_param_box.hako — Loop(Compare i<limit) with Local i=init and i+=step → LoopForm.build("count", init, step)
using "hako.mir.builder.internal.prog_scan" as ProgScanBox
using ProgScanBox as Scan
using selfhost.shared.mir.loopform as LoopFormBox
using selfhost.shared.common.string_helpers as StringHelpers
using selfhost.shared.json.utils.json_frag as JsonFragBox
using selfhost.mir.builder.internal.pattern_util_box as PatternUtilBox
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
using "hako.mir.builder.internal.loop_scan" as LoopScanBox
static box LowerLoopCountParamBox {

View File

@ -3,10 +3,9 @@
using selfhost.shared.mir.loopform as LoopFormBox
using "hako.mir.builder.internal.prog_scan" as ProgScanBox
using ProgScanBox as Scan
using selfhost.shared.common.string_helpers as StringHelpers
using selfhost.shared.json.utils.json_frag as JsonFragBox
using selfhost.mir.builder.internal.pattern_util_box as PatternUtilBox
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
using "hako.mir.builder.internal.loop_scan" as LoopScanBox
static box LowerLoopSimpleBox {

View File

@ -0,0 +1,58 @@
// UsingResolveSSOTBox — SSOT for using/modules resolution (Phase 22.1)
// Contract (MVP):
// - Pure function. IOfilesystem access禁止。与えられた ctx のみを参照。
// - 優先順: modulesnyash.toml 明示) > relative 推定cwd → using_paths の順) > 見つからないnull
// - relative 推定は ctx.relative_hint=="1" が有効時のみ既定OFF挙動不変
// - 曖昧(複数候補)の最終判断は Runner 側。strict=1 時は legacy へ委譲する(本箱は null を返すのが安全)。
// Extension points:
// - ctx.modules: Map<String,String>(厳密一致)
// - ctx.using_paths: Array<String>(将来のヒント/本箱では純粋合成のみ)
// - ctx.cwd: String相対の基準
static box UsingResolveSSOTBox {
/// Resolve a module name to a file path string (or null when not found).
/// name: requested module name (e.g., "hako.mir.builder.internal.lower_return_int")
/// ctx : optional map for extra hints. Supported keys (all optional):
/// - modules: Map<String,String> (exact name → path)
/// - using_paths: Array<String> (search bases; no IO here, used only for future hints)
/// - cwd: String (caller context dir)
method resolve(name, ctx) {
if name == null { return null }
// Strictly pure: do not access filesystem here. Consume only provided hints.
// 1) modules mapping has priority
if ctx != null {
local m = ctx.get("modules");
if m != null {
local hit = m.get(name);
if hit != null { return hit }
}
// 2) Relative hint (optional): synthesize a likely path using using_paths/cwd
// Gate via ctx.relative_hint == "1" to avoid behavior changes unless explicitly enabled.
local rh = ctx.get("relative_hint");
if rh != null && rh == "1" {
local leaf = me._dot_to_slash(name) + ".hako";
// prefer cwd
local cwd = ctx.get("cwd");
if cwd != null {
return me._join_path(cwd, leaf)
}
local ups = ctx.get("using_paths");
if ups != null {
local i = 0; while i < ups.size() {
local base = ups.get(i);
return me._join_path(base, leaf)
i = i + 1 }
}
}
}
// No IO side effects in MVP
return null
}
_dot_to_slash(s) { return s.replace(".", "/") }
_join_path(base, leaf) {
if base == null { return leaf }
if base.endsWith("/") { return base + leaf }
return base + "/" + leaf
}
}