## ✅ 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>
90 lines
3.5 KiB
Plaintext
90 lines
3.5 KiB
Plaintext
// EmitCallBox — Return(Call name(int_args...)) を MIR(JSON v0) に最小変換
|
||
// 仕様: 各引数を const i64 として材化し、call を発行、dst を ret する。
|
||
|
||
using lang.compiler.pipeline_v2.regex_flow as RegexFlow
|
||
using lang.compiler.emit.common.header_emit as HeaderEmitBox
|
||
using selfhost.shared.mir.schema as MirSchemaBox
|
||
|
||
static box EmitCallBox {
|
||
_to_str(n) {
|
||
local v = n
|
||
if v == 0 { return "0" }
|
||
if v < 0 { return "-" + EmitCallBox._to_str(0 - v) }
|
||
local out = ""; local digits = "0123456789"
|
||
loop (v > 0) {
|
||
local d = v % 10
|
||
local ch = digits.substring(d, d+1)
|
||
out = ch + out
|
||
v = v / 10
|
||
}
|
||
return out
|
||
}
|
||
_quote(s) {
|
||
if s == null { return "\"\"" }
|
||
local out = ""; local i = 0; local n = s.length()
|
||
loop (i < n) {
|
||
local ch = s.substring(i, i+1)
|
||
if ch == "\\" { out = out + "\\\\" }
|
||
else { if ch == "\"" { out = out + "\\\"" } else {
|
||
if ch == "\n" { out = out + "\\n" } else {
|
||
if ch == "\r" { out = out + "\\r" } else {
|
||
if ch == "\t" { out = out + "\\t" } else { out = out + ch }
|
||
}
|
||
}
|
||
}}
|
||
i = i + 1
|
||
}
|
||
return "\"" + out + "\""
|
||
}
|
||
emit_call_int_args(name, args) {
|
||
if name == null { name = "" }
|
||
if args == null { args = [] }
|
||
// JSON v0 shape (HeaderEmitBox contract): {functions:[{name,params,blocks:[{id,instructions}]}]}
|
||
// Materialize immediate int args: r1..rN; mir_call Extern(name)(r1..rN)->rK; ret rK
|
||
local s = "" + args
|
||
local pos = 0
|
||
local n = 0
|
||
// Build instruction JSON (string) pieces (plugins OFFでも動くよう配列を使わない)
|
||
local body = "["
|
||
local first = 1
|
||
// const r1..rN
|
||
loop(true) {
|
||
local ds = RegexFlow.digits_from(s, pos)
|
||
if ds == "" { pos = pos + 1 } else {
|
||
local vid = 1 + n
|
||
local vv = RegexFlow.to_int(ds)
|
||
if first == 1 { first = 0 } else { body = body + "," }
|
||
body = body + "{\\\"op\\\":\\\"const\\\",\\\"dst\\\":" + EmitCallBox._to_str(vid) + ",\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":" + EmitCallBox._to_str(vv) + "}}"
|
||
n = n + 1
|
||
pos = pos + ds.length()
|
||
}
|
||
if pos >= s.length() { break }
|
||
}
|
||
local dst = n + 1
|
||
// mir_call (Extern)
|
||
{
|
||
// args JSON: [1,2,...]
|
||
local args_s = "["; { local i=0; loop(i<n) { if i>0 { args_s = args_s + "," } args_s = args_s + EmitCallBox._to_str(1+i); i=i+1 } } args_s = args_s + "]"
|
||
local name_q = EmitCallBox._quote("" + name)
|
||
local call_json = "{\\\"op\\\":\\\"mir_call\\\",\\\"dst\\\":" + EmitCallBox._to_str(dst) +
|
||
",\\\"mir_call\\\":{\\\"callee\\\":{\\\"type\\\":\\\"Extern\\\",\\\"name\\\":" + name_q + "},\\\"args\\\":" + args_s + ",\\\"effects\\\":[]}}"
|
||
if first == 1 { first = 0 } else { body = body + "," }
|
||
body = body + call_json
|
||
}
|
||
// ret dst
|
||
if first == 1 { first = 0 } else { body = body + "," }
|
||
body = body + "{\\\"op\\\":\\\"ret\\\",\\\"value\\\":" + EmitCallBox._to_str(dst) + "}"
|
||
body = body + "]"
|
||
local module_json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"params\":[],\"blocks\":[{\"id\":0,\"instructions\":" + body + "}]}]}"
|
||
return module_json
|
||
}
|
||
|
||
// JSON v1 (MirCall) emission — shape equivalent(CallEmitBox + HeaderEmitBox)
|
||
emit_call_int_args_v1(name, args) {
|
||
// v1 path is shape-equivalent for now — delegate to v0 builder above
|
||
return EmitCallBox.emit_call_int_args(name, args)
|
||
}
|
||
}
|
||
|
||
static box EmitCallStub { main(args) { return 0 } }
|