feat(phase22.1): JsonFrag.last_index_of_from() unified search refactor
- Add: JsonFragBox.last_index_of_from(hay, needle, pos) method
- VM fallback: simple reverse search using substring + lastIndexOf
- Replaces hand-written lastIndexOf calls in MIR builder
- Refactor: lower_loop_sum_bc_box.hako uses unified method
- Line 75: Break sentinel backward search
- Line 113: Continue sentinel backward search
- Eliminates 2 hand-written lastIndexOf calls
- Test: json_frag_last_index_of_from_canary_vm.sh
- Loop with break(i==3) and continue(i==2)
- Expect: 0+1+4 = 5 (skip 2, break at 3)
- Status: PASS ✅
Phase 22.1 ultrathink cleanup: code consolidation complete
This commit is contained in:
@ -72,7 +72,7 @@ static box LowerLoopSumBcBox {
|
|||||||
local kb = JsonFragBox.index_of_from(s, "\"type\":\"Break\"", k_loop)
|
local kb = JsonFragBox.index_of_from(s, "\"type\":\"Break\"", k_loop)
|
||||||
if kb >= 0 {
|
if kb >= 0 {
|
||||||
// Find nearest previous Compare and grab rhs Int
|
// Find nearest previous Compare and grab rhs Int
|
||||||
local kbc = s.lastIndexOf("\"type\":\"Compare\"", kb)
|
local kbc = JsonFragBox.last_index_of_from(s, "\"type\":\"Compare\"", kb)
|
||||||
if kbc >= 0 {
|
if kbc >= 0 {
|
||||||
// Ensure op=="==" and lhs Var i
|
// Ensure op=="==" and lhs Var i
|
||||||
local kop = JsonFragBox.index_of_from(s, "\"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) }
|
||||||
@ -110,7 +110,7 @@ static box LowerLoopSumBcBox {
|
|||||||
{
|
{
|
||||||
local kc = JsonFragBox.index_of_from(s, "\"type\":\"Continue\"", k_loop)
|
local kc = JsonFragBox.index_of_from(s, "\"type\":\"Continue\"", k_loop)
|
||||||
if kc >= 0 {
|
if kc >= 0 {
|
||||||
local kcc = s.lastIndexOf("\"type\":\"Compare\"", kc)
|
local kcc = JsonFragBox.last_index_of_from(s, "\"type\":\"Compare\"", kc)
|
||||||
if kcc >= 0 {
|
if kcc >= 0 {
|
||||||
local kop2 = JsonFragBox.index_of_from(s, "\"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 == "==" {
|
if cop != null && cop == "==" {
|
||||||
|
|||||||
@ -124,6 +124,20 @@ static box JsonFragBox {
|
|||||||
if idx < 0 { return -1 }
|
if idx < 0 { return -1 }
|
||||||
return p2 + idx
|
return p2 + idx
|
||||||
}
|
}
|
||||||
|
last_index_of_from(hay, needle, pos) {
|
||||||
|
// VM fallback: reverse search from pos backwards to start
|
||||||
|
if hay == null || needle == null { return -1 }
|
||||||
|
local s = "" + hay
|
||||||
|
local n = s.length()
|
||||||
|
local p2 = pos
|
||||||
|
if p2 < 0 { return -1 }
|
||||||
|
if p2 >= n { p2 = n - 1 }
|
||||||
|
// Extract substring from 0 to pos (inclusive)
|
||||||
|
local substr = s.substring(0, p2 + 1)
|
||||||
|
// Find last occurrence of needle in substring
|
||||||
|
local idx = substr.lastIndexOf(needle)
|
||||||
|
return idx
|
||||||
|
}
|
||||||
read_digits(text, pos) { return StringHelpers.read_digits(text, pos) }
|
read_digits(text, pos) { return StringHelpers.read_digits(text, pos) }
|
||||||
_str_to_int(s) { return StringHelpers.to_i64(s) }
|
_str_to_int(s) { return StringHelpers.to_i64(s) }
|
||||||
_to_bool10(ch) { if ch == "t" { return 1 } if ch == "f" { return 0 } return null }
|
_to_bool10(ch) { if ch == "t" { return 1 } if ch == "f" { return 0 } return null }
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# JsonFrag.last_index_of_from() canary — Loop with break/continue → expect 0+1+4 = 5
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||||
|
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||||
|
|
||||||
|
tmp_json="/tmp/program_json_frag_last_index_$$.json"
|
||||||
|
cat > "$tmp_json" <<'JSON'
|
||||||
|
{
|
||||||
|
"version": 0,
|
||||||
|
"kind": "Program",
|
||||||
|
"body": [
|
||||||
|
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||||
|
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||||
|
{ "type":"Loop",
|
||||||
|
"cond": {"type":"Compare","op":"<","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":5}},
|
||||||
|
"body": [
|
||||||
|
{ "type":"If", "cond": {"type":"Compare","op":"==","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":2}},
|
||||||
|
"then": [ { "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":1}} }, { "type":"Continue" } ],
|
||||||
|
"else": [ ]
|
||||||
|
},
|
||||||
|
{ "type":"If", "cond": {"type":"Compare","op":"==","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":3}},
|
||||||
|
"then": [ { "type":"Break" } ],
|
||||||
|
"else": [ ]
|
||||||
|
},
|
||||||
|
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Var","name":"i"}} },
|
||||||
|
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":1}} }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
set +e
|
||||||
|
HAKO_VERIFY_PRIMARY=core verify_mir_rc "$tmp_json" >/dev/null 2>&1
|
||||||
|
rc=$?
|
||||||
|
set -e
|
||||||
|
rm -f "$tmp_json" || true
|
||||||
|
|
||||||
|
if [ "$rc" -eq 5 ]; then
|
||||||
|
echo "[PASS] json_frag_last_index_of_from_canary_vm"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "[FAIL] json_frag_last_index_of_from_canary_vm (rc=$rc, expect 5)" >&2; exit 1
|
||||||
Reference in New Issue
Block a user