// 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). using "lang/src/shared/json/json_cursor.hako" 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 } }