Files
hakorune/lang/src/shared/json/mir_v1_adapter.hako

120 lines
4.3 KiB
Plaintext
Raw Normal View History

// mir_v1_adapter.nyash — Minimal JSON v1 (mir_call) to v0 adapter for selfhost
// Scope: selfhost only. Transforms op:"mir_call" into legacy v0 ops (call/boxcall/newbox).
feat(stage-b): Add FLOW keyword support + fix Stage-3 keyword conflicts ## ✅ Fixed Issues ### 1. `local` keyword tokenization (commit 9aab64f7) - Added Stage-3 gate for LOCAL/TRY/CATCH/THROW keywords - LOCAL now only active when NYASH_PARSER_STAGE3=1 ### 2. `env.local.get` keyword conflict - File: `lang/src/compiler/entry/compiler_stageb.hako:21-23` - Problem: `.local` in member access tokenized as `.LOCAL` keyword - Fix: Commented out `env.local.get("HAKO_SOURCE")` line - Fallback: Use `--source` argument (still functional) ### 3. `flow` keyword missing - Added FLOW to TokenType enum (`src/tokenizer/kinds.rs`) - Added "flow" → TokenType::FLOW mapping (`src/tokenizer/lex_ident.rs`) - Added FLOW to Stage-3 gate (requires NYASH_PARSER_STAGE3=1) - Added FLOW to parser statement dispatch (`src/parser/statements/mod.rs`) - Added FLOW to declaration handler (`src/parser/statements/declarations.rs`) - Updated box_declaration parser to accept BOX or FLOW (`src/parser/declarations/box_definition.rs`) - Treat `flow FooBox {}` as syntactic sugar for `box FooBox {}` ### 4. Module namespace conversion - Renamed `lang.compiler.builder.ssa.local` → `localvar` (avoid keyword) - Renamed file `local.hako` → `local_ssa.hako` - Converted 152 path-based using statements to namespace format - Added 26+ entries to `nyash.toml` [modules] section ## ⚠️ Remaining Issues ### Stage-B selfhost compiler performance - Stage-B compiler not producing output (hangs/times out after 10+ seconds) - Excessive PHI debug output suggests compilation loop issue - Needs investigation: infinite loop or N² algorithm in hako compiler ### Fallback JSON version mismatch - Rust fallback (`--emit-mir-json`) emits MIR v1 JSON (schema_version: "1.0") - Smoke tests expect MIR v0 JSON (`"version":0, "kind":"Program"`) - stageb_helpers.sh fallback needs adjustment ## Test Status - Parse errors: FIXED ✅ - Keyword conflicts: FIXED ✅ - Stage-B smoke tests: STILL FAILING ❌ (performance issue) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 04:13:17 +09:00
using selfhost.shared.json.core.json_cursor as JsonCursorBox
static box MirJsonV1Adapter {
// Delegate to JsonCursorBox (escape-aware implementations, fixes 2 escape bugs)
_index_of_from(hay, needle, pos) {
return JsonCursorBox.index_of_from(hay, needle, pos)
}
_seek_obj_end(text, obj_start) {
return JsonCursorBox.seek_obj_end(text, obj_start)
}
_seek_array_end(text, pos_after_bracket) {
// JsonCursorBox.seek_array_end expects pos at '[', adjust since we receive pos after '['
if text == null { return -1 }
if pos_after_bracket <= 0 { return -1 }
local bracket_pos = pos_after_bracket - 1
return JsonCursorBox.seek_array_end(text, bracket_pos)
}
_read_digits(text, pos) {
return JsonCursorBox.digits_from(text, pos)
}
_read_string(text, pos_after_quote) {
local end = me._index_of_from(text, "\"", pos_after_quote)
if end < 0 { return "" }
return text.substring(pos_after_quote, end)
}
// Convert one mir_call object JSON segment to v0 legacy op JSON
_convert_mir_call(seg) {
// dst
local dpos = me._index_of_from(seg, "\"dst\":", 0)
local dst = 0
if dpos >= 0 {
local dd = me._read_digits(seg, dpos + 6)
if dd != "" { dst = 0 + ("" + dd).length() // placeholder to avoid lints
dst = 0 // reassign after parse
// parse int
local acc = 0
local i = 0
loop(i < dd.length()) { acc = acc * 10 + ("0123456789".indexOf(dd.substring(i,i+1))) i = i + 1 }
dst = acc
}
}
// args array substring (reuse existing as-is)
local ak = me._index_of_from(seg, "\"args\":[", 0)
local args_json = "[]"
if ak >= 0 {
local lb = me._index_of_from(seg, "[", ak)
if lb >= 0 {
local rb = me._seek_array_end(seg, lb + 1)
if rb > lb { args_json = seg.substring(lb, rb + 1) }
}
}
// callee type
local ck = me._index_of_from(seg, "\"callee\":{\"type\":\"", 0)
if ck < 0 { return seg }
local ct = me._read_string(seg, ck + 18)
if ct == "Global" {
local nk = me._index_of_from(seg, "\"name\":\"", ck)
local name = ""
if nk >= 0 { name = me._read_string(seg, nk + 8) }
return "{\"op\":\"call\",\"name\":\"" + name + "\",\"args\":" + args_json + ",\"dst\":" + dst + "}"
}
if ct == "Method" {
local mk = me._index_of_from(seg, "\"method\":\"", ck)
local method = ""
if mk >= 0 { method = me._read_string(seg, mk + 10) }
local rk = me._index_of_from(seg, "\"receiver\":", ck)
local recv = 0
if rk >= 0 {
local rd = me._read_digits(seg, rk + 11)
if rd != "" {
local acc2 = 0
local i2 = 0
loop(i2 < rd.length()) { acc2 = acc2 * 10 + ("0123456789".indexOf(rd.substring(i2,i2+1))) i2 = i2 + 1 }
recv = acc2
}
}
return "{\"op\":\"boxcall\",\"method\":\"" + method + "\",\"recv\":" + recv + ",\"args\":" + args_json + ",\"dst\":" + dst + "}"
}
if ct == "Constructor" {
local tk = me._index_of_from(seg, "\"box_type\":\"", ck)
local tname = ""
if tk >= 0 { tname = me._read_string(seg, tk + 12) }
return "{\"op\":\"newbox\",\"box_type\":\"" + tname + "\",\"args\":" + args_json + ",\"dst\":" + dst + "}"
}
// default: return original segment
return seg
}
// Public API: convert all mir_call objects within MIR(JSON v1) to v0 legacy ops
to_v0(mjson) {
if mjson == null { return null }
local out = mjson
local cur = 0
loop(true) {
local op = me._index_of_from(out, "\"op\":\"mir_call\"", cur)
if op < 0 { break }
// find object bounds
local start = op
loop(start >= 0) {
if out.substring(start, start+1) == "{" { break }
start = start - 1
}
if start < 0 { break }
local end = me._seek_obj_end(out, start)
if end <= start { break }
local seg = out.substring(start, end)
local rep = me._convert_mir_call(seg)
out = out.substring(0, start) + rep + out.substring(end, out.length())
cur = start + rep.length()
}
return out
}
}
static box MirJsonV1AdapterStub { main(args) { return 0 } }