Files
hakorune/lang/src/compiler/pipeline_v2/compare_extract_box.hako
nyash-codex df9068a555 feat(stage-b): Add FLOW keyword support + fix Stage-3 keyword conflicts
##  Fixed Issues

### 1. `local` keyword tokenization (commit 9aab64f7)
- Added Stage-3 gate for LOCAL/TRY/CATCH/THROW keywords
- LOCAL now only active when NYASH_PARSER_STAGE3=1

### 2. `env.local.get` keyword conflict
- File: `lang/src/compiler/entry/compiler_stageb.hako:21-23`
- Problem: `.local` in member access tokenized as `.LOCAL` keyword
- Fix: Commented out `env.local.get("HAKO_SOURCE")` line
- Fallback: Use `--source` argument (still functional)

### 3. `flow` keyword missing
- Added FLOW to TokenType enum (`src/tokenizer/kinds.rs`)
- Added "flow" → TokenType::FLOW mapping (`src/tokenizer/lex_ident.rs`)
- Added FLOW to Stage-3 gate (requires NYASH_PARSER_STAGE3=1)
- Added FLOW to parser statement dispatch (`src/parser/statements/mod.rs`)
- Added FLOW to declaration handler (`src/parser/statements/declarations.rs`)
- Updated box_declaration parser to accept BOX or FLOW (`src/parser/declarations/box_definition.rs`)
- Treat `flow FooBox {}` as syntactic sugar for `box FooBox {}`

### 4. Module namespace conversion
- Renamed `lang.compiler.builder.ssa.local` → `localvar` (avoid keyword)
- Renamed file `local.hako` → `local_ssa.hako`
- Converted 152 path-based using statements to namespace format
- Added 26+ entries to `nyash.toml` [modules] section

## ⚠️ Remaining Issues

### Stage-B selfhost compiler performance
- Stage-B compiler not producing output (hangs/times out after 10+ seconds)
- Excessive PHI debug output suggests compilation loop issue
- Needs investigation: infinite loop or N² algorithm in hako compiler

### Fallback JSON version mismatch
- Rust fallback (`--emit-mir-json`) emits MIR v1 JSON (schema_version: "1.0")
- Smoke tests expect MIR v0 JSON (`"version":0, "kind":"Program"`)
- stageb_helpers.sh fallback needs adjustment

## Test Status
- Parse errors: FIXED 
- Keyword conflicts: FIXED 
- Stage-B smoke tests: STILL FAILING  (performance issue)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 04:13:17 +09:00

120 lines
4.5 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.

// CompareExtractBox — Stage1 JSON から Compare(lhs,rhs,op) を堅牢に抽出(整数のみ)
using lang.compiler.pipeline_v2.regex_flow as RegexFlow
using selfhost.shared.common.box_helpers as BoxHelpers
static box CompareExtractBox {
// --- internal helpers (range & safe find) ---
_find_brace_range(s, around_pos) {
// Find object range that contains around_pos: search '{' backwards, then match '}' by depth
if around_pos < 0 { return null }
local start = around_pos
loop (start >= 0) {
local ch = s.substring(start, start+1)
if ch == "{" { break }
start = start - 1
}
if start < 0 { return null }
local i = start
local depth = 0
loop(true) {
local ch2 = s.substring(i, i+1)
if ch2 == "" { break }
if ch2 == "{" { depth = depth + 1 } else { if ch2 == "}" { depth = depth - 1 } }
if depth == 0 { return { "from": start, "to": i + 1 } }
i = i + 1
}
return null
}
_find_in_range(s, needle, start, endp) {
local p = RegexFlow.find_from(s, needle, start)
if p < 0 { return -1 }
if p >= endp { return -1 }
return p
}
// Returns MapBox {"cmp": String, "lhs": Int, "rhs": Int } or null when not found
extract_return_compare_ints(ast_json) {
if ast_json == null { return null }
// Find Return then Compare (whitespace耐性は RegexFlow に委譲)
local rq = RegexFlow.find_from(ast_json, "\"type\":\"Return\"", 0)
if rq < 0 { return null }
local cq = RegexFlow.find_from(ast_json, "\"type\":\"Compare\"", rq)
if cq < 0 { return null }
// op
local opk_pos = RegexFlow.find_from(ast_json, "\"op\":\"", cq)
if opk_pos < 0 { return null }
local opk_end = RegexFlow.find_from(ast_json, "\"", opk_pos + 6)
if opk_end < 0 { return null }
local cmp = ast_json.substring(opk_pos + 6, opk_end)
// lhs/rhs → 各 value の digits を抽出
local lhsp = RegexFlow.find_from(ast_json, "\"lhs\"", cq)
local rhsp = RegexFlow.find_from(ast_json, "\"rhs\"", cq)
if lhsp < 0 || rhsp < 0 { return null }
local lv = -1
local rv = -1
{
local vpos = RegexFlow.find_from(ast_json, "\"value\":", lhsp)
if vpos >= 0 {
local ds = RegexFlow.digits_from(ast_json, vpos + 8)
if ds != "" { lv = RegexFlow.to_int(ds) }
}
}
{
local vpos2 = RegexFlow.find_from(ast_json, "\"value\":", rhsp)
if vpos2 >= 0 {
local ds2 = RegexFlow.digits_from(ast_json, vpos2 + 8)
if ds2 != "" { rv = RegexFlow.to_int(ds2) }
}
}
if lv < 0 || rv < 0 { return null }
// Pack cmp/lhs/rhs into ArrayBox [cmp, lhs, rhs]
return [lv, rv, cmp]
}
// If(cond=Compare(lhs,rhs,op), then=[Return(Int 1)], else=[Return(Int 0)]) → MapBox {cmp,lhs,rhs} or null
extract_if_compare_ints(ast_json) {
if ast_json == null { return null }
// Find If first
local ip = RegexFlow.find_from(ast_json, "\"type\":\"If\"", 0)
if ip < 0 { return null }
// Find Compare after If
local cq = RegexFlow.find_from(ast_json, "\"type\":\"Compare\"", ip)
if cq < 0 { return null }
// Restrict to the Compare object range to avoid accidental matches
local range = me._find_brace_range(ast_json, cq)
if range == null { return null }
local rs = BoxHelpers.map_get(range, "from")
local re = BoxHelpers.map_get(range, "to")
// TEMP debug
print("DBG:cmp-range=" + ast_json.substring(rs, re))
// op
local opk_pos = me._find_in_range(ast_json, "\"op\":\"", rs, re)
if opk_pos < 0 { return null }
local opv_start = opk_pos + 6
local opk_end = me._find_in_range(ast_json, "\"", opv_start, re)
if opk_end < 0 { return null }
local cmp = ast_json.substring(opv_start, opk_end)
print("DBG:cmp-op=" + cmp)
// lhs
local lhsp = me._find_in_range(ast_json, "\"lhs\"", rs, re)
if lhsp < 0 { return null }
local vpos = me._find_in_range(ast_json, "\"value\":", lhsp, re)
if vpos < 0 { return null }
local ds = RegexFlow.digits_from(ast_json, vpos + 8)
if ds == "" { return null }
local lv = RegexFlow.to_int(ds)
print("DBG:lhs=" + (""+lv))
// rhs
local rhsp = me._find_in_range(ast_json, "\"rhs\"", rs, re)
if rhsp < 0 { return null }
local vpos2 = me._find_in_range(ast_json, "\"value\":", rhsp, re)
if vpos2 < 0 { return null }
local ds2 = RegexFlow.digits_from(ast_json, vpos2 + 8)
if ds2 == "" { return null }
local rv = RegexFlow.to_int(ds2)
print("DBG:rhs=" + (""+rv))
return [lv, rv, cmp]
}
}
static box CompareExtractStub { main(args) { return 0 } }