// 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 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