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:
56
CLAUDE.md
56
CLAUDE.md
@ -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実装)
|
||||
|
||||
@ -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経由外部API(Phase 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
|
||||
115
docs/design-decisions/constructor-name-decision.md
Normal file
115
docs/design-decisions/constructor-name-decision.md
Normal 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に生命を与える言語として、新たな進化を遂げる 🌟**
|
||||
226
docs/予定/native-plan/issues/phase_8_8_pack_transparency_system.md
Normal file
226
docs/予定/native-plan/issues/phase_8_8_pack_transparency_system.md
Normal 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を完全隠蔽**
|
||||
- **パフォーマンス劣化は避ける**
|
||||
|
||||
---
|
||||
|
||||
**実装時は必ずテストファースト開発で進める!** 🧪
|
||||
@ -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 {
|
||||
|
||||
@ -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を統一的に利用
|
||||
|
||||
@ -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: init(packがない場合)
|
||||
// 優先度2: init(birthがない場合)
|
||||
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使用
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)) {
|
||||
// コンストラクタを実行
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
27
test_birth_simple.nyash
Normal 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() テスト完了 ===")
|
||||
Reference in New Issue
Block a user