feat: Phase 9.78e complete - instance_v2 migration with legacy compatibility

- instance_v2 now includes legacy compatibility layer
- All interpreter code migrated to use instance_v2
- Added legacy field access methods (get_fields, set_field_legacy, etc.)
- Fixed type conversion issues (NyashValue vs SharedNyashBox)
- instance.rs still exists but no longer used in interpreter
- TODO: Remove instance.rs completely in next phase
- TODO: Implement proper SharedNyashBox -> NyashValue conversion

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-19 22:35:34 +09:00
parent 3ae4ae8211
commit 5582ad45c0
36 changed files with 1347926 additions and 43 deletions

View File

@ -0,0 +1,127 @@
Nyashプログラミング言語の統合Box管理システムについて深い相談です。
【Nyashの哲学と特徴】
- Everything is Box: すべてがBoxオブジェクト
- birthでインスタンスを生み、finiで解放する統一ライフサイクル
- メモリ安全性重視Rust実装、Arc<Mutex>パターン)
- 初学者フレンドリー、明示性重視
【現在の問題点】
src/interpreter/objects.rs内でBox生成が3つの完全に異なるフローに分かれています
1. ビルトインBoxStringBox, IntegerBox等
- 600行以上の巨大match文で直接生成
- 各Boxごとに個別のコード
- 新しいビルトインBox追加時に手動で追加必要
2. ユーザー定義Box
- InstanceBox経由で生成
- 継承、フィールド、メソッドを動的に解決
- birth/finiライフサイクル完全対応
3. プラグインBoxFileBox等
- BoxFactoryRegistry経由で生成v2システム
- 動的ロード、FFI経由
- nyash.tomlで設定
【統合BoxFactoryアーキテクチャ提案】
```rust
// 統一インターフェース
trait BoxFactory: Send + Sync {
fn create_box(&self, name: &str, args: &[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError>;
fn is_available(&self) -> bool;
fn box_types(&self) -> Vec<&str>;
fn supports_birth(&self) -> bool { true } // birth/finiサポート
}
// 実装例
struct BuiltinBoxFactory {
creators: HashMap<String, Box<dyn Fn(&[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError>>>
}
struct UserDefinedBoxFactory {
interpreter: Arc<NyashInterpreter>
}
struct PluginBoxFactory {
registry: Arc<BoxFactoryRegistry>
}
// 統合レジストリ
struct UnifiedBoxRegistry {
factories: Vec<Box<dyn BoxFactory>>,
}
impl UnifiedBoxRegistry {
pub fn create_box(&self, name: &str, args: &[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError> {
// 優先順位: ビルトイン → ユーザー定義 → プラグイン
for factory in &self.factories {
if factory.box_types().contains(&name) && factory.is_available() {
return factory.create_box(name, args);
}
}
Err(RuntimeError::InvalidOperation {
message: format!("Unknown Box type: {}", name)
})
}
}
```
【期待される効果】
1. コード削減
- 600行のmatch文 → 30行程度のHashMap登録
- 重複コード削除
2. 保守性向上
- 新しいBox追加が簡単HashMapに登録するだけ
- birth/finiライフサイクルの統一管理
- エラーハンドリングの一元化
3. 拡張性
- RemoteBoxFactory、AsyncBoxFactory等も同じインターフェースで追加可能
- WASM向けの条件付きコンパイルが簡単
4. パフォーマンス
- HashMapルックアップは高速
- 動的ディスパッチのオーバーヘッドは最小限
【深い検討事項】
1. 複雑性の評価
- 現在: 3つの完全に異なるコードパス複雑
- 提案: 1つの統一インターフェースシンプル
- トレードオフは?
2. birth/finiの統一性
- すべてのBoxがbirth/finiライフサイクルに従う
- Factoryパターンでこれをどう保証する
3. 型安全性
- Rustの型システムとの整合性
- 動的ディスパッチの影響
4. 段階的移行
- 既存コードとの互換性維持
- どの順序で移行すべき?
5. 実装の簡単さ vs 抽象化
- 過度な抽象化になっていないか?
- 初心者にも理解しやすいか?
【質問】
1. この統合により、本当にコードがシンプルになりますか?それとも抽象化により複雑になりますか?
2. 600行のmatch文を30行のHashMap登録に変換することは、保守性の観点から正しい選択ですか
3. birth/finiライフサイクルの統一性を保ちながら、Factoryパターンを適用する最良の方法は
4. パフォーマンスへの実質的な影響はどの程度でしょうか?
5. Nyashの「Everything is Box」哲学と「明示性重視」の観点から、この設計は適切ですか
6. より簡単で、かつ効果的な代替案はありますか?
プログラミング言語設計と実装の専門的視点から、深く考えてアドバイスをお願いします。特に「シンプルさ」と「保守性」のバランスについて重点的に分析してください。

View File

@ -0,0 +1,13 @@
// 🔍 文字列連結デバッグテスト
// 単純な文字列作成
local str1 = "Hello"
local str2 = "World"
print("str1 created")
print("str2 created")
// 文字列連結テスト(この行でエラーが出るはず)
local result = str1 + str2
print("Test completed WITH concatenation")

View File

@ -0,0 +1,218 @@
Nyashプログラミング言語のInstanceBox統一Factory設計について深い技術相談
【背景】
Phase 9.78: 統合BoxFactoryアーキテクチャ実装中
- ✅ 完了: ビルトインBox統合StringBox, IntegerBox等
- 🎯 現在: ユーザー定義Box統合設計検討中
- 目標: 「フローの上ではすべて同じ」統一美学の実現
【現在のアーキテクチャ】
```rust
// 統一インターフェース
pub trait BoxFactory: Send + Sync {
fn create_box(&self, name: &str, args: &[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError>;
fn box_types(&self) -> Vec<&str>;
}
// 統一レジストリ
pub struct UnifiedBoxRegistry {
factories: Vec<Arc<dyn BoxFactory>>, // 優先順: builtin > user > plugin
type_cache: RwLock<HashMap<String, usize>>,
}
```
【設計目標】
```rust
// すべて同じフロー - Everything is Box哲学の実装レベル体現
registry.create_box("StringBox", args) // → BuiltinBoxFactory
registry.create_box("FileBox", args) // → PluginBoxFactory
registry.create_box("MyUserBox", args) // → UserDefinedBoxFactory
```
【設計候補比較検討】
## **Option A: 動的Factory登録戦略複数Factory責務分離**
**1. UserDefinedBoxFactory設計:**
```rust
pub struct UserDefinedBoxFactory {
interpreter_ref: Weak<RefCell<NyashInterpreter>>, // 循環参照回避
registered_types: RwLock<HashSet<String>>, // 動的登録済み型管理
}
impl BoxFactory for UserDefinedBoxFactory {
fn create_box(&self, name: &str, args: &[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError> {
// 1⃣ box宣言取得
let interpreter = self.interpreter_ref.upgrade().ok_or(...)?;
let box_decl = interpreter.borrow().get_box_declaration(name)?;
// 2⃣ InstanceBox作成既存InstanceBox完全活用
let mut instance = InstanceBox::new(name, box_decl);
// 3⃣ 継承チェーン処理from Parent統合
if let Some(parent) = &box_decl.parent {
self.handle_delegation_chain(&mut instance, parent, args)?;
}
// 4⃣ birth/pack/initライフサイクル既存フロー完全活用
self.execute_constructor(&mut instance, args)?;
// 5⃣ 統一インターフェースで返却
Ok(Box::new(instance))
}
}
```
**2. 動的登録システム:**
```rust
impl NyashInterpreter {
fn execute_box_declaration(&mut self, decl: &BoxDeclaration) {
// box宣言の保存
self.register_box_declaration(decl.name.clone(), decl.clone());
// 統合レジストリに動的登録
let registry = get_global_unified_registry();
registry.lock().unwrap().register_user_defined_type(decl.name.clone());
}
pub fn get_box_declaration(&self, name: &str) -> Option<&BoxDeclaration> {
self.box_declarations.get(name)
}
}
```
**3. 統合レジストリ拡張:**
```rust
impl UnifiedBoxRegistry {
pub fn register_user_defined_type(&mut self, type_name: String) {
// UserDefinedBoxFactoryに型追加を通知
if let Some(user_factory) = self.get_user_defined_factory() {
user_factory.add_type(type_name);
}
}
}
```
**Option A メリット:**
1. **責務分離**: 各Factory内で適切な実装ビルトイン=直接生成、ユーザー=InstanceBox、プラグイン=FFI
2. **拡張性**: 新Factory種別の追加が容易
3. **既存活用**: InstanceBox、birth/pack/init、継承システムを部分再利用
**Option A 課題:**
1. **循環参照**: Factory→Interpreter→Registry→Factory の複雑な依存関係
2. **ライフタイム**: Weak参照でのinterpreter_ref管理の複雑性
3. **動的登録**: box宣言解析時の動的型登録の複雑性
## **Option B: InstanceBox統一Factory戦略単一Factory完全統一**
```rust
/// すべてのBox型をInstanceBoxとして統一処理
pub struct UnifiedInstanceBoxFactory {
builtin_registry: HashMap<String, BuiltinCreator>,
interpreter_context: Option<Weak<RefCell<NyashInterpreter>>>,
}
impl BoxFactory for UnifiedInstanceBoxFactory {
fn create_box(&self, name: &str, args: &[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError> {
match self.determine_box_type(name) {
BoxType::Builtin => {
// ビルトインBoxもInstanceBoxでラップして統一
let builtin_box = self.create_builtin_box(name, args)?;
Ok(Box::new(InstanceBox::from_builtin(builtin_box)))
},
BoxType::UserDefined => {
// ユーザー定義BoxをInstanceBoxとして作成
let declaration = self.get_user_box_declaration(name)?;
Ok(Box::new(InstanceBox::from_declaration(declaration, args)?))
},
BoxType::Plugin => {
// プラグインBoxもInstanceBoxでラップ
let plugin_box = self.create_plugin_box(name, args)?;
Ok(Box::new(InstanceBox::from_plugin(plugin_box)))
}
}
}
}
impl InstanceBox {
/// ビルトインBoxからInstanceBox作成
pub fn from_builtin(builtin: Box<dyn NyashBox>) -> Self {
Self {
box_type_name: builtin.type_name().to_string(),
inner_value: Some(builtin),
fields: HashMap::new(),
methods: HashMap::new(),
// ... 統一フィールド
}
}
/// ユーザー定義宣言からInstanceBox作成
pub fn from_declaration(decl: &BoxDeclaration, args: &[Box<dyn NyashBox>]) -> Result<Self, RuntimeError> {
let mut instance = Self::new(&decl.name);
// 1. 継承チェーン処理
if let Some(parent) = &decl.parent {
instance.setup_delegation_chain(parent)?;
}
// 2. フィールド初期化
for field in &decl.init_fields {
instance.fields.insert(field.clone(), Box::new(NullBox::new()));
}
// 3. メソッド登録
for method in &decl.methods {
instance.methods.insert(method.name.clone(), method.clone());
}
// 4. birth/pack/initコンストラクタ実行
instance.execute_constructor(args)?;
Ok(instance)
}
/// プラグインBoxからInstanceBox作成
pub fn from_plugin(plugin: Box<dyn NyashBox>) -> Self {
Self {
box_type_name: plugin.type_name().to_string(),
inner_value: Some(plugin),
plugin_wrapped: true,
// ... 統一フィールド
}
}
}
```
**Option B メリット:**
1. **完全統一**: すべてのBox型が同じInstanceBox経由で処理される
2. **Everything is Box**: 哲学に最も忠実な実装
3. **単純性**: 1つのFactoryですべて処理、理解しやすい
4. **一貫性**: ビルトイン・ユーザー定義・プラグインが完全に同じフロー
5. **拡張性**: 新Box種別も同じInstanceBoxパターン
**Option B 課題:**
1. **InstanceBox肥大化**: すべてを扱うため複雑になる可能性
2. **パフォーマンス**: ビルトインBoxもラップすることのオーバーヘッド
3. **既存互換**: 現在のInstanceBox実装との整合性
【深い比較質問】
1. **設計哲学**: Option AとOption B、どちらがNyashの「Everything is Box」哲学により適合しますか
2. **実装複雑性**: 循環参照を持つOption Aと、InstanceBox統一のOption B、どちらが保守しやすいですか
3. **パフォーマンス**: Option BのビルトインBoxラッピングのオーバーヘッドは許容範囲ですか
4. **拡張性**: 将来の新Box種別追加において、どちらのアプローチが柔軟ですか
5. **既存互換**: 現在のInstanceBox実装と最も整合性が取れるのはどちらですか
6. **コードの美しさ**: 「上からフローが綺麗に分かれる」観点でどちらが優れていますか?
7. **他の選択肢**: これら以外にさらに優れた第三の設計アプローチはありますか?
【特に重要な判断ポイント】
- Option Aは「責務分離」を重視各Factory専門化
- Option Bは「統一性」を重視すべてInstanceBox経由
- どちらがNyashの長期的な設計により適合するか
【Nyashの設計哲学】
- Everything is Box: すべてがBoxオブジェクト
- 明示性重視: 隠れた魔法的動作を避ける
- 安全性優先: Rust実装によるメモリ安全性
- 統一性重視: 一貫したインターフェース設計
専門的な視点から、この設計の妥当性と改善点について詳細に分析してください。

2
local_tests/run_test.sh Normal file
View File

@ -0,0 +1,2 @@
#!/bin/bash
./target/release/nyash local_tests/test_filebox_debug.nyash 2>&1 | grep -E "(TLV data|Plugin method returned)"

View File

@ -0,0 +1,29 @@
// 🔍 現状確認テスト
// ビルトインBox作成テスト
local str_box = new StringBox("Hello")
local int_box = new IntegerBox(42)
print("ビルトインBox作成: OK")
// ユーザー定義Boxテスト
box TestBox {
init { value, name }
testMethod() {
return me.value + 100
}
}
local test_instance = new TestBox()
test_instance.value = 10
test_instance.name = "test"
local result = test_instance.testMethod()
print("ユーザー定義Box: " + result)
// 文字列連結テスト
local concat_test = "Hello" + " " + "World"
print("文字列連結: " + concat_test)
print("現状確認テスト完了")

View File

@ -0,0 +1,49 @@
// FileBox v2プラグイン メソッドテスト
print("=== FileBox Methods Test ===")
// FileBoxを作成
print("\n1. Creating FileBox...")
local fileBox
fileBox = new FileBox()
print("✅ FileBox created: " + fileBox.toString())
// ファイルを開く
print("\n2. Opening file for writing...")
local success
success = fileBox.open("test_output.txt", "w")
print("✅ File opened: " + success.toString())
// ファイルに書き込む
print("\n3. Writing to file...")
local writeResult
writeResult = fileBox.write("Hello from Nyash FileBox v2!\n")
print("✅ Written bytes: " + writeResult.toString())
// もう一行書き込む
writeResult = fileBox.write("Everything is Box! 🎉\n")
print("✅ Written more bytes: " + writeResult.toString())
// ファイルを閉じる
print("\n4. Closing file...")
local closeResult
closeResult = fileBox.close()
print("✅ File closed: " + closeResult.toString())
// ファイルを読み込みモードで開く
print("\n5. Opening file for reading...")
success = fileBox.open("test_output.txt", "r")
print("✅ File opened for reading: " + success.toString())
// ファイル内容を読む
print("\n6. Reading from file...")
local content
content = fileBox.read()
print("✅ File content:")
print(content)
// 最後にファイルを閉じる
print("\n7. Closing file again...")
closeResult = fileBox.close()
print("✅ File closed: " + closeResult.toString())
print("\n=== Test completed successfully! ===")

View File

@ -0,0 +1,14 @@
// Test FileBox with no-argument methods
local file
file = new FileBox()
print("Created FileBox")
// Try read() - no arguments
local content
content = file.read()
print("Read result: " + content)
// Try close() - no arguments
local close_result
close_result = file.close()
print("Close result: " + close_result)

View File

@ -0,0 +1,9 @@
// Simple test with debug
local file
file = new FileBox()
// Check argument count
print("Calling open with 2 args...")
local result
result = file.open("test.txt", "w")
print("Done!")

View File

@ -0,0 +1,14 @@
// Minimal FileBox v2 Plugin Test
print("Testing FileBox v2...")
local file
file = new FileBox()
print("Created FileBox")
// Debug: Check type
print("Type: " + file)
// Try method call
local result
result = file.open("test.txt", "w")
print("Open result: " + result)

View File

@ -0,0 +1,20 @@
// Simple FileBox v2 Plugin Test - no string concatenation
print("Testing FileBox v2 plugin...")
local file
file = new FileBox()
// Test open without string concatenation
local result
result = file.open("test.txt", "w")
print("Open succeeded")
// Test write
result = file.write("Hello Nyash!")
print("Write succeeded")
// Test close
result = file.close()
print("Close succeeded")
print("Test completed!")

View File

@ -0,0 +1,80 @@
// 🧪 InstanceBox v2包括テスト文字列演算なし
// 複雑なネストしたBox階層のテスト
box DatabaseConnection {
init { host, port, status }
connect(hostname, portnum) {
me.host = hostname
me.port = portnum
me.status = 1
return me.status
}
isConnected() {
return me.status
}
}
box UserService {
init { db_connection, user_cache }
initialize() {
me.db_connection = new DatabaseConnection()
me.user_cache = new MapBox()
local result = me.db_connection.connect("localhost", 5432)
return result
}
getConnectionStatus() {
return me.db_connection.isConnected()
}
addUser(userId, userData) {
me.user_cache.set(userId, userData)
return me.user_cache.size()
}
}
box Application {
init { user_service, logger }
startup() {
me.user_service = new UserService()
me.logger = new ConsoleBox()
local init_result = me.user_service.initialize()
return init_result
}
testComplexOperations() {
// 複雑なネストしたメソッド呼び出し
local status = me.user_service.getConnectionStatus()
// MapBoxとの連携
local cache_size = me.user_service.addUser("user1", "data1")
// ログ出力
me.logger.log("Application test completed")
return cache_size
}
}
// メインテスト
static box Main {
init { app, test_result }
main() {
me.app = new Application()
// 段階的初期化テスト
local startup_result = me.app.startup()
// 複雑な操作テスト
me.test_result = me.app.testComplexOperations()
return me.test_result
}
}

View File

@ -0,0 +1,49 @@
// Phase 9.78e: instance_v2移行テスト
// 基本的なBoxクラス定義
box Person {
init { name, age }
init(name, age) {
me.name = name
me.age = age
print("Person created: " + name)
}
greet() {
print("Hello, I'm " + me.name + " and I'm " + me.age + " years old")
}
}
// インスタンス作成
local alice = new Person("Alice", 25)
alice.greet()
// フィールドアクセス
print("Name field: " + alice.name)
print("Age field: " + alice.age)
// フィールド更新
alice.age = 26
print("Updated age: " + alice.age)
// デリゲーションテスト
box Employee from Person {
init { company }
init(name, age, company) {
from Person.init(name, age)
me.company = company
print("Employee created at " + company)
}
override greet() {
from Person.greet()
print("I work at " + me.company)
}
}
local bob = new Employee("Bob", 30, "TechCorp")
bob.greet()
print("All tests passed!")

View File

@ -0,0 +1,10 @@
// Phase 9.78e test - InstanceBox with StringBox
local str
str = new StringBox("Hello, Nyash!")
print("Created StringBox: " + str)
// Try to call methods - this should fail with the current implementation
// print("Type: " + str.type_name()) // This would error without call_method integration
print("Test completed successfully")

View File

@ -0,0 +1,46 @@
// Phase 9.78e test - Method calls on StringBox through InstanceBox
local str
str = new StringBox("Hello, Nyash!")
print("Created StringBox: " + str)
// Test basic methods that should work with call_method
local len
len = str.length()
print("Length: " + len)
local upper
upper = str.toUpperCase()
print("Uppercase: " + upper)
local lower
lower = str.toLowerCase()
print("Lowercase: " + lower)
local trimmed
trimmed = str.trim()
print("Trimmed: " + trimmed)
// Test methods with arguments
local index
index = str.indexOf("Nyash")
print("Index of 'Nyash': " + index)
local replaced
replaced = str.replace("Hello", "Hi")
print("Replaced: " + replaced)
local char
char = str.charAt(0)
print("First character: " + char)
local substr
substr = str.substring(0, 5)
print("Substring(0,5): " + substr)
// Test concatenation
local concat
concat = str.concat(" How are you?")
print("Concatenated: " + concat)
print("All method tests completed!")

View File

@ -0,0 +1,26 @@
// 🎯 シンプルなInstanceBox v2テスト
print("テスト開始")
// ユーザー定義Box
box SimpleBox {
init { count }
birth() {
me.count = 100
}
getCount() {
return me.count
}
}
// インスタンス生成
local box1 = new SimpleBox()
print("Box生成完了")
// メソッド呼び出し
local result = box1.getCount()
print("カウント取得完了")
print("テスト成功")

View File

@ -0,0 +1,16 @@
// 🎯 StringBox統一テスト
print("=== StringBox統一テスト ===")
// StringBox作成
local str = new StringBox("Hello World")
// 統一確認
print("type_name: " + str.type_name())
print("content: " + str.toString())
// フィールドアクセステスト(統一後の機能)
str.custom_field = "Added Field"
print("custom_field: " + str.custom_field)
print("StringBox統一テスト完了")

View File

@ -0,0 +1,33 @@
// 🔍 3つのBox型統一テスト - 深いフロー確認
// 1. ビルトインBox
print("=== ビルトインBox ===")
local builtin_box = new StringBox("Hello")
print("ビルトイン型名: " + builtin_box.type_name())
// 2. ユーザー定義Box
print("=== ユーザー定義Box ===")
box UserBox {
init { value }
getValue() {
return me.value
}
}
local user_box = new UserBox()
user_box.value = "User Value"
print("ユーザー定義型名: " + user_box.type_name())
// 3. プラグインBox
print("=== プラグインBox ===")
local plugin_box = new FileBox()
print("プラグイン型名: " + plugin_box.type_name())
// 統一性テスト
print("=== 統一性確認 ===")
print("ビルトインBoxはInstanceBox?: " + (builtin_box.type_name() == "InstanceBox"))
print("ユーザーBoxはInstanceBox?: " + (user_box.type_name() == "InstanceBox"))
print("プラグインBoxはInstanceBox?: " + (plugin_box.type_name() == "InstanceBox"))
print("テスト完了")