feat(constructor): implement birth() syntax and pack transparency system

## 🌟 birth() Constructor Implementation
- Add BIRTH token to tokenizer (src/tokenizer.rs:37,403)
- Implement birth() parser support (src/parser/mod.rs)
- Add birth() interpreter support with priority system
- Priority: birth > pack > init > Box名

## 🚨 Fix Documentation Inconsistencies
- Fix delegation-system.md: pack → birth unified
- Fix box-design/README.md: add pack-specific section
- Fix LANGUAGE_GUIDE.md: birth unified, pack builtin-only
- Fix CLAUDE.md: birth philosophy, pack system separation

## 📋 pack Transparency System Design
- Create phase_8_8_pack_transparency_system.md specification
- Establish correct pack definition: builtin Box inheritance only
- Design user-transparent system: from BuiltinBox() → internal pack
- Comprehensive test cases and implementation requirements

## 🧪 Testing
- Add test_birth_simple.nyash: birth() functionality verification
- Document constructor name decision process
- Prepare for Copilot implementation with clear specifications

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-15 19:34:26 +09:00
parent 6bb288b694
commit 6b62209da9
13 changed files with 727 additions and 44 deletions

View File

@ -122,30 +122,56 @@ while condition { } // 使用不可
loop() { } // 使用不可
```
### 🎁 pack構文 - Box哲学の具現化2025-08-11実装)
### 🌟 birth構文 - 生命をBoxに与える2025-08-15実装)
```nyash
// 🎁箱に詰める」直感的コンストラクタ
box User {
init { name, email }
// 🌟Boxに生命を与える」直感的コンストラクタ
box Life {
init { name, energy }
pack(userName, userEmail) { // ← Box哲学を体現
me.name = userName
me.email = userEmail
birth(lifeName) { // ← Everything is Box哲学を体現
me.name = lifeName
me.energy = 100
print("🌟 " + lifeName + " が誕生しました!")
}
}
// 🔄 デリゲーションでのpack
box AdminUser from User {
init { permissions }
// 🔄 デリゲーションでのbirth
box Human from Life {
init { intelligence }
pack(adminName, adminEmail, perms) {
from User.pack(adminName, adminEmail) // 親のpackを呼び出し
me.permissions = perms
birth(humanName) {
from Life.birth(humanName) // 親のbirthを呼び出し
me.intelligence = 50
}
}
// ✅ 優先順位: pack > init > Box名形式
local user = new User("Alice", "alice@example.com") // packが使われる
// ✅ 優先順位: birth > pack > init > Box名形式
local alice = new Human("Alice") // birthが使われる
```
### 🚨 pack構文 - ビルトインBox継承専用
```nyash
// ⚠️ pack構文はビルトインBox継承専用ユーザー定義Boxでは使わない
box EnhancedP2P from P2PBox {
init { features }
pack(nodeId, transport) {
from P2PBox.pack(nodeId, transport) // ビルトイン初期化
me.features = new ArrayBox()
}
override send(intent, data, target) {
me.features.push("send:" + intent)
return from P2PBox.send(intent, data, target)
}
}
// ❌ 間違い: ユーザー定義Boxでpack使用
box RegularUser {
pack(name) { // これは間違いbirth()を使う
me.name = name
}
}
```
### 🎯 正統派Nyashスタイル2025-08-09実装

View File

@ -7,6 +7,70 @@
- **Arc::ptr_eq()検出**: 真のゼロコピー判定実現 ✅
- **新API978行追加**: すべて正常ビルド・実行成功 ✅
## 🚨 **コンストラクタ構文統一の緊急実装 (2025-08-15)**
### **🌟 birth()実装完了 → pack透明化設計** ✅
**birth()統一構文実装完了**!次は**pack透明化システム**の実装が必要
### **🎯 pack透明化設計 - ユーザー完全不可視システム**
**核心方針**: ユーザーは`pack`を一切書かない・意識しない
### **📋 ユーザー側の理想的な書き方**
```nyash
# ✅ ユーザーはこう書くpackを一切意識しない
box EnhancedString from StringBox {
init { prefix }
birth(content, prefixStr) {
from StringBox(content) # ← シンプルな呼び出し
me.prefix = prefixStr
}
override toString() {
return me.prefix + from StringBox.toString()
}
}
```
### **🔧 実装側の内部動作**
```rust
// from StringBox(content) の解決優先度
fn resolve_builtin_delegation(builtin: &str, args: Vec<_>) -> String {
if is_builtin_box(builtin) {
// 1. ビルトインBoxの場合、内部的にpackを呼ぶ
builtin_pack_registry.call_pack(builtin, args)
} else {
// 2. ユーザー定義Boxの場合、birth優先
resolve_user_constructor(builtin, args) // birth > init > Box名
}
}
```
### **🎯 実装すべきこと**
**1. ビルトインBox自動判定**
- `is_builtin_box()` 関数実装
- StringBox, P2PBox, MathBox等をビルトイン登録
**2. pack透明化システム**
- `from BuiltinBox()` → 内部的に `BuiltinBox.pack()` 呼び出し
- ユーザーは`pack`という単語を見ない・書かない
**3. デリゲーション解決統一**
- ビルトインBox: 自動pack呼び出し
- ユーザー定義Box: birth > init > Box名 優先順位
**4. エラーメッセージ改善**
- ユーザーには「birth()がありません」と表示
- packエラーは内部ログのみ
### **🎉 期待される効果**
- **完全透明化**: ユーザーはpackを一切意識しない
- **統一体験**: `from Parent()` で全て解決
- **設計分離**: ビルトインBox内部実装とユーザーAPI完全分離
## 🔄 **次期優先タスク**
**GitHub Issue**: https://github.com/moe-charm/nyash/issues/98
**移植計画**: 3つの実用Cアプリケーション同時移植プロジェクト
@ -36,6 +100,61 @@
- **実行性能**: WASM 13.5倍、VM 20.4倍高速化達成
- **Everything is Box哲学**: 全11個のBox型でRwLock統一完了
## 🔥 **実装優先度**
### **🚨 Critical (即時実装)**
1. **ビルトインBox判定システム** - is_builtin_box()実装15分
2. **pack透明化解決** - from BuiltinBox()自動変換30分
3. **統合テスト作成** - 透明化動作確認10分
### **⚡ High (今週中)**
4. **エラーメッセージ改善** - pack隠蔽、birth中心メッセージ
5. **ドキュメント更新** - CLAUDE.md透明化設計反映
6. **パフォーマンス最適化** - ビルトイン判定高速化
### **📝 Medium (来週)**
7. **既存テスト見直し** - pack直接呼び出し削除
8. **delegation-system.md更新** - 透明化設計反映
### **🔮 Future (今後の予定)**
9. **FFI/ABI統合** - ExternBox経由外部APIPhase 11予定
10. **動的ライブラリ読み込み** - 外部ライブラリBox化Phase 12予定
11. **BID自動生成** - YAML→実装自動化Phase 13予定
## 🚀 **Phase 8.8: pack透明化システム実装準備完了**
### **✅ 完了事項 (2025-08-15)**
1. **birth()実装完了** - コンストラクタ統一構文実装 ✅
2. **ドキュメント矛盾修正完了** - pack機能正しい定義確立 ✅
3. **pack透明化イシュー作成完了** - Copilot実装仕様書完成 ✅
### **📋 ドキュメント修正完了リスト**
-`delegation-system.md` - pack→birth統一、pack専用セクション追加
-`box-design/README.md` - pack専用セクション追加
-`LANGUAGE_GUIDE.md` - birth統一、pack専用明記
-`CLAUDE.md` - birth哲学、pack専用システム分離
### **🎯 次のアクション (Copilot実装待ち)**
**イシュー**: `phase_8_8_pack_transparency_system.md`
#### **実装内容**
1. **ビルトインBox判定システム** - `is_builtin_box()` 関数
2. **pack透明化解決** - `from BuiltinBox()` 自動変換
3. **エラーメッセージ改善** - pack隠蔽、ユーザーフレンドリー化
#### **必須テストケース (5種類)**
- ユーザー定義Box基本動作
- ビルトインBox継承
- **透明化システム動作** (最重要)
- 混在テスト
- エラーケーステスト
#### **完了条件**
- 全テストケース PASS
- 既存機能継続動作
- パフォーマンス維持
- ユーザーはpackを一切意識しない
---
**現在状況**: Phase 9.75完了 → Phase 9.5 HTTPサーバー実用テスト準備中
**最終更新**: 2025-08-15
**現在状況**: pack透明化システム実装準備完了Copilot実装開始待ち🤖
**最終更新**: 2025-08-15 17:00

View File

@ -0,0 +1,115 @@
# 🌟 Nyash コンストラクタ名決定: birth() 採用
**決定日**: 2025-08-15
**決定者**: Nyashプロジェクトチーム
**ステータス**: 正式決定
## 🎯 **最終決定**
**`birth()` を唯一のコンストラクタ名として採用**
## 📋 **検討経過**
### 候補と評価
1. **constructor()** - 業界標準だが長い、Box哲学との親和性低い
2. **pack()** - Box哲学完璧だが独自性強すぎ、混乱の元
3. **init()** - initフィールドとの混乱、廃止済み
4. **make()** - Go言語実績あり、短い、実用的
5. **birth()** - 🌟 **採用決定** 🌟
### birth() 選定理由
**1. 哲学的完璧性**
- 「Everything is Box」哲学との完璧な親和性
- 「Boxに魂が宿る」生命感のある言語思想を体現
- 「生命を誕生させる」直感的イメージ
**2. 強力なブランディング効果**
- 圧倒的独自性で一度見たら忘れない
- Nyashらしさを言語の核心で表現
- 学習者がコンストラクタを使うたびに世界観を体感
**3. 実用性**
- 短い5文字で覚えやすい
- 学習コストは低い(初見で一瞬考えるだけ)
- 明確で曖昧性がない
## 💡 **Geminiの専門的評価**
> 「`birth()` を採用することは、単なる名前選び以上の意味を持つ。それは、**Nyashの哲学を言語の根幹に据えるという宣言**である。学習者はコンストラクタを使うたびに、無意識にその世界観に触れることになる。これは非常に強力なブランディングです。」
**Gemini最終推奨**: `birth()` 採用
## 🌟 **構文例**
```nyash
// 基本的な使用法
box Life {
init { name, energy }
birth(lifeName) { // 生命を誕生させる
me.name = lifeName
me.energy = 100
print("🌟 " + lifeName + " が誕生しました!")
}
}
// デリゲーション
box Human from Life {
init { intelligence }
birth(humanName) {
from Life.birth(humanName) // 親から生命を受け継ぐ
me.intelligence = 50
}
}
// 使用例
local alice = new Human("Alice") // birth()が自動呼び出し
```
## 🔧 **実装要件**
### 1. トークナイザー修正
```rust
BIRTH, // birth (コンストラクタ)
"birth" => TokenType::BIRTH,
```
### 2. パーサー修正
- `birth()` 構文パース対応
- `init/pack/constructor` と同様の処理システム統合
### 3. インタープリター修正
- `birth/引数数` キーでの検索対応
- デリゲーション時の `from Parent.birth()` サポート
### 4. 優先順位システム
```rust
// 検索順序
1. "birth/引数数" // 最優先
2. "init/引数数" // 互換性
3. "pack/引数数" // 互換性
4. "Box名/引数数" // 互換性
```
## 🎉 **期待される効果**
- **哲学的一貫性**: Everything is Box思想の完璧な体現
- **ブランド確立**: Nyash独自の世界観を言語レベルで表現
- **学習体験向上**: コンストラクタ使用のたびに世界観を体感
- **混乱解消**: initフィールドとの完全な区別
- **統一性**: 全てのBoxで同一のbirth()構文
## 📝 **移行計画**
1. **Phase 1**: birth()実装(トークナイザー・パーサー・インタープリター)
2. **Phase 2**: テスト作成・動作確認
3. **Phase 3**: 既存コード段階的移行(互換性維持)
4. **Phase 4**: ドキュメント更新CLAUDE.md等
---
**🌟 Nyashは `birth()` でBoxに生命を与える言語として、新たな進化を遂げる 🌟**

View File

@ -0,0 +1,226 @@
# Phase 8.8: pack透明化システム実装
**Priority**: Critical
**Estimated Effort**: 2-3日
**Assignee**: Copilot (Claude監修)
**Status**: Ready for Implementation
## 🎯 概要
**pack構文のユーザー完全透明化システム**を実装する。ユーザーは`pack`を一切意識せず、`from BuiltinBox()`で自動的に内部のpack機能が呼ばれるシステム。
### 🚨 背景問題
- **Copilotがpack機能を誤解**:一般コンストラクタとして実装
- **ドキュメント矛盾**packの定義が混乱していた ✅ 修正済み
- **ユーザー体験悪化**packを意識する必要があった
## 📋 実装要件
### 1. **ビルトインBox判定システム**
```rust
// 実装必要な関数
fn is_builtin_box(box_name: &str) -> bool {
// StringBox, P2PBox, MathBox, ConsoleBox等を判定
}
// 登録リスト (最低限)
const BUILTIN_BOXES: &[&str] = &[
"StringBox", "IntegerBox", "BoolBox", "NullBox",
"P2PBox", "MathBox", "ConsoleBox", "DebugBox",
"TimeBox", "RandomBox", "SoundBox", "MapBox"
];
```
### 2. **pack透明化解決システム**
```rust
// from BuiltinBox() の自動解決
fn resolve_builtin_delegation(builtin: &str, args: Vec<_>) -> Result<(), String> {
if is_builtin_box(builtin) {
// 内部的に BuiltinBox.pack() を呼ぶ
call_builtin_pack(builtin, args)
} else {
// ユーザー定義Box: birth > init > Box名 の順
resolve_user_constructor(builtin, args)
}
}
```
### 3. **エラーメッセージ改善**
- ユーザーには「birth()がありません」表示
- pack関連エラーは内部ログのみ
- 混乱を避ける明確なメッセージ
## 🧪 テスト要件
### **必須テストケース** (全て PASS 必須)
#### **A. ユーザー定義Box基本動作**
```nyash
# test_user_box_basic.nyash
box Life {
init { name, energy }
birth(lifeName) {
me.name = lifeName
me.energy = 100
}
}
local alice = new Life("Alice")
assert(alice.name == "Alice")
assert(alice.energy == 100)
```
#### **B. ビルトインBox継承**
```nyash
# test_builtin_inheritance.nyash
box EnhancedP2P from P2PBox {
init { features }
pack(nodeId, transport) {
from P2PBox.pack(nodeId, transport) # 明示的pack
me.features = new ArrayBox()
}
}
local node = new EnhancedP2P("node1", "tcp")
assert(node.features != null)
```
#### **C. 透明化システム動作**
```nyash
# test_transparency.nyash
box SimpleString from StringBox {
init { prefix }
birth(content, prefixStr) {
from StringBox(content) # ← 透明化内部的にpack呼び出し
me.prefix = prefixStr
}
override toString() {
return me.prefix + from StringBox.toString()
}
}
local str = new SimpleString("Hello", ">>> ")
assert(str.toString() == ">>> Hello")
```
#### **D. 混在テスト**
```nyash
# test_mixed_inheritance.nyash
box AdvancedCalc from MathBox {
init { history }
birth() {
from MathBox() # 透明化
me.history = new ArrayBox()
}
}
box Calculator {
init { result }
birth() {
me.result = 0
}
}
local calc1 = new AdvancedCalc() # ビルトイン継承
local calc2 = new Calculator() # ユーザー定義
assert(calc1.history != null)
assert(calc2.result == 0)
```
#### **E. エラーケーステスト**
```nyash
# test_error_cases.nyash
# 1. 存在しないmethodを呼び出し
box BadBox from StringBox {
birth(content) {
from StringBox.nonexistent() # エラー:適切なメッセージ
}
}
# 2. 引数不一致
box ArgMismatch from P2PBox {
birth() {
from P2PBox("too", "many", "args") # エラー:引数不一致
}
}
```
### **パフォーマンステスト**
```nyash
# test_performance.nyash
local startTime = getCurrentTime()
loop(i < 1000) {
local str = new SimpleString("test" + i, "prefix")
local result = str.toString()
}
local endTime = getCurrentTime()
local elapsed = endTime - startTime
assert(elapsed < 1000) # 1秒以内で完了
```
## ✅ チェックリスト
### **実装前チェック**
- [ ] 既存のbirth()実装が正常動作している
- [ ] ドキュメント修正が完了している
- [ ] テストファイルが準備されている
### **実装中チェック**
- [ ] `is_builtin_box()` 関数実装完了
- [ ] pack透明化解決システム実装完了
- [ ] エラーメッセージ改善完了
- [ ] 全テストケース PASS
### **実装後チェック**
- [ ] 既存テストファイルが継続動作
- [ ] パフォーマンス劣化なし(<5%
- [ ] birth()優先順位システム正常動作
- [ ] エラーメッセージがユーザーフレンドリー
### **統合テスト**
- [ ] `test_birth_simple.nyash` 継続動作
- [ ] Chip-8エミュレーター修正版動作
- [ ] 全ビルトインBox継承パターン動作
- [ ] デリゲーションチェーン正常動作
## 📂 実装場所
### **主要ファイル**
- `src/interpreter/expressions.rs` - from解決ロジック
- `src/interpreter/objects.rs` - コンストラクタ優先順位
- `src/interpreter/core.rs` - ビルトインBox判定
- `src/box_trait.rs` - BUILTIN_BOXES定数
### **テストファイル**
- `test_pack_transparency.nyash` - 統合テスト
- `test_builtin_inheritance.nyash` - ビルトイン継承
- `test_user_box_birth.nyash` - ユーザー定義Box
- `test_error_cases.nyash` - エラーケース
## 🎉 完了条件
1. **全テストケース PASS**
2. **既存機能の継続動作**
3. **パフォーマンス維持**
4. **エラーメッセージ改善**
5. **ドキュメント整合性**
## 🚨 注意事項
- **既存のbirth()実装は変更しない**
- **pack機能自体は残す**ビルトイン継承で必要
- **ユーザーAPIからpackを完全隠蔽**
- **パフォーマンス劣化は避ける**
---
**実装時は必ずテストファースト開発で進める!** 🧪

View File

@ -65,9 +65,10 @@ not condition, a and b, a or b
box User {
init { name, email } // フィールド宣言
pack(userName, userEmail) { // 🎁 Box哲学の具現化
birth(userName, userEmail) { // 🌟 生命をBoxに与える
me.name = userName
me.email = userEmail
print("🌟 " + userName + " が誕生しました!")
}
greet() {
@ -81,8 +82,8 @@ box User {
box AdminUser from User { // 🔥 from構文でデリゲーション
init { permissions }
pack(adminName, adminEmail, perms) {
from User.pack(adminName, adminEmail) // 親のpack呼び出し
birth(adminName, adminEmail, perms) {
from User.birth(adminName, adminEmail) // 親のbirth呼び出し
me.permissions = perms
}
@ -93,6 +94,25 @@ box AdminUser from User { // 🔥 from構文でデリゲーション
}
```
#### ビルトインBox継承pack専用
```nyash
// ⚠️ pack構文はビルトインBox継承専用
box EnhancedP2P from P2PBox {
init { features }
pack(nodeId, transport) {
from P2PBox.pack(nodeId, transport) // ビルトイン初期化
me.features = new ArrayBox()
print("🌐 Enhanced P2P Node created: " + nodeId)
}
override send(intent, data, target) {
me.features.push("send:" + intent)
return from P2PBox.send(intent, data, target)
}
}
```
#### Static Box Main パターン
```nyash
static box Main {

View File

@ -63,9 +63,10 @@ local num = new IntegerBox(42)
box User {
init { name, email }
pack(userName, userEmail) {
birth(userName, userEmail) {
me.name = userName
me.email = userEmail
print("🌟 User " + userName + " が誕生しました!")
}
}
```
@ -75,8 +76,8 @@ box User {
box AdminUser from User {
init { permissions }
pack(adminName, adminEmail, perms) {
from User.pack(adminName, adminEmail)
birth(adminName, adminEmail, perms) {
from User.birth(adminName, adminEmail)
me.permissions = perms
}
@ -86,6 +87,24 @@ box AdminUser from User {
}
```
### ビルトインBox継承pack専用
```nyash
// ビルトインBoxを継承する場合のみpackを使用
box EnhancedP2P from P2PBox {
init { features }
pack(nodeId, transport) {
from P2PBox.pack(nodeId, transport) // ビルトイン初期化
me.features = new ArrayBox()
}
override send(intent, data, target) {
me.features.push("send:" + intent)
return from P2PBox.send(intent, data, target)
}
}
```
### 外部ライブラリ統合FFI/ABI
```nyash
// ExternBoxで外部APIを統一的に利用

View File

@ -134,21 +134,22 @@ box MultiChild from ParentA, ParentB {
}
```
## 🎁 pack構文 - Box哲学の具現化
## 🌟 birth構文 - Box哲学の具現化
### packの優先順位
### コンストラクタの優先順位
```nyash
box User {
init { name, email }
// 優先度1: pack(推奨)
pack(userName, userEmail) {
// 優先度1: birth(推奨)
birth(userName, userEmail) {
me.name = userName
me.email = userEmail
print("🌟 " + userName + " が誕生しました!")
}
// 優先度2: initpackがない場合)
// 優先度2: initbirthがない場合)
init(name, email) {
me.name = name
me.email = email
@ -161,28 +162,29 @@ box User {
}
}
// packが優先的に使用される
// birthが優先的に使用される
local user = new User("Alice", "alice@example.com")
```
### packとデリゲーション
### birth構文とデリゲーション
```nyash
box Product {
init { name, price }
pack(productName, productPrice) {
birth(productName, productPrice) {
me.name = productName
me.price = productPrice
print("📦 Product created: " + productName)
}
}
box DiscountedProduct from Product {
init { discount }
pack(name, originalPrice, discountPercent) {
birth(name, originalPrice, discountPercent) {
local discountedPrice = originalPrice * (1 - discountPercent / 100)
from Product.pack(name, discountedPrice)
from Product.birth(name, discountedPrice) # 親のbirthを呼ぶ
me.discount = discountPercent
}
@ -192,6 +194,38 @@ box DiscountedProduct from Product {
}
```
### 🚨 pack構文 - ビルトインBox継承専用
**重要**: `pack`構文は**ビルトインBox継承専用**です。ユーザー定義Boxでは使用しません。
```nyash
# ✅ 正しい使い方ビルトインBox継承のみ
box EnhancedP2P from P2PBox {
init { extraFeatures }
pack(nodeId, transport) {
from P2PBox.pack(nodeId, transport) # ビルトインBoxの初期化
me.extraFeatures = new ArrayBox()
}
}
box CustomMath from MathBox {
init { history }
pack() {
from MathBox.pack() # ビルトインBoxの初期化
me.history = new ArrayBox()
}
}
# ❌ 間違いユーザー定義Boxでpack使用
box RegularUser {
pack(name) { # これは間違いbirth()を使う
me.name = name
}
}
```
## 🔍 from構文の詳細
### メソッド内でのfrom使用

View File

@ -362,7 +362,38 @@ impl NyashInterpreter {
return Ok(field_value);
}
// 4. エラー:見つからない
// 4. statics名前空間内のstatic boxをチェック
eprintln!("🔍 DEBUG: Checking statics namespace for '{}'...", name);
if let Some(statics_namespace) = global_box.get_field("statics") {
eprintln!("🔍 DEBUG: statics namespace type: {}", statics_namespace.type_name());
// MapBoxとして試す
if let Some(map_box) = statics_namespace.as_any().downcast_ref::<crate::boxes::map_box::MapBox>() {
eprintln!("🔍 DEBUG: statics is a MapBox, looking for '{}'", name);
let key_box: Box<dyn NyashBox> = Box::new(StringBox::new(name));
let static_box_result = map_box.get(key_box);
// NullBoxでないかチェックMapBoxは見つからない場合NullBoxを返す
if static_box_result.type_name() != "NullBox" {
eprintln!("🔍 DEBUG: Found '{}' in statics namespace", name);
return Ok(Arc::from(static_box_result));
} else {
eprintln!("🔍 DEBUG: '{}' not found in statics MapBox", name);
}
} else if let Some(instance) = statics_namespace.as_any().downcast_ref::<crate::instance::InstanceBox>() {
eprintln!("🔍 DEBUG: statics is an InstanceBox, looking for '{}'", name);
if let Some(static_box) = instance.get_field(name) {
eprintln!("🔍 DEBUG: Found '{}' in statics namespace", name);
return Ok(static_box);
} else {
eprintln!("🔍 DEBUG: '{}' not found in statics InstanceBox", name);
}
} else {
eprintln!("🔍 DEBUG: statics namespace is neither MapBox nor InstanceBox");
}
}
// 5. エラー:見つからない
eprintln!("🔍 DEBUG: '{}' not found anywhere!", name);
Err(RuntimeError::UndefinedVariable {
name: name.to_string(),

View File

@ -1104,8 +1104,8 @@ impl NyashInterpreter {
drop(box_declarations); // ロック早期解放
// 4. constructorまたはinitまたはpackの場合の特別処理
if method == "constructor" || method == "init" || method == "pack" || method == parent {
// 4. constructorまたはinitまたはpackまたはbirthの場合の特別処理
if method == "constructor" || method == "init" || method == "pack" || method == "birth" || method == parent {
return self.execute_from_parent_constructor(parent, &parent_box_decl, current_instance_val.clone_box(), arguments);
}
@ -1177,12 +1177,14 @@ impl NyashInterpreter {
-> Result<Box<dyn NyashBox>, RuntimeError> {
// 1. 親クラスのコンストラクタを取得(引数の数でキーを作成)
// "pack/引数数"、"init/引数数"、"Box名/引数数" の順で試す
// "birth/引数数"、"pack/引数数"、"init/引数数"、"Box名/引数数" の順で試す
let birth_key = format!("birth/{}", arguments.len());
let pack_key = format!("pack/{}", arguments.len());
let init_key = format!("init/{}", arguments.len());
let box_name_key = format!("{}/{}", parent, arguments.len());
let parent_constructor = parent_box_decl.constructors.get(&pack_key)
let parent_constructor = parent_box_decl.constructors.get(&birth_key)
.or_else(|| parent_box_decl.constructors.get(&pack_key))
.or_else(|| parent_box_decl.constructors.get(&init_key))
.or_else(|| parent_box_decl.constructors.get(&box_name_key))
.ok_or(RuntimeError::InvalidOperation {

View File

@ -713,12 +713,14 @@ impl NyashInterpreter {
let instance_arc = Arc::from(instance_box);
// コンストラクタを呼び出す
// "pack/引数数"、"init/引数数"、"Box名/引数数" の順で試す
// "birth/引数数"、"pack/引数数"、"init/引数数"、"Box名/引数数" の順で試す
let birth_key = format!("birth/{}", arguments.len());
let pack_key = format!("pack/{}", arguments.len());
let init_key = format!("init/{}", arguments.len());
let box_name_key = format!("{}/{}", actual_class_name, arguments.len());
if let Some(constructor) = final_box_decl.constructors.get(&pack_key)
if let Some(constructor) = final_box_decl.constructors.get(&birth_key)
.or_else(|| final_box_decl.constructors.get(&pack_key))
.or_else(|| final_box_decl.constructors.get(&init_key))
.or_else(|| final_box_decl.constructors.get(&box_name_key)) {
// コンストラクタを実行

View File

@ -451,6 +451,66 @@ impl NyashParser {
span: Span::unknown(),
};
// パラメータの数でコンストラクタを区別
let constructor_key = format!("{}/{}", field_or_method, params.len());
constructors.insert(constructor_key, constructor);
}
}
// birthトークンをメソッド名として特別処理
else if self.match_token(&TokenType::BIRTH) && self.peek_token() == &TokenType::LPAREN {
let field_or_method = "birth".to_string();
self.advance(); // consume 'birth'
// コンストラクタとして処理
if self.match_token(&TokenType::LPAREN) {
// birthは常にコンストラクタ
if is_override {
return Err(ParseError::UnexpectedToken {
expected: "method definition, not constructor after override keyword".to_string(),
found: TokenType::BIRTH,
line: self.current_token().line,
});
}
// コンストラクタの処理
self.advance(); // consume '('
let mut params = Vec::new();
while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() {
must_advance!(self, _unused, "constructor parameter parsing");
if let TokenType::IDENTIFIER(param) = &self.current_token().token_type {
params.push(param.clone());
self.advance();
}
if self.match_token(&TokenType::COMMA) {
self.advance();
}
}
self.consume(TokenType::RPAREN)?;
self.consume(TokenType::LBRACE)?;
let mut body = Vec::new();
while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() {
self.skip_newlines();
if !self.match_token(&TokenType::RBRACE) {
body.push(self.parse_statement()?);
}
}
self.consume(TokenType::RBRACE)?;
let constructor = ASTNode::FunctionDeclaration {
name: field_or_method.clone(),
params: params.clone(),
body,
is_static: false,
is_override: false,
span: Span::unknown(),
};
// パラメータの数でコンストラクタを区別
let constructor_key = format!("{}/{}", field_or_method, params.len());
constructors.insert(constructor_key, constructor);
@ -461,8 +521,8 @@ impl NyashParser {
// メソッド定義またはコンストラクタか?
if self.match_token(&TokenType::LPAREN) {
// Box名と同じまたは"init"または"pack"の場合はコンストラクタ
if field_or_method == name || field_or_method == "init" || field_or_method == "pack" {
// Box名と同じまたは"init"または"pack"または"birth"の場合はコンストラクタ
if field_or_method == name || field_or_method == "init" || field_or_method == "pack" || field_or_method == "birth" {
// コンストラクタはoverrideできない
if is_override {
return Err(ParseError::UnexpectedToken {

View File

@ -33,7 +33,8 @@ pub enum TokenType {
THIS,
ME,
INIT, // init (初期化ブロック)
PACK, // pack (コンストラクタ)
PACK, // pack (コンストラクタ - 互換性)
BIRTH, // birth (コンストラクタ)
NOWAIT, // nowait
AWAIT, // await
INTERFACE, // interface
@ -399,6 +400,7 @@ impl NyashTokenizer {
"me" => TokenType::ME,
"init" => TokenType::INIT,
"pack" => TokenType::PACK,
"birth" => TokenType::BIRTH,
"nowait" => TokenType::NOWAIT,
"await" => TokenType::AWAIT,
"interface" => TokenType::INTERFACE,

27
test_birth_simple.nyash Normal file
View File

@ -0,0 +1,27 @@
# 🌟 birth() テスト - 生命をBoxに与える
box Life {
init { name, energy }
birth(lifeName) { # 生命を誕生させる
me.name = lifeName
me.energy = 100
print("🌟 " + lifeName + " が誕生しました!")
}
introduce() {
print("私の名前は " + me.name + " です。エネルギーは " + me.energy + " です。")
return me.name
}
}
print("=== birth() 構文テスト開始 ===")
# birth()コンストラクタでLife作成
local alice = new Life("Alice")
alice.introduce()
local bob = new Life("Bob")
bob.introduce()
print("=== birth() テスト完了 ===")