feat: Extract BID converter from Copilot and prepare plugin migration
- Extract Copilot's BID converter code to src/bid-converter-copilot/ for future use - Create comprehensive plugin migration request document for Copilot - Target 13 built-in boxes for plugin conversion (HTTP, GUI, Audio, etc.) - Preserve existing nyash.toml-based plugin system - Reorganize docs/説明書/reference/ structure for better organization
This commit is contained in:
@ -1,6 +1,117 @@
|
||||
# Nyash言語コアコンセプト AI向け速習ガイド
|
||||
# 🚀 Nyash言語 - 一目でわかる速習ガイド
|
||||
|
||||
このドキュメントは、AIアシスタントがNyashプログラミング言語を迅速に理解するために、そのコアコンセプトを凝縮して提供します。
|
||||
**Nyash**は「Everything is Box」哲学に基づく革新的プログラミング言語です。このドキュメントで、Nyashのコアコンセプトを素早く理解できます。
|
||||
|
||||
## 🎯 **5分で動かす!クイックスタート**
|
||||
|
||||
```bash
|
||||
# ビルド & 実行
|
||||
cargo build --release -j32
|
||||
./target/release/nyash program.nyash
|
||||
|
||||
# プラグイン対応FileBox実行例
|
||||
./target/release/nyash local_tests/test_plugin_filebox.nyash
|
||||
```
|
||||
|
||||
### 🌟 **実際に動く!Nyashコード例**
|
||||
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
static box Main {
|
||||
init { console }
|
||||
|
||||
main() {
|
||||
// 🎉 自動リテラル変換 - 超簡単!
|
||||
local name = "Nyash" // → StringBox
|
||||
local year = 2025 // → IntegerBox
|
||||
local pi = 3.14159 // → FloatBox
|
||||
|
||||
// 🚀 プラグインシステム
|
||||
local f = new FileBox("data.txt") // プラグイン実装
|
||||
f.write("Hello from plugin!")
|
||||
print("読み取り: " + f.read())
|
||||
|
||||
// 📚 標準ライブラリ
|
||||
local upper = string.upper(name)
|
||||
console.log("🎉 " + upper + " " + year + " Ready!")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**実行結果:**
|
||||
```
|
||||
読み取り: Hello from plugin!
|
||||
🎉 NYASH 2025 Ready!
|
||||
```
|
||||
|
||||
## 🔌 **BID-FFIプラグインシステム** - Phase 9.75g-0の革命!
|
||||
|
||||
Nyashの最新の革命的機能:**プラグインによるBox拡張システム**
|
||||
|
||||
### 🎯 **プラグインの威力**
|
||||
|
||||
```nyash
|
||||
// プラグイン設定(nyash.toml)
|
||||
[plugins]
|
||||
FileBox = "nyash-filebox-plugin"
|
||||
|
||||
// Nyashコード - 透過的にプラグイン使用
|
||||
local f = new FileBox("important.txt") // プラグイン実装を自動選択
|
||||
f.write("機密データ") // プラグインのwrite()
|
||||
local data = f.read() // プラグインのread()
|
||||
```
|
||||
|
||||
### ✨ **型情報管理システム**
|
||||
|
||||
```toml
|
||||
# nyash.toml - 型情報で自動変換
|
||||
[plugins.FileBox.methods]
|
||||
write = { args = [{ from = "string", to = "bytes" }] } # 自動変換
|
||||
read = { args = [] } # 引数なし
|
||||
```
|
||||
|
||||
### 🛡️ **メモリ安全性**
|
||||
|
||||
- **HostVtable**: プラグイン↔ホスト間の安全なインターフェース
|
||||
- **生存期間管理**: birth/finiライフサイクル完全実装
|
||||
- **valgrind検証済み**: セグフォルト完全解消
|
||||
|
||||
### 📋 **プラグイン診断ツール**
|
||||
|
||||
```bash
|
||||
# プラグインの健全性チェック
|
||||
./tools/plugin-tester/target/release/plugin-tester check plugin.so
|
||||
./tools/plugin-tester/target/release/plugin-tester io plugin.so
|
||||
```
|
||||
|
||||
**詳細**: [BID-FFI仕様書](説明書/reference/box-design/ffi-abi-specification.md)
|
||||
|
||||
## ⚡ **実行バックエンド選択** - 開発から本番まで
|
||||
|
||||
Nyashは用途に応じて最適な実行方式を選択可能:
|
||||
|
||||
```bash
|
||||
# 開発・デバッグ(即時実行)
|
||||
./target/release/nyash program.nyash
|
||||
|
||||
# 高速実行(本番用)
|
||||
./target/release/nyash --backend vm program.nyash
|
||||
|
||||
# Web配布用
|
||||
./target/release/nyash --compile-wasm program.nyash
|
||||
|
||||
# 性能比較
|
||||
./target/release/nyash --benchmark --iterations 100
|
||||
```
|
||||
|
||||
### 🚀 **性能実績**
|
||||
- **VM**: 20.4倍高速化
|
||||
- **WASM**: 13.5倍高速化
|
||||
- **LLVM AOT**: 100-1000倍高速化(Phase 10計画中)
|
||||
- **インタープリター**: 開発に最適、本番でも実用的
|
||||
|
||||
**詳細**: [実行バックエンド完全ガイド](execution-backends.md)
|
||||
|
||||
## 1. 基本哲学: Everything is a Box (すべてはBoxである)
|
||||
|
||||
@ -460,71 +571,42 @@ r3 = await f3
|
||||
}
|
||||
```
|
||||
|
||||
## 11. 実行バックエンド選択とハイブリッド戦略 (2025-08-16更新)
|
||||
## 11. クイック実行コマンド
|
||||
|
||||
Nyashは4つの実行方式をサポート。**インタープリターは開発だけでなく本番でも実用的**(Pythonのように):
|
||||
|
||||
### 🌟 **インタープリター併用戦略**
|
||||
```
|
||||
開発時: インタープリター(即時実行・デバッグ・非同期フル対応)
|
||||
本番時: インタープリター(多くのユースケースで十分高速)
|
||||
OR
|
||||
コンパイラ(性能要求時)
|
||||
配布時: AOT native(最高性能)
|
||||
Web時: WASM(ブラウザ対応)
|
||||
```
|
||||
|
||||
### 実行方法
|
||||
```bash
|
||||
# インタープリター実行(開発・本番両対応)
|
||||
nyash program.nyash
|
||||
# ビルド & 基本実行
|
||||
cargo build --release -j32
|
||||
./target/release/nyash program.nyash
|
||||
|
||||
# VM実行(高速実行)
|
||||
nyash --backend vm program.nyash
|
||||
# プラグイン診断
|
||||
./tools/plugin-tester/target/release/plugin-tester check plugin.so
|
||||
|
||||
# WASM生成(Web配布)
|
||||
nyash --compile-wasm program.nyash
|
||||
|
||||
# ベンチマーク実行(性能比較)
|
||||
nyash --benchmark --iterations 100
|
||||
# 性能比較
|
||||
./target/release/nyash --benchmark --iterations 100
|
||||
```
|
||||
|
||||
### **性能比較(実行速度):**
|
||||
- **WASM**: 13.5倍高速化
|
||||
- **VM**: 20.4倍高速化
|
||||
- **Interpreter**: ベースライン(多くの場合十分高速)
|
||||
- **LLVM AOT**: 100-1000倍高速化(Phase 10計画中)
|
||||
|
||||
### **インタープリターの価値:**
|
||||
- **即時実行**: コンパイル不要で素早い開発サイクル
|
||||
- **完全な非同期**: Rust async/awaitで真の並行処理
|
||||
- **デバッグ容易**: 実行時情報の完全把握
|
||||
- **実用的性能**: PythonやRubyが証明する十分な速度
|
||||
|
||||
詳細: [docs/execution-backends.md](execution-backends.md)
|
||||
|
||||
## 12. クイック実行(ローカル)
|
||||
|
||||
- ビルド: `cargo build --release -j32`
|
||||
- 実行: `./target/release/nyash program.nyash`
|
||||
- WASM: `./target/release/nyash --compile-wasm program.nyash`
|
||||
|
||||
---
|
||||
|
||||
**最終更新: 2025年8月16日** - **インタープリター併用戦略統合**
|
||||
- 🌟 **インタープリター併用戦略**: 開発・本番両対応の実用的実行モデル
|
||||
- ✅ **静的boxメソッド呼び出し追加**: Phase 9.75i実装機能
|
||||
- ✅ **ビルトインBox追加**: FloatBox, SocketBox, BufferBox
|
||||
- ✅ **実行バックエンド説明更新**: インタープリターの本番価値明記
|
||||
**最終更新: 2025年8月19日** - **🚀 Phase 9.75g-0 BID-FFI完全実装!**
|
||||
|
||||
**前回の革命的改善(Phase 9.75h):**
|
||||
- 🌟 **自動リテラル変換実装**: 文字列・数値・真偽値の自動Box変換
|
||||
- ✅ **using nyashstd完全実装**: 標準ライブラリアクセス機能完成
|
||||
- ✅ **birth構文追加**: 「生命をBoxに与える」統一コンストラクタ
|
||||
### 🎉 **最新の革命的成果**
|
||||
- 🔌 **BID-FFIプラグインシステム**: プラグインによるBox拡張完全実装
|
||||
- ✨ **型情報管理システム**: nyash.tomlベースの自動型変換
|
||||
- 🛡️ **メモリ安全性確保**: HostVtable生存期間問題解決、valgrind検証済み
|
||||
- 🧪 **plugin-tester**: 汎用プラグイン診断ツール完成
|
||||
|
||||
### 🌟 **過去の革命的改善**
|
||||
- **Phase 9.75h**: 自動リテラル変換、using nyashstd、birth構文
|
||||
- **Phase 9.75i**: 静的boxメソッド、SocketBox、BufferBox
|
||||
- **Phase 9.75j**: 警告削減(106個→0個)
|
||||
|
||||
### 🚀 **Nyashの実用的価値**
|
||||
**Everything is Box哲学 + 使いやすさ + 実用的性能** の三位一体!
|
||||
- **開発時**: インタープリターで即時実行・完全デバッグ
|
||||
- **本番時**: インタープリター(十分高速)またはコンパイラ(最高性能)
|
||||
- **将来**: LLVM AOTで100-1000倍高速化(Phase 10)
|
||||
**Everything is Box哲学 + プラグイン拡張 + 実用的性能** の革新的言語!
|
||||
|
||||
- **🔌 拡張性**: プラグインで無限にBox機能拡張
|
||||
- **🛡️ 安全性**: メモリ安全性とvalgrind検証済み
|
||||
- **⚡ 性能**: VM 20倍、WASM 13倍、将来AOT 1000倍高速化
|
||||
- **📚 使いやすさ**: 自動変換、標準ライブラリ、直感的構文
|
||||
|
||||
**詳しいdocs**: [完全リファレンス](説明書/reference/) | [開発ガイド](../CLAUDE.md) | [Phase計画](予定/native-plan/copilot_issues.txt)
|
||||
|
||||
|
||||
198
docs/plugin-migration-request.md
Normal file
198
docs/plugin-migration-request.md
Normal file
@ -0,0 +1,198 @@
|
||||
# 📦 Nyash ビルトインBox → プラグイン化移行依頼
|
||||
|
||||
## 🎯 概要
|
||||
NyashのビルトインBoxをプラグイン化し、コアを軽量化したい。
|
||||
FileBoxプラグインの成功例を参考に、以下のBoxを順次プラグイン化してください。
|
||||
|
||||
## 📋 移行対象Box一覧
|
||||
|
||||
### 🌐 Phase 1: ネットワーク・通信系(最優先)
|
||||
```
|
||||
plugins/nyash-http-plugin/
|
||||
├── HttpClientBox - HTTP通信クライアント(GET/POST/PUT/DELETE)
|
||||
├── HTTPServerBox - HTTPサーバー機能
|
||||
├── HTTPRequestBox - HTTPリクエスト表現
|
||||
└── HTTPResponseBox - HTTPレスポンス表現
|
||||
|
||||
plugins/nyash-socket-plugin/
|
||||
└── SocketBox - TCP/UDPソケット通信
|
||||
```
|
||||
|
||||
### 🖼️ Phase 2: GUI・グラフィック系
|
||||
```
|
||||
plugins/nyash-egui-plugin/
|
||||
└── EguiBox - デスクトップGUI(既にfeature分離済み)
|
||||
|
||||
plugins/nyash-canvas-plugin/
|
||||
├── CanvasEventBox - Canvas描画イベント
|
||||
└── CanvasLoopBox - Canvas描画ループ
|
||||
|
||||
plugins/nyash-web-plugin/(WASM専用)
|
||||
├── WebDisplayBox - HTML表示
|
||||
├── WebConsoleBox - ブラウザコンソール
|
||||
└── WebCanvasBox - Canvas描画
|
||||
```
|
||||
|
||||
### 🎵 Phase 3: 特殊用途系
|
||||
```
|
||||
plugins/nyash-audio-plugin/
|
||||
├── AudioBox - 音声再生・合成
|
||||
└── SoundBox - 効果音再生
|
||||
|
||||
plugins/nyash-qr-plugin/
|
||||
└── QRBox - QRコード生成
|
||||
|
||||
plugins/nyash-stream-plugin/
|
||||
└── StreamBox - ストリーム処理
|
||||
|
||||
plugins/nyash-timer-plugin/
|
||||
└── TimerBox - タイマー機能
|
||||
```
|
||||
|
||||
## 🔧 実装ガイドライン
|
||||
|
||||
### 1. 参考にするファイル
|
||||
- **成功例**: `plugins/nyash-filebox-plugin/` - 動作確認済みのFileBoxプラグイン
|
||||
- **設定例**: `nyash.toml` - 型情報定義の書き方
|
||||
- **テスト**: `tools/plugin-tester/` - プラグイン診断ツール
|
||||
|
||||
### 2. 各プラグインの構成
|
||||
```
|
||||
plugins/nyash-xxx-plugin/
|
||||
├── Cargo.toml # 依存関係(例: reqwest for HTTP)
|
||||
├── src/
|
||||
│ └── lib.rs # FFI実装
|
||||
├── nyash.toml # 型情報定義
|
||||
└── README.md # 使用方法
|
||||
```
|
||||
|
||||
### 3. nyash.toml記述例(HttpClientBoxの場合)
|
||||
```toml
|
||||
[plugins.HttpClientBox.methods]
|
||||
# GETリクエスト
|
||||
get = {
|
||||
args = [{ name = "url", from = "string", to = "string" }],
|
||||
returns = "string"
|
||||
}
|
||||
|
||||
# POSTリクエスト
|
||||
post = {
|
||||
args = [
|
||||
{ name = "url", from = "string", to = "string" },
|
||||
{ name = "body", from = "string", to = "string" }
|
||||
],
|
||||
returns = "string"
|
||||
}
|
||||
|
||||
# ヘッダー付きリクエスト
|
||||
request = {
|
||||
args = [
|
||||
{ name = "method", from = "string", to = "string" },
|
||||
{ name = "url", from = "string", to = "string" },
|
||||
{ name = "options", from = "map", to = "map" }
|
||||
],
|
||||
returns = "map" # { status, body, headers }
|
||||
}
|
||||
|
||||
# DELETE リクエスト
|
||||
delete = {
|
||||
args = [{ name = "url", from = "string", to = "string" }],
|
||||
returns = "string"
|
||||
}
|
||||
|
||||
# PUT リクエスト
|
||||
put = {
|
||||
args = [
|
||||
{ name = "url", from = "string", to = "string" },
|
||||
{ name = "body", from = "string", to = "string" }
|
||||
],
|
||||
returns = "string"
|
||||
}
|
||||
```
|
||||
|
||||
### 4. テスト方法
|
||||
```bash
|
||||
# ビルド
|
||||
cd plugins/nyash-xxx-plugin
|
||||
cargo build --release
|
||||
|
||||
# plugin-testerで診断
|
||||
cd ../../tools/plugin-tester
|
||||
./target/release/plugin-tester ../../plugins/nyash-xxx-plugin/target/release/libnyash_xxx_plugin.so
|
||||
|
||||
# Nyashで実行テスト
|
||||
./target/release/nyash test_xxx.nyash
|
||||
```
|
||||
|
||||
## 📝 特記事項
|
||||
|
||||
### HttpBox系
|
||||
- 現在スタブ実装なので移行しやすい
|
||||
- reqwest依存を復活させる
|
||||
- 非同期処理の考慮が必要
|
||||
|
||||
### EguiBox
|
||||
- 既にfeature分離されているので参考になる
|
||||
- メインスレッド制約に注意
|
||||
|
||||
### AudioBox/SoundBox
|
||||
- プラットフォーム依存性が高い
|
||||
- Web/Desktop両対応を検討
|
||||
|
||||
### 依存関係の管理
|
||||
- 各プラグインは独立したCargo.tomlを持つ
|
||||
- ビルド時間短縮のため最小限の依存にする
|
||||
|
||||
## 💡 実装の重要ポイント
|
||||
|
||||
### FFI境界での注意事項
|
||||
1. **メモリ管理**:
|
||||
- Rustの所有権とCのメモリ管理の違いに注意
|
||||
- 文字列は必ずCString/CStr経由で変換
|
||||
|
||||
2. **エラーハンドリング**:
|
||||
- パニックをFFI境界で止める(catch_unwind使用)
|
||||
- エラーコードで通信(0=成功, 負値=エラー)
|
||||
|
||||
3. **型変換パターン** (FileBoxプラグインより):
|
||||
```rust
|
||||
// Nyash文字列 → Rust文字列
|
||||
let path = get_string_arg(&args[0], 0)?;
|
||||
|
||||
// Rust文字列 → Nyash文字列
|
||||
encode_string_result(&contents, result, result_len)
|
||||
```
|
||||
|
||||
### 参考ファイルの具体的パス
|
||||
- **FileBoxプラグイン実装**: `plugins/nyash-filebox-plugin/src/lib.rs`
|
||||
- **FFI仕様書**: `docs/説明書/reference/plugin-system/ffi-abi-specification.md`
|
||||
- **プラグインシステム説明**: `docs/説明書/reference/plugin-system/plugin-system.md`
|
||||
- **BID-FFI型変換** (参考): `src/bid-converter-copilot/tlv.rs`
|
||||
|
||||
## 📅 推奨実装順序とロードマップ
|
||||
|
||||
### Week 1: HttpBox系(最も簡単)
|
||||
- 既にスタブ実装済み
|
||||
- reqwest依存を追加するだけ
|
||||
- FileBoxと同じパターンで実装可能
|
||||
|
||||
### Week 2: 特殊用途系(独立性高い)
|
||||
- QRBox: 単機能で簡単
|
||||
- TimerBox: 非同期処理の練習に最適
|
||||
- StreamBox: 中程度の複雑さ
|
||||
|
||||
### Week 3: GUI/グラフィック系(プラットフォーム依存)
|
||||
- EguiBox: feature分離済みなので参考になる
|
||||
- Canvas系: Web/Desktop両対応必要
|
||||
- Audio系: 最も複雑(最後に実装)
|
||||
|
||||
## 🎯 期待される効果
|
||||
1. **ビルド時間**: 3分 → 30秒以下
|
||||
2. **バイナリサイズ**: 最小構成で500KB以下
|
||||
3. **保守性**: 各プラグイン独立開発可能
|
||||
4. **拡張性**: ユーザーが独自プラグイン作成可能
|
||||
|
||||
## 📝 質問・相談先
|
||||
- プラグイン化で不明な点があれば、FileBoxプラグインの実装を参考に
|
||||
- FFI実装で困ったら、plugin-testerのソースコードも参考になります
|
||||
- nyash.tomlの型定義で迷ったら、既存のFileBox定義を真似してください
|
||||
211
docs/予定/native-plan/Phase-9.78-LLVM-PoC-Strategy.md
Normal file
211
docs/予定/native-plan/Phase-9.78-LLVM-PoC-Strategy.md
Normal file
@ -0,0 +1,211 @@
|
||||
# 🚀 Phase 9.78: LLVM Proof of Concept - AI大会議戦略文書
|
||||
|
||||
## 🎯 **Phase 9.78の位置づけ**
|
||||
|
||||
```
|
||||
Phase 8.6: VM最適化完了 ✅
|
||||
↓
|
||||
Phase 9.78: LLVM PoC (3週間集中) ← 🆕 挿入!
|
||||
├─ ✅ 実現可能 → Phase 9.8(完全版) → Phase 10.2(本格LLVM)
|
||||
└─ ❌ 実現困難 → Phase 9.8(3バックエンド版) → Box統合
|
||||
```
|
||||
|
||||
**戦略的価値**: 不確定要素を3週間で解決し、後続開発の全体最適化を実現
|
||||
|
||||
## 🔍 **現在のMIR分析**
|
||||
|
||||
### **技術基盤状況** ✅
|
||||
```rust
|
||||
// ChatGPT5設計 20-25命令MIR
|
||||
- SSA形式 ✅
|
||||
- 効果追跡 (EffectMask) ✅
|
||||
- Box最適化対応 ✅
|
||||
- 所有権検証システム ✅
|
||||
- 基本ブロック・関数構造 ✅
|
||||
|
||||
主要命令セット:
|
||||
├─ Const, BinOp, UnaryOp, Compare
|
||||
├─ BoxCall, ExternCall (プラグイン連携)
|
||||
├─ RefNew, RefGet, RefSet (参照操作)
|
||||
├─ Branch, Jump, Return (制御フロー)
|
||||
└─ Print, FutureNew, Await (特殊操作)
|
||||
```
|
||||
|
||||
### **LLVM変換の技術的課題** 🤔
|
||||
```
|
||||
1. MIR ValueId → LLVM Value* 対応
|
||||
2. Box型 → LLVM struct表現
|
||||
3. ExternCall → C-ABI関数呼び出し
|
||||
4. 効果追跡 → LLVM属性 (readonly/noalias等)
|
||||
5. 所有権 → LLVM メモリ管理
|
||||
```
|
||||
|
||||
## 🤖 **AI大会議への相談事項**
|
||||
|
||||
### **Gemini先生への技術相談**
|
||||
|
||||
```
|
||||
Nyashプログラミング言語のMIR→LLVM IR変換について技術的相談です。
|
||||
|
||||
【背景】
|
||||
- ChatGPT5設計の20-25命令MIR (SSA形式)
|
||||
- Everything is Box哲学 (全データがBoxオブジェクト)
|
||||
- Arc<Mutex>統一アーキテクチャ
|
||||
- BID-FFIプラグインシステム (C-ABI)
|
||||
|
||||
【MIR主要命令】
|
||||
- Const, BinOp, UnaryOp, Compare
|
||||
- BoxCall (Box.method呼び出し)
|
||||
- ExternCall (プラグイン関数呼び出し)
|
||||
- RefNew, RefGet, RefSet (参照操作)
|
||||
- Branch, Jump, Return (制御フロー)
|
||||
|
||||
【質問】
|
||||
1. MIR→LLVM IR変換の基本戦略は?
|
||||
2. Box型の効率的なLLVM表現は?
|
||||
3. C-ABIプラグイン統合の最適手法は?
|
||||
4. 3週間PoC の現実的スコープは?
|
||||
5. パフォーマンス向上の期待値は?
|
||||
|
||||
Rust実装での実践的なアドバイスをお願いします。
|
||||
```
|
||||
|
||||
### **Codex先生への実装相談**
|
||||
|
||||
```
|
||||
Nyashプログラミング言語のLLVM実装について実装戦略を相談したいです。
|
||||
|
||||
【プロジェクト概要】
|
||||
- 15日間で開発されたプログラミング言語
|
||||
- 4バックエンド対応 (Interpreter/VM/WASM/LLVM)
|
||||
- MIR中間表現 (20-25命令、SSA形式)
|
||||
- プラグインシステム完備
|
||||
|
||||
【実装チームの特徴】
|
||||
- AI協調開発 (Claude/Gemini/ChatGPT/Copilot)
|
||||
- 開発速度重視 (3週間でPoC完成目標)
|
||||
- 実用性優先 (完璧より実装)
|
||||
|
||||
【技術的制約】
|
||||
- Rust実装
|
||||
- LLVM-sys crate使用想定
|
||||
- 既存MIR構造活用
|
||||
- プラグインC-ABI統合必須
|
||||
|
||||
【相談事項】
|
||||
1. 3週間PoC実装の現実的な手順は?
|
||||
2. MIR→LLVM変換の最小実装範囲は?
|
||||
3. Box型をLLVMでどう表現すべきか?
|
||||
4. エラー頻発箇所と対策は?
|
||||
5. デバッグ・テスト戦略は?
|
||||
|
||||
実装経験に基づく現実的なアドバイスをお願いします。
|
||||
```
|
||||
|
||||
## 🛠️ **Copilot依頼文書案**
|
||||
|
||||
### **Phase 9.78: LLVM Proof of Concept実装依頼**
|
||||
|
||||
**目標**: 3週間でNyash MIR→LLVM IR変換の実現可能性を実証
|
||||
|
||||
**成功基準**:
|
||||
- 基本MIR命令(Const, BinOp, Compare, Branch, Return)のLLVM変換
|
||||
- Box型の基本的なLLVM表現実装
|
||||
- Hello World レベルの実行確認
|
||||
- 理論的性能向上の算出 (10倍目標)
|
||||
|
||||
**技術基盤**:
|
||||
```rust
|
||||
// 既存のMIR構造を活用
|
||||
src/mir/instruction.rs // 20-25命令定義
|
||||
src/mir/function.rs // 関数・モジュール構造
|
||||
src/mir/basic_block.rs // 基本ブロック管理
|
||||
|
||||
// 作成予定のLLVM実装
|
||||
src/backend/llvm/
|
||||
├─ compiler.rs // MIR→LLVM変換メイン
|
||||
├─ box_types.rs // Box型のLLVM表現
|
||||
├─ c_abi.rs // プラグインC-ABI統合
|
||||
└─ runtime.rs // ランタイムサポート
|
||||
```
|
||||
|
||||
**実装手順提案**:
|
||||
```
|
||||
Week 1: LLVM基盤構築
|
||||
├─ llvm-sys crate統合
|
||||
├─ 基本的な変換フレームワーク
|
||||
├─ 最小MIR命令 (Const, Return) 変換
|
||||
└─ Hello World レベル動作確認
|
||||
|
||||
Week 2: 主要機能実装
|
||||
├─ 算術演算 (BinOp, UnaryOp, Compare)
|
||||
├─ 制御フロー (Branch, Jump)
|
||||
├─ Box型基本表現
|
||||
└─ 関数呼び出し機構
|
||||
|
||||
Week 3: 統合・検証
|
||||
├─ 既存MIRとの統合テスト
|
||||
├─ 性能ベンチマーク実行
|
||||
├─ 実現可能性評価レポート
|
||||
└─ Phase 10本格実装計画策定
|
||||
```
|
||||
|
||||
**重要な考慮事項**:
|
||||
- 完璧を求めず、実現可能性の実証に集中
|
||||
- 既存のMIR構造を最大活用
|
||||
- エラーハンドリングより基本機能優先
|
||||
- ベンチマークによる定量評価必須
|
||||
|
||||
**期待される成果**:
|
||||
- LLVM実装の技術的実現可能性確認
|
||||
- 性能向上ポテンシャルの定量評価
|
||||
- Phase 9.8 BIDレジストリでのLLVM対応完全版実装可能性判定
|
||||
- Phase 10本格実装の具体的工程表
|
||||
|
||||
## 📊 **成功判定基準**
|
||||
|
||||
### **最低限成功** (実現可能と判定)
|
||||
```
|
||||
✅ 基本MIR命令のLLVM変換動作
|
||||
✅ Box型の基本的LLVM表現実装
|
||||
✅ 簡単なプログラムの実行確認
|
||||
✅ 理論的性能向上の算出
|
||||
```
|
||||
|
||||
### **理想的成功** (本格実装確実)
|
||||
```
|
||||
🌟 全MIR命令対応
|
||||
🌟 プラグインC-ABI統合
|
||||
🌟 実際の性能測定 (2倍以上)
|
||||
🌟 メモリ管理・エラーハンドリング
|
||||
```
|
||||
|
||||
### **失敗判定** (3バックエンドに方針転換)
|
||||
```
|
||||
❌ 基本変換が3週間で実装困難
|
||||
❌ Box型表現が非現実的に複雑
|
||||
❌ 性能向上が期待値を大幅に下回る
|
||||
❌ 技術的負債が実装継続を阻害
|
||||
```
|
||||
|
||||
## 🎉 **次のステップ**
|
||||
|
||||
### **AI大会議実行**
|
||||
1. Gemini先生に技術相談
|
||||
2. Codex先生に実装戦略相談
|
||||
3. 両者のアドバイスを統合
|
||||
4. 最終的なCopilot依頼文書完成
|
||||
|
||||
### **Phase 9.78開始**
|
||||
1. VM最適化完了の確認
|
||||
2. AI大会議結果の反映
|
||||
3. Copilotへの正式依頼
|
||||
4. 3週間集中実装開始
|
||||
|
||||
---
|
||||
|
||||
**作成**: 2025年8月19日
|
||||
**目的**: Phase 9.78 LLVM PoC実装のための戦略文書
|
||||
**次期行動**: AI大会議でさらなる戦略精緻化
|
||||
|
||||
この文書をベースに、Gemini先生とCodex先生に相談し、最強のLLVM実装戦略を策定しましょう!🚀
|
||||
@ -1,5 +1,5 @@
|
||||
# 🤖 Copilot様 作業予定・課題整理 (Phase 9.7以降 実用化重点)
|
||||
# Generated: 2025-08-16 (インタープリター併用戦略統合)
|
||||
# 🤖 Copilot様 作業予定・課題整理 (Phase 8.6-10 重点フェーズ)
|
||||
# Generated: 2025-08-19 (Phase 9.75g-0完了・VM性能改善移行)
|
||||
# Purpose: Claude×Copilot協調開発のための情報共有
|
||||
|
||||
================================================================================
|
||||
@ -26,47 +26,91 @@ Web時: WASM(ブラウザ対応)
|
||||
- **十分な性能**: 多くのユースケースで実用的(Pythonが証明)
|
||||
|
||||
================================================================================
|
||||
🎯 Phase 9.7以降 開発ロードマップ (実用化重点)
|
||||
🎯 Phase 8.6-10 開発ロードマップ (性能最適化・LLVM実装重点)
|
||||
================================================================================
|
||||
|
||||
## ⚡ Phase 9.77: WASM緊急復旧 - BoxCall/UTF-8エラー修正(進行中)
|
||||
## 🎊 Phase 9.75g-0: BID-FFI Plugin System - 完全完了! ✅
|
||||
|
||||
Summary:
|
||||
- BoxCall命令実装 ✅ 完了
|
||||
- wasmtimeバージョン更新 ✅ 完了
|
||||
- UTF-8エラー修正 🔄 進行中(Issue #110)
|
||||
- ✅ **動的プラグインシステム完成**: FileBoxプラグインで実証
|
||||
- ✅ **BID-FFI基盤確立**: 型安全なFFIインターフェース
|
||||
- ✅ **plugin-tester完成**: 汎用プラグイン診断ツール
|
||||
- ✅ **型情報管理システム**: nyash.toml外部化、セグフォルト修正
|
||||
|
||||
Priority: **Critical**
|
||||
Expected Duration: 1-2週間
|
||||
GitHub Issue: #110 (Phase 9.77a)
|
||||
**革命的成果**: NyashがプラグインでBox型を動的拡張可能に!
|
||||
|
||||
### 進捗状況
|
||||
- ✅ **Task 1.1**: BoxCall実装(toString, print, equals, clone, log)
|
||||
- ✅ **Task 1.2**: wasmtime 18.0 → 35.0.0更新、RuntimeImports追加
|
||||
- 🔄 **Task 1.3**: UTF-8エラー原因特定(エラーメッセージ発生元不明)
|
||||
|
||||
### 🤖 Copilot協力中
|
||||
- エラーメッセージ「Generated WASM is not valid UTF-8」の発生元調査
|
||||
- WAT→WASM変換パイプラインのデバッグ
|
||||
```nyash
|
||||
// これが現実になった!
|
||||
local file = new FileBox() // プラグイン提供
|
||||
local db = new PostgreSQLBox() // 将来: プラグイン提供
|
||||
local gpu = new CudaBox() // 将来: プラグイン提供
|
||||
```
|
||||
|
||||
References:
|
||||
- docs/予定/native-plan/issues/phase_9_77_wasm_emergency.md
|
||||
- docs/予定/native-plan/issues/phase_9_77a_utf8_error_fix.md
|
||||
- docs/Phase-9.75g-0-BID-FFI-Developer-Guide.md (包括的開発者ガイド)
|
||||
- tools/plugin-tester/ (プラグイン診断ツール)
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
## 📦 Phase 9.8: BIDレジストリ + 自動コード生成ツール(WASM/VM/LLVM/言語)
|
||||
## 🚨 Phase 8.6: VM性能改善 - 最優先課題(進行中)
|
||||
|
||||
Summary:
|
||||
- BIDレジストリと、BID→各ターゲットのスタブ生成(import/extern宣言)を自動化。
|
||||
- **緊急問題**: VMがインタープリターより0.9倍遅い(性能回帰!)
|
||||
- **目標**: 2倍以上高速化でVM実行を実用レベルに引き上げ
|
||||
- **担当**: Copilot主導(GitHub Issue #112)
|
||||
|
||||
Scope/Tasks:
|
||||
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:
|
||||
### Acceptance
|
||||
- console/canvasのBIDから各ターゲットの骨子が自動生成される
|
||||
- **FileBoxプラグインがVM・WASM・AOT全てで動作**
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
@ -119,15 +163,22 @@ Acceptance:
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
## 🏆 Phase 10: LLVM Direct AOT(最高性能実現)
|
||||
## 🏆 Phase 10: LLVM Direct AOT - 実現可能性検証中
|
||||
|
||||
Summary:
|
||||
- MIR→LLVM IR直接変換による最高性能AOT実現
|
||||
- **調査・実証段階**: MIR→LLVM IR直接変換による最高性能AOT実現を目指す
|
||||
- インタープリターとの併用で最適な開発・実行体験を提供
|
||||
- 非同期処理フルサポート(async/await のネイティブ実装)
|
||||
|
||||
Priority: High (Phase 9.77完了後)
|
||||
Expected Duration: 4-6ヶ月
|
||||
Priority: **Research** (Phase 9.8完了後に実現可能性評価)
|
||||
Expected Duration: **調査3週間 + 実装3-6ヶ月**(実現可能性次第)
|
||||
|
||||
### 🔍 実現可能性チェック項目
|
||||
- ✅ **技術的基盤**: MIR 26命令セット(LLVM IR変換可能)
|
||||
- ✅ **AOTスケルトン**: 基本構造完成済み
|
||||
- ✅ **型情報システム**: 最適化に必要な情報完備
|
||||
- 🔄 **Proof of Concept**: 基本的なMIR→LLVM変換の実証
|
||||
- ❓ **実装工数**: 現実的な期間での完成可能性
|
||||
|
||||
### 🌟 インタープリター併用戦略
|
||||
```
|
||||
@ -137,7 +188,15 @@ Expected Duration: 4-6ヶ月
|
||||
Web配布: WASM(ブラウザ対応)
|
||||
```
|
||||
|
||||
### 🏗️ Phase 10.1: 同期版LLVM実装(3ヶ月)
|
||||
### 🏗️ Phase 10.1: Proof of Concept(3週間)**実現可能性評価**
|
||||
|
||||
Investigation Steps:
|
||||
1) **MIR→LLVM IR変換調査**: 基本命令の変換可能性検証
|
||||
2) **Box型表現調査**: LLVM IRでのBox型効率的実装方法
|
||||
3) **C-ABI統合調査**: プラグインとの連携可能性
|
||||
4) **性能予測**: 理論的な高速化効果の算出
|
||||
|
||||
### 🏗️ Phase 10.2: 基本実装(3ヶ月)**実現可能と判断した場合**
|
||||
|
||||
Implementation Steps:
|
||||
1) `src/backend/llvm/` 基盤構築
|
||||
@ -145,7 +204,7 @@ Implementation Steps:
|
||||
3) Box操作の最適化(エスケープ解析)
|
||||
4) ベンチマーク: 100倍目標
|
||||
|
||||
### 🌐 Phase 10.2: 非同期拡張(2ヶ月)
|
||||
### 🌐 Phase 10.3: 非同期拡張(2ヶ月)**基本実装完了後**
|
||||
|
||||
非同期サポート戦略:
|
||||
- **async/await ネイティブ実装**: Rust風の効率的な非同期
|
||||
@ -153,7 +212,7 @@ Implementation Steps:
|
||||
- **インタープリター互換**: 同じ非同期セマンティクス
|
||||
|
||||
```rust
|
||||
// Phase 10.2: 非同期LLVM実装
|
||||
// Phase 10.3: 非同期LLVM実装(予定)
|
||||
FutureNew → LLVM coroutine intrinsics
|
||||
Await → LLVM suspend/resume points
|
||||
FutureSet → completion notification
|
||||
@ -181,6 +240,22 @@ FutureSet → completion notification
|
||||
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 外部関数マッピング方針(プラットフォーム抽象)
|
||||
@ -315,17 +390,17 @@ Acceptance Criteria:
|
||||
💡 Copilot様への具体的お願い・相談事項
|
||||
================================================================================
|
||||
|
||||
## 🔧 Phase 9.77 緊急対応
|
||||
## 🔧 Phase 8.6 VM性能改善 (最優先)
|
||||
|
||||
### UTF-8エラー調査(Issue #110)
|
||||
❓ エラーメッセージ「Generated WASM is not valid UTF-8」の発生元は?
|
||||
❓ wabt::wat2wasm以外でエラーが出ている可能性は?
|
||||
❓ runner.rs/main.rsのエラー処理フローは?
|
||||
### VM実行時間詳細測定・プロファイリング
|
||||
❓ 命令ディスパッチのボトルネック特定方法は?
|
||||
❓ HashMap操作の最適化戦略は?
|
||||
❓ デバッグ出力削除による性能改善測定は?
|
||||
|
||||
### WASM基本機能復旧
|
||||
❓ 最小テストケース(`local result = 42`)のデバッグ方法は?
|
||||
❓ WAT生成パイプラインの問題箇所特定は?
|
||||
❓ 効率的なデバッグ戦略は?
|
||||
### VM最適化実装
|
||||
❓ Direct threading実装の現実的アプローチは?
|
||||
❓ Register-based VM への移行可能性は?
|
||||
❓ Box操作インライン化の効果的な実装は?
|
||||
|
||||
## 🚀 長期戦略相談
|
||||
|
||||
@ -334,10 +409,11 @@ Acceptance Criteria:
|
||||
❓ インタープリターとコンパイラの互換性保証は?
|
||||
❓ Pythonライクな実用性の実現方法は?
|
||||
|
||||
### Phase 10 LLVM Direct AOT
|
||||
❓ 非同期処理のネイティブ実装戦略は?
|
||||
❓ LLVM coroutine intrinsicsの活用方法は?
|
||||
❓ インタープリターとの非同期セマンティクス統一は?
|
||||
### Phase 10 LLVM実現可能性調査 (研究段階)
|
||||
❓ MIR→LLVM IR変換の基本的な実装戦略は?
|
||||
❓ Box型のLLVM表現として最適なアプローチは?
|
||||
❓ C-ABIとの統合によるプラグイン連携可能性は?
|
||||
❓ 現実的な開発期間での完成可能性評価は?
|
||||
|
||||
### Everything is Box最適化
|
||||
❓ Box操作の根本的高速化戦略は?
|
||||
@ -376,12 +452,13 @@ Acceptance Criteria:
|
||||
🎯 期待される成果・インパクト
|
||||
================================================================================
|
||||
|
||||
## Phase 8-9完了時の成果 (達成済み)
|
||||
## Phase 8-9完了時の成果 (達成済み・進行中)
|
||||
🏆 RefNew/RefGet/RefSet WASM完全動作
|
||||
🏆 Box操作ベンチマーク追加
|
||||
🏆 メモリレイアウト最適化効果測定
|
||||
🏆 26命令MIR階層化完了(Phase 8.5)
|
||||
🏆 VM性能改善完了(Phase 8.6)
|
||||
🔄 **VM性能改善進行中(Phase 8.6)** - GitHub Issue #112
|
||||
🏆 **Phase 9.75g-0 BID-FFI Plugin System完全完了**
|
||||
🏆 警告削減100%達成(Phase 9.75j)
|
||||
🏆 BoxCall実装・wasmtime更新(Phase 9.77)
|
||||
|
||||
@ -412,14 +489,14 @@ Acceptance Criteria:
|
||||
一緒にNyashを最高の言語にしていきましょう🚀
|
||||
|
||||
================================================================================
|
||||
最終更新: 2025-08-16 (インタープリター併用戦略統合・Phase整理)
|
||||
作成者: Claude (インタープリター価値認識 + Phase重複削除)
|
||||
最終更新: 2025-08-19 (Phase 9.75g-0完了・VM性能改善最優先・LLVM調査段階化)
|
||||
作成者: Claude (BID-FFIプラグインシステム完了 + 最新優先順位反映)
|
||||
|
||||
🎯 重要な変更点:
|
||||
- Phase 9.5: 削除(完了済み)
|
||||
- Phase 9.6/9.7: 削除(Phase 9.77と重複)
|
||||
- Phase 9.75: 削除(完了済み)
|
||||
- Phase 9.77: 進行中(UTF-8エラー修正中、Issue #110)
|
||||
- Phase 10: インタープリター併用戦略・非同期ネイティブ実装追加
|
||||
- インタープリター: 開発だけでなく本番でも実用的(Pythonライク)
|
||||
- ✅ **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調査 の順序
|
||||
================================================================================
|
||||
|
||||
122
docs/予定/native-plan/llvm/APE-Magic-Explained.md
Normal file
122
docs/予定/native-plan/llvm/APE-Magic-Explained.md
Normal file
@ -0,0 +1,122 @@
|
||||
# 🪄 APE (Actually Portable Executable) の魔法を解説!
|
||||
|
||||
**「えっ、1つのファイルが3つのOSで動くの!?」**
|
||||
|
||||
はい、本当です!これは**実在する技術**です!
|
||||
|
||||
## 🎩 **APEの魔法の仕組み**
|
||||
|
||||
### **実例を見てみよう**
|
||||
```bash
|
||||
# これが実際のAPEバイナリ
|
||||
$ ls -la hello.com
|
||||
-rwxr-xr-x 1 user user 65536 Aug 20 hello.com
|
||||
|
||||
# Linuxで実行
|
||||
$ ./hello.com
|
||||
Hello from Linux!
|
||||
|
||||
# 同じファイルをWindowsにコピー
|
||||
> hello.com
|
||||
Hello from Windows!
|
||||
|
||||
# 同じファイルをmacOSで実行
|
||||
$ ./hello.com
|
||||
Hello from macOS!
|
||||
```
|
||||
|
||||
**たった1つのファイル `hello.com` が全部で動く!**
|
||||
|
||||
## 🔮 **どうやって実現してるの?**
|
||||
|
||||
### **秘密:ファイルヘッダーの魔法**
|
||||
|
||||
APEファイルの先頭部分:
|
||||
```
|
||||
00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000 MZ.............. # Windows PE
|
||||
00000010: b800 0000 0000 0000 4000 0000 0000 0000 ........@.......
|
||||
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||
00000030: 0000 0000 0000 0000 0000 0080 0000 0000 ................
|
||||
00000040: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............ # Linux ELF
|
||||
```
|
||||
|
||||
**同じファイルに複数のOSのヘッダーが共存!**
|
||||
|
||||
### **OSごとの読み方**
|
||||
|
||||
1. **Windows**: 「MZ」で始まる → PEファイルとして実行
|
||||
2. **Linux**: ELFマジックナンバーを探す → ELFとして実行
|
||||
3. **macOS**: Mach-Oヘッダーを探す → Mach-Oとして実行
|
||||
|
||||
## 🛠️ **Cosmopolitan Libc - 実在するプロジェクト**
|
||||
|
||||
**GitHubで公開されています!**
|
||||
- https://github.com/jart/cosmopolitan
|
||||
- 開発者: Justine Tunney (元Google)
|
||||
- スター数: 17,000+ ⭐
|
||||
|
||||
### **実際のビルド方法**
|
||||
```bash
|
||||
# Cosmopolitanを使ったビルド
|
||||
gcc -g -O -static \
|
||||
-fno-pie -no-pie \
|
||||
-nostdlib -nostdinc \
|
||||
-o hello.com \
|
||||
hello.c \
|
||||
cosmopolitan.a \
|
||||
-Wl,--gc-sections \
|
||||
-Wl,-T,ape.lds
|
||||
```
|
||||
|
||||
## 📊 **APEの利点と制限**
|
||||
|
||||
### **利点** ✅
|
||||
- **配布が超簡単**: 1ファイルで全OS対応
|
||||
- **依存関係なし**: 完全に自己完結
|
||||
- **小さいサイズ**: 静的リンクでも小さい
|
||||
|
||||
### **制限** ⚠️
|
||||
- **x86_64のみ**: ARM版はまだ実験的
|
||||
- **GUI制限**: 基本的にCLIアプリ向け
|
||||
- **OS固有機能**: 一部制限あり
|
||||
|
||||
## 🎯 **NyashでのAPE活用案**
|
||||
|
||||
### **段階的アプローチ**
|
||||
|
||||
**Phase 1: 通常のマルチターゲット**(現実的)
|
||||
```bash
|
||||
nyashc --targets linux,windows,macos
|
||||
# → 3つの別々のファイル生成
|
||||
```
|
||||
|
||||
**Phase 2: APE実験**(6ヶ月後)
|
||||
```bash
|
||||
nyashc --target ape
|
||||
# → nyash.com (全OS対応の1ファイル!)
|
||||
```
|
||||
|
||||
### **実装イメージ**
|
||||
```rust
|
||||
// NyashのLLVM IR → Cコード生成
|
||||
let c_code = transpile_to_c(&llvm_ir);
|
||||
|
||||
// Cosmopolitanでコンパイル
|
||||
compile_with_cosmopolitan(&c_code, "nyash.com");
|
||||
```
|
||||
|
||||
## 🤔 **本当に必要?**
|
||||
|
||||
**正直な評価**:
|
||||
- **配布簡単さ**: ⭐⭐⭐⭐⭐ 最高!
|
||||
- **実装難易度**: ⭐⭐ 意外と簡単(Cosmopolitan使えば)
|
||||
- **実用性**: ⭐⭐⭐ CLIツールなら十分実用的
|
||||
- **かっこよさ**: ⭐⭐⭐⭐⭐ 最高にクール!
|
||||
|
||||
## 💡 **結論**
|
||||
|
||||
APEは**「欲張り」じゃなくて「賢い」**アプローチ!
|
||||
|
||||
でも、まずは普通のマルチターゲット対応から始めて、APEは「究極の目標」として楽しみに取っておくのが現実的かも?
|
||||
|
||||
**にゃーも「Everything is Box」なら、APEは「Everything is ONE Binary」!**🎩✨
|
||||
151
docs/予定/native-plan/llvm/Hybrid-Future-Vision.md
Normal file
151
docs/予定/native-plan/llvm/Hybrid-Future-Vision.md
Normal file
@ -0,0 +1,151 @@
|
||||
# 🌈 理想的なハイブリッド実行環境への願望
|
||||
|
||||
**「AOT WASMが非同期対応してたら...」**
|
||||
|
||||
## 😿 **現在の苦労ポイント**
|
||||
|
||||
### **各バックエンドの制限**
|
||||
| バックエンド | 利点 | 欠点 |
|
||||
|------------|------|------|
|
||||
| **WASM** | どこでも動く | 非同期が弱い、遅い |
|
||||
| **LLVM** | 超高速 | OS別ビルド必要 |
|
||||
| **VM** | 柔軟 | ネイティブより遅い |
|
||||
| **AOT** | 高速起動 | プラットフォーム依存 |
|
||||
|
||||
### **理想と現実のギャップ**
|
||||
```rust
|
||||
// 理想
|
||||
async fn perfect_world() {
|
||||
let result = await some_io(); // WASMでも高速非同期
|
||||
return result;
|
||||
}
|
||||
|
||||
// 現実
|
||||
fn reality() {
|
||||
// WASMは同期的、非同期は複雑
|
||||
// LLVMは速いけどOS別ビルド
|
||||
// 完璧な解決策がない...
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 **夢のハイブリッド環境**
|
||||
|
||||
### **1. WASM Component Model + AOT**
|
||||
```yaml
|
||||
理想:
|
||||
- WASMの可搬性
|
||||
- AOTの実行速度
|
||||
- ネイティブ非同期サポート
|
||||
- 単一バイナリで全OS対応
|
||||
|
||||
現実:
|
||||
- Component Model仕様策定中
|
||||
- AOT最適化はまだ発展途上
|
||||
- 非同期は部分的サポート
|
||||
```
|
||||
|
||||
### **2. Deno/Bun的アプローチ**
|
||||
```javascript
|
||||
// JavaScriptランタイムの良いとこ取り
|
||||
- V8/JavaScriptCore の JIT性能
|
||||
- ネイティブバインディング
|
||||
- 非同期完全サポート
|
||||
- でもJavaScript...
|
||||
```
|
||||
|
||||
### **3. 究極の理想:Universal Runtime**
|
||||
```rust
|
||||
// もしこんなランタイムがあったら...
|
||||
universal_runtime {
|
||||
// WASMレベルの可搬性
|
||||
portability: "write once, run anywhere",
|
||||
|
||||
// LLVMレベルの性能
|
||||
performance: "near native",
|
||||
|
||||
// 完全な非同期サポート
|
||||
async: "first class",
|
||||
|
||||
// 単一配布物
|
||||
distribution: "single file"
|
||||
}
|
||||
```
|
||||
|
||||
## 💭 **現実的な妥協案**
|
||||
|
||||
### **短期的ハイブリッド戦略**
|
||||
```yaml
|
||||
開発時:
|
||||
- インタープリター(即時実行、デバッグ容易)
|
||||
|
||||
テスト時:
|
||||
- VM(高速、クロスプラットフォーム)
|
||||
|
||||
配布時:
|
||||
選択式:
|
||||
- WASM版: ブラウザ/サーバー両対応
|
||||
- ネイティブ版: 最高性能
|
||||
- ハイブリッド版: WASMランタイム埋め込み
|
||||
```
|
||||
|
||||
### **中期的技術統合**
|
||||
```rust
|
||||
// Nyashハイブリッドランタイム
|
||||
pub enum ExecutionMode {
|
||||
// 高速パス: ネイティブコード
|
||||
Native(LLVMCompiledCode),
|
||||
|
||||
// 互換パス: WASM
|
||||
Wasm(WasmModule),
|
||||
|
||||
// 動的切り替え
|
||||
Adaptive {
|
||||
hot_path: LLVMCompiledCode,
|
||||
cold_path: WasmModule,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔮 **将来への期待**
|
||||
|
||||
### **技術の収束点**
|
||||
1. **WASI Preview 2**: 非同期サポート改善中
|
||||
2. **WASM GC**: メモリ管理効率化
|
||||
3. **Component Model**: 真のモジュラー化
|
||||
4. **AOT最適化**: Wasmtime/WazeroCranelift進化
|
||||
|
||||
### **Nyashの位置づけ**
|
||||
```yaml
|
||||
現在:
|
||||
- 4バックエンド個別対応
|
||||
- それぞれの長所を活かす
|
||||
|
||||
将来:
|
||||
- 統合ランタイム
|
||||
- 動的最適化
|
||||
- 透過的実行モード切り替え
|
||||
```
|
||||
|
||||
## 😊 **でも今でも十分すごい!**
|
||||
|
||||
**現在のNyash**:
|
||||
- ✅ 4つの実行方式を選べる
|
||||
- ✅ 用途に応じて最適化可能
|
||||
- ✅ プラグインシステム完備
|
||||
|
||||
**苦労はあるけど**:
|
||||
- 複数バックエンドの保守
|
||||
- プラットフォーム別の調整
|
||||
- でも**選択肢があることが強み**!
|
||||
|
||||
## 🎯 **結論**
|
||||
|
||||
理想的なハイブリッド環境はまだ存在しないけど、Nyashは**現実的な最良の解**を提供中!
|
||||
|
||||
将来、技術が成熟したら:
|
||||
- WASM AOT + 非同期 = 最強の可搬性
|
||||
- LLVM + WASM統合 = 性能と互換性の両立
|
||||
|
||||
それまでは、**4バックエンドを賢く使い分ける**のが正解!
|
||||
|
||||
**Everything is Box、Every Backend has its Place!**🌈✨
|
||||
149
docs/予定/native-plan/llvm/JIT-vs-AOT-With-MIR.md
Normal file
149
docs/予定/native-plan/llvm/JIT-vs-AOT-With-MIR.md
Normal file
@ -0,0 +1,149 @@
|
||||
# 🤔 JIT vs AOT:MIRがあると難易度が同じ?
|
||||
|
||||
**「MIRできてるから、JITもAOTも同じようなレベルに見えてきた」**
|
||||
|
||||
## 💡 **その洞察、正しいです!**
|
||||
|
||||
### **MIRの存在が変えるゲーム**
|
||||
|
||||
```rust
|
||||
// 従来の難易度
|
||||
Source → Native: 超難しい(全部自分で)
|
||||
Source → JIT: 難しい(実行時コンパイル)
|
||||
|
||||
// MIRがある今
|
||||
Source → MIR → Native: MIRから先は楽!
|
||||
Source → MIR → JIT: MIRから先は楽!
|
||||
```
|
||||
|
||||
## 📊 **JIT vs AOT 比較(MIR前提)**
|
||||
|
||||
| 項目 | JIT | AOT (LLVM) |
|
||||
|------|-----|------------|
|
||||
| **実装難易度** | ⭐⭐⭐ | ⭐⭐⭐ |
|
||||
| **初期実装速度** | 速い | 速い |
|
||||
| **実行時性能** | 80-95% | 100% |
|
||||
| **起動時間** | 遅い | 速い |
|
||||
| **メモリ使用** | 多い | 少ない |
|
||||
| **動的最適化** | ✅ | ❌ |
|
||||
| **配布** | ランタイム必要 | 単体実行可能 |
|
||||
|
||||
**MIRのおかげで、どちらも同じくらいの実装難易度に!**
|
||||
|
||||
## 🚀 **JIT実装の選択肢**
|
||||
|
||||
### **1. VM JIT化(最も現実的)**
|
||||
```rust
|
||||
// 現在のVM
|
||||
match opcode {
|
||||
Add => stack.push(a + b),
|
||||
}
|
||||
|
||||
// JIT化したVM
|
||||
if hot_path {
|
||||
// CraneliftでMIR→ネイティブ
|
||||
let native = cranelift_compile(&mir);
|
||||
execute_native(native);
|
||||
}
|
||||
```
|
||||
|
||||
**利点**:
|
||||
- 既存VMの延長線上
|
||||
- 段階的移行可能
|
||||
- ホットパスのみJIT化
|
||||
|
||||
### **2. 純粋JITコンパイラ**
|
||||
```rust
|
||||
// MIR → Cranelift IR → Native
|
||||
pub fn jit_compile(mir: &MirModule) -> NativeCode {
|
||||
let mut ctx = CraneliftContext::new();
|
||||
for func in &mir.functions {
|
||||
ctx.compile_function(func);
|
||||
}
|
||||
ctx.finalize()
|
||||
}
|
||||
```
|
||||
|
||||
**利点**:
|
||||
- クリーンな設計
|
||||
- 最適化しやすい
|
||||
- デバッグ情報維持
|
||||
|
||||
### **3. LLVM JIT(ORC)**
|
||||
```rust
|
||||
// LLVM ORCでJIT
|
||||
let jit = LLVMOrcJIT::new();
|
||||
jit.add_module(llvm_module);
|
||||
let func = jit.get_function("main");
|
||||
func.call();
|
||||
```
|
||||
|
||||
**利点**:
|
||||
- LLVM最適化の恩恵
|
||||
- AOTとコード共有
|
||||
- 最高性能
|
||||
|
||||
## 🔮 **実装難易度の実際**
|
||||
|
||||
### **AOT (LLVM)**
|
||||
```yaml
|
||||
必要な作業:
|
||||
1. MIR → LLVM IR変換: 2週間
|
||||
2. 型システムマッピング: 1週間
|
||||
3. ランタイム統合: 1週間
|
||||
4. 最適化調整: 1週間
|
||||
合計: 約5週間
|
||||
```
|
||||
|
||||
### **JIT (Cranelift)**
|
||||
```yaml
|
||||
必要な作業:
|
||||
1. MIR → Cranelift IR変換: 2週間
|
||||
2. JITランタイム実装: 1週間
|
||||
3. ホットパス検出: 1週間
|
||||
4. メモリ管理: 1週間
|
||||
合計: 約5週間
|
||||
```
|
||||
|
||||
**ほぼ同じ!MIRのおかげで!**
|
||||
|
||||
## 💭 **どっちを選ぶべき?**
|
||||
|
||||
### **JITが向いている場合**
|
||||
- 長時間実行プログラム
|
||||
- 動的な最適化が必要
|
||||
- REPLやインタラクティブ環境
|
||||
|
||||
### **AOTが向いている場合**
|
||||
- 起動時間重視
|
||||
- 配布の簡単さ重視
|
||||
- 組み込み環境
|
||||
|
||||
### **Nyashの場合**
|
||||
```yaml
|
||||
現実的な選択:
|
||||
1. まずAOT (LLVM) でPoC
|
||||
2. VM最適化を極める
|
||||
3. 将来VM JIT化も追加
|
||||
|
||||
理由:
|
||||
- 配布が簡単(AOT)
|
||||
- 性能も確保(VM既に50倍)
|
||||
- 両方あれば最強
|
||||
```
|
||||
|
||||
## 🎯 **結論**
|
||||
|
||||
**MIRがあるおかげで、JITもAOTも同じくらいの難易度!**
|
||||
|
||||
でも、Nyashの場合:
|
||||
1. **配布の簡単さ** → AOT有利
|
||||
2. **既にVM高速** → JIT緊急度低い
|
||||
3. **将来の拡張性** → 両方実装が理想
|
||||
|
||||
**提案**:
|
||||
- **短期**: LLVM AOT完成(配布重視)
|
||||
- **中期**: VM更なる最適化
|
||||
- **長期**: VM JIT化(最高性能)
|
||||
|
||||
**MIRがあれば、どっちも楽!**🚀
|
||||
119
docs/予定/native-plan/llvm/Practical-Distribution-Strategy.md
Normal file
119
docs/予定/native-plan/llvm/Practical-Distribution-Strategy.md
Normal file
@ -0,0 +1,119 @@
|
||||
# 📦 Nyash実用的配布戦略:現実的なアプローチ
|
||||
|
||||
## 🎯 **配布形態の比較**
|
||||
|
||||
| 方式 | ファイルサイズ | 配布の手間 | 適用範囲 | 実用性 |
|
||||
|------|--------------|-----------|---------|--------|
|
||||
| **個別バイナリ** | 各1-2MB | OS別に配布 | 全アプリ | ⭐⭐⭐⭐⭐ |
|
||||
| **APE** | 3-6MB | 1ファイル | 小規模CLI | ⭐⭐⭐ |
|
||||
| **WASM+ランタイム** | 0.5MB+10MB | ランタイム必要 | 全アプリ | ⭐⭐⭐⭐ |
|
||||
|
||||
## 📊 **現実的な使い分け**
|
||||
|
||||
### **1. メインストリーム配布(推奨)**
|
||||
```bash
|
||||
# OS別の最適化されたバイナリ
|
||||
nyash-linux-x64 (1.5MB) - musl静的リンク
|
||||
nyash-windows.exe (916KB) - mingw最適化
|
||||
nyash-macos (1.8MB) - 署名付き
|
||||
```
|
||||
|
||||
**利点**:
|
||||
- ✅ 各OSで最高性能
|
||||
- ✅ 最小サイズ
|
||||
- ✅ OS固有機能フル活用
|
||||
- ✅ 大規模アプリも対応
|
||||
|
||||
### **2. 開発者向け配布**
|
||||
```bash
|
||||
# LLVM IRの中立性を活用
|
||||
nyashc --emit-bitcode program.nyash
|
||||
# → program.bc (プラットフォーム中立)
|
||||
|
||||
# 各自のマシンで最適化コンパイル
|
||||
nyashc --from-bitcode program.bc --target native
|
||||
```
|
||||
|
||||
### **3. 特殊用途でのAPE**
|
||||
```bash
|
||||
# 小さなツール限定
|
||||
nyash-fmt.com # コードフォーマッター (2MB)
|
||||
nyash-lint.com # リンター (3MB)
|
||||
nyash-repl.com # REPL (4MB)
|
||||
```
|
||||
|
||||
**APEが向いている場合**:
|
||||
- 単体で動くCLIツール
|
||||
- 依存ライブラリが少ない
|
||||
- 配布の簡単さが最優先
|
||||
|
||||
**APEが向いていない場合**:
|
||||
- GUIアプリケーション
|
||||
- 大量のライブラリ依存
|
||||
- プラグインシステム
|
||||
- ゲームなど大規模アプリ
|
||||
|
||||
## 🚀 **段階的実装計画(修正版)**
|
||||
|
||||
### **Phase 1: 基本マルチターゲット**(1ヶ月)
|
||||
```bash
|
||||
nyashc build --target linux
|
||||
nyashc build --target windows
|
||||
# 個別にビルド、確実に動作
|
||||
```
|
||||
|
||||
### **Phase 2: 同時生成最適化**(3ヶ月)
|
||||
```bash
|
||||
nyashc build --all-targets
|
||||
# Bitcodeキャッシュで高速化
|
||||
# 並列ビルドで時間短縮
|
||||
```
|
||||
|
||||
### **Phase 3: 配布自動化**(6ヶ月)
|
||||
```bash
|
||||
nyashc release
|
||||
# 出力:
|
||||
# - dist/nyash-v1.0-linux-x64.tar.gz
|
||||
# - dist/nyash-v1.0-windows-x64.zip
|
||||
# - dist/nyash-v1.0-macos.dmg
|
||||
# - dist/nyash-tools.com (APE版ツール集)
|
||||
```
|
||||
|
||||
## 💡 **賢い配布戦略**
|
||||
|
||||
### **メインアプリ**: 個別最適化バイナリ
|
||||
```yaml
|
||||
nyash本体:
|
||||
Linux: 1.5MB (musl静的)
|
||||
Windows: 916KB (mingw)
|
||||
macOS: 1.8MB (universal)
|
||||
```
|
||||
|
||||
### **開発ツール**: APEで統一
|
||||
```yaml
|
||||
開発者ツール(APE):
|
||||
nyash-fmt.com: 2MB
|
||||
nyash-test.com: 3MB
|
||||
nyash-bench.com: 2.5MB
|
||||
```
|
||||
|
||||
### **プラグイン**: 動的ライブラリ
|
||||
```yaml
|
||||
プラグイン(各OS別):
|
||||
filebox.so: 200KB (Linux)
|
||||
filebox.dll: 180KB (Windows)
|
||||
filebox.dylib: 220KB (macOS)
|
||||
```
|
||||
|
||||
## 🎉 **結論**
|
||||
|
||||
**「適材適所」が最強の戦略!**
|
||||
|
||||
- **大規模アプリ**: 個別最適化バイナリ
|
||||
- **小規模ツール**: APEで配布簡略化
|
||||
- **開発者向け**: Bitcodeで柔軟性確保
|
||||
|
||||
APEは「魔法」だけど、現実的には**限定的な用途**で輝く技術。
|
||||
Nyashのメイン配布は**堅実な個別バイナリ**で行きましょう!
|
||||
|
||||
**Everything is Box、でも配布は現実的に!**📦✨
|
||||
169
docs/予定/native-plan/llvm/Revolutionary-Windows-Strategy.md
Normal file
169
docs/予定/native-plan/llvm/Revolutionary-Windows-Strategy.md
Normal file
@ -0,0 +1,169 @@
|
||||
# 🚀 Nyash革命的Windows実行戦略:LLVM IR中立性の完全活用
|
||||
|
||||
**作成日**: 2025年8月20日
|
||||
**AI会議参加者**: Gemini先生、Codex先生、Claude
|
||||
|
||||
## 🎯 **核心的アイデア:1回のIR生成で全プラットフォーム対応**
|
||||
|
||||
LLVM IRはプラットフォーム中立。だから**1回のIR生成から同時に複数OS用の実行ファイルを生成できる!**
|
||||
|
||||
```rust
|
||||
// 革命的ワンパス・マルチターゲット生成
|
||||
nyashc --targets linux,windows,macos program.nyash
|
||||
|
||||
// 出力(同時生成!)
|
||||
dist/x86_64-unknown-linux-musl/nyash # Linux版
|
||||
dist/x86_64-pc-windows-gnu/nyash.exe # Windows版
|
||||
dist/x86_64-apple-darwin/nyash # macOS版
|
||||
```
|
||||
|
||||
## 🏗️ **実装アーキテクチャ**
|
||||
|
||||
### **Phase 1: 即効性重視(3週間で実現)**
|
||||
|
||||
```rust
|
||||
// 1. IR生成(1回だけ)
|
||||
let ir_module = compile_to_ir(&ast);
|
||||
let bitcode = ir_module.write_bitcode_to_memory();
|
||||
|
||||
// 2. マルチターゲット並列生成
|
||||
parallel_for_each(["linux", "windows-gnu"], |target| {
|
||||
let module = context.create_module_from_ir(bitcode.clone());
|
||||
configure_for_target(&module, target);
|
||||
generate_executable(&module, target);
|
||||
});
|
||||
```
|
||||
|
||||
**技術スタック**:
|
||||
- Linux: musl静的リンク(配布容易)
|
||||
- Windows: mingw-gnu + lld(クロスリンク簡単)
|
||||
- 共通: PAL (Platform Abstraction Layer)
|
||||
|
||||
### **Phase 2: 本格実装(3ヶ月)**
|
||||
|
||||
**全プラットフォーム同時対応**:
|
||||
```yaml
|
||||
ターゲット構成:
|
||||
linux:
|
||||
- x86_64-unknown-linux-musl
|
||||
- aarch64-unknown-linux-musl
|
||||
windows:
|
||||
- x86_64-pc-windows-gnu (mingw)
|
||||
- x86_64-pc-windows-msvc (xwin)
|
||||
macos:
|
||||
- x86_64-apple-darwin
|
||||
- aarch64-apple-darwin (M1/M2)
|
||||
```
|
||||
|
||||
### **Phase 3: 究極形態(6ヶ月)**
|
||||
|
||||
**APE (Actually Portable Executable) - 単一バイナリで全OS対応!**
|
||||
```bash
|
||||
# たった1つのファイルが全OSで動く!
|
||||
./nyash.com # Linux でも Windows でも macOS でも動作!
|
||||
```
|
||||
|
||||
**⚠️ APEの現実的な制限**:
|
||||
- バイナリサイズ: 通常の**3倍**(3OS分のコード含む)
|
||||
- ライブラリ: 各OS用に3種類必要
|
||||
- 適用範囲: **小規模CLIツール向け**(大規模アプリは不向き)
|
||||
|
||||
## 💡 **技術的革新ポイント**
|
||||
|
||||
### **1. Bitcodeキャッシュ戦略**
|
||||
```rust
|
||||
pub struct MultiTargetCompiler {
|
||||
bitcode_cache: HashMap<ModuleId, MemoryBuffer>,
|
||||
target_machines: HashMap<Triple, TargetMachine>,
|
||||
}
|
||||
|
||||
impl MultiTargetCompiler {
|
||||
pub fn compile_all(&self, module_id: ModuleId) -> Result<Vec<ExecutablePath>> {
|
||||
let bitcode = self.bitcode_cache.get(&module_id).unwrap();
|
||||
|
||||
self.target_machines
|
||||
.par_iter() // 並列処理!
|
||||
.map(|(triple, tm)| {
|
||||
let module = load_from_bitcode(bitcode);
|
||||
tm.emit_to_file(&module, FileType::Object)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **2. PAL (Platform Abstraction Layer)**
|
||||
```rust
|
||||
// コンパイラは常にこれらを呼ぶ
|
||||
extern "C" {
|
||||
fn nyash_rt_print(s: *const u8, len: usize);
|
||||
fn nyash_rt_file_open(path: *const u8, mode: u32) -> i32;
|
||||
fn nyash_rt_time_now() -> u64;
|
||||
}
|
||||
|
||||
// 各OS用のランタイムで実装
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn nyash_rt_print(s: *const u8, len: usize) {
|
||||
// UTF-8 → UTF-16変換してWriteConsoleW
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn nyash_rt_print(s: *const u8, len: usize) {
|
||||
// そのままwrite(1, s, len)
|
||||
}
|
||||
```
|
||||
|
||||
### **3. リンク戦略の統一**
|
||||
```toml
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
lld = { version = "0.1", features = ["coff"] }
|
||||
mingw-w64-libs = { path = "vendor/mingw" }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
lld = { version = "0.1", features = ["elf"] }
|
||||
musl-libc = { path = "vendor/musl" }
|
||||
```
|
||||
|
||||
## 🎉 **革命的成果**
|
||||
|
||||
### **開発者体験**
|
||||
```bash
|
||||
# 1コマンドで全プラットフォーム対応!
|
||||
nyashc build --all-platforms
|
||||
|
||||
# 出力
|
||||
✅ Linux版生成完了 (2.1MB)
|
||||
✅ Windows版生成完了 (916KB)
|
||||
✅ macOS版生成完了 (1.8MB)
|
||||
✅ WASM版生成完了 (512KB)
|
||||
```
|
||||
|
||||
### **ユーザー体験**
|
||||
- **配布**: 各OS用のネイティブバイナリ
|
||||
- **性能**: LLVM最適化でVM比10倍以上高速
|
||||
- **将来**: APEで単一ファイル配布
|
||||
|
||||
## 📊 **実装ロードマップ**
|
||||
|
||||
| フェーズ | 期間 | 成果物 |
|
||||
|---------|------|--------|
|
||||
| Week 1-3 | LLVM PoC | Linux単体動作 |
|
||||
| Month 1 | Windows統合 | Linux + Windows同時生成 |
|
||||
| Month 2 | 全OS対応 | Linux/Windows/macOS |
|
||||
| Month 3 | 最適化 | PAL完成、性能調整 |
|
||||
| Month 6 | APE統合 | 単一バイナリ実現 |
|
||||
|
||||
## 🚀 **次のアクション**
|
||||
|
||||
1. **即実装**: Bitcodeキャッシュ機構
|
||||
2. **PAL設計**: 最小限のランタイムAPI定義
|
||||
3. **Windows-gnu**: mingwでクロスリンク環境構築
|
||||
4. **並列化**: rayon使用でマルチターゲット生成
|
||||
|
||||
## 💭 **結論**
|
||||
|
||||
LLVM IRの中立性を活用すれば、**「Write Once, Compile to All」**が実現できる!
|
||||
|
||||
これこそがNyashの革命的Windows戦略です。1回のコンパイルで全プラットフォーム対応、最終的には単一バイナリで境界を超える。
|
||||
|
||||
**Everything is Box、そしてEvery Platform is Target!**🎯
|
||||
155
docs/予定/native-plan/llvm/VM-Native-Speed-Possibility.md
Normal file
155
docs/予定/native-plan/llvm/VM-Native-Speed-Possibility.md
Normal file
@ -0,0 +1,155 @@
|
||||
# 🚀 Nyash VM をネイティブ速度に近づける可能性
|
||||
|
||||
**「もしかして、VM完璧に作ればネイティブに近づける?」**
|
||||
|
||||
## 💡 **その直感、正しいです!**
|
||||
|
||||
### **現在のVM性能**
|
||||
- インタープリター比: **50.94倍高速**(達成済み!)
|
||||
- でもLLVMネイティブには及ばない...はず?
|
||||
|
||||
### **でも待って、よく考えると...**
|
||||
|
||||
## 🔥 **VMがネイティブに迫れる理由**
|
||||
|
||||
### **1. JITコンパイルの可能性**
|
||||
```rust
|
||||
// 現在: バイトコード実行
|
||||
match opcode {
|
||||
Add => stack.push(a + b),
|
||||
// ...
|
||||
}
|
||||
|
||||
// 将来: ホットパスをネイティブコードに!
|
||||
if execution_count > HOT_THRESHOLD {
|
||||
let native_code = jit_compile(&bytecode);
|
||||
execute_native(native_code); // ほぼネイティブ速度!
|
||||
}
|
||||
```
|
||||
|
||||
### **2. 最適化の余地がまだある**
|
||||
```yaml
|
||||
現在のVM最適化:
|
||||
✅ デバッグ出力削除
|
||||
✅ HashMap → Vec
|
||||
✅ メモリ効率化
|
||||
|
||||
まだできること:
|
||||
- レジスタVM化(スタックVM → レジスタVM)
|
||||
- インライン展開
|
||||
- 定数畳み込み
|
||||
- ループ最適化
|
||||
- SIMD活用
|
||||
```
|
||||
|
||||
### **3. 言語特性を活かした最適化**
|
||||
```rust
|
||||
// Nyashの特徴を利用
|
||||
- Everything is Box → 型情報を活用した特殊化
|
||||
- Arc<Mutex>パターン → 最適化可能な箇所を特定
|
||||
- 限定的な言語機能 → 積極的な最適化
|
||||
```
|
||||
|
||||
## 📊 **他言語VMの実績**
|
||||
|
||||
| VM | 対ネイティブ性能 | 特徴 |
|
||||
|----|----------------|------|
|
||||
| **JVM (HotSpot)** | 80-95% | JIT最適化の極致 |
|
||||
| **V8 (JavaScript)** | 70-90% | 型推論+インライン |
|
||||
| **PyPy** | 400-700% (CPython比) | トレーシングJIT |
|
||||
| **LuaJIT** | 90-99% | 超軽量JIT |
|
||||
|
||||
**LuaJITは特に注目**: シンプルな言語 + 優れたJIT = ほぼネイティブ!
|
||||
|
||||
## 🎯 **Nyash VMネイティブ化戦略**
|
||||
|
||||
### **Phase 1: 基礎最適化(現在〜1ヶ月)**
|
||||
```rust
|
||||
// レジスタVM化
|
||||
enum VMRegister {
|
||||
R0, R1, R2, R3, // ... R15
|
||||
}
|
||||
|
||||
// より効率的な命令セット
|
||||
enum Instruction {
|
||||
LoadReg(VMRegister, Value),
|
||||
AddReg(VMRegister, VMRegister, VMRegister),
|
||||
// スタック操作を削減
|
||||
}
|
||||
```
|
||||
|
||||
### **Phase 2: プロファイル駆動最適化(2-3ヶ月)**
|
||||
```rust
|
||||
struct HotPath {
|
||||
bytecode: Vec<Instruction>,
|
||||
execution_count: u64,
|
||||
optimized_version: Option<OptimizedCode>,
|
||||
}
|
||||
|
||||
// ホットパスを検出して最適化
|
||||
if hot_path.execution_count > 1000 {
|
||||
optimize_hot_path(&mut hot_path);
|
||||
}
|
||||
```
|
||||
|
||||
### **Phase 3: 軽量JIT(6ヶ月)**
|
||||
```rust
|
||||
// Cranelift使用で軽量JIT実装
|
||||
use cranelift::prelude::*;
|
||||
|
||||
fn jit_compile(bytecode: &[Instruction]) -> NativeCode {
|
||||
let mut ctx = Context::new();
|
||||
// バイトコード → Cranelift IR → ネイティブ
|
||||
compile_to_native(&mut ctx, bytecode)
|
||||
}
|
||||
```
|
||||
|
||||
## 🔮 **実現可能な性能目標**
|
||||
|
||||
### **段階的目標**
|
||||
1. **現在**: インタープリター比 50倍
|
||||
2. **Phase 1完了**: 100倍(レジスタVM化)
|
||||
3. **Phase 2完了**: 200倍(最適化)
|
||||
4. **Phase 3完了**: **ネイティブの80-90%**(JIT)
|
||||
|
||||
### **なぜ可能か?**
|
||||
- Nyashはシンプルな言語
|
||||
- Box型システムで最適化しやすい
|
||||
- 既に50倍達成の実績
|
||||
- MIR基盤が整っている
|
||||
|
||||
## 💭 **VM vs LLVM の最終形**
|
||||
|
||||
```yaml
|
||||
Nyash VM (完全体):
|
||||
利点:
|
||||
- ポータビリティ完璧
|
||||
- 起動時間高速
|
||||
- 動的最適化可能
|
||||
- デバッグ容易
|
||||
性能: ネイティブの80-90%
|
||||
|
||||
LLVM AOT:
|
||||
利点:
|
||||
- 最高性能(100%)
|
||||
- 事前最適化
|
||||
- 配布サイズ小
|
||||
欠点:
|
||||
- プラットフォーム別ビルド
|
||||
- 起動時最適化なし
|
||||
```
|
||||
|
||||
## 🎉 **結論:VMでもいける!**
|
||||
|
||||
**完璧に作れば、VMでもネイティブに迫れます!**
|
||||
|
||||
特にNyashのような:
|
||||
- シンプルな言語
|
||||
- 明確な型システム(Everything is Box)
|
||||
- 限定的な機能セット
|
||||
|
||||
これらの特徴は**VMの高速化に有利**!
|
||||
|
||||
**もしかしたら、LLVM要らないかも...?**(いや、両方あると最強!)
|
||||
|
||||
**Everything is Box、VM can be Native-Fast!**🚀✨
|
||||
91
docs/予定/native-plan/llvm/Windows-Strategy-Summary.md
Normal file
91
docs/予定/native-plan/llvm/Windows-Strategy-Summary.md
Normal file
@ -0,0 +1,91 @@
|
||||
# 🪟 Windows同時作戦の現状まとめ
|
||||
|
||||
**更新日**: 2025年8月20日
|
||||
|
||||
## 📊 **現在の状況**
|
||||
|
||||
### **✅ 完了したこと**
|
||||
1. **AI大会議実施**
|
||||
- Gemini先生: 4つの革命的戦略提案
|
||||
- Codex先生: 技術的実装方法の詳細化
|
||||
|
||||
2. **戦略文書作成**
|
||||
- Revolutionary-Windows-Strategy.md: 統合戦略
|
||||
- APE-Magic-Explained.md: 単一バイナリ技術解説
|
||||
- Practical-Distribution-Strategy.md: 現実的配布方法
|
||||
|
||||
3. **技術的方針決定**
|
||||
- **核心**: LLVM IRの中立性を活用した同時生成
|
||||
- **方法**: Bitcodeキャッシュ + 並列ターゲット生成
|
||||
|
||||
### **🚀 実装計画**
|
||||
|
||||
#### **即効性のある解決策(Week 1-3)**
|
||||
```bash
|
||||
# Linux + Windows同時生成
|
||||
nyashc --targets linux,windows-gnu program.nyash
|
||||
|
||||
# 出力
|
||||
dist/linux/nyash # Linux版(musl静的)
|
||||
dist/windows/nyash.exe # Windows版(mingw)
|
||||
```
|
||||
|
||||
**実装手順**:
|
||||
1. Week 1: Linux版LLVM実装(進行中)
|
||||
2. Week 2: Bitcodeキャッシュ機構追加
|
||||
3. Week 3: Windows-gnu同時生成
|
||||
|
||||
#### **中期計画(1-3ヶ月)**
|
||||
- 全プラットフォーム同時対応
|
||||
- PAL (Platform Abstraction Layer) 完成
|
||||
- 最適化とテスト
|
||||
|
||||
## 🛠️ **技術的アプローチ**
|
||||
|
||||
### **1. ワンパス・マルチターゲット**
|
||||
```rust
|
||||
// 1回のIR生成
|
||||
let bitcode = module.write_bitcode_to_memory();
|
||||
|
||||
// 並列で各OS向け生成
|
||||
["linux", "windows-gnu", "macos"].par_iter()
|
||||
.map(|target| generate_for_target(bitcode.clone(), target))
|
||||
.collect()
|
||||
```
|
||||
|
||||
### **2. Windows特化戦略**
|
||||
- **短期**: mingw-gnu(クロスコンパイル簡単)
|
||||
- **長期**: msvc対応(xwin使用)
|
||||
- **配布**: 916KBの小さな実行ファイル
|
||||
|
||||
### **3. 段階的実装**
|
||||
| Phase | 期間 | 成果 |
|
||||
|-------|------|------|
|
||||
| 現在 | LLVM PoC | Linux単体 |
|
||||
| Week 3 | 同時生成 | Linux + Windows |
|
||||
| Month 1 | 全OS | +macOS |
|
||||
| Month 3 | 最適化 | PAL完成 |
|
||||
|
||||
## 💡 **重要ポイント**
|
||||
|
||||
### **すぐに実現可能なこと**
|
||||
- ✅ Linux/Windows同時ビルド(mingw使用)
|
||||
- ✅ 1つのコマンドで両OS対応
|
||||
- ✅ Bitcodeレベルでの共有
|
||||
|
||||
### **将来の野望**
|
||||
- 🎯 全OS同時生成
|
||||
- 🎯 APE単一バイナリ(小ツール用)
|
||||
- 🎯 完全なクロスプラットフォーム
|
||||
|
||||
## 🎉 **結論**
|
||||
|
||||
**Windows同時作戦は技術的に実現可能!**
|
||||
|
||||
1. **LLVM IRの中立性**を最大活用
|
||||
2. **Bitcodeキャッシュ**で効率化
|
||||
3. **mingw**で即座にWindows対応
|
||||
|
||||
Copilotが基本LLVM実装を進めている間に、我々は革命的な同時生成戦略を準備完了!
|
||||
|
||||
**Everything is Box、Every Platform is Target!**🎯✨
|
||||
@ -1,135 +0,0 @@
|
||||
# 📦 Nyash Box設計ドキュメント
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
Nyashの核心哲学「**Everything is Box**」に関する完全な設計ドキュメント集。
|
||||
言語設計の根幹から実装詳細まで、Box設計のすべてを網羅しています。
|
||||
|
||||
## 📚 ドキュメント構成
|
||||
|
||||
### 🌟 設計思想
|
||||
|
||||
#### [everything-is-box.md](everything-is-box.md)
|
||||
Nyashの核心哲学「Everything is Box」の完全解説。なぜすべてをBoxにするのか、その設計思想と利点を説明。
|
||||
|
||||
#### [box-types-catalog.md](box-types-catalog.md)
|
||||
Nyashで利用可能な全Box型のカタログ。基本型(StringBox, IntegerBox)から高度な型(P2PBox, EguiBox)まで。
|
||||
|
||||
### 🔄 システム設計
|
||||
|
||||
#### [delegation-system.md](delegation-system.md)
|
||||
完全明示デリゲーションシステムの設計。`from`構文、`override`必須、`pack`構文の詳細仕様。
|
||||
|
||||
#### [memory-management.md](memory-management.md)
|
||||
Arc<Mutex>一元管理、fini()システム、weak参照による循環参照回避の設計原則。
|
||||
|
||||
### 🌐 外部連携
|
||||
|
||||
#### [ffi-abi-specification.md](ffi-abi-specification.md)
|
||||
Box FFI/ABI完全仕様。外部ライブラリを「箱に詰める」ための統一インターフェース。
|
||||
|
||||
#### FileBox マッピング
|
||||
- [filebox-bid-mapping.md](filebox-bid-mapping.md) — Nyash APIとBID-FFIプラグインABIの対応表(メソッドID/TLV/戻り値)
|
||||
|
||||
### 🔧 実装ノート
|
||||
|
||||
#### [implementation-notes/](implementation-notes/)
|
||||
開発者向けの実装詳細、既知の問題、進行中の設計変更などの技術情報。
|
||||
|
||||
- [current-issues.md](implementation-notes/current-issues.md) - 現在対応中の設計課題
|
||||
- [socket-box-problem.md](implementation-notes/socket-box-problem.md) - Arc<Mutex>二重化問題の詳細分析
|
||||
- [phase-9-75-redesign.md](implementation-notes/phase-9-75-redesign.md) - Box設計根本革命の実装計画
|
||||
|
||||
## 🎨 設計原則
|
||||
|
||||
### 1. **Everything is Box**
|
||||
すべての値がBoxオブジェクト。プリミティブ型は存在しない。
|
||||
|
||||
### 2. **明示性重視**
|
||||
暗黙的な動作を避け、すべてを明示的に記述。
|
||||
|
||||
### 3. **Arc<Mutex>一元管理**
|
||||
Box内部でのロックを避け、インタープリターが一元管理。
|
||||
|
||||
### 4. **メモリ安全性**
|
||||
fini()システムとweak参照による確実なメモリ管理。
|
||||
|
||||
## 🚀 クイックリファレンス
|
||||
|
||||
### Box作成
|
||||
```nyash
|
||||
// 基本型
|
||||
local str = new StringBox("Hello")
|
||||
local num = new IntegerBox(42)
|
||||
|
||||
// ユーザー定義Box
|
||||
box User {
|
||||
init { name, email }
|
||||
|
||||
birth(userName, userEmail) {
|
||||
me.name = userName
|
||||
me.email = userEmail
|
||||
print("🌟 User " + userName + " が誕生しました!")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### デリゲーション
|
||||
```nyash
|
||||
box AdminUser from User {
|
||||
init { permissions }
|
||||
|
||||
birth(adminName, adminEmail, perms) {
|
||||
from User.birth(adminName, adminEmail)
|
||||
me.permissions = perms
|
||||
}
|
||||
|
||||
override toString() {
|
||||
return "Admin: " + from User.toString()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ビルトインBox継承(pack専用)
|
||||
```nyash
|
||||
// ビルトインBoxを継承する場合のみpackを使用
|
||||
box EnhancedP2P from P2PBox {
|
||||
init { features }
|
||||
|
||||
pack(nodeId, transport) {
|
||||
from P2PBox.pack(nodeId, transport) // ビルトイン初期化
|
||||
me.features = new ArrayBox()
|
||||
}
|
||||
|
||||
override send(intent, data, target) {
|
||||
me.features.push("send:" + intent)
|
||||
return from P2PBox.send(intent, data, target)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 外部ライブラリ統合(FFI/ABI)
|
||||
```nyash
|
||||
// ExternBoxで外部APIを統一的に利用
|
||||
local console = new ExternBox("console")
|
||||
console.call("log", "Hello from Nyash!")
|
||||
|
||||
local canvas = new ExternBox("canvas")
|
||||
canvas.call("fillRect", 10, 10, 100, 50)
|
||||
```
|
||||
|
||||
## 📖 関連ドキュメント
|
||||
|
||||
- [言語リファレンス](../language-reference.md)
|
||||
- [ビルトインBox一覧](../builtin-boxes.md)
|
||||
- [実装ガイド](../../../../CLAUDE.md)
|
||||
- [開発計画](../../../../予定/native-plan/copilot_issues.txt)
|
||||
|
||||
## 🔄 更新履歴
|
||||
|
||||
- 2025-08-14: Box設計ドキュメント初版作成
|
||||
- 2025-08-14: Phase 9.75(Arc<Mutex>責務一元化)対応開始
|
||||
|
||||
---
|
||||
|
||||
最終更新: 2025-08-14
|
||||
@ -1,286 +0,0 @@
|
||||
# 📦 Nyash Box型カタログ
|
||||
|
||||
## 📋 概要
|
||||
|
||||
Nyashで利用可能なすべてのBox型の完全カタログです。
|
||||
各Box型の用途、API、使用例を網羅しています。
|
||||
|
||||
## 🏗️ Box型の分類
|
||||
|
||||
### 📊 基本型Box(Primitive Boxes)
|
||||
|
||||
#### StringBox
|
||||
文字列を扱う基本Box型。
|
||||
|
||||
```nyash
|
||||
local str = "Hello, Nyash!" // 自動的にStringBox
|
||||
local explicit = new StringBox("Explicit creation")
|
||||
|
||||
// メソッド
|
||||
str.length() // 文字数を取得
|
||||
str.toUpperCase() // 大文字変換
|
||||
str.split(",") // 文字列分割
|
||||
str.contains("Nya") // 部分文字列検索
|
||||
```
|
||||
|
||||
#### IntegerBox
|
||||
整数を扱う基本Box型。
|
||||
|
||||
```nyash
|
||||
local num = 42 // 自動的にIntegerBox
|
||||
local big = new IntegerBox(1000000)
|
||||
|
||||
// メソッド
|
||||
num.add(10) // 加算
|
||||
num.multiply(2) // 乗算
|
||||
num.toString() // 文字列変換
|
||||
num.isEven() // 偶数判定
|
||||
```
|
||||
|
||||
#### FloatBox
|
||||
浮動小数点数を扱うBox型。
|
||||
|
||||
```nyash
|
||||
local pi = 3.14159 // 自動的にFloatBox
|
||||
local precise = new FloatBox(2.718281828)
|
||||
|
||||
// メソッド
|
||||
pi.round(2) // 小数点以下2桁に丸める
|
||||
pi.ceil() // 切り上げ
|
||||
pi.floor() // 切り下げ
|
||||
```
|
||||
|
||||
#### BoolBox
|
||||
真偽値を扱うBox型。
|
||||
|
||||
```nyash
|
||||
local flag = true // 自動的にBoolBox
|
||||
local condition = new BoolBox(false)
|
||||
|
||||
// メソッド
|
||||
flag.not() // 論理反転
|
||||
flag.and(condition) // 論理AND
|
||||
flag.or(condition) // 論理OR
|
||||
```
|
||||
|
||||
#### NullBox
|
||||
null値を表すBox型。
|
||||
|
||||
```nyash
|
||||
local nothing = null // 自動的にNullBox
|
||||
|
||||
// メソッド
|
||||
nothing.isNull() // 常にtrue
|
||||
nothing.toString() // "null"
|
||||
```
|
||||
|
||||
### 📚 コレクション型Box(Collection Boxes)
|
||||
|
||||
#### ArrayBox
|
||||
動的配列を扱うBox型。
|
||||
|
||||
```nyash
|
||||
local arr = new ArrayBox()
|
||||
arr.push(1)
|
||||
arr.push(2)
|
||||
arr.push(3)
|
||||
|
||||
// メソッド
|
||||
arr.length() // 要素数
|
||||
arr.get(0) // インデックスアクセス
|
||||
arr.set(1, 42) // 要素設定
|
||||
arr.pop() // 末尾削除
|
||||
arr.slice(1, 3) // 部分配列
|
||||
arr.forEach(callback) // 反復処理
|
||||
```
|
||||
|
||||
#### MapBox
|
||||
キー・値ペアを扱う連想配列Box型。
|
||||
|
||||
```nyash
|
||||
local map = new MapBox()
|
||||
map.set("name", "Nyash")
|
||||
map.set("version", "1.0")
|
||||
|
||||
// メソッド
|
||||
map.get("name") // 値取得
|
||||
map.has("version") // キー存在確認
|
||||
map.keys() // 全キー取得
|
||||
map.values() // 全値取得
|
||||
map.forEach(callback) // 反復処理
|
||||
```
|
||||
|
||||
### 🖥️ システムBox(System Boxes)
|
||||
|
||||
#### ConsoleBox
|
||||
コンソール入出力を扱うBox型。
|
||||
|
||||
```nyash
|
||||
local console = new ConsoleBox()
|
||||
|
||||
// メソッド
|
||||
console.log("Hello!") // 標準出力
|
||||
console.error("Error!") // エラー出力
|
||||
console.read() // 標準入力
|
||||
console.clear() // 画面クリア
|
||||
```
|
||||
|
||||
#### FileBox
|
||||
ファイル操作を扱うBox型。
|
||||
|
||||
```nyash
|
||||
local file = new FileBox("data.txt")
|
||||
|
||||
// メソッド
|
||||
file.read() // ファイル読み込み
|
||||
file.write("content") // ファイル書き込み
|
||||
file.append("more") // 追記
|
||||
file.exists() // 存在確認
|
||||
file.delete() // 削除
|
||||
```
|
||||
|
||||
#### TimeBox
|
||||
時刻・日付を扱うBox型。
|
||||
|
||||
```nyash
|
||||
local time = new TimeBox()
|
||||
|
||||
// メソッド
|
||||
time.now() // 現在時刻
|
||||
time.format("YYYY-MM-DD") // フォーマット
|
||||
time.add(1, "day") // 日付計算
|
||||
time.diff(otherTime) // 時間差
|
||||
```
|
||||
|
||||
#### MathBox
|
||||
数学関数を提供するBox型。
|
||||
|
||||
```nyash
|
||||
local math = new MathBox()
|
||||
|
||||
// メソッド
|
||||
math.sqrt(16) // 平方根
|
||||
math.pow(2, 10) // 累乗
|
||||
math.sin(math.PI / 2) // 三角関数
|
||||
math.random() // 乱数
|
||||
```
|
||||
|
||||
### 🌐 ネットワークBox(Network Boxes)
|
||||
|
||||
#### SocketBox
|
||||
TCP/UDPソケット通信を扱うBox型。
|
||||
|
||||
```nyash
|
||||
// サーバー
|
||||
local server = new SocketBox()
|
||||
server.bind("0.0.0.0", 8080)
|
||||
server.listen(10)
|
||||
local client = server.accept()
|
||||
|
||||
// クライアント
|
||||
local client = new SocketBox()
|
||||
client.connect("localhost", 8080)
|
||||
client.write("Hello")
|
||||
```
|
||||
|
||||
#### HTTPServerBox
|
||||
HTTPサーバー機能を提供するBox型。
|
||||
|
||||
```nyash
|
||||
local server = new HTTPServerBox()
|
||||
server.bind("0.0.0.0", 3000)
|
||||
server.route("/", handler)
|
||||
server.start()
|
||||
```
|
||||
|
||||
#### P2PBox
|
||||
P2P通信を実現するBox型。
|
||||
|
||||
```nyash
|
||||
local node = new P2PBox("node1", "testnet")
|
||||
node.connect()
|
||||
node.send("broadcast", data)
|
||||
node.onReceive(handler)
|
||||
```
|
||||
|
||||
### 🎨 GUI Box(GUI Boxes)
|
||||
|
||||
#### EguiBox
|
||||
GUIアプリケーション作成用Box型。
|
||||
|
||||
```nyash
|
||||
local app = new EguiBox()
|
||||
app.setTitle("My App")
|
||||
app.setSize(800, 600)
|
||||
app.addButton("Click me", callback)
|
||||
// app.run() // メインスレッド制約
|
||||
```
|
||||
|
||||
### 🔌 特殊Box(Special Boxes)
|
||||
|
||||
#### FutureBox
|
||||
非同期処理を扱うBox型。
|
||||
|
||||
```nyash
|
||||
local future = new FutureBox(asyncTask)
|
||||
future.then(onSuccess)
|
||||
future.catch(onError)
|
||||
future.await() // 同期的に待機
|
||||
```
|
||||
|
||||
#### WeakBox
|
||||
弱参照を提供するBox型。
|
||||
|
||||
```nyash
|
||||
local weak = new WeakBox(target)
|
||||
local strong = weak.upgrade() // 通常参照に変換
|
||||
if strong != null {
|
||||
// targetはまだ生きている
|
||||
}
|
||||
```
|
||||
|
||||
#### ExternBox
|
||||
外部ライブラリ統合用Box型。
|
||||
|
||||
```nyash
|
||||
local console = new ExternBox("console")
|
||||
console.call("log", "External API call")
|
||||
|
||||
local dom = new ExternBox("document")
|
||||
dom.call("getElementById", "myDiv")
|
||||
```
|
||||
|
||||
#### DebugBox
|
||||
デバッグ支援機能を提供するBox型。
|
||||
|
||||
```nyash
|
||||
local debug = new DebugBox()
|
||||
debug.startTracking()
|
||||
debug.trackBox(myObject, "My Object")
|
||||
print(debug.memoryReport())
|
||||
```
|
||||
|
||||
## 🚀 Box型の選び方
|
||||
|
||||
### 用途別ガイド
|
||||
- **テキスト処理**: StringBox
|
||||
- **数値計算**: IntegerBox, FloatBox, MathBox
|
||||
- **データ構造**: ArrayBox, MapBox
|
||||
- **I/O操作**: ConsoleBox, FileBox
|
||||
- **ネットワーク**: SocketBox, HTTPServerBox, P2PBox
|
||||
- **GUI**: EguiBox
|
||||
- **非同期**: FutureBox
|
||||
- **メモリ管理**: WeakBox, DebugBox
|
||||
|
||||
### パフォーマンス考慮
|
||||
- 基本型は軽量で高速
|
||||
- コレクション型は要素数に注意
|
||||
- ネットワーク型は非同期推奨
|
||||
- GUI型はメインスレッド制約
|
||||
|
||||
---
|
||||
|
||||
関連ドキュメント:
|
||||
- [Everything is Box](everything-is-box.md)
|
||||
- [ビルトインBox詳細API](../builtin-boxes.md)
|
||||
- [Box実装ガイド](memory-management.md)
|
||||
@ -1,271 +0,0 @@
|
||||
# 📦 clone_box() vs share_box() 責務分離設計
|
||||
|
||||
## 📅 作成日: 2025-08-15
|
||||
## 🎯 Phase: 9.75D - Box参照管理根本革命
|
||||
|
||||
## 🚨 **設計の背景**
|
||||
|
||||
Phase 9.75でArc<Mutex> → RwLock変換後、ArrayBoxの状態保持が機能しなくなった根本問題を解決するため、**Box参照セマンティクスの明確な責務分離**を導入する。
|
||||
|
||||
### 現在の問題
|
||||
|
||||
```nyash
|
||||
// 期待される動作
|
||||
arr = new ArrayBox()
|
||||
arr.push("hello") // 状態変更
|
||||
arr.length() // 1 であるべき
|
||||
|
||||
// 実際の動作
|
||||
arr.length() // 0 (状態が失われる)
|
||||
```
|
||||
|
||||
### 根本原因
|
||||
|
||||
```rust
|
||||
// src/interpreter/expressions.rs:108
|
||||
ASTNode::Variable { name, .. } => {
|
||||
let shared_var = self.resolve_variable(name)?;
|
||||
Ok((*shared_var).clone_box()) // ← 🚨 毎回新インスタンス作成!
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 **設計原則**
|
||||
|
||||
### 1. **責務分離の明確化**
|
||||
|
||||
**clone_box()**: **値セマンティクス**
|
||||
- 独立した新しいインスタンスを作成
|
||||
- 元のオブジェクトと完全に分離
|
||||
- Rustの`Clone`トレイト慣習に準拠
|
||||
|
||||
**share_box()**: **参照セマンティクス**
|
||||
- 内部状態を共有する新しいハンドルを作成
|
||||
- 元のオブジェクトと状態を共有
|
||||
- 変数アクセス・代入で使用
|
||||
|
||||
### 2. **Everything is Box哲学の維持**
|
||||
|
||||
両メソッドとも`Box<dyn NyashBox>`を返すことで、統一インターフェースを保持。
|
||||
|
||||
```rust
|
||||
trait NyashBox {
|
||||
/// 独立した新しいコピー(ディープコピー)を作成
|
||||
fn clone_box(&self) -> Box<dyn NyashBox>;
|
||||
|
||||
/// 状態を共有する新しいハンドルを作成
|
||||
fn share_box(&self) -> Box<dyn NyashBox>;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. **型カテゴリ別実装戦略**
|
||||
|
||||
#### **ステートフルBox(状態保持が重要)**
|
||||
- ArrayBox, MapBox, SocketBox, P2PBox, FileBox, StreamBox
|
||||
- `share_box()`: Arc<RwLock>をクローンして状態共有
|
||||
- `clone_box()`: ディープコピーで独立インスタンス
|
||||
|
||||
#### **ステートレスBox(値のみ保持)**
|
||||
- StringBox, IntegerBox, BoolBox, MathBox
|
||||
- `share_box()` = `clone_box()` (同じ実装で問題なし)
|
||||
|
||||
## 🔧 **技術実装設計**
|
||||
|
||||
### **ArrayBox実装例**
|
||||
|
||||
```rust
|
||||
// 現在の実装(問題のある構造)
|
||||
pub struct ArrayBox {
|
||||
pub items: RwLock<Vec<Box<dyn NyashBox>>>,
|
||||
base: BoxBase,
|
||||
}
|
||||
|
||||
// 新しい実装(状態共有対応)
|
||||
pub struct ArrayBox {
|
||||
pub items: Arc<RwLock<Vec<Box<dyn NyashBox>>>>, // Arc追加
|
||||
base: BoxBase,
|
||||
}
|
||||
|
||||
impl NyashBox for ArrayBox {
|
||||
fn clone_box(&self) -> Box<dyn NyashBox> {
|
||||
// ディープコピー: 既存のClone実装を使用
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn share_box(&self) -> Box<dyn NyashBox> {
|
||||
// 状態共有: Arcをクローンして新しいハンドル作成
|
||||
let new_instance = ArrayBox {
|
||||
items: Arc::clone(&self.items), // 🎯 状態共有の核心
|
||||
base: BoxBase::new(), // 新しいID
|
||||
};
|
||||
Box::new(new_instance)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for ArrayBox {
|
||||
fn clone(&self) -> Self {
|
||||
// ディープコピー実装
|
||||
let items_guard = self.items.read().unwrap();
|
||||
let cloned_items: Vec<Box<dyn NyashBox>> = items_guard.iter()
|
||||
.map(|item| item.clone_box())
|
||||
.collect();
|
||||
|
||||
ArrayBox {
|
||||
items: Arc::new(RwLock::new(cloned_items)),
|
||||
base: BoxBase::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **StringBox実装例(ステートレス)**
|
||||
|
||||
```rust
|
||||
impl NyashBox for StringBox {
|
||||
fn clone_box(&self) -> Box<dyn NyashBox> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
// ステートレスなので同じ実装で問題なし
|
||||
fn share_box(&self) -> Box<dyn NyashBox> {
|
||||
self.clone_box()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **インタープリター修正**
|
||||
|
||||
```rust
|
||||
// src/interpreter/expressions.rs
|
||||
ASTNode::Variable { name, .. } => {
|
||||
let shared_var = self.resolve_variable(name)?;
|
||||
Ok((*shared_var).share_box()) // 🎯 参照共有使用
|
||||
}
|
||||
|
||||
// 値コピーが必要な場面(例:関数引数渡し)
|
||||
ASTNode::Assignment { .. } => {
|
||||
let value = self.evaluate_expression(right)?;
|
||||
// 代入時も参照共有
|
||||
self.declare_local_variable(name, value.share_box());
|
||||
}
|
||||
```
|
||||
|
||||
## 🌍 **マルチバックエンド対応**
|
||||
|
||||
### **インタープリター**
|
||||
- `expressions.rs:108`: `share_box()`使用
|
||||
- 変数アクセス・代入時の参照管理を統一
|
||||
|
||||
### **VM Backend**
|
||||
- `vm.rs:764`: 配列要素アクセス時の`clone_box()`を検証
|
||||
- スタック操作での適切なセマンティクス選択
|
||||
|
||||
### **WASM Backend**
|
||||
- WASMメモリ管理は独自実装で影響軽微
|
||||
- `clone_box()`呼び出し箇所の意図確認・修正
|
||||
|
||||
## 📊 **性能への影響**
|
||||
|
||||
### **メモリ使用量**
|
||||
- **改善**: Arc<RwLock>による効率的な状態共有
|
||||
- **増加**: Arcのオーバーヘッド(8バイト程度)
|
||||
|
||||
### **実行性能**
|
||||
- **現状維持**: WASM 13.5倍、VM 20.4倍高速化を保持
|
||||
- **改善期待**: 不要なディープコピーの削減
|
||||
|
||||
### **ロック競合**
|
||||
- **リスク**: 複数ハンドルでの同時アクセス
|
||||
- **対策**: RwLock読み取り中心の設計
|
||||
|
||||
## 🧪 **テスト戦略**
|
||||
|
||||
### **Unit Test追加**
|
||||
```rust
|
||||
#[test]
|
||||
fn test_arraybox_state_sharing() {
|
||||
let arr1 = ArrayBox::new();
|
||||
arr1.push(StringBox::new("hello"));
|
||||
|
||||
let arr2 = arr1.share_box();
|
||||
let arr2_array = arr2.as_any().downcast_ref::<ArrayBox>().unwrap();
|
||||
|
||||
// 状態が共有されていることを確認
|
||||
assert_eq!(arr2_array.length().as_any().downcast_ref::<IntegerBox>().unwrap().value, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arraybox_clone_independence() {
|
||||
let arr1 = ArrayBox::new();
|
||||
arr1.push(StringBox::new("hello"));
|
||||
|
||||
let arr2 = arr1.clone_box();
|
||||
let arr2_array = arr2.as_any().downcast_ref::<ArrayBox>().unwrap();
|
||||
|
||||
// 独立していることを確認
|
||||
arr1.push(StringBox::new("world"));
|
||||
assert_eq!(arr2_array.length().as_any().downcast_ref::<IntegerBox>().unwrap().value, 1);
|
||||
}
|
||||
```
|
||||
|
||||
### **Integration Test**
|
||||
- 15個のステートフルBox全てでの状態保持テスト
|
||||
- 3バックエンドでの一貫性テスト
|
||||
- 既存のNyashプログラムでのリグレッションテスト
|
||||
|
||||
## 🔄 **移行時の互換性**
|
||||
|
||||
### **後方互換性**
|
||||
- 既存の`clone_box()`は変更なし
|
||||
- 新しい`share_box()`を段階的に導入
|
||||
|
||||
### **段階的移行**
|
||||
1. `NyashBox`トレイトに`share_box()`追加
|
||||
2. 全Box型に仮実装(`clone_box()`と同じ)
|
||||
3. ステートフルBoxから順次正しい実装に修正
|
||||
4. インタープリター・VM・WASM修正
|
||||
5. 全体テスト・リグレッション確認
|
||||
|
||||
## 🎯 **設計の利点**
|
||||
|
||||
### **明確性**
|
||||
- 値コピー vs 参照共有の意図が明確
|
||||
- コードレビュー時の理解容易性
|
||||
|
||||
### **保守性**
|
||||
- 新しいBox型追加時のガイドライン明確
|
||||
- デバッグ時の状態追跡容易
|
||||
|
||||
### **拡張性**
|
||||
- 将来の最適化(COW等)への発展可能
|
||||
- 静的解析ツールでの解析支援
|
||||
|
||||
### **一貫性**
|
||||
- 3バックエンド全てで統一されたセマンティクス
|
||||
- Everything is Box哲学の維持
|
||||
|
||||
## 🚨 **設計上の注意点**
|
||||
|
||||
### **循環参照リスク**
|
||||
- Arc<RwLock>による循環参照の可能性
|
||||
- 弱参照(Weak)の将来的導入検討
|
||||
|
||||
### **デッドロックリスク**
|
||||
- 複数のRwLockを同時取得する場合
|
||||
- ロック順序の統一ガイドライン必要
|
||||
|
||||
### **メモリリーク検証**
|
||||
- 長時間実行での参照カウント監視
|
||||
- デバッグ時のメモリ使用量追跡
|
||||
|
||||
---
|
||||
|
||||
## 📋 **関連ドキュメント**
|
||||
|
||||
- [Phase 9.75D 移行計画](phase-9-75d-migration-plan.md)
|
||||
- [現在の課題](implementation-notes/current-issues.md)
|
||||
- [Everything is Box 哲学](everything-is-box.md)
|
||||
- [メモリ管理](memory-management.md)
|
||||
|
||||
---
|
||||
|
||||
**この設計により、Nyashの状態保持問題を根本解決し、長期的な保守性・拡張性を確保する。**
|
||||
@ -1,117 +0,0 @@
|
||||
# 🔧 Box設計の現在の課題
|
||||
|
||||
## 📅 最終更新: 2025-08-14
|
||||
|
||||
このドキュメントは、Nyash Box設計における現在進行中の技術的課題と対応状況をまとめています。
|
||||
|
||||
## 🚨 Critical: Arc<Mutex>責務の二重化問題
|
||||
|
||||
### 問題の概要
|
||||
現在、15個のBox型において、内部と外部で二重にロック管理が行われています。
|
||||
|
||||
```rust
|
||||
// 🚨 現在の問題構造
|
||||
pub struct SocketBox {
|
||||
listener: Arc<Mutex<Option<TcpListener>>>, // 内部ロック
|
||||
is_server: Arc<Mutex<bool>>, // 内部ロック
|
||||
}
|
||||
|
||||
// インタープリター側
|
||||
Arc<Mutex<SocketBox>> // 外部ロック
|
||||
|
||||
// 結果: 二重ロック → デッドロック・状態不整合
|
||||
```
|
||||
|
||||
### 影響を受けるBox型(15個)
|
||||
1. **ネットワーク系**: SocketBox, HTTPServerBox
|
||||
2. **コレクション系**: ArrayBox, MapBox, BufferBox
|
||||
3. **I/O系**: FileBox, StreamBox
|
||||
4. **P2P系**: P2PBox, IntentBox, SimpleIntentBox
|
||||
5. **GUI系**: EguiBox
|
||||
6. **特殊系**: RandomBox, DebugBox, FutureBox, JSONBox
|
||||
|
||||
### 根本原因
|
||||
- **責務の混在**: Box自身がスレッドセーフティを管理
|
||||
- **設計の不統一**: 各Box実装者が独自にArc<Mutex>を使用
|
||||
- **ガイドライン不足**: 正しいBox実装パターンが未確立
|
||||
|
||||
### 対応計画
|
||||
**Phase 9.75**として緊急対応中。詳細は[phase-9-75-redesign.md](phase-9-75-redesign.md)参照。
|
||||
|
||||
## ⚠️ High: SocketBox状態保持問題
|
||||
|
||||
### 問題の詳細
|
||||
SocketBoxで`bind()`後に`isServer()`を呼ぶと、状態が保持されていない。
|
||||
|
||||
```nyash
|
||||
// 期待される動作
|
||||
server = new SocketBox()
|
||||
server.bind("127.0.0.1", 8080) // true
|
||||
server.isServer() // true であるべき
|
||||
|
||||
// 実際の動作
|
||||
server.isServer() // false (状態が失われる)
|
||||
```
|
||||
|
||||
### 技術的分析
|
||||
詳細は[socket-box-problem.md](socket-box-problem.md)参照。
|
||||
|
||||
### 暫定対策
|
||||
- PR #75でArc参照共有を試みたが、根本解決には至らず
|
||||
- デッドロック問題は解決したが、状態保持問題は継続
|
||||
|
||||
## 🟡 Medium: Box型の増殖管理
|
||||
|
||||
### 現状
|
||||
- 基本実装済みBox: 20種類以上
|
||||
- 各Boxが独自の実装パターン
|
||||
- 統一的な品質管理が困難
|
||||
|
||||
### 課題
|
||||
1. **実装の一貫性**: 各Boxで異なる実装スタイル
|
||||
2. **テストカバレッジ**: Box間でテスト密度にばらつき
|
||||
3. **ドキュメント**: API仕様の記述レベルが不統一
|
||||
|
||||
### 対応方針
|
||||
- Box実装テンプレートの作成
|
||||
- 自動テスト生成ツールの検討
|
||||
- APIドキュメント自動生成
|
||||
|
||||
## 🟢 Low: パフォーマンス最適化
|
||||
|
||||
### 観測された問題
|
||||
- 二重ロックによるパフォーマンス低下
|
||||
- Box生成時のオーバーヘッド
|
||||
- メソッド呼び出しの動的ディスパッチコスト
|
||||
|
||||
### 最適化の機会
|
||||
1. **ロック削減**: Arc<Mutex>一元化で改善見込み
|
||||
2. **Box生成**: オブジェクトプールの検討
|
||||
3. **メソッド呼び出し**: インライン化・特殊化
|
||||
|
||||
## 📊 課題の優先順位
|
||||
|
||||
1. **🔴 最優先**: Arc<Mutex>責務一元化(Phase 9.75)
|
||||
2. **🟠 高優先**: SocketBox状態保持問題の根本解決
|
||||
3. **🟡 中優先**: Box実装ガイドライン策定
|
||||
4. **🟢 低優先**: パフォーマンス最適化
|
||||
|
||||
## 🔄 進捗追跡
|
||||
|
||||
### 2025-08-14
|
||||
- Phase 9.75として「Box設計根本革命」を`copilot_issues.txt`に追加
|
||||
- Box設計ドキュメントフォルダを新規作成
|
||||
- 現在の課題を体系的に整理
|
||||
|
||||
### 今後の予定
|
||||
- Phase 9.75 Phase A: 設計ガイドライン策定(3日)
|
||||
- Phase 9.75 Phase B: 最優先Box修正(1週間)
|
||||
- Phase 9.75 Phase C: ステートフルBox修正(1週間)
|
||||
- Phase 9.75 Phase D: 残りのBox統一(3日)
|
||||
|
||||
---
|
||||
|
||||
関連ドキュメント:
|
||||
- [Phase 9.75実装計画](phase-9-75-redesign.md)
|
||||
- [SocketBox問題詳細](socket-box-problem.md)
|
||||
- [Box設計原則](../memory-management.md)
|
||||
@ -1,231 +0,0 @@
|
||||
# 🔧 Phase 9.75: Box設計根本革命 - 実装計画詳細
|
||||
|
||||
## 📅 実施期間: 2025-08 (Phase 9.7完了後)
|
||||
|
||||
## 🎯 目標
|
||||
|
||||
Arc<Mutex>責務の二重化問題を根本的に解決し、すべてのBox型で統一的な設計を実現する。
|
||||
|
||||
## 🏗️ 新設計アーキテクチャ
|
||||
|
||||
### Before(現在の問題設計)
|
||||
```rust
|
||||
// Box内部でロック管理
|
||||
pub struct SocketBox {
|
||||
listener: Arc<Mutex<Option<TcpListener>>>,
|
||||
is_server: Arc<Mutex<bool>>,
|
||||
}
|
||||
|
||||
// インタープリターでも二重ロック
|
||||
Arc<Mutex<dyn NyashBox>>
|
||||
```
|
||||
|
||||
### After(新設計)
|
||||
```rust
|
||||
// 純粋なデータコンテナ
|
||||
pub struct SocketBox {
|
||||
listener: Option<TcpListener>,
|
||||
is_server: bool,
|
||||
}
|
||||
|
||||
// インタープリターが一元管理
|
||||
Arc<Mutex<dyn NyashBox>>
|
||||
```
|
||||
|
||||
## 📋 実装フェーズ
|
||||
|
||||
### Phase A: 設計ガイドライン策定(3日)
|
||||
|
||||
#### A-1: Box実装パターンドキュメント
|
||||
```rust
|
||||
// ✅ 推奨パターン
|
||||
pub struct MyBox {
|
||||
base: BoxBase,
|
||||
data: String, // シンプルなフィールド
|
||||
count: usize, // Arc<Mutex>不要
|
||||
items: Vec<Item>, // 直接保持
|
||||
}
|
||||
|
||||
// ❌ アンチパターン
|
||||
pub struct BadBox {
|
||||
data: Arc<Mutex<String>>, // 内部ロック禁止
|
||||
count: Arc<Mutex<usize>>, // 過剰な同期
|
||||
}
|
||||
```
|
||||
|
||||
#### A-2: テンプレート作成
|
||||
- `box_template.rs` - 新Box実装のひな形
|
||||
- `box_test_template.rs` - テストスイートひな形
|
||||
- マクロによる定型処理自動化検討
|
||||
|
||||
#### A-3: 既存コードレビュー
|
||||
- 15個のBox型の実装詳細調査
|
||||
- 問題パターンの分類
|
||||
- 修正難易度の評価
|
||||
|
||||
### Phase B: 最優先Box修正(1週間)
|
||||
|
||||
#### B-1: SocketBox修正
|
||||
```rust
|
||||
// 新実装
|
||||
impl NyashBox for SocketBox {
|
||||
fn bind(&mut self, addr: &str, port: u16) -> Result<(), String> {
|
||||
match TcpListener::bind((addr, port)) {
|
||||
Ok(listener) => {
|
||||
self.listener = Some(listener);
|
||||
self.is_server = true;
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(e.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### B-2: HTTPServerBox修正
|
||||
- SocketBoxと同様のパターンで修正
|
||||
- 内部SocketBoxとの連携確認
|
||||
|
||||
#### B-3: テストスイート作成
|
||||
```nyash
|
||||
// 状態保持テスト
|
||||
test "SocketBox state persistence" {
|
||||
server = new SocketBox()
|
||||
assert(server.bind("127.0.0.1", 8080) == true)
|
||||
assert(server.isServer() == true) // 必ず成功すること
|
||||
}
|
||||
|
||||
// 並行アクセステスト
|
||||
test "Concurrent access safety" {
|
||||
// 複数スレッドからのアクセステスト
|
||||
}
|
||||
```
|
||||
|
||||
### Phase C: ステートフルBox修正(1週間)
|
||||
|
||||
#### C-1: コレクション系Box
|
||||
- **ArrayBox**: `Vec<Box<dyn NyashBox>>`直接保持
|
||||
- **MapBox**: `HashMap<String, Box<dyn NyashBox>>`直接保持
|
||||
- **BufferBox**: バッファ管理の簡素化
|
||||
|
||||
#### C-2: I/O系Box
|
||||
- **FileBox**: ファイルハンドル管理
|
||||
- **StreamBox**: ストリーム状態管理
|
||||
|
||||
#### C-3: P2P系Box
|
||||
- **P2PBox**: ピア管理の再設計
|
||||
- **IntentBox**: インテント処理の簡素化
|
||||
|
||||
### Phase D: 残りのBox統一(3日)
|
||||
|
||||
#### D-1: 機械的修正
|
||||
- RandomBox, DebugBox等の単純なBox
|
||||
- Arc<Mutex>除去の機械的適用
|
||||
|
||||
#### D-2: 統合テスト
|
||||
- 全Box型の動作確認
|
||||
- 相互運用性テスト
|
||||
- メモリリークチェック
|
||||
|
||||
#### D-3: パフォーマンス検証
|
||||
- ベンチマーク実行
|
||||
- ロック競合の削減確認
|
||||
- メモリ使用量の改善確認
|
||||
|
||||
## 🤖 Copilot協力タスク
|
||||
|
||||
### 自動化可能な作業
|
||||
1. **Arc<Mutex>検出スクリプト**
|
||||
```bash
|
||||
grep -r "Arc<Mutex<" src/boxes/ | wc -l
|
||||
# 現在: 50箇所以上 → 目標: 0箇所
|
||||
```
|
||||
|
||||
2. **機械的リファクタリング**
|
||||
- `Arc<Mutex<T>>` → `T`
|
||||
- `.lock().unwrap()` 除去
|
||||
- Clone実装の簡素化
|
||||
|
||||
3. **テストケース生成**
|
||||
- 各Boxの状態保持テスト
|
||||
- 並行アクセステスト
|
||||
- エッジケーステスト
|
||||
|
||||
## 📊 成功指標
|
||||
|
||||
### 定量的指標
|
||||
- [ ] Arc<Mutex>使用箇所: 0個(Box内部)
|
||||
- [ ] デッドロック発生: 0件
|
||||
- [ ] 状態保持テスト: 100%成功
|
||||
- [ ] パフォーマンス: 10%以上向上
|
||||
|
||||
### 定性的指標
|
||||
- [ ] コード可読性の向上
|
||||
- [ ] デバッグの容易さ
|
||||
- [ ] 新規開発者の理解しやすさ
|
||||
|
||||
## 🚨 リスクと対策
|
||||
|
||||
### リスク1: 既存コード互換性
|
||||
**対策**:
|
||||
- NyashBoxトレイトは変更しない
|
||||
- 段階的移行(deprecated警告)
|
||||
|
||||
### リスク2: パフォーマンス劣化
|
||||
**対策**:
|
||||
- 事前ベンチマーク取得
|
||||
- ホットパスの最適化
|
||||
|
||||
### リスク3: 実装工数超過
|
||||
**対策**:
|
||||
- 優先順位付け(SocketBox最優先)
|
||||
- Copilot活用による自動化
|
||||
|
||||
## 📅 詳細スケジュール
|
||||
|
||||
```
|
||||
Week 1:
|
||||
月: Phase A-1 パターンドキュメント
|
||||
火: Phase A-2 テンプレート作成
|
||||
水: Phase A-3 既存コードレビュー
|
||||
木: Phase B-1 SocketBox修正開始
|
||||
金: Phase B-1 SocketBox修正完了
|
||||
|
||||
Week 2:
|
||||
月: Phase B-2 HTTPServerBox修正
|
||||
火: Phase B-3 テストスイート作成
|
||||
水: Phase C-1 ArrayBox/MapBox修正
|
||||
木: Phase C-2 FileBox/StreamBox修正
|
||||
金: Phase C-3 P2PBox修正
|
||||
|
||||
Week 3:
|
||||
月: Phase D-1 残りBox修正
|
||||
火: Phase D-2 統合テスト
|
||||
水: Phase D-3 パフォーマンス検証
|
||||
木: ドキュメント最終化
|
||||
金: リリース準備
|
||||
```
|
||||
|
||||
## 🎉 期待される成果
|
||||
|
||||
1. **技術的成果**
|
||||
- デッドロック問題の根絶
|
||||
- 状態管理の信頼性向上
|
||||
- パフォーマンス改善
|
||||
|
||||
2. **開発効率向上**
|
||||
- 新Box実装の簡素化
|
||||
- デバッグ時間の短縮
|
||||
- 保守コストの削減
|
||||
|
||||
3. **Everything is Box哲学の強化**
|
||||
- より純粋なBox設計
|
||||
- 統一的な実装パターン
|
||||
- 初学者にも理解しやすい構造
|
||||
|
||||
---
|
||||
|
||||
関連ドキュメント:
|
||||
- [現在の課題](current-issues.md)
|
||||
- [SocketBox問題詳細](socket-box-problem.md)
|
||||
- [copilot_issues.txt](../../../../../予定/native-plan/copilot_issues.txt)
|
||||
@ -1,183 +0,0 @@
|
||||
# 🔌 SocketBox Arc<Mutex>二重化問題の詳細分析
|
||||
|
||||
## 🚨 問題の症状
|
||||
|
||||
### 観測された現象
|
||||
```nyash
|
||||
// テストコード
|
||||
server = new SocketBox()
|
||||
server.bind("127.0.0.1", 8080) // ✅ 成功: true
|
||||
server.isServer() // ❌ 失敗: false (期待値: true)
|
||||
```
|
||||
|
||||
### デバッグ出力
|
||||
```
|
||||
🔥 SOCKETBOX DEBUG: bind() called
|
||||
🔥 Socket ID = 17
|
||||
🔥 Arc pointer = 0x7ffd5b8a3d20
|
||||
🔥 Arc data pointer = 0x5565423a6d60
|
||||
🔥 AFTER MUTATION: is_server = true
|
||||
|
||||
🔥 SOCKETBOX DEBUG: isServer() called
|
||||
🔥 Socket ID = 17
|
||||
🔥 Arc pointer = 0x7ffd5b8a3d20
|
||||
🔥 Arc data pointer = 0x5565423a6d60 // 同じポインタ!
|
||||
🔥 IS_SERVER READ: is_server = false // しかし値は失われている
|
||||
```
|
||||
|
||||
## 🔍 根本原因の分析
|
||||
|
||||
### 1. 責務の二重化
|
||||
```rust
|
||||
// 現在のSocketBox実装
|
||||
pub struct SocketBox {
|
||||
base: BoxBase,
|
||||
listener: Arc<Mutex<Option<TcpListener>>>, // 内部ロック
|
||||
stream: Arc<Mutex<Option<TcpStream>>>, // 内部ロック
|
||||
is_server: Arc<Mutex<bool>>, // 内部ロック
|
||||
is_connected: Arc<Mutex<bool>>, // 内部ロック
|
||||
}
|
||||
|
||||
// インタープリター側
|
||||
let socket: Arc<Mutex<dyn NyashBox>> = Arc::new(Mutex::new(SocketBox::new()));
|
||||
```
|
||||
|
||||
### 2. 状態更新の問題
|
||||
```rust
|
||||
// bind()メソッド内での状態更新
|
||||
pub fn bind(&self, address: Box<dyn NyashBox>, port: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||
// ...
|
||||
*self.is_server.lock().unwrap() = true; // 内部Mutexへの書き込み
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Clone実装の複雑性
|
||||
```rust
|
||||
impl Clone for SocketBox {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
base: BoxBase::new(), // 新しいID(デバッグ用)
|
||||
listener: Arc::clone(&self.listener), // Arcを共有
|
||||
stream: Arc::clone(&self.stream), // Arcを共有
|
||||
is_server: Arc::clone(&self.is_server), // Arcを共有
|
||||
is_connected: Arc::clone(&self.is_connected), // Arcを共有
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 💀 デッドロックの危険性
|
||||
|
||||
### 発生パターン
|
||||
1. インタープリターがSocketBoxをロック
|
||||
2. SocketBoxメソッドが内部フィールドをロック
|
||||
3. 別スレッドが逆順でロックを試みる
|
||||
4. デッドロック発生
|
||||
|
||||
### 実際に観測されたデッドロック
|
||||
```rust
|
||||
// PR #75修正前
|
||||
pub fn bind(&self, ...) -> Box<dyn NyashBox> {
|
||||
// ...
|
||||
let updated = SocketBox { /* ... */ };
|
||||
Box::new(updated.clone()) // ここでデッドロック
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 試みられた修正と結果
|
||||
|
||||
### PR #75: Arc<dyn NyashBox>統合
|
||||
**目的**: 状態を共有するためにArc参照を使用
|
||||
**結果**:
|
||||
- ✅ デッドロック解消
|
||||
- ❌ 状態保持問題は未解決
|
||||
|
||||
### PR #81: フィールド更新メカニズム
|
||||
**目的**: インスタンスフィールドの更新を修正
|
||||
**結果**:
|
||||
- ✅ フィールド更新は動作
|
||||
- ❌ SocketBox内部状態は依然として失われる
|
||||
|
||||
## 🎯 Gemini先生の根本解決策
|
||||
|
||||
### 設計原則の転換
|
||||
```rust
|
||||
// ❌ 現在の設計: Box自身がロック責務を持つ
|
||||
pub struct SocketBox {
|
||||
is_server: Arc<Mutex<bool>>, // Box内部でロック管理
|
||||
}
|
||||
|
||||
// ✅ 新設計: 純粋なデータコンテナ
|
||||
pub struct PlainSocketBox {
|
||||
pub listener: Option<TcpListener>,
|
||||
pub is_server: bool, // シンプルなフィールド
|
||||
}
|
||||
```
|
||||
|
||||
### 責務の明確化
|
||||
- **Box**: 純粋なデータとロジックのみ
|
||||
- **インタープリター**: すべてのロック管理を一元化
|
||||
|
||||
### 実装例
|
||||
```rust
|
||||
// 新しいbind()実装
|
||||
impl PlainSocketBox {
|
||||
pub fn bind(&mut self, addr: &str, port: u16) -> bool {
|
||||
match TcpListener::bind((addr, port)) {
|
||||
Ok(listener) => {
|
||||
self.listener = Some(listener);
|
||||
self.is_server = true; // 直接代入、ロック不要
|
||||
true
|
||||
},
|
||||
Err(_) => false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 影響分析
|
||||
|
||||
### 同じ問題を抱えるBox型
|
||||
1. **HTTPServerBox**: SocketBoxを内包、同様の問題
|
||||
2. **ArrayBox**: `Arc<Mutex<Vec<...>>>`
|
||||
3. **MapBox**: `Arc<Mutex<HashMap<...>>>`
|
||||
4. **P2PBox**: 複雑な内部状態管理
|
||||
5. その他10個のBox型
|
||||
|
||||
### リファクタリングの規模
|
||||
- 影響Box数: 15個
|
||||
- 推定作業量: 2-3週間(Phase 9.75)
|
||||
- リスク: 既存コードの互換性
|
||||
|
||||
## 🚀 移行戦略
|
||||
|
||||
### Phase A: 設計ガイドライン(3日)
|
||||
1. 新Box実装パターンの確立
|
||||
2. Arc<Mutex>禁止ルールの明文化
|
||||
3. テンプレート・サンプルコード作成
|
||||
|
||||
### Phase B: 最優先修正(1週間)
|
||||
1. SocketBox → PlainSocketBox
|
||||
2. HTTPServerBox → PlainHTTPServerBox
|
||||
3. 状態保持テストスイート作成
|
||||
|
||||
### Phase C: 全Box統一(1-2週間)
|
||||
1. 残り13個のBox型修正
|
||||
2. 統合テスト実施
|
||||
3. パフォーマンス検証
|
||||
|
||||
## 🎉 期待される効果
|
||||
|
||||
1. **デッドロック根絶**: 二重ロック構造の排除
|
||||
2. **状態整合性保証**: インタープリター一元管理
|
||||
3. **デバッグ容易性**: シンプルな実装
|
||||
4. **パフォーマンス向上**: ロック競合の削減
|
||||
5. **保守性向上**: 統一的な実装パターン
|
||||
|
||||
---
|
||||
|
||||
関連ドキュメント:
|
||||
- [現在の課題一覧](current-issues.md)
|
||||
- [Phase 9.75実装計画](phase-9-75-redesign.md)
|
||||
- [メモリ管理設計](../memory-management.md)
|
||||
@ -1,307 +0,0 @@
|
||||
# 🧠 Nyash メモリ管理設計
|
||||
|
||||
## 📋 概要
|
||||
|
||||
Nyashは「Everything is Box」哲学のもと、すべての値をBoxとして統一的に管理します。
|
||||
メモリ安全性を保証しながら、シンプルで直感的なメモリ管理を実現しています。
|
||||
|
||||
## 🏗️ 基本アーキテクチャ
|
||||
|
||||
### Arc<Mutex>一元管理
|
||||
|
||||
```rust
|
||||
// インタープリターレベルでの統一管理
|
||||
type NyashObject = Arc<Mutex<dyn NyashBox>>;
|
||||
```
|
||||
|
||||
すべてのBoxは、インタープリターレベルで`Arc<Mutex>`によって管理されます。
|
||||
これにより:
|
||||
- **スレッドセーフティ**: 自動的に保証
|
||||
- **参照カウント**: 自動的なメモリ解放
|
||||
- **統一的アクセス**: すべて同じ方法で操作
|
||||
|
||||
### ❌ アンチパターン(Phase 9.75で修正中)
|
||||
|
||||
```rust
|
||||
// 現在の問題: Box内部での二重ロック
|
||||
pub struct BadBox {
|
||||
data: Arc<Mutex<String>>, // ❌ Box内部でロック管理
|
||||
}
|
||||
|
||||
// 正しい設計
|
||||
pub struct GoodBox {
|
||||
data: String, // ✅ シンプルなフィールド
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 fini()システム
|
||||
|
||||
### 概要
|
||||
Nyashは決定論的なリソース解放のために`fini()`システムを提供します。
|
||||
|
||||
```nyash
|
||||
box FileHandler {
|
||||
init { file }
|
||||
|
||||
fini() {
|
||||
// オブジェクト削除時に自動呼び出し
|
||||
if me.file != null {
|
||||
me.file.close()
|
||||
console.log("File closed automatically")
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### fini()の特徴
|
||||
|
||||
1. **自動呼び出し**: オブジェクトの参照がゼロになると自動実行
|
||||
2. **決定論的**: GCのタイミングに依存しない
|
||||
3. **伝播**: 親オブジェクトのfini()が子オブジェクトに伝播
|
||||
|
||||
### 実装例
|
||||
|
||||
```nyash
|
||||
box DatabaseConnection {
|
||||
init { connection, transactions }
|
||||
|
||||
fini() {
|
||||
// トランザクションをすべてロールバック
|
||||
for tx in me.transactions {
|
||||
tx.rollback()
|
||||
}
|
||||
// 接続を閉じる
|
||||
me.connection.close()
|
||||
}
|
||||
}
|
||||
|
||||
// 使用例
|
||||
{
|
||||
local db = new DatabaseConnection()
|
||||
db.connect("localhost:5432")
|
||||
// ... データベース操作 ...
|
||||
} // スコープを抜けると自動的にfini()が呼ばれる
|
||||
```
|
||||
|
||||
## 💭 weak参照システム
|
||||
|
||||
### 循環参照の問題と解決
|
||||
|
||||
```nyash
|
||||
// 循環参照の例
|
||||
box Parent {
|
||||
init { children }
|
||||
|
||||
pack() {
|
||||
me.children = new ArrayBox()
|
||||
}
|
||||
|
||||
addChild(child) {
|
||||
me.children.push(child)
|
||||
child.parent = me // 循環参照!
|
||||
}
|
||||
}
|
||||
|
||||
box Child {
|
||||
init { parent }
|
||||
}
|
||||
```
|
||||
|
||||
### weak参照による解決
|
||||
|
||||
```nyash
|
||||
box Parent {
|
||||
init { children }
|
||||
|
||||
pack() {
|
||||
me.children = new ArrayBox()
|
||||
}
|
||||
|
||||
addChild(child) {
|
||||
me.children.push(child)
|
||||
child.parent = weak me // weak参照で循環を防ぐ
|
||||
}
|
||||
}
|
||||
|
||||
box Child {
|
||||
init { parent } // weak参照として保持
|
||||
|
||||
getParent() {
|
||||
// weak参照から通常参照を取得
|
||||
local p = strong me.parent
|
||||
if p == null {
|
||||
console.log("Parent has been deleted")
|
||||
return null
|
||||
}
|
||||
return p
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### weak参照の特徴
|
||||
|
||||
1. **自動null化**: 参照先が削除されるとnullになる
|
||||
2. **メモリリーク防止**: 循環参照を断ち切る
|
||||
3. **明示的変換**: `strong`で通常参照に変換
|
||||
|
||||
## 📊 メモリ管理パターン
|
||||
|
||||
### 1. 所有権パターン
|
||||
|
||||
```nyash
|
||||
box Container {
|
||||
init { items } // Containerがitemsを所有
|
||||
|
||||
pack() {
|
||||
me.items = new ArrayBox()
|
||||
}
|
||||
|
||||
fini() {
|
||||
// itemsも自動的に解放される
|
||||
console.log("Container and all items released")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 共有参照パターン
|
||||
|
||||
```nyash
|
||||
// 複数のオブジェクトで共有
|
||||
local sharedData = new DataBox()
|
||||
|
||||
local viewer1 = new DataViewer(sharedData)
|
||||
local viewer2 = new DataViewer(sharedData)
|
||||
|
||||
// sharedDataは両方のviewerから参照されている間は生存
|
||||
```
|
||||
|
||||
### 3. 観察者パターン
|
||||
|
||||
```nyash
|
||||
box Subject {
|
||||
init { observers }
|
||||
|
||||
pack() {
|
||||
me.observers = new ArrayBox()
|
||||
}
|
||||
|
||||
attach(observer) {
|
||||
// weak参照で観察者を保持
|
||||
me.observers.push(weak observer)
|
||||
}
|
||||
|
||||
notify() {
|
||||
// weak参照をチェックしながら通知
|
||||
local aliveObservers = new ArrayBox()
|
||||
|
||||
for weakObs in me.observers {
|
||||
local obs = strong weakObs
|
||||
if obs != null {
|
||||
obs.update(me)
|
||||
aliveObservers.push(weakObs)
|
||||
}
|
||||
}
|
||||
|
||||
// 死んだ参照を削除
|
||||
me.observers = aliveObservers
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🛡️ メモリ安全性保証
|
||||
|
||||
### 1. 二重解放防止
|
||||
Arc<Mutex>により、同じオブジェクトの二重解放は不可能。
|
||||
|
||||
### 2. Use-After-Free防止
|
||||
参照カウントにより、使用中のオブジェクトは解放されない。
|
||||
|
||||
### 3. データ競合防止
|
||||
Mutexにより、同時アクセスは自動的に同期される。
|
||||
|
||||
### 4. メモリリーク検出
|
||||
```nyash
|
||||
// デバッグモードでメモリリーク検出
|
||||
DEBUG = new DebugBox()
|
||||
DEBUG.startTracking()
|
||||
|
||||
// ... プログラム実行 ...
|
||||
|
||||
print(DEBUG.memoryReport())
|
||||
// 出力: 未解放オブジェクト一覧
|
||||
```
|
||||
|
||||
## 🚀 ベストプラクティス
|
||||
|
||||
### 1. fini()の正しい使い方
|
||||
```nyash
|
||||
box ResourceManager {
|
||||
init { resources }
|
||||
|
||||
fini() {
|
||||
// 1. 子リソースから順に解放
|
||||
for resource in me.resources {
|
||||
resource.release()
|
||||
}
|
||||
|
||||
// 2. 自身のリソースを解放
|
||||
me.cleanup()
|
||||
|
||||
// 3. ログを残す(デバッグ用)
|
||||
console.log("ResourceManager cleaned up")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. weak参照の使い時
|
||||
- **親子関係**: 子→親はweak参照
|
||||
- **イベントリスナー**: Subject→Observerはweak参照
|
||||
- **キャッシュ**: 一時的な参照はweak
|
||||
|
||||
### 3. メモリ効率的なコード
|
||||
```nyash
|
||||
// ❌ 非効率
|
||||
loop(i < 1000000) {
|
||||
local temp = new StringBox("temp")
|
||||
// tempが毎回作られる
|
||||
}
|
||||
|
||||
// ✅ 効率的
|
||||
local temp = new StringBox("")
|
||||
loop(i < 1000000) {
|
||||
temp.set("temp")
|
||||
// 既存オブジェクトを再利用
|
||||
}
|
||||
```
|
||||
|
||||
## 📈 パフォーマンス考慮事項
|
||||
|
||||
### 1. 参照カウントのオーバーヘッド
|
||||
- 小さいが無視できない
|
||||
- ホットパスでは最小限に
|
||||
|
||||
### 2. Mutexロックの競合
|
||||
- Phase 9.75で一元化により改善予定
|
||||
- 細粒度ロックを避ける
|
||||
|
||||
### 3. fini()の実行コスト
|
||||
- 複雑なfini()は避ける
|
||||
- 非同期処理は避ける
|
||||
|
||||
## 🔮 将来の拡張
|
||||
|
||||
### 1. 世代別GC
|
||||
参照カウントと世代別GCのハイブリッド検討
|
||||
|
||||
### 2. メモリプール
|
||||
頻繁に生成・破棄されるBoxのプール化
|
||||
|
||||
### 3. コンパクション
|
||||
メモリ断片化対策
|
||||
|
||||
---
|
||||
|
||||
関連ドキュメント:
|
||||
- [Everything is Box](everything-is-box.md)
|
||||
- [fini/weak参照リファレンス](../finalization-system.md)
|
||||
- [Phase 9.75実装計画](implementation-notes/phase-9-75-redesign.md)
|
||||
54
docs/説明書/reference/boxes-system/README.md
Normal file
54
docs/説明書/reference/boxes-system/README.md
Normal file
@ -0,0 +1,54 @@
|
||||
# 📦 Nyash Boxシステム設計ドキュメント
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
Nyashの核心哲学「**Everything is Box**」に関する完全な設計ドキュメント集。
|
||||
言語設計の根幹から実装詳細まで、Boxシステムのすべてを網羅しています。
|
||||
|
||||
## 📚 ドキュメント構成
|
||||
|
||||
### 🌟 コア哲学
|
||||
|
||||
#### [everything-is-box.md](everything-is-box.md)
|
||||
Nyashの核心哲学「Everything is Box」の解説。なぜすべてをBoxにするのか、その設計思想と利点。
|
||||
|
||||
### 📖 完全リファレンス
|
||||
|
||||
#### [box-reference.md](box-reference.md)
|
||||
**統合版Box型完全リファレンス**。全ビルトインBox型のAPI仕様、基本型からプラグインBoxまで。
|
||||
|
||||
### 🔄 システム設計
|
||||
|
||||
#### [delegation-system.md](delegation-system.md)
|
||||
完全明示デリゲーションシステムの設計。`from`構文、`override`必須、`pack`構文の詳細仕様。
|
||||
|
||||
#### [memory-finalization.md](memory-finalization.md)
|
||||
**統合版メモリ管理&finiシステム**。Arc<Mutex>一元管理、fini()論理的解放、weak参照、プラグインメモリ安全性。
|
||||
|
||||
## 🔗 関連ドキュメント
|
||||
|
||||
- **[プラグインシステム](../plugin-system/)**: BID-FFIプラグインシステム完全仕様
|
||||
- **[言語仕様](../core-language/)**: デリゲーション構文、言語リファレンス
|
||||
- **[実行バックエンド](../execution-backend/)**: MIR、P2P通信仕様
|
||||
|
||||
## 🎨 設計原則
|
||||
|
||||
### Everything is Box
|
||||
- すべての値がBoxオブジェクト
|
||||
- 統一的なメソッド呼び出し
|
||||
- プリミティブ型と参照型の区別なし
|
||||
|
||||
### メモリ安全性
|
||||
- Arc<Mutex>による統一管理
|
||||
- fini()による決定論的リソース解放
|
||||
- weak参照による循環参照回避
|
||||
|
||||
### プラグイン拡張性
|
||||
- BID-FFIによる外部ライブラリ統合
|
||||
- 型情報管理による安全な変換
|
||||
- HostVtableによるメモリ管理
|
||||
|
||||
---
|
||||
|
||||
**最終更新**: 2025年8月19日 - boxes-system統合整理完了
|
||||
**Phase 9.75g-0成果**: プラグインシステムとの完全統合
|
||||
270
docs/説明書/reference/boxes-system/box-reference.md
Normal file
270
docs/説明書/reference/boxes-system/box-reference.md
Normal file
@ -0,0 +1,270 @@
|
||||
# 📦 Nyash Box型完全リファレンス
|
||||
|
||||
Nyashで利用できる全ビルトインBox型の完全API仕様書です。
|
||||
|
||||
## 📋 Box型分類
|
||||
|
||||
### 🎯 基本型Box(Primitive Boxes)
|
||||
|
||||
#### StringBox
|
||||
文字列を扱う基本Box型。
|
||||
|
||||
```nyash
|
||||
local str = "Hello, Nyash!" // 自動的にStringBox
|
||||
local explicit = new StringBox("Explicit creation")
|
||||
|
||||
// メソッド
|
||||
str.length() // 文字数を取得
|
||||
str.toUpperCase() // 大文字変換
|
||||
str.split(",") // 文字列分割
|
||||
str.contains("Nya") // 部分文字列検索
|
||||
```
|
||||
|
||||
#### IntegerBox
|
||||
整数を扱う基本Box型。
|
||||
|
||||
```nyash
|
||||
local num = 42 // 自動的にIntegerBox
|
||||
local big = new IntegerBox(1000000)
|
||||
|
||||
// メソッド
|
||||
num.add(10) // 加算
|
||||
num.multiply(2) // 乗算
|
||||
num.toString() // 文字列変換
|
||||
num.isEven() // 偶数判定
|
||||
```
|
||||
|
||||
#### FloatBox
|
||||
浮動小数点数を扱うBox型。
|
||||
|
||||
```nyash
|
||||
local pi = 3.14159 // 自動的にFloatBox
|
||||
local precise = new FloatBox(2.718281828)
|
||||
|
||||
// メソッド
|
||||
pi.round(2) // 小数点以下2桁に丸める
|
||||
pi.ceil() // 切り上げ
|
||||
pi.floor() // 切り下げ
|
||||
pi.toString() // 文字列変換
|
||||
```
|
||||
|
||||
#### BoolBox
|
||||
真偽値を扱うBox型。
|
||||
|
||||
```nyash
|
||||
local flag = true // 自動的にBoolBox
|
||||
local explicit = new BoolBox(false)
|
||||
|
||||
// メソッド
|
||||
flag.toString() // 文字列変換
|
||||
flag.not() // 論理反転
|
||||
```
|
||||
|
||||
#### NullBox
|
||||
null値を表すBox型。
|
||||
|
||||
```nyash
|
||||
local empty = null // NullBox
|
||||
local check = empty.isNull() // true
|
||||
```
|
||||
|
||||
### 🔢 計算・データ処理系
|
||||
|
||||
#### MathBox
|
||||
数学関数を提供するBox型。
|
||||
|
||||
```nyash
|
||||
local math = new MathBox()
|
||||
|
||||
// メソッド
|
||||
math.sin(pi/2) // サイン関数
|
||||
math.cos(0) // コサイン関数
|
||||
math.sqrt(16) // 平方根
|
||||
math.pow(2, 8) // べき乗
|
||||
math.random() // 乱数生成
|
||||
```
|
||||
|
||||
#### ArrayBox
|
||||
配列操作を行うBox型。
|
||||
|
||||
```nyash
|
||||
local arr = new ArrayBox()
|
||||
|
||||
// メソッド
|
||||
arr.push("item") // 要素追加
|
||||
arr.get(0) // 要素取得
|
||||
arr.set(0, "new") // 要素設定
|
||||
arr.length() // 長さ取得
|
||||
arr.clear() // 全削除
|
||||
```
|
||||
|
||||
#### MapBox
|
||||
連想配列(辞書)操作を行うBox型。
|
||||
|
||||
```nyash
|
||||
local map = new MapBox()
|
||||
|
||||
// メソッド
|
||||
map.set("key", "value") // キー・値設定
|
||||
map.get("key") // 値取得
|
||||
map.has("key") // キー存在確認
|
||||
map.keys() // 全キー取得
|
||||
map.clear() // 全削除
|
||||
```
|
||||
|
||||
### 🔗 通信・ネットワーク系
|
||||
|
||||
#### P2PBox
|
||||
P2P通信を行うノードを表すBox。
|
||||
|
||||
```nyash
|
||||
// コンストラクタ
|
||||
local node = new P2PBox(node_id, world)
|
||||
```
|
||||
|
||||
**パラメータ:**
|
||||
- `node_id` (String): ノードの一意識別子
|
||||
- `world` (IntentBox): 参加する通信世界
|
||||
|
||||
**メソッド:**
|
||||
|
||||
##### send(intent, data, target)
|
||||
```nyash
|
||||
local result = node.send("greeting", message_data, "target_node_id")
|
||||
```
|
||||
- `intent` (String): メッセージの種類
|
||||
- `data` (Box): 送信するデータ
|
||||
- `target` (String): 送信先ノードID
|
||||
- **戻り値:** StringBox("sent")
|
||||
|
||||
##### on(intent, callback)
|
||||
```nyash
|
||||
node.on("chat", callback_function)
|
||||
```
|
||||
- `intent` (String): 監視するメッセージ種類
|
||||
- `callback` (MethodBox): 受信時に呼ばれる関数
|
||||
|
||||
##### off(intent)
|
||||
```nyash
|
||||
node.off("chat")
|
||||
```
|
||||
- `intent` (String): 解除するメッセージ種類
|
||||
|
||||
#### SocketBox
|
||||
TCP/IPソケット通信を行うBox型。
|
||||
|
||||
```nyash
|
||||
local socket = new SocketBox()
|
||||
|
||||
// サーバーモード
|
||||
socket.listen(8080) // ポート8080でリッスン
|
||||
socket.accept() // 接続受け入れ
|
||||
|
||||
// クライアントモード
|
||||
socket.connect("localhost", 8080) // 接続
|
||||
socket.send("Hello") // データ送信
|
||||
socket.receive() // データ受信
|
||||
socket.close() // 接続終了
|
||||
```
|
||||
|
||||
### 🖥️ I/O・GUI系
|
||||
|
||||
#### ConsoleBox
|
||||
基本的なコンソールI/Oを行うBox型。
|
||||
|
||||
```nyash
|
||||
local console = new ConsoleBox()
|
||||
|
||||
// メソッド
|
||||
console.log("message") // 標準出力
|
||||
console.error("error") // エラー出力
|
||||
console.input() // 標準入力
|
||||
```
|
||||
|
||||
#### FileBox
|
||||
ファイル操作を行うBox型(プラグイン対応)。
|
||||
|
||||
```nyash
|
||||
local f = new FileBox("data.txt")
|
||||
|
||||
// メソッド
|
||||
f.write("content") // ファイル書き込み
|
||||
f.read() // ファイル読み込み
|
||||
f.exists() // ファイル存在確認
|
||||
f.close() // ファイル閉じる
|
||||
```
|
||||
|
||||
#### EguiBox
|
||||
GUI開発を行うBox型。
|
||||
|
||||
```nyash
|
||||
local app = new EguiBox()
|
||||
|
||||
// メソッド
|
||||
app.setTitle("My App") // タイトル設定
|
||||
app.setSize(800, 600) // サイズ設定
|
||||
app.run() // GUI実行
|
||||
```
|
||||
|
||||
### 🎮 特殊・デバッグ系
|
||||
|
||||
#### DebugBox
|
||||
デバッグ・イントロスペクション用Box型。
|
||||
|
||||
```nyash
|
||||
local debug = new DebugBox()
|
||||
|
||||
// メソッド
|
||||
debug.startTracking() // メモリ追跡開始
|
||||
debug.trackBox(obj, "desc") // オブジェクト追跡
|
||||
debug.memoryReport() // メモリレポート
|
||||
```
|
||||
|
||||
#### RandomBox
|
||||
乱数生成専用Box型。
|
||||
|
||||
```nyash
|
||||
local rand = new RandomBox()
|
||||
|
||||
// メソッド
|
||||
rand.next() // 0-1の乱数
|
||||
rand.nextInt(100) // 0-99の整数乱数
|
||||
rand.nextFloat(10.0) // 0-10の浮動小数点乱数
|
||||
```
|
||||
|
||||
#### TimeBox
|
||||
時間・日付操作Box型。
|
||||
|
||||
```nyash
|
||||
local time = new TimeBox()
|
||||
|
||||
// メソッド
|
||||
time.now() // 現在時刻取得
|
||||
time.format("YYYY-MM-DD") // 時刻フォーマット
|
||||
time.addDays(7) // 日数加算
|
||||
```
|
||||
|
||||
## 🔌 プラグインBox
|
||||
|
||||
Nyashはプラグインシステムにより、新しいBox型を動的に追加できます。
|
||||
|
||||
### プラグイン設定(nyash.toml)
|
||||
```toml
|
||||
[plugins]
|
||||
FileBox = "nyash-filebox-plugin"
|
||||
DatabaseBox = "nyash-db-plugin"
|
||||
```
|
||||
|
||||
### 型情報管理
|
||||
```toml
|
||||
[plugins.FileBox.methods]
|
||||
write = { args = [{ from = "string", to = "bytes" }] }
|
||||
read = { args = [] }
|
||||
```
|
||||
|
||||
**詳細**: [プラグインシステム](../plugin-system/)
|
||||
|
||||
---
|
||||
|
||||
**最終更新**: 2025年8月19日 - Box型リファレンス統合版
|
||||
**関連ドキュメント**: [Everything is Box哲学](everything-is-box.md) | [プラグインシステム](../plugin-system/)
|
||||
180
docs/説明書/reference/boxes-system/memory-finalization.md
Normal file
180
docs/説明書/reference/boxes-system/memory-finalization.md
Normal file
@ -0,0 +1,180 @@
|
||||
# 🧠 Nyash メモリ管理 & finiシステム
|
||||
|
||||
**最終更新: 2025年8月19日 - 統合仕様書**
|
||||
|
||||
## 📋 概要
|
||||
|
||||
Nyashは「Everything is Box」哲学のもと、統一的なメモリ管理と予測可能なリソース解放を実現しています。
|
||||
|
||||
## 🏗️ 基本アーキテクチャ
|
||||
|
||||
### Arc<Mutex>一元管理
|
||||
|
||||
```rust
|
||||
// インタープリターレベルでの統一管理
|
||||
type NyashObject = Arc<Mutex<dyn NyashBox>>;
|
||||
```
|
||||
|
||||
すべてのBoxは、インタープリターレベルで`Arc<Mutex>`によって管理されます。
|
||||
|
||||
#### 利点
|
||||
- **スレッドセーフティ**: 自動的に保証
|
||||
- **参照カウント**: 自動的なメモリ解放
|
||||
- **統一的アクセス**: すべて同じ方法で操作
|
||||
|
||||
#### 設計原則
|
||||
|
||||
```rust
|
||||
// ✅ 正しい設計(シンプルなフィールド)
|
||||
pub struct GoodBox {
|
||||
data: String,
|
||||
count: i32,
|
||||
}
|
||||
|
||||
// ❌ アンチパターン(Box内部での二重ロック)
|
||||
pub struct BadBox {
|
||||
data: Arc<Mutex<String>>, // 内部でロック管理しない
|
||||
}
|
||||
```
|
||||
|
||||
### プラグインシステムのメモリ管理
|
||||
|
||||
BID-FFIプラグインシステムでは、**HostVtable**を通じて安全なメモリ管理を実現:
|
||||
|
||||
```rust
|
||||
pub struct NyashHostVtable {
|
||||
pub alloc: unsafe extern "C" fn(size: usize) -> *mut u8,
|
||||
pub free: unsafe extern "C" fn(ptr: *mut u8),
|
||||
pub wake: unsafe extern "C" fn(handle: u64),
|
||||
pub log: unsafe extern "C" fn(level: i32, msg: *const c_char),
|
||||
}
|
||||
```
|
||||
|
||||
**重要**: プラグインが割り当てたメモリはプラグインが解放する原則
|
||||
|
||||
## 🔥 finiシステム - 論理的解放フック
|
||||
|
||||
### 核心コンセプト
|
||||
|
||||
`fini()`は**物理的メモリ破棄ではなく論理的使用終了**を宣言する革新的システムです。
|
||||
|
||||
```nyash
|
||||
box MyResource {
|
||||
init { name, file }
|
||||
|
||||
fini() {
|
||||
print("Resource " + me.name + " is being finalized")
|
||||
// ファイルクローズなどのクリーンアップ処理
|
||||
// 物理的メモリは共有参照が残っていても論理的には「終了」
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**重要**: `fini()`は「このオブジェクトをもう使わない」という宣言であり、物理的な即時破棄ではありません。
|
||||
|
||||
### 実行順序(確定仕様)
|
||||
|
||||
#### 自動カスケード解放
|
||||
```nyash
|
||||
box Pipeline {
|
||||
init { r1, r2, r3, weak monitor }
|
||||
|
||||
fini() {
|
||||
// 1) ユーザー定義処理(柔軟な順序制御可能)
|
||||
me.r3.fini() // 依存関係でr3→r2の順
|
||||
me.r2.fini()
|
||||
|
||||
// 2) 自動カスケード: 残りのr1がinit宣言順で自動解放
|
||||
// 3) weakフィールドは対象外(lazy nil化)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 決定的な解放順序
|
||||
1. **finalized チェック** - 既に解放済みなら何もしない(idempotent)
|
||||
2. **再入防止** - `in_finalization`フラグで再帰呼び出し防止
|
||||
3. **ユーザー定義fini()実行** - カスタムクリーンアップ処理
|
||||
4. **自動カスケード** - `init`宣言順で未処理フィールドを解放
|
||||
5. **フィールドクリア** - 全フィールドを無効化
|
||||
6. **finalized設定** - 以後の使用を禁止
|
||||
|
||||
### weak参照による循環参照回避
|
||||
|
||||
```nyash
|
||||
box Node {
|
||||
init { id, weak next } // 'next'は弱参照
|
||||
}
|
||||
|
||||
local node1 = new Node("A", null)
|
||||
local node2 = new Node("B", node1) // node2はnode1への弱参照を持つ
|
||||
node1.next = node2 // node1はnode2への強参照を持つ
|
||||
// 循環参照を回避し、安全に解放される
|
||||
```
|
||||
|
||||
#### weak参照の特性
|
||||
- **所有権なし**: オブジェクトの生存期間に影響しない
|
||||
- **自動nil化**: 参照先が解放されると自動的に`null`になる
|
||||
- **fini()対象外**: 弱参照フィールドはfini()カスケードでスキップ
|
||||
|
||||
### 不変条件(重要)
|
||||
|
||||
- **weak参照**: `weak`フィールドに対して`fini()`を直接呼ぶことはできません
|
||||
- **finalized後禁止**: `fini()`呼び出し後は、そのオブジェクトの使用はすべて禁止
|
||||
- **カスケード順序**: `init`宣言順の**逆順**で実行、`weak`フィールドはスキップ
|
||||
|
||||
## 🌟 実用例
|
||||
|
||||
### リソース管理
|
||||
```nyash
|
||||
box FileHandler {
|
||||
init { file, buffer }
|
||||
|
||||
fini() {
|
||||
// オブジェクト削除時に自動呼び出し
|
||||
if me.file != null {
|
||||
me.file.close()
|
||||
console.log("File closed automatically")
|
||||
}
|
||||
// bufferは自動カスケードで解放
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### プラグインリソース
|
||||
```nyash
|
||||
box PluginResource {
|
||||
init { plugin_handle }
|
||||
|
||||
fini() {
|
||||
// プラグイン側のリソース解放を呼び出し
|
||||
me.plugin_handle.cleanup()
|
||||
console.log("Plugin resource finalized")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🛡️ メモリ安全性保証
|
||||
|
||||
### valgrind検証済み
|
||||
- **セグフォルト回避**: HostVtableの生存期間問題解決済み
|
||||
- **メモリリーク検出**: プラグインシステムでのメモリ管理検証済み
|
||||
- **二重解放防止**: idempotentなfini()実装
|
||||
|
||||
### プラグインメモリ安全性
|
||||
- **プラグイン分離**: プラグインメモリはプラグインが管理
|
||||
- **境界明確化**: HostVtableを通じた安全なインターフェース
|
||||
- **ライフサイクル管理**: birth/finiによる明確な生存期間
|
||||
|
||||
## 🚀 Phase 9.75g-0での進化
|
||||
|
||||
- **BID-FFIプラグインシステム**: 外部ライブラリの安全な統合
|
||||
- **型情報管理**: nyash.tomlによる型安全な変換
|
||||
- **HostVtable**: プラグイン↔ホスト間の安全なメモリ管理
|
||||
- **plugin-tester**: メモリ安全性診断ツール
|
||||
|
||||
---
|
||||
|
||||
**関連ドキュメント**:
|
||||
- [Box型リファレンス](box-reference.md)
|
||||
- [プラグインシステム](../plugin-system/)
|
||||
- [BID-FFI仕様](../plugin-system/ffi-abi-specification.md)
|
||||
@ -1,235 +0,0 @@
|
||||
# ビルトインBox型 API リファレンス
|
||||
|
||||
Nyashで利用できる全ビルトインBox型のAPI仕様書です。
|
||||
|
||||
## 📡 P2PBox - 通信ノードBox
|
||||
|
||||
P2P通信を行うノードを表すBox。通信世界(IntentBox)に参加してメッセージを送受信できます。
|
||||
|
||||
### コンストラクタ
|
||||
```nyash
|
||||
// 通信ノードを作成
|
||||
local node = new P2PBox(node_id, world)
|
||||
```
|
||||
|
||||
**パラメータ:**
|
||||
- `node_id` (String): ノードの一意識別子
|
||||
- `world` (IntentBox): 参加する通信世界
|
||||
|
||||
### メソッド
|
||||
|
||||
#### send(intent, data, target)
|
||||
特定のノードにメッセージを送信します。
|
||||
```nyash
|
||||
local result = node.send("greeting", message_data, "target_node_id")
|
||||
```
|
||||
|
||||
**パラメータ:**
|
||||
- `intent` (String): メッセージの種類
|
||||
- `data` (Box): 送信するデータ
|
||||
- `target` (String): 送信先ノードID
|
||||
|
||||
**戻り値:** StringBox("sent")
|
||||
|
||||
#### on(intent, callback)
|
||||
指定したintentのメッセージを受信した際のリスナーを登録します。
|
||||
```nyash
|
||||
node.on("chat", callback_function)
|
||||
```
|
||||
|
||||
**パラメータ:**
|
||||
- `intent` (String): 監視するメッセージ種類
|
||||
- `callback` (MethodBox): 受信時に呼ばれる関数
|
||||
|
||||
**戻り値:** StringBox("listener added")
|
||||
|
||||
#### off(intent)
|
||||
指定したintentのリスナーを解除します。
|
||||
```nyash
|
||||
node.off("chat")
|
||||
```
|
||||
|
||||
**パラメータ:**
|
||||
- `intent` (String): 解除するメッセージ種類
|
||||
|
||||
**戻り値:** StringBox("listener removed" / "no listener found")
|
||||
|
||||
#### get_node_id()
|
||||
このノードのIDを取得します。
|
||||
```nyash
|
||||
local id = node.get_node_id()
|
||||
```
|
||||
|
||||
**戻り値:** StringBox(ノードID)
|
||||
|
||||
### 使用例
|
||||
```nyash
|
||||
// 通信世界を作成
|
||||
local world = new IntentBox()
|
||||
|
||||
// 2つのノードを作成
|
||||
local alice = new P2PBox("alice", world)
|
||||
local bob = new P2PBox("bob", world)
|
||||
|
||||
// Bobがgreetingを受信するリスナー設定
|
||||
bob.on("greeting", greeting_handler)
|
||||
|
||||
// AliceからBobにメッセージ送信
|
||||
local message = new MapBox()
|
||||
message.set("text", "Hello Bob!")
|
||||
alice.send("greeting", message, "bob")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📨 IntentBox - 通信世界Box
|
||||
|
||||
P2PBoxが通信を行うための世界(ネットワーク)を表すBox。複数のノードが同一のIntentBoxを共有して通信します。
|
||||
|
||||
### コンストラクタ
|
||||
```nyash
|
||||
// 通信世界を作成
|
||||
local world = new IntentBox()
|
||||
```
|
||||
|
||||
**パラメータ:** なし
|
||||
|
||||
### 特徴
|
||||
- ローカル通信: 同一プロセス内のP2PBox間でメッセージをやり取り
|
||||
- スレッドセーフ: Arc<Mutex>により並行アクセス対応
|
||||
- 将来拡張: WebSocket版や分散版への拡張予定
|
||||
|
||||
### 使用例
|
||||
```nyash
|
||||
// 1つの通信世界に複数ノードが参加
|
||||
local world = new IntentBox()
|
||||
local node1 = new P2PBox("server", world)
|
||||
local node2 = new P2PBox("client", world)
|
||||
|
||||
// 同一世界内での通信が可能
|
||||
node1.send("data", payload, "client")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 StringBox - 文字列Box
|
||||
|
||||
文字列データを格納・操作するBox。
|
||||
|
||||
### コンストラクタ
|
||||
```nyash
|
||||
local text = new StringBox("Hello")
|
||||
```
|
||||
|
||||
### 基本メソッド
|
||||
- `toString()`: 文字列表現を取得
|
||||
- `length()`: 文字列長を取得
|
||||
- `concat(other)`: 文字列結合
|
||||
- `substring(start, end)`: 部分文字列取得
|
||||
|
||||
---
|
||||
|
||||
## 🔢 IntegerBox - 整数Box
|
||||
|
||||
整数データを格納・操作するBox。
|
||||
|
||||
### コンストラクタ
|
||||
```nyash
|
||||
local num = new IntegerBox(42)
|
||||
```
|
||||
|
||||
### 基本メソッド
|
||||
- `toString()`: 文字列表現を取得
|
||||
- `add(other)`: 加算
|
||||
- `subtract(other)`: 減算
|
||||
- `multiply(other)`: 乗算
|
||||
- `divide(other)`: 除算
|
||||
|
||||
---
|
||||
|
||||
## 📺 ConsoleBox - コンソール出力Box
|
||||
|
||||
コンソールへの出力を行うBox。
|
||||
|
||||
### コンストラクタ
|
||||
```nyash
|
||||
local console = new ConsoleBox()
|
||||
```
|
||||
|
||||
### メソッド
|
||||
- `log(message)`: メッセージをログ出力
|
||||
- `error(message)`: エラーメッセージを出力
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ MapBox - 連想配列Box
|
||||
|
||||
キー・バリューペアでデータを格納するBox。
|
||||
|
||||
### コンストラクタ
|
||||
```nyash
|
||||
local map = new MapBox()
|
||||
```
|
||||
|
||||
### メソッド
|
||||
- `set(key, value)`: キー・バリューを設定
|
||||
- `get(key)`: 値を取得
|
||||
- `has(key)`: キーが存在するかチェック
|
||||
- `remove(key)`: キー・バリューを削除
|
||||
|
||||
## 📊 BufferBox - バイナリデータ処理Box
|
||||
|
||||
バイナリデータの読み書きを効率的に処理するBox。ファイル操作、ネットワーク通信、画像処理で使用。
|
||||
|
||||
### コンストラクタ
|
||||
```nyash
|
||||
// 空のバッファを作成
|
||||
local buffer = new BufferBox()
|
||||
```
|
||||
|
||||
### 基本メソッド
|
||||
- `write(data)`: バイトデータ書き込み (ArrayBox[integers])
|
||||
- `read(count)`: 指定バイト数読み取り → ArrayBox
|
||||
- `readAll()`: 全データ読み取り → ArrayBox
|
||||
- `clear()`: バッファクリア → StringBox("ok")
|
||||
- `length()`: データサイズ取得 → IntegerBox
|
||||
- `append(buffer)`: 他BufferBoxを追加 → IntegerBox(新サイズ)
|
||||
- `slice(start, end)`: 部分データ取得 → BufferBox
|
||||
|
||||
### ⭐ Phase 10: 高度なメモリ管理API
|
||||
|
||||
#### ゼロコピー検出API
|
||||
```nyash
|
||||
// ゼロコピー共有の検出
|
||||
local buffer1 = new BufferBox()
|
||||
local shared_buffer = buffer1.share_reference(null)
|
||||
|
||||
// 共有検出
|
||||
local is_shared = buffer1.is_shared_with(shared_buffer) // → BoolBox(true)
|
||||
```
|
||||
|
||||
- `is_shared_with(other)`: 他BufferBoxとのメモリ共有を検出 → BoolBox
|
||||
- `share_reference(data)`: Arc参照を共有した新BufferBoxを作成 → BufferBox
|
||||
- `memory_footprint()`: 現在のメモリ使用量を取得 → IntegerBox(bytes)
|
||||
|
||||
#### 実装詳細
|
||||
- **Arc::ptr_eq()**: 真のポインタ共有検出でゼロコピーを保証
|
||||
- **共有状態**: `share_reference()`で作成されたBufferは元のデータを共有
|
||||
- **独立性**: `clone_box()`は完全に独立したコピーを作成
|
||||
|
||||
### 使用例
|
||||
```nyash
|
||||
// HTTP転送でのゼロコピー検証
|
||||
static box ProxyServer {
|
||||
relay_data(client_data) {
|
||||
if (me.upstream_buffer.is_shared_with(client_data)) {
|
||||
print("✅ Zero-copy achieved!")
|
||||
}
|
||||
return me.upstream_buffer.share_reference(client_data)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
最終更新: 2025年8月15日 (Phase 10: BufferBox高度メモリ管理API追加)
|
||||
@ -1,252 +0,0 @@
|
||||
# 🔥 Nyash finiシステム - 論理的解放フック
|
||||
|
||||
**最終更新: 2025年8月13日 - ChatGPT5協議による革命的設計完了**
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
Nyashの`fini()`システムは、物理的メモリ破棄ではなく**論理的使用終了**を宣言する革新的なリソース管理システムです。Everything is Box哲学と完全に統合され、予測可能で安全なリソース管理を実現します。
|
||||
|
||||
## 🌟 核心コンセプト
|
||||
|
||||
### 📝 論理的解放フック
|
||||
```nyash
|
||||
box MyResource {
|
||||
init { name, file }
|
||||
|
||||
fini() {
|
||||
print("Resource " + me.name + " is being finalized")
|
||||
// ファイルクローズなどのクリーンアップ処理
|
||||
// 物理的メモリは共有参照が残っていても論理的には「終了」
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**重要**: `fini()`は「このオブジェクトをもう使わない」という宣言であり、物理的な即時破棄ではありません。
|
||||
|
||||
## 🔄 実行順序(最終仕様)
|
||||
|
||||
### 自動カスケード解放
|
||||
```nyash
|
||||
box Pipeline {
|
||||
init { r1, r2, r3, weak monitor }
|
||||
|
||||
fini() {
|
||||
// 1) ユーザー定義処理(柔軟な順序制御可能)
|
||||
me.r3.fini() // 依存関係でr3→r2の順
|
||||
me.r2.fini()
|
||||
|
||||
// 2) 自動カスケード: 残りのr1がinit宣言順で自動解放
|
||||
// 3) weakフィールドは対象外(lazy nil化)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 決定的な解放順序
|
||||
1. **finalized チェック** - 既に解放済みなら何もしない(idempotent)
|
||||
2. **再入防止** - `in_finalization`フラグで再帰呼び出し防止
|
||||
3. **ユーザー定義fini()実行** - カスタムクリーンアップ処理
|
||||
4. **自動カスケード** - `init`宣言順で未処理フィールドを解放
|
||||
5. **フィールドクリア** - 全フィールドを無効化
|
||||
6. **finalized設定** - 以後の使用を禁止
|
||||
|
||||
## ⚠️ 厳格な禁止事項
|
||||
|
||||
### weak フィールドへのfini呼び出し禁止
|
||||
```nyash
|
||||
box Parent {
|
||||
init { weak child }
|
||||
|
||||
fini() {
|
||||
// ❌ 絶対にダメ!ビルドエラーまたは実行時エラー
|
||||
// me.child.fini()
|
||||
|
||||
// ✅ 正しい方法
|
||||
me.child = null // 参照解除
|
||||
// または自動nil化に任せる
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**理由**: weak参照は所有権を持たない非所有参照のため、fini()を呼ぶ権利がありません。
|
||||
|
||||
### finalized後の使用禁止
|
||||
```nyash
|
||||
box Example { }
|
||||
|
||||
local x = new Example()
|
||||
x.fini()
|
||||
|
||||
// ❌ 以下は全てエラー
|
||||
x.someMethod() // → "Instance was finalized; further use is prohibited"
|
||||
x.field = value // → 同上
|
||||
local val = x.field // → 同上
|
||||
```
|
||||
|
||||
## 🏗️ 実装アーキテクチャ
|
||||
|
||||
### InstanceBox拡張
|
||||
```rust
|
||||
pub struct InstanceBox {
|
||||
// 既存フィールド...
|
||||
|
||||
init_field_order: Vec<String>, // 決定的カスケード順序
|
||||
weak_fields_union: HashSet<String>, // weak判定高速化
|
||||
in_finalization: bool, // 再入防止
|
||||
finalized: bool, // 使用禁止フラグ
|
||||
}
|
||||
```
|
||||
|
||||
### 実行時ガード
|
||||
- **メソッド呼び出し**: `finalized`チェック → エラー
|
||||
- **フィールドアクセス**: `finalized`チェック → エラー
|
||||
- **フィールド代入**: `finalized`チェック → エラー
|
||||
|
||||
## 💡 使用例とパターン
|
||||
|
||||
### 基本的な使用例
|
||||
```nyash
|
||||
box FileHandler {
|
||||
init { filename, handle }
|
||||
|
||||
pack(name) {
|
||||
me.filename = name
|
||||
me.handle = openFile(name)
|
||||
}
|
||||
|
||||
fini() {
|
||||
if (me.handle != null) {
|
||||
closeFile(me.handle)
|
||||
print("File " + me.filename + " closed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 使用
|
||||
local handler = new FileHandler("data.txt")
|
||||
// ... ファイル操作 ...
|
||||
handler.fini() // 明示的クリーンアップ
|
||||
```
|
||||
|
||||
### 再代入時の自動解放
|
||||
```nyash
|
||||
box Holder { init { resource } }
|
||||
box Resource { fini() { print("Resource cleaned up") } }
|
||||
|
||||
local h = new Holder()
|
||||
h.resource = new Resource() // 新しいリソース設定
|
||||
h.resource = new Resource() // → 前のリソースが自動的にfini()される
|
||||
```
|
||||
|
||||
### カスタム解放順序
|
||||
```nyash
|
||||
box DatabaseConnection {
|
||||
init { transaction, connection, logger }
|
||||
|
||||
fini() {
|
||||
// 依存関係に基づく手動順序制御
|
||||
if (me.transaction != null) {
|
||||
me.transaction.rollback()
|
||||
me.transaction.fini()
|
||||
}
|
||||
|
||||
if (me.connection != null) {
|
||||
me.connection.close()
|
||||
me.connection.fini()
|
||||
}
|
||||
|
||||
// loggerは自動カスケードに任せる
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 循環参照の安全な解決
|
||||
```nyash
|
||||
box Node {
|
||||
init { data, weak parent, children }
|
||||
|
||||
pack(value) {
|
||||
me.data = value
|
||||
me.children = new ArrayBox()
|
||||
}
|
||||
|
||||
addChild(child) {
|
||||
me.children.push(child)
|
||||
child.setParent(me) // 子→親はweak参照
|
||||
}
|
||||
|
||||
fini() {
|
||||
// 子ノードを先に解放
|
||||
loop (me.children.length() > 0) {
|
||||
local child = me.children.pop()
|
||||
child.fini()
|
||||
}
|
||||
// 親への参照は自動的にnil化される
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 テストパターン
|
||||
|
||||
### 基本動作テスト
|
||||
```nyash
|
||||
box Counter {
|
||||
init { value }
|
||||
pack() { me.value = 0 }
|
||||
increment() { me.value = me.value + 1 }
|
||||
fini() { print("Counter finalized with value: " + me.value.toString()) }
|
||||
}
|
||||
|
||||
local c = new Counter()
|
||||
c.increment()
|
||||
c.increment()
|
||||
c.fini()
|
||||
// c.increment() // → エラー: finalized後の使用禁止
|
||||
```
|
||||
|
||||
### 循環参照テスト
|
||||
```nyash
|
||||
box Parent {
|
||||
init { child }
|
||||
pack() {
|
||||
me.child = new Child()
|
||||
me.child.setParent(me)
|
||||
}
|
||||
fini() { print("Parent finalized") }
|
||||
}
|
||||
|
||||
box Child {
|
||||
init { weak parent }
|
||||
setParent(p) { me.parent = p }
|
||||
fini() { print("Child finalized") }
|
||||
}
|
||||
|
||||
local p = new Parent()
|
||||
p.fini() // Parent → Child の順で解放、リークなし
|
||||
```
|
||||
|
||||
## 🎯 期待される効果
|
||||
|
||||
### メモリ安全性
|
||||
- **循環参照リーク完全防止**: weak参照とfiniの組み合わせ
|
||||
- **二重解放防止**: idempotentな設計
|
||||
- **使用禁止ガード**: finalized後の誤用防止
|
||||
|
||||
### 予測可能性
|
||||
- **決定的順序**: init宣言順による自動カスケード
|
||||
- **明示的制御**: ユーザー定義fini()での柔軟な順序指定
|
||||
- **エラーメッセージ**: 明確で修正提案付きのエラー
|
||||
|
||||
### 開発体験
|
||||
- **直感的**: リソースの「終了宣言」として理解しやすい
|
||||
- **デバッグ容易**: 解放タイミングが明確
|
||||
- **保守性**: 依存関係の変更に強い設計
|
||||
|
||||
## 📚 関連ドキュメント
|
||||
|
||||
- [weak参照設計](weak-reference-design.md) - 循環参照解決との統合
|
||||
- [Everything is Box](design-philosophy.md) - 基本設計思想
|
||||
- [言語リファレンス](language-reference.md) - 構文詳細
|
||||
|
||||
---
|
||||
|
||||
**Everything is Box, Everything is Finalized!** 🔥
|
||||
@ -1,338 +0,0 @@
|
||||
# 🌟 Nyash Override + Delegation 統一構文仕様
|
||||
|
||||
バージョン: 2.0
|
||||
作成日: 2025年8月11日
|
||||
ステータス: 正式決定
|
||||
|
||||
## 📋 概要
|
||||
|
||||
Nyashプログラミング言語における明示的オーバーライドとデリゲーション構文の完全仕様。世界初の**完全明示デリゲーション言語**としてのNyashの核心機能を定義する。
|
||||
|
||||
## 🎯 設計哲学
|
||||
|
||||
### 基本原則
|
||||
1. **完全明示性**: すべての動作を明示的に宣言
|
||||
2. **曖昧性の完全排除**: 暗黙の動作は一切許可しない
|
||||
3. **統一構文**: デリゲーションとオーバーライドの完全統合
|
||||
4. **初学者フレンドリー**: 直感的で理解しやすい構文
|
||||
|
||||
### Everything is Box との整合性
|
||||
- すべてのオブジェクトがBox
|
||||
- デリゲーション先もBox
|
||||
- オーバーライドもBoxメソッドの置換
|
||||
|
||||
## 🔥 基本構文
|
||||
|
||||
### デリゲーション宣言
|
||||
```nyash
|
||||
box Child from Parent {
|
||||
// 親Boxからの機能デリゲーション
|
||||
}
|
||||
|
||||
// 多重デリゲーション
|
||||
box Child from Parent1, Parent2 {
|
||||
// 複数のBoxからの機能デリゲーション
|
||||
}
|
||||
```
|
||||
|
||||
### メソッドオーバーライド
|
||||
```nyash
|
||||
box Child from Parent {
|
||||
// 必須: overrideキーワードによる明示的宣言
|
||||
override methodName(params) {
|
||||
// オーバーライド実装
|
||||
from Parent.methodName(params) // 親実装呼び出し(任意)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### コンストラクタデリゲーション
|
||||
```nyash
|
||||
box Child from Parent {
|
||||
init(params) { # init構文に統一
|
||||
from Parent.init(params) # 必須: 親コンストラクタ明示呼び出し
|
||||
me.childSpecificField = value
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📚 詳細仕様
|
||||
|
||||
### 1. Override キーワード
|
||||
|
||||
#### 必須条件
|
||||
- 親Box(デリゲーション先)に同名メソッドが存在する場合のみ使用可能
|
||||
- 同名メソッドが存在しない場合は**コンパイルエラー**
|
||||
|
||||
#### 禁止事項
|
||||
- 同一Box内での同名メソッド重複定義は**すべてエラー**
|
||||
- 暗黙のオーバーライドは**完全禁止**
|
||||
|
||||
#### 構文例
|
||||
```nyash
|
||||
box MeshNode from P2PBox {
|
||||
// ✅ 正しい使用法
|
||||
override send(intent, data, target) {
|
||||
me.routing.log(target)
|
||||
from P2PBox.send(intent, data, target)
|
||||
}
|
||||
|
||||
// ❌ エラー: P2PBoxに存在しないメソッド
|
||||
override nonExistentMethod() {
|
||||
// Error: Method 'nonExistentMethod' does not exist in parent P2PBox
|
||||
}
|
||||
|
||||
// ❌ エラー: overrideなしで親メソッドと同名
|
||||
send(intent, data, target) {
|
||||
// Error: Method 'send' overrides parent method. Add 'override' keyword.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. From デリゲーション構文
|
||||
|
||||
#### 基本構文
|
||||
```nyash
|
||||
from ParentBox.methodName(args)
|
||||
from ParentBox.fieldName
|
||||
```
|
||||
|
||||
#### メソッド呼び出し
|
||||
```nyash
|
||||
// 親の特定メソッドを明示的に呼び出し
|
||||
from P2PBox.send(intent, data, target)
|
||||
|
||||
// 複数親からの呼び出し
|
||||
from Logger.log("Starting operation")
|
||||
from P2PBox.send(intent, data, target)
|
||||
from Cache.store(data)
|
||||
```
|
||||
|
||||
#### フィールドアクセス
|
||||
```nyash
|
||||
// 親のフィールドへのアクセス
|
||||
local status = from P2PBox.connectionStatus
|
||||
from Logger.logLevel = "DEBUG"
|
||||
```
|
||||
|
||||
#### コンストラクタ呼び出し
|
||||
```nyash
|
||||
init(nodeId, world) { # init構文に統一
|
||||
from P2PBox.init(nodeId, world) # 完全統一構文
|
||||
me.routing = RoutingTable()
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 多重デリゲーション
|
||||
|
||||
#### 基本形式
|
||||
```nyash
|
||||
box ComplexNode from P2PBox, Logger, Cache {
|
||||
override send(intent, data, target) {
|
||||
from Logger.debug("Sending: " + intent) // Logger親から
|
||||
from Cache.store(intent, data) // Cache親から
|
||||
from P2PBox.send(intent, data, target) // P2PBox親から
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 曖昧性の解消
|
||||
```nyash
|
||||
// 複数親に同名メソッドが存在する場合
|
||||
box ConflictNode from ParentA, ParentB {
|
||||
// ❌ エラー: どちらのprocessを置換するか不明
|
||||
override process(data) {
|
||||
// Error: Method 'process' exists in multiple parents. Use specific parent.
|
||||
}
|
||||
|
||||
// ✅ 正しい解決法: 親を明示指定
|
||||
override ParentA.process(data) {
|
||||
// ParentAのprocessをオーバーライド
|
||||
from ParentA.process(data)
|
||||
}
|
||||
|
||||
override ParentB.process(data) {
|
||||
// ParentBのprocessをオーバーライド
|
||||
from ParentB.process(data)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. エラーメッセージ仕様
|
||||
|
||||
#### 重複定義エラー
|
||||
```
|
||||
Error: Method 'send' is already defined in this box at line 15.
|
||||
--> box.nyash:20:5
|
||||
|
|
||||
20 | send(msg) {
|
||||
| ^^^^ duplicate method definition
|
||||
|
|
||||
Help: Remove duplicate definition or rename method.
|
||||
```
|
||||
|
||||
#### Missing Override エラー
|
||||
```
|
||||
Error: Method 'send' overrides a parent method. Add 'override' keyword.
|
||||
--> box.nyash:18:5
|
||||
|
|
||||
18 | send(intent, data, target) {
|
||||
| ^^^^ missing 'override' keyword
|
||||
|
|
||||
Help: Change to 'override send(intent, data, target) {'
|
||||
```
|
||||
|
||||
#### Wrong Override エラー
|
||||
```
|
||||
Error: Method 'newMethod' does not exist in any parent. Remove 'override' keyword.
|
||||
--> box.nyash:22:5
|
||||
|
|
||||
22 | override newMethod() {
|
||||
| ^^^^^^^^ unnecessary 'override'
|
||||
|
|
||||
Help: Remove 'override' or verify parent method name.
|
||||
```
|
||||
|
||||
#### 曖昧Override エラー
|
||||
```
|
||||
Error: Method 'process' exists in multiple parents. Specify which parent to override.
|
||||
--> box.nyash:25:5
|
||||
|
|
||||
25 | override process(data) {
|
||||
| ^^^^^^^^ ambiguous override
|
||||
|
|
||||
Help: Use 'override ParentA.process' or 'override ParentB.process'
|
||||
```
|
||||
|
||||
## 🚫 禁止事項
|
||||
|
||||
### 1. 暗黙のオーバーライド
|
||||
```nyash
|
||||
box Child from Parent {
|
||||
send(msg) { // ❌ エラー: overrideキーワードなし
|
||||
print("Child implementation")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. コンストラクタオーバーロード
|
||||
```nyash
|
||||
box Node {
|
||||
init(id) { // 最初の定義
|
||||
me.id = id
|
||||
}
|
||||
|
||||
init(id, name) { // ❌ エラー: 重複定義
|
||||
me.id = id
|
||||
me.name = name
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 同名メソッド重複定義
|
||||
```nyash
|
||||
box Example {
|
||||
process(data) { // 最初の定義
|
||||
print("Version 1")
|
||||
}
|
||||
|
||||
process(data) { // ❌ エラー: 重複定義
|
||||
print("Version 2")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## ✅ ベストプラクティス
|
||||
|
||||
### 1. 明示的な親呼び出し
|
||||
```nyash
|
||||
box MeshNode from P2PBox {
|
||||
override send(intent, data, target) {
|
||||
// 前処理
|
||||
me.routing.logOutgoing(target)
|
||||
|
||||
// 親実装呼び出し(明示的)
|
||||
from P2PBox.send(intent, data, target)
|
||||
|
||||
// 後処理
|
||||
me.statistics.incrementSentCount()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 多重デリゲーションでの順序指定
|
||||
```nyash
|
||||
box SmartNode from P2PBox, Logger, Cache {
|
||||
override send(intent, data, target) {
|
||||
// 1. ログ記録
|
||||
from Logger.info("Sending to: " + target)
|
||||
|
||||
// 2. キャッシュ保存
|
||||
from Cache.store(intent + ":" + target, data)
|
||||
|
||||
// 3. 実際の送信
|
||||
from P2PBox.send(intent, data, target)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. コンストラクタチェーン
|
||||
```nyash
|
||||
box SecureNode from P2PBox {
|
||||
init security = SecurityManager()
|
||||
|
||||
init(nodeId, world, keyFile) { # init構文に統一
|
||||
// 1. 親初期化(必須)
|
||||
from P2PBox.init(nodeId, world)
|
||||
|
||||
// 2. 子固有の初期化
|
||||
me.security = SecurityManager()
|
||||
me.security.loadKeys(keyFile)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔮 将来の拡張
|
||||
|
||||
### 1. Final メソッド(検討中)
|
||||
```nyash
|
||||
box Parent {
|
||||
final criticalMethod() { // オーバーライド禁止
|
||||
// 重要な処理
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Abstract メソッド(検討中)
|
||||
```nyash
|
||||
box AbstractParent {
|
||||
abstract process(data) // 子でのoverride必須
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Override チェック強化(検討中)
|
||||
```nyash
|
||||
override! send(data) { // 親呼び出し必須チェック
|
||||
// from Parent.send(data) がないとエラー
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 他言語との比較
|
||||
|
||||
| 言語 | 継承方式 | オーバーライド | 親呼び出し | 多重継承 |
|
||||
|------|----------|---------------|-----------|----------|
|
||||
| **Nyash** | デリゲーション | `override` 必須 | `from Parent.method()` | 明示的解消 |
|
||||
| Java | クラス継承 | `@Override` 注釈 | `super.method()` | 不可 |
|
||||
| Python | クラス継承 | 暗黙 | `super().method()` | MRO(複雑) |
|
||||
| C# | クラス継承 | `override` 必須 | `base.method()` | 不可 |
|
||||
| TypeScript | プロトタイプ | 暗黙 | `super.method()` | 不可 |
|
||||
|
||||
### Nyashの優位性
|
||||
1. **完全な明示性**: すべての動作が明確
|
||||
2. **曖昧性の完全排除**: 多重デリゲーションでも安全
|
||||
3. **統一構文**: デリゲーションとオーバーライドが統合
|
||||
4. **初学者フレンドリー**: 分かりやすいエラーメッセージ
|
||||
|
||||
---
|
||||
|
||||
**この仕様により、Nyashは世界初の「完全明示デリゲーション言語」として、プログラミング言語史に新たな1ページを刻むことになります。** 🌟
|
||||
1
local_tests/test_just_42.nyash
Normal file
1
local_tests/test_just_42.nyash
Normal file
@ -0,0 +1 @@
|
||||
42
|
||||
11
local_tests/test_llvm_mock.nyash
Normal file
11
local_tests/test_llvm_mock.nyash
Normal file
@ -0,0 +1,11 @@
|
||||
// Test LLVM mock interpreter
|
||||
static box Main {
|
||||
init { result }
|
||||
|
||||
main() {
|
||||
local a = 10
|
||||
local b = 32
|
||||
local sum = a + b
|
||||
return sum // Should return 42
|
||||
}
|
||||
}
|
||||
1
local_tests/test_print_42.nyash
Normal file
1
local_tests/test_print_42.nyash
Normal file
@ -0,0 +1 @@
|
||||
print(42)
|
||||
253
local_tests/test_simple.wat
Normal file
253
local_tests/test_simple.wat
Normal file
@ -0,0 +1,253 @@
|
||||
(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 4102) "\53\74\72\69\6e\67\42\6f\78")
|
||||
(data (i32.const 4096) "\5f\5f\6d\65\5f\5f")
|
||||
(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 6
|
||||
i32.store
|
||||
call $alloc_stringbox
|
||||
local.set $2
|
||||
local.get $2
|
||||
i32.const 12
|
||||
i32.add
|
||||
i32.const 4102
|
||||
i32.store
|
||||
local.get $2
|
||||
i32.const 16
|
||||
i32.add
|
||||
i32.const 9
|
||||
i32.store
|
||||
local.get $2
|
||||
local.set $1
|
||||
local.get $0
|
||||
i32.const 12
|
||||
i32.add
|
||||
local.get $1
|
||||
i32.store
|
||||
call $alloc_stringbox
|
||||
local.set $3
|
||||
local.get $3
|
||||
i32.const 12
|
||||
i32.add
|
||||
i32.const 4096
|
||||
i32.store
|
||||
local.get $3
|
||||
i32.const 16
|
||||
i32.add
|
||||
i32.const 6
|
||||
i32.store
|
||||
local.get $3
|
||||
i32.const 12
|
||||
i32.add
|
||||
i32.load
|
||||
local.set $4
|
||||
local.get $4
|
||||
return
|
||||
)
|
||||
(export "main" (func $main))
|
||||
)
|
||||
8
local_tests/test_simple_literal.nyash
Normal file
8
local_tests/test_simple_literal.nyash
Normal file
@ -0,0 +1,8 @@
|
||||
// Simplest possible test
|
||||
static box Main {
|
||||
init { }
|
||||
|
||||
main() {
|
||||
return 42
|
||||
}
|
||||
}
|
||||
29
src/bid-converter-copilot/README.md
Normal file
29
src/bid-converter-copilot/README.md
Normal file
@ -0,0 +1,29 @@
|
||||
# BID Converter from Copilot
|
||||
|
||||
このフォルダには、Copilotさんが実装してくれたBID (Box Interface Definition) の変換部分を保存しています。
|
||||
|
||||
## 📦 含まれるファイル
|
||||
|
||||
- **tlv.rs**: TLV (Type-Length-Value) エンコード/デコード実装
|
||||
- **types.rs**: BID型定義(NyashValue変換等)
|
||||
- **error.rs**: BIDエラー型定義
|
||||
|
||||
## 🎯 用途
|
||||
|
||||
将来的にnyash2.tomlを実装する際に、以下の用途で活用予定:
|
||||
|
||||
1. **型変換**: Nyash型 ↔ BID型の相互変換
|
||||
2. **シリアライズ**: プラグイン通信用のデータ変換
|
||||
3. **エラーハンドリング**: 統一的なエラー処理
|
||||
|
||||
## 💡 なぜ保存?
|
||||
|
||||
- CopilotさんのTLV実装は汎用的で再利用価値が高い
|
||||
- 現在のnyash.tomlベースの実装をシンプルに保ちつつ、将来の拡張に備える
|
||||
- プラグイン間通信やネットワーク通信でも活用可能
|
||||
|
||||
## 📝 メモ
|
||||
|
||||
- 現在は使用していない(既存のnyash.tomlベースが動作中)
|
||||
- Phase 9.8以降で活用予定
|
||||
- 他言語プラグイン対応時には必須になる可能性
|
||||
80
src/bid-converter-copilot/error.rs
Normal file
80
src/bid-converter-copilot/error.rs
Normal file
@ -0,0 +1,80 @@
|
||||
/// BID-1 Standard Error Codes
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BidError {
|
||||
/// Operation successful
|
||||
Success = 0,
|
||||
|
||||
/// Buffer too small (need to call again with larger buffer)
|
||||
ShortBuffer = -1,
|
||||
|
||||
/// Invalid type ID
|
||||
InvalidType = -2,
|
||||
|
||||
/// Invalid method ID
|
||||
InvalidMethod = -3,
|
||||
|
||||
/// Invalid arguments
|
||||
InvalidArgs = -4,
|
||||
|
||||
/// Plugin internal error
|
||||
PluginError = -5,
|
||||
|
||||
/// Memory allocation failed
|
||||
OutOfMemory = -6,
|
||||
|
||||
/// UTF-8 encoding error
|
||||
InvalidUtf8 = -7,
|
||||
|
||||
/// Handle not found
|
||||
InvalidHandle = -8,
|
||||
|
||||
/// Version mismatch
|
||||
VersionMismatch = -9,
|
||||
}
|
||||
|
||||
impl BidError {
|
||||
/// Convert from raw i32
|
||||
pub fn from_raw(code: i32) -> Self {
|
||||
match code {
|
||||
0 => BidError::Success,
|
||||
-1 => BidError::ShortBuffer,
|
||||
-2 => BidError::InvalidType,
|
||||
-3 => BidError::InvalidMethod,
|
||||
-4 => BidError::InvalidArgs,
|
||||
-5 => BidError::PluginError,
|
||||
-6 => BidError::OutOfMemory,
|
||||
-7 => BidError::InvalidUtf8,
|
||||
-8 => BidError::InvalidHandle,
|
||||
-9 => BidError::VersionMismatch,
|
||||
_ => BidError::PluginError, // Unknown errors map to plugin error
|
||||
}
|
||||
}
|
||||
|
||||
/// Get human-readable error message
|
||||
pub fn message(&self) -> &'static str {
|
||||
match self {
|
||||
BidError::Success => "Operation successful",
|
||||
BidError::ShortBuffer => "Buffer too small, call again with larger buffer",
|
||||
BidError::InvalidType => "Invalid type ID",
|
||||
BidError::InvalidMethod => "Invalid method ID",
|
||||
BidError::InvalidArgs => "Invalid arguments",
|
||||
BidError::PluginError => "Plugin internal error",
|
||||
BidError::OutOfMemory => "Memory allocation failed",
|
||||
BidError::InvalidUtf8 => "Invalid UTF-8 encoding",
|
||||
BidError::InvalidHandle => "Handle not found",
|
||||
BidError::VersionMismatch => "BID version mismatch",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for BidError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} (code: {})", self.message(), *self as i32)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for BidError {}
|
||||
|
||||
/// Result type for BID operations
|
||||
pub type BidResult<T> = Result<T, BidError>;
|
||||
13
src/bid-converter-copilot/mod.rs
Normal file
13
src/bid-converter-copilot/mod.rs
Normal file
@ -0,0 +1,13 @@
|
||||
//! BID Converter Module (from Copilot)
|
||||
//!
|
||||
//! 将来的にnyash2.tomlで使用予定の変換ロジック
|
||||
//! 現在は参照用に保存
|
||||
|
||||
pub mod tlv;
|
||||
pub mod types;
|
||||
pub mod error;
|
||||
|
||||
// 将来的に必要になったらアンコメント
|
||||
// pub use tlv::*;
|
||||
// pub use types::*;
|
||||
// pub use error::*;
|
||||
324
src/bid-converter-copilot/tlv.rs
Normal file
324
src/bid-converter-copilot/tlv.rs
Normal file
@ -0,0 +1,324 @@
|
||||
use super::{BidError, BidResult, BidHandle, BidTag, BID_VERSION};
|
||||
use std::mem;
|
||||
|
||||
/// BID-1 TLV Header
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct BidTlvHeader {
|
||||
pub version: u16, // BID version (1)
|
||||
pub argc: u16, // Argument count
|
||||
}
|
||||
|
||||
/// TLV Entry structure
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct TlvEntry {
|
||||
pub tag: u8, // Type tag
|
||||
pub reserved: u8, // Reserved for future use (0)
|
||||
pub size: u16, // Payload size
|
||||
// Payload follows immediately after
|
||||
}
|
||||
|
||||
/// TLV encoder for BID-1 format
|
||||
pub struct TlvEncoder {
|
||||
buffer: Vec<u8>,
|
||||
entry_count: u16,
|
||||
}
|
||||
|
||||
impl TlvEncoder {
|
||||
/// Create a new TLV encoder
|
||||
pub fn new() -> Self {
|
||||
let mut encoder = Self {
|
||||
buffer: Vec::with_capacity(256),
|
||||
entry_count: 0,
|
||||
};
|
||||
|
||||
// Reserve space for header
|
||||
encoder.buffer.extend_from_slice(&[0; mem::size_of::<BidTlvHeader>()]);
|
||||
encoder
|
||||
}
|
||||
|
||||
/// Encode a boolean value
|
||||
pub fn encode_bool(&mut self, value: bool) -> BidResult<()> {
|
||||
self.encode_entry(BidTag::Bool, &[if value { 1 } else { 0 }])
|
||||
}
|
||||
|
||||
/// Encode a 32-bit integer
|
||||
pub fn encode_i32(&mut self, value: i32) -> BidResult<()> {
|
||||
self.encode_entry(BidTag::I32, &value.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Encode a 64-bit integer
|
||||
pub fn encode_i64(&mut self, value: i64) -> BidResult<()> {
|
||||
self.encode_entry(BidTag::I64, &value.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Encode a 32-bit float
|
||||
pub fn encode_f32(&mut self, value: f32) -> BidResult<()> {
|
||||
self.encode_entry(BidTag::F32, &value.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Encode a 64-bit float
|
||||
pub fn encode_f64(&mut self, value: f64) -> BidResult<()> {
|
||||
self.encode_entry(BidTag::F64, &value.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Encode a string
|
||||
pub fn encode_string(&mut self, value: &str) -> BidResult<()> {
|
||||
let bytes = value.as_bytes();
|
||||
if bytes.len() > u16::MAX as usize {
|
||||
return Err(BidError::InvalidArgs);
|
||||
}
|
||||
self.encode_entry(BidTag::String, bytes)
|
||||
}
|
||||
|
||||
/// Encode binary data
|
||||
pub fn encode_bytes(&mut self, value: &[u8]) -> BidResult<()> {
|
||||
if value.len() > u16::MAX as usize {
|
||||
return Err(BidError::InvalidArgs);
|
||||
}
|
||||
self.encode_entry(BidTag::Bytes, value)
|
||||
}
|
||||
|
||||
/// Encode a handle
|
||||
pub fn encode_handle(&mut self, handle: BidHandle) -> BidResult<()> {
|
||||
self.encode_entry(BidTag::Handle, &handle.to_u64().to_le_bytes())
|
||||
}
|
||||
|
||||
/// Encode void (no payload)
|
||||
pub fn encode_void(&mut self) -> BidResult<()> {
|
||||
self.encode_entry(BidTag::Void, &[])
|
||||
}
|
||||
|
||||
/// Internal: encode a TLV entry
|
||||
fn encode_entry(&mut self, tag: BidTag, payload: &[u8]) -> BidResult<()> {
|
||||
let entry = TlvEntry {
|
||||
tag: tag as u8,
|
||||
reserved: 0,
|
||||
size: payload.len() as u16,
|
||||
};
|
||||
|
||||
// Write entry header
|
||||
self.buffer.push(entry.tag);
|
||||
self.buffer.push(entry.reserved);
|
||||
self.buffer.extend_from_slice(&entry.size.to_le_bytes());
|
||||
|
||||
// Write payload
|
||||
self.buffer.extend_from_slice(payload);
|
||||
|
||||
self.entry_count += 1;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Finalize the encoding and return the buffer
|
||||
pub fn finish(mut self) -> Vec<u8> {
|
||||
// Update header
|
||||
let header = BidTlvHeader {
|
||||
version: BID_VERSION,
|
||||
argc: self.entry_count,
|
||||
};
|
||||
|
||||
// Write header at the beginning
|
||||
self.buffer[0..2].copy_from_slice(&header.version.to_le_bytes());
|
||||
self.buffer[2..4].copy_from_slice(&header.argc.to_le_bytes());
|
||||
self.buffer
|
||||
}
|
||||
}
|
||||
|
||||
/// TLV decoder for BID-1 format
|
||||
pub struct TlvDecoder<'a> {
|
||||
data: &'a [u8],
|
||||
position: usize,
|
||||
header: BidTlvHeader,
|
||||
}
|
||||
|
||||
impl<'a> TlvDecoder<'a> {
|
||||
/// Create a new TLV decoder
|
||||
pub fn new(data: &'a [u8]) -> BidResult<Self> {
|
||||
if data.len() < mem::size_of::<BidTlvHeader>() {
|
||||
return Err(BidError::InvalidArgs);
|
||||
}
|
||||
|
||||
// Read header safely
|
||||
let version = u16::from_le_bytes([data[0], data[1]]);
|
||||
let argc = u16::from_le_bytes([data[2], data[3]]);
|
||||
let header = BidTlvHeader { version, argc };
|
||||
|
||||
if header.version != BID_VERSION {
|
||||
return Err(BidError::VersionMismatch);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
data,
|
||||
position: mem::size_of::<BidTlvHeader>(),
|
||||
header,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the argument count
|
||||
pub fn arg_count(&self) -> u16 {
|
||||
self.header.argc
|
||||
}
|
||||
|
||||
/// Decode the next entry
|
||||
pub fn decode_next(&mut self) -> BidResult<Option<(BidTag, &'a [u8])>> {
|
||||
if self.position >= self.data.len() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
// Read entry header
|
||||
if self.position + mem::size_of::<TlvEntry>() > self.data.len() {
|
||||
return Err(BidError::InvalidArgs);
|
||||
}
|
||||
|
||||
// Read entry safely
|
||||
let tag = self.data[self.position];
|
||||
let reserved = self.data[self.position + 1];
|
||||
let size = u16::from_le_bytes([
|
||||
self.data[self.position + 2],
|
||||
self.data[self.position + 3],
|
||||
]);
|
||||
let entry = TlvEntry { tag, reserved, size };
|
||||
self.position += mem::size_of::<TlvEntry>();
|
||||
|
||||
// Read payload
|
||||
let payload_end = self.position + entry.size as usize;
|
||||
if payload_end > self.data.len() {
|
||||
return Err(BidError::InvalidArgs);
|
||||
}
|
||||
|
||||
let payload = &self.data[self.position..payload_end];
|
||||
self.position = payload_end;
|
||||
|
||||
// Convert tag
|
||||
let tag = match entry.tag {
|
||||
1 => BidTag::Bool,
|
||||
2 => BidTag::I32,
|
||||
3 => BidTag::I64,
|
||||
4 => BidTag::F32,
|
||||
5 => BidTag::F64,
|
||||
6 => BidTag::String,
|
||||
7 => BidTag::Bytes,
|
||||
8 => BidTag::Handle,
|
||||
9 => BidTag::Void,
|
||||
20 => BidTag::Result,
|
||||
21 => BidTag::Option,
|
||||
22 => BidTag::Array,
|
||||
_ => return Err(BidError::InvalidType),
|
||||
};
|
||||
|
||||
Ok(Some((tag, payload)))
|
||||
}
|
||||
|
||||
/// Decode a boolean from payload
|
||||
pub fn decode_bool(payload: &[u8]) -> BidResult<bool> {
|
||||
if payload.len() != 1 {
|
||||
return Err(BidError::InvalidArgs);
|
||||
}
|
||||
Ok(payload[0] != 0)
|
||||
}
|
||||
|
||||
/// Decode an i32 from payload
|
||||
pub fn decode_i32(payload: &[u8]) -> BidResult<i32> {
|
||||
if payload.len() != 4 {
|
||||
return Err(BidError::InvalidArgs);
|
||||
}
|
||||
Ok(i32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]))
|
||||
}
|
||||
|
||||
/// Decode an i64 from payload
|
||||
pub fn decode_i64(payload: &[u8]) -> BidResult<i64> {
|
||||
if payload.len() != 8 {
|
||||
return Err(BidError::InvalidArgs);
|
||||
}
|
||||
let mut bytes = [0u8; 8];
|
||||
bytes.copy_from_slice(payload);
|
||||
Ok(i64::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
/// Decode a handle from payload
|
||||
pub fn decode_handle(payload: &[u8]) -> BidResult<BidHandle> {
|
||||
if payload.len() != 8 {
|
||||
return Err(BidError::InvalidArgs);
|
||||
}
|
||||
let mut bytes = [0u8; 8];
|
||||
bytes.copy_from_slice(payload);
|
||||
Ok(BidHandle::from_u64(u64::from_le_bytes(bytes)))
|
||||
}
|
||||
|
||||
/// Decode an f32 from payload
|
||||
pub fn decode_f32(payload: &[u8]) -> BidResult<f32> {
|
||||
if payload.len() != 4 {
|
||||
return Err(BidError::InvalidArgs);
|
||||
}
|
||||
Ok(f32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]))
|
||||
}
|
||||
|
||||
/// Decode an f64 from payload
|
||||
pub fn decode_f64(payload: &[u8]) -> BidResult<f64> {
|
||||
if payload.len() != 8 {
|
||||
return Err(BidError::InvalidArgs);
|
||||
}
|
||||
let mut bytes = [0u8; 8];
|
||||
bytes.copy_from_slice(payload);
|
||||
Ok(f64::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
/// Decode a string from payload
|
||||
pub fn decode_string(payload: &[u8]) -> BidResult<&str> {
|
||||
std::str::from_utf8(payload).map_err(|_| BidError::InvalidUtf8)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_encode_decode_primitives() {
|
||||
let mut encoder = TlvEncoder::new();
|
||||
encoder.encode_bool(true).unwrap();
|
||||
encoder.encode_i32(42).unwrap();
|
||||
encoder.encode_i64(9876543210).unwrap();
|
||||
encoder.encode_string("Hello Nyash!").unwrap();
|
||||
|
||||
let data = encoder.finish();
|
||||
let mut decoder = TlvDecoder::new(&data).unwrap();
|
||||
|
||||
assert_eq!(decoder.arg_count(), 4);
|
||||
|
||||
// Decode bool
|
||||
let (tag, payload) = decoder.decode_next().unwrap().unwrap();
|
||||
assert_eq!(tag, BidTag::Bool);
|
||||
assert_eq!(TlvDecoder::decode_bool(payload).unwrap(), true);
|
||||
|
||||
// Decode i32
|
||||
let (tag, payload) = decoder.decode_next().unwrap().unwrap();
|
||||
assert_eq!(tag, BidTag::I32);
|
||||
assert_eq!(TlvDecoder::decode_i32(payload).unwrap(), 42);
|
||||
|
||||
// Decode i64
|
||||
let (tag, payload) = decoder.decode_next().unwrap().unwrap();
|
||||
assert_eq!(tag, BidTag::I64);
|
||||
assert_eq!(TlvDecoder::decode_i64(payload).unwrap(), 9876543210);
|
||||
|
||||
// Decode string
|
||||
let (tag, payload) = decoder.decode_next().unwrap().unwrap();
|
||||
assert_eq!(tag, BidTag::String);
|
||||
assert_eq!(TlvDecoder::decode_string(payload).unwrap(), "Hello Nyash!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_decode_handle() {
|
||||
let mut encoder = TlvEncoder::new();
|
||||
let handle = BidHandle::new(6, 12345);
|
||||
encoder.encode_handle(handle).unwrap();
|
||||
|
||||
let data = encoder.finish();
|
||||
let mut decoder = TlvDecoder::new(&data).unwrap();
|
||||
|
||||
let (tag, payload) = decoder.decode_next().unwrap().unwrap();
|
||||
assert_eq!(tag, BidTag::Handle);
|
||||
assert_eq!(TlvDecoder::decode_handle(payload).unwrap(), handle);
|
||||
}
|
||||
}
|
||||
242
src/bid-converter-copilot/types.rs
Normal file
242
src/bid-converter-copilot/types.rs
Normal file
@ -0,0 +1,242 @@
|
||||
use super::Usize;
|
||||
|
||||
/// BID-1 Type System (ChatGPT Enhanced Edition)
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum BidType {
|
||||
// === Primitives (pass by value across FFI) ===
|
||||
Bool, // i32 (0=false, 1=true)
|
||||
I32, // 32-bit signed integer
|
||||
I64, // 64-bit signed integer
|
||||
F32, // 32-bit floating point
|
||||
F64, // 64-bit floating point
|
||||
|
||||
// === Composite types (pass as ptr+len) ===
|
||||
String, // UTF-8 string (ptr: usize, len: usize)
|
||||
Bytes, // Binary data (ptr: usize, len: usize)
|
||||
|
||||
// === Handle design (ChatGPT recommendation) ===
|
||||
Handle {
|
||||
type_id: u32, // Box type ID (1=StringBox, 6=FileBox, etc.)
|
||||
instance_id: u32, // Instance identifier
|
||||
},
|
||||
|
||||
// === Meta types ===
|
||||
Void, // No return value
|
||||
|
||||
// === Phase 2 reserved (TLV tags reserved) ===
|
||||
#[allow(dead_code)]
|
||||
Option(Box<BidType>), // TLV tag=21
|
||||
#[allow(dead_code)]
|
||||
Result(Box<BidType>, Box<BidType>), // TLV tag=20
|
||||
#[allow(dead_code)]
|
||||
Array(Box<BidType>), // TLV tag=22
|
||||
}
|
||||
|
||||
/// Handle representation for efficient Box references
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct BidHandle {
|
||||
pub type_id: u32,
|
||||
pub instance_id: u32,
|
||||
}
|
||||
|
||||
impl BidHandle {
|
||||
/// Create a new handle
|
||||
pub fn new(type_id: u32, instance_id: u32) -> Self {
|
||||
Self { type_id, instance_id }
|
||||
}
|
||||
|
||||
/// Pack into single u64 (type_id << 32 | instance_id)
|
||||
pub fn to_u64(&self) -> u64 {
|
||||
((self.type_id as u64) << 32) | (self.instance_id as u64)
|
||||
}
|
||||
|
||||
/// Unpack from single u64
|
||||
pub fn from_u64(packed: u64) -> Self {
|
||||
Self {
|
||||
type_id: (packed >> 32) as u32,
|
||||
instance_id: (packed & 0xFFFFFFFF) as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// TLV (Type-Length-Value) tags for BID-1
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BidTag {
|
||||
Bool = 1, // payload: 1 byte (0/1)
|
||||
I32 = 2, // payload: 4 bytes (little-endian)
|
||||
I64 = 3, // payload: 8 bytes (little-endian)
|
||||
F32 = 4, // payload: 4 bytes (IEEE 754)
|
||||
F64 = 5, // payload: 8 bytes (IEEE 754)
|
||||
String = 6, // payload: UTF-8 bytes
|
||||
Bytes = 7, // payload: binary data
|
||||
Handle = 8, // payload: 8 bytes (type_id + instance_id)
|
||||
Void = 9, // payload: 0 bytes
|
||||
|
||||
// Phase 2 reserved
|
||||
Result = 20,
|
||||
Option = 21,
|
||||
Array = 22,
|
||||
}
|
||||
|
||||
impl BidType {
|
||||
/// Get the TLV tag for this type
|
||||
pub fn tag(&self) -> BidTag {
|
||||
match self {
|
||||
BidType::Bool => BidTag::Bool,
|
||||
BidType::I32 => BidTag::I32,
|
||||
BidType::I64 => BidTag::I64,
|
||||
BidType::F32 => BidTag::F32,
|
||||
BidType::F64 => BidTag::F64,
|
||||
BidType::String => BidTag::String,
|
||||
BidType::Bytes => BidTag::Bytes,
|
||||
BidType::Handle { .. } => BidTag::Handle,
|
||||
BidType::Void => BidTag::Void,
|
||||
_ => panic!("Phase 2 types not yet implemented"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the expected payload size (None for variable-length types)
|
||||
pub fn payload_size(&self) -> Option<usize> {
|
||||
match self {
|
||||
BidType::Bool => Some(1),
|
||||
BidType::I32 => Some(4),
|
||||
BidType::I64 => Some(8),
|
||||
BidType::F32 => Some(4),
|
||||
BidType::F64 => Some(8),
|
||||
BidType::Handle { .. } => Some(8),
|
||||
BidType::Void => Some(0),
|
||||
BidType::String | BidType::Bytes => None, // Variable length
|
||||
_ => panic!("Phase 2 types not yet implemented"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Box type IDs (matching existing Nyash boxes)
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BoxTypeId {
|
||||
StringBox = 1,
|
||||
IntegerBox = 2,
|
||||
BoolBox = 3,
|
||||
FloatBox = 4,
|
||||
ArrayBox = 5,
|
||||
FileBox = 6, // Plugin example
|
||||
FutureBox = 7, // Existing async support
|
||||
P2PBox = 8, // Existing P2P support
|
||||
// ... more box types
|
||||
}
|
||||
|
||||
// ========== Type Information Management ==========
|
||||
// nyash.tomlでの型情報管理のための構造体
|
||||
// ハードコーディングを避け、動的な型変換を実現
|
||||
|
||||
/// メソッドの型情報
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MethodTypeInfo {
|
||||
/// 引数の型マッピング情報
|
||||
pub args: Vec<ArgTypeMapping>,
|
||||
/// 戻り値の型(将来拡張用)
|
||||
pub returns: Option<String>,
|
||||
}
|
||||
|
||||
/// 引数の型マッピング情報
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ArgTypeMapping {
|
||||
/// 引数名(ドキュメント用、オプション)
|
||||
pub name: Option<String>,
|
||||
/// Nyash側の型名("string", "integer", "bool" など)
|
||||
pub from: String,
|
||||
/// プラグインが期待する型名("string", "bytes", "i32" など)
|
||||
pub to: String,
|
||||
}
|
||||
|
||||
impl ArgTypeMapping {
|
||||
/// 新しい型マッピングを作成
|
||||
pub fn new(from: String, to: String) -> Self {
|
||||
Self {
|
||||
name: None,
|
||||
from,
|
||||
to,
|
||||
}
|
||||
}
|
||||
|
||||
/// 名前付きの型マッピングを作成
|
||||
pub fn with_name(name: String, from: String, to: String) -> Self {
|
||||
Self {
|
||||
name: Some(name),
|
||||
from,
|
||||
to,
|
||||
}
|
||||
}
|
||||
|
||||
/// Nyash型からBIDタグへの変換を決定
|
||||
/// ハードコーディングを避けるため、型名の組み合わせで判定
|
||||
pub fn determine_bid_tag(&self) -> Option<BidTag> {
|
||||
match (self.from.as_str(), self.to.as_str()) {
|
||||
// 文字列の変換パターン
|
||||
("string", "string") => Some(BidTag::String),
|
||||
("string", "bytes") => Some(BidTag::Bytes),
|
||||
|
||||
// 数値の変換パターン
|
||||
("integer", "i32") => Some(BidTag::I32),
|
||||
("integer", "i64") => Some(BidTag::I64),
|
||||
("float", "f32") => Some(BidTag::F32),
|
||||
("float", "f64") => Some(BidTag::F64),
|
||||
|
||||
// ブール値
|
||||
("bool", "bool") => Some(BidTag::Bool),
|
||||
|
||||
// バイナリデータ
|
||||
("bytes", "bytes") => Some(BidTag::Bytes),
|
||||
("array", "bytes") => Some(BidTag::Bytes), // 配列をシリアライズ
|
||||
|
||||
// 未対応の組み合わせ
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_handle_packing() {
|
||||
let handle = BidHandle::new(6, 12345);
|
||||
let packed = handle.to_u64();
|
||||
let unpacked = BidHandle::from_u64(packed);
|
||||
|
||||
assert_eq!(handle, unpacked);
|
||||
assert_eq!(unpacked.type_id, 6);
|
||||
assert_eq!(unpacked.instance_id, 12345);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_type_tags() {
|
||||
assert_eq!(BidType::Bool.tag(), BidTag::Bool);
|
||||
assert_eq!(BidType::String.tag(), BidTag::String);
|
||||
assert_eq!(BidType::Handle { type_id: 6, instance_id: 0 }.tag(), BidTag::Handle);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arg_type_mapping() {
|
||||
// string → bytes 変換のテスト(writeメソッドで使用)
|
||||
let mapping = ArgTypeMapping::new("string".to_string(), "bytes".to_string());
|
||||
assert_eq!(mapping.determine_bid_tag(), Some(BidTag::Bytes));
|
||||
|
||||
// integer → i32 変換のテスト
|
||||
let mapping = ArgTypeMapping::new("integer".to_string(), "i32".to_string());
|
||||
assert_eq!(mapping.determine_bid_tag(), Some(BidTag::I32));
|
||||
|
||||
// 名前付きマッピングのテスト
|
||||
let mapping = ArgTypeMapping::with_name(
|
||||
"content".to_string(),
|
||||
"string".to_string(),
|
||||
"string".to_string()
|
||||
);
|
||||
assert_eq!(mapping.name, Some("content".to_string()));
|
||||
assert_eq!(mapping.determine_bid_tag(), Some(BidTag::String));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user