Phase 25.1b: Step2完了(FuncBodyBasicLowerBox導入)

Step2実装内容:
- FuncBodyBasicLowerBox導入(defs専用下請けモジュール)
- _try_lower_local_if_return実装(Local+単純if)
- _inline_local_ints実装(軽い正規化)
- minimal lowers統合(Return/BinOp/IfCompare/MethodArray系)

Fail-Fast体制確立:
- MirBuilderBox: defs_onlyでも必ずタグ出力
- [builder/selfhost-first:unsupported:defs_only]
- [builder/selfhost-first:unsupported:no_match]

Phase構造整備:
- Phase 25.1b README新設(Step0-3計画)
- Phase 25.2b README新設(次期計画)
- UsingResolverBox追加(using system対応準備)

スモークテスト:
- stage1_launcher_program_to_mir_canary_vm.sh追加

Next: Step3 LoopForm対応

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-15 22:32:13 +09:00
parent 6856922374
commit 7ca7f646de
31 changed files with 1670 additions and 323 deletions

View File

@ -7,16 +7,96 @@
using lang.compiler.parser.box as ParserBox
static box FuncScannerBox {
// Scan source for method definitions (excluding main)
// Returns ArrayBox of method definitions
// Scan source for method definitions (excluding Main.main)
method scan_functions(source, box_name) {
return me._scan_methods(source, box_name, 1, 0)
}
// Scan all static box definitions and collect their methods.
method scan_all_boxes(source) {
local defs = new ArrayBox()
local s = "" + source
local n = s.length()
local i = 0
local in_str = 0
local esc = 0
local in_line = 0
local in_block = 0
loop(i < n) {
local ch = s.substring(i, i + 1)
if in_line == 1 {
if ch == "\n" { in_line = 0 }
i = i + 1
continue
}
if in_block == 1 {
if ch == "*" && i + 1 < n && s.substring(i + 1, i + 2) == "/" {
in_block = 0
i = i + 2
continue
}
i = i + 1
continue
}
if in_str == 1 {
if esc == 1 { esc = 0 i = i + 1 continue }
if ch == "\\" { esc = 1 i = i + 1 continue }
if ch == "\"" { in_str = 0 i = i + 1 continue }
i = i + 1
continue
}
if ch == "\"" { in_str = 1 i = i + 1 continue }
if ch == "/" && i + 1 < n {
local ch2 = s.substring(i + 1, i + 2)
if ch2 == "/" { in_line = 1 i = i + 2 continue }
if ch2 == "*" { in_block = 1 i = i + 2 continue }
}
if s.substring(i, i + 3) == "box" && me._kw_boundary_before(s, i) == 1 && me._kw_boundary_after(s, i + 3) == 1 {
local cursor = i + 3
cursor = me._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 }
}
local box_name = s.substring(name_start, cursor)
if box_name == "" {
i = cursor
continue
}
cursor = me._skip_whitespace(s, cursor)
if cursor >= n || s.substring(cursor, cursor + 1) != "{" {
i = cursor
continue
}
local close_idx = me._find_matching_brace(s, cursor)
if close_idx < 0 { break }
local body = s.substring(cursor + 1, close_idx)
local skip_main = 0
if box_name == "Main" { skip_main = 1 }
local include_me = 0
if box_name != "Main" { include_me = 1 }
local defs_box = me._scan_methods(body, box_name, skip_main, include_me)
me._append_defs(defs, defs_box)
i = close_idx + 1
continue
}
i = i + 1
}
return defs
}
method _scan_methods(source, box_name, skip_main, include_me) {
local methods = new ArrayBox()
local s = "" + source
local n = s.length()
local i = 0
loop(i < n) {
// Search for "method " pattern
// Search for "method "
local k = -1
{
local pat = "method "
@ -28,7 +108,7 @@ static box FuncScannerBox {
}
}
if k < 0 { break }
i = k + 7 // skip "method "
i = k + 7
// Extract method name (alphanumeric until '(')
local name_start = i
@ -44,8 +124,7 @@ static box FuncScannerBox {
if name_end < 0 { break }
local method_name = s.substring(name_start, name_end)
// Skip main (already extracted as body)
if method_name == "main" { i = name_end continue }
if skip_main == 1 && box_name == "Main" && method_name == "main" { i = name_end continue }
// Find '(' after name
local lparen = name_end
@ -75,6 +154,21 @@ static box FuncScannerBox {
// Extract params (minimal: comma-separated names)
local params_str = s.substring(lparen + 1, rparen)
local params = me._parse_params(params_str)
if include_me == 1 {
local first = ""
if params.length() > 0 { first = "" + params.get(0) }
if first != "me" {
local merged = new ArrayBox()
merged.push("me")
local pi2 = 0
local pn2 = params.length()
loop(pi2 < pn2) {
merged.push(params.get(pi2))
pi2 = pi2 + 1
}
params = merged
}
}
// Find opening '{' after ')'
local lbrace = -1
@ -130,10 +224,7 @@ static box FuncScannerBox {
// Extract method body (inside braces)
local method_body = s.substring(lbrace + 1, rbrace)
// Strip comments from method body
method_body = me._strip_comments(method_body)
// Trim method body
method_body = me._trim(method_body)
// Parse method body to JSON (statement list)
@ -144,7 +235,6 @@ static box FuncScannerBox {
body_json = p.parse_program2(method_body)
}
// Store method definition
if body_json != null && body_json != "" {
local def = new MapBox()
def.set("name", method_name)
@ -159,6 +249,101 @@ static box FuncScannerBox {
return methods
}
method _append_defs(dst, defs_box) {
if defs_box == null { return }
local i = 0
loop(i < defs_box.length()) {
dst.push(defs_box.get(i))
i = i + 1
}
}
method _skip_whitespace(s, idx) {
local i = idx
local n = s.length()
loop(i < n) {
local ch = s.substring(i, i + 1)
if ch == " " || ch == "\t" || ch == "\n" || ch == "\r" { i = i + 1 } else { break }
}
return i
}
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 }
return 1
}
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 }
return 1
}
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 }
if ch >= "a" && ch <= "z" { return 1 }
if ch == "_" { return 1 }
return 0
}
method _find_matching_brace(s, open_idx) {
local n = s.length()
local i = open_idx
local depth = 0
local in_str = 0
local esc = 0
local in_line = 0
local in_block = 0
loop(i < n) {
local ch = s.substring(i, i + 1)
if in_line == 1 {
if ch == "\n" { in_line = 0 }
i = i + 1
continue
}
if in_block == 1 {
if ch == "*" && i + 1 < n && s.substring(i + 1, i + 2) == "/" {
in_block = 0
i = i + 2
continue
}
i = i + 1
continue
}
if in_str == 1 {
if esc == 1 { esc = 0 i = i + 1 continue }
if ch == "\\" { esc = 1 i = i + 1 continue }
if ch == "\"" { in_str = 0 i = i + 1 continue }
i = i + 1
continue
}
if ch == "\"" { in_str = 1 i = i + 1 continue }
if ch == "/" && i + 1 < n {
local ch2 = s.substring(i + 1, i + 2)
if ch2 == "/" { in_line = 1 i = i + 2 continue }
if ch2 == "*" { in_block = 1 i = i + 2 continue }
}
if ch == "{" {
depth = depth + 1
i = i + 1
continue
}
if ch == "}" {
depth = depth - 1
i = i + 1
if depth == 0 { return i - 1 }
continue
}
i = i + 1
}
return -1
}
// Helper: parse comma-separated parameter names
method _parse_params(params_str) {
local params = new ArrayBox()
@ -202,7 +387,6 @@ static box FuncScannerBox {
local esc = 0
local in_line = 0
local in_block = 0
loop(i < n) {
local ch = s.substring(i, i + 1)
if in_line == 1 {
@ -223,7 +407,6 @@ static box FuncScannerBox {
i = i + 1
continue
}
// Not in string/comment
if ch == "\"" { out = out + ch in_str = 1 i = i + 1 continue }
if ch == "/" && i + 1 < n {
local ch2 = s.substring(i + 1, i + 2)
@ -233,29 +416,24 @@ static box FuncScannerBox {
out = out + ch
i = i + 1
}
return out
}
// Helper: trim whitespace from string
// Helper: trim whitespace
method _trim(s) {
if s == null { return "" }
local str = "" + s
local n = str.length()
local b = 0
// left trim (space, tab, CR, LF)
loop(b < n) {
local ch = str.substring(b, b + 1)
if ch == " " || ch == "\t" || ch == "\r" || ch == "\n" { b = b + 1 } else { break }
if ch == " " || ch == "\t" || ch == "\n" || ch == "\r" { b = b + 1 } else { break }
}
// right trim
local e = n
loop(e > b) {
local ch = str.substring(e - 1, e)
if ch == " " || ch == "\t" || ch == "\r" || ch == "\n" { e = e - 1 } else { break }
if ch == " " || ch == "\t" || ch == "\n" || ch == "\r" { e = e - 1 } else { break }
}
if e > b { return str.substring(b, e) }
return ""
}