diff --git a/lang/src/compiler/entry/compiler_stageb.hako b/lang/src/compiler/entry/compiler_stageb.hako index 8ac6a766..fc5fb33a 100644 --- a/lang/src/compiler/entry/compiler_stageb.hako +++ b/lang/src/compiler/entry/compiler_stageb.hako @@ -760,9 +760,16 @@ static box StageBFuncScannerBox { if ch2 == "*" { in_block = 1 i = i + 2 continue } } - if s.substring(i, i + 3) == "box" && StageBFuncScannerBox._kw_boundary_before(s, i) == 1 && StageBFuncScannerBox._kw_boundary_after(s, i + 3) == 1 { + // Debug: box keyword detection + if i + 3 <= n && s.substring(i, i + 3) == "box" { + local boundary_before = FuncScannerBox.kw_boundary_before(s, i) + local boundary_after = FuncScannerBox.kw_boundary_after(s, i + 3) + } + + if s.substring(i, i + 3) == "box" && FuncScannerBox.kw_boundary_before(s, i) == 1 && FuncScannerBox.kw_boundary_after(s, i + 3) == 1 { + print("[scan_all_boxes] found box keyword at i=" + i) local cursor = i + 3 - cursor = StageBFuncScannerBox._skip_whitespace(s, cursor) + cursor = FuncScannerBox.skip_whitespace(s, cursor) local name_start = cursor loop(cursor < n) { @@ -771,15 +778,16 @@ static box StageBFuncScannerBox { cursor = cursor + 1 } local box_name = s.substring(name_start, cursor) + print("[scan_all_boxes] box_name='" + box_name + "'") - cursor = StageBFuncScannerBox._skip_whitespace(s, cursor) + cursor = FuncScannerBox.skip_whitespace(s, cursor) if s.substring(cursor, cursor + 1) != "{" { i = i + 3 continue } local open_idx = cursor - local close_idx = StageBFuncScannerBox._find_matching_brace(s, open_idx) + local close_idx = FuncScannerBox.find_matching_brace(s, open_idx) if close_idx < 0 { i = i + 3 @@ -812,15 +820,16 @@ static box StageBFuncScannerBox { // Open brace positions matching "box TestBox {" と "box Main {" local open1 = 19 - local close1 = StageBFuncScannerBox._find_matching_brace(src, open1) + local close1 = FuncScannerBox.find_matching_brace(src, open1) print("[funcscan/test] brace1 open=" + ("" + open1) + " close=" + ("" + close1)) local open2 = 209 - local close2 = StageBFuncScannerBox._find_matching_brace(src, open2) + local close2 = FuncScannerBox.find_matching_brace(src, open2) print("[funcscan/test] brace2 open=" + ("" + open2) + " close=" + ("" + close2)) // Full scan_all_boxes on the same src to observe defs - local defs = StageBFuncScannerBox.scan_all_boxes(src) + // Use FuncScannerBox directly to avoid delegation issues + local defs = FuncScannerBox.scan_all_boxes(src) local cnt = defs.length() print("[funcscan/test] defs_len=" + ("" + cnt)) local i = 0 @@ -833,7 +842,6 @@ static box StageBFuncScannerBox { } _scan_methods(source, box_name, skip_main, include_me) { - // print("[funcscan/debug] _scan_methods box=" + box_name + " src_len=" + source.length()) local methods = new ArrayBox() local s = "" + source local n = s.length() @@ -852,7 +860,6 @@ static box StageBFuncScannerBox { } } if k < 0 { break } - // print("[funcscan/debug] found 'method ' at " + k) i = k + 7 // Extract method name (alphanumeric until '(') @@ -898,7 +905,7 @@ static box StageBFuncScannerBox { // Extract params (minimal: comma-separated names) local params_str = s.substring(lparen + 1, rparen) - local params = StageBFuncScannerBox._parse_params(params_str) + local params = FuncScannerBox._parse_params(params_str) if include_me == 1 { local first = "" if params.length() > 0 { first = "" + params.get(0) } @@ -969,8 +976,8 @@ static box StageBFuncScannerBox { // Extract method body (inside braces) local method_body = s.substring(lbrace + 1, rbrace) - method_body = StageBFuncScannerBox._strip_comments(method_body) - method_body = StageBFuncScannerBox._trim(method_body) + method_body = FuncScannerBox._strip_comments(method_body) + method_body = FuncScannerBox._trim(method_body) // Parse method body to JSON (statement list) using block parser local body_json = null @@ -1012,74 +1019,65 @@ static box StageBFuncScannerBox { // Helper: 空白文字スキップ(FuncScannerBox に委譲) _skip_whitespace(s, idx) { - return FuncScannerBox._skip_whitespace(s, idx) + return FuncScannerBox.skip_whitespace(s, idx) } // Helper: キーワード前境界チェック(FuncScannerBox に委譲) _kw_boundary_before(s, idx) { - return FuncScannerBox._kw_boundary_before(s, idx) + return FuncScannerBox.kw_boundary_before(s, idx) } // Helper: キーワード後境界チェック(FuncScannerBox に委譲) _kw_boundary_after(s, idx) { - return FuncScannerBox._kw_boundary_after(s, idx) + return FuncScannerBox.kw_boundary_after(s, idx) } // Helper: 識別子文字判定(FuncScannerBox に委譲) _is_ident_char(ch) { - return FuncScannerBox._is_ident_char(ch) + return FuncScannerBox.is_ident_char(ch) } test_nested_loop_int(n) { - print("[funcscan/debug] entering test_nested_loop_int with n=" + n) local i = 0 loop(i < 3) { - print("[funcscan/debug] test_nested_loop_int i=" + i) i = i + 1 } - print("[funcscan/debug] exiting test_nested_loop_int") } test_nested_loop_str(s) { - print("[funcscan/debug] entering test_nested_loop_str with len=" + s.length()) local i = 0 loop(i < 3) { - print("[funcscan/debug] test_nested_loop_str i=" + i) i = i + 1 } - print("[funcscan/debug] exiting test_nested_loop_str") } // Helper: 対応する閉じブレース検索(FuncScannerBox に委譲) - _find_matching_brace(source_str, open_idx) { - return FuncScannerBox._find_matching_brace(source_str, open_idx) + find_matching_brace(source_str, open_idx) { + return FuncScannerBox.find_matching_brace(source_str, open_idx) } // Helper: パラメータリストパース(FuncScannerBox に委譲) - _parse_params(params_str) { + parse_params(params_str) { return FuncScannerBox._parse_params(params_str) } // Helper: コメント削除(FuncScannerBox に委譲) - _strip_comments(source) { + strip_comments(source) { return FuncScannerBox._strip_comments(source) } // Helper: 前後空白削除(FuncScannerBox に委譲) - _trim(s) { + trim(s) { return FuncScannerBox._trim(s) } } static box StageBHelperBox { test_loop(n) { - print("[funcscan/debug] entering StageBHelperBox.test_loop with n=" + n) local i = 0 loop(i < 3) { - print("[funcscan/debug] StageBHelperBox.test_loop i=" + i) i = i + 1 } - print("[funcscan/debug] exiting StageBHelperBox.test_loop") } } @@ -1216,7 +1214,7 @@ static box StageBDriverBox { tracer.log("StageBDriverBox.main:func_scan src_head=" + head) } - local methods = StageBFuncScannerBox.scan_all_boxes(src) + local methods = me.scan_all_boxes(src) { local cnt = 0 diff --git a/lang/src/compiler/entry/func_scanner.hako b/lang/src/compiler/entry/func_scanner.hako index fa00fd31..4f1665fd 100644 --- a/lang/src/compiler/entry/func_scanner.hako +++ b/lang/src/compiler/entry/func_scanner.hako @@ -9,7 +9,7 @@ using "lang.compiler.parser.box" as ParserBox static box FuncScannerBox { // Scan source for method definitions (excluding Main.main) method scan_functions(source, box_name) { - return me._scan_methods(source, box_name, 1, 0) + return me.scan_methods(source, box_name, 1, 0) } // Scan all static box definitions and collect their methods. @@ -81,23 +81,23 @@ static box FuncScannerBox { } // box キーワード検出(境界チェック付き) } else { - if i + 3 <= n && s.substring(i, i + 3) == "box" && me._kw_boundary_before(s, i) == 1 && me._kw_boundary_after(s, i + 3) == 1 { + if i + 3 <= n && s.substring(i, i + 3) == "box" && FuncScannerBox.kw_boundary_before(s, i) == 1 && FuncScannerBox.kw_boundary_after(s, i + 3) == 1 { local cursor = i + 3 - cursor = me._skip_whitespace(s, cursor) + cursor = FuncScannerBox.skip_whitespace(s, cursor) local name_start = cursor loop(cursor < n) { local ch_name = s.substring(cursor, cursor + 1) - if me._is_ident_char(ch_name) == 1 { cursor = cursor + 1 } else { break } + if FuncScannerBox.is_ident_char(ch_name) == 1 { cursor = cursor + 1 } else { break } } local box_name = s.substring(name_start, cursor) if box_name == "" { next_i = cursor } else { - cursor = me._skip_whitespace(s, cursor) + cursor = FuncScannerBox.skip_whitespace(s, cursor) if cursor >= n || s.substring(cursor, cursor + 1) != "{" { next_i = cursor } else { - local close_idx = me._find_matching_brace(s, cursor) + local close_idx = FuncScannerBox.find_matching_brace(s, cursor) if close_idx < 0 { // マッチしない場合はこれ以上スキャンしても意味がないのでループ終了。 i = n @@ -301,7 +301,7 @@ static box FuncScannerBox { // Helper: 空白文字(space/tab/newline/CR)を idx 位置からスキップ // 戻り値: スキップ後の位置(空白でない文字の位置、または文字列末尾) - method _skip_whitespace(s, idx) { + method skip_whitespace(s, idx) { local i = idx local n = s.length() loop(i < n) { @@ -313,25 +313,25 @@ static box FuncScannerBox { // Helper: キーワード前の境界チェック("box" などが識別子の一部でないことを確認) // 戻り値: 1=境界OK(キーワードとして有効), 0=境界NG(識別子の一部) - method _kw_boundary_before(s, idx) { + method kw_boundary_before(s, idx) { if idx <= 0 { return 1 } local ch = s.substring(idx - 1, idx) - if me._is_ident_char(ch) == 1 { return 0 } + if FuncScannerBox.is_ident_char(ch) == 1 { return 0 } return 1 } // Helper: キーワード後の境界チェック("box" などが識別子の一部でないことを確認) // 戻り値: 1=境界OK(キーワードとして有効), 0=境界NG(識別子の一部) - method _kw_boundary_after(s, idx) { + method kw_boundary_after(s, idx) { if idx >= s.length() { return 1 } local ch = s.substring(idx, idx + 1) - if me._is_ident_char(ch) == 1 { return 0 } + if FuncScannerBox.is_ident_char(ch) == 1 { return 0 } return 1 } // Helper: 識別子として有効な文字かチェック(0-9, A-Z, a-z, _) // 戻り値: 1=識別子文字, 0=非識別子文字 - method _is_ident_char(ch) { + method is_ident_char(ch) { if ch == null || ch == "" { return 0 } if ch >= "0" && ch <= "9" { return 1 } if ch >= "A" && ch <= "Z" { return 1 } @@ -340,7 +340,7 @@ static box FuncScannerBox { return 0 } - method _find_matching_brace(s, open_idx) { + method find_matching_brace(s, open_idx) { local n = s.length() if open_idx < 0 || open_idx >= n { return -1 } // open_idx 以降だけを対象に走査することで、前方の構造に依存しないようにする。 @@ -400,7 +400,7 @@ static box FuncScannerBox { // Helper: カンマ区切りパラメータリストをパース(例: "a, b, c" → ["a", "b", "c"]) // FuncScannerBox._trim を使用(static helper パターン) // 戻り値: ArrayBox(トリム済みパラメータ名のリスト) - method _parse_params(params_str) { + method parse_params(params_str) { local params = new ArrayBox() local pstr = "" + params_str local pn = pstr.length() @@ -424,7 +424,7 @@ static box FuncScannerBox { // Extract param name (trim) local pname = pstr.substring(pstart, pend) - pname = me._trim(pname) + pname = FuncScannerBox.trim(pname) if pname.length() > 0 { params.push(pname) } pstart = pend + 1 } @@ -434,7 +434,7 @@ static box FuncScannerBox { // Helper: "//" と "/* */" コメントを削除(文字列リテラル内は保持、改行は保持) // 戻り値: コメント削除後のソースコード(null の場合は空文字) - method _strip_comments(source) { + method strip_comments(source) { // source が null の場合はそのまま空文字として扱う(コメント除去する対象がないだけ) if source == null { return "" } local s = "" + source @@ -479,7 +479,7 @@ static box FuncScannerBox { // Helper: 前後の空白文字(space/tab/newline/CR)を削除 // 戻り値: トリム済み文字列(null の場合は空文字) - method _trim(s) { + method trim(s) { if s == null { return "" } local str = "" + s local n = str.length() @@ -496,4 +496,24 @@ static box FuncScannerBox { if e > b { return str.substring(b, e) } return "" } + + // ──────────────────────────────────────────────────────────── + // Static Helper Aliases (external API with underscore prefix) + // Stage-B および他の箱から static 呼び出しで使える薄いラッパー + // ──────────────────────────────────────────────────────────── + + // Static helper: パラメータリストパース(外部 API) + method _parse_params(params_str) { + return FuncScannerBox.parse_params(params_str) + } + + // Static helper: コメント削除(外部 API) + method _strip_comments(source) { + return FuncScannerBox.strip_comments(source) + } + + // Static helper: 前後空白削除(外部 API) + method _trim(s) { + return FuncScannerBox.trim(s) + } }