- Add HAKO_TRACE_EXECUTION to trace executor route - Rust hv1_inline: stderr [trace] executor: hv1_inline (rust) - Hakovm dispatcher: stdout [trace] executor: hakovm (hako) - test_runner: trace lines for hv1_inline/core/hakovm routes - Add HAKO_VERIFY_SHOW_LOGS and HAKO_DEBUG=1 (enables both) - verify_v1_inline_file() log passthrough with numeric rc extraction - test_runner exports via HAKO_DEBUG - Canary expansion under phase2170 (state spec) - Array: push×5/10 → size, len/length alias, per‑recv/global, flow across blocks - Map: set dup-key non-increment, value_state get/has - run_all.sh: unify, remove SKIPs; all PASS - Docs - ENV_VARS.md: add Debug/Tracing toggles and examples - PLAN.md/CURRENT_TASK.md: mark 21.7 green, add Quickstart lines All changes gated by env vars; default behavior unchanged.
106 lines
4.0 KiB
Plaintext
106 lines
4.0 KiB
Plaintext
// tools/hako_parser/ast_emit.hako - HakoAstEmitBox (MVP)
|
|
// no external helpers; keep emission self-contained
|
|
|
|
static box HakoAstEmitBox {
|
|
// Emit minimal AST JSON v0 from MapBox (stable order)
|
|
to_json(ast) {
|
|
if ast == null { return "{\"boxes\":[],\"uses\":[]}" }
|
|
local uses = me._sort_strings(ast.get("uses"))
|
|
local boxes = me._sort_boxes(ast.get("boxes"))
|
|
local out = "{\"uses\":" + me._emit_array(uses) + ",\"boxes\":" + me._emit_boxes(boxes) + "}"
|
|
return out
|
|
}
|
|
_emit_array(arr) {
|
|
if arr == null { return "[]" }
|
|
local s = "["
|
|
local n = arr.size()
|
|
local i = 0
|
|
while i < n {
|
|
local v = arr.get(i)
|
|
s = s + me._json_quote(v)
|
|
if i != n-1 { s = s + "," }
|
|
i = i + 1
|
|
}
|
|
return s + "]"
|
|
}
|
|
_emit_boxes(boxes) {
|
|
if boxes == null { return "[]" }
|
|
local s = "["
|
|
local n = boxes.size()
|
|
local i = 0
|
|
while i < n {
|
|
local b = boxes.get(i)
|
|
local name = me._json_quote(b.get("name"))
|
|
local is_static = b.get("is_static")
|
|
local methods = me._emit_methods(me._sort_methods(b.get("methods")))
|
|
s = s + "{\"name\":" + name + ",\"is_static\":" + me._itoa(is_static) + ",\"methods\":" + methods + "}"
|
|
if i != n-1 { s = s + "," }
|
|
i = i + 1
|
|
}
|
|
return s + "]"
|
|
}
|
|
_emit_methods(methods) {
|
|
if methods == null { return "[]" }
|
|
local s = "["
|
|
local n = methods.size()
|
|
local i = 0
|
|
while i < n {
|
|
local m = methods.get(i)
|
|
local name = me._json_quote(m.get("name"))
|
|
local arity = me._itoa(m.get("arity"))
|
|
// span is integer line number
|
|
local spanv = m.get("span"); if spanv == null { spanv = 0 }
|
|
s = s + "{\"name\":" + name + ",\"arity\":" + arity + ",\"span\":" + me._itoa(spanv) + "}"
|
|
if i != n-1 { s = s + "," }
|
|
i = i + 1
|
|
}
|
|
return s + "]"
|
|
}
|
|
// Helpers: sorting (naive O(n^2))
|
|
_sort_strings(arr) { if arr == null { return new ArrayBox() }
|
|
local out = new ArrayBox(); local i=0; while i<arr.size() { out.push(arr.get(i)); i=i+1 }
|
|
// selection sort
|
|
local n = out.size(); local a=0; while a<n { local b=a+1; while b<n { if out.get(b) < out.get(a) { local tmp=out.get(a); out.set(a,out.get(b)); out.set(b,tmp) } b=b+1 } a=a+1 }
|
|
return out }
|
|
_sort_boxes(boxes) { if boxes == null { return new ArrayBox() }
|
|
local out = new ArrayBox(); local i=0; while i<boxes.size() { out.push(boxes.get(i)); i=i+1 }
|
|
local n=out.size(); local a=0; while a<n { local b=a+1; while b<n { if out.get(b).get("name") < out.get(a).get("name") { local tmp=out.get(a); out.set(a,out.get(b)); out.set(b,tmp) } b=b+1 } a=a+1 }
|
|
return out }
|
|
_sort_methods(methods) { if methods == null { return new ArrayBox() }
|
|
local out = new ArrayBox(); local i=0; while i<methods.size() { out.push(methods.get(i)); i=i+1 }
|
|
local n=out.size(); local a=0; while a<n { local b=a+1; while b<n {
|
|
local ma=out.get(a); local mb=out.get(b)
|
|
local ka = ma.get("name") + "/" + me._itoa(ma.get("arity"))
|
|
local kb = mb.get("name") + "/" + me._itoa(mb.get("arity"))
|
|
if kb < ka { local tmp=out.get(a); out.set(a,out.get(b)); out.set(b,tmp) }
|
|
b=b+1 } a=a+1 }
|
|
return out }
|
|
// Local helpers (self-contained)
|
|
_itoa(n) {
|
|
local v = 0 + n; if v == 0 { return "0" }
|
|
local digits = "0123456789"; local out = ""; local tmp = ""
|
|
while v > 0 { local d = v % 10; tmp = digits.substring(d,d+1) + tmp; v = v / 10 }
|
|
out = tmp; return out
|
|
}
|
|
_json_quote(s) {
|
|
if s == null { return "\"\"" }
|
|
local out = ""; local i=0; local n=s.length()
|
|
while i<n {
|
|
local ch = s.substring(i,i+1)
|
|
if ch == "\\" { out = out + "\\\\" } else {
|
|
if ch == "\"" { out = out + "\\\"" } else {
|
|
if ch == "\n" { out = out + "\\n" } else {
|
|
if ch == "\r" { out = out + "\\r" } else {
|
|
if ch == "\t" { out = out + "\\t" } else { out = out + ch }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
i = i + 1
|
|
}
|
|
return "\"" + out + "\""
|
|
}
|
|
}
|
|
|
|
static box HakoAstEmitMain { method main(args) { return 0 } }
|