主な変更: - ✅ HC011 (dead methods) 実装・テスト緑 - ✅ HC016 (unused alias) 実装・テスト緑 - ✅ HC017 (non-ascii quotes) 実装完了 - 🔧 tokenizer/parser_core 強化(AST優先ルート) - 🛡️ plugin_guard.rs 追加(stderr専用出力) - 📋 テストインフラ整備(run_tests.sh改善) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
81 lines
3.2 KiB
Plaintext
81 lines
3.2 KiB
Plaintext
// tools/hako_parser/ast_emit.hako — HakoAstEmitBox (MVP)
|
|
using selfhost.shared.common.string_helpers as Str
|
|
|
|
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 + Str.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 = Str.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\":" + Str.int_to_str(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 = Str.json_quote(m.get("name"))
|
|
local arity = Str.int_to_str(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\":" + Str.int_to_str(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") + "/" + Str.int_to_str(ma.get("arity"))
|
|
local kb = mb.get("name") + "/" + Str.int_to_str(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 }
|
|
}
|
|
|
|
static box HakoAstEmitMain { method main(args) { return 0 } }
|