2025-11-08 15:49:25 +09:00
// tools/hako_parser/ast_emit.hako - HakoAstEmitBox (MVP)
2025-11-08 23:45:29 +09:00
// no external helpers; keep emission self-contained
2025-11-07 19:32:44 +09:00
static box HakoAstEmitBox {
2025-11-08 00:46:34 +09:00
// Emit minimal AST JSON v0 from MapBox (stable order)
2025-11-07 19:32:44 +09:00
to_json(ast) {
2025-11-08 00:46:34 +09:00
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
2025-11-07 19:32:44 +09:00
}
2025-11-08 00:46:34 +09:00
_emit_array(arr) {
if arr == null { return "[]" }
local s = "["
local n = arr.size()
local i = 0
while i < n {
local v = arr.get(i)
2025-11-08 23:45:29 +09:00
s = s + me._json_quote(v)
2025-11-08 00:46:34 +09:00
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)
2025-11-08 23:45:29 +09:00
local name = me._json_quote(b.get("name"))
2025-11-08 00:46:34 +09:00
local is_static = b.get("is_static")
local methods = me._emit_methods(me._sort_methods(b.get("methods")))
2025-11-08 23:45:29 +09:00
s = s + "{\"name\":" + name + ",\"is_static\":" + me._itoa(is_static) + ",\"methods\":" + methods + "}"
2025-11-08 00:46:34 +09:00
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)
2025-11-08 23:45:29 +09:00
local name = me._json_quote(m.get("name"))
local arity = me._itoa(m.get("arity"))
2025-11-08 00:46:34 +09:00
// span is integer line number
local spanv = m.get("span"); if spanv == null { spanv = 0 }
2025-11-08 23:45:29 +09:00
s = s + "{\"name\":" + name + ",\"arity\":" + arity + ",\"span\":" + me._itoa(spanv) + "}"
2025-11-08 00:46:34 +09:00
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)
2025-11-08 23:45:29 +09:00
local ka = ma.get("name") + "/" + me._itoa(ma.get("arity"))
local kb = mb.get("name") + "/" + me._itoa(mb.get("arity"))
2025-11-08 00:46:34 +09:00
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 }
2025-11-08 23:45:29 +09:00
// 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 + "\""
}
2025-11-07 19:32:44 +09:00
}
static box HakoAstEmitMain { method main(args) { return 0 } }