Files
hakorune/docs/reference/language/statements.md
nyash-codex 4b6b75932c chore(phase152-b): Static method 宣言整理(箱化モジュール化)
- MainDetectionHelper で main() 検出ロジックを箱化
- Legacy "static method main" と Modern "static box Main { main() }" の両パターン対応
- stage1_run_min.hako を modern 形式に統一
- ドキュメント更新(quickstart 等で static box スタイルに統一)
- パーサ新構文追加なし(仕様統一性保持)
- 後方互換性維持(Stage-B ヘルパーで legacy もサポート)
- テスト結果: 全スモーク PASS

Phase 152-B: Static Method 宣言の整理(Stage-3 仕様統一)

実装パターン: 箱化モジュール化(Phase 133/134 継承)

修正ファイル:
- lang/src/compiler/entry/compiler_stageb.hako: MainDetectionHelper (+103 lines)
- lang/src/compiler/entry/compiler.hako: Legacy Stage-A コメント (+3 lines)
- apps/tests/stage1_run_min.hako: Modern syntax に統一 (-1 line)
- docs/development/selfhosting/quickstart.md: サンプルコード更新
- CURRENT_TASK.md: Phase 152-B 完了記録

MainDetectionHelper 設計:
- findMainBody(): Entry point
- tryLegacyPattern(): "static method main" detection
- tryModernPattern(): "static box Main { main() }" detection
- findPattern(): Pattern search helper
- extractBodyFromPosition(): Brace matching extraction

利点:
 明確な責任分離(各パターン検出が独立モジュール)
 テスタビリティ(各メソッド個別テスト可能)
 拡張性(新パターン追加時は新メソッド追加のみ)
 後方互換性(Legacy パターン削除は tryLegacyPattern 削除のみ)

テスト結果:
- stage1_run_min.hako: RC 0
- Selfhost depth-1: RC 0
- 全スモーク: 30/31 PASS (1 timeout は無関係)
2025-12-04 13:54:45 +09:00

4.0 KiB
Raw Permalink Blame History

Statement Separation and Semicolons

Status: Adopted for Phase 15.3+; parser implementation is staged.

Policy

  • Newline as primary statement separator.
  • Semicolons are optional and only needed when multiple statements appear on one physical line.
  • Minimal ASI (auto semicolon insertion) rules to avoid surprises.

Rules (minimal and predictable)

  • Newline ends a statement when:
    • Parenthesis/brace/bracket depth is 0, and
    • The line does not end with a continuation token (+ - * / . , etc.).
  • Newline does NOT end a statement when:
    • Inside any open grouping (...), [...], {...}; or
    • The previous token is a continuation token.
  • return/break/continue end the statement at newline unless the value is on the same line or grouped via parentheses.
  • if/else (and similar paired constructs): do not insert a semicolon between a block and a following else.
  • Oneline multistatements are allowed with semicolons: x = 1; y = 2; print(y).
  • Method chains can break across lines after a dot: obj\n .method() (newline treated as whitespace).

Style guidance

  • Prefer newline separation (no semicolons) for readability.
  • Use semicolons only when placing multiple statements on a single line.

Examples

// Preferred (no semicolons)
local x = 5
x = x + 1
print(x)

// One line with multiple statements (use semicolons)
local x = 5; x = x + 1; print(x)

// Line continuation by operator
local n = 1 +
          2 +
          3

// Grouping across lines
return (
  1 + 2 + 3
)

// if / else on separate lines without inserting a semicolon
if cond {
  x = x - 1
}
else {
  print(x)
}

// Dot chain across lines
local v = obj
  .methodA()
  .methodB(42)

// Grouped assignment as expression (Stage3)
local y = (x = x + 1)    # (x = x + 1) が 1 を返す式として扱われる
if (x = next()) != null {
  print(x)
}

Implementation notes (parser)

  • Tokenizer keeps track of grouping depth.
  • At newline, attempt ASI only when depth==0 and previous token is not a continuation.
  • Error messages should suggest adding a continuation token or grouping when a newline unexpectedly ends a statement.

Parser dev notes (Stage1/2)

  • return + newline: treat bare return as statement end. To return an expression on the next line, require grouping with parentheses.
  • if/else: never insert a semicolon between a closed block and else (ASI禁止箇所)。
  • Dot chains: treat . followed by newline as whitespace (line continuation)。
  • Oneline multistatements: accept ; as statement separator, but formatter should prefer newlines.
  • Unary minus: disambiguate from binary minus; implement after Stage1当面は括弧で回避

Assignment ExpressionsStage3 追加仕様)

Stage3 では、制御構造や短絡評価との相性を良くするために「括弧付き代入を式として扱う」最小拡張を導入するよ。

Rules

  • x = expr は従来通り 代入文statement として扱う。
  • '(x = expr)' のように 括弧で囲まれた代入 だけを、値を返す式expressionとして扱う。
    • 値と型は右辺 expr と同じになる((x = 1) の値は 1)。
  • この拡張は Stage3 パーサーのみで有効Rust: NYASH_FEATURES=stage3 / selfhost: --stage3/NYASH_NY_COMPILER_STAGE3=1)。

Examples

# 依然として「文」
x = x + 1

# こちらは「値を返す式」
local y = (x = x + 1)   # y と x の両方が 1 増える

if (x = next()) != null {
  print("got: " + x)
}

return (counter = counter + 1)

Notes実装指針

  • EBNF 上は assignment_expr := IDENT '=' expr を定義し、factor '(' assignment_expr ')' を追加する形で表現する。
  • lowering では「代入命令 + その結果値を表す SSA 値」を 1 セットで生成し、その ValueId を式の値として返す。
  • 仕様を広げすぎないため、当面は「括弧付き代入のみ式扱い」とし、裸の x = expr を expression 文に自動昇格するような拡張は行わない。