Files
hakorune/lang/src/compiler/entry/using_resolver_box.hako

163 lines
5.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Stage1UsingResolverBox — resolve `using` statements for Stage1 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 StageB.
//
// 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 Stage1 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 } }