diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index 779d8474..63783d36 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -12,27 +12,35 @@ Updated: 2025‑09‑24 ### ✅ **重要な発見:既存システムが完全実装済み!** - **環境変数制御**: `NYASH_USE_PLUGIN_BUILTINS=1` + `NYASH_PLUGIN_OVERRIDE_TYPES="StringBox,IntegerBox"` - **実装箇所**: `src/box_factory/mod.rs:119-143`に完全な優先度制御システム -- **結論**: 新規実装不要、既存機能の活用が鍵 +- **課題発見**: 予約型保護(src/box_factory/mod.rs:73-86)がプラグイン登録を阻止 +- **解決策**: 環境変数で予約型保護を条件付き解除 + +### 🎯 **最終目標** +**3層構造→2層構造への完全移行** +``` +現状: コアBox(nyrt) + プラグインBox + ユーザーBox +最終: プラグインBox(デフォルト) + ユーザーBox +``` ### 実装フェーズ計画 -#### Phase A: プラグイン版動作確認(1週目) -- [ ] 環境変数制御のドキュメント作成 -- [ ] プラグイン版StringBox/IntegerBox/ArrayBox/MapBoxの動作テスト -- [ ] パフォーマンス測定(FFIオーバーヘッド確認) +#### Phase A: 予約型保護解除(1週目) +- [ ] `src/box_factory/mod.rs`の`is_reserved_type()`修正 +- [ ] 環境変数で条件付き保護解除実装 +- [ ] プラグイン版StringBox/IntegerBox動作確認 #### Phase B: MIRビルダー統一(2週目) - [ ] `src/mir/builder.rs`の特別扱い削除(行407-424) - [ ] `src/mir/builder/utils.rs`の型推論削除(行134-156) - [ ] すべてのBoxを`MirType::Box(name)`として統一 -#### Phase C: nyrt実装削除(3週目) -- [ ] `crates/nyrt/src/lib.rs`からコアBox関数削除(約300行) -- [ ] `crates/nyrt/src/plugin/array.rs`削除(143行) -- [ ] `crates/nyrt/src/plugin/string.rs`削除(173行) +#### Phase C: 完全統一(3週目) +- [ ] 予約型保護の完全削除 +- [ ] nyrt実装削除(約600行) +- [ ] デフォルト動作をプラグインBox化 +- [ ] 環境変数を廃止(プラグインがデフォルト) #### Phase D: Nyashコード化(将来) - [ ] `apps/lib/core_boxes/`にNyash実装作成 -- [ ] StringBox, IntegerBox, ArrayBox, MapBoxのNyash版実装 - [ ] 静的リンクによる性能最適化 ### ✅ **MIR Call命令統一実装完了済み**(2025-09-24) diff --git a/docs/development/roadmap/phases/phase-15/phase-15.5-core-box-unification.md b/docs/development/roadmap/phases/phase-15/phase-15.5-core-box-unification.md index 81a009b4..6cecb69d 100644 --- a/docs/development/roadmap/phases/phase-15/phase-15.5-core-box-unification.md +++ b/docs/development/roadmap/phases/phase-15/phase-15.5-core-box-unification.md @@ -11,12 +11,14 @@ - **特別扱い削除**: MIRビルダー/バックエンドから約100行 - **全体寄与**: Phase 15目標(80k→20k)の約1% -## 📊 現状の3層構造(削除対象) +## 📊 構造変更の全体像 + +### 現状(3層構造) ``` -1. コアBox(nyrt内蔵)← 削除対象 +1. コアBox(nyrt内蔵)← 完全削除 - StringBox, IntegerBox, BoolBox - ArrayBox, MapBox - - 特別な最適化パス + - 特別な最適化パス・予約型保護 2. プラグインBox(.so/.dll) - FileBox, NetBox, ConsoleBox等 @@ -26,22 +28,36 @@ - アプリケーション固有Box ``` +### 最終形(2層構造) +``` +1. プラグインBox(.so/.dll)← デフォルト動作 + - StringBox, IntegerBox(元コア) + - FileBox, NetBox等(既存プラグイン) + - 統一されたFFI TypeBox v2インターフェース + +2. ユーザー定義Box(Nyashコード) + - アプリケーション固有Box + - 将来:StringBox等もNyashコード実装 +``` + ## 🚀 実装計画 -### Phase A: プラグイン版動作確認(1週目) +### Phase A: 予約型保護解除(1週目) -#### 1. 環境変数制御の実装 +#### 1. 予約型保護の条件付き解除 ```rust -// src/mir/builder/utils.rs に追加 -fn get_box_provider(box_type: &str) -> BoxProvider { - if env::var("NYASH_USE_PLUGIN_CORE_BOXES").is_ok() { - // プラグイン版を優先 - if plugin_registry::exists(box_type) { - return BoxProvider::Plugin(box_type); +// src/box_factory/mod.rs: is_reserved_type()修正 +fn is_reserved_type(name: &str) -> bool { + // 環境変数でプラグイン優先モード時は保護解除 + if std::env::var("NYASH_USE_PLUGIN_BUILTINS").is_ok() { + if let Ok(types) = std::env::var("NYASH_PLUGIN_OVERRIDE_TYPES") { + if types.split(',').any(|t| t.trim() == name) { + return false; // 予約型として扱わない + } } } - // nyrt内蔵にフォールバック - BoxProvider::Builtin(box_type) + + matches!(name, "StringBox" | "IntegerBox" | ...) } ``` @@ -90,9 +106,21 @@ match class.as_str() { MirType::Box(class.to_string()) ``` -### Phase C: nyrt実装削除(3週目) +### Phase C: 完全統一(3週目) -#### 削除対象 +#### 1. 予約型保護の完全削除 +```rust +// src/box_factory/mod.rs: 予約型保護を完全削除 +// この関数を削除またはコメントアウト +// fn is_reserved_type(name: &str) -> bool { ... } + +// 登録処理から予約型チェックを削除 +// if is_reserved_type(type_name) && !factory.is_builtin_factory() { +// continue; // この部分を削除 +// } +``` + +#### 2. nyrt実装削除 1. **crates/nyrt/src/lib.rs** - StringBox関連: 約150行 - IntegerBox関連: 約50行 @@ -106,6 +134,12 @@ MirType::Box(class.to_string()) 3. **src/backend/llvm/compiler/codegen/instructions/newbox.rs** - コアBox最適化パス削除 +#### 3. デフォルト動作の確立 +```bash +# 環境変数なしでプラグインBox使用 +./target/release/nyash test.nyash # StringBox = プラグイン版 +``` + ### Phase D: Nyashコード実装(将来) ```nyash diff --git a/nyash.toml b/nyash.toml index 7b4d539c..3dc86e9a 100644 --- a/nyash.toml +++ b/nyash.toml @@ -333,3 +333,45 @@ singleton = false birth = { method_id = 0 } compile = { method_id = 1 } fini = { method_id = 4294967295 } +# StringBox Plugin (Core Box replacement) +[libraries."libnyash_string_plugin.so"] +boxes = ["StringBox"] +path = "target/release/libnyash_string_plugin.so" + +[libraries."libnyash_string_plugin.so".StringBox] +type_id = 10 +abi_version = 1 +singleton = false + +[libraries."libnyash_string_plugin.so".StringBox.methods] +birth = { method_id = 0 } +get = { method_id = 1 } +set = { method_id = 2 } +concat = { method_id = 3 } +length = { method_id = 4 } +substring = { method_id = 5 } +charCodeAt = { method_id = 6 } +indexOf = { method_id = 7 } +lastIndexOf = { method_id = 8 } +replace = { method_id = 9 } +split = { method_id = 10 } +trim = { method_id = 11 } +toUpper = { method_id = 12 } +toLower = { method_id = 13 } +fini = { method_id = 4294967295 } + +# IntegerBox Plugin (Core Box replacement) +[libraries."libnyash_integer_plugin.so"] +boxes = ["IntegerBox"] +path = "target/release/libnyash_integer_plugin.so" + +[libraries."libnyash_integer_plugin.so".IntegerBox] +type_id = 12 +abi_version = 1 +singleton = false + +[libraries."libnyash_integer_plugin.so".IntegerBox.methods] +birth = { method_id = 0 } +get = { method_id = 1 } +set = { method_id = 2 } +fini = { method_id = 4294967295 } \ No newline at end of file diff --git a/nyash.toml.backup2 b/nyash.toml.backup2 new file mode 100644 index 00000000..7b4d539c --- /dev/null +++ b/nyash.toml.backup2 @@ -0,0 +1,335 @@ +[env] +# Put environment defaults used by tools or examples if needed +# Enable using resolver by default (can be disabled with NYASH_SKIP_TOML_ENV=1) +NYASH_ENABLE_USING = "1" +# Enable dev sugar preexpand for @ local alias (line-head) during parsing +NYASH_DEV_AT_LOCAL = "1" + +[using] +paths = ["apps", "lib", "."] + +[modules] +# Map logical namespaces to Nyash source paths (consumed by runner) +selfhost.compiler.debug = "apps/selfhost/compiler/boxes/debug_box.nyash" +selfhost.compiler.parser = "apps/selfhost/compiler/boxes/parser_box.nyash" +selfhost.compiler.emitter = "apps/selfhost/compiler/boxes/emitter_box.nyash" +selfhost.compiler.mir = "apps/selfhost/compiler/boxes/mir_emitter_box.nyash" +selfhost.vm.json_cur = "apps/selfhost/vm/boxes/json_cur.nyash" +selfhost.vm.json = "apps/selfhost/common/json_adapter.nyash" +selfhost.vm.core = "apps/selfhost/vm/boxes/mini_vm_core.nyash" +selfhost.vm.scan = "apps/selfhost/common/mini_vm_scan.nyash" +selfhost.vm.binop = "apps/selfhost/common/mini_vm_binop.nyash" +selfhost.vm.compare = "apps/selfhost/common/mini_vm_compare.nyash" +selfhost.vm.prints = "apps/selfhost/vm/boxes/mini_vm_prints.nyash" +selfhost.vm.seam = "apps/selfhost/vm/boxes/seam_inspector.nyash" + +# Temporary alias keys (migration aid; keys kept stable) +selfhost.common.json = "apps/selfhost/common/json_adapter.nyash" +selfhost.common.scan = "apps/selfhost/common/mini_vm_scan.nyash" +selfhost.common.binop = "apps/selfhost/common/mini_vm_binop.nyash" +selfhost.common.compare = "apps/selfhost/common/mini_vm_compare.nyash" + +# v2 Plugin libraries (loader reads these for TypeBox ABI) +[libraries] +[libraries."libnyash_filebox_plugin.so"] +boxes = ["FileBox"] +path = "plugins/nyash-filebox-plugin/target/release/libnyash_filebox_plugin.so" + +[libraries."libnyash_filebox_plugin.so".FileBox] +type_id = 6 +abi_version = 1 +singleton = false + +[libraries."libnyash_filebox_plugin.so".FileBox.methods] +birth = { method_id = 0 } +open = { method_id = 1 } +read = { method_id = 2 } +write = { method_id = 3 } +close = { method_id = 4 } +exists = { method_id = 5 } +copyFrom = { method_id = 7 } +cloneSelf = { method_id = 8 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_path_plugin.so"] +boxes = ["PathBox"] +path = "plugins/nyash-path-plugin/target/release/libnyash_path_plugin.so" + +[libraries."libnyash_path_plugin.so".PathBox] +type_id = 55 +abi_version = 1 +singleton = false + +[libraries."libnyash_path_plugin.so".PathBox.methods] +birth = { method_id = 0 } +join = { method_id = 1 } +dirname = { method_id = 2 } +basename = { method_id = 3 } +extname = { method_id = 4 } +isAbs = { method_id = 5 } +normalize = { method_id = 6 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_math_plugin.so"] +boxes = ["MathBox", "TimeBox"] +path = "plugins/nyash-math-plugin/target/release/libnyash_math_plugin.so" + +[libraries."libnyash_math_plugin.so".MathBox] +type_id = 50 +abi_version = 1 +singleton = false + +[libraries."libnyash_math_plugin.so".MathBox.methods] +birth = { method_id = 0 } +sqrt = { method_id = 1 } +sin = { method_id = 2 } +cos = { method_id = 3 } +round = { method_id = 4 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_math_plugin.so".TimeBox] +type_id = 51 +abi_version = 1 +singleton = false + +[libraries."libnyash_math_plugin.so".TimeBox.methods] +birth = { method_id = 0 } +now = { method_id = 1 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_regex_plugin.so"] +boxes = ["RegexBox"] +path = "plugins/nyash-regex-plugin/target/release/libnyash_regex_plugin.so" + +[libraries."libnyash_regex_plugin.so".RegexBox] +type_id = 52 +abi_version = 1 +singleton = false + +[libraries."libnyash_regex_plugin.so".RegexBox.methods] +birth = { method_id = 0 } +compile = { method_id = 1 } +isMatch = { method_id = 2 } +find = { method_id = 3 } +replaceAll = { method_id = 4 } +split = { method_id = 5 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_net_plugin.so"] +boxes = ["ClientBox", "ResponseBox", "RequestBox", "ServerBox", "SockServerBox", "SockClientBox", "SockConnBox"] +path = "plugins/nyash-net-plugin/target/release/libnyash_net_plugin.so" + +[libraries."libnyash_net_plugin.so".ClientBox] +type_id = 23 +abi_version = 1 +singleton = false + +[libraries."libnyash_net_plugin.so".ClientBox.methods] +birth = { method_id = 0 } +get = { method_id = 1 } +post = { method_id = 2 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_net_plugin.so".ResponseBox] +type_id = 22 +abi_version = 1 +singleton = false + +[libraries."libnyash_net_plugin.so".ResponseBox.methods] +birth = { method_id = 0 } +setStatus = { method_id = 1 } +setHeader = { method_id = 2 } +write = { method_id = 3 } +readBody = { method_id = 4 } +getStatus = { method_id = 5 } +getHeader = { method_id = 6 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_net_plugin.so".RequestBox] +type_id = 21 +abi_version = 1 +singleton = false + +[libraries."libnyash_net_plugin.so".RequestBox.methods] +birth = { method_id = 0 } +path = { method_id = 1 } +readBody = { method_id = 2 } +respond = { method_id = 3 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_net_plugin.so".ServerBox] +type_id = 20 +abi_version = 1 +singleton = false + +[libraries."libnyash_net_plugin.so".ServerBox.methods] +birth = { method_id = 0 } +start = { method_id = 1 } +stop = { method_id = 2 } +accept = { method_id = 3 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_net_plugin.so".SockServerBox] +type_id = 30 +abi_version = 1 +singleton = false + +[libraries."libnyash_net_plugin.so".SockServerBox.methods] +birth = { method_id = 0 } +start = { method_id = 1 } +stop = { method_id = 2 } +accept = { method_id = 3 } +acceptTimeout = { method_id = 4 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_net_plugin.so".SockClientBox] +type_id = 32 +abi_version = 1 +singleton = false + +[libraries."libnyash_net_plugin.so".SockClientBox.methods] +birth = { method_id = 0 } +connect = { method_id = 1 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_net_plugin.so".SockConnBox] +type_id = 31 +abi_version = 1 +singleton = false + +[libraries."libnyash_net_plugin.so".SockConnBox.methods] +birth = { method_id = 0 } +send = { method_id = 1 } +recv = { method_id = 2 } +close = { method_id = 3 } +recvTimeout = { method_id = 4 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_encoding_plugin.so"] +boxes = ["EncodingBox"] +path = "plugins/nyash-encoding-plugin/target/release/libnyash_encoding_plugin.so" + +[libraries."libnyash_encoding_plugin.so".EncodingBox] +type_id = 53 +abi_version = 1 +singleton = false + +[libraries."libnyash_encoding_plugin.so".EncodingBox.methods] +birth = { method_id = 0 } +toUtf8Bytes = { method_id = 1 } +fromUtf8Bytes = { method_id = 2 } +base64Encode = { method_id = 3 } +base64Decode = { method_id = 4 } +hexEncode = { method_id = 5 } +hexDecode = { method_id = 6 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_json_plugin.so"] +boxes = ["JsonDocBox", "JsonNodeBox"] +path = "plugins/nyash-json-plugin/target/release/libnyash_json_plugin.so" + +[libraries."libnyash_json_plugin.so".JsonDocBox] +type_id = 70 +abi_version = 1 +singleton = false + +[libraries."libnyash_json_plugin.so".JsonDocBox.methods] +birth = { method_id = 0 } +parse = { method_id = 1 } +root = { method_id = 2 } +error = { method_id = 3 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_json_plugin.so".JsonNodeBox] +type_id = 71 +abi_version = 1 +singleton = false + +[libraries."libnyash_json_plugin.so".JsonNodeBox.methods] +birth = { method_id = 0 } +kind = { method_id = 1 } +get = { method_id = 2 } +size = { method_id = 3 } +at = { method_id = 4 } +str = { method_id = 5 } +int = { method_id = 6 } +bool = { method_id = 7 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_toml_plugin.so"] +boxes = ["TOMLBox"] +path = "plugins/nyash-toml-plugin/target/release/libnyash_toml_plugin.so" + +[libraries."libnyash_toml_plugin.so".TOMLBox] +type_id = 54 +abi_version = 1 +singleton = false + +[libraries."libnyash_toml_plugin.so".TOMLBox.methods] +birth = { method_id = 0 } +parse = { method_id = 1 } +get = { method_id = 2 } +toJson = { method_id = 3 } +fini = { method_id = 4294967295 } + +# Python (v2 TypeBox) plugins +[libraries."libnyash_python_plugin.so"] +boxes = ["PyRuntimeBox", "PyObjectBox"] +path = "plugins/nyash-python-plugin/target/release/libnyash_python_plugin.so" + +[libraries."libnyash_python_plugin.so".PyRuntimeBox] +type_id = 40 +abi_version = 1 +singleton = false + +[libraries."libnyash_python_plugin.so".PyRuntimeBox.methods] +birth = { method_id = 0 } +eval = { method_id = 1 } +import = { method_id = 2 } +evalR = { method_id = 11 } +importR = { method_id = 12 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_python_plugin.so".PyObjectBox] +type_id = 41 +abi_version = 1 +singleton = false + +[libraries."libnyash_python_plugin.so".PyObjectBox.methods] +birth = { method_id = 0 } +getattr = { method_id = 1 } +call = { method_id = 2 } +str = { method_id = 3 } +callKw = { method_id = 5 } +getattrR = { method_id = 11 } +callR = { method_id = 12 } +callKwR = { method_id = 15 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_python_parser_plugin.so"] +boxes = ["PythonParserBox"] +path = "plugins/nyash-python-parser-plugin/target/release/libnyash_python_parser_plugin.so" + +[libraries."libnyash_python_parser_plugin.so".PythonParserBox] +type_id = 60 +abi_version = 1 +singleton = false + +[libraries."libnyash_python_parser_plugin.so".PythonParserBox.methods] +birth = { method_id = 0 } +parse = { method_id = 1 } +fini = { method_id = 4294967295 } + +[libraries."libnyash_python_compiler_plugin.so"] +boxes = ["PythonCompilerBox"] +path = "plugins/nyash-python-compiler-plugin/target/release/libnyash_python_compiler_plugin.so" + +[libraries."libnyash_python_compiler_plugin.so".PythonCompilerBox] +type_id = 61 +abi_version = 1 +singleton = false + +[libraries."libnyash_python_compiler_plugin.so".PythonCompilerBox.methods] +birth = { method_id = 0 } +compile = { method_id = 1 } +fini = { method_id = 4294967295 } diff --git a/src/box_factory/mod.rs b/src/box_factory/mod.rs index ec7036f6..b9f9c571 100644 --- a/src/box_factory/mod.rs +++ b/src/box_factory/mod.rs @@ -71,6 +71,15 @@ impl UnifiedBoxRegistry { let mut cache = self.type_cache.write().unwrap(); // Reserved core types that must remain builtin-owned fn is_reserved_type(name: &str) -> bool { + // Phase 15.5: 環境変数でプラグイン優先モード時は保護解除 + if std::env::var("NYASH_USE_PLUGIN_BUILTINS").is_ok() { + if let Ok(types) = std::env::var("NYASH_PLUGIN_OVERRIDE_TYPES") { + if types.split(',').any(|t| t.trim() == name) { + return false; // 予約型として扱わない + } + } + } + matches!( name, // Core value types