feat: Major documentation reorganization and unified Box design updates

## Documentation & Organization
- Moved copilot_issues.txt → 00_MASTER_ROADMAP.md (phases folder)
- Created Phase 9.79b.1 & 9.79b.2 plans for unified Box implementation
- Updated unified-box-design-deep-analysis.md with ChatGPT5 insights
- Added P2P documentation and examples (ping-pong, self-ping)

## Code Updates
- P2PBox: Reverted to original error state for demonstration
- VM: Enhanced BoxCall dispatch for unified approach
- Updated box factory, interpreter calls, and transport layer

## Cleanup & Privacy
- Removed private/ and private_test/ from git tracking
- Added private folders to .gitignore for security
- Cleaned root directory: moved backups, removed temp files
- Moved consultation files to docs/archive/consultations/

## Other Improvements
- Added object literal syntax improvement idea
- Updated CLAUDE.md with master roadmap reference
- Updated CURRENT_TASK.md with latest progress

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-26 20:30:07 +09:00
parent 22212aa314
commit 6eda81f5db
41 changed files with 1446 additions and 3132 deletions

7
.gitignore vendored
View File

@ -45,6 +45,8 @@ nyash-rust/
# 開発用秘密フォルダ(完全除外) # 開発用秘密フォルダ(完全除外)
/development/ /development/
/private/
/private_test/
# Test files # Test files
*.tmp *.tmp
@ -118,4 +120,7 @@ local_tests/
# Font files (already in assets/) # Font files (already in assets/)
*.ttf *.ttf
*.otf *.otf
# Backup files
/backups/

View File

@ -5,22 +5,21 @@
## Start Here (必ずここから) ## Start Here (必ずここから)
- 現在のタスク: docs/development/current/CURRENT_TASK.md - 現在のタスク: docs/development/current/CURRENT_TASK.md
- ドキュメントハブ: README.md - ドキュメントハブ: README.md
- 主軸タスクリスト: docs/development/roadmap/native-plan/copilot_issues.txt - 🚀 **開発マスタープラン**: docs/development/roadmap/phases/00_MASTER_ROADMAP.md
Notes: Notes:
- ここから先の導線は README.md に集約。Claude Codeくんがこのファイルを上書きしても最低限のリンクは保たれるよ。 - ここから先の導線は README.md に集約。Claude Codeくんがこのファイルを上書きしても最低限のリンクは保たれるよ。
## 🤖 **Claude×Copilot協調開発の主軸** ## 🤖 **Claude×Copilot×ChatGPT協調開発**
### 📋 **copilot_issues.txt - 開発の軸となるファイル** ### 📋 **開発マスタープラン - 全フェーズの統合ロードマップ**
**すべてはここに書いてある!** - Phase順タスク・優先順位・技術詳細 **すべてはここに書いてある!** → [00_MASTER_ROADMAP.md](docs/development/roadmap/phases/00_MASTER_ROADMAP.md)
- **Phase 8.4**: AST→MIR Lowering完全実装最優先 - **Phase 8.6**: VM性能改善0.9倍 → 2倍以上**← 現在ここ**
- **Phase 8.5**: MIRダイエット35命令→20命令
- **Phase 8.6**: VM性能改善0.9倍 → 2倍以上
- **Phase 9**: JIT実装 - **Phase 9**: JIT実装
- **Phase 10**: Cranelift JIT主経路/ LLVM AOTは後段 - **Phase 10**: Cranelift JIT主経路/ LLVM AOTは後段
- **Phase 9.8**: BIDレジストリプラグイン全バックエンド対応
**迷ったらcopilot_issues.txtを確認せよ!** **迷ったらマスタープランを確認せよ!**
## 🏃 開発の基本方針: 80/20ルール - 完璧より進捗 ## 🏃 開発の基本方針: 80/20ルール - 完璧より進捗

View File

@ -1,171 +0,0 @@
[package]
name = "nyash-rust"
version = "0.1.0"
edition = "2021"
authors = ["Claude Code <claude@anthropic.com>"]
description = "Everything is Box in Rust - Ultimate Memory Safe Nyash Implementation"
license = "MIT"
repository = "https://github.com/user/nyash"
keywords = ["language", "interpreter", "box", "memory-safe", "rust"]
categories = ["development-tools::parsing", "interpreters"]
# Default features - minimal CLI only
[features]
default = ["cli"]
cli = []
gui = ["dep:egui", "dep:eframe", "dep:egui_extras", "dep:image"]
gui-examples = ["gui"]
all-examples = ["gui-examples"]
[lib]
name = "nyash_rust"
path = "src/lib.rs"
crate-type = ["cdylib", "rlib"]
# Main CLI binary - always available
[[bin]]
name = "nyash"
path = "src/main.rs"
# Examples for development - only available as examples, not bins
[[example]]
name = "gui_simple_notepad"
path = "examples/simple_notepad.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_simple_notepad_v2"
path = "examples/simple_notepad_v2.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_simple_notepad_ascii"
path = "examples/simple_notepad_ascii.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_debug_notepad"
path = "examples/debug_notepad.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_nyash_notepad_jp"
path = "examples/nyash_notepad_jp.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_nyash_explorer"
path = "examples/nyash_explorer.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_nyash_explorer_with_icons"
path = "examples/nyash_explorer_with_icons.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_test_icon_extraction"
path = "examples/test_icon_extraction.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_visual_node_prototype"
path = "development/egui_research/experiments/visual_node_prototype.rs"
required-features = ["gui-examples"]
[dependencies]
# エラーハンドリング
thiserror = "2.0"
anyhow = "1.0"
# シリアライゼーション将来のAST永続化用
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
# コマンドライン(将来の CLI用
clap = { version = "4.0", features = ["derive"] }
# 並行処理GlobalBox用
lazy_static = "1.5"
once_cell = "1.20"
# デバッグ・ログ
log = "0.4"
env_logger = "0.11"
# 日時処理
chrono = "0.4"
# HTTP通信HttpClientBox用
# reqwest = { version = "0.11", features = ["blocking"] } # Temporarily disabled
# 正規表現RegexBox用
regex = "1.0"
# WebAssembly対応
wasm-bindgen = "0.2"
console_error_panic_hook = "0.1"
js-sys = "0.3"
# WASM backend dependencies (Phase 8)
wabt = "0.10"
wasmtime = "35.0.0"
# GUI フレームワーク - only when gui feature is enabled
egui = { version = "0.29", optional = true }
eframe = { version = "0.29", default-features = false, features = ["default_fonts", "glow"], optional = true }
egui_extras = { version = "0.29", features = ["image"], optional = true }
image = { version = "0.25", features = ["png", "ico"], optional = true }
# Windows API
[target.'cfg(windows)'.dependencies]
windows = { version = "0.60", features = [
"Win32_Foundation",
"Win32_Storage_FileSystem",
"Win32_UI_Shell",
"Win32_UI_WindowsAndMessaging",
"Win32_System_Com",
"Win32_Graphics_Gdi",
] }
[dependencies.web-sys]
version = "0.3"
features = [
"console",
"Document",
"Element",
"HtmlElement",
"Window",
"DomTokenList",
"CssStyleDeclaration",
"HtmlCanvasElement",
"CanvasRenderingContext2d",
"ImageData",
"TextMetrics",
"CanvasGradient",
"CanvasPattern",
"Path2d",
]
[dev-dependencies]
# テスト・ベンチマークツール
criterion = "0.5"
# Benchmark configuration (will be added later)
# [[bench]]
# name = "box_performance"
# harness = false
[profile.release]
# 最適化設定
opt-level = 3
lto = true
codegen-units = 1
panic = "abort"
[profile.dev]
# 開発用設定
opt-level = 0
debug = true

View File

@ -1,247 +0,0 @@
Compiling nyash-rust v0.1.0 (/mnt/c/git/nyash-project/nyash)
error: implementation is not supported in `trait`s or `impl`s
--> src/runtime/plugin_loader_v2.rs:235:5
|
235 | impl PluginLoaderV2 {
| ^^^^^^^^^^^^^^^^^^^
|
= help: consider moving the implementation out to a nearby module scope
warning: unused macro definition: `debug_trace`
--> src/interpreter/core.rs:34:14
|
34 | macro_rules! debug_trace {
| ^^^^^^^^^^^
|
= note: `#[warn(unused_macros)]` on by default
warning: unused imports: `BasicBlockIdGenerator`, `BasicBlock`, `CompareOp`, `EffectMask`, `MirFunction`, and `ValueIdGenerator`
--> src/mir/loop_builder.rs:9:21
|
9 | MirInstruction, BasicBlock, BasicBlockId, MirFunction, ValueId,
| ^^^^^^^^^^ ^^^^^^^^^^^
10 | ConstValue, CompareOp, BasicBlockIdGenerator, ValueIdGenerator, EffectMask
| ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
warning: unused import: `HashSet`
--> src/mir/loop_builder.rs:13:33
|
13 | use std::collections::{HashMap, HashSet};
| ^^^^^^^
warning: unexpected `cfg` condition value: `llvm`
--> src/backend/mod.rs:13:7
|
13 | #[cfg(feature = "llvm")]
| ^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: `all-examples`, `cli`, `default`, `dynamic-file`, `gui`, `gui-examples`, `plugins`, and `wasm-backend`
= help: consider adding `llvm` as a feature in `Cargo.toml`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
warning: unexpected `cfg` condition value: `llvm`
--> src/backend/mod.rs:23:7
|
23 | #[cfg(feature = "llvm")]
| ^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: `all-examples`, `cli`, `default`, `dynamic-file`, `gui`, `gui-examples`, `plugins`, and `wasm-backend`
= help: consider adding `llvm` as a feature in `Cargo.toml`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
warning: unused import: `MirInstruction`
--> src/backend/vm_phi.rs:9:41
|
9 | use crate::mir::{BasicBlockId, ValueId, MirInstruction};
| ^^^^^^^^^^^^^^
warning: unused import: `super::Usize`
--> src/bid/types.rs:1:5
|
1 | use super::Usize;
| ^^^^^^^^^^^^
warning: unused import: `std::os::raw::c_char`
--> src/bid/plugin_api.rs:2:5
|
2 | use std::os::raw::c_char;
| ^^^^^^^^^^^^^^^^^^^^
warning: unused imports: `NyashHostVtable`, `NyashMethodInfo`, and `NyashPluginInfo`
--> src/bid/plugins/filebox/mod.rs:7:18
|
7 | use crate::bid::{NyashPluginInfo, NyashMethodInfo, NyashHostVtable};
| ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
warning: unused imports: `SeekFrom` and `Seek`
--> src/bid/plugins/filebox/mod.rs:10:28
|
10 | use std::io::{Read, Write, Seek, SeekFrom};
| ^^^^ ^^^^^^^^
warning: unused imports: `c_char` and `c_void`
--> src/bid/plugins/filebox/mod.rs:11:20
|
11 | use std::os::raw::{c_char, c_void};
| ^^^^^^ ^^^^^^
warning: unused imports: `CStr` and `CString`
--> src/bid/plugins/filebox/mod.rs:13:16
|
13 | use std::ffi::{CStr, CString};
| ^^^^ ^^^^^^^
warning: unused import: `std::ffi::c_void`
--> src/bid/loader.rs:4:5
|
4 | use std::ffi::c_void;
| ^^^^^^^^^^^^^^^^
warning: unused imports: `TlvDecoder` and `TlvEncoder`
--> src/bid/generic_plugin_box.rs:5:23
|
5 | use crate::bid::tlv::{TlvEncoder, TlvDecoder};
| ^^^^^^^^^^ ^^^^^^^^^^
warning: unused import: `crate::bid::types::BidTag`
--> src/bid/generic_plugin_box.rs:6:5
|
6 | use crate::bid::types::BidTag;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `BoxBase`
--> src/runtime/plugin_loader_v2.rs:10:47
|
10 | use crate::box_trait::{NyashBox, BoxCore, BoxBase, StringBox};
| ^^^^^^^
warning: unused import: `std::ffi::c_void`
--> src/runtime/plugin_loader_v2.rs:14:9
|
14 | use std::ffi::c_void;
| ^^^^^^^^^^^^^^^^
error[E0599]: no method named `invoke_instance_method` found for struct `RwLockReadGuard<'_, enabled::PluginLoaderV2>` in the current scope
--> src/backend/vm.rs:548:34
|
548 | match loader.invoke_instance_method(&plugin.box_type, method, plugin.instance_id, &arg_values) {
| ^^^^^^^^^^^^^^^^^^^^^^ method not found in `RwLockReadGuard<'_, PluginLoaderV2>`
warning: unused variable: `registry`
--> src/box_factory/plugin.rs:53:13
|
53 | let registry = get_global_registry();
| ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_registry`
|
= note: `#[warn(unused_variables)]` on by default
warning: variable does not need to be mutable
--> src/interpreter/expressions/calls.rs:734:13
|
734 | let mut is_builtin = is_builtin_box(parent);
| ----^^^^^^^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
warning: variable does not need to be mutable
--> src/interpreter/objects.rs:1106:17
|
1106 | let mut is_builtin = is_builtin_box(parent_name);
| ----^^^^^^^^^^
| |
| help: remove this `mut`
warning: unused variable: `args`
--> src/instance_v2.rs:147:28
|
147 | pub fn init(&mut self, args: &[Box<dyn NyashBox>]) -> Result<(), String> {
| ^^^^ help: if this is intentional, prefix it with an underscore: `_args`
warning: unused variable: `nyash_value`
--> src/instance_v2.rs:289:21
|
289 | if let Some(nyash_value) = self.fields_ng.lock().unwrap().get(field_name) {
| ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_nyash_value`
warning: variable does not need to be mutable
--> src/mir/builder.rs:85:13
|
85 | let mut function = MirFunction::new(signature, entry);
| ----^^^^^^^^
| |
| help: remove this `mut`
warning: unused variable: `block_id`
--> src/mir/loop_builder.rs:246:39
|
246 | fn mark_block_unsealed(&mut self, block_id: BasicBlockId) -> Result<(), String> {
| ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_block_id`
warning: unused variable: `block_id`
--> src/mir/loop_builder.rs:273:49
|
273 | fn get_variable_at_block(&self, name: &str, block_id: BasicBlockId) -> Option<ValueId> {
| ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_block_id`
warning: unused variable: `dst`
--> src/backend/vm_phi.rs:48:9
|
48 | dst: ValueId,
| ^^^ help: if this is intentional, prefix it with an underscore: `_dst`
warning: unused variable: `f`
--> src/bid/plugin_api.rs:167:36
|
167 | pub fn with_alloc<F>(mut self, f: F) -> Self
| ^ help: if this is intentional, prefix it with an underscore: `_f`
warning: variable does not need to be mutable
--> src/bid/plugin_api.rs:167:26
|
167 | pub fn with_alloc<F>(mut self, f: F) -> Self
| ----^^^^
| |
| help: remove this `mut`
warning: unused variable: `f`
--> src/bid/plugin_api.rs:176:35
|
176 | pub fn with_free<F>(mut self, f: F) -> Self
| ^ help: if this is intentional, prefix it with an underscore: `_f`
warning: variable does not need to be mutable
--> src/bid/plugin_api.rs:176:25
|
176 | pub fn with_free<F>(mut self, f: F) -> Self
| ----^^^^
| |
| help: remove this `mut`
warning: unused variable: `f`
--> src/bid/plugin_api.rs:183:34
|
183 | pub fn with_log<F>(mut self, f: F) -> Self
| ^ help: if this is intentional, prefix it with an underscore: `_f`
warning: variable does not need to be mutable
--> src/bid/plugin_api.rs:183:24
|
183 | pub fn with_log<F>(mut self, f: F) -> Self
| ----^^^^
| |
| help: remove this `mut`
warning: unused variable: `args`
--> src/runtime/plugin_loader_v2.rs:352:46
|
352 | pub fn create_box(&self, box_type: &str, args: &[Box<dyn NyashBox>]) -> BidResult<Box<dyn NyashBox>> {
| ^^^^ help: if this is intentional, prefix it with an underscore: `_args`
For more information about this error, try `rustc --explain E0599`.
warning: `nyash-rust` (lib) generated 33 warnings
error: could not compile `nyash-rust` (lib) due to 2 previous errors; 33 warnings emitted

View File

View File

@ -0,0 +1,113 @@
Nyashプログラミング言語の革命的設計変更について深い技術的相談をお願いします。
【背景】
Nyashは「Everything is Box」哲学を掲げるプログラミング言語です。現在、3種類のBoxが存在します
1. ビルトインBoxStringBox, IntegerBox等- Rustで静的リンク
2. プラグインBoxFileBox等- 動的ライブラリ(.soで提供
3. ユーザー定義Boxbox Person等- Nyashコードで定義
【現状の問題】
現在、2つの異なるプラグインシステムが並存しています
- plugin_loader.rs1217行: ビルトインBoxを動的ライブラリ化するシステム未使用
- plugin_loader_v2.rs906行: 汎用プラグインシステムBID-FFI
合計2000行以上の重複コードが存在し、メンテナンスが困難です。
【革命的提案ビルトインBox完全プラグイン化】
すべてのBoxStringBox、IntegerBox含むをプラグインとして実装する提案です。
```rust
// 現在
ビルトインStringBox → Rust静的リンク
プラグインFileBox → 動的ロード(.so
// 提案
すべてのBox → プラグイン(.soとして統一
```
【実装案】
```rust
// コアBoxの定義
const CORE_BOXES: &[&str] = &[
"libnyash_string_box.so",
"libnyash_integer_box.so",
"libnyash_bool_box.so",
"libnyash_console_box.so", // print用
];
// 起動時自動ロード
fn main() {
for plugin in CORE_BOXES {
plugin_loader.load_required(plugin)?;
}
}
```
【期待されるメリット】
1. コード削減plugin_loader.rs1217行を完全削除
2. 統一性「Everything is Box」の究極の実現
3. 柔軟性StringBoxすら置き換え可能カスタムString実装など
4. ビルド高速化:本体が軽量化
5. 配布の柔軟性必要なBoxだけ選択可能
6. 開発の独立性各Boxを独立して開発・テスト可能
【懸念事項と対策案】
1. パフォーマンス
- 懸念FFI境界でのオーバーヘッド
- 分析C関数呼び出しなのでナ秒レベル、実用上問題なし
2. デバッグの困難さ
- 懸念:エラー時のスタックトレースが不明瞭
- 対策案:
a) プラグイン側での詳細ロギング
b) デバッグシンボルの保持
c) プラグイン単体テストの充実
3. 起動時間
- 懸念:多数のプラグインロードで遅くなる?
- 対策案コアBoxのみ必須、他は遅延ロード
4. 配布の複雑さ
- 懸念:実行ファイル+多数の.soファイル
- 対策案:標準パスに配置、設定ファイルで管理
【深く検討してほしい点】
1. 技術的妥当性
- この設計は本当に実現可能で健全でしょうか?
- 見落としている致命的な問題はありませんか?
2. パフォーマンスへの実影響
- FFIオーバーヘッドは本当に無視できるレベルでしょうか
- 頻繁に呼ばれるメソッドtoString等での累積的影響は
3. エコシステムへの影響
- すべてがプラグインになることで、ライブラリ開発はどう変わりますか?
- パッケージマネージャーの設計にどんな影響がありますか?
4. 他言語での前例
- 同様のアプローチを採用した言語はありますか?
- 成功例・失敗例から学べることは?
5. セキュリティ
- コアBoxまでプラグイン化することのセキュリティリスクは
- 悪意のあるStringBox置き換えなどへの対策は
6. 開発体験
- デバッグの困難さは実際どの程度深刻でしょうか?
- IDE統合やデバッガサポートはどうなりますか
7. 段階的移行戦略
- 一気に移行すべきか、段階的に移行すべきか?
- 既存ユーザーへの影響を最小化する方法は?
8. 長期的な保守性
- 5年後、10年後もこの設計は維持可能でしょうか
- 技術的負債になる可能性は?
【最終的な問い】
「Everything is Box」哲学を実装レベルでも完全に実現するこの提案は、革新的な美しさか、それとも行き過ぎた純粋主義でしょうか
実装の現実性、パフォーマンス、開発体験、エコシステムなど、多角的な視点から深い分析をお願いします。特に、この決定が言語の将来に与える影響について、時間をかけて考察していただければ幸いです。

View File

@ -0,0 +1,170 @@
Nyash MIRレベルデバッグインフラストラクチャ設計相談
【背景】
NyashはMIR中間表現を経由して複数のバックエンドで実行されます
- VM現在実装済み
- JITPhase 9で実装予定
- AOT将来実装
- WASM実装済み
現在、デバッグ・メモリリーク検出・パフォーマンス解析機能をVM層で実装することを検討していますが、
MIRレベルで実装できれば、すべてのバックエンドで統一的に使える理想的な設計になります。
【技術的課題】
1. MIRは低レベル命令26命令で、高レベルのBox情報が失われる
- NewBox(type_id=6, args) → 6が何のBoxか分からない
- BoxCall(reg=0, "toString") → どのBox型のメソッドか不明
2. MIRは実行前の静的表現なので、実行時情報の追跡が困難
- Boxの生成・破棄タイミング
- メソッド実行時間の計測
- メモリ使用量の追跡
3. 各バックエンドでの実装の違い
- VM: スタックベース、インタープリター
- JIT: ネイティブコード生成
- WASM: 別の仮想マシン
【設計案1: MIRデバッグ命令の追加】
```rust
pub enum MIRInstruction {
// 既存の命令
NewBox(u16, Vec<u8>),
BoxCall(RegisterIndex, RegisterIndex, String, Vec<RegisterIndex>),
// デバッグ専用命令(本番では無視)
DebugBoxCreate(RegisterIndex, String), // Box型名を記録
DebugMethodEnter(String, Vec<RegisterIndex>), // メソッド開始
DebugMethodExit(RegisterIndex), // メソッド終了
DebugSnapshot(String), // 任意の時点のスナップショット
}
```
メリット:
- MIRレベルで完結
- すべてのバックエンドで同じデバッグ情報
デメリット:
- MIRが肥大化
- 本番実行時のオーバーヘッド
【設計案2: MIRメタデータの分離】
```rust
pub struct MIRModule {
pub functions: HashMap<String, MIRFunction>,
pub constants: Vec<Constant>,
pub debug_info: Option<MIRDebugInfo>, // デバッグ時のみ生成
}
pub struct MIRDebugInfo {
// 命令インデックス → デバッグ情報
instruction_map: HashMap<usize, InstructionDebugInfo>,
// type_id → Box型名
type_names: HashMap<u16, String>,
// ソースマップ
source_map: SourceMap,
}
```
メリット:
- MIR本体はクリーン
- デバッグ時のみメタデータ生成
デメリット:
- 実行時追跡には各バックエンドでのフック必要
【設計案3: MIRプロファイリング拡張】
```rust
pub trait MIRExecutor {
// 基本実行
fn execute(&mut self, module: &MIRModule) -> Result<(), Error>;
// プロファイリング付き実行
fn execute_with_profiling(
&mut self,
module: &MIRModule,
profiler: &mut dyn MIRProfiler
) -> Result<(), Error>;
}
pub trait MIRProfiler {
fn on_instruction(&mut self, pc: usize, inst: &MIRInstruction);
fn on_box_create(&mut self, type_id: u16, reg: RegisterIndex);
fn on_method_call(&mut self, receiver: RegisterIndex, method: &str);
// ...
}
```
メリット:
- 各バックエンドが同じプロファイラーインターフェースを実装
- 柔軟な拡張が可能
デメリット:
- 各バックエンドでの実装が必要
【設計案4: MIR静的解析による事前情報抽出】
```rust
pub struct MIRAnalyzer {
pub fn analyze(module: &MIRModule) -> AnalysisResult {
// Box生成パターンの検出
let box_creations = find_box_creations(&module);
// メソッド呼び出しグラフの構築
let call_graph = build_call_graph(&module);
// 潜在的なメモリリークパターン
let leak_patterns = detect_leak_patterns(&module);
AnalysisResult {
box_creations,
call_graph,
leak_patterns,
// ...
}
}
}
```
メリット:
- 実行前に多くの情報を取得
- オーバーヘッドなし
デメリット:
- 動的な振る舞いは追跡できない
【質問事項】
1. MIRレベルでのデバッグ実装について、どの設計案が最も実用的でしょうか
2. 他の言語LLVM IR、Java bytecode、.NET IL等では、
このような問題をどのように解決していますか?
3. MIR命令セットの拡張 vs メタデータ分離、
どちらがパフォーマンスと保守性のバランスが良いでしょうか?
4. JIT/AOTコンパイル時にデバッグコードを埋め込む方法として、
効率的なアプローチはありますか?
5. WASMのような異なる実行環境でも統一的にデバッグ情報を
扱う方法についてアドバイスをお願いします。
【現在のMIR命令セット26命令
- 基本: Const, Move, Copy
- 算術: Add, Sub, Mul, Div, Mod, Neg
- 比較: Eq, Ne, Lt, Le, Gt, Ge
- 論理: And, Or, Not
- Box: NewBox, BoxCall, GetField, SetField
- 制御: Br, Jmp, Call, Ret
- メモリ: RefNew, RefGet, RefSet
- 型: AsType, IsType
【Nyashの設計哲学】
- Everything is Box - すべてがBoxオブジェクト
- メモリ安全性重視
- 初学者フレンドリー
- 高速実行VM実装で13.5倍高速化達成)
専門的な観点から、MIRレベルでの統一デバッグインフラストラクチャの
実現可能性と最適な設計についてアドバイスをお願いします。

View File

@ -1,74 +1,51 @@
# 🎯 CURRENT TASK - 2025-08-26Context Reset / Fresh Focus # 🎯 CURRENT TASK - 2025-08-26Phase 9.79b Kickoff
コンテキストを「0%」にリセットし、いま必要なことだけに集中するにゃ。 コンテキストを最小化して、次フェーズへの導線だけ残すにゃ。
## ⏱️ 今日のフォーカスPhase 9.79a: Unified Dispatch + P2P Polish ## ⏱️ 今日のフォーカスPhase 9.79b: Unified IDs → VM Thunks
- 判断: 統一Box設計は「非侵襲のディスパッチ統一」から入る → P2PBox磨きを同時並行 - 目的: Box種別builtin/user/pluginをMIR/VMで数値IDスロット統一に移行し、Phase 10(JIT)の足場を固める。
- 目的: ユニバーサルメソッドtoString/type/equals/cloneをVM/Interpreter前段で統一 + P2PBoxのmulti-node/async UX安定化
### 直近の実行タスク(小さく早く) ### 直近タスク(小さく早く)
1) ユニバーサルメソッドの前段ディスパッチ(非侵襲) 1) 9.79b.1: Unified Registry IDs + Builder Slotting
- VM/Interpreterで`toString/type/equals/clone`を共通ヘルパにマップ(トレイト変更なし - 型ID/メソッドスロットの導入(レジストリ
2) P2PBox磨きmulti-node/async/解除 - ユニバーサルメソッド低スロット予約0..3
- share/cloneセマンティクスshare=共有, clone=新規(実装済みの明文化 - Builderが解決可能なBoxCallに`method_id`を付与(未解決は遅延
- unregisterの安全化endpoint一致 or refcount 2) 9.79b.2: VM VTable Thunks + Mono-PIC
- onOnce/off のE2Eテスト追加 - `execute_boxcall`をvtable+thunkの単一路線へ
- VM表示整合getLast*/debug_* の toString/Console - call-site単位のモモーフィックPICを追加
3) E2Eスモーク更新
- self→self, two-node ping-pong安定
- asyncデモTimeBox併用で確実に出力
### すぐ試せるコマンド(最小) ### すぐ試せるコマンド
```bash ```bash
# RustRelease
cargo build --release -j32 cargo build --release -j32
./target/release/nyash --help ./target/release/nyash examples/p2p_self_ping.nyash
./target/release/nyash examples/p2p_ping_pong.nyash
# Plugin デバッグ実行(任意)
NYASH_DEBUG_PLUGIN=1 ./target/release/nyash --backend vm local_tests/extern_console_log.nyash || true
# WASMWeb配布
cd projects/nyash-wasm && wasm-pack build --target web --out-dir pkg
``` ```
## 現在の地図Done / Doing / Next ## 現在の地図Done / Next
### ✅ 完了 ### ✅ 完了9.79a
- PluginHostファサード導入・移行create/invoke/extern - ユニバーサル前段ディスパッチtoString/type/equals/cloneInterpreter/VM
- TLVヘッダ/引数/ハンドルの共通化(`plugin_ffi_common.rs` - P2P unregister安全化・onOnce/off E2E・self/two-nodeスモーク
- Interpreter分割の導線: `eval.rs` / `calls.rs` / `methods_dispatch.rs` 抽出 - IntentBoxのpayload糖衣MapBox/JSONBox直渡し可
- ログ静音の基盤: `idebug!`NYASH_DEBUG=1 で有効)を calls/core/statements に適用 - Docs: P2Pリファレンス/サンプル
- MIR modular builder ゲート追加feature: `mir_modular_builder`/ 整合パッチ投入
### 🚧 進行中(小タスク ### ⏭️ 次9.79b
- Interpreterログ統一の残り`delegation.rs` など) - 9.79b.1: `phase_9_79b_1_unified_registry_ids_and_builder_slotting.md`
- PluginHost の `resolve_method` キャッシュ化I/O削減 - 9.79b.2: `phase_9_79b_2_vm_vtable_thunks_and_pic.md`
### ⏭️ 次アクション(今日~明日 ## 統一Box設計メモ唯一参照
- 9.79a-M1: ユニバーサル前段ディスパッチVM/Interpreter/ 回帰確認 - `docs/ideas/other/2025-08-25-unified-box-design-deep-analysis.md`
- 9.79a-M2: P2P unregister安全化 + onOnce/off E2E + async安定 - 数値ID/スロット/Thunk/PIC/DebugInfoの全体像
- 9.79a-M3: VM表示整合/ Docs更新言語ガイド・P2Pリファレンス
## 決定事項Unified Box設計メモ ## 参考リンク
- ドキュメント: `docs/ideas/other/2025-08-25-unified-box-design-deep-analysis.md` - MIR命令セット: `docs/reference/mir/INSTRUCTION_SET.md`
- 判断: まずはディスパッチャ層でユニバーサルメソッドを統一(トレイト変更なし) - Phase 9.79a(完了): `docs/development/roadmap/phases/phase-9/phase_9_79a_unified_box_dispatch_and_p2p_polish.md`
- P2Pは共有セマンティクスshare=共有, clone=新規)を維持しつつ unregister 正式化へ - Phase 9.79b(計画):
- `docs/development/roadmap/phases/phase-9/phase_9_79b_1_unified_registry_ids_and_builder_slotting.md`
## 参考リンク(唯一参照/ゲート) - `docs/development/roadmap/phases/phase-9/phase_9_79b_2_vm_vtable_thunks_and_pic.md`
- MIR命令セット26命令: `docs/reference/mir/INSTRUCTION_SET.md`
- Phase 9.79P2P: `docs/development/roadmap/phases/phase-9/phase_9_79_p2pbox_rebuild.md`
- Phase 9.79aUnified Dispatch + P2P Polish: `docs/development/roadmap/phases/phase-9/phase_9_79a_unified_box_dispatch_and_p2p_polish.md`
- Phase 9.78h(前段完了): `docs/development/roadmap/phases/phase-9/phase_9_78h_mir_pipeline_stabilization.md`
- Phase 10Cranelift JIT主経路: `docs/development/roadmap/phases/phase-10/phase_10_cranelift_jit_backend.md` - Phase 10Cranelift JIT主経路: `docs/development/roadmap/phases/phase-10/phase_10_cranelift_jit_backend.md`
## Doneの定義P2PBox 最小)
- `LocalLoopback` で ping/pong が安定
- P2PBox APIstart/stop/send/broadcast/reply/onが固まる
- ResultBox経由でエラーが伝搬E2E テスト含む)
- ログは既定静音(環境変数でデバッグオン)
## Parking Lot後でやる ## Parking Lot後でやる
- NyashValue enum導入即値最適化 - NyashValue即値最適化・演算子特化
- トレイト階層化Comparable/Arithmetic etc. - トレイト階層化Comparable/Arithmetic etc.
- メタプログラミング・パイプライン演算子 - オブジェクトリテラル糖衣feature `object_literal`)提案: `docs/ideas/improvements/2025-08-26-object-literal-sugar.md`
- `mir_modular_builder` をデフォルト化(パリティ後)

View File

@ -1,494 +0,0 @@
# 🤖 Copilot様 作業予定・課題整理 (Phase 8.6-10 重点フェーズ)
# Generated: 2025-08-19 (Phase 9.75g-0完了・VM性能改善移行)
# Purpose: Claude×Copilot協調開発のための情報共有
================================================================================
🎯 Nyash実行モード併用戦略
================================================================================
## 🌟 インタープリター+コンパイラ併用の価値
### 実行モード使い分け
```
開発時: インタープリター(デバッグ・即時実行・非同期フル対応)
本番時: インタープリターPythonのように実用的
OR
WASM/AOT性能要求時
配布時: AOT native最高性能
Web時: WASMブラウザ対応
```
### インタープリターの強み
- **即時実行**: コンパイル不要で高速開発
- **デバッグ容易**: 実行時情報の完全把握
- **非同期完全対応**: Rust async/awaitで真の並行処理
- **動的性**: 実行時評価・REPL対応
- **十分な性能**: 多くのユースケースで実用的Pythonが証明
================================================================================
🎯 Phase 8.6-10 開発ロードマップ (性能最適化・LLVM実装重点)
================================================================================
## 🎊 Phase 9.75g-0: BID-FFI Plugin System - 完全完了! ✅
Summary:
- ✅ **動的プラグインシステム完成**: FileBoxプラグインで実証
- ✅ **BID-FFI基盤確立**: 型安全なFFIインターフェース
- ✅ **plugin-tester完成**: 汎用プラグイン診断ツール
- ✅ **型情報管理システム**: nyash.toml外部化、セグフォルト修正
**革命的成果**: NyashがプラグインでBox型を動的拡張可能に
```nyash
// これが現実になった!
local file = new FileBox() // プラグイン提供
local db = new PostgreSQLBox() // 将来: プラグイン提供
local gpu = new CudaBox() // 将来: プラグイン提供
```
References:
- docs/Phase-9.75g-0-BID-FFI-Developer-Guide.md (包括的開発者ガイド)
- tools/plugin-tester/ (プラグイン診断ツール)
------------------------------------------------------------
## 🚨 Phase 8.6: VM性能改善 - 最優先課題(進行中)
Summary:
- **緊急問題**: VMがインタープリターより0.9倍遅い(性能回帰!)
- **目標**: 2倍以上高速化でVM実行を実用レベルに引き上げ
- **担当**: Copilot主導GitHub Issue #112
Priority: **Critical**
Expected Duration: 1-2週間
GitHub Issue: #112 (Phase 8.6 VM性能改善)
### 技術的課題
```bash
# 現状のベンチマーク結果
Interpreter: 110.10ms (ベースライン)
VM: 119.80ms (0.9倍 - 遅い...)
Target: 55.00ms (2倍高速化目標)
```
### 推定原因と対策
- **デバッグ出力過多**: `println!`による性能劣化
- **HashMap操作重い**: ValueId → VM値の変換コスト
- **命令ディスパッチ非効率**: switch文ベースディスパッチ
### 🤖 Copilot協力期待
- VM実行時間詳細測定・プロファイリング
- 命令ディスパッチ最適化direct threading等
- Box操作インライン化・メモリレイアウト最適化
References:
- docs/予定/native-plan/issues/phase_8_6_vm_performance_improvement.md
------------------------------------------------------------
## 📦 Phase 9.8: BIDレジストリ + 自動コード生成ツール - MIR統合の要
Summary:
- **Phase 9.75g-0完了により準備完了**: プラグインがMIR経由で全バックエンド利用可能に
- BIDレジストリと、BID→各ターゲットのスタブ生成import/extern宣言を自動化
Priority: **High** (Phase 8.6完了直後)
Expected Duration: 2-3週間
### 🌟 革命的価値
```bash
# 🎯 1つのプラグインが4バックエンド全対応
nyash bid gen --target wasm bid.yaml # WASM用import生成
nyash bid gen --target vm bid.yaml # VM用関数テーブル生成
nyash bid gen --target llvm bid.yaml # AOT用declare生成LLVM実装時
```
### Scope/Tasks
- BIDレジストリ仕様署名・効果・バージョン・依存関係
- 生成: WASM(importObject), VM(関数テーブル), LLVM(declare), TS/Python(RTEラッパ)
- CLI: `nyash bid gen --target wasm|vm|llvm|ts|py bid.yaml`
### Acceptance
- console/canvasのBIDから各ターゲットの骨子が自動生成される
- **FileBoxプラグインがVM・WASM・AOT全てで動作**
------------------------------------------------------------
## 🔒 Phase 9.9: ExternCall 権限/ケイパビリティモデルSandbox/Allowlist
Summary:
- 外部API呼び出しの安全化。BIDに必要権限を宣言し、ホスト側で許可/拒否。WASMはimport allowlist、VM/LLVMは関数テーブルで制御。
Scope/Tasks:
- 権限種別console, canvas, storage, net, audio...)とポリシー
- 実行時プロンプト/設定ファイル/環境変数での許可
- 失権時の挙動(明示エラー)
Acceptance:
- 禁止権限のExternCallが実行時にブロックされ、明確なエラーが返る
------------------------------------------------------------
## 🧱 Phase 9.10: NyIR公開IR仕様化 + フォーマット + 検証器
Summary:
- 26命令MIRを公開IRNyIR v1として基本セマンティクス凍結。バージョニング、バイナリ`.nybc`/テキスト`.nyir`、厳格検証器を用意。
Scope/Tasks:
- docs/nyir/spec.mdCoreExt骨子
- nyir-parser/nyir-serializer.nyir/.nybc
- Verifier: 所有森/weak/効果/Bus整合
- ツール: `nyashel -S`, `nyir-run`
Acceptance:
- 代表サンプルがNyIRで保存・検証・実行可能
References:
- docs/nyir/spec.md
- docs/予定/native-plan/issues/phase_9_10_nyir_spec.md
------------------------------------------------------------
## 🧪 Phase 9.11: Golden NyIR + Differential 実行テストCI
Summary:
- NyIRダンプをゴールデンとし、interp/vm/wasm/jitの出力一致をCIで検証。
Scope/Tasks:
- golden/*.nyir の整備
- CIで各バックエンド実行→結果一致チェック
Acceptance:
- 主要サンプルで全バックエンド一致
------------------------------------------------------------
## 🏆 Phase 10: Cranelift JIT主経路 + LLVM AOT後段研究
Summary:
- **主経路**: MIR→VMを維持しつつ、ホットパスをCraneliftでJIT化して2倍以上の高速化を狙う
- **LLVM AOT**: 設計資産は維持しつつ、JIT安定後Phase 11以降に検討
- **目標**: VMのホットパスBoxCall/Array/Mapで体感高速化、ベンチで優位性を実証
Priority: **High**Phase 8.6完了直後着手)
Expected Duration: **実装6-8週間段階導入**
### 🚧 Start Gate着手前の必須完了
- MIRダイエット26命令整合完了Printer/Verifier/Optimizer一致・効果ラベル統一
- Loop SSA復帰Phi/Seal/Pred更新のVerifierチェック合格
- TypeOp網羅is/as/isType/asTypeの早期loweringOptimizer診断未lowering検出
- 軽量スナップショットTypeOp/extern_call/loop/await/boxcallでゴールデン緑
- P2PBox再設計Phase 9.79完了・E2Eグリーン
- CLI分離テスト導線`cargo test -p core`)安定
### 🔍 実現可能性チェック項目Cranelift
- ✅ **技術的基盤**: MIR26整合TypeOp/WeakRef/Barrier
- ✅ **VM統計**: `--vm-stats` でホット関数抽出可能
- 🔄 **Proof of Concept**: MIR→CLIFの最小Lower算術/比較/分岐)
- ❓ **実装工数**: BoxCall/Array/MapのJIT最適化の妥当性
### 🌟 インタープリター併用戦略
```
開発・デバッグ: インタープリター(即時実行・完全な情報)
軽量タスク: インタープリターPythonライク
性能要求時: LLVM AOT1000倍高速化
Web配布: WASMブラウザ対応
```
### 🏗️ Phase 10.1: Proof of Concept2週間
Steps:
1) **JITマネージャ**: プロファイル収集・しきい値設計
2) **MIR→CLIF最小Lower**: Const/BinOp/Compare/Branch/Return
3) **呼出しABI**: VMとの引数/戻り値・BoxRef受け渡し
### 🏗️ Phase 10.2: 基本実装4週間
Implementation Steps:
1) `src/backend/cranelift/` 基盤構築
2) MIR→CLIF Lowerの拡充Call/BoxCall/Array系
3) JIT関数テーブル + VM切替の安定化
4) ベンチ: VM比2×目標、BoxCallホットパス優位
### 🌐 Phase 10.3: 非同期の扱い(最小)
- awaitは当面VM側で処理継続JIT対象外
- JIT関数は同期区間を優先将来拡張
### 技術アプローチ
🤖 Copilot協力期待:
- **Cranelift統合**: MIR→CLIF Lower
- **VMハイブリッド**: JITスイッチ・例外/フォールバック
- **ホットパス最適化**: BoxCall/Array/Mapの直結最適化
### パフォーマンス目標
- **同期処理**: VM比 2×以上段階的に引き上げ
- **起動時間**: 低オーバーヘッドJIT初回コストを隠蔽
### Acceptance Criteria
- インタープリター/VMとの互換性結果一致
- ホットパスでの実測高速化2×
- 回帰テスト・スナップショットの整備
References:
- docs/予定/native-plan/issues/phase_10_x_llvm_backend_skeleton.md
### 🌟 戦略的決定: ネームスペース統合はLLVM後に実施
**理由**: 4バックエンドInterpreter/VM/WASM/LLVM全体の知見蓄積後に、最適化された統合設計を一回で実現するため
**効果**: 後戻り・再設計なしで完璧な統合ネームスペースを実装可能
```rust
// Phase 10完了後: 4バックエンド対応統合ネームスペース
pub struct UniversalNamespaceManager {
interpreter_cache: BuiltinCache,
vm_function_table: VmFunctionTable,
wasm_import_object: WasmImports,
llvm_module_linking: LlvmLinker, // LLVM完成後追加
}
```
------------------------------------------------------------
## 🧰 Phase 10.1: LLVM 外部関数マッピング方針(プラットフォーム抽象)
Summary:
- ExternCallのFQN→ネイティブ関数printf等への写像レイヤーと、OS差の抽象。初手はLinux/clang、他OSは後続。
Scope/Tasks:
- env.console.log → printfテンプレート、他は段階的拡張
- プラットフォーム切替featureとリンク方針
Acceptance:
- 代表ExternCallconsole.logがAOTバイナリで出力可能
------------------------------------------------------------
## 🧩 Phase 10.2: Host API層C-ABI `ny_host_*` / WASM `nyir_host`
Summary:
- Rust依存を薄い宿主APIへ集約。C-ABI公開ファイル/メモリ/時間等、WASMは`nyir_host` importで提供。
Scope/Tasks:
- `ny_host_*`関数群read_file/free/clockなどをC-ABIで実装
- Nyash側extern宣言と所有移管`*_from_raw`/`*_into_raw`
- WASM: import `nyir_host` 名前空間で最低限の関数提供
Acceptance:
- 代表I/OがHost API経由で動作し、Rust実装置換が容易
------------------------------------------------------------
## 🧱 Phase 10.3: ランタイム層の切り分けcorelang/rt/sys/std
Summary:
- corelang純Nyash, rtBox ABI/所有/weak/Safepoint/Bus, sysプラットフォーム, stdNyash実装に整理。
Scope/Tasks:
- ドキュメント化+最小コードの配置替えスケルトン
Acceptance:
- 層構造が明文化され、新規実装がガイドに従って進められる
------------------------------------------------------------
## 🧬 Phase 10.4: Box ABIfat ptrとLLVM属性Effects
Summary:
- Boxのfat pointerdata*, typeid, flagsの定義、Weakの世代タグ、SafepointのLLVM降ろし、Effect→LLVM属性readonly/readnone等
Scope/Tasks:
- LLVM IR側のstruct宣言・属性付与の雛形
Acceptance:
- 代表関数で属性が付与され、最適化に寄与noalias/argmemonly等は可能な範囲で
------------------------------------------------------------
## 📚 Phase 10.5: コア標準String/Array/MapNyash実装Rust依存の段階的削減
Summary:
- 現在Rust実装に依存している基本コンテナString/Array/Mapを、rt/sys層を活用してNyash実装に置換。
Scope/Tasks:
- String: {ptr,len,cap}, new/push_str/substr/len、`ny_host_alloc/realloc/free`
- Array<T>: {ptr,len,cap}, push/get/set/len/reserve、要素fini
- Map<K,V>: 簡易hash、set/get/remove/len、所有規則順守
Acceptance:
- 代表サンプルでString/Array/MapがNyash実装で動作し、Rust実装をリンクせずに通る
References:
- docs/予定/native-plan/issues/phase_10_5_core_std_nyash_impl.md
## Phase 11-14: Infrastructure & Polish
### Phase 11: MIR Optimization Framework
- エスケープ解析基盤
- 型特殊化・ボックス化解除
- デッドコード除去
### Phase 12: Advanced JIT Features
- Profile-guided optimization
- インライン展開
- レジスタ割り当て最適化
### Phase 13: Production Readiness
- GC統合最適化
- メモリ使用量最適化
- 起動時間短縮
### Phase 14: Packaging/CI polish
Summary:
- Windows/Linux の配布パッケージ化と CI 整備。
Scope/Tasks:
- GitHub Actions: Windows(MSVC)/WSL+cargo-xwin のマトリクス
- dist/: nyash(.exe) + LICENSE/README 同梱
Acceptance Criteria:
- リリースアーティファクトが自動生成される
================================================================================
🧠 AI大会議 + 実用優先戦略で得られた技術的知見 (2025-08-14更新)
================================================================================
## Gemini先生の助言修正適用
✅ エスケープ解析・ボックス化解除が性能の鍵
✅ wasmtime compileは短期的に実用的 → **Phase 9で最優先実装**
✅ WASM実行は確実に高速13.5倍実証済み)
🔄 Cranelift → LLVM段階的アプローチ → **実用優先でLLVM直接へ**
## codex先生の助言重点化
✅ MIR前倒し実装推奨全バックエンドが恩恵
✅ wasmtime互換性管理が重要 → **AOT実装で最重要**
✅ CPU差異対応 (baseline/v3二段ビルド)
✅ 起動時間・割当削減・配布体験がKPI → **AOT価値の核心**
## Claude統合分析実用優先
✅ 実用価値最大化: WASM+AOTで十分な競争力
✅ 開発効率: Cranelift JITの恩恵限定的cargo build変わらず
✅ Everything is Box最適化が差別化の核心
✅ 時間効率: 2-3ヶ月節約でLLVM集中投資
## 🎯 実用優先戦略の確定理由
- **ユーザー体験**: WASM既に動作、AOTで配布価値追加
- **開発効率**: Cranelift JITは重複投資Rust開発環境改善せず
- **競合優位**: AOT+LLVM早期実現で差別化
- **リソース効果**: 限られた開発時間の最大効率化
================================================================================
💡 Copilot様への具体的お願い・相談事項
================================================================================
## 🔧 Phase 8.6 VM性能改善 (最優先)
### VM実行時間詳細測定・プロファイリング
❓ 命令ディスパッチのボトルネック特定方法は?
❓ HashMap操作の最適化戦略は
❓ デバッグ出力削除による性能改善測定は?
### VM最適化実装
❓ Direct threading実装の現実的アプローチは
❓ Register-based VM への移行可能性は?
❓ Box操作インライン化の効果的な実装は
## 🚀 長期戦略相談
### インタープリター併用戦略
❓ 開発時と本番時の最適な使い分け方法は?
❓ インタープリターとコンパイラの互換性保証は?
❓ Pythonライクな実用性の実現方法は
### Phase 10 LLVM実現可能性調査 (研究段階)
❓ MIR→LLVM IR変換の基本的な実装戦略は
❓ Box型のLLVM表現として最適なアプローチは
❓ C-ABIとの統合によるプラグイン連携可能性は
❓ 現実的な開発期間での完成可能性評価は?
### Everything is Box最適化
❓ Box操作の根本的高速化戦略は
❓ エスケープ解析によるスタック化判定は?
❓ 型特殊化・ボックス化解除の実装戦略は?
### ベンチマーク戦略
❓ インタープリター/VM/WASM/LLVMの性能比較方法は
❓ 非同期処理のベンチマーク設計は?
❓ 実用アプリケーションでの測定指標は?
================================================================================
📊 進捗管理・コミュニケーション
================================================================================
## 🤝 協調開発ルール
### コミット・マージ戦略
✅ 大きな変更前にはdocs/CURRENT_TASK.mdで情報共有
✅ ベンチマーク機能は最優先で維持
✅ CLI統合は両機能を統合的に対応
✅ 競合発生時は機能優先度で解決
### 進捗報告
📅 週次: 進捗状況をCURRENT_TASK.mdに反映
📅 完了時: 新機能のベンチマーク結果を共有
📅 問題発生: AI大会議で技術的相談
### 品質保証
✅ cargo check でビルドエラーなし
✅ 既存ベンチマークが regression なし
✅ 新機能のドキュメント整備
✅ テストケース追加・CI通過
================================================================================
🎯 期待される成果・インパクト
================================================================================
## Phase 8-9完了時の成果 (達成済み・進行中)
🏆 RefNew/RefGet/RefSet WASM完全動作
🏆 Box操作ベンチマーク追加
🏆 メモリレイアウト最適化効果測定
🏆 26命令MIR階層化完了Phase 8.5
🔄 **VM性能改善進行中Phase 8.6** - GitHub Issue #112
🏆 **Phase 9.75g-0 BID-FFI Plugin System完全完了**
🏆 警告削減100%達成Phase 9.75j
🏆 BoxCall実装・wasmtime更新Phase 9.77
## Phase 10以降の展望
🚀 **WASM復旧完了** (Phase 9.77): 基本機能の完全動作
🚀 **Cranelift JIT** (Phase 10): VM比2×以上の高速化段階導入
🚀 **非同期ネイティブ実装** (Phase 10.2): async/await完全対応
🚀 **インタープリター併用** : 開発・本番両対応
## 言語としての完成度向上
💎 Everything is Box哲学のネイティブ実現
💎 インタープリター+コンパイラの最適併用
💎 4つの実行形態対応Interpreter/VM/WASM/AOT
💎 Pythonライクな実用性C++並みの性能
================================================================================
📞 連絡・相談方法
================================================================================
技術的相談や進捗報告は、以下の方法でお気軽にどうぞ:
1. 📝 GitHub Issues・Pull Request
2. 📋 docs/CURRENT_TASK.md コメント
3. 🤖 AI大会議 (重要な技術決定)
4. 💬 コミットメッセージでの進捗共有
どんな小さなことでも相談大歓迎です!
一緒にNyashを最高の言語にしていきましょう🚀
================================================================================
最終更新: 2025-08-19 (Phase 9.75g-0完了・VM性能改善最優先・LLVM調査段階化)
作成者: Claude (BID-FFIプラグインシステム完了 + 最新優先順位反映)
🎯 重要な変更点:
- ✅ **Phase 9.75g-0 BID-FFI Plugin System完全完了** (動的プラグインシステム実現)
- 🔄 **Phase 8.6 VM性能改善を最優先** (進行中 - GitHub Issue #112)
- 📦 **Phase 9.8 BIDレジストリ** (Phase 8.6完了後の次期重点)
- 🔍 **Phase 10 LLVM** (実現可能性調査・検証段階として位置づけ)
- 🌟 **ネームスペース統合戦略変更** (LLVM完成後に4バックエンド統合設計)
- 📅 **優先順位明確化**: VM性能 → BIDレジストリ → LLVM調査 の順序
================================================================================

View File

@ -0,0 +1,219 @@
# 🚀 Nyash開発マスタープラン
Status: Active Development
Last Updated: 2025-08-26
Purpose: Claude×Copilot×ChatGPT協調開発の総合ロードマップ
## 📍 現在位置
- **現在フェーズ**: Phase 8.6 VM性能改善進行中
- **次フェーズ**: Phase 9 JIT実装
- **詳細タスク**: [CURRENT_TASK.md](../../current/CURRENT_TASK.md)
## 🗺️ フェーズ概要
| Phase | 状態 | 概要 | 詳細リンク |
|-------|------|------|------------|
| 8.4 | ✅完了 | AST→MIR Lowering完全実装 | [phase_8_4_ast_mir_lowering.md](phase-8/phase_8_4_ast_mir_lowering.md) |
| 8.5 | ✅完了 | MIRダイエット35→26命令 | [phase_8_5_mir_35_to_26_reduction.md](phase-8/phase_8_5_mir_35_to_26_reduction.md) |
| 8.6 | 🔄進行中 | VM性能改善0.9倍→2倍以上 | [phase_8_6_vm_performance_improvement.md](phase-8/phase_8_6_vm_performance_improvement.md) |
| 9 | 📅予定 | JIT実装 | [phase-9/](phase-9/) |
| 9.75g-0 | ✅完了 | BID-FFI Plugin System | [Phase-9.75g-0-BID-FFI-Developer-Guide.md](phase-9/Phase-9.75g-0-BID-FFI-Developer-Guide.md) |
| 9.8 | 📅予定 | BIDレジストリ + 自動コード生成 | [phase_9_8_bid_registry_and_codegen.md](phase-9/phase_9_8_bid_registry_and_codegen.md) |
| 10 | 📅予定 | Cranelift JIT主経路 | [phase_10_cranelift_jit_backend.md](phase-10/phase_10_cranelift_jit_backend.md) |
| 11+ | 🔮将来 | LLVM AOT研究段階 | 後段検討 |
---
## 🎯 Nyash実行モード併用戦略
### 🌟 インタープリター+コンパイラ併用の価値
#### 実行モード使い分け
```
開発時: インタープリター(デバッグ・即時実行・非同期フル対応)
本番時: インタープリターPythonのように実用的
OR
WASM/AOT性能要求時
配布時: AOT native最高性能
Web時: WASMブラウザ対応
```
#### インタープリターの強み
- **即時実行**: コンパイル不要で高速開発
- **デバッグ容易**: 実行時情報の完全把握
- **非同期完全対応**: Rust async/awaitで真の並行処理
- **動的性**: 実行時評価・REPL対応
- **十分な性能**: 多くのユースケースで実用的Pythonが証明
---
## 📊 Phase別詳細
### 🚨 Phase 8.6: VM性能改善 - 最優先課題(進行中)
**Summary**:
- **緊急問題**: VMがインタープリターより0.9倍遅い(性能回帰!)
- **目標**: 2倍以上高速化でVM実行を実用レベルに引き上げ
- **担当**: Copilot主導GitHub Issue #112
**技術的課題**:
```bash
# 現状のベンチマーク結果
Interpreter: 110.10ms (ベースライン)
VM: 119.80ms (0.9倍 - 遅い...)
Target: 55.00ms (2倍高速化目標)
```
**推定原因と対策**:
- **デバッグ出力過多**: `println!`による性能劣化
- **HashMap操作重い**: ValueId → VM値の変換コスト
- **命令ディスパッチ非効率**: switch文ベースディスパッチ
---
### 🎊 Phase 9.75g-0: BID-FFI Plugin System - 完全完了! ✅
**革命的成果**: NyashがプラグインでBox型を動的拡張可能に
```nyash
// これが現実になった!
local file = new FileBox() // プラグイン提供
local db = new PostgreSQLBox() // 将来: プラグイン提供
local gpu = new CudaBox() // 将来: プラグイン提供
```
**References**:
- [Phase-9.75g-0-BID-FFI-Developer-Guide.md](phase-9/Phase-9.75g-0-BID-FFI-Developer-Guide.md)
- tools/plugin-tester/ (プラグイン診断ツール)
---
### 📦 Phase 9.8: BIDレジストリ + 自動コード生成ツール
**Summary**:
- Phase 9.75g-0完了により準備完了
- BID→各ターゲットのスタブ生成自動化
**革命的価値**:
```bash
# 🎯 1つのプラグインが4バックエンド全対応
nyash bid gen --target wasm bid.yaml # WASM用import生成
nyash bid gen --target vm bid.yaml # VM用関数テーブル生成
nyash bid gen --target llvm bid.yaml # AOT用declare生成LLVM実装時
```
---
### 🏆 Phase 10: Cranelift JIT主経路
**Summary**:
- MIR→VMを維持しつつ、ホットパスをCraneliftでJIT化
- 目標: VM比2倍以上の高速化
- LLVM AOTは設計資産は維持しつつ、Phase 11以降に検討
**Start Gate着手前の必須完了**:
- ✅ MIRダイエット26命令整合完了
- ✅ VM統計: `--vm-stats` でホット関数抽出可能
- 🔄 Proof of Concept: MIR→CLIFの最小Lower
- ❓ BoxCall/Array/MapのJIT最適化
**実装ステップ**:
1. **Phase 10.1**: Proof of Concept2週間
2. **Phase 10.2**: 基本実装4週間
3. **Phase 10.3**: 非同期の扱い(最小)
---
## 🧠 AI大会議から得られた技術的知見
### Gemini先生の助言
- ✅ エスケープ解析・ボックス化解除が性能の鍵
- ✅ wasmtime compileは短期的に実用的
- ✅ WASM実行は確実に高速13.5倍実証済み)
- 🔄 Cranelift → LLVM段階的アプローチ
### codex先生の助言
- ✅ MIR前倒し実装推奨全バックエンドが恩恵
- ✅ wasmtime互換性管理が重要
- ✅ CPU差異対応 (baseline/v3二段ビルド)
- ✅ 起動時間・割当削減・配布体験がKPI
### Claude統合分析
- ✅ 実用価値最大化: WASM+AOTで十分な競争力
- ✅ 開発効率: Cranelift JITの恩恵限定的
- ✅ Everything is Box最適化が差別化の核心
- ✅ 時間効率: 2-3ヶ月節約でLLVM集中投資
---
## 💡 協調開発への具体的お願い
### 🔧 Phase 8.6 VM性能改善最優先
- ❓ 命令ディスパッチのボトルネック特定方法は?
- ❓ HashMap操作の最適化戦略は
- ❓ デバッグ出力削除による性能改善測定は?
- ❓ Direct threading実装の現実的アプローチは
### 🚀 長期戦略相談
- ❓ インタープリターとコンパイラの互換性保証は?
- ❓ MIR→LLVM IR変換の基本的な実装戦略は
- ❓ Box型のLLVM表現として最適なアプローチは
- ❓ エスケープ解析によるスタック化判定は?
---
## 📊 進捗管理・コミュニケーション
### 🤝 協調開発ルール
- ✅ 大きな変更前にはdocs/CURRENT_TASK.mdで情報共有
- ✅ ベンチマーク機能は最優先で維持
- ✅ 競合発生時は機能優先度で解決
### 品質保証
- ✅ cargo check でビルドエラーなし
- ✅ 既存ベンチマークが regression なし
- ✅ 新機能のドキュメント整備
- ✅ テストケース追加・CI通過
---
## 🎯 期待される成果
### 達成済み
- 🏆 RefNew/RefGet/RefSet WASM完全動作
- 🏆 26命令MIR階層化完了Phase 8.5
- 🏆 Phase 9.75g-0 BID-FFI Plugin System完全完了
- 🏆 警告削減100%達成Phase 9.75j
### 進行中・予定
- 🔄 VM性能改善進行中Phase 8.6- GitHub Issue #112
- 📅 Cranelift JITPhase 10: VM比2×以上の高速化
- 📅 非同期ネイティブ実装: async/await完全対応
- 📅 インタープリター併用: 開発・本番両対応
---
## 📞 連絡・相談方法
技術的相談や進捗報告は、以下の方法でお気軽にどうぞ:
1. 📝 GitHub Issues・Pull Request
2. 📋 docs/CURRENT_TASK.md コメント
3. 🤖 AI大会議 (重要な技術決定)
4. 💬 コミットメッセージでの進捗共有
どんな小さなことでも相談大歓迎です!
一緒にNyashを最高の言語にしていきましょう🚀
---
**最終更新**: 2025-08-26 (copilot_issues.txt統合・Markdown化)
**作成者**: Claude (ファイル統合・構造整理)
### 🎯 重要な変更点
-**Phase 9.75g-0 BID-FFI Plugin System完全完了**
- 🔄 **Phase 8.6 VM性能改善を最優先** (進行中)
- 📦 **Phase 9.8 BIDレジストリ** (Phase 8.6完了後の次期重点)
- 🔍 **Phase 10 Cranelift JIT** (主経路として確定)
- 🌟 **統一ロードマップ化** (phasesフォルダに集約)

View File

@ -1,6 +1,6 @@
# Phase 9.79a: Unified Box Dispatch (Minimal) + P2PBox Polish # Phase 9.79a: Unified Box Dispatch (Minimal) + P2PBox Polish
Status: Planned Status: Completed
Last Updated: 2025-08-26 Last Updated: 2025-08-26
Owner: core-runtime Owner: core-runtime
@ -37,6 +37,7 @@ Owner: core-runtime
- VM: universal methods 前置ディスパッチ - VM: universal methods 前置ディスパッチ
- Interpreter: 同様の前置ディスパッチ - Interpreter: 同様の前置ディスパッチ
- スモーク:既存演算子/print動作の回帰なし - スモーク:既存演算子/print動作の回帰なし
- 進捗: 2025-08-26 達成VM/Interpreterともに toString/type/equals/clone を前段で統一。cargo build 成功)
- M2Day 34 - M2Day 34
- P2PBox unregister安全化endpoint一致 or refcount - P2PBox unregister安全化endpoint一致 or refcount
- E2E: onOnce/off 追加、two-node ping-pong 安定、asyncデモが確実に出力 - E2E: onOnce/off 追加、two-node ping-pong 安定、asyncデモが確実に出力
@ -44,6 +45,26 @@ Owner: core-runtime
- VM表示整合P2PヘルパのtoString/ConsoleをInterpreterと一致 - VM表示整合P2PヘルパのtoString/ConsoleをInterpreterと一致
- Docs更新言語ガイド/P2Pリファレンス反映 - Docs更新言語ガイド/P2Pリファレンス反映
## Completion Notes (2025-08-26)
- Universal dispatch (toString/type/equals/clone): Interpreter/VMに前段実装・整合確認済み。
- P2PBox Polish:
- InProcess unregister: endpoint一致時のみunregisterで安全化。
- E2E: onOnce/off ユニットテスト追加、two-node ping→pong スモーク、self→selfスモーク追加。
- 受信トレース: getLastFrom/getLastIntentName を受信時に更新。
- 実用ミニ糖衣: IntentBoxの第2引数に MapBox/JSONBox を直接渡せるよう拡張。
- Docs: 新規リファレンス追加P2P/ 例追加
- docs/reference/boxes-system/p2p_box.md
- examples/p2p_self_ping.nyash
- examples/p2p_ping_pong.nyash
Notes:
- 非WASM環境のTimerBoxはダミーのため、async出力の確実化はWASM側のガイドで扱う。ネイティブでは同期スモークself→self/二者)で安定確認。
## Next (roll-forward)
- Language sugar: Object literal → MapBox loweringfeature flag `object_literal`で段階導入)
- Proposal: docs/ideas/improvements/2025-08-26-object-literal-sugar.md
- WASMガイドにTimer併用のasyncサンプル追記。
## リスクと対策 ## リスクと対策
- VM分岐に触るリスク → 型別分岐の“前段”に追加、既存分岐はフォールバックとして維持 - VM分岐に触るリスク → 型別分岐の“前段”に追加、既存分岐はフォールバックとして維持
- unregister回りの退行 → 一致解除テスト/順次Dropテストclone/share/Drop順の組み合わせを追加 - unregister回りの退行 → 一致解除テスト/順次Dropテストclone/share/Drop順の組み合わせを追加

View File

@ -0,0 +1,49 @@
# Phase 9.79b.1: Unified Registry IDs + Builder Slotting
Status: Planned
Owner: core-runtime
Target: Before Phase 10 (Cranelift JIT)
Last Updated: 2025-08-26
## Goals
- Introduce `BoxTypeId`/`MethodId` and stable method slot reservation in the unified registry.
- Resolve method names to slot IDs at MIR builder time when possible.
- Keep MIR instruction set stable (26) while enabling ID-based BoxCall.
## Scope
- Registry
- Add numeric `BoxTypeId` mapping (type-name → id) and `(type_id, method)``slot` table.
- Reserve low slots for universal methods: `0=toString`, `1=type`, `2=equals`, `3=clone`.
- Provide `reserve_method_slot()`, `resolve_slot()` APIs.
- MIR Builder
- When receiver type can be inferred, emit `BoxCall { method_id }` (slot ID) instead of name.
- Add late-bind fallback path for unresolved sites (keeps current behavior).
- Debug scaffolding
- Add `MIRDebugInfo` container types (empty by default) for ID→name mapping (off by default).
- Docs
- Update MIR design note to mention ID-based BoxCall with late-bind fallback.
## Deliverables
- New IDs and slot APIs in registry
- Builder emits `method_id` when resolvable
- Unit tests for slot reservation and universal slot invariants
## Non-Goals
- VM vtable/thunk dispatch (handled in 9.79b.2)
- PIC/JIT codegen
## Risks & Mitigations
- Slot consistency with inheritance: document rule “override keeps parent slot”; add test.
- Partial resolvability: ensure late-bind remains correct and does not regress semantics.
## Timeline
- 12 days
## Acceptance Criteria
- Tests pass; builder prints BoxCall with numeric `method_id` for resolvable sites.
- Universal methods occupy reserved slots across all types.
- No change to MIR opcode count (26) and existing dumps remain valid except for `method_id` where applicable.
## Roll-forward
- Proceed to 9.79b.2 (VM vtable/thunk + mono-PIC).

View File

@ -0,0 +1,51 @@
# Phase 9.79b.2: VM VTable Thunks + Mono-PIC
Status: Planned
Owner: core-runtime
Target: Before Phase 10 (Cranelift JIT)
Last Updated: 2025-08-26
## Goals
- Implement unified VM BoxCall path via vtable thunks indexed by `MethodId`.
- Add monomorphic inline cache (PIC) at call sites; prepare for polymorphic expansion.
- Keep behavior identical; improve structure and enable JIT lowering.
## Scope
- VM Dispatch
- Add `TypeMeta` with `vtable_base`, `version`.
- `execute_boxcall(receiver, method_id, args)`: lookup thunk = `vtable[slot]` and call target.
- PIC (Monomorphic)
- Per call-site cache: `(type_id, version) → target` fast path with fallback.
- Counters for hit/miss (debug only) to validate performance wins.
- Plugin safety (stub)
- Provide thunk replacement and type `version++` API (actual unload handled later with plugin mgr).
- Tests
- BoxCall correctness across builtin/user/plugin (plugin mocked if needed).
- PIC hit on repeated calls; miss on version change.
- Docs
- Update VM README with unified path and PIC diagram.
## Deliverables
- Unified VM BoxCall path (vtable + thunk)
- Monomorphic PIC
- Test coverage for core scenarios
## Non-Goals
- Polymorphic PIC (plan only)
- JIT emission (Phase 10)
## Risks & Mitigations
- Thunk ABI uniformity: define single target signature usable by builtin/VM/plugin shims.
- Cache invalidation: bump `version` on thunk replacement; verify miss logic.
## Timeline
- 23 days
## Acceptance Criteria
- All existing tests pass; new VM dispatch tests pass.
- Measurable hit rate on hot call-sites in debug stats.
- No observable behavior change from user code perspective.
## Roll-forward
- Phase 10: Cranelift JIT lowers BoxCall to the same thunks; add poly-PIC and codegen stubs.

View File

@ -0,0 +1,80 @@
# Object Literal Sugar for Nyash (Draft)
Status: Proposal (target: Phase 9.79b or 9.80)
Author: core-runtime
Last Updated: 2025-08-26
## Goals
- Provide ergonomic inline construction of structured data for messaging and config.
- Keep parser stable and avoid ambiguity with blocks and control structures.
- Lower to existing Box types (MapBox/JSONBox) without breaking NyashBox trait.
## Syntax Candidates
- A) JSON-like literals
- Example: `{ a: 1, b: "x", ok: true }`
- Variant: Allow string keys without quotes; values are Nyash expressions.
- B) Explicit constructors with sugar keyword
- Example: `map { a: 1, b: "x" }` → lowers to `new MapBox()` + sets
- C) JSON string auto-parse contextually
- Example: `"{\"a\":1}"` auto-parsed where JSON is expected (too implicit → avoid as default)
Recommendation: Start with A) JSON-like object literal lowering to MapBox.
## Grammar Design (A)
- Token additions: `{`, `}`, `:`, `,` are already present.
- Production:
- PrimaryExpr := ObjectLiteral | existing-primary
- ObjectLiteral := `{` ObjMembers? `}`
- ObjMembers := ObjPair (`,` ObjPair)* (`,`)?
- ObjPair := Identifier `:` Expr
- Key constraints: Identifier (no quotes) initially; string-literal keys as follow-up.
- Values: Any expression; evaluation order left-to-right.
## Lowering Strategy
- `{ k1: v1, k2: v2 }`
- `tmp = new MapBox(); tmp.set("k1", (v1)); tmp.set("k2", (v2)); tmp`
- In AST builder: desugar ObjectLiteral into a sequence and final tmp reference.
- Side-effects: preserve evaluation order; each `vi` evaluated once.
## Ambiguity & Conflict Checks
- With blocks: Nyash does not use `{}` for statement blocks (loop uses `loop(cond) { }` but parser differentiates by context). Ensure lookahead disambiguates after `=` or in expression position.
- With `from`: no conflict.
- With `while/if` (obsolete): not applicable.
## Types & Interop
- MapBox chosen for mutability and existing rich API.
- Allow JSONBox interop later via `json{ ... }` form or helper.
- IntentBox constructor already accepts MapBox/JSONBox (implemented 2025-08-26).
## Examples
- `msg = new IntentBox("chat", { text: "hi", user: me.name })`
- `cfg = { retries: 3, verbose: true }`
- `headers = { Accept: "application/json", Host: host }`
## Validation & Tests
- Parser tests: empty `{}`, single/multi pairs, trailing comma, nested values, errors.
- Runtime tests: MapBox size/keys/values; evaluation order with side effects.
- Negative tests: `{ :1 }`, `{a 1}`, `{a:}`, `{a: 1, , b:2}`.
## Phased Rollout
- Phase 1 (behind feature flag `object_literal`): parser + lowering to MapBox; docs + examples.
- Phase 2: string-literal keys; nested object/array literals sugar (`[ ... ]`?) once array-literal is designed.
- Phase 3: JSONBox literal form `json{ ... }` (optional).
## Migration & Back-compat
- No breaking changes; literals are additive syntax.
- Existing code using JSON strings/MapBox continues to work.
## Open Questions
- Should we permit numeric/bool literals as keys? → No (keys stringify already).
- Trailing comma allowed? → Yes (developer-friendly).
- Pretty-printer/formatter impact? → Add simple rule to keep one-line small maps.
## Out of Scope (for this proposal)
- Array literal `[ ... ]` (future parallel RFC)
- Spread syntax, computed keys, deep merge helpers
## Appendix
- Related work: JS object literals, Rust maplit!, Lua tables, TOML inline tables.
- Risks: Parser precedence bugs → mitigate with unit tests + feature flag.

View File

@ -1,539 +1,427 @@
# Nyash統一Box設計の深い分析と今後の方向性 # Nyash統一Box設計の深い分析と実装戦略
Status: Research Status: Active Design
Created: 2025-08-25 Created: 2025-08-25
Priority: High Updated: 2025-08-26 (Codex深掘り版)
Priority: Critical
Related: Everything is Box哲学の実装レベルでの完全実現 Related: Everything is Box哲学の実装レベルでの完全実現
## 現状の統一Box設計 ## 📌 最新の合意事項2025-08-26
### 3種類のBoxの存在 ### 2つのAI専門家からの統一見解
1. **ビルトインBox** - Rustで実装StringBox, IntegerBox, ConsoleBox等 - **Codex (GPT-5)**: ハイブリッドアプローチ推奨、Method ID = Stable Slot Index
2. **プラグインBox** - 動的ライブラリで提供FileBox等の置き換え可能 - **Claude**: MIRレベル完全統一の重要性を強調
3. **ユーザー定義Box** - Nyashコードで定義box Person等 - **共通結論**: コアBox静的リンクMIR統一Thunk indirection = 最適解
### 現在の統一アーキテクチャ ### 核心的設計決定
``` 1. **ハイブリッドアプローチ** - コアは静的、拡張はプラグイン
UnifiedBoxRegistry統一レジストリ 2. **MIRレベル完全統一** - 3種類のBoxを数値IDで区別なく扱う
├── BuiltinBoxFactory優先度1 3. **Stable Slot Index** - メソッドIDは型ごとのvtableスロット番号
├── UserDefinedBoxFactory優先度2 4. **Thunk-based Safety** - プラグインアンロード時の安全性保証
└── PluginBoxFactory優先度3
```
### 統一の美しさ ## 🎯 統一Box設計の全体像
1. **透過的な置き換え** ### 1. Box分類の最終決定
- 同じ名前のBoxをプラグインで上書き可能
- 実行時の動的切り替えも可能
2. **統一インターフェース**
```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>;
fn supports_birth(&self) -> bool;
}
```
3. **優先順位システム**
- ビルトイン > ユーザー定義 > プラグイン
- 予約語保護StringBox等は上書き不可
## InstanceBoxによる完全統一
### 統一実装の核心
```rust
pub struct InstanceBox {
pub class_name: String, // "StringBox", "Person"等
pub inner_content: Option<Box<dyn NyashBox>>, // 内包Box統一
pub fields_ng: Arc<Mutex<HashMap<String, NyashValue>>>,
pub methods: Arc<HashMap<String, ASTNode>>,
}
```
### 3つの形態を統一的に扱う
```rust
// ビルトイン
InstanceBox::from_any_box("StringBox", Box::new(StringBox::new("hello")))
// プラグイン
InstanceBox::from_any_box("FileBox", plugin_loader.create_box("FileBox"))
// ユーザー定義
InstanceBox::from_declaration("Person", vec!["name", "age"], methods)
```
## 基本メソッドの統一提案
### 問題点
- `toString()` → `to_string_box()` Rustの命名規則で異なる
- `type()` → `type_name()` (微妙に異なる)
- 各Boxで個別実装されていて統一感がない
### 解決案NyashBoxトレイトにデフォルト実装
```rust
pub trait NyashBox: BoxCore + Debug {
// Nyash標準メソッドデフォルト実装
fn toString(&self) -> Box<dyn NyashBox> {
Box::new(StringBox::new(&self.to_string_box().value))
}
fn type(&self) -> Box<dyn NyashBox> {
Box::new(StringBox::new(self.type_name()))
}
fn equals(&self, other: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
Box::new(BoolBox::new(self.equals_internal(other.as_ref())))
}
fn clone(&self) -> Box<dyn NyashBox> {
self.clone_box()
}
}
```
### VMでの統一的な呼び出し
```rust
pub(super) fn call_box_method(&self, box_value: Box<dyn NyashBox>, method: &str, args: Vec<Box<dyn NyashBox>>) -> Result<Box<dyn NyashBox>, VMError> {
// 基本メソッドは全Boxで使える
match method {
"toString" => Ok(box_value.toString()),
"type" => Ok(box_value.type()),
"equals" => Ok(box_value.equals(args[0].clone_or_share())),
"clone" => Ok(box_value.clone()),
_ => self.call_specific_method(box_value, method, args)
}
}
```
## Gemini先生からの提案部分
### 1. NyashValue Enumの導入
```rust
pub enum NyashValue {
// 即値(スタック上)
Void,
Bool(bool),
Integer(i64),
Float(f64),
// ヒープ上の不変値
String(Arc<String>),
// 複雑なオブジェクト
Object(Arc<NyashObject>),
}
```
**メリット**:
- 小さな値のヒープアロケーション回避
- パターンマッチによる高速ディスパッチ
- 型安全性の向上
### 2. トレイトの階層化
```rust
// 基本トレイト
pub trait NyashBox: Send + Sync + Debug {
fn to_string(&self) -> String;
fn type_name(&self) -> &'static str;
fn equals(&self, other: &dyn NyashBox) -> bool;
}
// 拡張トレイト
pub trait Comparable: NyashBox {
fn compare(&self, other: &dyn NyashBox) -> Option<Ordering>;
}
pub trait Arithmetic: NyashBox {
fn add(&self, other: &dyn NyashBox) -> Result<Box<dyn NyashBox>, String>;
}
```
### 3. メタプログラミング機能
```rust
pub trait BoxMetadata {
fn on_method_missing(&self, name: &str, args: &[NyashValue]) -> Option<NyashValue>;
fn on_field_access(&self, name: &str) -> Option<NyashValue>;
}
```
## 統一継承の実現
### ~~現在の課題~~ → 2025-08-25更新すべて実装済み
- ~~ビルトインBoxの継承ができない~~ → ✅ 実装済み!
- ~~プラグインBoxの継承も未実装~~ → ✅ 実装済み!
### 理想的な統一継承(すでに実現!)
```nyash
// すべて可能になった!
box MyString from StringBox { } // ビルトイン継承 ✅
box MyFile from FileBox { } // プラグイン継承 ✅
box Employee from Person { } // ユーザー定義継承 ✅
// 多重デリゲーションも可能!
box MultiChild from StringBox, IntegerBox { } // ✅
```
### 実際のコード例(動作確認済み)
```nyash
box EnhancedString from StringBox {
init { prefix, suffix }
birth(text) {
from StringBox.birth(text) // 透過的にpackに変換される
me.prefix = "【"
me.suffix = "】"
}
enhanced() {
return me.prefix + me.toString() + me.suffix + "✨"
}
}
```
## さらなる美化への道
### 1. パイプライン演算子
```nyash
// 現在
local result = str.substring(0, 5).toUpperCase().trim()
// パイプライン版
local result = str
|> substring(0, 5)
|> toUpperCase()
|> trim()
```
### 2. Box階層の整理
```
NyashBox (trait)
├── ValueBox (数値・文字列・真偽値)
│ ├── IntegerBox
│ ├── StringBox
│ └── BoolBox
├── ContainerBox (コレクション)
│ ├── ArrayBox
│ └── MapBox
├── IOBox (入出力)
│ ├── ConsoleBox
│ └── FileBox
└── ConcurrentBox (並行処理)
├── FutureBox
└── ChannelBox
```
### 3. エフェクトシステムの美化
```rust
impl ArrayBox {
#[effect(Pure)]
fn length(&self) -> IntegerBox { }
#[effect(State)]
fn push(&mut self, item: Box<dyn NyashBox>) { }
}
```
## 実装優先順位80/20ルール
### 今すぐやるべき80%
1. 基本メソッドtoString, type, equals, cloneの統一実装
2. VMでの統一的なメソッドディスパッチ
3. InstanceBoxのinner_content活用の徹底
### 後でじっくり20%
1. NyashValue enum導入によるパフォーマンス最適化
2. トレイト階層化による整理
3. パイプライン演算子の実装
4. メタプログラミング機能
5. 完全な統一継承システム
## まとめ
現在のNyashの統一Box設計は、すでに相当美しく実装されている。特に
1. **UnifiedBoxRegistry**による透過的な管理
2. **優先順位システム**による明確な解決
3. **InstanceBox**による統一的な扱い
これらは「Everything is Box」哲学を実装レベルで体現している。
ユーザー定義Boxをビルトイン/プラグインBoxと完全に同じレベルで扱うことは、強引ではなく、むしろ設計として自然で美しい。この統一により、言語の一貫性と拡張性が大幅に向上する。
今後は、基本メソッドの統一実装から始めて、段階的により洗練された設計へと進化させていくのが良いだろう。
## 🚀 MIR/VM統一実装計画2025-08-25追記
### 📍 現状の課題
VMとMIRで、Box型によって異なる処理をしている
```rust ```rust
// VMでの現状InstanceBoxだけ特別扱い // 絶対的コアBox静的リンク必須- 10個
if let Some(inst) = arc_box.as_any().downcast_ref::<InstanceBox>() {
// ユーザー定義Box → 関数呼び出しに変換
let func_name = format!("{}.{}/{}", inst.class_name, method, args.len());
} else {
// ビルトイン/プラグイン → 直接メソッド呼び出し
self.call_box_method(cloned_box, method, nyash_args)?
}
```
### 🎯 統一実装の提案
#### 1. 統一メソッドディスパッチインターフェース
```rust
pub trait UnifiedBox: NyashBox {
fn dispatch_method(&self, method: &str, args: Vec<Box<dyn NyashBox>>)
-> Result<Box<dyn NyashBox>, String> {
// デフォルト実装:既存のメソッド呼び出しを使用
self.call_method(method, args)
}
}
// InstanceBoxでのオーバーライド
impl UnifiedBox for InstanceBox {
fn dispatch_method(&self, method: &str, args: Vec<Box<dyn NyashBox>>)
-> Result<Box<dyn NyashBox>, String> {
// MIR関数へのリダイレクト
let func_name = format!("{}.{}/{}", self.class_name, method, args.len());
// VM経由で関数呼び出し
}
}
```
#### 2. VMの簡素化
```rust
// 統一後:すべて同じ処理パス
let result = match &recv {
VMValue::BoxRef(arc_box) => {
arc_box.dispatch_method(method, nyash_args)?
}
_ => {
recv.to_nyash_box().dispatch_method(method, nyash_args)?
}
};
```
#### 3. MIRレベルでの統一
- `BoxCall`命令ですべてのBox型を統一的に処理
- 型による分岐や特殊処理を削除
- コンパイル時の最適化は維持
### 💎 期待される効果
1. **コードの簡素化**
- VM内の条件分岐削除で30%以上のコード削減
- 新Box型追加時の変更箇所が最小限に
2. **保守性の向上**
- Box型の実装詳細がVMから隠蔽される
- テストが書きやすくなる
3. **パフォーマンス**
- 統一的な最適化(メソッドキャッシュ等)が可能
- 仮想関数テーブルによる高速化の可能性
4. **美しさ**
- 「Everything is Box」が実装レベルでも完全に実現
- シンプルで理解しやすいコード
### 📅 実装ロードマップ
1. **Phase 1**: UnifiedBoxトレイトの導入後方互換性を保ちながら
2. **Phase 2**: VMでの統一ディスパッチ実装
3. **Phase 3**: MIRビルダーの簡素化
4. **Phase 4**: 旧実装の削除とクリーンアップ
### 🌟 最終的なビジョン
すべてのBoxビルトイン、プラグイン、ユーザー定義が完全に統一された世界
- 同じインターフェース
- 同じ実行パス
- 同じ最適化機会
これこそが「Everything is Box」の究極の実現
## 🔌 プラグインローダーv2との統合
### 現在のプラグインシステムとの関係
- プラグインローダーv2がすでに統一的なインターフェースを提供
- `extern_call`経由での統一的なアクセス
- UnifiedBoxトレイトとの相性は良好
### 統合のメリット
- プラグインBoxも`dispatch_method()`で統一処理
- ホットリロード時も透過的に動作
- FFI境界を意識しない実装
## 📊 パフォーマンス測定計画
### 現在のベースライン
- インタープリター基準で13.5倍高速化達成VM実装
- BoxCall命令の実行時間が全体の約30%
### 統一実装後の予測
- 条件分岐削減で5-10%の高速化期待
- メソッドキャッシュで追加20%改善の可能性
- 測定方法:`--benchmark --iterations 1000`で検証
## 🔄 移行時の互換性戦略
### 段階的移行計画
1. **Phase 1**: UnifiedBoxトレイトを追加既存APIは維持
2. **Phase 2**: 警告付きで旧API使用を通知
3. **Phase 3**: 内部実装を統一版に切り替え
4. **Phase 4**: 旧APIをdeprecated化
5. **Phase 5**: 完全削除6ヶ月後
### テスト戦略
- 既存の全E2Eテストが通ることを保証
- パフォーマンスリグレッションテスト追加
- プラグイン互換性テストスイート
## ⚡ JITコンパイラとの統合Phase 9準備
### 統一メソッドディスパッチの利点
- JITが最適化しやすい単純な呼び出しパターン
- インライン展開の機会増加
- 型情報を活用した特殊化
### 仮想関数テーブルvtable戦略
```rust
struct BoxVTable {
methods: HashMap<String, fn(&dyn NyashBox, Vec<Box<dyn NyashBox>>) -> Result<Box<dyn NyashBox>, String>>,
}
```
- 起動時に事前計算
- JITコンパイル時に直接参照
- キャッシュフレンドリーな配置
## 🔧 具体的な実装タスクTODO
### Phase 1: 基礎実装1週間
- [ ] UnifiedBoxトレイトの定義src/box_trait.rs
- [ ] StringBox, IntegerBox等への実装
- [ ] InstanceBoxへのdispatch_method実装
- [ ] 単体テストの作成
### Phase 2: VM統合2週間
- [ ] execute_boxcall()の簡素化
- [ ] InstanceBox特別扱いコードの削除
- [ ] VMValueとの統合
- [ ] E2Eテスト全パス確認
- [ ] ベンチマーク実行と比較
### Phase 3: 最適化1週間
- [ ] メソッドキャッシュ実装
- [ ] 頻出メソッドの特殊化
- [ ] vtable事前計算
- [ ] JIT統合準備
### Phase 4: クリーンアップ3日
- [ ] 旧実装コードの削除
- [ ] ドキュメント更新
- [ ] CHANGELOG記載
- [ ] マイグレーションガイド作成
### 検証項目
- [ ] 全Box型でtoString/type/equals/cloneが動作
- [ ] プラグインBoxの透過的な動作
- [ ] パフォーマンス改善の確認
- [ ] メモリ使用量の変化なし
## 🚀 究極の統一ビルトインBox完全プラグイン化構想
### 現状の二重実装問題
- **plugin_loader.rs** (1217行) - ビルトインBoxの動的ライブラリ化
- **plugin_loader_v2.rs** (906行) - プラグインBoxシステム
- 合計2000行以上の重複
### 完全プラグイン化の提案
#### すべてをプラグインに統一
```rust
// 現在
ビルトインFileBox → 静的リンク
プラグインFileBox → 動的ロード(.so
// 統一後
すべてのBox → プラグイン(.soとして実装
```
#### コアBoxの自動ロード戦略
```rust
const CORE_BOXES: &[&str] = &[ const CORE_BOXES: &[&str] = &[
"libnyash_string_box.so", // StringBox必須 "NilBox", "BoolBox", "IntegerBox", "FloatBox",
"libnyash_integer_box.so", // IntegerBox必須 "StringBox", "ArrayBox", "MapBox",
"libnyash_bool_box.so", // BoolBox必須 "ConsoleBox", "ResultBox", "MethodBox"
"libnyash_console_box.so", // ConsoleBoxprint用
]; ];
// 起動時に自動ロード // 準コアBox静的だが置換可能- 4個
fn init_core_boxes() { const SEMI_CORE_BOXES: &[&str] = &[
for plugin in CORE_BOXES { "MathBox", "DebugBox", "TimeBox", "RandomBox"
plugin_loader.load_required(plugin) ];
.expect("Core box loading failed");
// プラグイン推奨Box - 残り全て
const PLUGIN_BOXES: &[&str] = &[
"FileBox", "NetworkBox", "AudioBox",
"P2PBox", "EguiBox", "WebDisplayBox", // ...
];
```
### 2. 革新的な統一レジストリ設計Codex提案
```rust
pub struct UnifiedBoxRegistry {
// 型名 → 型ID安定
type_registry: HashMap<String, BoxTypeId>,
// 型メタデータvtableベースアドレス含む
type_meta: Vec<TypeMeta>,
// (型ID, メソッド名) → スロット番号(永続的)
slot_index: HashMap<(BoxTypeId, String), SlotIdx>,
// Thunkプール固定アドレス、原子的更新可能
thunks: Vec<MethodThunk>,
// グローバルエポック(大規模無効化用)
epoch: AtomicU64,
}
// 型ごとのメタデータ
struct TypeMeta {
version: AtomicU32, // 動的更新のバージョン
vtable_base: *const *const MethodThunk, // vtableベースポインタ
slot_count: u32, // 割り当て済みスロット数
}
// メソッドThunk間接層
struct MethodThunk {
target: AtomicPtr<c_void>, // 実装への原子的ポインタ
sig: Signature, // メソッドシグネチャ
flags: MethodFlags, // 純粋性、インライン可能性等
}
```
## 🚀 MIRレベルでの完全統一実装
### 1. 統一MIR命令最終形
```rust
pub enum MirInstruction {
// Box生成すべて同じ
BoxNew {
dst: ValueId,
type_id: BoxTypeId, // 数値IDビルトイン=1、ユーザー=1000でも同じ
args: Vec<ValueId>,
},
// メソッド呼び出し(すべて同じ)
BoxCall {
dst: Option<ValueId>,
receiver: ValueId,
method_id: MethodId, // 安定したスロット番号
args: Vec<ValueId>,
effects: EffectFlags, // 純粋性、副作用情報
},
}
```
### 2. メソッドID解決戦略Codex推奨
```rust
impl MirBuilder {
fn compile_method_call(&mut self, receiver: ValueId, method: &str, args: Vec<ValueId>) {
let receiver_type = self.infer_type(receiver);
// 静的に解決可能な場合
if let Some(slot) = self.registry.resolve_slot(receiver_type, method) {
self.emit(MirInstruction::BoxCall {
dst: Some(self.new_value()),
receiver,
method_id: slot,
args,
effects: self.registry.get_method_flags(receiver_type, slot),
});
} else {
// 動的解決が必要eval、動的ロード
self.emit_late_bind_call(receiver, method, args);
}
} }
} }
``` ```
### メリット ### 3. VM実装の劇的簡素化
1. **コード削減**: plugin_loader.rs (1217行) を完全削除
2. **統一性**: Everything is Boxの究極の実現
3. **柔軟性**: StringBoxすら置き換え可能
4. **ビルド高速化**: 本体が軽量に
5. **配布の柔軟性**: 必要なBoxだけ選択可能
### 考慮事項
#### パフォーマンス
- FFI境界のオーバーヘッドは**ナノ秒レベル**
- 実用上の影響なし
#### デバッグの課題と対策
```rust ```rust
// 課題:エラー時のスタックトレース // 現在Box種類で複雑な分岐
thread 'main' panicked at 'FFI boundary: 0x7f8b2c001234' match determine_box_kind(&receiver) {
BoxKind::Instance => {
// 対策1プラグイン側でのロギング // ユーザー定義Boxの特殊処理
#[no_mangle] let func_name = format!("{}.{}", class_name, method);
pub extern "C" fn box_method_toString() { self.call_mir_function(func_name, args)?
eprintln!("[StringBox::toString] called from {:?}", std::thread::current().id()); },
BoxKind::Plugin => {
// プラグインのFFI呼び出し
unsafe { plugin_invoke(receiver, method, args) }
},
BoxKind::Builtin => {
// ビルトインメソッド直接呼び出し
builtin_dispatch(receiver, method, args)
}
} }
// 対策2デバッグシンボル保持 // 統一後:完全に均一なディスパッチ!
cargo build --features debug-symbols fn execute_boxcall(&mut self, receiver: ValueId, method_id: MethodId, args: Vec<ValueId>) {
// 1. 受信者の型を取得
// 対策3プラグイン単体テストの充実 let type_meta = self.get_type_meta(receiver);
#[test]
fn test_string_box_methods() { /* ... */ } // 2. vtableからThunkを取得
let thunk = unsafe { *type_meta.vtable_base.add(method_id as usize) };
// 3. Thunkのターゲットを原子的に読み取り
let target = thunk.target.load(Ordering::Acquire);
// 4. 統一的な呼び出し
let result = (target)(receiver, args);
self.push(result);
}
``` ```
### 実装ロードマップ ## ⚡ 高性能化の核心技術
1. **Phase A**: コアBoxのプラグイン化
- StringBox, IntegerBox, BoolBox, ConsoleBox
2. **Phase B**: 起動時自動ロード機構
3. **Phase C**: plugin_loader.rs削除
4. **Phase D**: ドキュメント・テスト整備
### 設定ファイル案 ### 1. Polymorphic Inline Cache (PIC) 実装
```toml
# ~/.nyash/config.toml
[plugins]
core_path = "./plugins/core/"
search_paths = ["./plugins", "/usr/lib/nyash/plugins"]
[core_boxes] ```rust
required = ["string", "integer", "bool", "console"] // コールサイトごとのインラインキャッシュ
optional = ["file", "math", "time"] struct InlineCache {
// モノモーフィックエントリ(最頻出)
mono_type: BoxTypeId,
mono_version: u32,
mono_target: *const fn,
// ポリモーフィックエントリ2-4個
poly_entries: [(BoxTypeId, u32, *const fn); 4],
poly_count: u8,
}
// JIT生成コード例疑似コード
fn generate_pic_stub(cache: &InlineCache) -> Code {
// 1. 受信者の型IDを取得
// 2. モノモーフィックチェック
if receiver.type_id == cache.mono_type &&
receiver.version == cache.mono_version {
jump cache.mono_target // 直接ジャンプ!
}
// 3. ポリモーフィックチェック
for entry in cache.poly_entries[..cache.poly_count] {
if receiver.type_id == entry.0 && receiver.version == entry.1 {
jump entry.2
}
}
// 4. スローパス
call slow_path_resolver
}
``` ```
これにより、「Everything is Box」哲学が実装レベルでも完全に実現される ### 2. メソッドスロットの永続性保証
## 🔍 統一デバッグインフラストラクチャ2025-08-26追記 ```rust
impl UnifiedBoxRegistry {
// スロット予約(一度割り当てたら永続)
pub fn reserve_method_slot(
&mut self,
type_id: BoxTypeId,
method: &str,
sig: &Signature
) -> SlotIdx {
let key = (type_id, method.to_string());
// 既存スロットがあれば返す
if let Some(&slot) = self.slot_index.get(&key) {
return slot;
}
// 新規スロット割り当て(削除後も再利用しない)
let type_meta = &mut self.type_meta[type_id as usize];
let slot = SlotIdx(type_meta.slot_count);
type_meta.slot_count += 1;
self.slot_index.insert(key, slot);
slot
}
}
```
### 3. 安全なプラグインアンロード
```rust
impl PluginManager {
fn unload_plugin(&mut self, plugin_id: PluginId) {
// 1. 影響を受ける型とメソッドを列挙
let affected = self.get_plugin_methods(plugin_id);
for (type_id, slot) in affected {
// 2. Thunkを原子的にスタブに差し替え
let thunk = &self.registry.get_thunk(type_id, slot);
let stub = get_unloaded_method_stub();
thunk.target.store(stub, Ordering::Release);
// 3. 型バージョンをインクリメント(キャッシュ無効化)
let type_meta = &self.registry.type_meta[type_id];
type_meta.version.fetch_add(1, Ordering::AcqRel);
}
// 4. RCU/Hazard Pointerで安全に回収
self.defer_plugin_cleanup(plugin_id);
}
}
// アンロード後のスタブ関数
fn unloaded_method_stub(_: ValueId, _: Vec<ValueId>) -> VMValue {
panic!("Method has been unloaded")
}
```
## 📊 パフォーマンス分析と予測
### 現状のベースライン
- インタープリター比: **13.5倍**高速
- BoxCall実行時間: 全体の**30%**
- 主なオーバーヘッド: 文字列比較、型判定、間接呼び出し
### 改善による期待効果
| 最適化技術 | 個別改善率 | 全体への影響 |
|-----------|----------|-----------|
| メソッドID化 | 50-70% | 15-21% |
| PICキャッシュ | 80-90% | 24-27% |
| インライン化 | 特定サイト10倍 | 10-25% |
| 純粋性解析 | CSE/LICM可能 | 5-15% |
### 20倍達成への道筋
```
現在: 13.5倍
目標: 20.0倍(+48%必要)
達成可能性:
- ID化+PIC: 1.15-1.20倍
- インライン化: 1.10-1.25倍
- 効果解析: 1.05-1.15倍
合計: 1.32-1.73倍 → 17.8-23.4倍(達成可能!)
```
## 🛠️ 実装ロードマップ(詳細版)
### Phase 1: 基盤構築1週間
```rust
// Week 1のタスク
- [ ] MethodThunk構造体とアロケーター実装
- [ ] TypeMetaとvtable管理実装
- [ ] スロット予約APIreserve_method_slot
- [ ] 基本的なレジストリ操作
```
### Phase 2: MIR統合1週間
```rust
// Week 2のタスク
- [ ] BoxNew/BoxCallの数値ID化
- [ ] メソッド名→スロット解決
- [ ] late-bind placeholderサポート
- [ ] デバッグ情報サイドテーブル
```
### Phase 3: VM最適化2週間
```rust
// Week 3-4のタスク
- [ ] 統一execute_boxcall実装
- [ ] モノモーフィックPIC実装
- [ ] ポリモーフィックPIC拡張
- [ ] ベンチマーク検証
```
### Phase 4: プラグイン対応1週間
```rust
// Week 5のタスク
- [ ] プラグインAPIのスロット対応
- [ ] 安全なアンロード実装
- [ ] バージョン管理とキャッシュ無効化
- [ ] 実プラグイン移行(FileBox
```
### Phase 5: JIT準備継続的
```rust
// 継続タスク
- [ ] 純粋性フラグの伝搬
- [ ] インライン可能IRの提供
- [ ] Craneliftメタデータ整備
- [ ] PIC codegenサポート
```
## 🔍 技術的詳細と実装のコツ
### デバッグ情報の管理
```rust
// MIRは数値のみ保持
struct MirDebugInfo {
// (type_id, slot) → 人間可読情報
method_names: HashMap<(BoxTypeId, SlotIdx), MethodDebug>,
// PC → ソース位置
source_map: HashMap<usize, SourceLocation>,
}
struct MethodDebug {
type_name: String,
method_name: String,
signature: String,
source_file: PathBuf,
line: u32,
}
```
### スレッドセーフティ
```rust
// Read-Copy-Update パターン
impl UnifiedBoxRegistry {
fn update_method(&self, type_id: BoxTypeId, slot: SlotIdx, new_impl: *const fn) {
// 1. 新バージョンを準備
let new_thunk = MethodThunk {
target: AtomicPtr::new(new_impl),
// ...
};
// 2. RCUで安全に更新
rcu::synchronize(|| {
self.thunks[slot].target.store(new_impl, Ordering::Release);
});
}
}
```
### メモリレイアウト最適化
```rust
// キャッシュフレンドリーな配置
#[repr(C, align(64))] // キャッシュライン境界
struct TypeVTable {
thunks: [MethodThunk; MAX_METHODS_PER_TYPE],
}
// ホットデータをまとめる
struct HotMethodData {
frequently_called: [MethodThunk; 8], // toString, equals等
cold_methods: *const ColdMethodTable,
}
```
## 💡 結論と次のステップ
### 統一設計の価値
1. **簡潔性**: VM/JIT実装が劇的にシンプルに
2. **性能**: 20倍高速化が現実的に達成可能
3. **安全性**: Thunk indirectionで動的更新も安全
4. **拡張性**: 新Box型追加が容易
### ChatGPT5への相談ポイント
1. **Thunk実装の具体的なアセンブリ**
2. **RCU/Hazard Pointerの実装詳細**
3. **PICのCranelift codegenパターン**
4. **型推論とスロット解決の統合**
5. **デバッガ統合のベストプラクティス**
### 実装の第一歩
```rust
// まずはこれを実装!
pub struct MethodThunk {
target: AtomicPtr<extern "C" fn(*const u8, *const *const u8) -> *const u8>,
#[cfg(debug_assertions)]
debug_name: &'static str,
}
// そしてスロット予約
registry.reserve_method_slot(STRING_BOX_ID, "toString", &sig);
```
「Everything is Box」の理想が、ついに実装レベルで完全に実現される時が来ました
## 🔍 統一デバッグインフラストラクチャ
### 📍 MIRレベルでの統一デバッグ実現 ### 📍 MIRレベルでの統一デバッグ実現
今までの議論で、MIRレベルでのデバッグ実装が最も理想的であることが判明しました。 MIRレベルでのデバッグ実装が最も理想的であることが判明しました。
Gemini先生とCodex先生の両方が同じ結論に達しました**設計案23のハイブリッド**が最適解です。 Gemini先生とCodex先生の両方が同じ結論に達しました**設計案23のハイブリッド**が最適解です。
#### 核心設計メタデータ分離プロファイリングAPI #### 核心設計メタデータ分離プロファイリングAPI
@ -737,7 +625,7 @@ impl DeepInspectorBox {
} }
``` ```
### 🚀 実装ロードマップ2025年後半 ### 🚀 統一デバッグ実装ロードマップ
#### Phase 1: MIRデバッグ基盤2週間 #### Phase 1: MIRデバッグ基盤2週間
- [ ] MIRDebugInfo構造の実装 - [ ] MIRDebugInfo構造の実装
@ -764,7 +652,7 @@ impl DeepInspectorBox {
- [ ] サンプリングモード - [ ] サンプリングモード
- [ ] 増分参照グラフ更新 - [ ] 増分参照グラフ更新
### 💎 統一の美しさ ### 💎 統一デバッグの美しさ
この設計により、以下が実現されます: この設計により、以下が実現されます:

View File

@ -0,0 +1,39 @@
# P2PBox - Modern P2P Node (InProcess)
Status: Experimental (Phase 9.79a)
## Overview
- Structured messaging with `IntentBox(name, payload)`
- Local in-process routing via `MessageBus`
- Deterministic smoke demo available without timers
## API
- `new P2PBox(nodeId: String, transport: String)`
- `send(to: String|Box, intent: IntentBox) -> ResultBox`
- `on(name: String, handler: MethodRef) -> ResultBox`
- `onOnce(name: String, handler: MethodRef) -> ResultBox`
- `off(name: String) -> ResultBox`
- `getNodeId() -> String`
- `isReachable(nodeId: String) -> Bool`
- `getTransportType() -> String`
- `debugNodes() -> String` (inprocess only)
- `debugBusId() -> String` (inprocess only)
- `getLastFrom() -> String` (loopback trace)
- `getLastIntentName() -> String` (loopback trace)
Notes:
- Handlers currently accept a method reference (`MethodBox`) rather than an inline function literal.
- For quick loopback smoke without handlers, send to self and read `getLast*()`.
## Quick Smoke (No Handlers)
```
alice = new P2PBox("alice", "inprocess")
msg = new IntentBox("ping", { })
res = alice.send("alice", msg)
print("last.from=" + alice.getLastFrom())
print("last.intent=" + alice.getLastIntentName())
```
## Two-Node Ping-Pong (Concept)
This is covered in unit tests; handler wiring uses `MethodBox` internally. A higher-level sugar for method references will arrive in later phases.

Binary file not shown.

View File

@ -0,0 +1,44 @@
// 📡 P2P Two-Node Ping-Pong (InProcess)
// Uses MethodBox handlers to wire reply path.
print("🚀 P2P Two-Node Ping-Pong Start")
// Nodes
alice = new P2PBox("alice", "inprocess")
bob = new P2PBox("bob", "inprocess")
// Service box to hold node reference and implement handlers
box PingService {
init { node, name }
onPing(intent, sender) {
print("[" + me.name + "] recv " + intent.getName() + " from " + sender)
// reply pong back
reply = new IntentBox("pong", "{}")
me.node.send(sender, reply)
}
onPong(intent, sender) {
print("[" + me.name + "] recv " + intent.getName() + " from " + sender)
}
}
// Wire handlers
svcBob = new PingService()
svcBob.node = bob
svcBob.name = "bob"
bob.on("ping", new MethodBox(svcBob, "onPing"))
svcAlice = new PingService()
svcAlice.node = alice
svcAlice.name = "alice"
alice.on("pong", new MethodBox(svcAlice, "onPong"))
// Kick ping
alice.send("bob", new IntentBox("ping", "{}"))
// Show traces for determinism
print("alice.last=" + alice.getLastIntentName())
print("bob.last=" + bob.getLastIntentName())
print("✅ P2P Two-Node Ping-Pong Done")

View File

@ -0,0 +1,26 @@
// 📡 P2P Self Ping Smoke
// Purpose: Minimal, deterministic P2PBox demo without external timing.
// Shows send(to=self) loopback traces and universal methods.
print("🚀 P2P Self Ping Smoke Start")
// Create node 'alice' on inprocess transport
alice = new P2PBox("alice", "inprocess")
// Show basic info
print("node=" + alice.getNodeId() + ", transport=" + alice.getTransportType())
// Create an IntentBox and send to self
msg = new IntentBox("ping", "{}")
res = alice.send("alice", msg)
print("send result=" + res.toString())
// Read back last received traces (populated for self-loop)
print("last.from=" + alice.getLastFrom())
print("last.intent=" + alice.getLastIntentName())
// Show debug helpers
print("nodes=" + alice.debugNodes())
print("bus=" + alice.debugBusId())
print("✅ P2P Self Ping Smoke Done")

View File

@ -1,48 +0,0 @@
HTTP E2Eテスト実行ログ (2025-08-21)
================================
【テスト実行コマンド】
NYASH_NET_LOG=1 cargo test --features plugins --test e2e_plugin_net -- --nocapture
【テスト結果サマリー】
- 全5テスト失敗
- エラー内容: Cannot call method 'respond' on non-instance type (VoidBox)
【詳細なエラー解析】
1. 根本原因: HttpRequestBox作成失敗
- HttpServerBox.start() → 成功instance_id作成確認
- server.accept() → VoidBoxを返す本来はHttpRequestBoxを返すべき
- VoidBox.respond() → エラーVoidBoxにはrespond()メソッドがない)
2. 主要なログ出力:
- 🎉 birth() success: HttpServerBox instance_id=5
- 🎉 birth() success: HttpClientBox instance_id=6
- ❌ Interpreter error: Type error: Cannot call method 'respond' on non-instance type
3. プラグインシステムの挙動:
- プラグインロード: 成功
- Box型の認識: 成功type_id=20 for HttpServerBox等
- メソッド呼び出し: 部分的成功start/stopは動作、acceptが問題
【失敗したテスト一覧】
1. e2e_http_stub_end_to_end
2. e2e_http_post_and_headers
3. e2e_http_multiple_requests_order
4. e2e_http_server_restart
5. e2e_http_server_shutdown_and_restart
【Socket E2Eテストとの比較】
- Socket E2Eテスト: 全て成功2/2 passed
- HTTP E2Eテスト: 全て失敗0/5 passed
- 結論: プラグインシステム自体は正常、HTTP実装固有の問題
【推測される問題】
1. HTTP accept()メソッドの実装が未完成PoC段階
2. 実際のHTTPリクエスト受信処理が未実装
3. HttpRequestBoxインスタンスの生成ロジックが欠落
【ChatGPT5さんへの報告事項】
- VoidBoxエラーはaccept()メソッドの戻り値が原因
- HTTPサーバーの実装は基本的なソケット処理が必要
- Socket実装は安定しているので参考にできる可能性あり

View File

@ -1,459 +0,0 @@
warning: unused macro definition: `debug_trace`
--> src/interpreter/core.rs:35:14
|
35 | macro_rules! debug_trace {
| ^^^^^^^^^^^
|
= note: `#[warn(unused_macros)]` on by default
warning: unexpected `cfg` condition value: `llvm`
--> src/backend/mod.rs:13:7
|
13 | #[cfg(feature = "llvm")]
| ^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: `all-examples`, `cli`, `default`, `dynamic-file`, `gui`, `gui-examples`, `plugins`, and `wasm-backend`
= help: consider adding `llvm` as a feature in `Cargo.toml`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
warning: unexpected `cfg` condition value: `llvm`
--> src/backend/mod.rs:23:7
|
23 | #[cfg(feature = "llvm")]
| ^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: `all-examples`, `cli`, `default`, `dynamic-file`, `gui`, `gui-examples`, `plugins`, and `wasm-backend`
= help: consider adding `llvm` as a feature in `Cargo.toml`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
warning: unreachable statement
--> src/interpreter/objects.rs:109:9
|
27 | / match nyash_args {
28 | | Ok(args) => {
29 | | // Handle generics: if user-defined and type arguments provided, specialize declaration
30 | | let mut target_class = class.to_string();
... |
106 | | }
| |_________- any code following this `match` expression is unreachable, as all arms diverge
...
109 | return Err(RuntimeError::UndefinedClass { name: class.to_string() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement
|
= note: `#[warn(unreachable_code)]` on by default
warning: unreachable pattern
--> src/interpreter/objects.rs:231:13
|
120 | / "StringBox" | "IntegerBox" | "BoolBox" | "ArrayBox" | "ResultBox" |
121 | | "ErrorBox" | "NullBox" | "FloatBox" | "MapBox" => {
| |__________________________________________________________- matches all the relevant values
...
231 | "NullBox" => {
| ^^^^^^^^^ no value can reach this
|
= note: `#[warn(unreachable_patterns)]` on by default
warning: unreachable pattern
--> src/interpreter/objects.rs:384:13
|
120 | / "StringBox" | "IntegerBox" | "BoolBox" | "ArrayBox" | "ResultBox" |
121 | | "ErrorBox" | "NullBox" | "FloatBox" | "MapBox" => {
| |__________________________________________________________- matches all the relevant values
...
384 | "FloatBox" => {
| ^^^^^^^^^^ no value can reach this
warning: unreachable pattern
--> src/interpreter/objects.rs:484:13
|
120 | / "StringBox" | "IntegerBox" | "BoolBox" | "ArrayBox" | "ResultBox" |
121 | | "ErrorBox" | "NullBox" | "FloatBox" | "MapBox" => {
| |__________________________________________________________- matches all the relevant values
...
484 | "MapBox" => {
| ^^^^^^^^ no value can reach this
warning: `nyash-rust` (lib) generated 7 warnings
warning: unexpected `cfg` condition value: `llvm`
--> src/runner.rs:28:7
|
28 | #[cfg(feature = "llvm")]
| ^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: `all-examples`, `cli`, `default`, `dynamic-file`, `gui`, `gui-examples`, `plugins`, and `wasm-backend`
= help: consider adding `llvm` as a feature in `Cargo.toml`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `llvm`
--> src/runner.rs:568:15
|
568 | #[cfg(feature = "llvm")]
| ^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: `all-examples`, `cli`, `default`, `dynamic-file`, `gui`, `gui-examples`, `plugins`, and `wasm-backend`
= help: consider adding `llvm` as a feature in `Cargo.toml`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `llvm`
--> src/runner.rs:591:19
|
591 | #[cfg(not(feature = "llvm"))]
| ^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: `all-examples`, `cli`, `default`, `dynamic-file`, `gui`, `gui-examples`, `plugins`, and `wasm-backend`
= help: consider adding `llvm` as a feature in `Cargo.toml`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
warning: `nyash-rust` (bin "nyash") generated 3 warnings (1 duplicate)
running 5 tests
🔍 create_box called for: HttpServerBox
🔍 Config loaded successfully
🔍 create_box called for: HttpServerBox
🔍 Config loaded successfully
🔍 create_box called for: HttpServerBox
🔍 Config loaded successfully
🔍 create_box called for: HttpServerBox
🔍 Config loaded successfully
🔍 create_box called for: HttpServerBox
🔍 Config loaded successfully
🔍 Found library: libnyash_net_plugin.so for box type: HttpServerBox
🔍 Plugin loaded successfully
🔍 Reading nyash.toml for type configuration...
🔍 Found library: libnyash_net_plugin.so for box type: HttpServerBox
🔍 Plugin loaded successfully
🔍 Reading nyash.toml for type configuration...
🔍 Found library: libnyash_net_plugin.so for box type: HttpServerBox
🔍 Plugin loaded successfully
🔍 Reading nyash.toml for type configuration...
🔍 Found library: libnyash_net_plugin.so for box type: HttpServerBox
🔍 Plugin loaded successfully
🔍 Reading nyash.toml for type configuration...
🔍 Found library: libnyash_net_plugin.so for box type: HttpServerBox
🔍 Plugin loaded successfully
🔍 Reading nyash.toml for type configuration...
🔍 nyash.toml read successfully
🔍 nyash.toml read successfully
🔍 nyash.toml read successfully
🔍 nyash.toml read successfully
🔍 nyash.toml read successfully
🔍 nyash.toml parsed successfully
🔍 Found box config for HttpServerBox with type_id: 20
🔍 Preparing to call birth() with type_id: 20
🔍 Output buffer allocated, about to call plugin invoke_fn...
🔍 Calling invoke_fn(type_id=20, method_id=0, instance_id=0, tlv_args=[1, 0, 0, 0], output_buf, output_size=1024)
🔍 invoke_fn returned with result: 0
🎉 birth() success: HttpServerBox instance_id=1
🔍 DEBUG: PluginBoxV2::share_box called for HttpServerBox (id=1)
🔍 stdlib not initialized for method call
🔍 DEBUG: PluginBoxV2::share_box called for HttpServerBox (id=1)
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: start
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpServerBox.start
[PluginLoaderV2] Invoke HttpServerBox.start: resolving and encoding args (argc=1)
[PluginLoaderV2] arg[0]: Integer(8099) -> Integer(tag=5)
🔍 stdlib not initialized for method call
🔍 nyash.toml parsed successfully
🔍 Found box config for HttpServerBox with type_id: 20
🔍 Preparing to call birth() with type_id: 20
🔍 Output buffer allocated, about to call plugin invoke_fn...
🔍 Calling invoke_fn(type_id=20, method_id=0, instance_id=0, tlv_args=[1, 0, 0, 0], output_buf, output_size=1024)
🔍 invoke_fn returned with result: 0
🎉 birth() success: HttpServerBox instance_id=2
🔍 DEBUG: PluginBoxV2::share_box called for HttpServerBox (id=2)
🔍 stdlib not initialized for method call
🔍 DEBUG: PluginBoxV2::share_box called for HttpServerBox (id=2)
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: start
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpServerBox.start
[PluginLoaderV2] Invoke HttpServerBox.start: resolving and encoding args (argc=1)
[PluginLoaderV2] arg[0]: Integer(8095) -> Integer(tag=5)
🔍 stdlib not initialized for method call
🔍 nyash.toml parsed successfully
🔍 Found box config for HttpServerBox with type_id: 20
🔍 Preparing to call birth() with type_id: 20
🔍 Output buffer allocated, about to call plugin invoke_fn...
🔍 Calling invoke_fn(type_id=20, method_id=0, instance_id=0, tlv_args=[1, 0, 0, 0], output_buf, output_size=1024)
🔍 invoke_fn returned with result: 0
🎉 birth() success: HttpServerBox instance_id=3
🔍 DEBUG: PluginBoxV2::share_box called for HttpServerBox (id=3)
🔍 stdlib not initialized for method call
🔍 DEBUG: PluginBoxV2::share_box called for HttpServerBox (id=3)
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: start
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpServerBox.start
[PluginLoaderV2] Invoke HttpServerBox.start: resolving and encoding args (argc=1)
[PluginLoaderV2] arg[0]: Integer(8096) -> Integer(tag=5)
🔍 stdlib not initialized for method call
🔍 nyash.toml parsed successfully
🔍 Found box config for HttpServerBox with type_id: 20
🔍 Preparing to call birth() with type_id: 20
🔍 Output buffer allocated, about to call plugin invoke_fn...
🔍 Calling invoke_fn(type_id=20, method_id=0, instance_id=0, tlv_args=[1, 0, 0, 0], output_buf, output_size=1024)
🔍 invoke_fn returned with result: 0
🎉 birth() success: HttpServerBox instance_id=4
🔍 DEBUG: PluginBoxV2::share_box called for HttpServerBox (id=4)
🔍 stdlib not initialized for method call
🔍 DEBUG: PluginBoxV2::share_box called for HttpServerBox (id=4)
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: start
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpServerBox.start
[PluginLoaderV2] Invoke HttpServerBox.start: resolving and encoding args (argc=1)
[PluginLoaderV2] arg[0]: Integer(8097) -> Integer(tag=5)
🔍 stdlib not initialized for method call
🔍 nyash.toml parsed successfully
🔍 Found box config for HttpServerBox with type_id: 20
🔍 Preparing to call birth() with type_id: 20
🔍 Output buffer allocated, about to call plugin invoke_fn...
🔍 Calling invoke_fn(type_id=20, method_id=0, instance_id=0, tlv_args=[1, 0, 0, 0], output_buf, output_size=1024)
🔍 invoke_fn returned with result: 0
🎉 birth() success: HttpServerBox instance_id=5
🔍 DEBUG: PluginBoxV2::share_box called for HttpServerBox (id=5)
🔍 stdlib not initialized for method call
🔍 DEBUG: PluginBoxV2::share_box called for HttpServerBox (id=5)
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: start
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpServerBox.start
[PluginLoaderV2] Invoke HttpServerBox.start: resolving and encoding args (argc=1)
[PluginLoaderV2] arg[0]: Integer(8098) -> Integer(tag=5)
🔍 stdlib not initialized for method call
🔍 create_box called for: HttpClientBox
🔍 Config loaded successfully
🔍 create_box called for: HttpClientBox
🔍 Config loaded successfully
🔍 create_box called for: HttpClientBox
🔍 Config loaded successfully
🔍 Found library: libnyash_net_plugin.so for box type: HttpClientBox
🔍 Plugin loaded successfully
🔍 Reading nyash.toml for type configuration...
🔍 Found library: libnyash_net_plugin.so for box type: HttpClientBox
🔍 Plugin loaded successfully
🔍 Reading nyash.toml for type configuration...
🔍 Found library: libnyash_net_plugin.so for box type: HttpClientBox
🔍 Plugin loaded successfully
🔍 Reading nyash.toml for type configuration...
🔍 nyash.toml read successfully
🔍 nyash.toml read successfully
🔍 nyash.toml read successfully
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: accept
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpServerBox.accept
[PluginLoaderV2] Invoke HttpServerBox.accept: resolving and encoding args (argc=0)
🔍 stdlib not initialized for method call
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: accept
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpServerBox.accept
[PluginLoaderV2] Invoke HttpServerBox.accept: resolving and encoding args (argc=0)
🔍 stdlib not initialized for method call
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: accept
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpServerBox.accept
[PluginLoaderV2] Invoke HttpServerBox.accept: resolving and encoding args (argc=0)
🔍 stdlib not initialized for method call
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: accept
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpServerBox.accept
[PluginLoaderV2] Invoke HttpServerBox.accept: resolving and encoding args (argc=0)
🔍 stdlib not initialized for method call
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: accept
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpServerBox.accept
[PluginLoaderV2] Invoke HttpServerBox.accept: resolving and encoding args (argc=0)
🔍 stdlib not initialized for method call
🔍 nyash.toml parsed successfully
🔍 Found box config for HttpClientBox with type_id: 23
🔍 Preparing to call birth() with type_id: 23
🔍 Output buffer allocated, about to call plugin invoke_fn...
🔍 Calling invoke_fn(type_id=23, method_id=0, instance_id=0, tlv_args=[1, 0, 0, 0], output_buf, output_size=1024)
🔍 invoke_fn returned with result: 0
🎉 birth() success: HttpClientBox instance_id=6
🔍 DEBUG: PluginBoxV2::share_box called for HttpClientBox (id=6)
🔍 stdlib not initialized for method call
🔍 DEBUG: PluginBoxV2::share_box called for HttpClientBox (id=6)
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: get
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpClientBox.get
[PluginLoaderV2] Invoke HttpClientBox.get: resolving and encoding args (argc=1)
[PluginLoaderV2] arg[0]: String(len=27) -> String(tag=6)
🔍 stdlib not initialized for method call
🔍 nyash.toml parsed successfully
🔍 Found box config for HttpClientBox with type_id: 23
🔍 Preparing to call birth() with type_id: 23
🔍 Output buffer allocated, about to call plugin invoke_fn...
🔍 Calling invoke_fn(type_id=23, method_id=0, instance_id=0, tlv_args=[1, 0, 0, 0], output_buf, output_size=1024)
🔍 invoke_fn returned with result: 0
🎉 birth() success: HttpClientBox instance_id=7
🔍 DEBUG: PluginBoxV2::share_box called for HttpClientBox (id=7)
🔍 stdlib not initialized for method call
🔍 DEBUG: PluginBoxV2::share_box called for HttpClientBox (id=7)
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: post
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpClientBox.post
[PluginLoaderV2] Invoke HttpClientBox.post: resolving and encoding args (argc=2)
[PluginLoaderV2] arg[0]: String(len=35) -> String(tag=6)
[PluginLoaderV2] arg[1]: String(len=15) -> String(tag=6)
🔍 stdlib not initialized for method call
🔍 nyash.toml parsed successfully
🔍 Found box config for HttpClientBox with type_id: 23
🔍 Preparing to call birth() with type_id: 23
🔍 Output buffer allocated, about to call plugin invoke_fn...
🔍 Calling invoke_fn(type_id=23, method_id=0, instance_id=0, tlv_args=[1, 0, 0, 0], output_buf, output_size=1024)
🔍 invoke_fn returned with result: 0
🎉 birth() success: HttpClientBox instance_id=8
🔍 DEBUG: PluginBoxV2::share_box called for HttpClientBox (id=8)
🔍 stdlib not initialized for method call
🔍 DEBUG: PluginBoxV2::share_box called for HttpClientBox (id=8)
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: get
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpClientBox.get
[PluginLoaderV2] Invoke HttpClientBox.get: resolving and encoding args (argc=1)
[PluginLoaderV2] arg[0]: String(len=21) -> String(tag=6)
🔍 stdlib not initialized for method call
🔍 Plugin invoke completed with result: 0
🔍 plugin_invoke_v2 returned result: 0
🔍 TLV output from plugin (len=4): [1, 0, 0, 0]
🔍 Plugin invoke completed with result: 0
🔍 plugin_invoke_v2 returned result: 0
🔍 TLV output from plugin (len=4): [1, 0, 0, 0]
🔍 Plugin invoke completed with result: 0
🔍 plugin_invoke_v2 returned result: 0
🔍 TLV output from plugin (len=4): [1, 0, 0, 0]
🔍 Plugin invoke completed with result: 0
🔍 plugin_invoke_v2 returned result: 0
🔍 TLV output from plugin (len=4): [1, 0, 0, 0]
🔍 Plugin invoke completed with result: 0
🔍 plugin_invoke_v2 returned result: 0
🔍 TLV output from plugin (len=4): [1, 0, 0, 0]
🔍 Plugin invoke completed with result: 0
🔍 plugin_invoke_v2 returned result: 0
🔍 TLV output from plugin (len=4): [1, 0, 0, 0]
🔍 Plugin invoke completed with result: 0
🔍 plugin_invoke_v2 returned result: 0
🔍 TLV output from plugin (len=4): [1, 0, 0, 0]
🔍 Plugin invoke completed with result: 0
🔍 plugin_invoke_v2 returned result: 0
🔍 TLV output from plugin (len=4): [1, 0, 0, 0]
🔍 create_box called for: VoidBox
VoidBox is not a plugin box type
🔍 DEBUG: execute_method_call - object type: VoidBox, method: respond
🔍 DEBUG: Checking StringBox downcast for type: VoidBox
🔍 DEBUG: StringBox downcast failed
🔍 DEBUG: Reached non-instance type error for type: VoidBox, method: respond
❌ Interpreter error: Type error: Cannot call method 'respond' on non-instance type
🔍 create_box called for: VoidBox
VoidBox is not a plugin box type
🔍 create_box called for: VoidBox
VoidBox is not a plugin box type
🔍 DEBUG: execute_method_call - object type: VoidBox, method: readBody
🔍 DEBUG: Checking StringBox downcast for type: VoidBox
🔍 DEBUG: StringBox downcast failed
🔍 DEBUG: Reached non-instance type error for type: VoidBox, method: readBody
❌ Interpreter error: Type error: Cannot call method 'readBody' on non-instance type
🔍 create_box called for: HttpResponseBox
🔍 Config loaded successfully
🔍 create_box called for: HttpResponseBox
🔍 Config loaded successfully
thread 'e2e_http_post_and_headers' panicked at tests/e2e_plugin_net.rs:159:43:
exec failed: TypeError { message: "Cannot call method 'readBody' on non-instance type" }
🔍 Found library: libnyash_net_plugin.so for box type: HttpResponseBox
🔍 Plugin loaded successfully
🔍 Reading nyash.toml for type configuration...
🔍 Found library: libnyash_net_plugin.so for box type: HttpResponseBox
🔍 Plugin loaded successfully
🔍 Reading nyash.toml for type configuration...
🔍 nyash.toml read successfully
🔍 nyash.toml read successfully
🔍 nyash.toml parsed successfully
🔍 Found box config for HttpResponseBox with type_id: 22
🔍 Preparing to call birth() with type_id: 22
🔍 Output buffer allocated, about to call plugin invoke_fn...
🔍 Calling invoke_fn(type_id=22, method_id=0, instance_id=0, tlv_args=[1, 0, 0, 0], output_buf, output_size=1024)
🔍 invoke_fn returned with result: 0
🎉 birth() success: HttpResponseBox instance_id=9
🔍 DEBUG: PluginBoxV2::share_box called for HttpResponseBox (id=9)
🔍 stdlib not initialized for method call
🔍 DEBUG: PluginBoxV2::share_box called for HttpResponseBox (id=9)
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: write
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpResponseBox.write
🔍 nyash.toml parsed successfully
🔍 Found box config for HttpResponseBox with type_id: 22
🔍 Preparing to call birth() with type_id: 22
🔍 Output buffer allocated, about to call plugin invoke_fn...
🔍 Calling invoke_fn(type_id=22, method_id=0, instance_id=0, tlv_args=[1, 0, 0, 0], output_buf, output_size=1024)
🔍 invoke_fn returned with result: 0
🎉 birth() success: HttpResponseBox instance_id=10
🔍 DEBUG: PluginBoxV2::share_box called for HttpResponseBox (id=10)
🔍 stdlib not initialized for method call
🔍 DEBUG: PluginBoxV2::share_box called for HttpResponseBox (id=10)
🔍 DEBUG: execute_method_call - object type: PluginBoxV2, method: write
🔍 DEBUG: Checking StringBox downcast for type: PluginBoxV2
🔍 DEBUG: StringBox downcast failed
🔍 execute_plugin_box_v2_method called: HttpResponseBox.write
🔍 DEBUG: execute_method_call - object type: VoidBox, method: path
🔍 DEBUG: Checking StringBox downcast for type: VoidBox
🔍 DEBUG: StringBox downcast failed
🔍 DEBUG: Reached non-instance type error for type: VoidBox, method: path
❌ Interpreter error: Type error: Cannot call method 'path' on non-instance type
thread 'e2e_http_multiple_requests_order' panicked at tests/e2e_plugin_net.rs:186:43:
exec failed: TypeError { message: "Cannot call method 'path' on non-instance type" }
[PluginLoaderV2] Invoke HttpResponseBox.write: resolving and encoding args (argc=1)
[PluginLoaderV2] arg[0]: String(len=1) -> String(tag=6)
🔍 stdlib not initialized for method call
[PluginLoaderV2] Invoke HttpResponseBox.write: resolving and encoding args (argc=1)
[PluginLoaderV2] arg[0]: String(len=1) -> String(tag=6)
🔍 stdlib not initialized for method call
🔍 DEBUG: execute_method_call - object type: VoidBox, method: respond
🔍 DEBUG: Checking StringBox downcast for type: VoidBox
🔍 DEBUG: StringBox downcast failed
🔍 DEBUG: Reached non-instance type error for type: VoidBox, method: respond
🔍 DEBUG: execute_method_call - object type: VoidBox, method: respond
🔍 DEBUG: Checking StringBox downcast for type: VoidBox
🔍 DEBUG: StringBox downcast failed
🔍 DEBUG: Reached non-instance type error for type: VoidBox, method: respond
❌ Interpreter error: Type error: Cannot call method 'respond' on non-instance type
❌ Interpreter error: Type error: Cannot call method 'respond' on non-instance type
thread 'e2e_http_server_shutdown_and_restart' panicked at tests/e2e_plugin_net.rs:102:22:
exec1: TypeError { message: "Cannot call method 'respond' on non-instance type" }
thread 'e2e_http_server_restart' panicked at tests/e2e_plugin_net.rs:80:43:
exec failed: TypeError { message: "Cannot call method 'respond' on non-instance type" }
error: test failed, to rerun pass `--test e2e_plugin_net`
running 5 tests
test e2e_http_stub_end_to_end ... FAILED
test e2e_http_post_and_headers ... FAILED
test e2e_http_multiple_requests_order ... FAILED
test e2e_http_server_shutdown_and_restart ... FAILED
test e2e_http_server_restart ... FAILED
failures:
failures:
e2e_http_multiple_requests_order
e2e_http_post_and_headers
e2e_http_server_restart
e2e_http_server_shutdown_and_restart
e2e_http_stub_end_to_end
test result: FAILED. 0 passed; 5 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.81s

View File

@ -1,57 +0,0 @@
🔍 DEBUG: Initializing v2 plugin system
[FileBox] Plugin initialized
🔌 v2 plugin system initialized from nyash.toml
📦 Registering plugin provider for FileBox
✅ v2 plugin system fully configured
🚀 Nyash MIR Compiler - Processing file: docs/examples/visibility_error.nyash 🚀
🚀 MIR Output for docs/examples/visibility_error.nyash:
; MIR Module: main
define void @User.birth/2(box<User> %0, ? %1, ? %2) effects(read) {
bb1:
0: ref_set %0.name = %1
1: ref_set %0.age = %2
2: %3 = const void
3: ret %3
}
define void @main() {
bb0:
0: safepoint
1: %0 = const "__me__"
2: %1 = new ConsoleBox()
3: call %1.birth()
4: ref_set %0.console = %1
5: %2 = const "__box_type_User"
6: %3 = const "__field_User_age"
7: %4 = const "__field_User_passwordHash"
8: %5 = const "__field_User_name"
9: %6 = const void
10: %7 = const "Alice"
11: %8 = new StringBox(%7)
12: call %8.birth(%7)
13: %9 = const 20
14: %10 = new IntegerBox(%9)
15: call %10.birth(%9)
16: %11 = new User(%8, %10)
17: call %11.birth(%8, %10)
18: %12 = const "__me__"
19: %13 = ref_get %12.console
20: %14 = const "name(public)="
21: %15 = new StringBox(%14)
22: call %15.birth(%14)
23: %16 = ref_get %11.name
24: %17 = %15 Add %16
25: %18 = call %13.log(%17)
26: %19 = const 30
27: %20 = new IntegerBox(%19)
28: call %20.birth(%19)
29: ref_set %11.age = %20
30: %21 = const "__me__"
31: %22 = ref_get %21.console
32: %23 = ref_get %11.age
33: %24 = call %22.log(%23)
34: ret %24
}

View File

@ -1,91 +0,0 @@
🔍 DEBUG: Initializing v2 plugin system
[FileBox] Plugin initialized
🔌 v2 plugin system initialized from nyash.toml
📦 Registering plugin provider for FileBox
✅ v2 plugin system fully configured
🚀 Nyash MIR Compiler - Processing file: docs/examples/visibility_ok.nyash 🚀
🚀 MIR Output for docs/examples/visibility_ok.nyash:
; MIR Module: main
define void @User.birth/2(box<User> %0, ? %1, ? %2) effects(read) {
bb1:
0: ref_set %0.name = %1
1: ref_set %0.age = %2
2: %3 = const void
3: ret %3
}
define void @User.setAge/1(box<User> %0, ? %1) effects(read) {
bb3:
0: ref_set %0.age = %1
1: %2 = const void
2: ret %2
}
define ? @User.getAge/0(box<User> %0) effects(read) {
bb2:
0: %1 = ref_get %0.age
1: ret %1
}
define void @main() {
bb0:
0: safepoint
1: %0 = const "__me__"
2: %1 = new ConsoleBox()
3: call %1.birth()
4: ref_set %0.console = %1
5: %2 = const "__box_type_User"
6: %3 = const "__field_User_age"
7: %4 = const "__field_User_passwordHash"
8: %5 = const "__field_User_name"
9: %6 = const "__method_User_getAge"
10: %7 = const "__method_User_setAge"
11: %8 = const void
12: %9 = const "Alice"
13: %10 = new StringBox(%9)
14: call %10.birth(%9)
15: %11 = const 20
16: %12 = new IntegerBox(%11)
17: call %12.birth(%11)
18: %13 = new User(%10, %12)
19: call %13.birth(%10, %12)
20: %14 = const "__me__"
21: %15 = ref_get %14.console
22: %16 = const "name(public)="
23: %17 = new StringBox(%16)
24: call %17.birth(%16)
25: %18 = ref_get %13.name
26: %19 = %17 Add %18
27: %20 = call %15.log(%19)
28: %21 = const "Bob"
29: %22 = new StringBox(%21)
30: call %22.birth(%21)
31: ref_set %13.name = %22
32: %23 = const "__me__"
33: %24 = ref_get %23.console
34: %25 = const "age(private, internal)="
35: %26 = new StringBox(%25)
36: call %26.birth(%25)
37: %28 = const "User.getAge/0"
38: %27 = call %28(%13)
39: %29 = %26 Add %27
40: %30 = call %24.log(%29)
41: %31 = const 21
42: %32 = new IntegerBox(%31)
43: call %32.birth(%31)
44: %33 = const 21
45: %34 = new IntegerBox(%33)
46: call %34.birth(%33)
47: %36 = const "User.setAge/1"
48: %35 = call %36(%13, %34)
49: %37 = const "__me__"
50: %38 = ref_get %37.console
51: %39 = const "done"
52: %40 = new StringBox(%39)
53: call %40.birth(%39)
54: %41 = call %38.log(%40)
55: ret %41
}

View File

@ -1,2 +0,0 @@
🔍 Analyzing dead code in session: 86fc6615
Using external tools for high-accuracy analysis (90%+ confidence)

View File

@ -1,215 +0,0 @@
# Nyash Configuration File v2
# マルチBox型プラグイン対応
[libraries]
# ライブラリ定義1つのプラグインで複数のBox型を提供可能
[libraries."libnyash_filebox_plugin.so"]
boxes = ["FileBox"]
path = "./plugins/nyash-filebox-plugin/target/release/libnyash_filebox_plugin.so"
[libraries."libnyash_counter_plugin.so"]
boxes = ["CounterBox"]
path = "./plugins/nyash-counter-plugin/target/release/libnyash_counter_plugin.so"
[libraries."libnyash_net_plugin.so"]
boxes = ["HttpServerBox", "HttpClientBox", "HttpResponseBox", "HttpRequestBox", "SocketServerBox", "SocketClientBox"]
path = "./plugins/nyash-net-plugin/target/release/libnyash_net_plugin.so"
# 将来の拡張例:
# "libnyash_database_plugin.so" = {
# boxes = ["PostgreSQLBox", "MySQLBox", "SQLiteBox"],
# path = "./target/release/libnyash_database_plugin.so"
# }
# FileBoxの型情報定義
[libraries."libnyash_filebox_plugin.so".FileBox]
type_id = 6
[libraries."libnyash_filebox_plugin.so".FileBox.methods]
# 全メソッドをmethod_idと共に定義
birth = { method_id = 0 }
open = { method_id = 1, args = ["path", "mode"] }
read = { method_id = 2 }
write = { method_id = 3, args = ["data"] }
close = { method_id = 4 }
fini = { method_id = 4294967295 }
# v2.1: Box引数を受け取るメソッド宣言FileBox: copyFrom(other: Handle)
copyFrom = { method_id = 7, args = [ { kind = "box", category = "plugin" } ] }
# v2.2: BoxRef(Handle)を返すメソッド宣言
cloneSelf = { method_id = 8 }
[libraries."libnyash_counter_plugin.so".CounterBox]
type_id = 7
singleton = true
[libraries."libnyash_counter_plugin.so".CounterBox.methods]
birth = { method_id = 0 }
inc = { method_id = 1 }
get = { method_id = 2 }
fini = { method_id = 4294967295 }
# HttpServerBox
[libraries."libnyash_net_plugin.so".HttpServerBox]
type_id = 10
[libraries."libnyash_net_plugin.so".HttpServerBox.methods]
birth = { method_id = 0 }
start = { method_id = 1, args = ["port"], returns_result = true }
stop = { method_id = 2, returns_result = true }
accept = { method_id = 3, returns_result = true }
fini = { method_id = 4294967295 }
# HttpClientBox
[libraries."libnyash_net_plugin.so".HttpClientBox]
type_id = 11
[libraries."libnyash_net_plugin.so".HttpClientBox.methods]
birth = { method_id = 0 }
get = { method_id = 1, args = ["url"] }
post = { method_id = 2, args = ["url", "body"] }
fini = { method_id = 4294967295 }
# HttpResponseBox
[libraries."libnyash_net_plugin.so".HttpResponseBox]
type_id = 12
[libraries."libnyash_net_plugin.so".HttpResponseBox.methods]
birth = { method_id = 0 }
setStatus = { method_id = 1, args = ["status"] }
setHeader = { method_id = 2, args = ["key", "value"] }
write = { method_id = 3, args = ["body"] }
readBody = { method_id = 4 }
getStatus = { method_id = 5 }
getHeader = { method_id = 6, args = ["key"] }
fini = { method_id = 4294967295 }
# HttpRequestBox
[libraries."libnyash_net_plugin.so".HttpRequestBox]
type_id = 13
[libraries."libnyash_net_plugin.so".HttpRequestBox.methods]
birth = { method_id = 0 }
respond = { method_id = 1, args = [{ kind = "box", category = "plugin" }] }
path = { method_id = 2 }
readBody = { method_id = 3 }
fini = { method_id = 4294967295 }
# SocketServerBox
[libraries."libnyash_net_plugin.so".SocketServerBox]
type_id = 14
[libraries."libnyash_net_plugin.so".SocketServerBox.methods]
birth = { method_id = 0 }
bind = { method_id = 1, args = ["port"] }
accept = { method_id = 2 }
fini = { method_id = 4294967295 }
# SocketClientBox
[libraries."libnyash_net_plugin.so".SocketClientBox]
type_id = 15
[libraries."libnyash_net_plugin.so".SocketClientBox.methods]
birth = { method_id = 0 }
connect = { method_id = 1, args = ["host", "port"] }
send = { method_id = 2, args = ["data"] }
receive = { method_id = 3 }
close = { method_id = 4 }
fini = { method_id = 4294967295 }
[plugin_paths]
# プラグインの検索パス(デフォルト)
search_paths = [
"./target/release",
"./target/debug",
"./plugins/*/target/release",
"./plugins/*/target/debug",
"/usr/local/lib/nyash/plugins",
"~/.nyash/plugins"
]
[libraries."libnyash_net_plugin.so"]
boxes = ["HttpServerBox", "HttpRequestBox", "HttpResponseBox", "HttpClientBox", "SocketServerBox", "SocketClientBox", "SocketConnBox"]
path = "./plugins/nyash-net-plugin/target/release/libnyash_net_plugin.so"
[libraries."libnyash_net_plugin.so".HttpServerBox]
type_id = 20
[libraries."libnyash_net_plugin.so".HttpServerBox.methods]
birth = { method_id = 0 }
start = { method_id = 1, args = ["port"], returns_result = true }
stop = { method_id = 2, returns_result = true }
accept = { method_id = 3, returns_result = true }
fini = { method_id = 4294967295 }
[libraries."libnyash_net_plugin.so".HttpRequestBox]
type_id = 21
[libraries."libnyash_net_plugin.so".HttpRequestBox.methods]
birth = { method_id = 0 }
path = { method_id = 1 }
readBody = { method_id = 2 }
respond = { method_id = 3, args = [ { kind = "box", category = "plugin" } ] }
fini = { method_id = 4294967295 }
[libraries."libnyash_net_plugin.so".HttpResponseBox]
type_id = 22
[libraries."libnyash_net_plugin.so".HttpResponseBox.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, args = ["name"] }
fini = { method_id = 4294967295 }
[libraries."libnyash_net_plugin.so".HttpClientBox]
type_id = 23
[libraries."libnyash_net_plugin.so".HttpClientBox.methods]
birth = { method_id = 0 }
get = { method_id = 1, returns_result = true }
post = { method_id = 2, returns_result = true }
fini = { method_id = 4294967295 }
## ResultBox normalization enabled above for get/post
[libraries."libnyash_net_plugin.so".SocketServerBox]
type_id = 30
[libraries."libnyash_net_plugin.so".SocketServerBox.methods]
birth = { method_id = 0 }
start = { method_id = 1, args = ["port"], returns_result = true }
stop = { method_id = 2, returns_result = true }
accept = { method_id = 3, returns_result = true }
acceptTimeout = { method_id = 4, args = ["timeout_ms"], returns_result = true }
fini = { method_id = 4294967295 }
# Optional: ResultBox normalization (recommendation)
# start = { method_id = 1, args = ["port"], returns_result = true }
# stop = { method_id = 2, returns_result = true }
# accept = { method_id = 3, returns_result = true }
[libraries."libnyash_net_plugin.so".SocketClientBox]
type_id = 32
[libraries."libnyash_net_plugin.so".SocketClientBox.methods]
birth = { method_id = 0 }
connect = { method_id = 1, args = ["host", "port"], returns_result = true }
fini = { method_id = 4294967295 }
# Optional: ResultBox normalization (recommendation)
# connect = { method_id = 1, args = ["host", "port"], returns_result = true }
[libraries."libnyash_net_plugin.so".SocketConnBox]
type_id = 31
[libraries."libnyash_net_plugin.so".SocketConnBox.methods]
birth = { method_id = 0 }
send = { method_id = 1 }
recv = { method_id = 2 }
close = { method_id = 3 }
recvTimeout = { method_id = 4, args = ["timeout_ms"], returns_result = true }
fini = { method_id = 4294967295 }

View File

@ -1,62 +0,0 @@
# AI Agent Challenge 1日実装戦略
## 概要
DEV.toのAI Agents Challengen8n + Bright DataにNyashで参加する戦略。
締切: 2025年8月31日
## 重要な発見
- 他の参加者は普通にJavaScriptで実装しているWASMは不要だった
- n8nはーコードツール、Webhookで簡単に連携可能
- NetBoxプラグインが既にHTTP機能を提供
## 1日実装プラン
### タイムライン
- 8:00-10:00: 基本設計・n8n理解
- 10:00-13:00: Nyash実装HTTPBox活用
- 13:00-16:00: n8n連携・Bright Data統合
- 16:00-19:00: デモアプリ完成
- 19:00-21:00: 記事作成・動画録画
- 21:00-23:00: 投稿・最終調整
### 実装アーキテクチャ
```nyash
// n8nブリッジ
box N8nBridge {
init { httpClient, workflows }
triggerWorkflow(webhookUrl, data) {
return me.httpClient.post(webhookUrl, data)
}
}
// 価格監視AIエージェント例
box PriceMonitorAgent {
init { products, notifier }
monitorPrices() {
// Bright Data経由でスクレイピング
// n8n経由で通知
}
}
```
### 差別化ポイント
1. **Nyashという独自言語**での実装(創造性満点)
2. Everything is Box哲学によるエレガントな設計
3. 既存のNetBoxプラグインを活用した高速開発
### 必要な準備
- n8n無料アカウント作成
- Bright Data $250クレジット取得
- NetBoxプラグインのテスト修正完了
### リスクと対策
- 時間制約 → シンプルな実装に集中
- 技術学習 → Webhook連携のみに限定
- デモ作成 → 録画で対応(ライブ不要)
## 結論
技術的には1日で実装可能。Nyashの知名度向上と$1,000の賞金獲得のチャンス。
最終更新: 2025-08-21

View File

@ -1,133 +0,0 @@
# Midnight Network Privacy-First Challenge 戦略
## 🎯 チャレンジ概要
- **主催**: DEV.to × Midnight Network
- **賞金総額**: $5,000
- **締切**: 2025年9月7日 11:59 PM PDT
- **発表**: 2025年9月18日
## 🏆 カテゴリーと賞金
1. **"Protect That Data"** - $3,500
- プライバシー保護アプリケーション
- ゼロ知識証明を活用したソリューション
2. **"Enhance the Ecosystem"** - $1,000
- 開発者ツール・SDK
- Midnight開発体験の改善
3. **"Best Tutorial"** - $500
- 教育コンテンツ
- Midnight技術の解説
## 💡 Nyashでの参加アイデア
### 1. **NyashPrivacyBox** - ゼロ知識証明ラッパーProtect That Data部門
```nyash
// Midnight NetworkのCompact言語をNyashから使いやすくするBox
box PrivacyBox {
init { midnightClient, proofs }
// プライベートデータの証明生成
proveAge(actualAge, minimumAge) {
// ゼロ知識証明で「最低年齢以上」を証明
// 実際の年齢は公開しない
return me.midnightClient.generateProof({
"statement": "age >= " + minimumAge,
"witness": actualAge
})
}
// プライベート投票システム
vote(choice) {
// 投票内容を秘密にしたまま、有効な投票であることを証明
local proof = me.midnightClient.proveValidVote(choice)
return me.submitVote(proof)
}
}
```
### 2. **Nyash→Compact トランスパイラー** Enhance the Ecosystem部門
```nyash
// NyashコードをMidnight Compact言語に変換
box CompactTranspiler {
transpile(nyashCode) {
// Everything is Box → Compact型システム
// Nyashのプライバシー宣言をCompactに変換
return me.convertToCompact(nyashCode)
}
}
```
### 3. **インタラクティブZKPチュートリアル** Best Tutorial部門
- Nyashで書かれたステップバイステップガイド
- ブラウザ上で動作するWASM版デモ
- ゼロ知識証明の概念を視覚的に解説
## 🛠️ 技術要件
- **Midnight Compact言語**: プライバシー保護言語
- **MidnightJS**: JavaScript SDK
- **Apache 2.0ライセンス**: オープンソース必須
- **GitHub公開**: リポジトリ必須
## 📅 実装計画〜9月7日
### Phase 1: 調査8月24-26日
- [ ] Midnight Networkドキュメント熟読
- [ ] Compact言語の基礎学習
- [ ] MidnightJSのサンプル実行
### Phase 2: プロトタイプ8月27-31日
- [ ] NyashからMidnightJSを呼び出す基本実装
- [ ] PrivacyBoxの最小実装
- [ ] 簡単なゼロ知識証明デモ
### Phase 3: 本実装9月1-5日
- [ ] 選択したカテゴリーの実装完成
- [ ] ドキュメント作成
- [ ] デモアプリケーション
### Phase 4: 仕上げ9月6-7日
- [ ] チュートリアル動画作成
- [ ] 最終テスト
- [ ] 提出準備
## 🎯 戦略的優位性
### Nyashの強み
1. **Everything is Box哲学**
- プライバシーもBoxとして扱える
- 直感的なAPIデザイン
2. **WASM対応**
- ブラウザでゼロ知識証明デモ可能
- インタラクティブな教育コンテンツ
3. **独自性**
- Nyashという新言語での実装は注目を集める
- 審査員の記憶に残りやすい
## 🤔 検討事項
### 技術的課題
- MidnightJSとの統合方法
- Compact言語の学習曲線
- ゼロ知識証明の実装複雑性
### 時間的制約
- 約2週間での実装
- Midnight技術の学習時間
- ドキュメント・チュートリアル作成
## 🎬 次のステップ
1. **今すぐ**: Midnight Networkのアカウント作成
2. **明日**: Compact言語チュートリアル開始
3. **週末**: 最初のプロトタイプ作成
## 📚 参考リンク
- [Midnight Developer Docs](https://docs.midnight.network/)
- [Challenge Details](https://dev.to/devteam/join-the-midnight-network-privacy-first-challenge-5000-in-prizes-3l45)
- [Submission Template](https://dev.to/new/midnightchallenge)
---
最終更新: 2025-08-24

View File

@ -1,113 +0,0 @@
# AI Agents Challenge - ワークフロー設計
## 基本的な流れ
### 1. **Nyash側** - トリガー送信
```nyash
box PriceMonitorAgent {
init { webhookUrl, products }
checkPrices() {
local net = new NetBox()
local data = new MapBox()
data.set("action", "check_prices")
data.set("products", me.products)
// n8nのWebhookをトリガー
net.post(me.webhookUrl, data.toJsonBox())
}
}
```
### 2. **n8n側** - ワークフロー
```
[Webhook] → [AI Agent] → [Bright Data] → [Process] → [Response]
```
- **Webhook Node**: Nyashからのリクエストを受信
- **AI Agent Node**:
- どのサイトをスクレイピングするか決定
- Bright Dataへのクエリを構築
- **Bright Data Node**:
- 実際のWebスクレイピング実行
- 商品価格などのデータ取得
- **Process**: データ整形・比較
- **Response**: 結果をWebhookで返す
### 3. **具体例: 価格監視エージェント**
#### Nyash側の実装
```nyash
static box Main {
main() {
local agent = new PriceMonitorAgent()
agent.webhookUrl = "https://your-n8n-instance.n8n.cloud/webhook/price-monitor"
// 監視したい商品
local products = new ArrayBox()
products.push({
"name": "iPhone 15",
"url": "https://example.com/iphone15",
"targetPrice": 800
})
agent.products = products
agent.checkPrices()
}
}
```
#### n8nでの設定手順
1. **Webhook Node設定**
- Method: POST
- Path: /price-monitor
- Response Mode: Last Node
2. **AI Agent Node設定**
- Model: GPT-3.5/4
- Prompt:
```
商品リストから、Bright Dataでスクレイピングすべき
URLとセレクタを生成してください。
商品: {{$json.products}}
```
3. **Bright Data Node設定**
- Scraper API使用
- Dynamic URL from AI Agent
- Extract: 価格情報
4. **Code Node価格比較**
```javascript
const currentPrice = $node["Bright Data"].json.price;
const targetPrice = $node["Webhook"].json.products[0].targetPrice;
if (currentPrice < targetPrice) {
return {
alert: true,
message: `価格が下がりました!${currentPrice}円`
};
}
```
### チャレンジの要件チェック
- ✅ n8n AI Agent Node使用
- ✅ Bright Data Verified Node使用
- ✅ 実用的で複雑
- ✅ 創造的Nyash言語使用
### デモ動画に含めるべき内容
1. Nyashコードの実行
2. n8nワークフローの動作
3. Bright Dataでのデータ取得
4. 結果の表示
### 簡単に始めるには
まず超シンプルな例から:
1. Webhookを受け取る
2. AI Agentに「今日の天気は」と聞く
3. 結果を返す
これが動いたら、Bright Dataを追加していく

View File

@ -1,67 +0,0 @@
# Bright Dataアクセス不可の場合の代替案
## 🌟 アイデア1: 公開APIを使ったAIエージェント
Bright Dataの代わりに公開APIを使う
```nyash
box WeatherAIAgent {
init { n8nWebhook, apiKeys }
// OpenWeatherMap APIなど無料APIを使用
getWeatherInsights(location) {
local net = new NetBox()
// n8n経由でAI分析
local data = new MapBox()
data.set("location", location)
data.set("action", "analyze_weather")
return net.post(me.n8nWebhook, data.toJsonBox())
}
}
```
## 🌟 アイデア2: GitHub/GitLab API活用
```nyash
box CodeReviewAgent {
// GitHubのPRを自動レビュー
reviewPullRequest(repoUrl, prNumber) {
// GitHub APIでPR情報取得
// n8n AI AgentでコードレビューSS
// 結果をコメントとして投稿
}
}
```
## 🌟 アイデア3: RSS/ニュースAPI
```nyash
box NewsDigestAgent {
// NewsAPI.orgなどの無料ニュースAPI使用
// AI要約・分析を提供
}
```
## n8nワークフロー構成
1. **Webhook****HTTP Request (API)****AI Agent****Response**
Bright Data Nodeの代わりに
- HTTP Request Node一般的なAPI呼び出し
- RSS Read NodeRSS/Atomフィード
- GitHub NodeGitHub API
- その他の統合
## 審査基準への対応
- ✅ AI Agent Node使用必須
- ✅ 実用的で複雑
- ✅ 創造的Nyash使用
- ⚠️ Bright Data未使用減点の可能性
## 結論
Bright Dataが使えなくても、他のデータソースでAIエージェントは作れる
ただし、賞金狙いなら要件を満たす必要があるので、メールで相談するのがベスト。

View File

@ -1,22 +0,0 @@
// n8n Webhook連携テスト
static box Main {
main() {
// NetBoxプラグインでHTTPリクエスト
local net = new NetBox()
// n8nのWebhook URLに送信
local webhookUrl = "https://webhook.n8n.io/test"
local data = new MapBox()
data.set("message", "Hello from Nyash!")
data.set("timestamp", new TimeBox().now())
print("Sending webhook to n8n...")
local response = net.post(webhookUrl, data.toJsonBox())
if response.isOk() {
print("Success! Response: " + response.getValue())
} else {
print("Error: " + response.getError())
}
}
}

View File

@ -1,71 +0,0 @@
// Midnight Network ZKPチュートリアル - Nyashデモ
// ゼロ知識証明を視覚的に理解する
static box Main {
main() {
local tutorial = new ZKPTutorial()
tutorial.start()
}
}
box ZKPTutorial {
init { console }
constructor() {
me.console = new ConsoleBox()
}
start() {
me.console.log("🔐 ゼロ知識証明チュートリアル by Nyash")
me.console.log("=====================================")
// レッスン1: 年齢証明
me.ageProofDemo()
// レッスン2: 秘密投票
me.votingDemo()
// レッスン3: 残高証明
me.balanceProofDemo()
}
ageProofDemo() {
me.console.log("\n📝 レッスン1: 年齢証明")
me.console.log("実際の年齢を明かさずに「18歳以上」を証明します")
local alice = new Person("Alice", 25)
local proof = alice.proveAgeAbove(18)
me.console.log("Aliceの証明: " + proof)
me.console.log("検証結果: 18歳以上 ✅")
me.console.log("実際の年齢: 秘密のまま 🤫")
}
votingDemo() {
me.console.log("\n🗳 レッスン2: 秘密投票")
// 投票内容を秘密にしながら有効性を証明
}
balanceProofDemo() {
me.console.log("\n💰 レッスン3: 残高証明")
// 具体的な金額を明かさずに「十分な残高がある」を証明
}
}
box Person {
init { name, age }
constructor(name, age) {
me.name = name
me.age = age
}
proveAgeAbove(minAge) {
// 実際のMidnightではZKP生成
// デモ用の簡易実装
if me.age >= minAge {
return "VALID_PROOF_" + new RandomBox().randomString(16)
}
return "INVALID_PROOF"
}
}

View File

@ -539,10 +539,41 @@ impl VM {
} }
/// Call a method on a Box - simplified version of interpreter method dispatch /// Call a method on a Box - simplified version of interpreter method dispatch
pub(super) fn call_box_method(&self, box_value: Box<dyn NyashBox>, method: &str, _args: Vec<Box<dyn NyashBox>>) -> Result<Box<dyn NyashBox>, VMError> { pub(super) fn call_box_method(&self, box_value: Box<dyn NyashBox>, method: &str, mut _args: Vec<Box<dyn NyashBox>>) -> Result<Box<dyn NyashBox>, VMError> {
// For now, implement basic methods for common box types // For now, implement basic methods for common box types
// This is a simplified version - real implementation would need full method dispatch // This is a simplified version - real implementation would need full method dispatch
// 🌟 Universal methods pre-dispatch (non-invasive)
match method {
"toString" => {
if !_args.is_empty() {
return Ok(Box::new(StringBox::new(format!("Error: toString() expects 0 arguments, got {}", _args.len()))));
}
return Ok(Box::new(StringBox::new(box_value.to_string_box().value)));
}
"type" => {
if !_args.is_empty() {
return Ok(Box::new(StringBox::new(format!("Error: type() expects 0 arguments, got {}", _args.len()))));
}
return Ok(Box::new(StringBox::new(box_value.type_name())));
}
"equals" => {
if _args.len() != 1 {
return Ok(Box::new(StringBox::new(format!("Error: equals() expects 1 argument, got {}", _args.len()))));
}
let rhs = _args.remove(0);
let eq = box_value.equals(&*rhs);
return Ok(Box::new(eq));
}
"clone" => {
if !_args.is_empty() {
return Ok(Box::new(StringBox::new(format!("Error: clone() expects 0 arguments, got {}", _args.len()))));
}
return Ok(box_value.clone_box());
}
_ => {}
}
// ResultBox (NyashResultBox - new) // ResultBox (NyashResultBox - new)
if let Some(result_box) = box_value.as_any().downcast_ref::<crate::boxes::result::NyashResultBox>() { if let Some(result_box) = box_value.as_any().downcast_ref::<crate::boxes::result::NyashResultBox>() {
match method { match method {
@ -562,11 +593,6 @@ impl VM {
// Legacy box_trait::ResultBox is no longer handled here (migration complete) // Legacy box_trait::ResultBox is no longer handled here (migration complete)
// Generic fallback: toString for any Box type
if method == "toString" {
return Ok(Box::new(StringBox::new(box_value.to_string_box().value)));
}
// StringBox methods // StringBox methods
if let Some(string_box) = box_value.as_any().downcast_ref::<StringBox>() { if let Some(string_box) = box_value.as_any().downcast_ref::<StringBox>() {
match method { match method {

View File

@ -455,8 +455,15 @@ impl BuiltinBoxFactory {
}); });
} }
let name = args[0].to_string_box().value; let name = args[0].to_string_box().value;
// Accept multiple payload forms: JSON string, JSONBox, MapBox
let payload_str = if let Some(jb) = args[1].as_any().downcast_ref::<crate::boxes::json::JSONBox>() {
jb.to_string()
} else if let Some(mb) = args[1].as_any().downcast_ref::<crate::boxes::map_box::MapBox>() {
mb.toJSON().to_string_box().value
} else {
args[1].to_string_box().value
};
// Try parse payload as JSON, fallback to string // Try parse payload as JSON, fallback to string
let payload_str = args[1].to_string_box().value;
let payload = match serde_json::from_str::<serde_json::Value>(&payload_str) { let payload = match serde_json::from_str::<serde_json::Value>(&payload_str) {
Ok(json) => json, Ok(json) => json,
Err(_) => serde_json::Value::String(payload_str), Err(_) => serde_json::Value::String(payload_str),

View File

@ -179,9 +179,15 @@ impl P2PBox {
if let Some(method_box) = handler.as_any().downcast_ref::<MethodBox>() { if let Some(method_box) = handler.as_any().downcast_ref::<MethodBox>() {
let method_clone = method_box.clone(); let method_clone = method_box.clone();
let intent_name = intent_str.to_string(); let intent_name = intent_str.to_string();
// capture state holders for receive-side tracing
let last_from = Arc::clone(&self.last_from);
let last_intent = Arc::clone(&self.last_intent_name);
t.register_intent_handler(&intent_name, Box::new(move |env| { t.register_intent_handler(&intent_name, Box::new(move |env| {
// flagがtrueのときのみ実行 // flagがtrueのときのみ実行
if flag.load(Ordering::SeqCst) { if flag.load(Ordering::SeqCst) {
// Update receive-side traces for E2E visibility
if let Ok(mut lf) = last_from.write() { *lf = Some(env.from.clone()); }
if let Ok(mut li) = last_intent.write() { *li = Some(env.intent.get_name().to_string_box().value); }
let _ = method_clone.invoke(vec![ let _ = method_clone.invoke(vec![
Box::new(env.intent.clone()), Box::new(env.intent.clone()),
Box::new(StringBox::new(env.from.clone())), Box::new(StringBox::new(env.from.clone())),
@ -253,6 +259,16 @@ impl P2PBox {
} }
} }
/// デバッグ: intentに対する有効ハンドラー数trueフラグ数
pub fn debug_active_handler_count(&self, intent_name: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
let name = intent_name.to_string_box().value;
let flags = self.handler_flags.read().unwrap();
let cnt = flags.get(&name)
.map(|v| v.iter().filter(|f| f.load(Ordering::SeqCst)).count())
.unwrap_or(0);
Box::new(crate::box_trait::IntegerBox::new(cnt as i64))
}
/// 最後に受信したfromを取得ループバック検証用 /// 最後に受信したfromを取得ループバック検証用
pub fn get_last_from(&self) -> Box<dyn NyashBox> { pub fn get_last_from(&self) -> Box<dyn NyashBox> {
let v = self.last_from.read().unwrap().clone().unwrap_or_default(); let v = self.last_from.read().unwrap().clone().unwrap_or_default();
@ -354,4 +370,83 @@ mod tests {
assert_eq!(p.get_last_from().to_string_box().value, "alice".to_string()); assert_eq!(p.get_last_from().to_string_box().value, "alice".to_string());
assert_eq!(p.get_last_intent_name().to_string_box().value, "ping".to_string()); assert_eq!(p.get_last_intent_name().to_string_box().value, "ping".to_string());
} }
/// Internal helper for tests: register raw Rust handler with optional async reply
impl P2PBox {
#[allow(dead_code)]
fn __debug_on_rust(&self, intent: &str, reply_intent: Option<&str>) {
if let Ok(mut t) = self.transport.write() {
let intent_name = intent.to_string();
let last_from = Arc::clone(&self.last_from);
let last_intent = Arc::clone(&self.last_intent_name);
// create self clone for reply
let self_clone = self.clone();
let reply_name = reply_intent.map(|s| s.to_string());
t.register_intent_handler(&intent_name, Box::new(move |env| {
if let Ok(mut lf) = last_from.write() { *lf = Some(env.from.clone()); }
if let Ok(mut li) = last_intent.write() { *li = Some(env.intent.get_name().to_string_box().value); }
if let Some(rn) = reply_name.clone() {
let to = env.from.clone();
std::thread::spawn(move || {
// slight delay to avoid lock contention
std::thread::sleep(std::time::Duration::from_millis(5));
let intent = IntentBox::new(rn, serde_json::json!({}));
let _ = self_clone.send(Box::new(StringBox::new(to)), Box::new(intent));
});
}
}));
}
}
}
#[test]
fn two_node_ping_pong() {
let alice = P2PBox::new("alice".to_string(), TransportKind::InProcess);
let bob = P2PBox::new("bob".to_string(), TransportKind::InProcess);
// bob replies pong to ping
bob.__debug_on_rust("ping", Some("pong"));
// alice listens pong
alice.__debug_on_rust("pong", None);
// send ping
let ping = IntentBox::new("ping".to_string(), serde_json::json!({}));
let _ = alice.send(Box::new(StringBox::new("bob")), Box::new(ping));
// bob should record ping
assert_eq!(bob.get_last_intent_name().to_string_box().value, "ping");
// allow async reply
std::thread::sleep(std::time::Duration::from_millis(20));
// alice should record pong
assert_eq!(alice.get_last_intent_name().to_string_box().value, "pong");
}
#[test]
fn on_once_disables_after_first_delivery() {
let p = P2PBox::new("alice".to_string(), TransportKind::InProcess);
// Register one-time handler for 'hello'
let handler = crate::method_box::MethodBox::new(Box::new(p.clone()), "noop".to_string());
let _ = p.on_once(Box::new(StringBox::new("hello")), Box::new(handler));
// Initially active = 1
let c0 = p.debug_active_handler_count(Box::new(StringBox::new("hello")));
assert_eq!(c0.to_string_box().value, "1");
// Send twice to self
let intent = IntentBox::new("hello".to_string(), serde_json::json!({}));
let _ = p.send(Box::new(StringBox::new("alice")), Box::new(intent.clone()));
let _ = p.send(Box::new(StringBox::new("alice")), Box::new(intent));
// After first delivery, once-flag should be false => active count = 0
let c1 = p.debug_active_handler_count(Box::new(StringBox::new("hello")));
assert_eq!(c1.to_string_box().value, "0");
}
#[test]
fn off_clears_handlers() {
let p = P2PBox::new("bob".to_string(), TransportKind::InProcess);
let handler = crate::method_box::MethodBox::new(Box::new(p.clone()), "noop".to_string());
let _ = p.on(Box::new(StringBox::new("bye")), Box::new(handler));
// Active = 1
let c0 = p.debug_active_handler_count(Box::new(StringBox::new("bye")));
assert_eq!(c0.to_string_box().value, "1");
// Off
let _ = p.off(Box::new(StringBox::new("bye")));
let c1 = p.debug_active_handler_count(Box::new(StringBox::new("bye")));
assert_eq!(c1.to_string_box().value, "0");
}
} }

View File

@ -229,6 +229,38 @@ impl NyashInterpreter {
// オブジェクトを評価(通常のメソッド呼び出し) // オブジェクトを評価(通常のメソッド呼び出し)
let obj_value = self.execute_expression(object)?; let obj_value = self.execute_expression(object)?;
idebug!("🔍 DEBUG: execute_method_call - object type: {}, method: {}", obj_value.type_name(), method); idebug!("🔍 DEBUG: execute_method_call - object type: {}, method: {}", obj_value.type_name(), method);
// 🌟 ユニバーサルメソッド前段ディスパッチ(非侵襲)
// toString()/type()/equals(x)/clone() をトレイトに直結
match method {
"toString" => {
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation { message: format!("toString() expects 0 arguments, got {}", arguments.len()) });
}
return Ok(Box::new(obj_value.to_string_box()));
}
"type" => {
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation { message: format!("type() expects 0 arguments, got {}", arguments.len()) });
}
return Ok(Box::new(StringBox::new(obj_value.type_name())));
}
"equals" => {
if arguments.len() != 1 {
return Err(RuntimeError::InvalidOperation { message: format!("equals() expects 1 argument, got {}", arguments.len()) });
}
let rhs = self.execute_expression(&arguments[0])?;
let eq = obj_value.equals(&*rhs);
return Ok(Box::new(eq));
}
"clone" => {
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation { message: format!("clone() expects 0 arguments, got {}", arguments.len()) });
}
return Ok(obj_value.clone_box());
}
_ => {}
}
// Builtin dispatch (centralized) // Builtin dispatch (centralized)
if let Some(res) = self.dispatch_builtin_method(&obj_value, method, arguments) { if let Some(res) = self.dispatch_builtin_method(&obj_value, method, arguments) {

View File

@ -47,6 +47,9 @@ impl NyashInterpreter {
method: &str, method: &str,
arguments: &[ASTNode], arguments: &[ASTNode],
) -> Result<Box<dyn NyashBox>, RuntimeError> { ) -> Result<Box<dyn NyashBox>, RuntimeError> {
if crate::interpreter::utils::debug_on() || std::env::var("NYASH_DEBUG_P2P").unwrap_or_default() == "1" {
eprintln!("[Interp:P2P] {}(..) called with {} args", method, arguments.len());
}
match method { match method {
// ードID取得 // ードID取得
"getNodeId" | "getId" => Ok(p2p_box.get_node_id()), "getNodeId" | "getId" => Ok(p2p_box.get_node_id()),
@ -74,7 +77,7 @@ impl NyashInterpreter {
} }
// on メソッド実装ResultBox返却 // on メソッド実装ResultBox返却
, "on" => { "on" => {
if arguments.len() < 2 { if arguments.len() < 2 {
return Err(RuntimeError::InvalidOperation { message: "on requires (intentName, handler) arguments".to_string() }); return Err(RuntimeError::InvalidOperation { message: "on requires (intentName, handler) arguments".to_string() });
} }

View File

@ -114,6 +114,9 @@ impl MessageBusData {
/// メッセージをルーティング /// メッセージをルーティング
pub fn route(&self, to: &str, intent: IntentBox, from: &str) -> Result<(), SendError> { pub fn route(&self, to: &str, intent: IntentBox, from: &str) -> Result<(), SendError> {
if let Some(endpoint) = self.nodes.get(to) { if let Some(endpoint) = self.nodes.get(to) {
if std::env::var("NYASH_DEBUG_P2P").unwrap_or_default() == "1" {
eprintln!("[MessageBus] route {} -> {} intent={}", from, to, intent.get_name().to_string_box().value);
}
endpoint.deliver(intent, from); endpoint.deliver(intent, from);
Ok(()) Ok(())
} else { } else {

View File

@ -109,6 +109,9 @@ impl Transport for InProcessTransport {
let cb = std::sync::Arc::new(cb); let cb = std::sync::Arc::new(cb);
let cb_clone = cb.clone(); let cb_clone = cb.clone();
// Adapt to MessageBus handler signature // Adapt to MessageBus handler signature
if std::env::var("NYASH_DEBUG_P2P").unwrap_or_default() == "1" {
eprintln!("[InProcessTransport] register handler node={} intent={}", self.node_id, intent_name);
}
self.add_handler(&intent_name, Box::new(move |intent_box: IntentBox, from: &str| { self.add_handler(&intent_name, Box::new(move |intent_box: IntentBox, from: &str| {
let env = IntentEnvelope { let env = IntentEnvelope {
from: from.to_string(), from: from.to_string(),
@ -133,7 +136,17 @@ impl Transport for InProcessTransport {
impl Drop for InProcessTransport { impl Drop for InProcessTransport {
fn drop(&mut self) { fn drop(&mut self) {
// NOTE: Temporarily disabled unregister to avoid interfering with shared-node lifetimes. // Safe unregister: only remove if the current endpoint matches the registry entry
// Proper refcounted unregister will be implemented later. if let Ok(mut bus) = self.bus.lock() {
let removed = bus.unregister_if_same(&self.node_id, &self.endpoint);
if std::env::var("NYASH_DEBUG_P2P").unwrap_or_default() == "1" {
eprintln!(
"[InProcessTransport::drop] node_id={} removed={} (bus={:?})",
self.node_id,
removed,
&*bus
);
}
}
} }
} }

View File

@ -1,29 +0,0 @@
# Test Configuration for plugin-tester
# Valid TOML structure
# Plugin name mappings (simple version)
[plugin_names]
FileBox = "nyash-filebox-plugin"
# Plugin configurations with method type information
[plugins.FileBox]
plugin_name = "nyash-filebox-plugin"
[plugins.FileBox.methods]
# readは引数なし
read = { args = [] }
# writeは文字列をbytesとして送る
write = { args = [{ from = "string", to = "bytes" }] }
# openは2つの文字列引数
open = { args = [
{ name = "path", from = "string", to = "string" },
{ name = "mode", from = "string", to = "string" }
] }
# closeは引数なし、戻り値なし
close = { args = [] }
# existsは引数なし、戻り値はbool将来拡張
exists = { args = [], returns = "bool" }

View File

@ -1,241 +0,0 @@
(module
(import "env" "print" (func $print (param i32) ))
(import "env" "print_str" (func $print_str (param i32 i32) ))
(import "env" "console_log" (func $console_log (param i32 i32) ))
(import "env" "canvas_fillRect" (func $canvas_fillRect (param i32 i32 i32 i32 i32 i32 i32 i32) ))
(import "env" "canvas_fillText" (func $canvas_fillText (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) ))
(import "env" "box_to_string" (func $box_to_string (param i32) (result i32)))
(import "env" "box_print" (func $box_print (param i32) ))
(import "env" "box_equals" (func $box_equals (param i32 i32) (result i32)))
(import "env" "box_clone" (func $box_clone (param i32) (result i32)))
(memory (export "memory") 1)
(data (i32.const 4096) "\48\65\6c\6c\6f\20\66\72\6f\6d\20\57\41\53\4d\21")
(data (i32.const 4112) "\54\68\65\20\61\6e\73\77\65\72\20\69\73\3a\20")
(global $heap_ptr (mut i32) (i32.const 2048))
(func $malloc (param $size i32) (result i32)
(local $ptr i32)
(local $aligned_size i32)
;; Align size to 4-byte boundary
local.get $size
i32.const 3
i32.add
i32.const -4
i32.and
local.set $aligned_size
;; Get current heap pointer
global.get $heap_ptr
local.set $ptr
;; Advance heap pointer by aligned size
global.get $heap_ptr
local.get $aligned_size
i32.add
global.set $heap_ptr
;; Return allocated pointer
local.get $ptr
)
(func $box_alloc (param $type_id i32) (param $field_count i32) (result i32)
(local $ptr i32)
(local $total_size i32)
;; Calculate total size: header (12) + fields (field_count * 4)
local.get $field_count
i32.const 4
i32.mul
i32.const 12
i32.add
local.set $total_size
;; Allocate memory
local.get $total_size
call $malloc
local.set $ptr
;; Initialize type_id
local.get $ptr
local.get $type_id
i32.store
;; Initialize ref_count to 1
local.get $ptr
i32.const 4
i32.add
i32.const 1
i32.store
;; Initialize field_count
local.get $ptr
i32.const 8
i32.add
local.get $field_count
i32.store
;; Return box pointer
local.get $ptr
)
(func $alloc_stringbox (result i32)
(local $ptr i32)
;; Allocate memory for box
i32.const 20
call $malloc
local.set $ptr
;; Initialize type_id
local.get $ptr
i32.const 4097
i32.store
;; Initialize ref_count to 1
local.get $ptr
i32.const 4
i32.add
i32.const 1
i32.store
;; Initialize field_count
local.get $ptr
i32.const 8
i32.add
i32.const 2
i32.store
;; Return box pointer
local.get $ptr
)
(func $alloc_integerbox (result i32)
(local $ptr i32)
;; Allocate memory for box
i32.const 16
call $malloc
local.set $ptr
;; Initialize type_id
local.get $ptr
i32.const 4098
i32.store
;; Initialize ref_count to 1
local.get $ptr
i32.const 4
i32.add
i32.const 1
i32.store
;; Initialize field_count
local.get $ptr
i32.const 8
i32.add
i32.const 1
i32.store
;; Return box pointer
local.get $ptr
)
(func $alloc_boolbox (result i32)
(local $ptr i32)
;; Allocate memory for box
i32.const 16
call $malloc
local.set $ptr
;; Initialize type_id
local.get $ptr
i32.const 4099
i32.store
;; Initialize ref_count to 1
local.get $ptr
i32.const 4
i32.add
i32.const 1
i32.store
;; Initialize field_count
local.get $ptr
i32.const 8
i32.add
i32.const 1
i32.store
;; Return box pointer
local.get $ptr
)
(func $alloc_databox (result i32)
(local $ptr i32)
;; Allocate memory for box
i32.const 16
call $malloc
local.set $ptr
;; Initialize type_id
local.get $ptr
i32.const 4101
i32.store
;; Initialize ref_count to 1
local.get $ptr
i32.const 4
i32.add
i32.const 1
i32.store
;; Initialize field_count
local.get $ptr
i32.const 8
i32.add
i32.const 1
i32.store
;; Return box pointer
local.get $ptr
)
(func $main (local $0 i32) (local $1 i32) (local $2 i32) (local $3 i32) (local $4 i32)
nop
call $alloc_stringbox
local.set $0
local.get $0
i32.const 12
i32.add
i32.const 4096
i32.store
local.get $0
i32.const 16
i32.add
i32.const 16
i32.store
local.get $0
call $print
i32.const 0
local.set $1
i32.const 42
local.set $2
call $alloc_stringbox
local.set $3
local.get $3
i32.const 12
i32.add
i32.const 4112
i32.store
local.get $3
i32.const 16
i32.add
i32.const 15
i32.store
local.get $3
local.get $2
i32.add
local.set $4
local.get $4
call $print
local.get $4
return
)
(export "main" (func $main))
)

View File

@ -1,24 +0,0 @@
# Nyash v2 configuration test file
# Legacy single-box plugins (for backward compatibility)
[plugins]
FileBox = "plugins/nyash-filebox-plugin/target/release/libnyash_filebox_plugin.so"
# New multi-box plugin libraries
[plugins.libraries]
"nyash-test-multibox" = { plugin_path = "plugins/nyash-test-multibox/target/release/libnyash_test_multibox.so", provides = ["TestBoxA", "TestBoxB"] }
# Box type definitions
[plugins.types.TestBoxA]
library = "nyash-test-multibox"
type_id = 200
[plugins.types.TestBoxA.methods]
hello = { args = [] }
[plugins.types.TestBoxB]
library = "nyash-test-multibox"
type_id = 201
[plugins.types.TestBoxB.methods]
greet = { args = [] }