parser(match): add MVP type patterns (IntegerBox(x)/StringBox(s)) via AST If-chain; keep literal-only path using PeekExpr; add smoke app (apps/tests/match_type_pattern_basic.nyash); build + stage-2 smokes green

This commit is contained in:
Selfhosting Dev
2025-09-19 08:34:29 +09:00
parent f4e340da08
commit 9142476484
348 changed files with 2539 additions and 281 deletions

View File

@ -0,0 +1,72 @@
# Nyash文法改革仕様書
このフォルダには、Phase 12.7で決定されたNyash文法改革の仕様書が含まれています。
## 📄 ドキュメント一覧
### 📝 最終決定事項
- **[grammar-reform-final-decision.txt](grammar-reform-final-decision.txt)** - 文法改革の最終決定
- 予約語15個への削減
- peek構文の導入
- birth統一コンストラクタ
- フィールド宣言の明示化
### 📐 技術仕様
- **[grammar-technical-spec.txt](grammar-technical-spec.txt)** - 詳細な技術仕様書
- 構文のBNF定義
- パーサー実装ガイド
- 後方互換性の考慮事項
## 🎯 文法改革の要点
### 15個の予約語
```
box, new, me, public, if, else, loop, break, continue,
peek, return, import, from, birth, fn
```
### 主要な変更点
#### 1. peek構文switch/case代替
```nyash
peek value {
"hello" => print("Hi!")
42 => print("The answer")
else => print("Other")
}
```
#### 2. birth統一コンストラクタ
```nyash
box Life {
init { name, energy }
birth(lifeName) { // すべてのBoxでbirth使用
me.name = lifeName
me.energy = 100
}
}
```
#### 3. fn{}でFunctionBox作成
```nyash
local add = fn{a, b => a + b}
```
#### 4. フィールド宣言の明示化
```nyash
box Person {
init { name, age } // フィールドを明示的に宣言
}
```
## 🔄 実装状況
- ✅ 仕様決定完了
- ✅ ChatGPT5による基本実装
- 🔄 テスト作成中
- 📅 完全移行Phase 12.7-B
---
詳細な実装については、implementation/フォルダを参照してください。

View File

@ -0,0 +1,231 @@
================================================================================
Nyash文法改革 - 最終決定事項(実装向け)
2025-09-03
================================================================================
【Phase 12.7: 文法改革の完全仕様】
================================================================================
1. 予約語リスト(最終版)
================================================================================
合計15個の予約語
1. box - Box定義
2. new - インスタンス生成
3. me - 自己参照
4. public - 公開指定(デフォルトは非公開)
5. if - 条件分岐
6. else - else節
7. loop - ループ(唯一の形式)
8. break - ループ脱出
9. continue - 次の反復へスキップ
10. peek - 分岐構文旧when※※※新決定※※※
11. return - 関数リターン
12. import - モジュール読み込み
13. from - デリゲーション/親メソッド呼び出し
14. birth - コンストラクタEverything is Box哲学
15. fn - 関数定義/関数Box生成
================================================================================
2. peek構文分岐構文
================================================================================
【基本構文】
peek <expression> {
<pattern> => <expression-or-block>
<pattern> => <expression-or-block>
else => <expression-or-block> // else必須
}
【3つの形式】
// 単一式
peek animal {
"dog" => bark()
"cat" => meow()
else => silent()
}
// ブロック式(最後の式が値)
peek type {
"error" => {
log("Error occurred")
local message = getErrorMessage()
notifyAdmin(message)
message // これがpeekの値
}
else => "ok"
}
// 関数Box新しいスコープ
peek operation {
"factorial" => fn(n) {
if n <= 1 { return 1 }
return n * me(n - 1) // meは関数Box自身
}(5)
else => fn() { return 1 }()
}
【重要な仕様】
- peekは「式」値を返す
- else節は必須非網羅エラーを防ぐ
- returnはpeekではなく関数から脱出
- =>の右側は式、ブロック、関数Boxのいずれか
- パターンは当初「リテラルの等値比較」のみ
================================================================================
3. フィールド宣言Box内
================================================================================
【基本形式】
box ClassName {
// フィールド宣言(最上部に配置)
fieldName: TypeBox // デフォルト非公開
public fieldName: TypeBox // 公開フィールド
// コンストラクタ
birth(params) {
// 初期化処理
}
// メソッド
methodName(params) {
// 処理
}
}
【具体例】
box Counter {
count: IntegerBox
public name: StringBox
cache: MapBox = new MapBox() // デフォルト値も可能
birth(name) {
me.name = name
me.count = 0
// cacheは既に初期化済み
}
}
================================================================================
4. デリゲーション構文
================================================================================
box Child from Parent {
additionalField: StringBox
birth(name, extra) {
from Parent.birth(name) // 親のコンストラクタ呼び出し
me.additionalField = extra
}
// メソッドオーバーライド(@overrideは将来検討
process() {
Parent::process() // 親メソッド呼び出し(::記法)
// または
from Parent.process() // 従来記法も可
}
}
================================================================================
5. fn関数Boxの拡張
================================================================================
【用途】
1. トップレベル関数定義
2. インライン関数Box作成クロージャ
【例】
// 通常の関数定義
fn add(a, b) {
return a + b
}
// インライン関数Box
local counter = fn() {
local count = 0
return {
increment: fn() { count = count + 1 },
get: fn() { return count }
}
}()
// peek内での使用
peek operation {
"make_adder" => fn(x) {
return fn(y) { return x + y } // クロージャ
}
else => fn() { return null }
}
【重要】
- fn{} は新しいスコープ関数Boxを作る
- {} だけは単なるブロック(スコープ共有)
- meの意味が変わる関数Box内では関数自身
================================================================================
6. その他の重要事項
================================================================================
【セミコロン】
- 基本的に不要(改行が文の区切り)
- 1行に複数文を書く場合のみ使用可
【変数宣言】
- local x = 42 // ローカル変数
- 未宣言変数への代入はエラー
【論理演算子】
- not, and, or を使用(!, &&, || は非推奨)
【型チェック】
- typeof()関数 + peek構文で実現
- 例: peek typeof(value) { "StringBox" => ... }
================================================================================
7. 実装優先順位
================================================================================
P0即実装:
1. パーサーにpeek構文追加
2. continue追加
3. フィールド宣言の name: Type 形式
4. birth統一
P1次フェーズ:
1. Parent::method() 記法
2. fn{} クロージャ完全実装
3. OptionBox/ResultBox標準化
P2将来検討:
1. パターンマッチング拡張
2. @override等の属性
3. 構文糖衣nyan等のエイリアス
================================================================================
8. パーサー実装への注意点
================================================================================
- peek <expr> { の識別
- => トークンの追加
- else必須チェック
- ブロックと関数Boxの区別fnキーワードの有無
- returnのスコープ最も内側の関数から脱出
================================================================================
9. MIR/VM/LLVM実装指針
================================================================================
【MIR】
- PeekExpr { scrutinee, arms: [(Pattern, Expr)], else_expr }
- Pattern は当初 Literal のみ
- 将来的に Pattern を拡張可能な設計に
【VM】
- 小規模: if-else連鎖
- 大規模: ジャンプテーブル最適化
【LLVM】
- 整数: switch命令
- 文字列: ハッシュテーブル or 二分探索
================================================================================

View File

@ -0,0 +1,267 @@
================================================================================
Nyash文法改革 - 技術仕様書(パーサー実装向け)
2025-09-03
================================================================================
1. トークン定義
================================================================================
【予約語Keywords】15個
- box, new, me, public, if, else, loop, break, continue
- peek, return, import, from, birth, fn
【演算子・記号Operators/Symbols
- 算術: + - * / %
- 比較: == != < > <= >=
- 論理: and or not
- 代入: =
- アクセス: . (ドット) [ ] (インデックス)
- 関数: ( ) { }
- 区切り: , ;
- 型注釈: :
- peekアーム: =>
- 親メソッド: ::
- コメント: // /* */
【リテラルLiterals
- 整数: /[0-9]+/
- 浮動小数: /[0-9]+\.[0-9]+/
- 文字列: /"([^"\\]|\\.)*"/
- 真偽値: true false
- null値: null
【識別子Identifier
- /[a-zA-Z_][a-zA-Z0-9_]*/
- 予約語と衝突しない
【空白・改行】
- 改行は文の区切り(セミコロン自動挿入規則適用)
- インデント: 意味を持たないPython風ではない
- 行継続: \ で明示的に次行へ続く
================================================================================
2. 式構文Expression Grammar
================================================================================
【優先順位(高→低)】
1. リテラル、識別子、(式)
2. 関数呼び出し: expr(args)
3. メンバアクセス: expr.member
4. インデックス: expr[index]
5. 単項演算: not expr, -expr
6. 乗除: * / %
7. 加減: + -
8. 比較: < > <= >= == !=
9. 論理積: and
10. 論理和: or
11. peek式: peek expr { ... }
【結合規則】
- 算術演算子: 左結合
- 比較演算子: 非結合a < b < c は不可)
- 論理演算子: 左結合
【式の種類】
```
Expression ::=
| Literal
| Identifier
| "me"
| Expression "." Identifier // メンバアクセス
| Expression "[" Expression "]" // インデックス
| Expression "(" ExprList? ")" // 関数呼び出し
| "new" Identifier "(" ExprList? ")" // インスタンス生成
| "fn" "(" ParamList? ")" Block // 関数Box
| PeekExpression
| BinaryOp
| UnaryOp
| "(" Expression ")"
```
【peek式】
```
PeekExpression ::=
"peek" Expression "{"
PeekArm*
"else" "=>" (Expression | Block)
"}"
PeekArm ::=
Pattern "=>" (Expression | Block)
Pattern ::=
| Literal // 現在はリテラルのみ
| Pattern "|" Pattern // 将来: 複数パターン
```
================================================================================
3. 文構文Statement Grammar
================================================================================
```
Statement ::=
| Expression // 式文
| "local" IdentList ("=" ExprList)? // 変数宣言
| Identifier "=" Expression // 代入
| "if" Expression Block ("else" (Block | Statement))?
| "loop" "(" Expression ")" Block
| "break"
| "continue"
| "return" Expression?
| BoxDeclaration
| FunctionDeclaration
| "import" StringLiteral ("as" Identifier)?
Block ::= "{" Statement* "}"
BoxDeclaration ::=
"box" Identifier ("from" IdentList)? "{"
FieldDeclaration*
MethodDeclaration*
"}"
FieldDeclaration ::=
("public")? Identifier ":" Identifier ("=" Expression)?
MethodDeclaration ::=
("public")? (Identifier | "birth") "(" ParamList? ")" Block
```
================================================================================
4. 名前解決規則
================================================================================
【スコープ】
1. グローバルスコープbox、関数定義
2. Box内スコープフィールド、メソッド
3. 関数スコープ引数、local変数
4. ブロックスコープ({}内のlocal
【シャドーイング】
- 内側のスコープが外側を隠蔽
- 同一スコープ内での再定義は不可
【meの解決】
- Box内: 現在のBoxインスタンス
- fn{}内: 関数Box自身
- それ以外: エラー
【from Parent.method()の解決】
- 現在のBoxがParentにデリゲートしているか確認
- Parent::method()も同様
================================================================================
5. 曖昧性と解決策
================================================================================
【左再帰なし】
- 全て右再帰または反復で記述
【最長一致】
- トークナイザーレベルで最長一致
- 例: ">=" は2文字演算子として認識
【バックトラック不要】
- LL(1)またはLL(2)で解析可能
- peekトークンで次の構文要素を判別
【曖昧箇所】
1. 関数呼び出し vs 変数
- 解決: "("の有無で判別
2. {} がブロックか関数Boxか
- 解決: 直前のfnキーワードで判別
3. セミコロン自動挿入
- 改行時に次が中置演算子でない場合挿入
- 例外: 行末が不完全な式の場合は挿入しない
================================================================================
6. エラー処理
================================================================================
【期待トークンエラー】
```
Expected 'token' but found 'actual'
at line X, column Y
```
【回復戦略】
1. 文レベル: 次の文開始トークンまでスキップ
2. ブロックレベル: 対応する}までスキップ
3. Box/関数レベル: 次のbox/fnまでスキップ
【行・列の追跡】
- 各トークンに位置情報を付与
- エラー時は該当箇所を表示
【エラーメッセージ例】
```
Error: Missing 'else' in peek expression
--> program.nyash:10:5
|
10 | peek value {
| ^^^^ peek expression requires 'else' branch
```
================================================================================
7. 将来拡張の余地
================================================================================
【予約済み位置】
- @ 記号: 将来の属性用
- # 記号: 将来のマクロ用
- ` 記号: 将来のテンプレート用
【拡張可能な構文】
- Pattern: 現在はリテラルのみ、将来は構造体パターン等
- 型注釈: 現在は : Type のみ、将来はジェネリクス等
【前方互換性】
- 未知の @ で始まる行は読み飛ばし
- box内の未知セクションは警告のみ
================================================================================
8. 既存実装への差分最小化
================================================================================
【tokenizer.rs への変更】
1. 予約語リストにpeek, continue, birthを追加
2. => を2文字演算子として追加
3. :: を2文字演算子として追加
【parser.rs への変更】
1. parse_when() → parse_peek() に改名
2. parse_field_declaration() を追加name: Type形式
3. parse_fn_literal() を追加fn式のため
4. continue文の処理追加
5. birthキーワードの特殊処理
【AST変更】
```rust
// 追加
enum Expr {
// ...
Peek {
scrutinee: Box<Expr>,
arms: Vec<(Pattern, BlockOrExpr)>,
else_arm: Box<BlockOrExpr>,
},
FnLiteral {
params: Vec<String>,
body: Block,
},
}
enum Stmt {
// ...
Continue,
}
```
【セマンティクス】
- peekは式として値を返す
- else必須のバリデーション追加
- returnは最内関数スコープから脱出
================================================================================