diff --git a/docs/CURRENT_TASK.md b/docs/CURRENT_TASK.md index 18c10e52..65dfb0bb 100644 --- a/docs/CURRENT_TASK.md +++ b/docs/CURRENT_TASK.md @@ -364,26 +364,39 @@ if let TokenType::IDENTIFIER(id) = &self.current_token().token_type { **現在状況**: 🚀 **Phase 9.75f ビルトインBox動的ライブラリ分離開始!** **最終更新**: 2025-08-17 03:30 -## 🔥 **Phase 9.75f: 緊急ビルド時間改善** +## 🔥 **Phase 9.75f: 緊急ビルド時間改善(Option C段階的実装)** ### 🎯 **動的ライブラリ化によるビルド革命** - **現状**: 16個のビルトインBox静的リンク → 2分以上のビルド - **目標**: コア2MB + 動的ライブラリ → 15秒ビルド -### 📋 **Gemini先生の推奨実装** -1. **C ABI + libloading**: 最も安定した方法 -2. **段階的移行**: インタープリターExternCall → プラグイン化 -3. **メモリ管理**: ハンドルパターンでArc問題解決 +### 📋 **Option C: 段階的移行戦略** +1. **[9.75f-1]**: FileBox動的化(即実装) + - 詳細: [phase_9_75f_1_filebox_dynamic.md](docs/予定/native-plan/issues/phase_9_75f_1_filebox_dynamic.md) + - libnyash_file.so作成、C ABI実装 + - 目標: 15秒のビルド時間短縮 + +2. **[9.75f-2]**: Math/Time系動的化(今週中) + - 詳細: [phase_9_75f_2_math_time_dynamic.md](docs/予定/native-plan/issues/phase_9_75f_2_math_time_dynamic.md) + - 統合プラグイン(Math, Random, Time) + - 目標: さらに30秒短縮 + +3. **[9.75f-3]**: 基本型実験(将来) + - 詳細: [phase_9_75f_3_core_types_experiment.md](docs/予定/native-plan/issues/phase_9_75f_3_core_types_experiment.md) + - --dynamic-all フラグで完全動的化 + - 目標: 5秒ビルド(実験的) ### ✅ **完了タスク** -- FFI-ABI file実装(stdlib方式) -- MIRビルダーfile.read/write追加 -- Gemini先生への相談・回答取得 +- FFI-ABI file実装テスト(削除済み) +- Gemini先生への相談・アドバイス取得 +- FileBox実装確認(存在・利用可能) +- Option C実装計画策定 -### 🚀 **次のステップ** -1. インタープリターでExternCall直接実行 -2. FileBoxの元実装を探して置き換え -3. プラグインアーキテクチャ基盤構築 +### 🚀 **現在の作業: 9.75f-1 FileBox動的化** +1. workspace構成準備 +2. FileBoxプラグイン作成 +3. C ABI関数実装 +4. インタープリター統合 ## 🌐 **WASM研究メモ** diff --git a/docs/予定/native-plan/issues/phase_9_75f_1_filebox_dynamic.md b/docs/予定/native-plan/issues/phase_9_75f_1_filebox_dynamic.md new file mode 100644 index 00000000..19117d9c --- /dev/null +++ b/docs/予定/native-plan/issues/phase_9_75f_1_filebox_dynamic.md @@ -0,0 +1,175 @@ +# Phase 9.75f-1: FileBox動的ライブラリ化(第一段階) + +## 🎯 目的 +- FileBoxを最初の動的ライブラリ化対象として実装 +- ビルド時間短縮効果の実証(目標: 15秒短縮) +- 動的ライブラリアーキテクチャの検証 + +## 📋 実装計画 + +### Step 1: プロジェクト構造準備 +```toml +# Cargo.toml (workspace) +[workspace] +members = [ + "nyash-core", + "plugins/nyash-file", +] + +# nyash-core/Cargo.toml +[dependencies] +libloading = "0.8" + +[features] +default = ["static-boxes"] +static-boxes = [] +dynamic-file = [] +``` + +### Step 2: FileBox切り離し +```rust +// plugins/nyash-file/src/lib.rs +#[repr(C)] +pub struct FileBoxPlugin { + magic: u32, // 0x4E594153 ('NYAS') + version: u32, + api_version: u32, +} + +#[no_mangle] +extern "C" fn nyash_plugin_init() -> *const FileBoxPlugin { + Box::into_raw(Box::new(FileBoxPlugin { + magic: 0x4E594153, + version: 1, + api_version: 1, + })) +} + +// FileBox methods as C ABI functions +#[no_mangle] +extern "C" fn nyash_file_open(path: *const c_char) -> *mut c_void { + // FileBox::open implementation +} + +#[no_mangle] +extern "C" fn nyash_file_read(handle: *mut c_void) -> *mut c_char { + // FileBox::read implementation +} + +#[no_mangle] +extern "C" fn nyash_file_write(handle: *mut c_void, content: *const c_char) -> i32 { + // FileBox::write implementation +} + +#[no_mangle] +extern "C" fn nyash_file_free(handle: *mut c_void) { + // Cleanup +} +``` + +### Step 3: インタープリター統合 +```rust +// src/interpreter/plugin_loader.rs +use libloading::{Library, Symbol}; +use std::sync::RwLock; +use std::collections::HashMap; + +lazy_static! { + static ref PLUGIN_CACHE: RwLock> = + RwLock::new(HashMap::new()); +} + +impl NyashInterpreter { + fn load_file_plugin(&mut self) -> Result<(), RuntimeError> { + #[cfg(feature = "dynamic-file")] + { + let mut cache = PLUGIN_CACHE.write().unwrap(); + if !cache.contains_key("file") { + let lib_path = if cfg!(windows) { + "./plugins/nyash_file.dll" + } else if cfg!(target_os = "macos") { + "./plugins/libnyash_file.dylib" + } else { + "./plugins/libnyash_file.so" + }; + + unsafe { + let lib = Library::new(lib_path)?; + cache.insert("file".to_string(), lib); + } + } + } + Ok(()) + } +} +``` + +### Step 4: execute_new修正 +```rust +// src/interpreter/objects.rs +"FileBox" => { + #[cfg(feature = "static-boxes")] + { + // 既存の静的実装 + let file_box = FileBox::open(&path)?; + Ok(Box::new(file_box)) + } + + #[cfg(feature = "dynamic-file")] + { + // 動的ライブラリ経由 + self.load_file_plugin()?; + let cache = PLUGIN_CACHE.read().unwrap(); + let lib = cache.get("file").unwrap(); + + unsafe { + let open_fn: Symbol *mut c_void> = + lib.get(b"nyash_file_open")?; + let handle = open_fn(CString::new(path)?.as_ptr()); + + // FileBoxProxyでラップ + Ok(Box::new(FileBoxProxy { handle })) + } + } +} +``` + +### Step 5: FileBoxProxy実装 +```rust +// src/interpreter/proxy_boxes.rs +struct FileBoxProxy { + handle: *mut c_void, +} + +impl NyashBox for FileBoxProxy { + fn type_name(&self) -> &'static str { + "FileBox" + } + + // メソッド呼び出しは動的ライブラリへ委譲 +} + +impl Drop for FileBoxProxy { + fn drop(&mut self) { + // nyash_file_free呼び出し + } +} +``` + +## 🎯 成功条件 +1. ✅ `new FileBox(path)` が動的ライブラリ経由で動作 +2. ✅ FileBoxのメソッド(read, write, exists)が正常動作 +3. ✅ ビルド時間が15秒以上短縮 +4. ✅ 静的/動的をfeature flagで切り替え可能 +5. ✅ メモリリークなし(valgrindで確認) + +## ⚠️ 注意事項 +- Windows/Mac/Linuxでのパス解決 +- エラーハンドリング(プラグイン読み込み失敗時) +- ABI互換性(C ABIで安定化) + +## 📊 測定項目 +- ビルド時間(クリーンビルド) +- 起動時間(プラグインロード込み) +- FileBox操作のベンチマーク +- バイナリサイズ削減量 \ No newline at end of file diff --git a/docs/予定/native-plan/issues/phase_9_75f_2_math_time_dynamic.md b/docs/予定/native-plan/issues/phase_9_75f_2_math_time_dynamic.md new file mode 100644 index 00000000..0866607f --- /dev/null +++ b/docs/予定/native-plan/issues/phase_9_75f_2_math_time_dynamic.md @@ -0,0 +1,200 @@ +# Phase 9.75f-2: Math/Time系Box動的ライブラリ化(第二段階) + +## 🎯 目的 +- FileBox成功を受けて、Math/Random/Time系を動的化 +- 複数Boxの単一ライブラリ化パターン検証 +- ビルド時間追加短縮(目標: さらに30秒短縮) + +## 📋 実装計画 + +### Step 1: プラグイン構成 +```toml +# plugins/nyash-math/Cargo.toml +[package] +name = "nyash-math" +crate-type = ["cdylib"] + +[dependencies] +rand = "0.8" +chrono = "0.4" +``` + +### Step 2: 統合プラグインAPI +```rust +// plugins/nyash-math/src/lib.rs +#[repr(C)] +pub struct MathPlugin { + magic: u32, + version: u32, + // 複数Box型を1つのプラグインで提供 + box_types: *const BoxTypeInfo, + box_count: usize, +} + +#[repr(C)] +pub struct BoxTypeInfo { + name: *const c_char, // "MathBox", "RandomBox", etc. + constructor: extern "C" fn() -> *mut c_void, + methods: *const MethodInfo, + method_count: usize, +} + +#[repr(C)] +pub struct MethodInfo { + name: *const c_char, + func: extern "C" fn(*mut c_void, *const c_void) -> *mut c_void, +} + +// プラグイン初期化 +#[no_mangle] +extern "C" fn nyash_plugin_init() -> *const MathPlugin { + static BOX_TYPES: &[BoxTypeInfo] = &[ + BoxTypeInfo { + name: c"MathBox", + constructor: math_box_new, + methods: &MATH_METHODS, + method_count: MATH_METHODS.len(), + }, + BoxTypeInfo { + name: c"RandomBox", + constructor: random_box_new, + methods: &RANDOM_METHODS, + method_count: RANDOM_METHODS.len(), + }, + BoxTypeInfo { + name: c"TimeBox", + constructor: time_box_new, + methods: &TIME_METHODS, + method_count: TIME_METHODS.len(), + }, + ]; + + Box::into_raw(Box::new(MathPlugin { + magic: 0x4E594153, + version: 1, + box_types: BOX_TYPES.as_ptr(), + box_count: BOX_TYPES.len(), + })) +} +``` + +### Step 3: メソッド実装 +```rust +// MathBox methods +static MATH_METHODS: &[MethodInfo] = &[ + MethodInfo { name: c"sin", func: math_sin }, + MethodInfo { name: c"cos", func: math_cos }, + MethodInfo { name: c"sqrt", func: math_sqrt }, + MethodInfo { name: c"pow", func: math_pow }, +]; + +extern "C" fn math_sin(_self: *mut c_void, args: *const c_void) -> *mut c_void { + // 引数をFloatBoxとして解釈 + // sin計算 + // 結果をFloatBoxとして返す +} + +// RandomBox methods +static RANDOM_METHODS: &[MethodInfo] = &[ + MethodInfo { name: c"int", func: random_int }, + MethodInfo { name: c"float", func: random_float }, + MethodInfo { name: c"choice", func: random_choice }, +]; + +// TimeBox methods +static TIME_METHODS: &[MethodInfo] = &[ + MethodInfo { name: c"now", func: time_now }, + MethodInfo { name: c"format", func: time_format }, + MethodInfo { name: c"add", func: time_add }, +]; +``` + +### Step 4: 改良されたプラグインローダー +```rust +// src/interpreter/plugin_loader.rs +pub struct PluginRegistry { + plugins: HashMap, + box_registry: HashMap, +} + +struct LoadedPlugin { + library: Library, + info: PluginInfo, +} + +struct BoxTypeEntry { + plugin_name: String, + type_info: BoxTypeInfo, +} + +impl PluginRegistry { + pub fn load_plugin(&mut self, name: &str, path: &str) -> Result<(), Error> { + let lib = unsafe { Library::new(path)? }; + + // プラグイン初期化 + let init_fn: Symbol *const MathPlugin> = + unsafe { lib.get(b"nyash_plugin_init")? }; + let plugin_info = unsafe { &*init_fn() }; + + // Box型を登録 + for i in 0..plugin_info.box_count { + let box_info = unsafe { &*plugin_info.box_types.add(i) }; + let box_name = unsafe { CStr::from_ptr(box_info.name).to_string_lossy() }; + + self.box_registry.insert( + box_name.to_string(), + BoxTypeEntry { + plugin_name: name.to_string(), + type_info: *box_info, + } + ); + } + + self.plugins.insert(name.to_string(), LoadedPlugin { library: lib, info: *plugin_info }); + Ok(()) + } +} +``` + +### Step 5: インタープリター統合 +```rust +// src/interpreter/objects.rs +impl NyashInterpreter { + fn execute_new_dynamic(&mut self, box_name: &str, args: Vec>) + -> Result, RuntimeError> { + + let registry = self.plugin_registry.read().unwrap(); + + if let Some(entry) = registry.box_registry.get(box_name) { + // 動的ライブラリ経由でコンストラクタ呼び出し + let handle = unsafe { (entry.type_info.constructor)() }; + + Ok(Box::new(DynamicBoxProxy { + handle, + type_name: box_name.to_string(), + type_info: entry.type_info.clone(), + })) + } else { + Err(RuntimeError::UndefinedBox { name: box_name.to_string() }) + } + } +} +``` + +## 🎯 成功条件 +1. ✅ Math/Random/Timeの全メソッドが動的ライブラリ経由で動作 +2. ✅ 1つのプラグインで複数Box型を提供 +3. ✅ ビルド時間がさらに30秒短縮 +4. ✅ プラグイン遅延ロード(使用時のみ) +5. ✅ 静的版と同等のパフォーマンス + +## 📊 ベンチマーク項目 +- Math演算1000回のオーバーヘッド +- Random生成のスループット +- Time操作のレイテンシ +- プラグインロード時間(初回/キャッシュ後) + +## 🔮 将来の拡張 +- プラグイン自動検出(plugins/ディレクトリスキャン) +- バージョン管理とアップグレード +- プラグイン間依存関係 \ No newline at end of file diff --git a/docs/予定/native-plan/issues/phase_9_75f_3_core_types_experiment.md b/docs/予定/native-plan/issues/phase_9_75f_3_core_types_experiment.md new file mode 100644 index 00000000..ecf3afc5 --- /dev/null +++ b/docs/予定/native-plan/issues/phase_9_75f_3_core_types_experiment.md @@ -0,0 +1,199 @@ +# Phase 9.75f-3: 基本型動的化実験(第三段階・実験的) + +## 🎯 目的 +- String/Integer/Bool/Nullまで動的化する実験 +- "Everything is Plugin"哲学の究極形 +- ビルドを5秒以下にする野心的目標 + +## ⚠️ 警告 +これは**実験的機能**です。以下のリスクがあります: +- 起動時間の増加(基本型ロード) +- デバッグの複雑化 +- パフォーマンスオーバーヘッド + +## 📋 実装計画 + +### Step 1: 最小コア定義 +```rust +// nyash-core/src/minimal_core.rs +// 本当に必要な最小限のみ残す +pub trait MinimalBox: Send + Sync { + fn type_id(&self) -> u64; + fn as_ptr(&self) -> *const c_void; +} + +// FFI境界用の最小構造 +#[repr(C)] +pub struct FFIValue { + type_id: u64, + data_ptr: *mut c_void, + vtable: *const FFIVTable, +} + +#[repr(C)] +pub struct FFIVTable { + drop: extern "C" fn(*mut c_void), + clone: extern "C" fn(*const c_void) -> *mut c_void, + to_string: extern "C" fn(*const c_void) -> *mut c_char, +} +``` + +### Step 2: 基本型プラグイン +```rust +// plugins/nyash-core-types/src/lib.rs +#[no_mangle] +extern "C" fn nyash_create_string(data: *const c_char) -> FFIValue { + let s = unsafe { CStr::from_ptr(data).to_string_lossy().to_string() }; + let boxed = Box::new(StringData { value: s }); + + FFIValue { + type_id: STRING_TYPE_ID, + data_ptr: Box::into_raw(boxed) as *mut c_void, + vtable: &STRING_VTABLE, + } +} + +static STRING_VTABLE: FFIVTable = FFIVTable { + drop: string_drop, + clone: string_clone, + to_string: string_to_string, +}; + +extern "C" fn string_drop(ptr: *mut c_void) { + unsafe { Box::from_raw(ptr as *mut StringData); } +} + +// Integer, Bool, Null も同様に実装 +``` + +### Step 3: 起動時プリロード +```rust +// src/main.rs +fn initialize_core_plugins() -> Result<(), Error> { + let registry = PLUGIN_REGISTRY.write().unwrap(); + + // 基本型は起動時に必ずロード + #[cfg(feature = "dynamic-core")] + { + registry.preload_plugin("core-types", "./plugins/libnyash_core_types.so")?; + + // 基本操作をキャッシュ + registry.cache_constructor("StringBox"); + registry.cache_constructor("IntegerBox"); + registry.cache_constructor("BoolBox"); + registry.cache_constructor("NullBox"); + } + + Ok(()) +} +``` + +### Step 4: リテラル処理の最適化 +```rust +// src/interpreter/expressions/literals.rs +impl NyashInterpreter { + fn evaluate_string_literal(&mut self, value: &str) -> Result, RuntimeError> { + #[cfg(feature = "static-core")] + { + Ok(Box::new(StringBox::new(value))) + } + + #[cfg(feature = "dynamic-core")] + { + // キャッシュされたコンストラクタを使用 + let constructor = self.cached_constructors.get("StringBox").unwrap(); + let ffi_value = unsafe { + constructor(CString::new(value)?.as_ptr()) + }; + + Ok(Box::new(FFIBoxWrapper::new(ffi_value))) + } + } +} +``` + +### Step 5: JITライクな最適化 +```rust +// src/interpreter/optimizer.rs +struct DynamicCallOptimizer { + // よく使われる操作をインライン化 + hot_paths: HashMap FFIValue>, +} + +impl DynamicCallOptimizer { + fn optimize_hot_path(&mut self, op: &str, count: usize) { + if count > HOT_THRESHOLD { + match op { + "StringBox.concat" => { + // 頻繁に呼ばれる操作は専用パス + self.hot_paths.insert(op.to_string(), optimized_string_concat); + } + _ => {} + } + } + } +} +``` + +## 🎯 実験的機能 + +### --dynamic-all フラグ +```bash +# 通常起動(基本型は静的) +./nyash program.nyash + +# 完全動的モード(実験) +./nyash --dynamic-all program.nyash + +# プロファイリングモード +./nyash --dynamic-all --profile program.nyash +``` + +### プラグイン統計 +``` +Plugin Load Statistics: + core-types: 2.3ms (cached) + math: 0.8ms (lazy) + file: 1.2ms (on-demand) + +Method Call Overhead: + StringBox.concat: +15ns (optimized) + IntegerBox.add: +12ns (optimized) + FileBox.read: +3ns (already dynamic) +``` + +## 📊 ベンチマーク目標 +- Hello Worldの起動: < 10ms(プラグインロード込み) +- 基本演算オーバーヘッド: < 20ns +- ビルド時間: 5秒以下 +- バイナリサイズ: 500KB以下 + +## 🔮 超実験的アイデア + +### ホットリロード +```rust +// 開発中にプラグインを再読み込み +./nyash --watch-plugins program.nyash +``` + +### WASM プラグイン +```rust +// プラグインもWASMで記述可能に +registry.load_wasm_plugin("custom-box.wasm")?; +``` + +### 分散プラグイン +```rust +// ネットワーク経由でプラグインロード(危険!) +registry.load_remote_plugin("https://plugins.nyash.dev/crypto-box")?; +``` + +## ⚠️ 既知の課題 +1. **デバッグ体験**: スタックトレースが複雑化 +2. **エラーメッセージ**: プラグイン境界でのエラーが分かりにくい +3. **セキュリティ**: 任意のプラグインロードは危険 +4. **互換性**: プラグインABIバージョン管理が必要 + +## 📝 まとめ +Phase 9.75f-3は**純粋な実験**です。実用性より「どこまでできるか」の探求。 +成功すれば革新的、失敗しても学びは大きい。 \ No newline at end of file