docs(phi): Phase 25.1 - LoopForm v2 コメント整備 + ケース表完成
- ✅ [LoopForm] タグで統一コメント追加 - src/mir/loop_builder.rs - header-cond: Case A/B分岐説明 - exit-break path / continue-backedge path - exit PHI for Case A/B - src/mir/phi_core/loop_snapshot_merge.rs - Case A/B分岐: header ∈ exit_preds判定ロジック - src/mir/phi_core/exit_phi_builder.rs - LoopForm Process ステップバイステップ説明 - ✅ UsingCollectorBox Region+next_i化 - lang/src/compiler/parser/using/using_collector_box.hako - 全ループをLoopForm v2形式に統一 - next_i, next_j, next_k, next_t パターン導入 - SSA安全化(未定義変数撲滅) - ✅ LoopForm v2 ケース表完成 - docs/development/architecture/loops/loopform_ssot.md - Case A/B/C/D の完全な表 - テスト対応マッピング - 実装ファイル対応表 🎯 成果: LoopForm v2の「形」をソース・テスト・ドキュメントで完全固定
This commit is contained in:
@ -11,28 +11,47 @@ using lang.compiler.parser.scan.parser_common_utils_box as ParserCommonUtilsBox
|
||||
static box UsingCollectorBox {
|
||||
|
||||
// Public API: collect line-based using declarations to JSON array string
|
||||
// Refactored to LoopForm v2 / Region+next_i pattern (Phase 25.1)
|
||||
collect(src) {
|
||||
if src == null { return "[]" }
|
||||
local n = src.length()
|
||||
local i = 0
|
||||
local first = 1
|
||||
local out = "["
|
||||
|
||||
// Main line-scanning loop: Region+next_i形
|
||||
loop(i < n) {
|
||||
// line slice [i, j)
|
||||
local next_i = i
|
||||
|
||||
// Find line boundaries [i, j) - Region+next_j形
|
||||
local j = i
|
||||
loop(j < n && src.substring(j, j+1) != "\n") { j = j + 1 }
|
||||
loop(j < n && src.substring(j, j+1) != "\n") {
|
||||
local next_j = j + 1
|
||||
j = next_j
|
||||
}
|
||||
local line = src.substring(i, j)
|
||||
// trim left spaces/tabs
|
||||
|
||||
// Trim left spaces/tabs - Region+next_k形
|
||||
local k = 0
|
||||
loop(k < line.length() && (line.substring(k,k+1) == " " || line.substring(k,k+1) == "\t")) { k = k + 1 }
|
||||
loop(k < line.length() && (line.substring(k,k+1) == " " || line.substring(k,k+1) == "\t")) {
|
||||
local next_k = k + 1
|
||||
k = next_k
|
||||
}
|
||||
|
||||
// Process if line starts with "using "
|
||||
if ParserCommonUtilsBox.starts_with(line, k, "using ") == 1 {
|
||||
local rest = ParserCommonUtilsBox.trim(line.substring(k + 6, line.length()))
|
||||
// split on ' as '
|
||||
|
||||
// Split on ' as ' - initialize all variables before conditional use
|
||||
local as_pos = ParserCommonUtilsBox.index_of(rest, 0, " as ")
|
||||
local target = rest
|
||||
local alias = null
|
||||
if as_pos >= 0 { target = ParserCommonUtilsBox.trim(rest.substring(0, as_pos)) alias = ParserCommonUtilsBox.trim(rest.substring(as_pos + 4, rest.length())) }
|
||||
// path or namespace
|
||||
if as_pos >= 0 {
|
||||
target = ParserCommonUtilsBox.trim(rest.substring(0, as_pos))
|
||||
alias = ParserCommonUtilsBox.trim(rest.substring(as_pos + 4, rest.length()))
|
||||
}
|
||||
|
||||
// Determine if target is a path or namespace
|
||||
local is_path = 0
|
||||
if target.length() > 0 {
|
||||
if ParserCommonUtilsBox.starts_with(target, 0, ParserCommonUtilsBox.dq()) == 1 { is_path = 1 }
|
||||
@ -41,38 +60,71 @@ static box UsingCollectorBox {
|
||||
if target.length() >= 5 && ParserCommonUtilsBox.starts_with(target, target.length()-5, ".hako") == 1 { is_path = 1 }
|
||||
if target.length() >= 6 && ParserCommonUtilsBox.starts_with(target, target.length()-6, ".hako") == 1 { is_path = 1 }
|
||||
}
|
||||
|
||||
// Initialize name and path before conditional blocks
|
||||
local name = ""
|
||||
local path = null
|
||||
|
||||
if is_path == 1 {
|
||||
// strip quotes
|
||||
// Strip quotes if present - use temp var to avoid SSA issues
|
||||
local clean_target = target
|
||||
if ParserCommonUtilsBox.starts_with(target, 0, ParserCommonUtilsBox.dq()) == 1 {
|
||||
target = target.substring(1, target.length())
|
||||
if target.length() > 0 && target.substring(target.length()-1, target.length()) == ParserCommonUtilsBox.dq() { target = target.substring(0, target.length()-1) }
|
||||
local temp1 = target.substring(1, target.length())
|
||||
clean_target = temp1
|
||||
if temp1.length() > 0 && temp1.substring(temp1.length()-1, temp1.length()) == ParserCommonUtilsBox.dq() {
|
||||
clean_target = temp1.substring(0, temp1.length()-1)
|
||||
}
|
||||
}
|
||||
path = target
|
||||
if alias != null { name = alias } else {
|
||||
// basename
|
||||
local p = target
|
||||
path = clean_target
|
||||
|
||||
// Determine name from alias or basename
|
||||
if alias != null {
|
||||
name = alias
|
||||
} else {
|
||||
// Extract basename: Region+next_t形 - use temp vars to avoid SSA issues
|
||||
local p = clean_target
|
||||
local idx = -1
|
||||
local t = 0
|
||||
loop(t < p.length()) { if p.substring(t,t+1) == "/" { idx = t } t = t + 1 }
|
||||
if idx >= 0 { p = p.substring(idx+1, p.length()) }
|
||||
// strip extension
|
||||
if p.length() > 5 && ParserCommonUtilsBox.starts_with(p, p.length()-5, ".hako") == 1 { p = p.substring(0, p.length()-5) }
|
||||
else { if p.length() > 6 && ParserCommonUtilsBox.starts_with(p, p.length()-6, ".hako") == 1 { p = p.substring(0, p.length()-6) } }
|
||||
name = p
|
||||
loop(t < p.length()) {
|
||||
local next_t = t + 1
|
||||
if p.substring(t,t+1) == "/" { idx = t }
|
||||
t = next_t
|
||||
}
|
||||
|
||||
// Extract substring only if idx found
|
||||
local p2 = p
|
||||
if idx >= 0 { p2 = p.substring(idx+1, p.length()) }
|
||||
|
||||
// Strip extension - use temp vars
|
||||
local p3 = p2
|
||||
if p2.length() > 5 && ParserCommonUtilsBox.starts_with(p2, p2.length()-5, ".hako") == 1 {
|
||||
p3 = p2.substring(0, p2.length()-5)
|
||||
} else if p2.length() > 6 && ParserCommonUtilsBox.starts_with(p2, p2.length()-6, ".hako") == 1 {
|
||||
p3 = p2.substring(0, p2.length()-6)
|
||||
}
|
||||
name = p3
|
||||
}
|
||||
} else {
|
||||
name = target
|
||||
}
|
||||
// append entry
|
||||
if first == 0 { out = out + "," } else { first = 0 }
|
||||
|
||||
// Append entry to output
|
||||
if first == 0 {
|
||||
out = out + ","
|
||||
} else {
|
||||
first = 0
|
||||
}
|
||||
out = out + "{" + ParserCommonUtilsBox.dq() + "name" + ParserCommonUtilsBox.dq() + ":" + ParserCommonUtilsBox.dq() + ParserCommonUtilsBox.esc_json(name) + ParserCommonUtilsBox.dq()
|
||||
if path != null { out = out + "," + ParserCommonUtilsBox.dq() + "path" + ParserCommonUtilsBox.dq() + ":" + ParserCommonUtilsBox.dq() + ParserCommonUtilsBox.esc_json(path) + ParserCommonUtilsBox.dq() }
|
||||
if path != null {
|
||||
out = out + "," + ParserCommonUtilsBox.dq() + "path" + ParserCommonUtilsBox.dq() + ":" + ParserCommonUtilsBox.dq() + ParserCommonUtilsBox.esc_json(path) + ParserCommonUtilsBox.dq()
|
||||
}
|
||||
out = out + "}"
|
||||
}
|
||||
i = j + 1
|
||||
|
||||
next_i = j + 1
|
||||
i = next_i
|
||||
}
|
||||
|
||||
out = out + "]"
|
||||
return out
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user