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:
@ -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: Hako‑first(registry)を既定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 dispatch(using は 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 } }
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
58
lang/src/using/resolve_ssot_box.hako
Normal file
58
lang/src/using/resolve_ssot_box.hako
Normal file
@ -0,0 +1,58 @@
|
||||
// UsingResolveSSOTBox — SSOT for using/modules resolution (Phase 22.1)
|
||||
// Contract (MVP):
|
||||
// - Pure function. IO(filesystem access)禁止。与えられた ctx のみを参照。
|
||||
// - 優先順: modules(nyash.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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user