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