163 lines
5.2 KiB
Plaintext
163 lines
5.2 KiB
Plaintext
// Stage1UsingResolverBox — resolve `using` statements for Stage‑1 pipelines
|
||
// Responsibilities:
|
||
// - Collect line-based using declarations via UsingCollectorBox.
|
||
// - Resolve namespace targets against `nyash.toml` `[modules]` entries (fed via env).
|
||
// - Read the referenced .hako files and return a concatenated prefix for Stage‑B.
|
||
//
|
||
// Env requirements:
|
||
// - HAKO_STAGEB_MODULES_LIST: `name=path` entries joined by "|||".
|
||
// - NYASH_ROOT: absolute path to repo root (for resolving relative paths).
|
||
|
||
using lang.compiler.parser.using.using_collector_box as UsingCollectorBox
|
||
using lang.compiler.parser.scan.parser_common_utils_box as ParserCommonUtilsBox
|
||
using selfhost.shared.json.utils.json_frag as JsonFragBox
|
||
|
||
static box Stage1UsingResolverBox {
|
||
resolve_for_source(src) {
|
||
// Shallow recursion guard to prevent accidental self-recursion in Stage‑1 using resolver.
|
||
{
|
||
local depth = env.get("HAKO_STAGEB_USING_DEPTH")
|
||
if depth != null && ("" + depth) != "0" {
|
||
print("[stageb/recursion] Stage1UsingResolverBox.resolve_for_source recursion detected")
|
||
return ""
|
||
}
|
||
env.set("HAKO_STAGEB_USING_DEPTH", "1")
|
||
}
|
||
|
||
if src == null { return "" }
|
||
local apply_flag = env.get("HAKO_STAGEB_APPLY_USINGS")
|
||
if apply_flag != null && ("" + apply_flag) == "0" { return "" }
|
||
|
||
local entries = me._collect_using_entries(src)
|
||
if entries == null || entries.length() == 0 { return "" }
|
||
|
||
local modules = me._build_module_map()
|
||
local seen = new MapBox()
|
||
local prefix = ""
|
||
|
||
local i = 0
|
||
local n = entries.length()
|
||
loop(i < n) {
|
||
local entry = entries.get(i)
|
||
local name = "" + entry.get("name")
|
||
if name == "" { i = i + 1 continue }
|
||
|
||
local path = entry.get("path")
|
||
if path == null || ("" + path) == "" {
|
||
path = me._lookup_module_path(modules, name)
|
||
} else {
|
||
path = "" + path
|
||
}
|
||
if path == null || path == "" { i = i + 1 continue }
|
||
|
||
local abs_path = me._abs_path(path)
|
||
if abs_path == null || abs_path == "" { i = i + 1 continue }
|
||
if seen.get(abs_path) == "1" { i = i + 1 continue }
|
||
|
||
local code = me._read_file(abs_path)
|
||
if code == null { i = i + 1 continue }
|
||
|
||
seen.set(abs_path, "1")
|
||
prefix = prefix + "\n" + code + "\n"
|
||
i = i + 1
|
||
}
|
||
|
||
// Clear depth guard before returning
|
||
env.set("HAKO_STAGEB_USING_DEPTH", "0")
|
||
return prefix
|
||
}
|
||
|
||
// Collect entries from UsingCollectorBox JSON output.
|
||
_collect_using_entries(src) {
|
||
local json = UsingCollectorBox.collect(src)
|
||
if json == null || json == "" || json == "[]" { return null }
|
||
local out = new ArrayBox()
|
||
local pos = 0
|
||
local n = json.length()
|
||
loop(pos < n) {
|
||
local name_idx = JsonFragBox.index_of_from(json, "\"name\":\"", pos)
|
||
if name_idx < 0 { break }
|
||
local name = JsonFragBox.read_string_after(json, name_idx + 7)
|
||
local obj_end = JsonFragBox.index_of_from(json, "}", name_idx)
|
||
if obj_end < 0 { obj_end = n }
|
||
|
||
local path = null
|
||
local path_idx = JsonFragBox.index_of_from(json, "\"path\":\"", name_idx)
|
||
if path_idx >= 0 && path_idx < obj_end {
|
||
path = JsonFragBox.read_string_after(json, path_idx + 7)
|
||
}
|
||
|
||
local entry = new MapBox()
|
||
entry.set("name", name)
|
||
if path != null { entry.set("path", path) }
|
||
out.push(entry)
|
||
pos = obj_end + 1
|
||
}
|
||
return out
|
||
}
|
||
|
||
_build_module_map() {
|
||
local map = new MapBox()
|
||
local raw = env.get("HAKO_STAGEB_MODULES_LIST")
|
||
if raw == null { return map }
|
||
local str = "" + raw
|
||
if str == "" { return map }
|
||
|
||
local delim = "|||"
|
||
local start = 0
|
||
loop(true) {
|
||
local next = ParserCommonUtilsBox.index_of(str, start, delim)
|
||
local seg = ""
|
||
if next >= 0 { seg = str.substring(start, next) } else { seg = str.substring(start, str.length()) }
|
||
me._push_module_entry(map, seg)
|
||
if next < 0 { break }
|
||
start = next + delim.length()
|
||
}
|
||
return map
|
||
}
|
||
|
||
_push_module_entry(map, seg) {
|
||
if seg == null { return }
|
||
local line = ParserCommonUtilsBox.trim("" + seg)
|
||
if line == "" { return }
|
||
local eq_idx = ParserCommonUtilsBox.index_of(line, 0, "=")
|
||
if eq_idx < 0 { return }
|
||
local key = ParserCommonUtilsBox.trim(line.substring(0, eq_idx))
|
||
local val = ParserCommonUtilsBox.trim(line.substring(eq_idx + 1, line.length()))
|
||
if key == "" || val == "" { return }
|
||
map.set(key, val)
|
||
}
|
||
|
||
_lookup_module_path(map, name) {
|
||
if map == null { return null }
|
||
local val = map.get(name)
|
||
if val != null { return "" + val }
|
||
return null
|
||
}
|
||
|
||
_abs_path(path) {
|
||
if path == null { return null }
|
||
local p = "" + path
|
||
if p == "" { return null }
|
||
if ParserCommonUtilsBox.starts_with(p, 0, "/") == 1 { return p }
|
||
local root = env.get("NYASH_ROOT")
|
||
if root == null || root == "" { return p }
|
||
local base = "" + root
|
||
if base == "" { return p }
|
||
if base.substring(base.length() - 1, base.length()) == "/" { return base + p }
|
||
return base + "/" + p
|
||
}
|
||
|
||
_read_file(path) {
|
||
if path == null { return null }
|
||
@fb = new FileBox()
|
||
@ok = fb.open(path, "r")
|
||
if ok != 1 { return null }
|
||
@content = fb.read()
|
||
fb.close()
|
||
return content
|
||
}
|
||
}
|
||
|
||
static box Stage1UsingResolverBoxMain { main(args) { return 0 } }
|