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>
This commit is contained in:
nyash-codex
2025-11-02 04:13:17 +09:00
parent 82cdfa7056
commit df9068a555
115 changed files with 478 additions and 232 deletions

View File

@ -2,7 +2,7 @@
// 目的: ArrayBox/MapBox の安全な操作を統一的に提供
// 削減: 7ファイル × 2パターン = 14重複 → 1箇所に集約
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
using selfhost.shared.common.string_helpers as StringHelpers
static box BoxHelpers {
// ArrayBox.size/1 の結果unwrap (MapBox-wrapped integer対応)

View File

@ -1,7 +1,7 @@
// Mini-VM scanning and numeric helpers
// Delegation Policy: all scanning primitives route to JsonCursorBox to avoid divergence.
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
using "lang/src/shared/json/json_cursor.hako" as JsonCursorBox
using selfhost.shared.common.string_helpers as StringHelpers
using selfhost.shared.json.core.json_cursor as JsonCursorBox
static box MiniVmScan {
// helper: find needle from position pos (escape-aware where needed)

View File

@ -1,8 +1,8 @@
// json_scan.hako — JsonScanBox
// Escape-aware JSON structure scanning helpers.
using "lang/src/shared/json/core/string_scan.hako" as StringScanBox
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
using selfhost.shared.json.core.string_scan as StringScanBox
using selfhost.shared.common.string_helpers as StringHelpers
static box JsonScanBox {
// minimal string→int (delegate to shared helper)

View File

@ -1,7 +1,7 @@
// string_scan.hako — StringScanBox
// Escape-aware string scanning helpers for JSON/text processing.
using "lang/src/shared/common/string_ops.hako" as StringOps
using selfhost.shared.common.string_ops as StringOps
static box StringScanBox {
// Return the single-character string at index i (empty if out of bounds)

View File

@ -2,9 +2,9 @@
// Responsibility: provide a minimal, escape-aware scanning facade used by JsonFragBox
// Delegates to StringOps, StringScanBox and JsonScanBox.
using "lang/src/shared/common/string_ops.hako" as StringOps
using "lang/src/shared/json/core/string_scan.hako" as StringScanBox
using "lang/src/shared/json/core/json_scan.hako" as JsonScanBox
using selfhost.shared.common.string_ops as StringOps
using selfhost.shared.json.core.string_scan as StringScanBox
using selfhost.shared.json.core.json_scan as JsonScanBox
static box JsonCursorBox {
index_of_from(hay, needle, pos) {

View File

@ -1,7 +1,7 @@
// JsonUtilsBox — JSON読み取りユーティリティの共通箱
// 責務: JSON値抽出・JSON構造パース・トップレベル配列分割
// Extracted from JsonProgramBox (480行 → 345行, 削減 ~135行)
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
using selfhost.shared.common.string_helpers as StringHelpers
static box JsonUtilsBox {
// Extract JSON value by key (returns value with '@' + end position marker)

View File

@ -1,5 +1,5 @@
// mir_builder2.hako — Instance builder引数渡しバグ回避のため、非staticで内部状態を保持
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
using selfhost.shared.common.string_helpers as StringHelpers
using lang.compiler.emit.common.json_emit as JsonEmitBox
using lang.compiler.emit.common.mir_emit as MirEmitBox
using lang.compiler.emit.common.header_emit as HeaderEmitBox

View File

@ -1,13 +1,13 @@
// mir_builder_min.nyash — Minimal MIR(JSON v0) builder for selfhost tests
// Scope: selfhost only (apps/selfhost/...); no core/runtime changes.
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
using "lang/src/shared/common/box_helpers.hako" as BoxHelpers
using selfhost.shared.common.string_helpers as StringHelpers
using selfhost.shared.common.box_helpers as BoxHelpers
using lang.compiler.emit.common.json_emit as JsonEmitBox
using lang.compiler.emit.common.mir_emit as MirEmitBox
using lang.compiler.emit.common.call_emit as CallEmitBox
using lang.compiler.emit.common.newbox_emit as NewBoxEmitBox
using "lang/src/shared/json/json_inst_encode_box.hako" as JsonInstEncodeBox
using selfhost.shared.json.json_inst_encode_box as JsonInstEncodeBox
box MirJsonBuilderMin {
buf: StringBox

View File

@ -1,7 +1,7 @@
// mir_v1_adapter.nyash — Minimal JSON v1 (mir_call) to v0 adapter for selfhost
// Scope: selfhost only. Transforms op:"mir_call" into legacy v0 ops (call/boxcall/newbox).
using "lang/src/shared/json/json_cursor.hako" as JsonCursorBox
using selfhost.shared.json.core.json_cursor as JsonCursorBox
static box MirJsonV1Adapter {
// Delegate to JsonCursorBox (escape-aware implementations, fixes 2 escape bugs)

View File

@ -2,8 +2,8 @@
// 責務: 文字列JSONから key:int / key:str を簡便に取り出す。
// 非責務: 実行・評価構造検査やVM実行は他箱に委譲
using "lang/src/shared/json/json_cursor.hako" as JsonCursorBox
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
using selfhost.shared.json.core.json_cursor as JsonCursorBox
using selfhost.shared.common.string_helpers as StringHelpers
static box JsonFragBox {
// 基本ヘルパ

View File

@ -1,9 +1,9 @@
// selfhost/shared/mir/block_builder_box.hako
// BlockBuilderBox — small helpers to assemble P1 shapes
using "lang/src/shared/mir/mir_schema_box.hako" as MirSchemaBox
using "lang/src/shared/mir/loop_form_box.hako" as LoopFormBox
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
using selfhost.shared.mir.schema as MirSchemaBox
using selfhost.shared.mir.loopform as LoopFormBox
using selfhost.shared.common.string_helpers as StringHelpers
static box BlockBuilderBox {

View File

@ -1,8 +1,8 @@
// selfhost/shared/mir/json_emit_box.hako
// JsonEmitBox — Gate C JSON emitter (schema_version 1.0, numbers unwrapped)
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
using "lang/src/shared/common/box_helpers.hako" as BoxHelpers
using selfhost.shared.common.string_helpers as StringHelpers
using selfhost.shared.common.box_helpers as BoxHelpers
static box JsonEmitBox {
_expect_map(val, context) {

View File

@ -1,7 +1,7 @@
// selfhost/shared/mir/loop_form_box.hako
// LoopFormBox — minimal loop structure builder (P2: continue/break snapshots + Exit PHI)
using "lang/src/shared/mir/mir_schema_box.hako" as MirSchemaBox
using selfhost.shared.mir.schema as MirSchemaBox
static box LoopFormBox {

View File

@ -9,15 +9,15 @@
using "lang/src/vm/boxes/result_box.hako" as Result
using "lang/src/vm/boxes/result_helpers.hako" as ResultHelpers
using "lang/src/shared/json/json_cursor.hako" as JsonCursorBox
using selfhost.shared.json.core.json_cursor as JsonCursorBox
using "lang/src/shared/json/json_canonical_box.hako" as JsonCanonicalBox
using "lang/src/vm/hakorune-vm/function_locator.hako" as FunctionLocatorBox
using "lang/src/vm/hakorune-vm/blocks_locator.hako" as BlocksLocatorBox
using "lang/src/vm/hakorune-vm/instrs_locator.hako" as InstrsLocatorBox
using "lang/src/vm/hakorune-vm/backward_object_scanner.hako" as BackwardObjectScannerBox
using "lang/src/vm/hakorune-vm/block_iterator.hako" as BlockIteratorBox
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
using "lang/src/shared/common/box_helpers.hako" as BoxHelpers
using selfhost.shared.common.string_helpers as StringHelpers
using selfhost.shared.common.box_helpers as BoxHelpers
static box MirIoBox {
// Internal: provider gate (yyjson)

View File

@ -1,7 +1,7 @@
// selfhost/shared/mir/mir_schema_box.hako
// MirSchemaBox — minimal MIR(JSON v0) constructors (P1 scope)
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
using selfhost.shared.common.string_helpers as StringHelpers
static box MirSchemaBox {
_expect_map(val, context) {