Phase 22.x WIP: LLVM backend improvements + MIR builder enhancements

LLVM backend improvements:
- Add native LLVM backend support (NYASH_LLVM_BACKEND=native)
- Add crate backend selector with priority (crate > llvmlite)
- Add native_llvm_builder.py for native IR generation
- Add NYASH_LLVM_NATIVE_TRACE=1 for IR dump

MIR builder enhancements:
- Refactor lower_if_compare_* boxes for better code generation
- Refactor lower_return_* boxes for optimized returns
- Refactor lower_loop_* boxes for loop handling
- Refactor lower_method_* boxes for method calls
- Update pattern_util_box for better pattern matching

Smoke tests:
- Add phase2100 S3 backend selector tests (17 new tests)
- Add phase2120 native backend tests (4 new tests)
- Add phase2034 MIR builder internal tests (2 new tests)
- Add phase2211 TLV shim parity test

Documentation:
- Update ENV_VARS.md with LLVM backend variables
- Update CURRENT_TASK.md with progress
- Update README.md and CHANGELOG.md

Config:
- Add NYASH_LLVM_BACKEND env support in src/config/env.rs
- Update ny_mir_builder.sh for backend selection
- Update dispatch.rs for backend routing

Tools:
- Add tools/native_llvm_builder.py
- Update smokes/v2/profiles/quick/core/phase2100/run_all.sh

Known: Many Hako builder internal files modified for optimization
This commit is contained in:
nyash-codex
2025-11-09 23:40:36 +09:00
parent fb6129183d
commit f6c5dc9e43
65 changed files with 1965 additions and 434 deletions

View File

@ -5,51 +5,51 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
static box LowerIfCompareBox {
try_lower(program_json) {
local s = "" + program_json
local k_if = s.indexOf("\"type\":\"If\"")
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0)
if k_if < 0 { return null }
// cond Compare
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if)
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if)
if k_cmp < 0 { return null }
local k_op = s.indexOf("\"op\":", k_cmp)
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp)
if k_op < 0 { return null }
local op = JsonFragBox.read_string_after(s, k_op + 5)
if op == null { return null }
if !(op == "<" || op == ">" || op == "<=" || op == ">=" || op == "==" || op == "!=") { return null }
// lhs/rhs ints
local klhs = s.indexOf("\"lhs\":{", k_cmp)
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp)
if klhs < 0 { return null }
local ti = s.indexOf("\"type\":\"Int\"", klhs)
local ti = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs)
if ti < 0 { return null }
local kv_lhs = s.indexOf("\"value\":", ti)
local kv_lhs = JsonFragBox.index_of_from(s, "\"value\":", ti)
if kv_lhs < 0 { return null }
local lhs_val = JsonFragBox.read_int_after(s, kv_lhs + 8)
if lhs_val == null { return null }
local krhs = s.indexOf("\"rhs\":{", k_cmp)
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp)
if krhs < 0 { return null }
local ti2 = s.indexOf("\"type\":\"Int\"", krhs)
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs)
if ti2 < 0 { return null }
local kv_rhs = s.indexOf("\"value\":", ti2)
local kv_rhs = JsonFragBox.index_of_from(s, "\"value\":", ti2)
if kv_rhs < 0 { return null }
local rhs_val = JsonFragBox.read_int_after(s, kv_rhs + 8)
if rhs_val == null { return null }
// then/else return ints
local kth = s.indexOf("\"then\":", k_if)
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if)
if kth < 0 { return null }
local rt = s.indexOf("\"type\":\"Return\"", kth)
local rt = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth)
if rt < 0 { return null }
local ti3 = s.indexOf("\"type\":\"Int\"", rt)
local ti3 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt)
if ti3 < 0 { return null }
local kv_then = s.indexOf("\"value\":", ti3)
local kv_then = JsonFragBox.index_of_from(s, "\"value\":", ti3)
if kv_then < 0 { return null }
local then_val = JsonFragBox.read_int_after(s, kv_then + 8)
if then_val == null { return null }
local kel = s.indexOf("\"else\":", k_if)
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if)
if kel < 0 { return null }
local rt2 = s.indexOf("\"type\":\"Return\"", kel)
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel)
if rt2 < 0 { return null }
local ti4 = s.indexOf("\"type\":\"Int\"", rt2)
local ti4 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2)
if ti4 < 0 { return null }
local kv_else = s.indexOf("\"value\":", ti4)
local kv_else = JsonFragBox.index_of_from(s, "\"value\":", ti4)
if kv_else < 0 { return null }
local else_val = JsonFragBox.read_int_after(s, kv_else + 8)
if else_val == null { return null }

View File

@ -7,15 +7,15 @@ using selfhost.shared.mir.schema as MirSchemaBox
static box LowerIfCompareFoldBinIntsBox {
_fold_bin_ints(s, k_bin_start) {
// expects: {"type":"Binary","op":"+|-|*|/","lhs":{"type":"Int","value":L},"rhs":{"type":"Int","value":R}}
local kop = s.indexOf("\"op\":\"", k_bin_start); if kop < 0 { return null }
local kop = JsonFragBox.index_of_from(s, "\"op\":\"", k_bin_start); if kop < 0 { return null }
local iop = kop + 6; local op = s.substring(iop, iop+1)
if !(op == "+" || op == "-" || op == "*" || op == "/") { return null }
local kli = s.indexOf("\"type\":\"Int\"", k_bin_start); if kli < 0 { return null }
local kvl = s.indexOf("\"value\":", kli); if kvl < 0 { return null }
local kli = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_bin_start); if kli < 0 { return null }
local kvl = JsonFragBox.index_of_from(s, "\"value\":", kli); if kvl < 0 { return null }
local l = JsonFragBox.read_int_after(s, kvl + 8); if l == null { return null }
// rhs int
local kri = s.indexOf("\"type\":\"Int\"", kli + 1); if kri < 0 { return null }
local kv2 = s.indexOf("\"value\":", kri); if kv2 < 0 { return null }
local kri = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", kli + 1); if kri < 0 { return null }
local kv2 = JsonFragBox.index_of_from(s, "\"value\":", kri); if kv2 < 0 { return null }
local r = JsonFragBox.read_int_after(s, kv2 + 8); if r == null { return null }
// compute
local li = 0; local ri = 0; // string to int by simple parse (assume i64 fits)
@ -32,17 +32,17 @@ static box LowerIfCompareFoldBinIntsBox {
// node may be Int, Binary(Int,Int), or Var with Local Int before if_pos
if node_pos < 0 { return null }
// Int
if s.indexOf("\"type\":\"Int\"", node_pos) == node_pos { // best-effort
local kv = s.indexOf("\"value\":", node_pos); if kv < 0 { return null }
if JsonFragBox.index_of_from(s, "\"type\":\"Int\"", node_pos) == node_pos { // best-effort
local kv = JsonFragBox.index_of_from(s, "\"value\":", node_pos); if kv < 0 { return null }
return JsonFragBox.read_int_after(s, kv + 8)
}
// Binary
if s.indexOf("\"type\":\"Binary\"", node_pos) == node_pos {
if JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", node_pos) == node_pos {
return me._fold_bin_ints(s, node_pos)
}
// Var(name)
if s.indexOf("\"type\":\"Var\"", node_pos) == node_pos {
local kn = s.indexOf("\"name\":\"", node_pos); if kn < 0 { return null }
if JsonFragBox.index_of_from(s, "\"type\":\"Var\"", node_pos) == node_pos {
local kn = JsonFragBox.index_of_from(s, "\"name\":\"", node_pos); if kn < 0 { return null }
local name = JsonFragBox.read_string_after(s, kn + 5); if name == null { return null }
// find last matching Local Int before if_pos via util
return PatternUtilBox.find_local_int_before(s, name, if_pos)
@ -51,29 +51,29 @@ static box LowerIfCompareFoldBinIntsBox {
}
try_lower(program_json){
local s = "" + program_json
local k_if = s.indexOf("\"type\":\"If\""); if k_if < 0 { return null }
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0); if k_if < 0 { return null }
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
local sym = JsonFragBox.read_string_after(s, k_op + 5); if sym == null { return null }
local op = PatternUtilBox.map_cmp(sym); if op == null { return null }
// locate lhs/rhs node starts (Var/Int/Binary)
local klhs = s.indexOf("\"lhs\":{", k_cmp); if klhs < 0 { return null }
local krhs = s.indexOf("\"rhs\":{", k_cmp); if krhs < 0 { return null }
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if klhs < 0 { return null }
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if krhs < 0 { return null }
local lhs_pos = klhs + 6
local rhs_pos = krhs + 6
local lhs_val = me._resolve_side_int(s, lhs_pos, k_if)
local rhs_val = me._resolve_side_int(s, rhs_pos, k_if)
if lhs_val == null || rhs_val == null { return null }
// then/else Return(Int)
local kth = s.indexOf("\"then\":", k_if); if kth < 0 { return null }
local rt1 = s.indexOf("\"type\":\"Return\"", kth); if rt1 < 0 { return null }
local ti1 = s.indexOf("\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
local kv1 = s.indexOf("\"value\":", ti1); if kv1 < 0 { return null }
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if); if kth < 0 { return null }
local rt1 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt1 < 0 { return null }
local ti1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
local kv1 = JsonFragBox.index_of_from(s, "\"value\":", ti1); if kv1 < 0 { return null }
local then_v = JsonFragBox.read_int_after(s, kv1 + 8); if then_v == null { return null }
local kel = s.indexOf("\"else\":", k_if); if kel < 0 { return null }
local rt2 = s.indexOf("\"type\":\"Return\"", kel); if rt2 < 0 { return null }
local ti2 = s.indexOf("\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
local kv2b = s.indexOf("\"value\":", ti2); if kv2b < 0 { return null }
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if); if kel < 0 { return null }
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel); if rt2 < 0 { return null }
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
local kv2b = JsonFragBox.index_of_from(s, "\"value\":", ti2); if kv2b < 0 { return null }
local else_v = JsonFragBox.read_int_after(s, kv2b + 8); if else_v == null { return null }
// Build MIR
local b0 = new ArrayBox(); b0.push(MirSchemaBox.inst_const(1, lhs_val)); b0.push(MirSchemaBox.inst_const(2, rhs_val)); b0.push(MirSchemaBox.inst_compare(op,1,2,3)); b0.push(MirSchemaBox.inst_branch(3,1,2))

View File

@ -7,24 +7,24 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
static box LowerIfCompareFoldVarIntBox {
_fold_bin_varint(s, k_bin, if_pos) {
// Binary with one Var and one Int; resolve Var via Local and compute result
local kop = s.indexOf("\"op\":\"", k_bin); if kop < 0 { return null }
local kop = JsonFragBox.index_of_from(s, "\"op\":\"", k_bin); if kop < 0 { return null }
local op = JsonFragBox.read_string_after(s, kop + 5)
if !(op=="+"||op=="-"||op=="*"||op=="/") { return null }
local klv = s.indexOf("\"lhs\":{\"type\":\"Var\"", k_bin)
local kli = s.indexOf("\"lhs\":{\"type\":\"Int\"", k_bin)
local krv = s.indexOf("\"rhs\":{\"type\":\"Var\"", k_bin)
local kri = s.indexOf("\"rhs\":{\"type\":\"Int\"", k_bin)
local klv = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\"", k_bin)
local kli = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Int\"", k_bin)
local krv = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_bin)
local kri = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Int\"", k_bin)
local vval = null; local ival = null
if klv >= 0 && kri >= 0 {
local kn = s.indexOf("\"name\":", klv); if kn < 0 { return null }
local kn = JsonFragBox.index_of_from(s, "\"name\":", klv); if kn < 0 { return null }
local name = JsonFragBox.read_string_after(s, kn + 7)
vval = PatternUtilBox.find_local_int_before(s, name, if_pos)
local kv = s.indexOf("\"value\":", kri); if kv < 0 { return null }
local kv = JsonFragBox.index_of_from(s, "\"value\":", kri); if kv < 0 { return null }
ival = JsonFragBox.read_int_after(s, kv + 8)
} else if kli >= 0 && krv >= 0 {
local kv2 = s.indexOf("\"value\":", kli); if kv2 < 0 { return null }
local kv2 = JsonFragBox.index_of_from(s, "\"value\":", kli); if kv2 < 0 { return null }
ival = JsonFragBox.read_int_after(s, kv2 + 8)
local kn2 = s.indexOf("\"name\":", krv); if kn2 < 0 { return null }
local kn2 = JsonFragBox.index_of_from(s, "\"name\":", krv); if kn2 < 0 { return null }
local name2 = JsonFragBox.read_string_after(s, kn2 + 7)
vval = PatternUtilBox.find_local_int_before(s, name2, if_pos)
}
@ -36,17 +36,17 @@ static box LowerIfCompareFoldVarIntBox {
}
_resolve_side(s, node_pos, if_pos) {
// Try Int
if s.indexOf("\"type\":\"Int\"", node_pos) == node_pos {
local kv = s.indexOf("\"value\":", node_pos); if kv < 0 { return null }
if JsonFragBox.index_of_from(s, "\"type\":\"Int\"", node_pos) == node_pos {
local kv = JsonFragBox.index_of_from(s, "\"value\":", node_pos); if kv < 0 { return null }
return JsonFragBox.read_int_after(s, kv + 8)
}
// Binary(Var,Int) or (Int,Var)
if s.indexOf("\"type\":\"Binary\"", node_pos) == node_pos {
if JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", node_pos) == node_pos {
return me._fold_bin_varint(s, node_pos, if_pos)
}
// Var → Local Int
if s.indexOf("\"type\":\"Var\"", node_pos) == node_pos {
local kn = s.indexOf("\"name\":", node_pos); if kn < 0 { return null }
if JsonFragBox.index_of_from(s, "\"type\":\"Var\"", node_pos) == node_pos {
local kn = JsonFragBox.index_of_from(s, "\"name\":", node_pos); if kn < 0 { return null }
local name = JsonFragBox.read_string_after(s, kn + 7)
return PatternUtilBox.find_local_int_before(s, name, if_pos)
}
@ -54,26 +54,26 @@ static box LowerIfCompareFoldVarIntBox {
}
try_lower(program_json){
local s = "" + program_json
local k_if = s.indexOf("\"type\":\"If\""); if k_if < 0 { return null }
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0); if k_if < 0 { return null }
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
local op_sym = JsonFragBox.read_string_after(s, k_op + 5)
local op = PatternUtilBox.map_cmp(op_sym); if op == null { return null }
local klhs = s.indexOf("\"lhs\":{", k_cmp); if klhs < 0 { return null }
local krhs = s.indexOf("\"rhs\":{", k_cmp); if krhs < 0 { return null }
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if klhs < 0 { return null }
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if krhs < 0 { return null }
local lhs = me._resolve_side(s, klhs+6, k_if)
local rhs = me._resolve_side(s, krhs+6, k_if)
if lhs == null || rhs == null { return null }
// then/else Return(Int)
local kth = s.indexOf("\"then\":", k_if); if kth < 0 { return null }
local rt1 = s.indexOf("\"type\":\"Return\"", kth); if rt1 < 0 { return null }
local ti1 = s.indexOf("\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
local kv1 = s.indexOf("\"value\":", ti1); if kv1 < 0 { return null }
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if); if kth < 0 { return null }
local rt1 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt1 < 0 { return null }
local ti1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
local kv1 = JsonFragBox.index_of_from(s, "\"value\":", ti1); if kv1 < 0 { return null }
local tv = JsonFragBox.read_int_after(s, kv1 + 8); if tv == null { return null }
local kel = s.indexOf("\"else\":", k_if); if kel < 0 { return null }
local rt2 = s.indexOf("\"type\":\"Return\"", kel); if rt2 < 0 { return null }
local ti2 = s.indexOf("\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
local kv2b = s.indexOf("\"value\":", ti2); if kv2b < 0 { return null }
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if); if kel < 0 { return null }
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel); if rt2 < 0 { return null }
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
local kv2b = JsonFragBox.index_of_from(s, "\"value\":", ti2); if kv2b < 0 { return null }
local ev = JsonFragBox.read_int_after(s, kv2b + 8); if ev == null { return null }
// Build
local b0=new ArrayBox(); b0.push(MirSchemaBox.inst_const(1,lhs)); b0.push(MirSchemaBox.inst_const(2,rhs)); b0.push(MirSchemaBox.inst_compare(op,1,2,3)); b0.push(MirSchemaBox.inst_branch(3,1,2))

View File

@ -7,50 +7,51 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
static box LowerIfCompareVarIntBox {
try_lower(program_json){
local s = "" + program_json
local k_if = s.indexOf("\"type\":\"If\""); if k_if < 0 { return null }
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
// Locate If → Compare → op using robust index_of_from helpers
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0); if k_if < 0 { return null }
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
local op_sym = JsonFragBox.read_string_after(s, k_op + 5)
local op = PatternUtilBox.map_cmp(op_sym); if op == null { return null }
// Var vs Int
local klhs_var = s.indexOf("\"lhs\":{\"type\":\"Var\"", k_cmp)
local krhs_int = s.indexOf("\"rhs\":{\"type\":\"Int\"", k_cmp)
local klhs_var = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\"", k_cmp)
local krhs_int = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Int\"", k_cmp)
local aval=null; local bval=null
if klhs_var >= 0 && krhs_int >= 0 {
local k_name = s.indexOf("\"name\":", klhs_var); if k_name < 0 { return null }
local k_name = JsonFragBox.index_of_from(s, "\"name\":", klhs_var); if k_name < 0 { return null }
local name = JsonFragBox.read_string_after(s, k_name + 7)
aval = PatternUtilBox.find_local_int_before(s, name, k_if)
local ki = s.indexOf("\"type\":\"Int\"", krhs_int)
local ki = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs_int)
if ki >= 0 {
local kv = s.indexOf("\"value\":", ki); if kv < 0 { return null }
local kv = JsonFragBox.index_of_from(s, "\"value\":", ki); if kv < 0 { return null }
bval = JsonFragBox.read_int_after(s, kv + 8)
}
} else {
// Int vs Var
local klhs_int = s.indexOf("\"lhs\":{\"type\":\"Int\"", k_cmp)
local krhs_var = s.indexOf("\"rhs\":{\"type\":\"Var\"", k_cmp)
local klhs_int = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Int\"", k_cmp)
local krhs_var = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_cmp)
if klhs_int >= 0 && krhs_var >= 0 {
local ki2 = s.indexOf("\"type\":\"Int\"", klhs_int)
local ki2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs_int)
if ki2 >= 0 {
local kv2 = s.indexOf("\"value\":", ki2); if kv2 < 0 { return null }
local kv2 = JsonFragBox.index_of_from(s, "\"value\":", ki2); if kv2 < 0 { return null }
aval = JsonFragBox.read_int_after(s, kv2 + 8)
}
local k_name2 = s.indexOf("\"name\":", krhs_var); if k_name2 < 0 { return null }
local k_name2 = JsonFragBox.index_of_from(s, "\"name\":", krhs_var); if k_name2 < 0 { return null }
local name2 = JsonFragBox.read_string_after(s, k_name2 + 7)
if name2 != null { bval = PatternUtilBox.find_local_int_before(s, name2, k_if) }
}
}
if aval == null || bval == null { return null }
// then/else Return(Int)
local kth = s.indexOf("\"then\":", k_if); if kth < 0 { return null }
local rt1 = s.indexOf("\"type\":\"Return\"", kth); if rt1 < 0 { return null }
local ti1 = s.indexOf("\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
local kv_then = s.indexOf("\"value\":", ti1); if kv_then < 0 { return null }
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if); if kth < 0 { return null }
local rt1 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt1 < 0 { return null }
local ti1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
local kv_then = JsonFragBox.index_of_from(s, "\"value\":", ti1); if kv_then < 0 { return null }
local then_v = JsonFragBox.read_int_after(s, kv_then + 8); if then_v == null { return null }
local kel = s.indexOf("\"else\":", k_if); if kel < 0 { return null }
local rt2 = s.indexOf("\"type\":\"Return\"", kel); if rt2 < 0 { return null }
local ti2 = s.indexOf("\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
local kv_else = s.indexOf("\"value\":", ti2); if kv_else < 0 { return null }
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if); if kel < 0 { return null }
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel); if rt2 < 0 { return null }
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
local kv_else = JsonFragBox.index_of_from(s, "\"value\":", ti2); if kv_else < 0 { return null }
local else_v = JsonFragBox.read_int_after(s, kv_else + 8); if else_v == null { return null }
// Build MIR
local b0=new ArrayBox(); b0.push(MirSchemaBox.inst_const(1,aval)); b0.push(MirSchemaBox.inst_const(2,bval)); b0.push(MirSchemaBox.inst_compare(op,1,2,3)); b0.push(MirSchemaBox.inst_branch(3,1,2))

View File

@ -11,21 +11,21 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
static box LowerIfCompareVarVarBox {
try_lower(program_json) {
local s = "" + program_json
local k_if = s.indexOf("\"type\":\"If\"")
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0)
if k_if < 0 { return null }
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if)
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if)
if k_cmp < 0 { return null }
// LHS/RHS Var names
local lhs_name = null
local klhs = s.indexOf("\"lhs\":{\"type\":\"Var\"", k_cmp)
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\"", k_cmp)
if klhs >= 0 {
local k_name_lhs = s.indexOf("\"name\":", klhs); if k_name_lhs < 0 { return null }
local k_name_lhs = JsonFragBox.index_of_from(s, "\"name\":", klhs); if k_name_lhs < 0 { return null }
lhs_name = JsonFragBox.read_string_after(s, k_name_lhs + 7)
}
local rhs_name = null
local krhs = s.indexOf("\"rhs\":{\"type\":\"Var\"", k_cmp)
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_cmp)
if krhs >= 0 {
local k_name_rhs = s.indexOf("\"name\":", krhs); if k_name_rhs < 0 { return null }
local k_name_rhs = JsonFragBox.index_of_from(s, "\"name\":", krhs); if k_name_rhs < 0 { return null }
rhs_name = JsonFragBox.read_string_after(s, k_name_rhs + 7)
}
if lhs_name == null || rhs_name == null { return null }
@ -34,21 +34,21 @@ static box LowerIfCompareVarVarBox {
local bval = PatternUtilBox.find_local_int_before(s, rhs_name, k_if)
if aval == null || bval == null { return null }
// op map
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
local sym = JsonFragBox.read_string_after(s, k_op + 5)
if sym == null { return null }
local op = PatternUtilBox.map_cmp(sym)
if op == null { return null }
// then/else Return(Int)
local kth = s.indexOf("\"then\":", k_if); if kth < 0 { return null }
local rt1 = s.indexOf("\"type\":\"Return\"", kth); if rt1 < 0 { return null }
local ti1 = s.indexOf("\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
local kv_then = s.indexOf("\"value\":", ti1); if kv_then < 0 { return null }
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if); if kth < 0 { return null }
local rt1 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt1 < 0 { return null }
local ti1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
local kv_then = JsonFragBox.index_of_from(s, "\"value\":", ti1); if kv_then < 0 { return null }
local then_val = JsonFragBox.read_int_after(s, kv_then + 8); if then_val == null { return null }
local kel = s.indexOf("\"else\":", k_if); if kel < 0 { return null }
local rt2 = s.indexOf("\"type\":\"Return\"", kel); if rt2 < 0 { return null }
local ti2 = s.indexOf("\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
local kv_else = s.indexOf("\"value\":", ti2); if kv_else < 0 { return null }
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if); if kel < 0 { return null }
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel); if rt2 < 0 { return null }
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
local kv_else = JsonFragBox.index_of_from(s, "\"value\":", ti2); if kv_else < 0 { return null }
local else_val = JsonFragBox.read_int_after(s, kv_else + 8); if else_val == null { return null }
// Build MIR

View File

@ -19,53 +19,53 @@ using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
static box LowerIfNestedBox {
try_lower(program_json) {
local s = "" + program_json
local k_if1 = s.indexOf("\"type\":\"If\"")
local k_if1 = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0)
if k_if1 < 0 { return null }
local k_cmp1 = s.indexOf("\"type\":\"Compare\"", k_if1)
local k_cmp1 = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if1)
if k_cmp1 < 0 { return null }
local kop1 = s.indexOf("\"op\":", k_cmp1); if kop1 < 0 { return null }
local kop1 = JsonFragBox.index_of_from(s, "\"op\":", k_cmp1); if kop1 < 0 { return null }
local op1s = JsonFragBox.read_string_after(s, kop1 + 5); if op1s == null { return null }
local op1 = PatternUtilBox.map_cmp(op1s); if op1 == null { return null }
local klhs1 = s.indexOf("\"lhs\":{", k_cmp1); if klhs1 < 0 { return null }
local ti11 = s.indexOf("\"type\":\"Int\"", klhs1); if ti11 < 0 { return null }
local kv11 = s.indexOf("\"value\":", ti11); if kv11 < 0 { return null }
local klhs1 = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp1); if klhs1 < 0 { return null }
local ti11 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs1); if ti11 < 0 { return null }
local kv11 = JsonFragBox.index_of_from(s, "\"value\":", ti11); if kv11 < 0 { return null }
local lhs1 = JsonFragBox.read_int_after(s, kv11 + 8); if lhs1 == null { return null }
local krhs1 = s.indexOf("\"rhs\":{", k_cmp1); if krhs1 < 0 { return null }
local ti12 = s.indexOf("\"type\":\"Int\"", krhs1); if ti12 < 0 { return null }
local kv12 = s.indexOf("\"value\":", ti12); if kv12 < 0 { return null }
local krhs1 = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp1); if krhs1 < 0 { return null }
local ti12 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs1); if ti12 < 0 { return null }
local kv12 = JsonFragBox.index_of_from(s, "\"value\":", ti12); if kv12 < 0 { return null }
local rhs1 = JsonFragBox.read_int_after(s, kv12 + 8); if rhs1 == null { return null }
// then Return(Int A)
local kth = s.indexOf("\"then\":", k_if1); if kth < 0 { return null }
local rt1 = s.indexOf("\"type\":\"Return\"", kth); if rt1 < 0 { return null }
local ti13 = s.indexOf("\"type\":\"Int\"", rt1); if ti13 < 0 { return null }
local kv13 = s.indexOf("\"value\":", ti13); if kv13 < 0 { return null }
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if1); if kth < 0 { return null }
local rt1 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt1 < 0 { return null }
local ti13 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt1); if ti13 < 0 { return null }
local kv13 = JsonFragBox.index_of_from(s, "\"value\":", ti13); if kv13 < 0 { return null }
local aval = JsonFragBox.read_int_after(s, kv13 + 8); if aval == null { return null }
// else contains nested If with Return(Int)/Return(Int)
local kel = s.indexOf("\"else\":", k_if1); if kel < 0 { return null }
local k_if2 = s.indexOf("\"type\":\"If\"", kel); if k_if2 < 0 { return null }
local k_cmp2 = s.indexOf("\"type\":\"Compare\"", k_if2); if k_cmp2 < 0 { return null }
local kop2 = s.indexOf("\"op\":", k_cmp2); if kop2 < 0 { return null }
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if1); if kel < 0 { return null }
local k_if2 = JsonFragBox.index_of_from(s, "\"type\":\"If\"", kel); if k_if2 < 0 { return null }
local k_cmp2 = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if2); if k_cmp2 < 0 { return null }
local kop2 = JsonFragBox.index_of_from(s, "\"op\":", k_cmp2); if kop2 < 0 { return null }
local op2s = JsonFragBox.read_string_after(s, kop2 + 5); if op2s == null { return null }
local op2 = PatternUtilBox.map_cmp(op2s); if op2 == null { return null }
local klhs2 = s.indexOf("\"lhs\":{", k_cmp2); if klhs2 < 0 { return null }
local ti21 = s.indexOf("\"type\":\"Int\"", klhs2); if ti21 < 0 { return null }
local kv21 = s.indexOf("\"value\":", ti21); if kv21 < 0 { return null }
local klhs2 = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp2); if klhs2 < 0 { return null }
local ti21 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs2); if ti21 < 0 { return null }
local kv21 = JsonFragBox.index_of_from(s, "\"value\":", ti21); if kv21 < 0 { return null }
local lhs2 = JsonFragBox.read_int_after(s, kv21 + 8); if lhs2 == null { return null }
local krhs2 = s.indexOf("\"rhs\":{", k_cmp2); if krhs2 < 0 { return null }
local ti22 = s.indexOf("\"type\":\"Int\"", krhs2); if ti22 < 0 { return null }
local kv22 = s.indexOf("\"value\":", ti22); if kv22 < 0 { return null }
local krhs2 = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp2); if krhs2 < 0 { return null }
local ti22 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs2); if ti22 < 0 { return null }
local kv22 = JsonFragBox.index_of_from(s, "\"value\":", ti22); if kv22 < 0 { return null }
local rhs2 = JsonFragBox.read_int_after(s, kv22 + 8); if rhs2 == null { return null }
// then Return(Int B)
local kth2 = s.indexOf("\"then\":", k_if2); if kth2 < 0 { return null }
local rt2 = s.indexOf("\"type\":\"Return\"", kth2); if rt2 < 0 { return null }
local ti23 = s.indexOf("\"type\":\"Int\"", rt2); if ti23 < 0 { return null }
local kv23 = s.indexOf("\"value\":", ti23); if kv23 < 0 { return null }
local kth2 = JsonFragBox.index_of_from(s, "\"then\":", k_if2); if kth2 < 0 { return null }
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth2); if rt2 < 0 { return null }
local ti23 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2); if ti23 < 0 { return null }
local kv23 = JsonFragBox.index_of_from(s, "\"value\":", ti23); if kv23 < 0 { return null }
local bval = JsonFragBox.read_int_after(s, kv23 + 8); if bval == null { return null }
// else Return(Int C)
local kel2 = s.indexOf("\"else\":", k_if2); if kel2 < 0 { return null }
local rt3 = s.indexOf("\"type\":\"Return\"", kel2); if rt3 < 0 { return null }
local ti24 = s.indexOf("\"type\":\"Int\"", rt3); if ti24 < 0 { return null }
local kv24 = s.indexOf("\"value\":", ti24); if kv24 < 0 { return null }
local kel2 = JsonFragBox.index_of_from(s, "\"else\":", k_if2); if kel2 < 0 { return null }
local rt3 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel2); if rt3 < 0 { return null }
local ti24 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt3); if ti24 < 0 { return null }
local kv24 = JsonFragBox.index_of_from(s, "\"value\":", ti24); if kv24 < 0 { return null }
local cval = JsonFragBox.read_int_after(s, kv24 + 8); if cval == null { return null }
// Build MIR(JSON)

View File

@ -10,29 +10,29 @@ static box LowerIfThenElseFollowingReturnBox {
try_lower(program_json) {
local s = "" + program_json
// If with Compare(Int,Int)
local k_if = s.indexOf("\"type\":\"If\"")
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0)
if k_if < 0 { return null }
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if)
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if)
if k_cmp < 0 { return null }
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
local sym = JsonFragBox.read_string_after(s, k_op + 5); if sym == null { return null }
local op = PatternUtilBox.map_cmp(sym); if op == null { return null }
// LHS/RHS ints
local klhs = s.indexOf("\"lhs\":{", k_cmp); if klhs < 0 { return null }
local ti1 = s.indexOf("\"type\":\"Int\"", klhs); if ti1 < 0 { return null }
{ local kv = s.indexOf("\"value\":", ti1); if kv < 0 { return null }; var lhs_val = JsonFragBox.read_int_after(s, kv + 8); if lhs_val == null { return null } }
local krhs = s.indexOf("\"rhs\":{", k_cmp); if krhs < 0 { return null }
local ti2 = s.indexOf("\"type\":\"Int\"", krhs); if ti2 < 0 { return null }
{ local kv2 = s.indexOf("\"value\":", ti2); if kv2 < 0 { return null }; var rhs_val = JsonFragBox.read_int_after(s, kv2 + 8); if rhs_val == null { return null } }
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if klhs < 0 { return null }
local ti1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs); if ti1 < 0 { return null }
{ local kv = JsonFragBox.index_of_from(s, "\"value\":", ti1); if kv < 0 { return null }; var lhs_val = JsonFragBox.read_int_after(s, kv + 8); if lhs_val == null { return null } }
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if krhs < 0 { return null }
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs); if ti2 < 0 { return null }
{ local kv2 = JsonFragBox.index_of_from(s, "\"value\":", ti2); if kv2 < 0 { return null }; var rhs_val = JsonFragBox.read_int_after(s, kv2 + 8); if rhs_val == null { return null } }
// then: Return(Int)
local kth = s.indexOf("\"then\":", k_if); if kth < 0 { return null }
local rt = s.indexOf("\"type\":\"Return\"", kth); if rt < 0 { return null }
local ti3 = s.indexOf("\"type\":\"Int\"", rt); if ti3 < 0 { return null }
{ local kv3 = s.indexOf("\"value\":", ti3); if kv3 < 0 { return null }; var then_val = JsonFragBox.read_int_after(s, kv3 + 8); if then_val == null { return null } }
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if); if kth < 0 { return null }
local rt = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt < 0 { return null }
local ti3 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt); if ti3 < 0 { return null }
{ local kv3 = JsonFragBox.index_of_from(s, "\"value\":", ti3); if kv3 < 0 { return null }; var then_val = JsonFragBox.read_int_after(s, kv3 + 8); if then_val == null { return null } }
// else is omitted → following Return(Int) in Program body
local k_after = s.indexOf("\"type\":\"Return\"", k_if + 1); if k_after < 0 { return null }
local ti4 = s.indexOf("\"type\":\"Int\"", k_after); if ti4 < 0 { return null }
{ local kv4 = s.indexOf("\"value\":", ti4); if kv4 < 0 { return null }; var else_val = JsonFragBox.read_int_after(s, kv4 + 8); if else_val == null { return null } }
local k_after = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", k_if + 1); if k_after < 0 { return null }
local ti4 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_after); if ti4 < 0 { return null }
{ local kv4 = JsonFragBox.index_of_from(s, "\"value\":", ti4); if kv4 < 0 { return null }; var else_val = JsonFragBox.read_int_after(s, kv4 + 8); if else_val == null { return null } }
// Build MIR(JSON)
local b0 = new ArrayBox()

View File

@ -12,27 +12,27 @@ static box LowerLoopCountParamBox {
local s = "" + program_json
// Discover loop variable name from Compare first
// We'll accept either lhs Var(name) or rhs Var(name)
local k_loop = s.indexOf("\"type\":\"Loop\"", 0)
local k_loop = JsonFragBox.index_of_from(s, "\"type\":\"Loop\"", 0)
if k_loop < 0 { return null }
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_loop)
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_loop)
if k_cmp < 0 { return null }
local varname = LoopScanBox.find_loop_var_name(s, k_cmp)
if varname == null { return null }
// Local <varname> = (Int init | Var initName)
local k_local_i = s.indexOf("\"type\":\"Local\"")
local k_local_i = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", 0)
if k_local_i < 0 { return null }
if s.indexOf("\"name\":\"" + varname + "\"", k_local_i) < 0 { return null }
if JsonFragBox.index_of_from(s, "\"name\":\"" + varname + "\"", k_local_i) < 0 { return null }
local init = null
{
local k_init_int = s.indexOf("\"type\":\"Int\"", k_local_i)
local k_loop_next = s.indexOf("\"type\":\"Loop\"", k_local_i)
local k_init_int = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_local_i)
local k_loop_next = JsonFragBox.index_of_from(s, "\"type\":\"Loop\"", k_local_i)
if k_init_int >= 0 && (k_loop_next < 0 || k_init_int < k_loop_next) {
local kv_i = s.indexOf("\"value\":", k_init_int); if kv_i >= 0 { init = JsonFragBox.read_int_after(s, kv_i + 8) }
local kv_i = JsonFragBox.index_of_from(s, "\"value\":", k_init_int); if kv_i >= 0 { init = JsonFragBox.read_int_after(s, kv_i + 8) }
} else {
local k_init_var = s.indexOf("\"type\":\"Var\"", k_local_i)
local k_init_var = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_local_i)
if k_init_var >= 0 && (k_loop_next < 0 || k_init_var < k_loop_next) {
local kn_i = s.indexOf("\"name\":\"", k_init_var); if kn_i < 0 { return null }
local kn_i = JsonFragBox.index_of_from(s, "\"name\":\"", k_init_var); if kn_i < 0 { return null }
local vname = JsonFragBox.read_string_after(s, kn_i)
if vname != null { init = PatternUtilBox.find_local_int_before(s, vname, k_local_i) }
}
@ -41,22 +41,22 @@ static box LowerLoopCountParamBox {
if init == null { return null }
// Loop Compare normalize: accept < / <= / > / >= with Var(varname) on either side
// op: accept '<'/'<=' with i on lhs; '>'/'>=' with i on lhs (descending); swapped '>'/'>=' with i on rhs (ascending)
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
local op = JsonFragBox.read_string_after(s, k_op + 5)
if op == null { return null }
local has_lhs_i = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
local has_rhs_i = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
local has_lhs_i = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
local has_rhs_i = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
if !has_lhs_i && !has_rhs_i { return null }
local cmp = null
local limit = null
if has_lhs_i {
// rhs Int/Var → resolve limit
local k_rhs = s.indexOf("\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
local k_lim_t = s.indexOf("\"type\":\"Int\"", k_rhs)
if k_lim_t >= 0 { local kv = s.indexOf("\"value\":", k_lim_t); if kv >= 0 { limit = JsonFragBox.read_int_after(s, kv + 8) } }
local k_rhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
local k_lim_t = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhs)
if k_lim_t >= 0 { local kv = JsonFragBox.index_of_from(s, "\"value\":", k_lim_t); if kv >= 0 { limit = JsonFragBox.read_int_after(s, kv + 8) } }
else {
local k_rv = s.indexOf("\"type\":\"Var\"", k_rhs); if k_rv < 0 { return null }
local kn = s.indexOf("\"name\":\"", k_rhs); if kn < 0 { return null }
local k_rv = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_rhs); if k_rv < 0 { return null }
local kn = JsonFragBox.index_of_from(s, "\"name\":\"", k_rhs); if kn < 0 { return null }
local lname = JsonFragBox.read_string_after(s, kn); if lname == null { return null }
limit = PatternUtilBox.find_local_int_before(s, lname, k_cmp)
}
@ -69,12 +69,12 @@ static box LowerLoopCountParamBox {
limit = norm.substring(cpos+1, norm.length())
} else {
if op != ">" && op != ">=" && op != "<" && op != "<=" && op != "!=" { return null }
local k_lhs = s.indexOf("\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
local k_lim_t2 = s.indexOf("\"type\":\"Int\"", k_lhs)
if k_lim_t2 >= 0 { local kv2 = s.indexOf("\"value\":", k_lim_t2); if kv2 >= 0 { limit = JsonFragBox.read_int_after(s, kv2 + 8) } }
local k_lhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
local k_lim_t2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhs)
if k_lim_t2 >= 0 { local kv2 = JsonFragBox.index_of_from(s, "\"value\":", k_lim_t2); if kv2 >= 0 { limit = JsonFragBox.read_int_after(s, kv2 + 8) } }
else {
local k_lv = s.indexOf("\"type\":\"Var\"", k_lhs); if k_lv < 0 { return null }
local kn3 = s.indexOf("\"name\":\"", k_lhs); if kn3 < 0 { return null }
local k_lv = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_lhs); if k_lv < 0 { return null }
local kn3 = JsonFragBox.index_of_from(s, "\"name\":\"", k_lhs); if kn3 < 0 { return null }
local lname3 = JsonFragBox.read_string_after(s, kn3); if lname3 == null { return null }
limit = PatternUtilBox.find_local_int_before(s, lname3, k_cmp)
}
@ -86,27 +86,27 @@ static box LowerLoopCountParamBox {
limit = norm2.substring(cpos2+1, norm2.length())
}
// Body increment: Local i = Binary('+', Var i, Int step)
local k_body_i = s.indexOf("\"name\":\"" + varname + "\"", k_loop)
local k_body_i = JsonFragBox.index_of_from(s, "\"name\":\"" + varname + "\"", k_loop)
if k_body_i < 0 { return null }
local k_bop = s.indexOf("\"type\":\"Binary\"", k_body_i)
local k_bop = JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", k_body_i)
if k_bop < 0 { return null }
// Body increment: Local i = Binary(op '+' or '-', Var i, (Int step | Var stepName))
local bop_plus = (s.indexOf("\"op\":\"+\"", k_bop) >= 0)
local bop_minus = (s.indexOf("\"op\":\"-\"", k_bop) >= 0)
local bop_plus = (JsonFragBox.index_of_from(s, "\"op\":\"+\"", k_bop) >= 0)
local bop_minus = (JsonFragBox.index_of_from(s, "\"op\":\"-\"", k_bop) >= 0)
if (!bop_plus && !bop_minus) { return null }
if s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_bop) < 0 { return null }
if JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_bop) < 0 { return null }
local step = null
// Prefer rhs Int if present; otherwise try rhs Var and reverse-lookup its Local Int
{
local k_rhsb = s.indexOf("\"rhs\":{", k_bop); if k_rhsb < 0 { return null }
local k_t_int = s.indexOf("\"type\":\"Int\"", k_rhsb)
local k_rhsb = JsonFragBox.index_of_from(s, "\"rhs\":{", k_bop); if k_rhsb < 0 { return null }
local k_t_int = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb)
if k_t_int >= 0 {
local kvs = s.indexOf("\"value\":", k_t_int); if kvs >= 0 { step = JsonFragBox.read_int_after(s, kvs + 8) }
local kvs = JsonFragBox.index_of_from(s, "\"value\":", k_t_int); if kvs >= 0 { step = JsonFragBox.read_int_after(s, kvs + 8) }
} else {
local k_t_var = s.indexOf("\"type\":\"Var\"", k_rhsb)
local k_t_var = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_rhsb)
if k_t_var < 0 { return null }
local kns = s.indexOf("\"name\":\"", k_rhsb); if kns < 0 { return null }
local kns = JsonFragBox.index_of_from(s, "\"name\":\"", k_rhsb); if kns < 0 { return null }
local vname = JsonFragBox.read_string_after(s, kns); if vname == null { return null }
step = PatternUtilBox.find_local_int_before(s, vname, k_bop)
}

View File

@ -12,38 +12,38 @@ static box LowerLoopSimpleBox {
try_lower(program_json) {
local s = "" + program_json
// Find Loop with cond Compare and normalize to canonical (<) with dynamic var name
local k_loop = s.indexOf("\"type\":\"Loop\"")
local k_loop = JsonFragBox.index_of_from(s, "\"type\":\"Loop\"", 0)
if k_loop < 0 { return null }
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_loop)
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_loop)
if k_cmp < 0 { return null }
// discover loop var name from cond (lhs or rhs Var)
local varname = LoopScanBox.find_loop_var_name(s, k_cmp)
if varname == null { return null }
// op: accept '<' / '<=' as-is, '!=' (with var on lhs) as '<', and swapped '>' / '>=' (with var on rhs)
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
local op = JsonFragBox.read_string_after(s, k_op + 5)
if op == null { return null }
// Determine where Var(varname) is and extract the Int from the opposite side
local has_lhs_i = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
local has_rhs_i = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
local has_lhs_i = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
local has_rhs_i = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
if !has_lhs_i && !has_rhs_i { return null }
local swapped = 0
local limit = null
if has_lhs_i {
// rhs Int value
local k_rhs = s.indexOf("\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
local k_ti = s.indexOf("\"type\":\"Int\"", k_rhs); if k_ti < 0 { return null }
local k_v = s.indexOf("\"value\":", k_ti); if k_v < 0 { return null }
local k_rhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
local k_ti = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhs); if k_ti < 0 { return null }
local k_v = JsonFragBox.index_of_from(s, "\"value\":", k_ti); if k_v < 0 { return null }
limit = JsonFragBox.read_int_after(s, k_v + 8)
if limit == null { return null }
} else {
// Var is on rhs; lhs must be Int
swapped = 1
local k_lhs = s.indexOf("\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
local k_ti2 = s.indexOf("\"type\":\"Int\"", k_lhs); if k_ti2 < 0 { return null }
local k_v2 = s.indexOf("\"value\":", k_ti2); if k_v2 < 0 { return null }
local k_lhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
local k_ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhs); if k_ti2 < 0 { return null }
local k_v2 = JsonFragBox.index_of_from(s, "\"value\":", k_ti2); if k_v2 < 0 { return null }
limit = JsonFragBox.read_int_after(s, k_v2 + 8)
if limit == null { return null }
}

View File

@ -21,19 +21,19 @@ static box LowerLoopSumBcBox {
print("[sum_bc] enter lower")
}
// Loop and Compare normalize to canonical (<) with dynamic var name
local k_loop = s.indexOf("\"type\":\"Loop\"")
local k_loop = JsonFragBox.index_of_from(s, "\"type\":\"Loop\"", 0)
if k_loop < 0 { return null }
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_loop)
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_loop)
if k_cmp < 0 { return null }
// discover loop var name from cond (lhs or rhs Var)
local varname = null
{
local kl = s.indexOf("\"lhs\":{", k_cmp); local kr = s.indexOf("\"rhs\":{", k_cmp)
if kl >= 0 && s.indexOf("\"type\":\"Var\"", kl) >= 0 {
local kn = s.indexOf("\"name\":\"", kl); if kn >= 0 { varname = JsonFragBox.read_string_after(s, kn) }
local kl = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); local kr = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp)
if kl >= 0 && JsonFragBox.index_of_from(s, "\"type\":\"Var\"", kl) >= 0 {
local kn = JsonFragBox.index_of_from(s, "\"name\":\"", kl); if kn >= 0 { varname = JsonFragBox.read_string_after(s, kn) }
}
if varname == null && kr >= 0 && s.indexOf("\"type\":\"Var\"", kr) >= 0 {
local kn2 = s.indexOf("\"name\":\"", kr); if kn2 >= 0 { varname = JsonFragBox.read_string_after(s, kn2) }
if varname == null && kr >= 0 && JsonFragBox.index_of_from(s, "\"type\":\"Var\"", kr) >= 0 {
local kn2 = JsonFragBox.index_of_from(s, "\"name\":\"", kr); if kn2 >= 0 { varname = JsonFragBox.read_string_after(s, kn2) }
}
}
if varname == null { return null }
@ -41,27 +41,27 @@ static box LowerLoopSumBcBox {
print("[sum_bc] var=" + varname)
}
// op: accept '<'/'<=' with var on lhs; also accept swapped '>'/'>=' with var on rhs
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
local op = JsonFragBox.read_string_after(s, k_op + 5)
if op == null { return null }
local has_lhs_i = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
local has_rhs_i = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
local has_lhs_i = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
local has_rhs_i = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
if !has_lhs_i && !has_rhs_i { return null }
local limit = null
if has_lhs_i {
if op != "<" && op != "<=" { return null }
// rhs Int limit
local k_rhs = s.indexOf("\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
local k_ti = s.indexOf("\"type\":\"Int\"", k_rhs); if k_ti < 0 { return null }
local kv = s.indexOf("\"value\":", k_ti); if kv < 0 { return null }
local k_rhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
local k_ti = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhs); if k_ti < 0 { return null }
local kv = JsonFragBox.index_of_from(s, "\"value\":", k_ti); if kv < 0 { return null }
limit = JsonFragBox.read_int_after(s, kv + 8); if limit == null { return null }
if op == "<=" { limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1) }
} else {
// swapped: Int on lhs, Var i on rhs, op should be '>' or '>='
if op != ">" && op != ">=" { return null }
local k_lhs = s.indexOf("\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
local k_ti2 = s.indexOf("\"type\":\"Int\"", k_lhs); if k_ti2 < 0 { return null }
local kv2 = s.indexOf("\"value\":", k_ti2); if kv2 < 0 { return null }
local k_lhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
local k_ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhs); if k_ti2 < 0 { return null }
local kv2 = JsonFragBox.index_of_from(s, "\"value\":", k_ti2); if kv2 < 0 { return null }
limit = JsonFragBox.read_int_after(s, kv2 + 8); if limit == null { return null }
if op == ">=" { limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1) }
}
@ -69,22 +69,24 @@ static box LowerLoopSumBcBox {
// Break sentinel: If(cond Compare var==X or X==var) then Break
local break_value = null
{
local kb = s.indexOf("\"type\":\"Break\"", k_loop)
local kb = JsonFragBox.index_of_from(s, "\"type\":\"Break\"", k_loop)
if kb >= 0 {
// Find nearest previous Compare and grab rhs Int
local kbc = s.lastIndexOf("\"type\":\"Compare\"", kb)
if kbc >= 0 {
// Ensure op=="==" and lhs Var i
local kop = s.indexOf("\"op\":", kbc); local bop = null; if kop >= 0 { bop = JsonFragBox.read_string_after(s, kop + 5) }
local kop = JsonFragBox.index_of_from(s, "\"op\":", kbc); local bop = null; if kop >= 0 { bop = JsonFragBox.read_string_after(s, kop + 5) }
if bop != null && bop == "==" {
local lhs_i = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kbc) >= 0
local rhs_i = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kbc) >= 0
local lhs_i = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kbc) >= 0
local rhs_i = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kbc) >= 0
if lhs_i {
local kbi = s.indexOf("\"type\":\"Int\"", s.indexOf("\"rhs\":{", kbc))
if kbi >= 0 { local kvb = s.indexOf("\"value\":", kbi); if kvb >= 0 { break_value = JsonFragBox.read_int_after(s, kvb + 8) } }
local k_rhsb = JsonFragBox.index_of_from(s, "\"rhs\":{", kbc)
local kbi = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb)
if kbi >= 0 { local kvb = JsonFragBox.index_of_from(s, "\"value\":", kbi); if kvb >= 0 { break_value = JsonFragBox.read_int_after(s, kvb + 8) } }
} else if rhs_i {
local kbi2 = s.indexOf("\"type\":\"Int\"", s.indexOf("\"lhs\":{", kbc))
if kbi2 >= 0 { local kvb2 = s.indexOf("\"value\":", kbi2); if kvb2 >= 0 { break_value = JsonFragBox.read_int_after(s, kvb2 + 8) } }
local k_lhsb = JsonFragBox.index_of_from(s, "\"lhs\":{", kbc)
local kbi2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhsb)
if kbi2 >= 0 { local kvb2 = JsonFragBox.index_of_from(s, "\"value\":", kbi2); if kvb2 >= 0 { break_value = JsonFragBox.read_int_after(s, kvb2 + 8) } }
}
} else if bop != null && bop == "!=" {
// Delegate to loop-scan helper for '!=' + else [Break]
@ -92,11 +94,11 @@ static box LowerLoopSumBcBox {
// Fallback: try local JsonFragBox-based extraction near kbc
if break_value == null {
// Read Int from lhs or rhs around kbc
local k_rhsb = s.indexOf("\"rhs\":{", kbc); local k_lhsb = s.indexOf("\"lhs\":{", kbc)
if k_rhsb >= 0 && s.indexOf("\"type\":\"Int\"", k_rhsb) >= 0 {
local kvi = s.indexOf("\"value\":", s.indexOf("\"type\":\"Int\"", k_rhsb)); if kvi >= 0 { break_value = JsonFragBox.read_int_after(s, kvi + 8) }
} else if k_lhsb >= 0 && s.indexOf("\"type\":\"Int\"", k_lhsb) >= 0 {
local kvj = s.indexOf("\"value\":", s.indexOf("\"type\":\"Int\"", k_lhsb)); if kvj >= 0 { break_value = JsonFragBox.read_int_after(s, kvj + 8) }
local k_rhsb = JsonFragBox.index_of_from(s, "\"rhs\":{", kbc); local k_lhsb = JsonFragBox.index_of_from(s, "\"lhs\":{", kbc)
if k_rhsb >= 0 && JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb) >= 0 {
local kvi = JsonFragBox.index_of_from(s, "\"value\":", JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb)); if kvi >= 0 { break_value = JsonFragBox.read_int_after(s, kvi + 8) }
} else if k_lhsb >= 0 && JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhsb) >= 0 {
local kvj = JsonFragBox.index_of_from(s, "\"value\":", JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhsb)); if kvj >= 0 { break_value = JsonFragBox.read_int_after(s, kvj + 8) }
}
}
}
@ -106,31 +108,33 @@ static box LowerLoopSumBcBox {
// Continue sentinel: If(cond Compare var==Y or Y==var) then Continue
local skip_value = null
{
local kc = s.indexOf("\"type\":\"Continue\"", k_loop)
local kc = JsonFragBox.index_of_from(s, "\"type\":\"Continue\"", k_loop)
if kc >= 0 {
local kcc = s.lastIndexOf("\"type\":\"Compare\"", kc)
if kcc >= 0 {
local kop2 = s.indexOf("\"op\":", kcc); local cop = null; if kop2 >= 0 { cop = JsonFragBox.read_string_after(s, kop2 + 5) }
local kop2 = JsonFragBox.index_of_from(s, "\"op\":", kcc); local cop = null; if kop2 >= 0 { cop = JsonFragBox.read_string_after(s, kop2 + 5) }
if cop != null && cop == "==" {
local lhs_i2 = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kcc) >= 0
local rhs_i2 = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kcc) >= 0
local lhs_i2 = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kcc) >= 0
local rhs_i2 = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kcc) >= 0
if lhs_i2 {
local kci = s.indexOf("\"type\":\"Int\"", s.indexOf("\"rhs\":{", kcc))
if kci >= 0 { local kvs = s.indexOf("\"value\":", kci); if kvs >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs + 8) } }
local k_rhsb2 = JsonFragBox.index_of_from(s, "\"rhs\":{", kcc)
local kci = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb2)
if kci >= 0 { local kvs = JsonFragBox.index_of_from(s, "\"value\":", kci); if kvs >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs + 8) } }
} else if rhs_i2 {
local kci2 = s.indexOf("\"type\":\"Int\"", s.indexOf("\"lhs\":{", kcc))
if kci2 >= 0 { local kvs2 = s.indexOf("\"value\":", kci2); if kvs2 >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs2 + 8) } }
local k_lhsb2 = JsonFragBox.index_of_from(s, "\"lhs\":{", kcc)
local kci2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhsb2)
if kci2 >= 0 { local kvs2 = JsonFragBox.index_of_from(s, "\"value\":", kci2); if kvs2 >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs2 + 8) } }
}
} else if cop != null && cop == "!=" {
// Delegate to loop-scan helper for '!=' + else [Continue]
if skip_value == null { skip_value = LoopScanBox.extract_ne_else_sentinel_value(s, "Continue", k_loop, varname) }
// Fallback: JsonFragBox-based local extraction near kcc
if skip_value == null {
local k_rhsb2 = s.indexOf("\"rhs\":{", kcc); local k_lhsb2 = s.indexOf("\"lhs\":{", kcc)
if k_rhsb2 >= 0 && s.indexOf("\"type\":\"Int\"", k_rhsb2) >= 0 {
local kvs = s.indexOf("\"value\":", s.indexOf("\"type\":\"Int\"", k_rhsb2)); if kvs >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs + 8) }
} else if k_lhsb2 >= 0 && s.indexOf("\"type\":\"Int\"", k_lhsb2) >= 0 {
local kvs2 = s.indexOf("\"value\":", s.indexOf("\"type\":\"Int\"", k_lhsb2)); if kvs2 >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs2 + 8) }
local k_rhsb2x = JsonFragBox.index_of_from(s, "\"rhs\":{", kcc); local k_lhsb2x = JsonFragBox.index_of_from(s, "\"lhs\":{", kcc)
if k_rhsb2x >= 0 && JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb2x) >= 0 {
local kvs = JsonFragBox.index_of_from(s, "\"value\":", JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb2x)); if kvs >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs + 8) }
} else if k_lhsb2x >= 0 && JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhsb2x) >= 0 {
local kvs2 = JsonFragBox.index_of_from(s, "\"value\":", JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhsb2x)); if kvs2 >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs2 + 8) }
}
}
}

View File

@ -5,8 +5,8 @@ static box LowerMethodArrayGetSetBox {
try_lower(program_json) {
if program_json == null { return null }
local s = "" + program_json
if s.indexOf("\"type\":\"New\"") < 0 { return null }
if s.indexOf("\"class\":\"ArrayBox\"") < 0 { return null }
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
if JsonFragBox.index_of_from(s, "\"class\":\"ArrayBox\"", 0) < 0 { return null }
// Reverse-lookup (safe subset): prefer Local(Int) for index, Local(String) for value
local n = s.length()
local idx = PatternUtilBox.find_any_local_int_before(s, n)

View File

@ -5,8 +5,8 @@ static box LowerMethodArrayPushBox {
try_lower(program_json) {
if program_json == null { return null }
local s = "" + program_json
if s.indexOf("\"type\":\"New\"") < 0 { return null }
if s.indexOf("\"class\":\"ArrayBox\"") < 0 { return null }
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
if JsonFragBox.index_of_from(s, "\"class\":\"ArrayBox\"", 0) < 0 { return null }
// Reverse-lookup (safe subset): prefer Local(Int) for push values when present
local n = s.length()
local p1 = PatternUtilBox.find_any_local_int_before(s, n); if p1 == null { p1 = "1" }

View File

@ -5,8 +5,8 @@ static box LowerMethodArraySizeBox {
try_lower(program_json) {
if program_json == null { return null }
local s = "" + program_json
if s.indexOf("\"type\":\"New\"") < 0 { return null }
if s.indexOf("\"class\":\"ArrayBox\"") < 0 { return null }
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
if JsonFragBox.index_of_from(s, "\"class\":\"ArrayBox\"", 0) < 0 { return null }
// Emit MIR v1 JSON: new ArrayBox -> r1, size(r1) -> r2, const 0 -> r3, ret r3
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
"{\"op\":\"mir_call\",\"dst\":1,\"mir_call\":{\"callee\":{\"type\":\"Constructor\",\"box_type\":\"ArrayBox\"},\"args\":[],\"effects\":[]}}," +
@ -16,4 +16,3 @@ static box LowerMethodArraySizeBox {
return json
}
}

View File

@ -5,8 +5,8 @@ static box LowerMethodMapGetSetBox {
try_lower(program_json) {
if program_json == null { return null }
local s = "" + program_json
if s.indexOf("\"type\":\"New\"") < 0 { return null }
if s.indexOf("\"class\":\"MapBox\"") < 0 { return null }
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
if JsonFragBox.index_of_from(s, "\"class\":\"MapBox\"", 0) < 0 { return null }
// Reverse-lookup (safe subset): prefer Local(String) for key, Local(Int) for value
local n = s.length()
local key = PatternUtilBox.find_any_local_string_before(s, n)

View File

@ -4,8 +4,8 @@ static box LowerMethodMapSizeBox {
try_lower(program_json) {
if program_json == null { return null }
local s = "" + program_json
if s.indexOf("\"type\":\"New\"") < 0 { return null }
if s.indexOf("\"class\":\"MapBox\"") < 0 { return null }
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
if JsonFragBox.index_of_from(s, "\"class\":\"MapBox\"", 0) < 0 { return null }
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
"{\"op\":\"mir_call\",\"dst\":1,\"mir_call\":{\"callee\":{\"type\":\"Constructor\",\"box_type\":\"MapBox\"},\"args\":[],\"effects\":[]}}," +
"{\"op\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"MapBox\",\"method\":\"size\",\"receiver\":1},\"args\":[],\"effects\":[]}}," +
@ -14,4 +14,3 @@ static box LowerMethodMapSizeBox {
return json
}
}

View File

@ -7,11 +7,11 @@ static box LowerNewboxConstructorBox {
if program_json == null { return null }
local s = "" + program_json
// Quick pattern check
if s.indexOf("\"type\":\"New\"") < 0 { return null }
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
// Find class name (minimal scan)
local cls = null
if s.indexOf("\"class\":\"ArrayBox\"") >= 0 { cls = "ArrayBox" }
else { if s.indexOf("\"class\":\"MapBox\"") >= 0 { cls = "MapBox" } }
if JsonFragBox.index_of_from(s, "\"class\":\"ArrayBox\"", 0) >= 0 { cls = "ArrayBox" }
else { if JsonFragBox.index_of_from(s, "\"class\":\"MapBox\"", 0) >= 0 { cls = "MapBox" } }
if cls == null { return null }
// Only accept known minimal boxes
if !(cls == "ArrayBox" || cls == "MapBox") { return null }

View File

@ -5,34 +5,34 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
static box LowerReturnBinOpBox {
try_lower(program_json) {
local s = "" + program_json
local k_ret = s.indexOf("\"type\":\"Return\"")
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
if k_ret < 0 { return null }
local k_bin = s.indexOf("\"type\":\"Binary\"", k_ret)
local k_bin = JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", k_ret)
if k_bin < 0 { return null }
// op
local k_op = s.indexOf("\"op\":", k_bin)
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_bin)
if k_op < 0 { return null }
local op = JsonFragBox.read_string_after(s, k_op + 5)
if op == null { return null }
if !(op == "+" || op == "-" || op == "*" || op == "/") { return null }
// lhs/rhs object starts
local klhs = s.indexOf("\"lhs\":{", k_bin)
local krhs = s.indexOf("\"rhs\":{", k_bin)
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_bin)
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_bin)
if klhs < 0 { return null }
// strictly ensure lhs node is Int by bounding search before rhs start
local ti = s.indexOf("\"type\":\"Int\"", klhs)
local ti = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs)
if ti < 0 { return null }
if krhs >= 0 && ti >= krhs { return null }
local kv_lhs = s.indexOf("\"value\":", ti)
local kv_lhs = JsonFragBox.index_of_from(s, "\"value\":", ti)
if kv_lhs < 0 { return null }
if krhs >= 0 && kv_lhs >= krhs { return null }
local lhs_val = JsonFragBox.read_int_after(s, kv_lhs + 8)
if lhs_val == null { return null }
// rhs int
if krhs < 0 { return null }
local ti2 = s.indexOf("\"type\":\"Int\"", krhs)
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs)
if ti2 < 0 { return null }
local kv_rhs = s.indexOf("\"value\":", ti2)
local kv_rhs = JsonFragBox.index_of_from(s, "\"value\":", ti2)
if kv_rhs < 0 { return null }
local rhs_val = JsonFragBox.read_int_after(s, kv_rhs + 8)
if rhs_val == null { return null }

View File

@ -10,26 +10,27 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
static box LowerReturnBinOpVarIntBox {
try_lower(program_json) {
local s = "" + program_json
local k_ret = s.indexOf("\"type\":\"Return\"")
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
if k_ret < 0 { return null }
local k_bin = s.indexOf("\"type\":\"Binary\"", k_ret)
local k_bin = JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", k_ret)
if k_bin < 0 { return null }
local k_op = s.indexOf("\"op\":", k_bin)
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_bin)
if k_op < 0 { return null }
local op = JsonFragBox.read_string_after(s, k_op + 5)
if op == null { return null }
if !(op == "+" || op == "-" || op == "*" || op == "/") { return null }
// Map op symbol to MIR op_kind via shared util
local kind = PatternUtilBox.map_binop(op); if kind == null { return null }
// Try Var + Int
local klhs_var = s.indexOf("\"lhs\":{\"type\":\"Var\"", k_bin)
local krhs_int = s.indexOf("\"rhs\":{\"type\":\"Int\"", k_bin)
local klhs_var = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\"", k_bin)
local krhs_int = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Int\"", k_bin)
local var_name = null
local rhs_val = null
if klhs_var >= 0 && krhs_int >= 0 {
local k_name = s.indexOf("\"name\":", klhs_var); if k_name < 0 { return null }
local k_name = JsonFragBox.index_of_from(s, "\"name\":", klhs_var); if k_name < 0 { return null }
var_name = JsonFragBox.read_string_after(s, k_name + 7)
local kvi = s.indexOf("\"type\":\"Int\"", krhs_int)
local kvi = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs_int)
if kvi >= 0 {
local kv = s.indexOf("\"value\":", kvi); if kv < 0 { return null }
local kv = JsonFragBox.index_of_from(s, "\"value\":", kvi); if kv < 0 { return null }
rhs_val = JsonFragBox.read_int_after(s, kv + 8)
}
if var_name != null && rhs_val != null {
@ -38,7 +39,7 @@ static box LowerReturnBinOpVarIntBox {
local b0 = new ArrayBox()
b0.push(MirSchemaBox.inst_const(1, var_val))
b0.push(MirSchemaBox.inst_const(2, rhs_val))
b0.push(MirSchemaBox.inst_binop(op == "+" ? "Add" : (op == "-" ? "Sub" : (op == "*" ? "Mul" : "Div")), 1, 2, 3))
b0.push(MirSchemaBox.inst_binop(kind, 1, 2, 3))
b0.push(MirSchemaBox.inst_ret(3))
local blocks = new ArrayBox(); blocks.push(MirSchemaBox.block(0, b0))
return MirSchemaBox.module(MirSchemaBox.fn_main(blocks))
@ -46,17 +47,17 @@ static box LowerReturnBinOpVarIntBox {
}
}
// Try Int + Var
local klhs_int = s.indexOf("\"lhs\":{\"type\":\"Int\"", k_bin)
local krhs_var = s.indexOf("\"rhs\":{\"type\":\"Var\"", k_bin)
local klhs_int = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Int\"", k_bin)
local krhs_var = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_bin)
var_name = null
local lhs_val = null
if klhs_int >= 0 && krhs_var >= 0 {
local kvi2 = s.indexOf("\"type\":\"Int\"", klhs_int)
local kvi2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs_int)
if kvi2 >= 0 {
local kv2 = s.indexOf("\"value\":", kvi2); if kv2 < 0 { return null }
local kv2 = JsonFragBox.index_of_from(s, "\"value\":", kvi2); if kv2 < 0 { return null }
lhs_val = JsonFragBox.read_int_after(s, kv2 + 8)
}
local k_name2 = s.indexOf("\"name\":", krhs_var); if k_name2 < 0 { return null }
local k_name2 = JsonFragBox.index_of_from(s, "\"name\":", krhs_var); if k_name2 < 0 { return null }
var_name = JsonFragBox.read_string_after(s, k_name2 + 7)
if lhs_val != null && var_name != null {
local var_val2 = PatternUtilBox.find_local_int_before(s, var_name, k_ret)
@ -64,7 +65,7 @@ static box LowerReturnBinOpVarIntBox {
local b1 = new ArrayBox()
b1.push(MirSchemaBox.inst_const(1, lhs_val))
b1.push(MirSchemaBox.inst_const(2, var_val2))
b1.push(MirSchemaBox.inst_binop(op == "+" ? "Add" : (op == "-" ? "Sub" : (op == "*" ? "Mul" : "Div")), 1, 2, 3))
b1.push(MirSchemaBox.inst_binop(kind, 1, 2, 3))
b1.push(MirSchemaBox.inst_ret(3))
local blocks = new ArrayBox(); blocks.push(MirSchemaBox.block(0, b1))
return MirSchemaBox.module(MirSchemaBox.fn_main(blocks))

View File

@ -7,20 +7,20 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
static box LowerReturnBinOpVarVarBox {
try_lower(program_json){
local s = "" + program_json
local k_ret = s.indexOf("\"type\":\"Return\""); if k_ret < 0 { return null }
local k_bin = s.indexOf("\"type\":\"Binary\"", k_ret); if k_bin < 0 { return null }
local k_op = s.indexOf("\"op\":", k_bin); if k_op < 0 { return null }
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0); if k_ret < 0 { return null }
local k_bin = JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", k_ret); if k_bin < 0 { return null }
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_bin); if k_op < 0 { return null }
local op = JsonFragBox.read_string_after(s, k_op + 5); if op == null { return null }
if !(op == "+" || op == "-" || op == "*" || op == "/") { return null }
local klhs = s.indexOf("\"lhs\":{\"type\":\"Var\"", k_bin); if klhs < 0 { return null }
local krhs = s.indexOf("\"rhs\":{\"type\":\"Var\"", k_bin); if krhs < 0 { return null }
local knl = s.indexOf("\"name\":", klhs); if knl < 0 { return null }
local kind = PatternUtilBox.map_binop(op); if kind == null { return null }
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\"", k_bin); if klhs < 0 { return null }
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_bin); if krhs < 0 { return null }
local knl = JsonFragBox.index_of_from(s, "\"name\":", klhs); if knl < 0 { return null }
local lname = JsonFragBox.read_string_after(s, knl + 7); if lname == null { return null }
local knr = s.indexOf("\"name\":", krhs); if knr < 0 { return null }
local knr = JsonFragBox.index_of_from(s, "\"name\":", krhs); if knr < 0 { return null }
local rname = JsonFragBox.read_string_after(s, knr + 7); if rname == null { return null }
local lval = PatternUtilBox.find_local_int_before(s, lname, k_ret); if lval == null { return null }
local rval = PatternUtilBox.find_local_int_before(s, rname, k_ret); if rval == null { return null }
local b0=new ArrayBox(); b0.push(MirSchemaBox.inst_const(1,lval)); b0.push(MirSchemaBox.inst_const(2,rval)); b0.push(MirSchemaBox.inst_binop(op == "+" ? "Add" : (op == "-" ? "Sub" : (op == "*" ? "Mul" : "Div")),1,2,3)); b0.push(MirSchemaBox.inst_ret(3))
local b0=new ArrayBox(); b0.push(MirSchemaBox.inst_const(1,lval)); b0.push(MirSchemaBox.inst_const(2,rval)); b0.push(MirSchemaBox.inst_binop(kind,1,2,3)); b0.push(MirSchemaBox.inst_ret(3))
local blocks=new ArrayBox(); blocks.push(MirSchemaBox.block(0,b0));
return MirSchemaBox.module(MirSchemaBox.fn_main(blocks))
}

View File

@ -5,16 +5,16 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
static box LowerReturnBoolBox {
try_lower(program_json) {
local s = "" + program_json
local k_ret = s.indexOf("\"type\":\"Return\"")
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
if k_ret < 0 { return null }
// Restrict to Return(expr=Bool …): require expr 開始直後に Bool が来る
// 例: "expr":{"type":"Bool","value":true}
local k_expr = s.indexOf("\"expr\":", k_ret)
local k_expr = JsonFragBox.index_of_from(s, "\"expr\":", k_ret)
if k_expr < 0 { return null }
local k_bool = s.indexOf("\"type\":\"Bool\"", k_expr)
local k_bool = JsonFragBox.index_of_from(s, "\"type\":\"Bool\"", k_expr)
if k_bool < 0 { return null }
// Ensure this Bool belongs to the same expr (次の '}' までに value があることを確認)
local k_val = s.indexOf("\"value\":", k_bool)
local k_val = JsonFragBox.index_of_from(s, "\"value\":", k_bool)
if k_val < 0 { return null }
local is_true = JsonFragBox.read_bool_after(s, k_val+8)
if is_true == null { return null }

View File

@ -6,11 +6,11 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
static box LowerReturnFloatBox {
try_lower(program_json) {
local s = "" + program_json
local k_ret = s.indexOf("\"type\":\"Return\"")
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
if k_ret < 0 { return null }
local k_float = s.indexOf("\"type\":\"Float\"", k_ret)
local k_float = JsonFragBox.index_of_from(s, "\"type\":\"Float\"", k_ret)
if k_float < 0 { return null }
local k_val = s.indexOf("\"value\":", k_float)
local k_val = JsonFragBox.index_of_from(s, "\"value\":", k_float)
if k_val < 0 { return null }
local fstr = JsonFragBox.read_float_after(s, k_val+8)
if fstr == null { return null }

View File

@ -5,14 +5,14 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
static box LowerReturnIntBox {
try_lower(program_json) {
local s = "" + program_json
local k_ret = s.indexOf("\"type\":\"Return\"")
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
if k_ret < 0 { return null }
// Find expr object
local k_expr = s.indexOf("\"expr\":{", k_ret)
local k_expr = JsonFragBox.index_of_from(s, "\"expr\":{", k_ret)
if k_expr < 0 { return null }
// Check that expr.type is directly Int (not Binary, Logical, Var, etc)
local k_type_start = k_expr + 8
local k_type = s.indexOf("\"type\":", k_type_start)
local k_type = JsonFragBox.index_of_from(s, "\"type\":", k_type_start)
if k_type < 0 || k_type > k_type_start + 20 { return null }
// Extract type value to verify it's "Int"
local k_type_val = k_type + 7
@ -28,9 +28,9 @@ static box LowerReturnIntBox {
if k_type_val + 3 >= n { return null }
if s.substring(k_type_val+3, k_type_val+4) != "\"" { return null }
// Now extract the value
local k_int = s.indexOf("\"type\":\"Int\"", k_expr)
local k_int = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_expr)
if k_int < 0 { return null }
local kv = s.indexOf("\"value\":", k_int); if kv < 0 { return null }
local kv = JsonFragBox.index_of_from(s, "\"value\":", k_int); if kv < 0 { return null }
local val = JsonFragBox.read_int_after(s, kv + 8)
if val == null { return null }
local debug_on = 0

View File

@ -11,7 +11,7 @@ static box LowerReturnLogicalBox {
try_lower(program_json) {
local s = "" + program_json
local k_ret = s.indexOf("\"type\":\"Return\"")
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
if k_ret < 0 { return null }
local k_log = JsonFragBox.index_of_from(s, "\"type\":\"Logical\"", k_ret)
if k_log < 0 { return null }

View File

@ -8,12 +8,12 @@ using selfhost.vm.helpers.method_alias_policy as MethodAliasPolicy
static box LowerReturnMethodArrayMapBox {
try_lower(program_json) {
local s = "" + program_json
local k_ret = s.indexOf("\"type\":\"Return\""); if k_ret < 0 { return null }
local k_m = s.indexOf("\"type\":\"Method\"", k_ret); if k_m < 0 { return null }
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0); if k_ret < 0 { return null }
local k_m = JsonFragBox.index_of_from(s, "\"type\":\"Method\"", k_ret); if k_m < 0 { return null }
// receiver must be Var(name)
local k_recv = s.indexOf("\"recv\":{\"type\":\"Var\"", k_m); if k_recv < 0 { return null }
local k_recv = JsonFragBox.index_of_from(s, "\"recv\":{\"type\":\"Var\"", k_m); if k_recv < 0 { return null }
local method = null
{ local km = s.indexOf("\"method\":\"", k_m); if km < 0 { return null } method = JsonFragBox.read_string_after(s, km) }
{ local km = JsonFragBox.index_of_from(s, "\"method\":\"", k_m); if km < 0 { return null } method = JsonFragBox.read_string_after(s, km) }
// Standardize: generate 'size' (len/length are accepted aliases at receiver)
method = MethodAliasPolicy.normalize_size(method)
// Allow basic methods
@ -23,91 +23,56 @@ static box LowerReturnMethodArrayMapBox {
local b0 = new ArrayBox()
// Receiver placeholder (Var resolve未実装のため 0 を置く)
b0.push(MirSchemaBox.inst_const(1, 0))
local k_args = s.indexOf("\"args\":", k_m)
local k_args = JsonFragBox.index_of_from(s, "\"args\":", k_m)
local next_id = 2
if k_args >= 0 {
// first arg: Int or Var(Int)
local k_i1 = s.indexOf("\"type\":\"Int\"", k_args)
local k_v1 = s.indexOf("\"type\":\"Var\"", k_args)
local k_i1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_args)
local k_v1 = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_args)
if k_i1 >= 0 && (k_v1 < 0 || k_i1 < k_v1) {
// read numeric after value:
local k_val1 = s.indexOf("\"value\":", k_i1)
local k_val1 = JsonFragBox.index_of_from(s, "\"value\":", k_i1)
if k_val1 >= 0 {
local v1 = JsonFragBox.read_int_after(s, k_val1 + 8)
if v1 != null { b0.push(MirSchemaBox.inst_const(next_id, v1)) args_ids.push(next_id) next_id = next_id + 1 }
}
// second arg after first
local k_i2 = s.indexOf("\"type\":\"Int\"", k_i1 + 1)
local k_v2a = s.indexOf("\"type\":\"Var\"", k_i1 + 1)
local k_i2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_i1 + 1)
local k_v2a = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_i1 + 1)
if k_i2 >= 0 {
local k_v2 = s.indexOf("\"value\":", k_i2)
local k_v2 = JsonFragBox.index_of_from(s, "\"value\":", k_i2)
if k_v2 >= 0 { local v2 = JsonFragBox.read_int_after(s, k_v2 + 8); if v2 != null { b0.push(MirSchemaBox.inst_const(next_id, v2)) args_ids.push(next_id) next_id = next_id + 1 } }
} else if k_v2a >= 0 {
// second arg is Var: resolve Local Int value
local kn = s.indexOf("\"name\":\"", k_v2a)
local kn = JsonFragBox.index_of_from(s, "\"name\":\"", k_v2a)
if kn >= 0 {
local name2 = JsonFragBox.read_string_after(s, kn)
// scan backwards for Local name2 Int
local pos = 0; local last = -1
loop(true) {
local kL = s.indexOf("\"type\":\"Local\"", pos)
if kL < 0 || kL >= k_m { break }
local nm = null
{
local kn2 = s.indexOf("\"name\":\"", kL)
if kn2 >= 0 {
local iii = kn2 + 8; local nnn = s.length(); local jjj = iii
loop(jjj < nnn) { if s.substring(jjj,jjj+1) == '"' { break } jjj = jjj + 1 }
nm = s.substring(iii, jjj)
}
}
if nm != null && nm == name2 { last = kL }
pos = kL + 1
}
if last >= 0 {
local ki = s.indexOf("\"type\":\"Int\"", last)
if ki >= 0 && ki < k_m {
local kv = s.indexOf("\"value\":", ki)
if kv >= 0 { local v = JsonFragBox.read_int_after(s, kv + 8); if v != null { b0.push(MirSchemaBox.inst_const(next_id, v)) args_ids.push(next_id) next_id = next_id + 1 } }
}
}
local v = PatternUtilBox.find_local_int_before(s, name2, k_m)
if v != null { b0.push(MirSchemaBox.inst_const(next_id, v)) args_ids.push(next_id) next_id = next_id + 1 }
}
}
} else if k_v1 >= 0 && (k_i1 < 0 || k_v1 < k_i1) {
// first arg is Var: resolve Local value (Int/Bool/Float/String)
local kn = s.indexOf("\"name\":\"", k_v1)
local kn = JsonFragBox.index_of_from(s, "\"name\":\"", k_v1)
if kn >= 0 {
local namev = JsonFragBox.read_string_after(s, kn)
// find last Local namev Int before method
local pos2 = 0; local last2 = -1
loop(true) {
local kL2 = s.indexOf("\"type\":\"Local\"", pos2)
if kL2 < 0 || kL2 >= k_m { break }
local nm2 = null
{
local knm = s.indexOf("\"name\":\"", kL2)
if knm >= 0 {
local iii2 = knm + 8; local nnn2 = s.length(); local jjj2 = iii2
loop(jjj2 < nnn2) { if s.substring(jjj2,jjj2+1) == '"' { break } jjj2 = jjj2 + 1 }
nm2 = s.substring(iii2, jjj2)
}
}
if nm2 != null && nm2 == namev { last2 = kL2 }
pos2 = kL2 + 1
// Prefer exact-name Local lookups via PatternUtilBox
// Int / Bool / Float / String (in this order)
{
local vi = PatternUtilBox.find_local_int_before(s, namev, k_m)
if vi != null { b0.push(MirSchemaBox.inst_const(next_id, vi)) args_ids.push(next_id) next_id = next_id + 1 }
}
if last2 >= 0 {
// Int
local ki3 = s.indexOf("\"type\":\"Int\"", last2)
if ki3 >= 0 && ki3 < k_m { local kv3 = s.indexOf("\"value\":", ki3); if kv3 >= 0 { local v = JsonFragBox.read_int_after(s, kv3 + 8); if v != null { b0.push(MirSchemaBox.inst_const(next_id, v)) args_ids.push(next_id) next_id = next_id + 1 } } }
// Bool
local kb3 = s.indexOf("\"type\":\"Bool\"", last2)
if kb3 >= 0 && kb3 < k_m { local kvb = s.indexOf("\"value\":", kb3); if kvb >= 0 { local vb = JsonFragBox.read_bool_after(s, kvb + 8); if vb != null { b0.push(MirSchemaBox.inst_const(next_id, vb)) args_ids.push(next_id) next_id = next_id + 1 } } }
// Float
local kf3 = s.indexOf("\"type\":\"Float\"", last2)
if kf3 >= 0 && kf3 < k_m { local kvf = s.indexOf("\"value\":", kf3); if kvf >= 0 { local fv = JsonFragBox.read_float_after(s, kvf + 8); if fv != null { b0.push(MirSchemaBox.inst_const_f64(next_id, fv)) args_ids.push(next_id) next_id = next_id + 1 } } }
// String
local ks3 = s.indexOf("\"type\":\"String\"", last2)
if ks3 >= 0 && ks3 < k_m { local kvs = s.indexOf("\"value\":\"", ks3); if kvs >= 0 { local sv = JsonFragBox.read_string_after(s, kvs + 8); if sv != null { b0.push(MirSchemaBox.inst_const_str(next_id, sv)) args_ids.push(next_id) next_id = next_id + 1 } } }
{
local vb = PatternUtilBox.find_local_bool_before(s, namev, k_m)
if vb != null { b0.push(MirSchemaBox.inst_const(next_id, vb)) args_ids.push(next_id) next_id = next_id + 1 }
}
{
local vf = PatternUtilBox.find_local_float_before(s, namev, k_m)
if vf != null { b0.push(MirSchemaBox.inst_const_f64(next_id, vf)) args_ids.push(next_id) next_id = next_id + 1 }
}
{
local vs = PatternUtilBox.find_local_string_before(s, namev, k_m)
if vs != null { b0.push(MirSchemaBox.inst_const_str(next_id, vs)) args_ids.push(next_id) next_id = next_id + 1 }
}
}
}

View File

@ -6,11 +6,11 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
static box LowerReturnStringBox {
try_lower(program_json) {
local s = "" + program_json
local k_ret = s.indexOf("\"type\":\"Return\"")
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
if k_ret < 0 { return null }
local k_str = s.indexOf("\"type\":\"String\"", k_ret)
local k_str = JsonFragBox.index_of_from(s, "\"type\":\"String\"", k_ret)
if k_str < 0 { return null }
local k_val = s.indexOf("\"value\":", k_str)
local k_val = JsonFragBox.index_of_from(s, "\"value\":", k_str)
if k_val < 0 { return null }
local sval = JsonFragBox.read_string_after(s, k_val+8)
if sval == null { return null }

View File

@ -7,25 +7,25 @@ static box LowerReturnVarLocalBox {
try_lower(program_json) {
local s = "" + program_json
// Find Local with name:"x" and expr Int value
local k_loc = s.indexOf("\"type\":\"Local\"")
local k_loc = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", 0)
if k_loc < 0 { return null }
// Extract name
local k_name = s.indexOf("\"name\":", k_loc); if k_name < 0 { return null }
local k_name = JsonFragBox.index_of_from(s, "\"name\":", k_loc); if k_name < 0 { return null }
local name = JsonFragBox.read_string_after(s, k_name + 5)
if name == null || name == "" { return null }
// Ensure expr Int after this Local
local k_int = s.indexOf("\"type\":\"Int\"", k_loc)
local k_int = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_loc)
if k_int < 0 { return null }
local kv = s.indexOf("\"value\":", k_int); if kv < 0 { return null }
local kv = JsonFragBox.index_of_from(s, "\"value\":", k_int); if kv < 0 { return null }
local val = JsonFragBox.read_int_after(s, kv + 8)
if val == null { return null }
// Following Return Var(name)
local k_ret = s.indexOf("\"type\":\"Return\"", k_loc)
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", k_loc)
if k_ret < 0 { return null }
// Verify Var(name)
local k_var = s.indexOf("\"type\":\"Var\"", k_ret)
local k_var = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_ret)
if k_var < 0 { return null }
local k_vn = s.indexOf("\"name\":", k_var); if k_vn < 0 { return null }
local k_vn = JsonFragBox.index_of_from(s, "\"name\":", k_var); if k_vn < 0 { return null }
local vname = JsonFragBox.read_string_after(s, k_vn + 5)
if vname == null || vname != name { return null }

View File

@ -5,6 +5,7 @@ using selfhost.shared.common.string_helpers as StringHelpers
static box PatternUtilBox {
map_cmp(sym) { if sym=="<" {return "Lt"} if sym==">" {return "Gt"} if sym=="<=" {return "Le"} if sym==">=" {return "Ge"} if sym=="==" {return "Eq"} if sym=="!=" {return "Ne"} return null }
map_binop(sym) { if sym=="+" {return "Add"} if sym=="-" {return "Sub"} if sym=="*" {return "Mul"} if sym=="/" {return "Div"} return null }
// Normalize (op, swapped, limit) → (cmp, limit') where cmp in {Lt, Le, Gt, Ge}
// swapped=0: i ? L, swapped=1: L ? i
normalize_cmp_limit(op, swapped, limit_str) {
@ -50,9 +51,9 @@ static box PatternUtilBox {
// Bound the search between this Local and the next Local/before_pos
local next = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last + 1)
if next < 0 || next > before_pos { next = before_pos }
local ki = s.indexOf("\"type\":\"Int\"", last)
local ki = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", last)
if ki < 0 || ki >= next { return null }
local kv = s.indexOf("\"value\":", ki)
local kv = JsonFragBox.index_of_from(s, "\"value\":", ki)
if kv < 0 || kv >= next { return null }
return JsonFragBox.read_int_after(s, kv+8)
}
@ -62,14 +63,64 @@ static box PatternUtilBox {
if last<0 { return null }
local next = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last + 1)
if next < 0 || next > before_pos { next = before_pos }
local kb = s.indexOf("\"type\":\"Bool\"", last)
local kb = JsonFragBox.index_of_from(s, "\"type\":\"Bool\"", last)
if kb < 0 || kb >= next { return null }
local kv = s.indexOf("\"value\":", kb)
local kv = JsonFragBox.index_of_from(s, "\"value\":", kb)
if kv < 0 || kv >= next { return null }
// JSON v0 uses 0/1 for bool values, not true/false literals
return JsonFragBox.read_int_after(s, kv+8)
}
// Find the last Local(String) with given name before a given position.
// Returns raw string or null when not found.
find_local_string_before(s, name, before_pos) {
local pos=0; local last=-1
loop(true){
local k=JsonFragBox.index_of_from(s, "\"type\":\"Local\"",pos)
if k<0||k>=before_pos{break}
local kn=JsonFragBox.index_of_from(s, "\"name\":\"",k)
if kn>=0{
local ii=kn+8; local nn=(""+s).length(); local jj=ii
loop(jj<nn){ if (""+s).substring(jj,jj+1)=="\"" {break} jj=jj+1 }
if (""+s).substring(ii,jj)==name { last=k }
}
pos=k+1
}
if last<0 { return null }
local next=JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last+1)
if next<0||next>before_pos{ next=before_pos }
local ts=(""+s).indexOf("\"type\":\"String\"", last)
if ts<0||ts>=next { return null }
local kv=(""+s).indexOf("\"value\":\"", ts)
if kv<0||kv>=next { return null }
return JsonFragBox.read_string_after(s, kv+8)
}
// Find the last Local(Float) with given name before a given position.
// Returns float string (as scanned) or null when not found.
find_local_float_before(s, name, before_pos) {
local pos=0; local last=-1
loop(true){
local k=JsonFragBox.index_of_from(s, "\"type\":\"Local\"",pos)
if k<0||k>=before_pos{break}
local kn=JsonFragBox.index_of_from(s, "\"name\":\"",k)
if kn>=0{
local ii=kn+8; local nn=(""+s).length(); local jj=ii
loop(jj<nn){ if (""+s).substring(jj,jj+1)=="\"" {break} jj=jj+1 }
if (""+s).substring(ii,jj)==name { last=k }
}
pos=k+1
}
if last<0 { return null }
local next=JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last+1)
if next<0||next>before_pos{ next=before_pos }
local tf=(""+s).indexOf("\"type\":\"Float\"", last)
if tf<0||tf>=next { return null }
local kv=(""+s).indexOf("\"value\":", tf)
if kv<0||kv>=next { return null }
return JsonFragBox.read_float_after(s, kv+8)
}
// Find the last Local(Int) before a given position (name-agnostic).
// Returns string digits or null when not found.
find_any_local_int_before(s, before_pos) {