feat(phase21.5): selfhost CWD fix + loop executable semantics + diagnostics
## Task 1: Selfhost Child Process CWD Fix ✅ - Fix: try_selfhost_builder() now runs from repo root - Implementation: (cd "$ROOT" && ... "$NYASH_BIN" ...) - Benefit: nyash.toml using mappings are reliably loaded - Location: tools/hakorune_emit_mir.sh:96-108 - Resolves: "using not found: 'hako.mir.builder.internal.*'" errors ## Task 2: Loop JSONFrag Executable Semantics ✅ - Upgrade: FORCE=1 now generates complete executable while-loop - Structure: entry(0) → loop(1) → body(2) → exit(3) - Semantics: - PHI node: i = {i0, entry} | {i_next, body} - Increment: i_next = i + 1 - Backedge: body → loop - Exit: ret i (final loop variable value) - Location: lang/src/mir/builder/internal/loop_opts_adapter_box.hako:24-44 - Expected: rc=10 (limit value) instead of structure-only validation ## Task 3: Enhanced Diagnostics ✅ - Added: HAKO_SELFHOST_TRACE=1 outputs comprehensive diagnostics - Info: prog_json_len, tokens (Loop/Compare counts), cwd, nyash.toml status - Example: [builder/selfhost-first:trace] prog_json_len=90 tokens=Loop:0,Compare:0 cwd=... nyash.toml=present - Location: tools/hakorune_emit_mir.sh:87-100 - Benefit: One-line diagnosis of CWD/nyash.toml/using issues ## Task 4: nyash.toml Missing Entries ✅ - Added: hako.mir.builder.internal.builder_config mapping - Added: hako.mir.builder.internal.loop_opts_adapter mapping - Location: nyash.toml - Benefit: Selfhost-first can resolve internal builder dependencies ## Implementation Principles - 既定挙動不変 (Default unchanged, FORCE=1 guarded) - Dev toggle controlled (TRACE=1, NO_DELEGATE=1) - Minimal diff with clear rollback path - CWD fix ensures stable using resolution - Executable semantics enable proper EXE testing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -17,6 +17,41 @@ static box LoopOptsBox {
|
||||
using selfhost.shared.mir.loopform as LoopFormBox
|
||||
using selfhost.shared.common.string_helpers as StringHelpers
|
||||
using "hako.mir.builder.internal.jsonfrag_normalizer" as JsonFragNormalizerBox
|
||||
// Force toggle: always return JsonFrag (dev/test override)
|
||||
if BuilderConfigBox.loop_force_jsonfrag_on() == 1 {
|
||||
local limit = opts.get("limit"); if limit == null { limit = 0 }
|
||||
local limit_s = "" + limit
|
||||
// Minimal while-loop semantics (executable, not just structure):
|
||||
// Block 0 (entry): i0=0, limit=N, jump to loop
|
||||
// Block 1 (loop header): phi i={i0,0}|{i_next,2}, cmp i<limit, branch
|
||||
// Block 2 (body): i_next = i+1, jump back to loop
|
||||
// Block 3 (exit): ret i (final loop variable value)
|
||||
// Value IDs: r1=i0(0), r2=limit(N), r3=phi(i), r4=cmp, r5=i_next, r10=const(1)
|
||||
local mir = "{\"functions\":[{\"name\":\"main\",\"params\":[],\"locals\":[],\"blocks\":[" +
|
||||
"{\"id\":0,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"const\",\"dst\":2,\"value\":{\"type\":\"i64\",\"value\":" + limit_s + "}}," +
|
||||
"{\"op\":\"jump\",\"target\":1}]}," +
|
||||
"{\"id\":1,\"instructions\":[" +
|
||||
"{\"op\":\"phi\",\"dst\":3,\"incoming\":[[1,0],[5,2]]}," +
|
||||
"{\"op\":\"compare\",\"operation\":\"<\",\"lhs\":3,\"rhs\":2,\"dst\":4}," +
|
||||
"{\"op\":\"branch\",\"cond\":4,\"then\":2,\"else\":3}]}," +
|
||||
"{\"id\":2,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":10,\"value\":{\"type\":\"i64\",\"value\":1}}," +
|
||||
"{\"op\":\"binop\",\"operation\":\"+\",\"lhs\":3,\"rhs\":10,\"dst\":5}," +
|
||||
"{\"op\":\"jump\",\"target\":1}]}," +
|
||||
"{\"id\":3,\"instructions\":[" +
|
||||
"{\"op\":\"ret\",\"value\":3}]}]}]}"
|
||||
if BuilderConfigBox.trace_enabled() == 1 { print("[mirbuilder/loop_opts:force_jsonfrag:semantics:limit=" + limit_s + "]") }
|
||||
if BuilderConfigBox.jsonfrag_normalize_on() == 1 { mir = JsonFragNormalizerBox.normalize_all(mir) }
|
||||
local mode = BuilderConfigBox.loop_adapter_return_mode()
|
||||
if mode == "map" {
|
||||
local m = self.new_map()
|
||||
m = self.put(m, "mir", mir)
|
||||
return m
|
||||
}
|
||||
return mir
|
||||
}
|
||||
// Opt-in: minimal MIR(JSON) construction for structure validation
|
||||
if BuilderConfigBox.loop_jsonfrag_on() == 1 {
|
||||
// Read limit if present, else default to 0 (safe)
|
||||
|
||||
@ -225,6 +225,8 @@ path = "lang/src/shared/common/string_helpers.hako"
|
||||
"hako.mir.builder.internal.lower_typeop_cast" = "lang/src/mir/builder/internal/lower_typeop_cast_box.hako"
|
||||
"hako.mir.builder.internal.runner_min" = "lang/src/mir/builder/internal/runner_min_box.hako"
|
||||
"hako.mir.builder.internal.jsonfrag_normalizer" = "lang/src/mir/builder/internal/jsonfrag_normalizer_box.hako"
|
||||
"hako.mir.builder.internal.builder_config" = "lang/src/mir/builder/internal/builder_config_box.hako"
|
||||
"hako.mir.builder.internal.loop_opts_adapter" = "lang/src/mir/builder/internal/loop_opts_adapter_box.hako"
|
||||
|
||||
# Stage‑B support modules
|
||||
"hako.compiler.entry.bundle_resolver" = "lang/src/compiler/entry/bundle_resolver.hako"
|
||||
|
||||
@ -87,12 +87,21 @@ HCODE
|
||||
# Trace mode: analyze Program(JSON) before passing to builder
|
||||
if [ "${HAKO_SELFHOST_TRACE:-0}" = "1" ]; then
|
||||
local prog_len=${#prog_json}
|
||||
local loop_count=$(printf '%s' "$prog_json" | grep -o '"type":"Loop"' | wc -l || echo 0)
|
||||
local cmp_count=$(printf '%s' "$prog_json" | grep -o '"type":"Compare"' | wc -l || echo 0)
|
||||
echo "[builder/selfhost-first:trace] prog_json_len=$prog_len tokens=Loop:$loop_count,Compare:$cmp_count" >&2
|
||||
local loop_count=$(printf '%s' "$prog_json" | grep -o '"type":"Loop"' 2>/dev/null | wc -l | tr -d ' \n')
|
||||
local cmp_count=$(printf '%s' "$prog_json" | grep -o '"type":"Compare"' 2>/dev/null | wc -l | tr -d ' \n')
|
||||
loop_count=${loop_count:-0}
|
||||
cmp_count=${cmp_count:-0}
|
||||
local cwd="$(pwd)"
|
||||
local toml_status="absent"
|
||||
if [ -f "$ROOT/nyash.toml" ]; then
|
||||
toml_status="present"
|
||||
fi
|
||||
echo "[builder/selfhost-first:trace] prog_json_len=$prog_len tokens=Loop:$loop_count,Compare:$cmp_count cwd=$cwd nyash.toml=$toml_status" >&2
|
||||
fi
|
||||
|
||||
set +e
|
||||
# Run from repo root to ensure nyash.toml is available for using resolution
|
||||
(cd "$ROOT" && \
|
||||
HAKO_MIR_BUILDER_INTERNAL=1 HAKO_MIR_BUILDER_REGISTRY=1 \
|
||||
HAKO_MIR_BUILDER_LOOP_JSONFRAG="${HAKO_MIR_BUILDER_LOOP_JSONFRAG:-}" \
|
||||
HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG="${HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG:-}" \
|
||||
@ -103,7 +112,7 @@ HCODE
|
||||
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
||||
NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 NYASH_PARSER_ALLOW_SEMICOLON=1 \
|
||||
HAKO_BUILDER_PROGRAM_JSON="$prog_json" \
|
||||
"$NYASH_BIN" --backend vm "$tmp_hako" 2>/dev/null | tee "$tmp_stdout" >/dev/null
|
||||
"$NYASH_BIN" --backend vm "$tmp_hako" 2>/dev/null | tee "$tmp_stdout" >/dev/null)
|
||||
local rc=$?
|
||||
set -e
|
||||
|
||||
|
||||
Reference in New Issue
Block a user