🚨 Critical Issue #76: SocketBox Method Call Deadlock Investigation

## 🎯 Problem Identification Complete
- SocketBox method calls (bind, isServer, toString) cause infinite blocking
- Root cause: Method resolution pipeline deadlock before execute_socket_method
- Other Box types (ArrayBox, StringBox, MapBox) work normally
- Arc<Mutex> reference sharing confirmed working (Arc addresses match = true)

## 🔧 Debug Infrastructure Added
- Comprehensive debug logging in socket_box.rs (bind, isServer, clone, toString)
- Method call tracing in http_methods.rs
- Deadlock detection points identified at interpreter expressions.rs:462-464

## 📋 Issue #76 Created for Copilot Investigation
- Systematic root cause analysis requirements (Architecture→Parser→Runtime levels)
- Comprehensive test cases: minimal/comprehensive/comparison scenarios
- Strict prohibition of band-aid fixes - architectural analysis required
- Hypothesis: Multiple Arc<Mutex> combinations causing circular deadlock

## 🧪 Test Suite Added
- test_socket_deadlock_minimal.nyash: Minimal reproduction case
- test_socket_methods_comprehensive.nyash: All methods deadlock verification
- test_other_boxes_working.nyash: Normal Box operation confirmation
- SOCKETBOX_ISSUE_REPRODUCTION.md: Complete reproduction guide

## 📊 Impact Assessment
- Phase 9 HTTP server implementation completely blocked
- SocketBox functionality entirely non-functional
- Critical blocker for production readiness
- Requires immediate systematic investigation

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-14 20:55:33 +09:00
parent 7ceaae957a
commit 80c911d3c8
63 changed files with 7720 additions and 75 deletions

View File

@ -0,0 +1,102 @@
# 🚨 Issue #76: SocketBoxデッドロック再現手順
## 📋 **即座実行可能テスト**
### **1. 最小デッドロック再現**
```bash
# 実行コマンド (10秒でタイムアウト)
timeout 10s ./target/release/nyash test_socket_deadlock_minimal.nyash
# 期待結果: タイムアウトでデッドロック確認
# 出力例:
# [Console LOG] ✅ SocketBox作成成功
# [Console LOG] bind()実行開始...
# (ここで無限ブロック)
```
### **2. 他のBox正常動作確認**
```bash
# 実行コマンド
./target/release/nyash test_other_boxes_working.nyash
# 期待結果: 正常完了
# 出力例:
# [Console LOG] ✅ ArrayBox正常: size=1
# [Console LOG] ✅ MapBox正常: value=test_value
# [Console LOG] 🎉 他のBox全て正常動作: 4件成功
```
### **3. SocketBox全メソッドテスト**
```bash
# 実行コマンド (30秒でタイムアウト)
timeout 30s ./target/release/nyash test_socket_methods_comprehensive.nyash
# 期待結果: 最初のtoString()でデッドロック
# 出力例:
# [Console LOG] Test 1: toString()実行...
# (ここで無限ブロック)
```
## 🔧 **ビルド手順**
```bash
# フルリビルド
cargo clean
cargo build --release -j32
# 確認
ls -la target/release/nyash
```
## 📊 **デバッグログ確認ポイント**
### **正常Box vs SocketBoxの出力差異**
```bash
# 正常Box例ArrayBox:
✅ ARRAY_METHOD: push() called
✅ ArrayBox push completed
# SocketBox問題:
🔥 SOCKETBOX CLONE DEBUG: Arc addresses match = true
# ここで停止 - 🔥 SOCKET_METHOD: bind() called が出力されない
```
### **問題箇所ピンポイント**
```rust
// src/interpreter/expressions.rs:462-464
// この downcast_ref または obj_value 取得でデッドロック
if let Some(socket_box) = obj_value.as_any().downcast_ref::<SocketBox>() {
let result = self.execute_socket_method(socket_box, method, arguments)?;
```
## 📝 **実行後報告フォーマット**
```
## テスト実行結果
### Test 1: 最小デッドロック再現
- 実行時間: XX秒タイムアウト
- 最後の出力: "bind()実行開始..."
- 結果: ✅ デッドロック再現確認 / ❌ 正常動作
### Test 2: 他のBox正常動作
- 実行時間: XX秒
- 成功Box数: X件
- 結果: ✅ 正常動作 / ❌ 異常あり
### Test 3: Socket全メソッド
- デッドロック発生メソッド: toString/isServer/bind/close
- 結果: ✅ 全メソッドでデッドロック / ❌ 一部のみ問題
## 修正内容
- 変更ファイル: src/xxx.rs
- 修正内容: 具体的変更点
- 根本原因: 原因の詳細説明
## 修正後テスト結果
- Test 1: ✅ 正常完了
- Test 2: ✅ 正常完了
- Test 3: ✅ 全メソッド正常動作
```
---
**⚠️ 重要**: 必ず上記3テスト全ての実行結果を報告してください。部分的修正は不可です。

View File

@ -0,0 +1,346 @@
# AI大会議: Nyash Phase 9 JIT実装設計相談
## 🎯 相談の目的
Phase 8.7完了前にPhase 9 JIT実装の技術設計を確定
実装効率最大化・性能目標達成・Everything is Box哲学の最適実現
================================================================================
## 📊 現在の開発状況2025-08-14
================================================================================
### ✅ 完了済みPhase
- **Phase 8.4**: AST→MIR Lowering完全実装
- **Phase 8.5**: MIR 25命令階層化完成ChatGPT5設計
- **Phase 8.7**: 予定kilo実装 + VM BoxCall修正統合
### 📈 現在のパフォーマンス実績
```
Interpreter: 110.10ms (1x baseline)
VM: 119.80ms (0.9x slower) ← BoxCall戻り値問題
WASM: 8.12ms (13.5x faster) ← 実証済み
```
### 🎯 JIT目標
- **短期目標**: 50-100倍高速化WASM 13.5倍を大幅超越)
- **中期目標**: 実用アプリケーション開発での競争力確保
- **長期目標**: Phase 10 AOT実装への基盤確立
================================================================================
## 🔧 MIR 25命令完全仕様ChatGPT5設計
================================================================================
### Tier-0: 普遍コア8命令
```
Const, BinOp, Compare, Branch, Jump, Phi, Call, Return
```
- **効果**: Const/Phi=pure, BinOp/Compare=pure, Branch/Jump/Return=control
- **位置づけ**: 将来のJIT/AOT/WASMすべてで必須の基盤
### Tier-1: Nyashセマンティクス12命令
```
NewBox // 強所有のBox生成所有森のード
BoxFieldLoad // Boxのフィールド読みEverything is Box核心
BoxFieldStore // Boxのフィールド書きmut効果
BoxCall // Boxのメソッド呼び出し動的/静的両方)
Safepoint // 分割finiや割込み許可ポイント
RefGet // 参照(強/弱を問わず)を値として取得
RefSet // 参照の差し替え(所有規則検証付き)
WeakNew // weak ハンドル生成(非所有リンク作成)
WeakLoad // weak から生存チェック付きで強参照取得失効時null
WeakCheck // weak の生存確認bool
Send // Bus送信io効果
Recv // Bus受信io効果
```
- **革命的価値**: 所有森weakBusが言語一次市民として表現可能
- **効果**: BoxFieldStore/RefSet=mut, Send/Recv=io, 他は基本pure
### Tier-2: 実装補助・最適化友好5命令
```
TailCall // 末尾呼び出し(スタック節約)
Adopt // 所有移管: this が子を強所有に取り込む
Release // 強所有を解除weak化 or null化
MemCopy // 小さなメモリ移動(構造体/配列最適化フック)
AtomicFence // 並行時の順序保証Actor/Port境界で使用
```
- **位置づけ**: 性能・安全検査・移植性の安定化
### 効果システム(最適化の鍵)
- **pure**: Const, BinOp, Compare, Phi, RefGet, WeakNew, WeakLoad, WeakCheck
- **mut**: BoxFieldStore, RefSet, Adopt, Release, MemCopy
- **io**: Send, Recv, Safepoint, AtomicFence
- **control**: Branch, Jump, Return, TailCall
- **context依存**: Call, BoxCall呼び先効果に従属
**最適化ルール**: 「pure同士の再順序化OK」「mutは同一Box/同一Fieldで依存保持」「ioは再順序化禁止」
================================================================================
## 🚀 JIT設計の核心技術選択
================================================================================
### 1. JITバックエンド選択の判断軸
#### Option A: Cranelift実装容易派
**利点**:
- Rust純正、統合容易
- 学習コスト低、開発速度高
- WebAssembly origin、Nyash WASM既存実装との親和性
- 中程度最適化で実用十分
**欠点**:
- 最高峰最適化はLLVMに劣る
- エコシステムがLLVMより小さい
#### Option B: LLVM最適化重視派
**利点**:
- 世界最高峰の最適化エンジン
- 豊富な最適化パス(ボックス化解除、インライン展開等)
- 他言語との競争力確保
**欠点**:
- 実装複雑、学習コスト高
- 起動時間長JITコンパイル時間
- 依存関係重い
#### Option C: 段階的アプローチ(現実的派)
```
Phase 9A: Cranelift Baseline (実証・学習)
Phase 9B: LLVM Ultimate (最適化・競争力)
Phase 10: AOT統合 (最終形態)
```
### 2. Baseline JIT実装範囲
#### Strategy A: 全25命令対応
- 利点: 完全性、将来の拡張が容易
- 欠点: 実装時間長、複雑度高
#### Strategy B: 段階的実装
```
Step 1: Tier-0のみ8命令→ 基本制御フロー動作確認
Step 2: Tier-1追加20命令→ Everything is Box実現
Step 3: Tier-2完成25命令→ 最適化機能追加
```
#### Strategy C: 頻出命令優先
- プロファイリングで頻出命令特定
- 80/20ルール適用20%の命令で80%の性能改善)
### 3. MIR→JIT変換方式
#### Approach A: Direct Compilation
```rust
// MIR命令を直接ネイティブコードに変換
MirInstruction::BinOp { dst, op: Add, lhs, rhs } => {
emit_load_register(rhs);
emit_add_instruction(lhs, rhs);
emit_store_register(dst);
}
```
#### Approach B: Template-based Compilation
```rust
// 事前定義済みコードテンプレートを使用
templates.get("BinOp_Add").instantiate(dst, lhs, rhs);
```
#### Approach C: Profile-guided Optimization
```rust
// 実行時プロファイル情報を活用
if hotspot_detected(basic_block) {
apply_aggressive_optimization();
}
```
================================================================================
## 💎 Nyash特化最適化戦略
================================================================================
### 1. Everything is Box最適化
#### Box→プリミティブ値最適化ボックス化解除
```nyash
// Before: Box operations
local a = new IntegerBox(10)
local b = new IntegerBox(20)
local c = a.add(b)
// After: Primitive operations (JIT optimized)
int64_t a = 10;
int64_t b = 20;
int64_t c = a + b;
```
#### エスケープ解析によるスタック割り当て
```rust
// Heap allocation回避
if !escapes_current_function(box_instance) {
allocate_on_stack(box_instance);
}
```
### 2. weak参照システム最適化
#### WeakNew/WeakLoad/WeakCheck効率実装
```rust
// 世代タグによるO(1)生存チェック
struct WeakRef {
ptr: *mut Box,
generation: u64,
}
fn weak_load(weak_ref: &WeakRef) -> Option<Box> {
if weak_ref.generation == (*weak_ref.ptr).generation {
Some((*weak_ref.ptr).clone())
} else {
None // 失効済み
}
}
```
### 3. デリゲーションfrom構文最適化
#### 静的解決による直接呼び出し
```nyash
// Before: Dynamic dispatch
from Parent.method()
// After: Static resolution (JIT optimized)
Parent_method_direct_call();
```
#### メソッド解決キャッシュ
```rust
// メソッド解決結果をキャッシュ
method_cache: HashMap<(TypeId, MethodName), FunctionPtr>
```
### 4. fini()システム統合
#### Safepoint効率実装
```rust
// インライン vs コールバック
if lightweight_operation() {
inline_safepoint_check();
} else {
register_safepoint_callback();
}
```
#### 自動メモリ管理協調
```rust
// GCとJITの協調
gc_integration: {
stack_map: StackMap, // GCルート情報
safepoint_table: SafepointTable, // 安全停止点
deopt_table: DeoptTable, // 逆最適化情報
}
```
================================================================================
## 🎯 深く考えるべき技術的判断ポイント
================================================================================
### Critical Decision 1: Cranelift vs LLVM
**判断基準**:
- 開発速度 vs 最終性能
- 学習コスト vs 最適化能力
- Nyash特性Everything is Boxへの適応度
**Nyash特有考慮点**:
- Box操作の頻度が極めて高い → ボックス化解除が性能の鍵
- weak参照が言語核心 → 効率的な生存チェックが必須
- fini()システム → GC統合が必須
### Critical Decision 2: 最適化優先順位
**Option A**: ボックス化解除最優先
- Everything is Box → プリミティブ化で劇的高速化期待
**Option B**: メソッド解決最優先
- from構文、BoxCall頻発 → 動的ディスパッチ削減
**Option C**: メモリ管理最優先
- weak参照、fini()システム → GC協調最適化
### Critical Decision 3: 段階実装戦略
**All-in approach**: 25命令完全実装から開始
- 利点: 完全性、将来拡張容易
- 欠点: 初期成功が遅い、複雑度高
**Incremental approach**: Tier順次実装
- 利点: 早期成功、段階検証
- 欠点: 設計変更リスク、重複作業
### Critical Decision 4: パフォーマンス目標設定
**Conservative**: WASM 13.5倍 → JIT 30-50倍
**Aggressive**: WASM 13.5倍 → JIT 100-300倍
**Moonshot**: WASM 13.5倍 → JIT 500-1000倍
各目標での実装戦略・最適化要件が大きく異なる
================================================================================
## ❓ AI大会議への具体的質問事項
================================================================================
### 🤖 Gemini先生への質問理論・設計重視
1. **アーキテクチャ選択**:
Nyashの特性Everything is Box、25命令MIR、fini/weak参照を考慮して、Cranelift vs LLVM vs 段階的アプローチ、どれが最適?
2. **最適化戦略**:
Box操作のボックス化解除、weak参照の効率実装、デリゲーション最適化、どれを最優先すべき理論的根拠は
3. **メモリ管理統合**:
fini()システム + weak参照 + JIT最適化の協調設計で、技術的に最も堅実なアプローチは
4. **段階実装設計**:
25命令を段階的に実装する場合の最適な順序・境界は各段階での検証方法は
### 🤖 ChatGPT(codex)先生への質問(実装・現実重視)
1. **実装優先度**:
Phase 9実装で最短時間で最大効果を得る実装優先順位は開発工数の現実的見積もりは
2. **技術的実現性**:
NyashのEverything is Box哲学をJITで効率的に実装する現実的な技術アプローチは実装上の落とし穴は
3. **パフォーマンス予測**:
現在のWASM 13.5倍を基準に、JITで現実的に達成可能な性能向上倍率は各最適化の寄与度予測は
4. **開発戦略**:
Copilot + Claude協調開発でPhase 9を成功させるための具体的開発ステップ・役割分担は
### 🎯 統合判断が必要な項目
1. **技術選択**: Cranelift(実装容易) vs LLVM(最適化強力) の最終判断
2. **実装範囲**: Baseline JITでの命令対応範囲8/20/25命令
3. **最適化焦点**: ボックス化解除 vs メソッド解決 vs メモリ管理
4. **性能目標**: 現実的な高速化倍率設定30/100/500倍
5. **開発期間**: Phase 9完成までの現実的スケジュール
================================================================================
## 📋 参考資料・関連ファイル
================================================================================
- **MIR完全仕様**: docs/予定/native-plan/MIR仕様書.txt
- **全体計画**: docs/予定/native-plan/copilot_issues.txt
- **Phase 8.7設計**: docs/予定/native-plan/issues/phase_8_7_real_world_memory_testing.md
- **現在状況**: docs/CURRENT_TASK.md
- **実行性能**: benchmarks/ ディレクトリ
- **MIR実装**: src/mir/ ディレクトリ
================================================================================
## 🎯 期待される大会議成果
================================================================================
1. **技術方針確定**: JITバックエンド・実装戦略の明確な決定
2. **最適化戦略**: Nyash特化最適化の優先順位・手法確定
3. **実装計画**: Phase 9の具体的実装ステップ・期間設定
4. **性能目標**: 現実的で野心的な性能向上目標設定
5. **協調開発**: Copilot + Claude の効率的役割分担
この相談により、Phase 9 JIT実装が成功し、Nyashが真に競争力のあるプログラミング言語として確立されることを期待します。
---
作成日: 2025-08-14
作成者: Claude (AI大会議準備)
優先度: CriticalPhase 8.7完了前の事前設計)

View File

@ -0,0 +1,198 @@
# AI大会議結果: Phase 9 JIT実装設計2025-08-14
## 🎯 大会議参加者
- **Gemini先生**: 理論・アーキテクチャ重視一部取得、Rate Limit発生
- **ChatGPT先生codex exec**: 実装・現実重視(部分回答、タイムアウト)
- **Claude**: 統合・調整役
## 📋 大会議での合意事項
### 1. JITバックエンド選択 ✅ **合意**
**Gemini提案**: 段階的アプローチOption Cを強く推奨
**ChatGPT提案**: Cranelift-first with two-tier JIT
**最終合意**: **段階的アプローチ**
```
Phase 9A: Cranelift Baseline JIT (実証・学習・高速実装)
Phase 9B: LLVM Ultimate JIT (最適化・競争力)
Phase 10: AOT統合 (最終形態)
```
**理由**:
- **実装リスク管理**: 複雑なLLVMを最初から使うのではなく、確実なCraneliftで基盤構築
- **Rust親和性**: Craneliftの統合容易性でイテレーション高速化
- **WASM知見活用**: 既存WASM実装の経験を活かせる
- **段階的価値提供**: 早期に動作するJITで成功体験
### 2. 最適化戦略 ✅ **合意**
**Gemini提案**: ボックス化解除を最優先Everything is Box対策
**ChatGPT提案**: (1) BoxCall PIC化+キャッシュ (2) 数値Boxアンボックス化 (3) エスケープ解析
**最終合意**: **ボックス化解除最優先**
```
1. 最優先: Box→プリミティブ値最適化アンボックス化
2. 次点: エスケープ解析によるスタック割り当て
3. 並行: BoxCall PIC化Polymorphic Inline Cache
4. 後回し: weak参照・メモリ管理最適化
```
**理論的根拠**:
- アムダールの法則: 最も時間消費している部分の改善が全体に最大寄与
- Everything is Box哲学 → Box操作オーバーヘッドが性能ボトルネック
- ボックス化解除により他の最適化(メソッド解決等)も連鎖的に改善
### 3. メモリ管理統合 ✅ **合意**
**Gemini提案**: Safepointとスタックマップ実績ある標準技術
**ChatGPT提案**: シャドウスタックでGC連携、世代タグによる弱参照
**最終合意**: **Safepointベース + 世代タグ弱参照**
```
- Safepoint挿入: 関数序盤/ループバックエッジ/Call/Alloc箇所
- スタックマップ: Craneliftサポート機能でGCルート追跡
- 弱参照: 世代タグによるO(1)生存チェック
- GC協調: シャドウスタックで堅実に開始
```
### 4. 段階実装戦略 ✅ **合意**
**Gemini提案**: Tier順次実装Tier-0 → Tier-1 → Tier-2
**ChatGPT提案**: Tier-0 + Box core 4命令優先
**最終合意**: **Core-first段階実装**
```
Step 1: 基本制御フロー (Tier-0 8命令)
+ Box core 4命令 (NewBox/BoxFieldLoad/BoxFieldStore/BoxCall)
Step 2: Everything is Box完成 (Tier-1残り + weak/ref実装)
Step 3: 最適化機能追加 (Tier-2全命令 + 高度最適化)
```
## 🎯 重要な技術的合意
### MIR→JIT Lowering戦略
**ChatGPT提案**採用:
- **Tier-0 (8命令)**: 全対応、Callは当面ランタイムFFIトランポリン
- **Tier-1最小核 (4命令)**: NewBox/BoxFieldLoad/BoxFieldStore/BoxCall優先
- **その他命令**: 最初はランタイム呼び出しで埋める段階的JIT化
### パフォーマンス予測
**ChatGPT予測**:
```
Baseline JIT: 20-40倍高速化
+PIC+軽量アンボックス: 50-100倍高速化
+LLVM AOT: 120-200倍高速化
```
**目標**: WASM 13.5倍は早期段階で確実に超越
### 実装工数見積もり
**ChatGPT見積もり**:
```
Phase 9A (Cranelift Baseline): 2.5-4週間 (Copilot+Claude協調)
Phase 9B (最適化): 3-6週間追加
Phase 10 (AOT): 別フェーズ
```
## 🚨 重要な実装注意点
### 技術的落とし穴ChatGPT警告
- **ABI不整合**: Rust↔Cranelift間のデータ型マッピング
- **マルチスレッド安全性**: JITコード生成と実行の並行性
- **デバッグ困難性**: JIT化されたコードのスタックトレース
### Cranelift固有の考慮点
- **スタックマップサポート**: GC連携の要
- **最適化限界**: LLVMと比べた制約認識
- **メモリモデル**: weak参照との整合性
## 💎 Nyash特化最適化手法
### 1. ボックス化解除(最優先)
```rust
// Before (Box operations)
let a = new IntegerBox(10);
let b = new IntegerBox(20);
let c = a.add(b);
// After (JIT optimized)
int64_t a = 10;
int64_t b = 20;
int64_t c = a + b;
```
### 2. エスケープ解析
```rust
// Heap allocation回避
if !escapes_current_function(box_instance) {
allocate_on_stack(box_instance);
}
```
### 3. 世代タグ弱参照
```rust
struct WeakRef {
ptr: *mut Box,
generation: u64,
}
fn weak_load(weak_ref: &WeakRef) -> Option<Box> {
if weak_ref.generation == (*weak_ref.ptr).generation {
Some((*weak_ref.ptr).clone())
} else {
None // 失効済み
}
}
```
## 🤖 Copilot + Claude協調開発戦略
### 役割分担
- **Copilot**: Cranelift統合、MIR→CLIF変換、コード生成エンジン
- **Claude**: 設計統合、テスト戦略、最適化アルゴリズム、ドキュメント
### 開発手順
1. **インフラ構築**: JIT Manager、コードキャッシュ、Safepointシステム
2. **基本実装**: Tier-0命令完全対応
3. **Box操作**: 4つのコア命令NewBox/FieldLoad/FieldStore/BoxCall
4. **最適化**: PIC、アンボックス化、エスケープ解析
5. **統合テスト**: 3バックエンドInterpreter/VM/JIT比較
## ✅ 次期アクション
### Phase 8.7完了後の即座実行項目
1. **JIT Manager設計**: コードキャッシュ、ホットスポット検出
2. **Cranelift統合**: 基本パイプライン構築
3. **MIR→CLIF変換**: Tier-0命令マッピング
4. **Safepoint実装**: GC協調基盤
5. **ベンチマーク拡張**: JIT性能測定機能
### 成功基準
- [ ] WASM 13.5倍を確実に超える20倍以上目標
- [ ] Phase 8.7 kilo実装がJITで高速動作
- [ ] メモリ安全性維持weak参照・fini()システム正常動作)
- [ ] 開発効率性Craneliftによる高速イテレーション
## 🏆 期待される革命的成果
### 技術的インパクト
- **Nyash JIT確立**: Everything is Box哲学のネイティブ高速実行
- **言語競争力**: 他のスクリプト言語を凌駕する性能
- **AOT基盤**: Phase 10への確実な道筋
### 戦略的価値
- **段階的実装**: リスク管理された確実な進歩
- **技術実証**: Cranelift→LLVM移行の実現可能性証明
- **開発効率**: AI協調開発の成功事例確立
---
**作成日**: 2025-08-14
**大会議時間**: 約60分Gemini Rate Limit、ChatGPT Timeout含む
**合意レベル**: 高(主要技術選択で一致)
**実装準備**: 完了Phase 8.7後即座開始可能)
**重要**: このAI大会議結果は、Phase 9成功の設計図として機能します。
Gemini先生とChatGPT先生の英知を統合し、Nyash JIT実装を確実に成功させる道筋が確立されました。

21
bench_simple.wat Normal file
View File

@ -0,0 +1,21 @@
(module
(func $main (result i32)
(local $x i32)
(local $y i32)
(local $result i32)
i32.const 10
local.set $x
i32.const 20
local.set $y
local.get $x
local.get $y
i32.add
local.set $result
local.get $result
)
(export "main" (func $main))
)

66
benchmark_real.sh Normal file
View File

@ -0,0 +1,66 @@
#!/bin/bash
echo "🚀 真のWASM実行性能ベンチマーク"
echo "================================="
# 実行回数
ITERATIONS=100
echo "📊 測定回数: $ITERATIONS"
echo
# 1. インタープリター測定
echo "1⃣ インタープリター実行測定"
interpreter_total=0
for i in $(seq 1 $ITERATIONS); do
start_time=$(date +%s%N)
./target/release/nyash test_local_vars.nyash >/dev/null 2>&1
end_time=$(date +%s%N)
duration=$((($end_time - $start_time) / 1000000)) # ms
interpreter_total=$(($interpreter_total + $duration))
done
interpreter_avg=$(echo "scale=2; $interpreter_total / $ITERATIONS" | bc)
echo " 平均実行時間: ${interpreter_avg} ms"
# 2. VM測定
echo "2⃣ VM実行測定"
vm_total=0
for i in $(seq 1 $ITERATIONS); do
start_time=$(date +%s%N)
./target/release/nyash --backend vm test_local_vars.nyash >/dev/null 2>&1
end_time=$(date +%s%N)
duration=$((($end_time - $start_time) / 1000000)) # ms
vm_total=$(($vm_total + $duration))
done
vm_avg=$(echo "scale=2; $vm_total / $ITERATIONS" | bc)
echo " 平均実行時間: ${vm_avg} ms"
# 3. WASM実行測定wasmtime
echo "3⃣ WASM実行測定wasmtime"
wasm_total=0
for i in $(seq 1 $ITERATIONS); do
start_time=$(date +%s%N)
$HOME/.wasmtime/bin/wasmtime run bench_simple.wat --invoke main >/dev/null 2>&1
end_time=$(date +%s%N)
duration=$((($end_time - $start_time) / 1000000)) # ms
wasm_total=$(($wasm_total + $duration))
done
wasm_avg=$(echo "scale=2; $wasm_total / $ITERATIONS" | bc)
echo " 平均実行時間: ${wasm_avg} ms"
# 4. 結果比較
echo
echo "📈 性能比較結果"
echo "==============="
echo "インタープリター: ${interpreter_avg} ms (1x baseline)"
echo "VM: ${vm_avg} ms"
echo "WASM (wasmtime): ${wasm_avg} ms"
# 速度比計算
vm_speedup=$(echo "scale=1; $interpreter_avg / $vm_avg" | bc)
wasm_speedup=$(echo "scale=1; $interpreter_avg / $wasm_avg" | bc)
echo
echo "🏆 速度向上比較"
echo "VM: ${vm_speedup}x faster"
echo "WASM: ${wasm_speedup}x faster"

204
clean_test.wat Normal file
View File

@ -0,0 +1,204 @@
(module
(import "env" "print" (func $print (param i32) ))
(memory (export "memory") 1)
(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)
nop
i32.const 10
local.set $0
i32.const 20
local.set $1
local.get $0
local.get $1
i32.add
local.set $2
local.get $2
return
)
(export "main" (func $main))
)

192
debug_socketbox.rs Normal file
View File

@ -0,0 +1,192 @@
// 🔍 デバッグ版SocketBox - 全操作を詳細ログ出力
use std::sync::{Arc, Mutex};
use std::fs::OpenOptions;
use std::io::Write;
// デバッグログをファイルに出力
fn debug_log(message: &str) {
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_millis();
let log_message = format!("[{}] {}\n", timestamp, message);
if let Ok(mut file) = OpenOptions::new()
.create(true)
.append(true)
.open("debug_socketbox.log")
{
let _ = file.write_all(log_message.as_bytes());
let _ = file.flush();
}
// コンソールにも出力
print!("{}", log_message);
}
#[derive(Debug)]
pub struct DebugSocketBox {
id: u64,
listener: Arc<Mutex<Option<std::net::TcpListener>>>,
is_server: Arc<Mutex<bool>>,
}
impl DebugSocketBox {
pub fn new() -> Self {
let id = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos() as u64;
let instance = Self {
id,
listener: Arc::new(Mutex::new(None)),
is_server: Arc::new(Mutex::new(false)),
};
debug_log(&format!("🆕 NEW SocketBox created: id={}, is_server_ptr={:p}",
instance.id, &*instance.is_server));
instance
}
pub fn bind(&self, addr: &str, port: &str) -> bool {
debug_log(&format!("🔗 BIND called on id={}, is_server_ptr={:p}",
self.id, &*self.is_server));
let socket_addr = format!("{}:{}", addr, port);
debug_log(&format!("🔗 BIND address: {}", socket_addr));
match std::net::TcpListener::bind(&socket_addr) {
Ok(listener) => {
// listener設定
match self.listener.lock() {
Ok(mut listener_guard) => {
*listener_guard = Some(listener);
debug_log(&format!("✅ BIND listener set successfully on id={}", self.id));
},
Err(e) => {
debug_log(&format!("❌ BIND listener lock failed: {:?}", e));
return false;
}
}
// is_server=true設定
debug_log(&format!("🔧 BIND setting is_server=true on id={}, ptr={:p}",
self.id, &*self.is_server));
match self.is_server.lock() {
Ok(mut is_server_guard) => {
let old_value = *is_server_guard;
*is_server_guard = true;
debug_log(&format!("✅ BIND is_server changed: {} -> true on id={}",
old_value, self.id));
},
Err(e) => {
debug_log(&format!("❌ BIND is_server lock failed: {:?}", e));
}
}
debug_log(&format!("🎉 BIND completed successfully on id={}", self.id));
true
},
Err(e) => {
debug_log(&format!("❌ BIND failed: {:?}", e));
false
}
}
}
pub fn is_server(&self) -> bool {
debug_log(&format!("❓ IS_SERVER called on id={}, ptr={:p}",
self.id, &*self.is_server));
match self.is_server.lock() {
Ok(is_server_guard) => {
let value = *is_server_guard;
debug_log(&format!("📖 IS_SERVER result: {} on id={}", value, self.id));
value
},
Err(e) => {
debug_log(&format!("❌ IS_SERVER lock failed: {:?}", e));
false
}
}
}
}
impl Clone for DebugSocketBox {
fn clone(&self) -> Self {
debug_log(&format!("🔄 CLONE called on id={}", self.id));
debug_log(&format!("🔄 CLONE original is_server_ptr={:p}", &*self.is_server));
let new_id = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos() as u64;
let cloned = Self {
id: new_id, // 新しいID
listener: Arc::clone(&self.listener),
is_server: Arc::clone(&self.is_server), // ✅ Arc共有
};
debug_log(&format!("🔄 CLONE created: old_id={} -> new_id={}", self.id, cloned.id));
debug_log(&format!("🔄 CLONE new is_server_ptr={:p}", &*cloned.is_server));
debug_log(&format!("🔄 CLONE Arc共有確認: {} == {}",
Arc::as_ptr(&self.is_server) as *const _ as usize,
Arc::as_ptr(&cloned.is_server) as *const _ as usize));
cloned
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_debug_socketbox() {
// ログファイルをクリア
std::fs::write("debug_socketbox.log", "").unwrap();
debug_log("🚀 === DEBUG TEST START ===");
// Step 1: 作成
let socket = DebugSocketBox::new();
debug_log(&format!("Step 1 completed: id={}", socket.id));
// Step 2: bind実行
debug_log("🔥 Step 2: BIND execution");
let bind_result = socket.bind("127.0.0.1", "18080");
debug_log(&format!("Step 2 completed: bind_result={}", bind_result));
// Step 3: 状態確認
debug_log("🔥 Step 3: Check state after bind");
let is_server1 = socket.is_server();
debug_log(&format!("Step 3 completed: is_server={}", is_server1));
// Step 4: clone実行
debug_log("🔥 Step 4: CLONE execution");
let socket_cloned = socket.clone();
// Step 5: clone後の状態確認
debug_log("🔥 Step 5: Check state after clone");
let is_server2 = socket_cloned.is_server();
debug_log(&format!("Step 5 completed: cloned is_server={}", is_server2));
// Step 6: 元の状態確認
debug_log("🔥 Step 6: Check original after clone");
let is_server3 = socket.is_server();
debug_log(&format!("Step 6 completed: original is_server={}", is_server3));
debug_log("🎉 === DEBUG TEST COMPLETED ===");
assert!(bind_result, "bind should succeed");
assert!(is_server1, "is_server should be true after bind");
assert!(is_server2, "cloned is_server should be true (shared Arc)");
assert!(is_server3, "original is_server should still be true");
}
}

BIN
debug_test Normal file

Binary file not shown.

View File

@ -1,4 +1,4 @@
# 🎯 現在のタスク (2025-08-14 Phase 9.51修正完了・NyIR Core 26命令統一完了)
# 🎯 現在のタスク (2025-08-14 Phase 9.7実装完了・PR #75修正完了)
## 🎉 2025-08-14 Phase 8完全完了
@ -91,37 +91,101 @@ Tier-2 (5命令): TailCall, Adopt, Release, MemCopy, AtomicFence
**🔥 ExternCall**: 外部ライブラリを統一Box APIで利用する革命的機能
## 🚀 **次期優先タスク (Phase 9.7: Box FFI/ABI実装)**
## **Phase 9.7: ExternCall実装完了2025-08-14**
### 📋 **Phase 9.7実装準備完了**
- **技術仕様**: `docs/予定/native-plan/issues/phase_9_7_box_ffi_abi_and_externcall.md`
- **ABI設計**: `docs/予定/native-plan/box_ffi_abi.md` (ChatGPT5完全設計)
- **BIDサンプル**: `docs/nyir/bid_samples/*.yaml`
- **26命令統合**: ExternCallがNyIR Core確定
### 🎉 **Phase 9.7実装完了成果**
**技術実装完了**:
- **ExternBox**: `src/boxes/extern_box.rs` 完全実装 ✅
- **WASM Runtime imports**: `src/backend/wasm/runtime.rs` 実装 ✅
- **console_log/canvas FFI**: ブラウザー連携基盤完成 ✅
- **NyIR Core 26命令**: ExternCall統合完了 ✅
### 🎯 **実装目標**
```yaml
1. MIR ExternCall命令追加: NyIR Core 26命令の13番目として確立
2. WASM RuntimeImports: env.console.log, env.canvas.*等最小実装
3. BID統合: Box Interface Definition仕様適用
4. E2Eデモ: Nyash→MIR→WASM→ブラウザ動作確認
**Everything is Box FFI/ABI基盤完成**:
```nyash
// 🌍 ブラウザーAPIをBoxで統一利用
local console = new ExternBox("console")
console.call("log", "Hello from Nyash!")
local canvas = new ExternBox("canvas")
canvas.call("fillRect", 10, 10, 100, 50)
```
### 💎 **期待され革命的効果**
- **Universal Exchange**: 外部ライブラリの統一Box API化
- **Everything is Box完成**: 内部Box + 外部Boxの完全統合
- **クロスプラットフォーム**: WASM/VM/LLVM統一外部呼び出し
### 💎 **達成され革命的効果**
- **Universal Exchange**: 外部ライブラリの統一Box API化
- **Everything is Box完成**: 内部Box + 外部Boxの完全統合
- **クロスプラットフォーム**: WASM/VM/LLVM統一外部呼び出し
## 🧪 **今後のテスト計画**
## **PR #75: SocketBox状態保持問題修正完了2025-08-14**
### 🎉 **Arc<dyn NyashBox>統合修正完了**
**技術的修正完了**:
- **20箇所の型エラー**: 機械的修正完了 ✅
- **Arc参照共有**: `(**arc)``(*arc)` 統一 ✅
- **Box↔Arc変換**: `Arc::from(box)` / `(*arc).clone_box()` 統一 ✅
- **フルビルド成功**: `cargo build --release` エラー0個 ✅
**SocketBox状態保持修正原理**:
```rust
// 🔧 修正前: 状態が失われる
Box::new(updated_instance) // 新しいBox作成
// ✅ 修正後: Arcで状態共有
Arc::new(updated_instance) // 参照共有
Arc::clone(&existing_arc) // 同じ状態コンテナ共有
```
### 📝 **期待効果(テスト必要)**
```nyash
server = new SocketBox()
server.bind("127.0.0.1", 8080) // 状態設定
server.isServer() // 🎯 true期待修正前: false
```
## ✅ **PR #75・Phase 9.7実装完了 - 新規緊急問題発生**
### 🎯 **SocketBoxメソッド呼び出しデッドロック問題 (2025-08-14発見)**
**🔥 緊急度: 最高** - SocketBoxの全メソッドbind, listen, isServer, toString等が無限ブロックする致命的バグ
**📋 問題の詳細**:
- SocketBox作成・Clone・Arc参照共有: ✅ **正常動作確認済み**
- メソッド呼び出し: ❌ **インタープリターメソッド解決段階でデッドロック**
- 他のBoxStringBox, IntegerBox, ArrayBox等: ✅ **正常動作**
**🎯 特定済み問題箇所**:
```rust
// src/interpreter/expressions.rs:462-464
if let Some(socket_box) = obj_value.as_any().downcast_ref::<SocketBox>() {
let result = self.execute_socket_method(socket_box, method, arguments)?;
// ↑ ここに到達しないexecute_socket_methodが呼ばれない
```
**📊 実行ログ証拠**:
```bash
[Console LOG] bind実行開始...
🔥 SOCKETBOX CLONE DEBUG: Arc addresses match = true # ← Clone正常
# ここで無限ブロック - 🔥 SOCKET_METHOD: bind() called が出力されない
```
### 🚨 **Copilot緊急依頼Issue作成済み**: [Issue #76](https://github.com/moe-charm/nyash/issues/76)
- SocketBox専用デッドロック問題の完全解決
- 詳細テストケース・再現手順・期待結果すべて明記
- 他のBox型との差異分析要請
### 🌍 **Phase 9.7: ExternCallテスト**
```bash
# ExternBox動作テスト
./target/release/nyash test_extern_call_demo.nyash
# WASMブラウザーテスト
./target/release/nyash --compile-wasm extern_demo.nyash
# ブラウザーでconsole.log確認
```
### ⚡ **ストレステスト**
- SocketBox状態管理: 大量接続・早期切断テスト
- HTTPServerBox負荷: 同時100接続処理確認
- メモリリーク検証: fini/weak参照システム長時間運用
### 🌐 **実用アプリケーション検証**
- NyaMesh P2P: 実際のP2P通信での状態管理テスト
- WebサーバーDemo: 実用HTTPサーバーでの負荷確認
- ExternCall WASM: ブラウザーFFI連携テスト
### 📋 **Phase 9.51修正計画Issue #68**
**期間**: 1週間
@ -258,4 +322,4 @@ WASM: 11.5倍 → 13.5倍以上
**配布可能実行ファイル**: Nyashがついに「おもちゃ言語」を卒業
---
最終更新: 2025-08-14 - **Phase 8完全完了・実用優先戦略でPhase 9開始**
最終更新: 2025-08-14 - **Phase 9.7・PR #75完了・次は実装テスト実行**

View File

@ -0,0 +1,217 @@
# 🤖 Copilot様 作業予定・課題整理
# Generated: 2025-08-14
# Purpose: Claude×Copilot協調開発のための情報共有
================================================================================
🎯 現在進行中のタスク (Phase 8.3)
================================================================================
## Issue #53: Phase 8.3 - WASM Box Operations
Status: 🚧 進行中 (Copilot担当)
Priority: High
### 実装範囲
- RefNew/RefGet/RefSet WASMコード生成
- Box メモリレイアウト定義
- malloc/freeアロケータ改良
- NewBox MIR命令→WASM変換
### 成功基準
✅ Box操作のend-to-end動作確認
✅ CI環境での全テストPASS
✅ `--compile-wasm`オプション正常動作
✅ 既存Phase 8.2互換性維持
### Claude側で完成済みマージ競合回避
✅ ベンチマークシステム完全実装 (src/benchmarks.rs)
✅ CLI統合 (--benchmark, --iterations オプション)
✅ 3バックエンド性能比較基盤
✅ 280倍高速化実証データ取得
✅ ドキュメント整備 (execution-backends.md等)
### Copilot実装時の協調ポイント
⚠️ 競合予想ファイル:
- src/main.rs (CLI引数パーサー) ← Claude修正済み
- src/lib.rs (benchmarksモジュール) ← Claude修正済み
- src/backend/wasm/ (WASM実装) ← Copilot修正予定
🤝 推奨協調戦略:
- Phase 8.3 PR前にClaude変更をcommit済み
- ベンチマーク機能維持を最優先
- 機能統合時は両機能を併存
================================================================================
🚀 次期計画 (Phase 8.4+) - AI大会議で策定済み
================================================================================
## Phase A: AOT WASM ネイティブ化 (2-3週間)
Priority: High (Phase 8.3完了後に即座開始)
### 実装目標
新CLI機能:
nyash --compile-native program.nyash -o program.exe
nyash --aot program.nyash
### 技術アプローチ
Pipeline: Nyash → AST → MIR → WASM → wasmtime compile → Native Binary
### 期待効果
280倍 → 500倍高速化 (1.8倍追加向上)
### Copilot協力期待事項
🤖 技術的助言:
- wasmtime::Config 最適設定
- CPU機能検出・ターゲット分岐
- .cwasm 互換性管理
🤖 実装支援:
- MIR最適化基盤設計
- エスケープ解析アルゴリズム
- ボックス化解除戦略
## Phase B: Cranelift Direct (2-3ヶ月)
Priority: Medium
### 技術目標
Pipeline: Nyash → AST → MIR → Cranelift IR → Native Binary
### 期待効果
500倍 → 600倍高速化
### Copilot協力期待事項
🤖 アーキテクチャ設計:
- MIR → Cranelift IR変換設計
- ABI・呼出規約定義
- GC統合戦略
## Phase C: LLVM Ultimate (6ヶ月+)
Priority: Low (長期目標)
### 技術目標
Pipeline: Nyash → AST → MIR → LLVM IR → Optimized Native Binary
### 期待効果
600倍 → 1000倍高速化
================================================================================
🧠 AI大会議で得られた技術的知見
================================================================================
## Gemini先生の助言
✅ Cranelift → LLVM段階的アプローチ推奨
✅ エスケープ解析・ボックス化解除が性能の鍵
✅ wasmtime compileは短期的に実用的
✅ WASM→Native 3.4倍向上は現実的
## codex先生の助言
✅ MIR前倒し実装推奨全バックエンドが恩恵
✅ wasmtime互換性管理が重要
✅ CPU差異対応 (baseline/v3二段ビルド)
✅ 起動時間・割当削減・配布体験がKPI
## Claude統合分析
✅ 段階的アプローチが技術的に最適
✅ Everything is Box最適化が差別化の核心
✅ ベンチマーク駆動開発で継続改善
================================================================================
💡 Copilot様への具体的お願い・相談事項
================================================================================
## 🔧 Phase 8.3実装中の相談
### 技術的課題
❓ RefNew/RefGet/RefSet の最適なWASMメモリレイアウトは
❓ Box型ID管理の効率的な実装方法は
❓ malloc/freeアロケータの詳細設計は
### 性能最適化
❓ WASMでのBox操作性能向上のコツは
❓ メモリアクセスパターンの最適化方法は?
❓ wasmtimeとの統合で注意すべき点は
### テスト・品質保証
❓ Box操作の包括的テストケース設計は
❓ 既存Phase 8.2テストとの互換性確保方法は?
❓ CI/CDでの自動テスト最適化は
## 🚀 Phase 8.4準備での相談
### AOT WASM実装
❓ wasmtime compileの実用的な使い方は
❓ .cwasm互換性管理のベストプラクティスは
❓ クロスプラットフォーム配布戦略は?
### MIR最適化設計
❓ エスケープ解析の効率的なアルゴリズムは?
❓ ボックス化解除の判定条件設計は?
❓ 型推論・特殊化の実装アプローチは?
### ベンチマーク拡張
❓ Box操作性能測定の追加指標は
❓ ネイティブ性能比較の測定方法は?
❓ 回帰テスト自動化の改善点は?
================================================================================
📊 進捗管理・コミュニケーション
================================================================================
## 🤝 協調開発ルール
### コミット・マージ戦略
✅ 大きな変更前にはdocs/CURRENT_TASK.mdで情報共有
✅ ベンチマーク機能は最優先で維持
✅ CLI統合は両機能を統合的に対応
✅ 競合発生時は機能優先度で解決
### 進捗報告
📅 週次: 進捗状況をCURRENT_TASK.mdに反映
📅 完了時: 新機能のベンチマーク結果を共有
📅 問題発生: AI大会議で技術的相談
### 品質保証
✅ cargo check でビルドエラーなし
✅ 既存ベンチマークが regression なし
✅ 新機能のドキュメント整備
✅ テストケース追加・CI通過
================================================================================
🎯 期待される成果・インパクト
================================================================================
## Phase 8.3完了時の成果
🏆 RefNew/RefGet/RefSet WASM完全動作
🏆 Box操作ベンチマーク追加
🏆 メモリレイアウト最適化効果測定
🏆 オブジェクト指向プログラミングWASM対応
## Phase 8.4以降の展望
🚀 ネイティブ実行ファイル生成
🚀 1000倍高速化達成
🚀 実用レベルのアプリケーション開発対応
🚀 他言語との競争力確立
## 言語としての完成度向上
💎 Everything is Box哲学のWASM実現
💎 開発効率性と実行性能の両立
💎 4つの実行形態対応Interpreter/VM/WASM/Native
💎 現代的言語としての地位確立
================================================================================
📞 連絡・相談方法
================================================================================
技術的相談や進捗報告は、以下の方法でお気軽にどうぞ:
1. 📝 GitHub Issues・Pull Request
2. 📋 docs/CURRENT_TASK.md コメント
3. 🤖 AI大会議 (重要な技術決定)
4. 💬 コミットメッセージでの進捗共有
どんな小さなことでも相談大歓迎です!
一緒にNyashを最高の言語にしていきましょう🚀
================================================================================
最終更新: 2025-08-14
作成者: Claude (AI大会議結果を基に作成)
================================================================================

View File

@ -0,0 +1,110 @@
やったね!この粒度なら “化け物に伸びる余白” と “実装の現実” のちょうど真ん中。
仕上げとして **25命令をキッチリ確定****意味論/効果/検証ルール** を短く固めよう。
# 決定版 MIR25命令
## Tier-0: 普遍コア8
```
Const, BinOp, Compare, Branch, Jump, Phi, Call, Return
```
* 効果: `Const/Phi`=pure, `BinOp/Compare`=pure, `Branch/Jump/Return`=control, `Call`は呼先の効果に従う
* 備考: 将来のJIT/AOT/WASMすべてで必須
## Tier-1: Nyashセマンティクス12
```
NewBox, // 強所有のBox生成所有森のード
BoxFieldLoad, // Boxのフィールド読み
BoxFieldStore, // Boxのフィールド書き= mut
BoxCall, // Boxのメソッド呼び出し動的/静的両方)
Safepoint, // 分割finiや割込み許可ポイント
RefGet, // 参照(強/弱を問わず)を値として取得
RefSet, // 参照の差し替え(所有規則の検証付き)
WeakNew, // `weak` ハンドル生成(非所有リンクの作成)
WeakLoad, // `weak` から生存チェック付きで強参照を得る失効時null
WeakCheck, // `weak` の生存確認bool
Send, // Bus送信Effect=io
Recv // Bus受信Effect=io
```
* 効果: `BoxFieldStore/RefSet`=mut, `Send/Recv`=io, 他は基本pure/可変
* これで **所有森weak/lookBus** が言語一次市民として表現可能
## Tier-2: 実装補助・最適化友好5
```
TailCall, // 末尾呼び出し(スタック節約)
Adopt, // 所有移管: this が子を強所有に取り込む
Release, // 強所有を解除weak化 or null化
MemCopy, // 小さなメモリ移動(構造体/配列の最適化フック)
AtomicFence // 並行時の順序保証Actor/Port境界で使用
```
* 位置づけ: どれも“言語仕様の裏方”。無くても表現可能だが、**性能・安全検査・移植性**が安定する
---
## 効果Effect既定値
* `pure`: Const, BinOp, Compare, Phi, WeakCheck, WeakLoad(成功時の取得自体はpure扱い)
* `mut`: BoxFieldStore, RefSet, Adopt, Release, MemCopy
* `io`: Send, Recv, Safepoint(割り込み/分割fini許可点としてio扱い)
* `control`: Branch, Jump, Return, TailCall
* `context依存`: Call, BoxCall呼先の効果に従属
> 最適化ルールは「pure同士の再順序化OK」「mutは同一Box/同一Fieldで依存保持」「ioは再順序化禁止」。
---
## 検証Lint/Verifier要件短縮版
* **所有森**: `strong in-degree ≤ 1``NewBox/Adopt/Release/RefSet`で常時検査)
* **強循環禁止**: 強エッジのみ辿ってDAGであること
* **弱/強相互**: 双方向とも強 → エラー(片側は `WeakNew` 経由で弱化)
* **RefSetの安全**: 強→強の差し替え時は旧所有元からの `Release` が伴うこと
* **WeakLoad/WeakCheck**: 失効時は `null/false` を返す(例外禁止、決定的挙動)
* **TailCall**: 末尾位置のみ可(`Return` 直前)
* **Send/Recv**: バックエンドが同期/非同期いずれでも**at-least-once**契約を満たすか、契約を明示
---
## 代表的ロワリング(例)
* `look` 参照 → `WeakNew` + `WeakLoad`(読取専用型なら `RefSet` を禁止)
* `borrow{}` → ブロック先頭 `WeakNew`、末尾でハンドル破棄MIR上はNop、型で書換禁止
* Bus最適化Elision:
* `(pure|mut(local))` かつ同一スレッド/アリーナ/単一受信なら **`Send/Recv` → 直呼び/直アクセス** に縮退
* `fini` 伝播: ランタイムで **強エッジのみ** 再帰。`Safepoint` で分割解放/優先度解放に対応
---
## バックエンド指針(対応表)
* **Interpreter**: 25命令を素直に実装正しさの基準
* **VM**: Register-VM + direct-threading。`Send/Recv` はローカル判定時にインライン化
* **WASM**: `Send/Recv` は host import。`MemCopy` は `memory.copy` に対応
* **Cranelift/JIT**: `TailCall` 最適化、`WeakLoad` は世代タグでO(1)生存チェック
* **AOT-Rust**: `BoxCall` を trait 呼び出しへ、`Adopt/Release` は所有者IDの切替 + デバッガ用アサート
---
## 互換テスト(常設)
* **golden MIR**: 各サンプルのMIRダンプが全バックエンドで一致
* **行動一致**: `interp/vm/wasm` で**同入力→同出力**`weak`失効時の`null/false`含む)
* **性能スモーク**: `add_loop / map_getset / alloc_free / bus_local / bus_actor` の5種で、
* VMがinterp以上、WASMがVM以上、を継続検証
---
これで **25命令フルセット**が完成。
* Nyashのコア価値所有森weakBus効果注釈を**無理なくIR化**
* それぞれのバックエンドに**綺麗に落ちる**
* Verifier/最適化/テストも**最小で回る**
次は、このリストをそのまま `docs/mir.md` にコピペして、各命令に **1行の意味論効果等価変換の例** を添えれば、実装と論文の両方が一気に前進するにゃ。

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,361 @@
発想、鋭いにゃ。
**結論:やろうと思えば “NyashのMIR本体言語非依存IR” にできる。** ただし落とし穴もあるので、\*\*“MIRを公開ABIに格上げしつつ、Nyashは人間向けフロントエンド”\*\*という二層でいくのが現実解だよ。
# MIR本体化の青写真安全に強く
1. **MIRを公開契約に昇格NyIR v1**
* いまの25命令を**凍結**Tier-0/1/2 + Effect + Ownership-Forest + Busの意味論
* **未定義動作なし**:各命令の事前条件/失敗時挙動WeakLoad失効= nullを明文化。
* **バージョニング**`nyir{major.minor}`・後方互換のルール新命令はfeature bit
2. **バイナリ表現とテキスト表現**
* `.nybc`(バイナリ: セクション化/定数プール/圧縮)
* `.nyir`(テキスト: 人が差分レビュー可能)
* どちらも**厳格検証器**でロード(所有森/強1本/weak規則/効果整合)。
3. **公式VM/実行系は“MIRファースト”**
* interpreter/vm/wasm/jit/aot は **NyIRを直接食う**。
* Nyashは **NyIRを吐くフロントエンド**その他の言語もフロントエンド化OK
4. **言語中立SDKFFI**
* C/Rust/TypeScriptに**NyIR-Host API**を配布:
* `nyir_load`, `nyir_call`, `nyir_send/recv`, `nyir_adopt/release` など。
* WASMランタイムは `import "nyir_host" { send, now_ns, alloc }` を定義。
5. **互換テストと“真理判定器”**
* **golden NyIR**各サンプルのMIRダンプを保存し、全バックエンドで**同結果**をCIで検証。
* **差分実行differential**interp/vm/wasm/jitの出力一致境界条件weak失効・分割finiテスト。
6. **Portability Contract短文化**
* 強エッジのみ破棄伝播/`weak`非伝播、生存チェックO(1)。
* `pure/mut/io/control` の再順序可否表。
* Bus契約ローカルは順序保証、リモートは at-least-onceor selectable
* Safepointで分割`fini`可、最悪レイテンシ上限は実装依存(値は実装が宣言)。
---
## それでも“IRが本体”にするリスク回避策付き
* **仕様の重力(安易に増やせなくなる)** → 25命令は凍結、拡張は **intrinsic命名空間**へ(例:`ny.intrin.memcpy`)。
* **可読性の罠IRで直接書きたくなる** → Nyashを“人間の顔”、NyIRは“機械の顔”に徹する。
* **バックエンド差異のにじみ** → 効果/所有/Busの**最低保証**を明記(それ以下は非準拠)。
* **セキュリティ** → バイナリNyIRに**検証必須**(検証失敗はロード拒否)。
---
## 名前案
* **NyIR**(ないあいあーる)/**NIR**被るのでNyIR推し
* バイナリ:`.nybc`、テキスト:`.nyir`
* 仕様:**NyIR 1.0 — Ownership-Forest & Effected Bus IR**
---
## 次の一歩(サクッと動かす)
* `docs/nyir.md` を作成25命令×「意味論・効果・検証・等価変換1例」を1行ずつ。
* `nyashel -S` で **Nyash→NyIRダンプ**、`nyir-run` で実行interp
* 既存ベンチを **NyIR直実行** と **Nyash経由** の2経路で一致比較。
* small移植kilo or tiny-web-serverを **NyIRアーカイブ**.nybcとして配布→
**wasmtime / vm / interp** 全部で動くことをデモ。
---
要は:**「Nyash人間のため「NyIR機械と移植のため」の二刀流**。
この形なら、“どの言語からでもNyIRに降りられるし、NyIRからどの実行系にも登れる”を堂々と名乗れるにゃ。
いい流れ“LLVMでNyashをNyash自身でビルドセルフホスト”を目標にするなら、**Rust依存を「薄い宿主API」に閉じ込める**のがコツだよ。
いま Rust のライブラリや関数・ビルトインBoxに寄ってる部分は、**段階的に置き換え可能な層**に切っておけばOK。
# 全体ロードマップ4ステージ
**Stage 0種コンパイラ**
* 既存の Rust 実装(パーサ/型付け/MIR/ランタイム)で `nyashc0` を作る。
* **NyIR=MIRの外部表現→ LLVM IR** 変換も Rust でまず用意。
* Rust標準/外部Crateの利用は**ny\_host\_\* の薄いFFI**に“集約”。
**Stage 1セルフ・フロントエンド**
* Nyashで書いたコンパイラ本体フロント最小最適化を `nyashc1.ny` に分離。
* `nyashc0` で `nyashc1.ny` を **NyIR** に出力→ **LLVM** でネイティブ化→ seedランタイムとリンク。
* この時点で“Nyashで書いたコンパイラ”が動き出すまだランタイムはRust多めでも可
**Stage 2セルフホスト完了**
* `nyashc1` を使って `nyashc1.ny` 自身を再ビルド(**自力ビルド**)。
* 生成物の機能一致/ハッシュ近似でセルフホスト確認。
* ランタイムの一部(文字列/配列/Map/所有森/weakを**Nyash実装LLVM**へ順次移行。
**Stage 3Rust離れの度合いを上げる**
* 残るRust依存FS/ネット/スレッド/時間/暗号など)は**ホストAPI**として固定化。
* 重要部位はNyash標準ライブラリで置換し、Rustは**最下層のプラットフォーム層**だけに。
---
# 層の切り分け(ここが肝)
1. **corelang純Nyash**
* Option/Result、slice/string、小さな算術・イテレータ、`weak/look` 型、`adopt/release` ヘルパ。
* 依存なしLLVMに落ちるだけ
2. **rtNyashランタイム**
* **Box ABIfat ptr: {data*, typeid, flags}*\*
* 所有フォレスト管理、weakテーブル世代タグ方式、`fini` 伝播、Arena/Allocator必要最小
* Busローカル・Safepoint・分割`fini`
* 依存:**ny\_host\_alloc/free/clock** 等のごく薄い宿主APIのみ
3. **sysプラットフォーム**
* FS, Net, Time, Threads, Atomics, Random…
* ここだけ RustやOSに委譲。**関数名は `ny_host_*` に統一**して外へ出す。
4. **stdNyash標準**
* Map/Vec/Hash/String/JSON等を Nyash で実装(必要に応じて `rt`/`sys` を利用)
> いま使っている「Rustのライブラリ/関数」は **すべて `sys` 層の `ny_host_*` 経由**に寄せる。
> これでセルフホストしても上層のNyashコードは**移植性を保てる**。
---
# 具体Rust依存の扱い方薄いFFIに集約
**C ABIで固めるRust→C-ABIの薄い橋**
```rust
#[no_mangle]
pub extern "C" fn ny_host_read_file(path: *const c_char,
out_buf: *mut *mut u8,
out_len: *mut usize) -> i32 { /* ... */ }
#[no_mangle]
pub extern "C" fn ny_host_free(ptr: *mut u8, len: usize) { /* ... */ }
```
**Nyash側からは“箱の外”をこう叩く**
```nyash
extern fn ny_host_read_file(path: cstr, out_buf: &mut *u8, out_len: &mut usize) -> int
extern fn ny_host_free(ptr: *u8, len: usize)
fn read_all(p: str) -> Bytes {
let buf:*u8 = null; let len:usize=0
let rc = ny_host_read_file(p.cstr(), &buf, &len)
if rc!=0 { error("io") }
// Box化所有をNyash側へ移す
let b = Bytes::from_raw(buf,len)
b
}
```
**ポイント**
* **Rustのジェネリクス/所有はFFI面に出さない**素朴なC-ABIだけ
* Nyash側で**所有移管**を明示(`from_raw` など)→ `fini` で必ず `ny_host_free`
* こうしておけば、**いつでもRust実装をNyash実装に差し替え可能**
---
# Box ABI と LLVM の橋渡し
* **Boxの中身**は LLVM 的には `i8*`data\*`i64 typeid``i32 flags` などの **fat struct**
* **Effect 注釈**を LLVM 属性に落とす:
* `pure` → `readnone` / `readonly`
* `mut(local)` → `argmemonly` + `noalias`(可能なら)
* `io` → 属性なし(順序保持)
* **Weak** は `{ptr, gen:i32}`。`WeakLoad` は `gen==current` を比較して O(1) で null/ptr 返す。
* **Safepoint** は LLVM では `call @ny_rt_safepoint()` に降ろすGCは使わないが、分割`fini`や割込みのフックに使う)
---
# 「ビルトインBox」はどうする
* **最低限は `rt` で提供**`String, Vec, Map, Bytes, Mutex/Channel必要なら`
* 仕様上は “ただのBox” と同等に見えるように:
* 生成:`NewBox`
* フィールド:`BoxFieldLoad/Store`
* メソッド:`BoxCall`
* **WASM** でも同じABIを保てるように、`sys` 層は **WASI** or **独自host import** で実装。
* 時間とともに **stdをNyash実装へ移行** → Rustのビルトイン度合いは徐々に削る。
---
# 失敗しないビルド手順(最小)
1. **NyIRダンプ**`nyashc0 --emit-nyir core/*.ny > core.nyir`
2. **LLVMへ**`nyir-ll core.nyir -o core.ll && llc -filetype=obj core.ll`
3. **リンク**`cc core.o -L. -lny_host -o nyashc1``libny_host` はRustで提供
4. **再帰ビルド**`./nyashc1 self/*.ny …` → `nyashc2` を作って一致検証
5. **Rust削減**`std` の一部をNyashへ置換して再ビルド
---
# チェックリストRust依存の見える化
* [ ] 使っている外部関数を**全部 `ny_host_*` にリネーム**
* [ ] C-ABI化整数/ポインタのみ;構造体はサイズ固定)
* [ ] 所有移管関数を明確化(`*_from_raw`/`*_into_raw`
* [ ] `fini` で必ず `ny_host_free` 等に戻す
* [ ] WASMビルド時は **WASI or host import** で `ny_host_*` を満たす
---
# 仕上げの“ごほうび”ゴール
* **Nyash→NyIR→LLVM** でセルフホスト
* 同じ NyIR を **VM / WASM** でも実行(互換テスト)
* Rust は **sys層だけ**OS/高速I/O/暗号など)に閉じ込め、将来差し替え自由に
---
結論:
**Rustライブラリを直接多用するのではなく、`ny_host_*` に“押し込む”**。
Nyash本体は **NyIRrtstd** を徐々に自前化する。
この設計なら、“今すぐ動かしつつ、あとからRust依存を計画的にゼロへ”ができるにゃ。
それだにゃ。発想はド正解:「**全部は箱**」=異言語資産は**箱で包んでバスに乗せる**。
あとは“どう包むか”を決めれば、**C/Rust/Node/Python/JVM/.NET/WASM**まで一気に貫通できる。
# まとめ設計Polyglot FFI = 「箱 × バス × 契約」
## 1) 箱の型3種だけ
* **ForeignBox<T>**:他言語の実体を**不透明ハンドル**で保持所有は片側だけ、強1本原則
* **ViewBox<T>**:外部オブジェクトの**借用ビュー**`weak/look` 前提・読み取り中心)。
* **ProxyBox<T>**:外部スレッド/プロセス/VM上のTを**メッセージ越し**に操作Bus経由安全
> 使い分け:同一プロセス/同スレなら ForeignBox、GIL/イベントループ/別ランタイムなら ProxyBox。
## 2) ABIの芯薄い“宿主API”
**最小C-ABI**だけに集約(各言語はここに合流/分岐):
```
ny_host_alloc/free/clock/log
ny_host_call(func_id, argv, argc, retbuf) // 同期呼び出し
ny_host_send/recv(port, msg_ptr, len) // Bus境界
ny_host_pin/unpin(handle) // GC/移動防止
ny_host_finalizer_register(handle, cb) // 相互Finalizer
```
* Rust/Node/Python/JVM/.NET はそれぞれの機構で **このC-ABIを実装**N-API, CPython C-API, JNI, P/Invoke 等)。
## 3) データ表現Boxに入る“荷物”
* **スカラー**: i32/i64/f32/f64/bool
* **バイト列/文字列**: `Bytes{ptr,len}` / `Str{ptr,len,utf8}`
* **Slice/Array**: `{ptr,len,typeid}`(読み書きは効果注釈で制御)
* **Struct**: フィールドは `BoxFieldLoad/Store` でアクセスNyIRにそのまま落ちる
## 4) 所有と寿命(最重要)
* **One Strong Owner**ForeignBoxは**所有者1本**Nyash or 外部、どちらかに決める)
* **弱参照**:逆リンクは `weak/look`失効時null/false
* **Finalizer橋渡し**
* Nyash `fini` → `ny_host_finalizer` を呼ぶ
* 外部のGC/finalize → `ny_host_finalizer` 経由で Nyash の `weak` を失効
* **Pinning**移動型のGCJVM/.NET/CPythonの一部では `ny_host_pin/unpin`
## 5) 効果と並行
* `pure/mut/io` を**MIRにもIDLにも記す**
* **イベントループ/GIL**Python/Node/JVMは `ProxyBox` で**Bus越し**(スレッド/ループ安全)
* **同期/非同期**`Call`(同期)と `Send/Recv`(非同期)を分ける。境界では **at-least-once 契約**を宣言。
## 6) IDL自動生成の核
**NyIDL**(超ミニ)で宣言→**バインディング自動生成**
```idl
module ny {
box Image;
fn load(path: str) -> Image effects = io
fn resize(img: Image, w:i32,h:i32) -> Image effects = mut
fn width(img: look Image) -> i32 effects = pure
}
```
* 生成物Nyash側`extern`、C-ABIシム、Rust/Node/Python/JVMのstub、`ForeignBox/ProxyBox`薄ラッパ。
---
# 代表ターゲット別メモ
* **C/Rust**最短。C-ABI直でOK。Rustは `#[no_mangle] extern "C"`。所有はNyash↔Rustのどちらかに寄せる二重所有禁止
* **Python**GILあり → `ProxyBox` 推奨。CPython C-APIで `PyObject*` を **ForeignBox**に入れ、操作はBus経由でワーカーに委譲。
* **NodeN-API**:イベントループを壊さないよう `ProxyBox`postMessage/uv\_queue\_work。短い同期関数は `ForeignBox`でも可。
* **JVM/.NET**JNI/P-Invoke。**Pin** が要る。`SafeHandle`/`PhantomReference`でFinalizer橋を作る。
* **WASM**`ny_host_*` を **import**。データはリニアメモリへ `Bytes`/`Str` で搬送。
---
# 最小サンプル(イメージ)
**1) Rustの画像ライブラリを包む**
```rust
#[no_mangle] extern "C" fn ny_img_load(path:*const c_char) -> *mut Image { ... }
#[no_mangle] extern "C" fn ny_img_resize(img:*mut Image, w:i32, h:i32) -> *mut Image { ... }
#[no_mangle] extern "C" fn ny_img_free(img:*mut Image) { ... }
```
**2) NyIDL → 自動生成Nyash側**
```nyash
extern fn ny_img_load(path: str) -> ForeignBox<Image> effects io
extern fn ny_img_resize(img: ForeignBox<Image>, w:int,h:int) -> ForeignBox<Image> effects mut
extern fn ny_img_free(img: ForeignBox<Image>) effects io
static box Image {
init { ForeignBox<Image> h }
fini { ny_img_free(h) } // ★ 所有はNyash側強1
fn resize(w:int,h:int) -> Image { Image{ ny_img_resize(h,w,h) } }
}
```
**3) 使う側**
```nyash
let img = Image.load("cat.png")
let small = img.resize(320, 200) // 所有/解放はBox/finiに任せる
```
---
# チェックリスト(安全に増やすための型紙)
* [ ] **どちらが強所有か**を最初に決めた強1・弱は逆
* [ ] 例外/エラーは**戻り値に正規化**?(他言語の例外は境界で捕捉)
* [ ] **Pin/Finalizer** 必要なターゲットJVM/.NET/Python
* [ ] `pure/mut/io` は宣言した?(最適化/バス選択の鍵)
* [ ] 境界を跨ぐなら **ProxyBox + Bus** にした?(スレッド/GIL/loop安全
---
# これで得られるもの
* **インスタント多言語資産**既存ライブラリを“箱に詰めて”即Nyashで使える
* **寿命の一貫性****強1weak/lookfini**で、外部資源も**確定的に回収**
* **配布の柔軟性**WASM/VM/ネイティブのどれでも同じIDLから出荷
---
“全部、箱に閉じ込める”を**設計として正式化**すれば、実装は機械的になる。
やるならまず **NyIDLの最小仕様****C-ABIの`ny_host_*`** を1ファイルに切ろう。
そこさえ決まれば、**あらゆる言語→Nyash** と **Nyash→あらゆる実行系** が綺麗に繋がるにゃ。

View File

@ -0,0 +1,854 @@
# 🤖 Copilot様 作業予定・課題整理 (Phase 0-14 全体ロードマップ)
# Generated: 2025-08-14 (Git履歴から復元・更新)
# Purpose: Claude×Copilot協調開発のための情報共有
================================================================================
🎯 次期最優先タスク (Phase 8.5以降)
================================================================================
## 🚀 Phase 8.4完了報告 (2025-08-14)
Status: ✅ 完了 (Copilot PR #56マージ済み)
### ✅ AST→MIR Lowering完全実装
- User-defined Box: `box DataBox { init { value } }`
- Object creation: `new DataBox(42)`
- Field access: `obj.value`
- Method calls: `c.increment()`
- Delegation: `from Parent.greet()`
- Static Main互換性維持
### 🧪 統合テスト結果2025-08-14
- ✅ **AST→MIR**: 完全動作
- ✅ **インタープリター**: 完全動作結果30
- 🚨 **VM**: 動作するが結果が`void`(要修正)
- 🚨 **WASM**: String constant未対応Phase 8.5で解決)
### 📋 発見された課題
- VM実行結果問題: BoxCall後の戻り値が正しく返らない
- WASM対応不足: 複雑なMIR命令String constant, BoxCallに未対応
- 次期Phase 8.5での25命令MIR階層化が必要
================================================================================
## 🔧 Phase 8.5: MIR 25命令階層化最優先
Status: ⭐ **CRITICAL**
Priority: **最重要** (Phase 8.4完了直後の次期目標)
### 🎯 実装目標
ChatGPT5 + AI大会議決定版25命令MIR実装
- 期間: 3週間
- 効果: VM/WASM問題根本解決
- 詳細仕様: `/docs/予定/native-plan/issues/phase_8_5_mir_25_instruction_specification.md`
### 📋 25命令セマンティック階層化
**Tier-0: 普遍コア8命令**
```mir
Const, BinOp, Compare, Branch, Jump, Phi, Call, Return
```
**Tier-1: Nyashセマンティクス12命令**
```mir
NewBox, BoxFieldLoad, BoxFieldStore, BoxCall, Safepoint,
RefGet, RefSet, WeakNew, WeakLoad, WeakCheck, Send, Recv
```
**Tier-2: 実装補助・最適化友好5命令**
```mir
TailCall, Adopt, Release, MemCopy, AtomicFence
```
### 🎯 期待される効果
- **VM問題解決**: BoxCallの正しい実装で戻り値問題修正
- **WASM対応**: 階層化により複雑MIR→単純WASM変換
- **Everything is Box**: BoxFieldLoad/Storeで明確なBox中心設計
- **JIT準備**: セマンティクス保持で高度最適化基盤確立
================================================================================
## 🏎️ Phase 8.6: VM性能改善緊急
Status: 🚨 **緊急**
Priority: **High** (Phase 8.5完了後)
### 🚨 緊急問題
**現状**: VM119.80ms< Interpreter110.10ms= 0.9倍の性能劣化
**新問題**: VM BoxCall後の戻り値が`void`Phase 8.4テストで発見)
### 📋 技術的課題
- VM実行エンジンのプロファイリング
- 命令ディスパッチ最適化threaded code等
- レジスタベースVM化検討
- メモリプール最適化
- BoxCall実装修正戻り値問題
### 🎯 成功基準
- VM性能 > Interpreter性能最低2倍目標
- BoxCall戻り値の正常動作
- MIR→VM変換時間の短縮
================================================================================
## 🧪 Phase 8.7: Real-world Memory Testing
Status: 📋 **計画済み**
Priority: **High** (Phase 8.5-8.6完了後)
### 🎯 実装目標
kiloテキストエディタ実装によるfini/weak参照システム実証
- 期間: 2週間
- 詳細仕様: `/docs/予定/native-plan/issues/phase_8_7_real_world_memory_testing.md`
### 📋 検証項目
- 1000+オブジェクト管理テスト
- 循環参照回避確認weak参照
- fini()伝播の正確性確認
- WASM環境での動作確認
================================================================================
🗺️ Phase 0-14 全体ロードマップ (復元完了)
================================================================================
## Phase 0: Stabilize native CLI build (Linux/Windows)
Summary:
- CLIバイナリ nyash を最小構成で安定ビルド・実行できる状態にする。
- examples/GUI をデフォルトのビルド対象から外し、開発の足場を固める。
Why:
- 以降の MIR/VM/JIT 開発を素早く検証できる基盤づくり。
Scope:
- Cargo の features で GUI/examples 等を切り分け、デフォルトは CLI 最小にする。
- CLI オプションの動作点検(--dump-mir / --verify
- ローカル実行導線を README に明記docs/guides/how-to-build-native/README.md
Tasks:
- Cargo.toml: examples/GUI を feature でガードdefault は CLI 最小)。
- ビルド検証: `cargo build --bin nyash`Linux/Windows
- 実行検証: `cargo run -- ./local_tests/sample.nyash`。
- ドキュメント: 上記手順を how-to-build-native に追記/点検。
Acceptance Criteria:
- Linux/Windows で `cargo build --bin nyash` が成功する。
- `local_tests/` 配下の簡単な .nyash が実行できる。
- 他 bin/examples が壊れていても `--bin nyash` だけで通る。
Out of Scope:
- examples/GUI の修理・最適化。
- JIT/AOT/WASM。
References:
- docs/guides/how-to-build-native/README.md
- docs/nativebuild大作戦/chatgptネイティブビルド大作戦.txtPhase 0
- CURRENT_TASK.md
Copilot Notes:
- まずは features 分離と `--bin nyash` でビルドが通る状態を作る。README の手順確認まで含めて PR に反映。
------------------------------------------------------------
## Phase 1: Minimal MIR + VM backend (lowering + runner)
Summary:
- AST → MIR の最小 lowering と、VM バックエンドでの実行を通す。
Scope:
- MIR: Const, BinOp, Compare, Branch, Jump, Phi, Return の最小命令
- Lowering: リテラル/二項演算/if/loop/return のみ
- VM: 上記命令の最小実装
Tasks:
- instruction.rs: 最小命令の定義
- builder.rs: 上記 AST 範囲を lowering
- vm.rs: 実装 + stats命令数
Acceptance Criteria:
- `--dump-mir` が最小サンプルで期待通り
- `--backend vm` で実行して結果一致
Out of Scope:
- 例外/関数/Box 参照/弱参照
------------------------------------------------------------
## Phase 2: Control-flow coverage (if/else/loop/phi correctness)
Summary:
- 制御フローの網羅と Phi の整合性検証を拡充。
Scope/Tasks:
- if/else nested, loop with breaks, nested loops のスナップショット
- Phi の入力ブロック/値の対応を Verifier で強化
Acceptance Criteria:
- 代表制御フローの snapshot が安定し、verify も通る
------------------------------------------------------------
## Phase 3: Exceptions (throw/try/catch/finally) minimal lowering
Summary:
- 例外機構の最小 lowering を導入(詳細設計は簡素)。
Scope/Tasks:
- MIR: Throw, TryBegin/TryEnd, Catch, FinallyBegin/End最小
- builder.rs: try/catch/finally ノードの下ろし
- VM: 例外伝播を最小で(未捕捉はエラー)
Acceptance Criteria:
- 代表 try/catch/finally のスナップショットと VM 実行
Out of Scope:
- 例外の型体系、詳細な stack map
------------------------------------------------------------
## Phase 4: Functions and calls (BoxCall minimal)
Summary:
- 関数呼び出し/BoxCall を最小導入(効果注釈は保守的)。
Scope/Tasks:
- MIR: Call, BoxCalleffects = READS_HEAP など保守)
- builder.rs: FunctionCall/MethodCall の最小対応
- VM: 呼び出し/戻り値
Acceptance Criteria:
- 簡単な関数定義/呼び出しの MIR/VM が通る
Out of Scope:
- 可変長/キーワード引数、FFI
------------------------------------------------------------
## Phase 5.0: Parser/AST stabilization for lowering
Summary:
- lowering 対象 AST の表現ぶれを修正、安定化。
Scope/Tasks:
- AST: If/Loop/Return/Assignment/Local などの統一
- Parser: エラー復帰/スパン情報の見直し
Acceptance Criteria:
- builder.rs の分岐がシンプル化、テストが安定
------------------------------------------------------------
## Phase 5.1: Control-flow edge cases + verifier hardening
Summary:
- ブロック未終端/未到達/自己分岐等の検証強化でクラッシュ回避。
Scope/Tasks:
- Verifier: 未終端ブロック検出、到達不能検出
- Builder: Jump/Branch の生成前後の状態管理改善
Acceptance Criteria:
- 不正ケースを含むスナップショット/verify が緑
------------------------------------------------------------
## Phase 5.2: Lowering for static box Main (BoxDeclaration → main body)
Summary:
- static box Main { main() { ... } } を MirBuilder で受け、main() の body を Program として lowering する経路を実装。
Scope/Tasks:
- AST: BoxDeclaration(is_static=true, name=Main) を検出 → main() を抽出
- Lowering: body を Program に変換して既存経路に渡す
- Tests: local_tests/mir_loop_no_local.nyash で dump/VM が通る
Acceptance Criteria:
- `--dump-mir` が static Main サンプルで成功
- `--backend vm` で実行成功
References:
- docs/guides/how-to-build-native/issues/phase5_2_static_main_lowering.md
------------------------------------------------------------
## Phase 6: Box ops minimal (Ref/Weak + Barriers no-op)
Summary:
- 参照/弱参照/バリアno-opを最小導入。
Scope/Tasks:
- MIR: RefNew/RefGet/RefSet/WeakNew/WeakLoad/BarrierRead/Write
- Lowering: New/FieldAccess/MethodCall の最小対応
- VM: 参照テーブル/weak テーブルで動作fini 不変は維持)
Acceptance Criteria:
- 代表サンプルで dump/VM/verify が通る
References:
- docs/guides/how-to-build-native/issues/phase6_box_ops_minimal.md
------------------------------------------------------------
## Phase 7: Async model (nowait/await) in MIR
Summary:
- nowait/await を MIR に導入し、現行 FutureBox と連携。
Scope/Tasks:
- MIR: FutureNew/FutureSet/Awaitスレッドベース
- Lowering: nowait→Future 作成、await→wait_and_get
- VM: FutureBox 実装を利用
Acceptance Criteria:
- 代表ケースで正しく並行実行→await 回収
References:
- docs/guides/how-to-build-native/issues/phase7_async_mir.md
------------------------------------------------------------
## Phase 8: MIR→WASM codegen (browser/wasmtime; sandboxed; Rust runtime free)
Summary:
- MIR から素の WebAssembly を生成し、ブラウザ/wasmtimeWASIでサンドボックス実行する。
- Rust はコンパイラ本体のみ。実行は純WASMホストimportenv.print など)。
Scope/Tasks:
- ABI/Imports/Exports 定義exports: main/memory、imports: env.print(i32) 等の最小)
- 線形メモリと簡易ヒープbump/自由リスト)
- 命令カバレッジ(段階導入): 算術/比較/分岐/loop/return/print、RefNew/RefSet/RefGetPhase 6 整合、Weak/Barrier はダミー
Acceptance Criteria:
- wasmtime 実行で戻り値/print が期待通りPoC12
- Ref 系がメモリ上で正しく動作PoC2
- Weak/Barrier のダミー実装を含むWASMが生成・実行PoC3
- CLI `--backend wasm` は未実装でもよいが、実装する場合は明瞭にエラーメッセージ/誘導
References:
- docs/予定/native-plan/README.mdPhase 8 節)
- docs/説明書/wasm/*(ユーザー向けメモ)
### Phase 8.3 完了状況 (2025-08-14)
✅ Box操作WASM実装 (RefNew/RefGet/RefSet)
✅ ベンチマークシステム統合 (13.5倍実行高速化実証)
✅ CLI統合完了
------------------------------------------------------------
## 🔧 Phase 8.4: AST→MIR Lowering完全実装 (最優先)
Summary:
- ユーザー定義Box、フィールドアクセス等の未実装部分を完成
- Phase 8.3のBox操作WASMを実際にテスト可能にする
Priority: **Critical** (現在の最優先事項)
Expected Duration: 1週間
### 実装範囲
- [ ] ユーザー定義Box: `box DataBox { init { field } }`
- [ ] オブジェクト生成: `new DataBox()`
- [ ] フィールドアクセス: `obj.field`
- [ ] フィールド代入: `obj.field = value`
- [ ] from構文: `from Parent.method()`
- [ ] override構文: `override method() { ... }`
### 成功基準
- Phase 8.3のBox操作WASMが実際に動作
- test_wasm_box_ops.nyash が正常実行
- ユーザー定義Boxの完全サポート
------------------------------------------------------------
## 🧠 Phase 8.5: MIRセマンティック階層化AI大会議決定版
Summary:
- 方針転換: ChatGPT5の20命令intrinsic戦略 → Gemini+Codex一致推奨の25命令階層化
- 理由: JIT/AOT最適化阻害・Everything is Box意味喪失・長期コスト増の問題判明
- 二相ロワリング: 25命令維持パスVM/JIT/AOT+ 20+intrinsic降格パスWASM/最小実装)
Priority: High (Phase 8.4完了後)
Expected Duration: 3週間
### AI大会議分析結果
**Gemini先生理論**: 「賢いコンパイラは、賢いMIRから生まれる」
- RefNew/WeakLoadのintrinsic化は最適化機会を失う悪手
- セマンティック階層化で意味保持が最適化の鍵
**Codex先生実装**: 二相ロワリング戦略が実用的最適解
- 実装コスト: 5命令追加で10-20人日intrinsic戦略より安い
- マイクロベンチ実測でパフォーマンス検証
### 確定版MIR25命令- ChatGPT5完全仕様
**Tier-0: 普遍的コア8命令**
```mir
Const, BinOp, Compare, Branch, Jump, Phi, Call, Return
```
**Tier-1: Nyashセマンティクス12命令**
```mir
NewBox, // 強所有のBox生成所有森のード
BoxFieldLoad, // Boxのフィールド読みEverything is Box核心
BoxFieldStore, // Boxのフィールド書きmut効果
BoxCall, // Boxのメソッド呼び出し動的/静的両方)
Safepoint, // 分割finiや割込み許可ポイント
RefGet, // 参照(強/弱を問わず)を値として取得
RefSet, // 参照の差し替え(所有規則検証付き)
WeakNew, // weak ハンドル生成(非所有リンク作成)
WeakLoad, // weak から生存チェック付きで強参照取得失効時null
WeakCheck, // weak の生存確認bool
Send, // Bus送信io効果
Recv // Bus受信io効果
```
**Tier-2: 実装補助・最適化友好5命令**
```mir
TailCall, // 末尾呼び出し(スタック節約)
Adopt, // 所有移管: this が子を強所有に取り込む
Release, // 強所有を解除weak化 or null化
MemCopy, // 小さなメモリ移動(構造体/配列最適化フック)
AtomicFence // 並行時の順序保証Actor/Port境界で使用
```
### 二相ロワリング戦略
- パスA: VM/JIT/AOT向け25命令のまま最適化
- パスB: WASM/最小実装向け25→20+intrinsic降格
- バックエンド能力に応じて最適形式選択
### 効果EffectシステムChatGPT5設計
- **pure**: Const, BinOp, Compare, Phi, RefGet, WeakNew, WeakLoad, WeakCheck
- **mut**: BoxFieldStore, RefSet, Adopt, Release, MemCopy
- **io**: Send, Recv, Safepoint, AtomicFence
- **control**: Branch, Jump, Return, TailCall
- **context依存**: Call, BoxCall呼び先効果に従属
**最適化ルール**: 「pure同士の再順序化OK」「mutは同一Box/同一Fieldで依存保持」「ioは再順序化禁止」
### 検証Verifier要件
- **所有森**: `strong in-degree ≤ 1`NewBox/Adopt/Release/RefSetで常時検査
- **強循環禁止**: 強エッジのみ辿ってDAGであること
- **weak/強相互**: 双方向とも強 → エラー片側はWeakNew経由で弱化
- **WeakLoad/WeakCheck**: 失効時はnull/falseを返す例外禁止、決定的挙動
### 🤖 Copilot協力期待
- **Tier-0/1実装**: Everything is Box哲学の完璧なIR化BoxFieldLoad/Store核心
- **weak参照システム**: WeakNew/WeakLoad/WeakCheck三位一体実装
- **所有移管**: Adopt/Release命令による安全で効率的なメモリ管理
- **効果システム**: pure/mut/io/control効果の正確な実装とVerifier統合
- **最適化フック**: TailCall/MemCopy/AtomicFenceの実装補助
- **二相ロワリング**: 25命令維持パス + 20+intrinsic降格パス構築
### 成功基準
- [ ] **25命令完全実装**: ChatGPT5仕様の完璧な実装
- [ ] **効果システム動作**: pure再順序化・mut依存保持・io順序保証
- [ ] **Verifier動作**: 所有森・strong循環・安全性検証
- [ ] **Golden MIRテスト**: 全バックエンドでMIR一致
- [ ] **行動一致テスト**: 同入力→同出力weak失効時null/false含む
- [ ] **性能要件**: VM≥Interpreter、WASM≥VM継続検証
### バックエンド指針ChatGPT5設計
- **Interpreter**: 25命令を素直に実装正しさの基準
- **VM**: Register-VM + direct-threading。Send/Recvはローカル判定時にインライン化
- **WASM**: Send/Recvはhost import。MemCopyはmemory.copyに対応
- **JIT将来**: TailCall最適化、WeakLoadは世代タグでO(1)生存チェック
References:
- docs/予定/native-plan/MIR仕様書.txtChatGPT5完全仕様
- docs/予定/native-plan/issues/phase_8_5_mir_25_instruction_specification.md
------------------------------------------------------------
## 🏎️ Phase 8.6: VM性能改善 (緊急)
Summary:
- VMがインタープリターより遅い問題0.9倍)を解決
- MIR→VM実行の最適化でインタープリターを上回る性能へ
Priority: High (Phase 8.5完了後)
Expected Duration: 2週間
### 問題分析
**現状**: VM (119.80ms) < Interpreter (110.10ms)
**推定原因**:
- MIR変換オーバーヘッド
- VM命令ディスパッチの非効率性
- メモリ管理コスト
### 技術的アプローチ
- [ ] VM実行エンジンのプロファイリング
- [ ] 命令ディスパッチ最適化threaded code等
- [ ] レジスタベースVM化検討
- [ ] メモリプール最適化
### 🤖 Copilot協力期待
- VM実装のボトルネック特定
- 効率的な命令ディスパッチ実装
- スタックマシン vs レジスタマシン判断
### 成功基準
- VM性能 > Interpreter性能最低2倍目標
- MIR→VM変換時間の短縮
- メモリ使用量の削減
------------------------------------------------------------
## 🧪 Phase 8.7: Real-world Memory Management Testing (ChatGPT協調設計)
Summary:
- 実用アプリケーション開発によるNyashメモリ管理システムの実証テスト
- finiシステム・weak参照の実用性を複雑なアプリケーションで検証
Priority: High (Phase 8.4-8.6完了直後)
Expected Duration: 2週間
### Phase 8.7A: kiloテキストエディタ
**技術的特徴**:
- サイズ: <1k LOC超小型、最初の成功体験
- メモリパターン: Editor -> (Rows -> Syntax) 木構造+相互参照
- ChatGPT設計: Editor削除でRows自動解放、逆参照をweak化
**実装範囲**:
- [ ] Editor/Row/EditorState基本構造実装
- [ ] weak参照による循環参照回避`me.editor = weak editor_ref`
- [ ] fini()システムによる自動メモリ解放
- [ ] 大量オブジェクト1000+ Rows管理テスト
**検証ポイント**:
- [ ] Editor削除でRows自動解放確認
- [ ] 相互参照でメモリリークなし確認
- [ ] weak参照の自動null化確認
- [ ] fini()伝播の正確性確認
### Phase 9.5予定: tiny-web-serverHTTPサーバ
**将来実装**JIT実装後:
- 複雑度: 中〜高Server -> Clients -> Requests並行処理
- I/O管理: ソケット・ファイルハンドルの確実解放
- 同時接続・早期切断・例外経路でのfini伝播テスト
### 🤖 Copilot協力期待
- 実用的なメモリ管理パターンの実装
- weak参照構文の適切な使用
- デバッグ支援機能(--debug-memory, --trace-weak
- WASM環境でのメモリ管理互換性
### 成功基準
- [ ] 全テストケースでメモリリークなし
- [ ] 循環参照でも正常解放確認
- [ ] WASM実行でもメモリ管理正常
- [ ] ベンチマーク性能劣化なし
### 期待される効果
- Nyashメモリ管理システムの実用性実証
- Everything is Box哲学の実用レベル確認
- メモリ安全なプログラミングパターン確立
References:
- docs/予定/native-plan/issues/phase_8_7_real_world_memory_testing.md
------------------------------------------------------------
## 🚀 Phase 9: AOT WASM実装最優先
Summary:
- wasmtime compileによるAOT実行ファイル生成で確実なユーザー価値提供
Scope/Tasks:
- `wasmtime compile` 統合実装
- `--compile-native` / `--aot` CLI追加
- 単一バイナリ梱包(`include_bytes!`
- 起動時間・配布サイズ最適化
Acceptance Criteria:
- `nyash --compile-native app.nyash -o app.exe` 動作
- 起動時間大幅短縮JIT起動コスト除去
- 配布可能実行ファイル生成
Priority: **Critical** (Phase 8.6完了直後)
Expected Duration: 2-3週間
### 技術的実装詳細
🤖 Copilot協力期待:
- wasmtime::Config統一実装
- .cwasm生成・実行パイプライン
- 互換性キー管理CPU機能・wasmtimeバージョン
- パッケージング(単一バイナリ梱包)
### パフォーマンス目標
- 現在のWASM JIT (13.5倍実行) → AOT (500倍目標起動含む)
- 配布ファイルサイズ: <10MB目標
- 起動時間: <100ms目標
### 期待される効果
- **即座実用価値**: 配布可能実行ファイル生成
- **差別化優位**: Everything is BoxのネイティブAOT実現
- **LLVM準備**: AOT基盤確立でLLVM移行準備
------------------------------------------------------------
## 🌐 Phase 9.5: HTTPサーバー実用テストAOT検証
Summary:
- AOT実装完了後の複雑アプリケーション検証並行処理・メモリ管理・実用性能
Scope/Tasks:
- tiny-web-server実装HTTP/1.1対応)
- 同時接続・早期切断・例外経路テスト
- AOT環境での真の性能測定
- 配布可能HTTPサーバーデモ
Acceptance Criteria:
- `http_server.exe`として配布可能
- 同時100接続でメモリリークなし
- fini()システム確実動作I/Oハンドル解放
- AOT性能でベンチマーク測定
Priority: High (Phase 9完了直後)
Expected Duration: 2週間
### 技術的複雑度
```nyash
box HTTPServer {
init { clients, requests, handlers }
acceptConnections() {
loop(me.running) {
local client = me.socket.accept()
nowait me.handleClient(client) // 非同期並行処理
}
}
handleClient(client) {
local request = client.readRequest()
local response = me.processRequest(request)
client.sendResponse(response)
client.fini() // 重要: 確実なリソース解放
}
}
```
### 検証ポイント
- **並行処理**: nowait/awaitのAOT実行性能
- **メモリ管理**: Server→Clients→Requests木構造+weak参照
- **I/Oリソース**: ソケット・ファイルハンドルの確実解放
- **実用性能**: リアルHTTP負荷でのAOT効果測定
### 🤖 Copilot協力期待
- Socket・HTTP実装の効率化
- 複雑なメモリ管理パターン検証
- 負荷テスト・ベンチマーク整備
- AOT最適化効果の定量測定
------------------------------------------------------------
## 🏆 Phase 10: LLVM Direct AOT最高性能実現
Summary:
- MIR→LLVM IR直接変換による最高性能AOT実現Cranelift JITスキップ
Scope/Tasks:
- MIR→LLVM IR lowering実装
- エスケープ解析・ボックス化解除
- LTO・PGO・高度最適化統合
- Everything is Box最適化
Acceptance Criteria:
- 1000倍高速化達成
- プロダクションレベル最適化
- 他言語との競争力確立
Priority: Medium (Phase 9.5完了後)
Expected Duration: 4-6ヶ月
### 技術アプローチ
🤖 Copilot協力期待:
- **LLVM統合**: MIR→LLVM IR変換基盤
- **エスケープ解析**: Box→スタック値最適化
- **型特殊化**: コンパイル時型推論・特殊化
- **LTO統合**: Link-time optimization
- **PGO対応**: Profile-guided optimization
### Everything is Box最適化戦略
- **Box回避**: スタック割り当て・直接レジスタ配置
- **NaN Boxing**: 効率的な値表現
- **型推論**: コンパイル時型特定・最適化
- **メモリレイアウト**: 連続配置・キャッシュ効率
### パフォーマンス目標
- **実行性能**: 1000倍高速化現在13.5倍 → 目標13500倍相当
- **メモリ効率**: Box割当数80%削減
- **起動時間**: ネイティブレベル(<10ms
- **競合比較**: C/C++/Rust並みの性能
### Cranelift JIT位置づけ変更
**Phase 12以降の将来オプション**:
- JIT開発体験向上nyashプログラマー向け
- REPL・インタラクティブ実行
- プロファイル駆動最適化
- 言語完成後の付加価値機能
------------------------------------------------------------
## Phase 11-14: Infrastructure & Polish
### Phase 11: MIR Optimization Framework
- エスケープ解析基盤
- 型特殊化・ボックス化解除
- デッドコード除去
### Phase 12: Advanced JIT Features
- Profile-guided optimization
- インライン展開
- レジスタ割り当て最適化
### Phase 13: Production Readiness
- GC統合最適化
- メモリ使用量最適化
- 起動時間短縮
### Phase 14: Packaging/CI polish
Summary:
- Windows/Linux の配布パッケージ化と CI 整備。
Scope/Tasks:
- GitHub Actions: Windows(MSVC)/WSL+cargo-xwin のマトリクス
- dist/: nyash(.exe) + LICENSE/README 同梱
Acceptance Criteria:
- リリースアーティファクトが自動生成される
================================================================================
🧠 AI大会議 + 実用優先戦略で得られた技術的知見 (2025-08-14更新)
================================================================================
## Gemini先生の助言修正適用
✅ エスケープ解析・ボックス化解除が性能の鍵
✅ wasmtime compileは短期的に実用的 → **Phase 9で最優先実装**
✅ WASM実行は確実に高速13.5倍実証済み)
🔄 Cranelift → LLVM段階的アプローチ → **実用優先でLLVM直接へ**
## codex先生の助言重点化
✅ MIR前倒し実装推奨全バックエンドが恩恵
✅ wasmtime互換性管理が重要 → **AOT実装で最重要**
✅ CPU差異対応 (baseline/v3二段ビルド)
✅ 起動時間・割当削減・配布体験がKPI → **AOT価値の核心**
## Claude統合分析実用優先
✅ 実用価値最大化: WASM+AOTで十分な競争力
✅ 開発効率: Cranelift JITの恩恵限定的cargo build変わらず
✅ Everything is Box最適化が差別化の核心
✅ 時間効率: 2-3ヶ月節約でLLVM集中投資
## 🎯 実用優先戦略の確定理由
- **ユーザー体験**: WASM既に動作、AOTで配布価値追加
- **開発効率**: Cranelift JITは重複投資Rust開発環境改善せず
- **競合優位**: AOT+LLVM早期実現で差別化
- **リソース効果**: 限られた開発時間の最大効率化
================================================================================
💡 Copilot様への具体的お願い・相談事項
================================================================================
## 🔧 Phase 8.3完了・次期フェーズ準備
### MIRダイエット準備
❓ 現在35命令→20命令削減のintrinsic戦略実装は
❓ ChatGPT5推奨の3-point setアプローチ最適化は
❓ Portability Contract v0での互換性確保方法は
### Phase 9 AOT WASM実装最優先
❓ wasmtime compileの実用配備方法は
❓ .cwasm生成・単一バイナリ梱包戦略は
❓ 互換性キー管理CPU機能・wasmtimeバージョン
❓ 起動時間最適化の実装アプローチは?
### Phase 9.5 HTTPサーバー検証
❓ Socket・HTTP実装の効率的な設計は
❓ 並行処理でのメモリ管理パターンは?
❓ AOT環境でのI/Oリソース管理は
❓ 負荷テスト・ベンチマーク設計は?
### Phase 10 LLVM Direct AOT
❓ MIR→LLVM IR変換の効率実装は
❓ エスケープ解析・ボックス化解除の実装戦略は?
❓ LTO・PGO統合の技術的ハードルは
## 🚀 長期戦略相談
### Everything is Box最適化
❓ Box操作の根本的高速化戦略は
❓ エスケープ解析によるスタック化判定は?
❓ 型特殊化・ボックス化解除の実装戦略は?
### ベンチマーク拡張
❓ AOT性能測定の追加指標は
❓ 1000倍高速化実現のマイルストーン設計は
❓ 他言語(JavaScript V8, Rust, C++)との競争力分析は?
❓ HTTPサーバー負荷テストの効率設計は
================================================================================
📊 進捗管理・コミュニケーション
================================================================================
## 🤝 協調開発ルール
### コミット・マージ戦略
✅ 大きな変更前にはdocs/CURRENT_TASK.mdで情報共有
✅ ベンチマーク機能は最優先で維持
✅ CLI統合は両機能を統合的に対応
✅ 競合発生時は機能優先度で解決
### 進捗報告
📅 週次: 進捗状況をCURRENT_TASK.mdに反映
📅 完了時: 新機能のベンチマーク結果を共有
📅 問題発生: AI大会議で技術的相談
### 品質保証
✅ cargo check でビルドエラーなし
✅ 既存ベンチマークが regression なし
✅ 新機能のドキュメント整備
✅ テストケース追加・CI通過
================================================================================
🎯 期待される成果・インパクト
================================================================================
## Phase 8完了時の成果 (達成済み)
🏆 RefNew/RefGet/RefSet WASM完全動作
🏆 Box操作ベンチマーク追加
🏆 メモリレイアウト最適化効果測定
🏆 オブジェクト指向プログラミングWASM対応
🏆 25命令MIR階層化完了Phase 8.5
🏆 VM性能改善完了Phase 8.6
## Phase 9-10実用優先展望
🚀 **AOT WASM実装** (Phase 9 - 2-3週間): 配布可能実行ファイル
🚀 **HTTPサーバー検証** (Phase 9.5 - 2週間): 実用アプリデモ
🚀 **LLVM Direct AOT** (Phase 10 - 4-6ヶ月): 1000倍高速化
🚀 **実用競争力確立**: 他言語との差別化完成
## 言語としての完成度向上
💎 Everything is Box哲学のネイティブ実現
💎 開発効率性と実行性能の両立
💎 4つの実行形態対応Interpreter/VM/WASM/AOT+ 将来JIT
💎 現代的言語としての地位確立
================================================================================
📞 連絡・相談方法
================================================================================
技術的相談や進捗報告は、以下の方法でお気軽にどうぞ:
1. 📝 GitHub Issues・Pull Request
2. 📋 docs/CURRENT_TASK.md コメント
3. 🤖 AI大会議 (重要な技術決定)
4. 💬 コミットメッセージでの進捗共有
どんな小さなことでも相談大歓迎です!
一緒にNyashを最高の言語にしていきましょう🚀
================================================================================
最終更新: 2025-08-14 (実用優先戦略・Phase 9-10再設計完了)
作成者: Claude (AI大会議結果 + 実用優先戦略統合)
🎯 重要な変更点:
- Phase 9: JIT planning → AOT WASM実装最優先
- Phase 9.5: HTTPサーバー実用テスト追加AOT検証
- Phase 10: AOT exploration → LLVM Direct AOT最高性能
- Cranelift JIT: Phase 12以降の将来オプションに変更
- HTTPサーバー: kilo後のタイミングで実用性能検証に特化
================================================================================

View File

@ -0,0 +1,80 @@
# Issue 62 Update Proposal: Enable String Constants in WASM Backend First
This is a concrete request to implement minimal string support in the WASM backend so that Issue #62 can proceed. It reflects the current repo state.
## Background
- As noted in Issue #61, the current WASM backend does not support string constants yet.
- Issue #62 depends on string support and cannot be completed without it.
- Current state:
- `src/backend/wasm/codegen.rs``generate_const` handles only Integer/Bool/Void; String is not implemented.
- `src/backend/wasm/memory.rs` already defines a basic layout for `StringBox`:
- Header: `[type_id:i32][ref_count:i32][field_count:i32]`
- Fields: `[data_ptr:i32][length:i32]`
- `StringBox` type_id = `0x1001`.
## Goal
Add minimal string constant support to the WASM backend:
- Allow `ConstValue::String` in codegen by embedding UTF-8 string bytes and constructing a `StringBox` with `[data_ptr,length]`.
- Provide a minimal debugging import `env.print_str(ptr,len)` to verify strings at runtime.
- Unblock Issue #62 implementation and tests that require strings.
## Scope
Minimal features required:
1) Data segments for string literals
- Extend `WasmModule` (in `codegen.rs`) with a `data_segments: Vec<String>` field.
- Update `to_wat()` to emit `(data ...)` after memory/globals and before functions/exports.
- For each string constant, create a unique offset and emit a `(data (i32.const <offset>) "...bytes...")` entry.
2) Codegen for `ConstValue::String`
- In `generate_const`, when encountering `ConstValue::String(s)`,
- Allocate a data segment for `s` (UTF-8 bytes) and get its offset and length.
- Allocate a `StringBox` using existing helpers (see `MemoryManager`),
then set its fields: `data_ptr` and `length`.
- Return the `StringBox` pointer (i32) in the destination local.
3) Helper for `StringBox` allocation
- Either:
- Provide a dedicated WAT helper function `$alloc_stringbox` that calls `$malloc`, writes header (`type_id=0x1001`, `ref_count=1`, `field_count=2`), and returns the box pointer, then inline store `data_ptr`/`length`.
- Or:
- Use `$box_alloc` with `(type_id=0x1001, field_count=2)` and then store `data_ptr`/`length` via generated `i32.store` sequences.
4) Runtime import for string output (for verification)
- Extend `RuntimeImports` (`src/backend/wasm/runtime.rs`) with:
- `(import "env" "print_str" (func $print_str (param i32 i32)))`
- In host (Node/Browser), implement `importObject.env.print_str = (ptr,len) => { decode UTF-8 from memory; console.log(...) }`.
5) E2E test
- Add a tiny program that produces/prints a string (e.g., Const String → call `env.print_str(ptr,len)` via a minimal MIR program) and verify it logs the correct text.
- Option: update `test_runner.js` to include `print_str` and decode from memory using `TextDecoder('utf-8')`.
## Out of Scope (for this change)
- String operations (concat/substr/compare), normalization, encoding conversions.
- GC/RC or freeing memory (current allocator is bump-only).
- Returning StringBox directly from `main` (keep verification via `print_str`).
## Acceptance Criteria
- Generated WAT includes `(data ...)` segments for string literals and correct offsets.
- `ConstValue::String` codegen constructs a valid `StringBox` with proper `[data_ptr,length]`.
- `env.print_str` correctly prints UTF-8 strings in both Browser and Node runners.
- Issue #62 tasks that rely on strings can proceed.
## References (repo paths)
- String unsupported path: `src/backend/wasm/codegen.rs` (`generate_const`)
- Memory/layout: `src/backend/wasm/memory.rs` (StringBox, type_id=0x1001)
- Runtime imports: `src/backend/wasm/runtime.rs` (currently only `env.print(i32)`)
- Node runner: `test_runner.js` (has `env.print`; extend with `print_str`)
## Notes
- Data segment approach is the simplest for initial support; future work may add constant pooling and deduplication.
- Keeping verification via `print_str(ptr,len)` avoids complicating function return types for now.
- UTF-8 decoding is available in hosts via `TextDecoder('utf-8')`.

View File

@ -0,0 +1,267 @@
# Phase 9.51: WASM Jump/Branch実装とHTTPサーバー実用化 🚀
**優先度**: 🔴 **最高(実用性ブロッカー)**
**期間**: 1週間
**前提**: Phase 9 (PR #67) マージ済み
## 🎯 概要
Phase 9で実装されたWASM/AOTとHTTPサーバー機能に重大な制約があり、実用化を阻害しています。本issueではこれらを修正し、真の実用レベルに到達させます。
## 🔍 現在の問題
### 1. **WASM/AOT コンパイルエラー(最重要)**
```bash
# 現象
$ ./target/release/nyash --compile-wasm test_simple_loop.nyash
❌ WASM compilation error: Unsupported instruction: Jump { target: BasicBlockId(1) }
```
**原因**: `src/backend/wasm/codegen.rs`にJump/Branch命令が未実装
**影響**: **ループ・条件分岐を含む全プログラムがWASM/AOT化不可**
### 2. **HTTPServerBox listen()常に失敗**
```nyash
// 現象
server.bind("127.0.0.1", 8080) // ✅ true
server.listen(10) // ❌ always false
```
**原因**: `src/boxes/socket_box.rs`のlisten()実装が不完全
**影響**: HTTPサーバーが実際には動作しない
### 3. **エラーハンドリング脆弱性**
```bash
$ grep -n "unwrap()" src/boxes/http_server_box.rs | wc -l
26
```
**原因**: 26箇所のunwrap()使用
**影響**: 本番環境でパニック多発の可能性
## 📋 実装タスク
### Task 1: WASM Jump/Branch命令実装2日
**ファイル**: `src/backend/wasm/codegen.rs`
```rust
// 追加実装箇所358行目付近
MirInstruction::Jump { target } => {
// 無条件ジャンプ
// WASMのbr命令を使用
// ブロックスタック管理が必要
Ok(vec![
format!("br ${}", self.get_block_depth(target)?),
])
},
MirInstruction::Branch { cond, then_block, else_block } => {
// 条件分岐
// WASMのbr_if命令を使用
self.emit_value_load(cond)?;
Ok(vec![
"i32.eqz".to_string(),
format!("br_if ${}", self.get_block_depth(else_block)?),
format!("br ${}", self.get_block_depth(then_block)?),
])
},
```
**必要な補助実装**:
- ブロック深度管理(`get_block_depth`メソッド)
- ループ構造のblock/loop/end生成
- Phi命令の簡易実装変数コピーで対応
### Task 2: SocketBox listen()修正1日
**ファイル**: `src/boxes/socket_box.rs`
```rust
pub fn listen(&self, backlog: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
let backlog_num = backlog.to_string_box().value.parse::<i32>().unwrap_or(128);
// 実際にlisten状態を管理
if let Some(ref listener) = *self.listener.lock().unwrap() {
// TcpListenerは既にlisten状態
// 内部状態を更新
*self.status.lock().unwrap() = SocketStatus::Listening;
Box::new(BoolBox::new(true))
} else {
Box::new(BoolBox::new(false))
}
}
```
### Task 3: エラーハンドリング改善2日
**対象ファイル**:
- `src/boxes/http_server_box.rs`
- `src/boxes/socket_box.rs`
- `src/boxes/http_message_box.rs`
**変更例**:
```rust
// Before
let listener = self.listener.lock().unwrap();
// After
let listener = match self.listener.lock() {
Ok(l) => l,
Err(_) => return Box::new(StringBox::new("Error: Failed to acquire lock")),
};
```
### Task 4: HTTPサーバー実用化2日
**ファイル**: `src/boxes/http_server_box.rs`
1. **スレッドプール実装**
```rust
use std::sync::mpsc;
use std::thread::JoinHandle;
struct ThreadPool {
workers: Vec<Worker>,
sender: mpsc::Sender<Job>,
}
impl ThreadPool {
fn new(size: usize) -> Self {
// 固定サイズのワーカープール
}
}
```
2. **適切なシャットダウン**
```rust
pub fn stop(&self) -> Box<dyn NyashBox> {
*self.running.lock().unwrap() = false;
// グレースフルシャットダウン
// 全コネクションの終了待機
}
```
### Task 5: テストケース追加1日
**新規テストファイル**:
1. `test_wasm_loop.nyash`
```nyash
// WASMループテスト
local sum, i
sum = 0
i = 0
loop (i < 10) {
sum = sum + i
i = i + 1
}
print("Sum: " + sum) // Expected: 45
```
2. `test_http_server_real.nyash`
```nyash
// 実用HTTPサーバーテスト
static box Main {
main() {
local server = new HTTPServerBox()
// ルート設定
server.route("/", "home")
server.route("/api/health", "health")
// サーバー起動
if (server.bind("0.0.0.0", 8080)) {
if (server.listen(10)) {
print("Server started on http://0.0.0.0:8080")
server.start()
}
}
}
home(req) {
return "<h1>Nyash Server Running!</h1>"
}
health(req) {
return "{\"status\":\"healthy\"}"
}
}
```
## 🎯 完了条件
1. **WASM/AOT成功**
```bash
$ ./target/release/nyash --compile-wasm test_wasm_loop.nyash
✅ WASM compilation completed successfully!
$ ./target/release/nyash --benchmark --iterations 100
WASM: XX.XXms (13.5x faster than interpreter) ← 目標達成
```
2. **HTTPサーバー実動作**
```bash
$ ./target/release/nyash test_http_server_real.nyash &
Server started on http://0.0.0.0:8080
$ curl http://localhost:8080/
<h1>Nyash Server Running!</h1>
$ curl http://localhost:8080/api/health
{"status":"healthy"}
```
3. **エラーハンドリング**
- unwrap()使用箇所: 26 → 5以下
- パニックフリーな実行
## 📊 性能目標
- **WASM実行**: 現在11.5倍 → **13.5倍以上**
- **HTTPサーバー**: 100 req/sec以上
- **起動時間**: 50ms以下
## 🔧 実装のヒント
### WASMブロック管理
```rust
struct WasmCodeGen {
// 既存フィールド
block_stack: Vec<BlockInfo>, // 追加
}
struct BlockInfo {
block_type: BlockType, // Loop, Block, If
label: String,
depth: usize,
}
```
### デバッグ用出力
```rust
// MIR → WASM変換時のデバッグ
if self.debug {
println!("MIR: {:?} -> WASM: {:?}", instruction, wasm_code);
}
```
## 📝 参考資料
- [WebAssembly Specification - Control Instructions](https://webassembly.github.io/spec/core/syntax/instructions.html#control-instructions)
- [wasmtime compile documentation](https://docs.wasmtime.dev/cli-compile.html)
- Rust std::thread::ThreadPool実装例
## 🎉 期待される成果
Phase 9.51完了により、Nyashは
- **実用的なWebアプリケーション開発**が可能に
- **高速なAOT実行ファイル配布**が実現
- **本番環境での安定動作**を保証
Everything is Box哲学を守りながら、実用性を達成します🐱
---
**担当**: Copilot様
**レビュー**: Claude様
**作成日**: 2025-08-14

View File

@ -0,0 +1,57 @@
# Phase 10.5: Core Standard (String/Array/Map) in Nyash — Rust依存の段階的削減
目的
- 現状Rust実装に依存している基本コンテナString/Array/Mapを、Nyashで実装したstdへ段階的に置換し、セルフホストへ近づける。
- rt/sys層Box ABI・所有・weak・最小アロケータ、`ny_host_*`)を活用して堅牢性と性能の両立を図る。
前提
- Phase 10.2: Host API層C-ABI `ny_host_*` / WASM `nyir_host`
- Phase 10.3: 層の切り分けcorelang/rt/sys/std
- Phase 10.4: Box ABIfat ptrとEffect→LLVM属性の方向性
範囲MVP
- String
- 構造: { ptr: *u8, len: usize, cap: usize }
- API: new, from_raw, into_raw, clone, len, is_empty, push_str, substr(view), to_utf8(view)
- メモリ: `ny_host_alloc/realloc/free` 経由、UTF-8不変validation optional
- Array<T>
- 構造: { ptr: *T, len: usize, cap: usize }
- API: new, push, pop, get(i), set(i,v), len, reserve
- メモリ: `ny_host_*` 経由、要素のfiniハンドリングBox所有規則順守
- Map<K,V>
- 構造: ハッシュテーブル(オープンアドレス or チェイン; v0は単純で可
- API: new, get, set, remove, len, keys(view), values(view)
- メモリ: `ny_host_*` 経由、キー/値の所有/weak規則順守
設計ポリシー
- 所有とfini: 再代入・スコープ終端でfiniが適切に発火することEverything is Box準拠
- 互換: 現行言語表面の挙動に合わせる(差異は仕様に明記)
- 効果: mut操作の順序保持、view系はpure読み取り
- WASM/LLVM: ABI/ExternCallと矛盾しないStringの(ptr,len)は共通)
タスクCopilot TODO
1) stdレイアウトの骨子作成ファイル/モジュール構成)
2) String v0実装 + 単体テストpush_str/len/substr
3) Array v0実装 + 単体テストpush/get/set/len
4) Map v0簡易hash+ 単体テストset/get/remove/len
5) 再代入/スコープ終端でのfini挙動の統合テスト
6) ベンチ: 既存Rust実装対比の大まかな目安悪化しない/許容範囲)
7) フェールセーフ: OOM/境界エラーの明確化panic/Resultは設計に従う
8) ドキュメント: stdのMVP API一覧と互換要件
受け入れ基準
- 代表サンプルがRust実装なしでString/Array/Mapを利用し動作
- 再代入・スコープ終端時にfiniが期待通り発火ログで可視化
- WASM/LLVMの文字列(ptr,len)取り扱いと整合print等のExternCallで可視化
リスク・軽減
- パフォーマンス劣化: ベンチで目視確認、ホットパス最適化は後続で実施
- メモリ安全: 所有/weak/効果規則をVerifierで補助後続でLSP/静的解析を強化)
- 実装負債: MVP範囲を明確にし、機能追加はIssue分割
参考
- ABIドラフト: docs/予定/native-plan/box_ffi_abi.md
- NyIR: docs/nyir/spec.md
- Host API: Phase 10.2 仕様
最終更新: 2025-08-14

View File

@ -0,0 +1,98 @@
# Phase 10: LLVM Backend SkeletonMIR→LLVM IR AOT 最小実装)
目的
- MIRからLLVM IRへの直接変換と、最小AOTパイプラインを構築するための実装ガイドCopilot向けタスクリスト
- Phase 9.7ABI/BIDExternCallを前提に、外部呼び出しの取り扱いも含めて安全に前進。
前提
- MIR Tier-0/1Const/BinOp/Compare/Branch/Jump/Phi/Call/Return ほか基本)が利用可能。
- ExternCall命令Phase 9.7導入予定。ABIは`docs/予定/native-plan/box_ffi_abi.md`に準拠。
アウトカム(受け入れ基準)
- CLI: `nyash --backend llvm --emit obj app.nyash -o app.o` が成功し、`clang app.o -o app` で実行可能。
- 代表サンプルで `main``i32` を返却0=成功)。
- `ExternCall(env.console.log)``printf` 等へ写像し、標準出力へ表示できる(文字列は (i8*, i32))。
- 単純な四則演算・比較・分岐・ループが LLVM AOT で動作。
実装ステップ
1) モジュール構成の追加src/backend/llvm
- `src/backend/llvm/mod.rs`
- `src/backend/llvm/lower.rs`MIR→LLVM IR 変換)
- `src/backend/llvm/passes.rs`最小パス設定DCE/インラインは未使用でOK
- `src/backend/llvm/build.rs`(オブジェクト生成/ターゲット設定)
2) 依存設定
- Cargo.toml に `llvm-sys` を feature で追加(例: `feature = ["llvm-backend"]`)。
- ビルド要件を `README` に明記llvm-config が必要、Linux優先
3) エントリポイント
- `LLVMBackend { context, module, builder }` 構造体を定義。
- `compile_mir(&MirModule) -> Result<Vec<u8>, String>` を公開:
- `lower_mir_to_llvm` でIR生成
- `apply_minimal_passes`(任意・後回し可)
- `emit_object()``.o` を返す
4) 関数シグネチャとmain
- MIRの `main``i32 ()` で宣言戻り値がvoidなら 0 を返す)。
- 将来の引数は未対応でOKv0
5) 値と型の写像v0
- i32/i64/f32/f64/bool → それぞれのLLVMプリミティブ型。
- 文字列: (i8*, i32) のペアで扱うABIドラフトに一致
- Box参照: 当面 `i32``i8*` のopaqueに固定v0ではBox操作は行わない
6) 命令の下ろし
- Const: `i32.const` 等を `LLVMConstInt/LLVMConstReal` に対応。
- BinOp: add/sub/mul/div符号付きを対応。
- Compare: eq/ne/lt/le/gt/gei32想定
- Branch: 条件分岐と無条件分岐。
- Phi: ブロックごとに `LLVMPhiNode` を作成。
- Return: 値あり/なしに対応(なしは `i32 0`)。
- Call: 内部関数呼び出し同Module内
- ExternCall: 後述のマッピングに従う。
7) ExternCall の LLVM 写像v0
- Console: `env.console.log(ptr,len)``declare i32 @printf(i8*, ...)`
- 呼び出し時に `%fmt = getelementptr ([3 x i8], [3 x i8]* @"%.*s", i32 0, i32 0)` などの定数フォーマット文字列を準備
- `printf("%.*s", len, ptr)` で出力lenは`i32`、ptrは`i8*`)。
- Canvas: ネイティブ環境では利用不可 → v0は `noop` または `printf`でログに落とす(パラメータの表示)。
- 名前解決: BIDのFQNenv.console.log 等)→ 内部ディスパッチswitch/テーブル)で `printf` 等へ。
8) 文字列定数
- データレイアウトに `@.str = private unnamed_addr constant [N x i8] c"...\00"` を生成し、`getelementptr``i8*` を取得。
- ただし v0 のNyash→MIRでは「定数文字列を printf に渡す」パスだけ実装すれば良い。
- StringBoxの具象表現は当面不要WASMで進行中。LLVM側は (i8*, i32) で十分。
9) オブジェクト出力
- `LLVMTargetInitializeAllTargets()` 等でターゲット初期化。
- `TargetMachine` を作成し、`LLVMTargetMachineEmitToMemoryBuffer``.o` バッファ取得。
- CLIから `.o` をファイル出力。リンクはユーザー側で `clang app.o -o app`
10) ビルドフラグ/CLI
- `--backend llvm` / `--emit obj` を追加。
- featureが無い/LLVMが無い場合は明確なエラーメッセージ。
11) テスト(最小)
- 算術: `return 40+2;``42`
- 分岐: `if (x<y) return 1 else return 0`
- ループ: 累積加算で既知の値。
- ExternCall(console.log): 固定文字列/動的整数を出力(`printf("value=%d\n", v)` など)。
12) 将来拡張フック
- Passes: DCE/InstCombine/Inlining/LTO/PGOの導入ポイントを `passes.rs` に下書き。
- Box最適化: エスケープ解析→Stack化後続Phase
- ABI: ExternCallの宣言生成をBIDから自動化Phase 10後半〜
リスクと回避
- LLVMビルド依存: ドキュメント整備llvm-config 必須、CIにキャッシュ導入。
- 文字列/外部呼び出し差: v0はprintf固定。Canvas等はログに退避。
- OS差: v0はLinux/clang優先、他環境は後続。
参考
- ABIドラフト: `docs/予定/native-plan/box_ffi_abi.md`
- Phase 9.7: `docs/予定/native-plan/issues/phase_9_7_box_ffi_abi_and_externcall.md`
- LLVM LangRef: https://llvm.org/docs/LangRef.html
- llvm-sys: https://crates.io/crates/llvm-sys
最終更新: 2025-08-14

View File

@ -0,0 +1,335 @@
# Phase 8.4: AST→MIR Lowering完全実装
## 🎯 Issue概要
**現在の最重要課題**: Phase 8.3のBox操作WASMが実際にテストできない
**根本原因**: AST→MIR Loweringが不完全で、基本的なオブジェクト指向機能が使用不可
**影響範囲**:
- ユーザー定義Boxが定義・使用できない
- Phase 8.3のRefNew/RefGet/RefSet WASMが実際にテストできない
- Everything is Box哲学の基盤部分が欠如
## 🚨 現在の具体的問題
### 1. ユーザー定義Box定義不可
```nyash
box DataBox {
init { value }
}
```
**エラー**: `BoxDeclaration support is currently limited to static box Main`
### 2. オブジェクト生成不可
```nyash
local obj = new DataBox(42)
```
**エラー**: `Unsupported AST node type: New`
### 3. フィールドアクセス不可
```nyash
obj.value
me.field = 10
```
**エラー**: `Unsupported AST node type: Me`
### 4. デリゲーション構文不完全
```nyash
from Parent.method()
override method() { ... }
```
**エラー**: 未対応
## 📋 実装が必要な機能
### Priority 1: 基本オブジェクト操作
- [ ] **BoxDeclaration**: ユーザー定義Box定義
- [ ] **New expression**: `new DataBox(args)` オブジェクト生成
- [ ] **Field access**: `obj.field` フィールド読み取り
- [ ] **Field assignment**: `obj.field = value` フィールド書き込み
- [ ] **Me expression**: `me.field` 自己参照
### Priority 2: デリゲーション・継承
- [ ] **From expression**: `from Parent.method()` デリゲーション呼び出し
- [ ] **Override declaration**: `override method() { ... }` メソッドオーバーライド
- [ ] **Method calls**: `obj.method(args)` メソッド呼び出し
### Priority 3: 高度な機能
- [ ] **Constructor calls**: `pack()`, `init()` コンストラクタ
- [ ] **Static methods**: `Class.method()` 静的メソッド呼び出し
## 🔧 実装場所・方法
### メインファイル: `src/mir/builder.rs`
#### 1. `build_expression()` メソッド拡張 (行103-)
**現在の対応**: Literal, BinaryOp, UnaryOp, AwaitExpression のみ
**追加が必要**:
```rust
// Line 215付近の _ => Err(...) の前に追加
ASTNode::New { class, arguments, .. } => {
self.build_new_expression(class, arguments)
},
ASTNode::Me { span } => {
// 現在のインスタンスへの参照を返す
self.build_me_expression()
},
ASTNode::FieldAccess { object, field, .. } => {
self.build_field_access(*object, field)
},
ASTNode::MethodCall { object, method, arguments, .. } => {
self.build_method_call(*object, method, arguments)
},
ASTNode::From { parent, method, arguments, .. } => {
self.build_from_expression(parent, method, arguments)
},
```
#### 2. `build_statement()` メソッド拡張
**BoxDeclaration制限解除**:
```rust
// Line 190付近の条件を拡張
ASTNode::BoxDeclaration { name, methods, is_static, fields, .. } => {
if *is_static && name == "Main" {
// 既存のstatic box Main処理
} else {
// 新規ユーザー定義Box処理
self.build_box_declaration(name.clone(), methods.clone(), fields.clone())
}
}
```
#### 3. 新規メソッド実装が必要
```rust
impl MirBuilder {
fn build_new_expression(&mut self, class: String, arguments: Vec<ASTNode>) -> Result<ValueId, String> {
// RefNew MIR命令生成
// Phase 8.3のWASM Box操作と連携
}
fn build_field_access(&mut self, object: ASTNode, field: String) -> Result<ValueId, String> {
// RefGet MIR命令生成
}
fn build_field_assignment(&mut self, object: ASTNode, field: String, value: ASTNode) -> Result<ValueId, String> {
// RefSet MIR命令生成
}
fn build_me_expression(&mut self) -> Result<ValueId, String> {
// 現在のインスタンスへの参照
}
fn build_box_declaration(&mut self, name: String, methods: Vec<ASTNode>, fields: Vec<String>) -> Result<(), String> {
// ユーザー定義Box登録
}
}
```
## 🧪 テストケースCopilot実装必須
### Test 1: 基本Box定義・生成
**ファイル**: `test_user_defined_box.nyash`
```nyash
box DataBox {
init { value }
pack(v) {
me.value = v
}
}
static box Main {
main() {
local obj = new DataBox(42)
return obj.value
}
}
```
**期待MIR出力例**:
```mir
define void @main() {
bb0:
0: safepoint
1: %0 = const 42
2: %1 = ref_new "DataBox", %0
3: %2 = ref_get %1, "value"
4: ret %2
}
```
**実行期待結果**: `42`
### Test 2: フィールドアクセス・代入
**ファイル**: `test_field_operations.nyash`
```nyash
box Counter {
init { count }
pack() {
me.count = 0
}
increment() {
me.count = me.count + 1
return me.count
}
}
static box Main {
main() {
local c = new Counter()
return c.increment()
}
}
```
**期待結果**: `1`
### Test 3: デリゲーション基本
**ファイル**: `test_delegation_basic.nyash`
```nyash
box Parent {
init { name }
pack(n) {
me.name = n
}
greet() {
return "Hello " + me.name
}
}
box Child from Parent {
init { age }
pack(n, a) {
from Parent.pack(n)
me.age = a
}
override greet() {
local base = from Parent.greet()
return base + " (age " + me.age + ")"
}
}
static box Main {
main() {
local c = new Child("Alice", 25)
return c.greet()
}
}
```
**期待結果**: `"Hello Alice (age 25)"`
### Test 4: WASM Box操作統合テスト
**ファイル**: `test_wasm_box_integration.nyash`
```nyash
box SimpleData {
init { x, y }
pack(a, b) {
me.x = a
me.y = b
}
sum() {
return me.x + me.y
}
}
static box Main {
main() {
local data = new SimpleData(10, 20)
return data.sum()
}
}
```
**テスト方法**:
```bash
# MIR生成テスト
./target/release/nyash --dump-mir test_wasm_box_integration.nyash
# WASM生成テスト
./target/release/nyash --compile-wasm test_wasm_box_integration.nyash
# WASM実行テストwasmtime
./target/release/nyash --compile-wasm test_wasm_box_integration.nyash > test.wat
sed -n '4,$p' test.wat > clean_test.wat
$HOME/.wasmtime/bin/wasmtime run clean_test.wat --invoke main
```
**期待結果**: 全プロセスでエラーなし、最終結果 `30`
## ✅ 成功基準
### 必須基準
- [ ] 上記4つのテストケースがすべて成功
- [ ] `cargo build --release` でエラーなし
- [ ] 既存のstatic box Main機能が破損していない
- [ ] Phase 8.3のWASM Box操作が実際に動作確認
### 理想基準
- [ ] MIR→WASM→wasmtime実行の完全パイプライン動作
- [ ] ベンチマーク性能が劣化していない
- [ ] 複雑なデリゲーション・継承チェーンが動作
## 🤖 Copilot向け実装ガイド
### 実装順序推奨
1. **Phase 1**: `build_new_expression()` - オブジェクト生成
2. **Phase 2**: `build_field_access()` - フィールド読み取り
3. **Phase 3**: Field assignment - フィールド書き込み
4. **Phase 4**: `build_me_expression()` - 自己参照
5. **Phase 5**: `build_box_declaration()` - Box定義
6. **Phase 6**: デリゲーション構文
### 既存コードとの統合注意点
- **MIR命令**: 既存のRefNew/RefGet/RefSet MIR命令を活用
- **型システム**: 既存のValueId/BasicBlockId体系を維持
- **エラーハンドリング**: 既存のResult<ValueId, String>パターンを踏襲
### デバッグ支援
```bash
# MIR生成確認
./target/release/nyash --dump-mir --mir-verbose test_file.nyash
# パーサー確認
./target/release/nyash --debug-fuel unlimited test_file.nyash
```
## 📊 期待される効果
### 技術的効果
- Phase 8.3のBox操作WASMが実際に使用可能
- Everything is Box哲学の実用レベル実現
- 真のオブジェクト指向プログラミング対応
### 開発効率向上
- Nyashプログラムの実用性大幅向上
- 実際のアプリケーション開発が可能
- ベンチマーク・テストの精度向上
## 🔗 関連リンク
- **Phase 8.3実装**: RefNew/RefGet/RefSet WASM対応
- **MIR設計**: `docs/説明書/reference/mir-reference.md`
- **AST定義**: `src/ast.rs`
- **既存MIR実装**: `src/mir/instruction.rs`
---
**優先度**: Critical
**担当**: Copilot + Claude協調実装
**最終目標**: test_wasm_box_integration.nyash が完全動作

View File

@ -0,0 +1,160 @@
# Phase 8.5: MIRセマンティック階層化AI大会議決定版
## 🎯 Issue概要
**方針転換**: ChatGPT5推奨の「20命令intrinsic戦略」から、**Gemini+Codex両先生一致推奨の「25命令セマンティック階層化」**に変更
**理由**: AI大会議による深い分析の結果、20命令intrinsic戦略は以下の致命的問題が判明
- JIT/AOT最適化機会の喪失
- Everything is Box哲学の意味情報消失
- 長期的な実装・保守コスト増大
- パフォーマンス劣化リスク
## 🧠 AI大会議分析結果
### Gemini先生分析理論面
- **「賢いコンパイラは、賢いMIRから生まれる」**
- RefNew/WeakLoadのintrinsic化 = 最適化阻害の悪手
- BoxFieldLoad/Store等でEverything is Box明示化
- セマンティック階層化で意味保持
### Codex先生分析実装面
- **二相ロワリング戦略**: 25命令維持パス + 20+intrinsic降格パス
- 実装コスト: 5命令追加で10-20人日intrinsic戦略より安い
- マイクロベンチ実測でintrinsicオーバーヘッド検証
- 段階的移行35→25で安全な実装
## 📋 決定版: セマンティック階層化MIR25命令
### **Tier-0: 普遍的コア8命令**
```mir
Const, BinOp, Compare, Branch, Jump, Return, Phi, Call
```
- どんな言語にも共通する基本命令群
- 全バックエンドで必須サポート
### **Tier-1: Nyashセマンティクス12命令**
```mir
NewBox, BoxFieldLoad, BoxFieldStore, BoxCall, Safepoint,
RefGet, RefSet, WeakNew, WeakLoad, Send, Recv,
TypeTest, WeakUpgrade
```
- **Everything is Box哲学の具現化**
- **最適化に不可欠**: JIT/AOTでのエスケープ解析・RC除去の基盤
- **BoxFieldLoad/Store**: `obj.field`専用Load/Storeより明確
- **TypeTest**: 動的型検査(分岐最適化の核心)
- **WeakUpgrade**: weak→strong昇格GC協調で重要
### **Tier-2: 高度フロー5命令**
```mir
Throw, Catch, Pin, Unpin, Barrier
```
- 必須だが頻出度低い高度機能
- WASM等ではランタイム関数呼出しに降格可能
## 🔄 二相ロワリング戦略Codex提案
### アーキテクチャ
```
Frontend → New MIR(25命令) →
├─ パスA: VM/JIT/AOT向け25命令のまま最適化
└─ パスB: WASM/最小実装向け25→20+intrinsic降格
```
### 利点
- **柔軟性**: バックエンドの能力に応じて最適形式選択
- **互換性**: 既存35命令からの段階移行
- **性能**: 高度バックエンドでセマンティクス活用、最小バックエンドで実装簡素化
## 🧪 検証戦略
### 1. パフォーマンス実測Codex設計
**マイクロベンチ3カテゴリ:**
- BoxFieldLoad/Store連鎖構造体/配列/辞書)
- WeakLoad/Upgrade頻発GCセーフポイント
- Send/Recvホットループ多待ち
**比較軸:**
- 35現行 vs 25セマンティクス vs 20+intrinsic
- Interpreter/VM/WASM全バックエンド
- 命令数/ランタイムcall回数/最適化効果
### 2. 実装検証
**段階的移行4フェーズ:**
1. 仕様固定・ロワリング設計
2. 二相ロワリング導入互換Shim
3. バックエンド増分対応
4. 旧命令縮退・削除
### 3. 機能保持確認
- **参照実装**: 単一ソース→両MIR→出力一致検証
- **ゴールデンMIR**: 代表プログラムのスナップショット
- **差分実行**: Interpreter/VM/WASMトライアングル比較
## 🎯 実装優先度
### Phase 8.5A: コア変換(最優先)
- [ ] Tier-0/1命令の詳細仕様策定
- [ ] BoxFieldLoad/Store → RefGet/SetのMIR変換
- [ ] TypeTest/WeakUpgrade命令実装
### Phase 8.5B: 二相ロワリング
- [ ] 25命令維持パス実装
- [ ] 20+intrinsic降格パス実装
- [ ] バックエンド選択ロジック
### Phase 8.5C: 検証・最適化
- [ ] マイクロベンチ実装・実測
- [ ] Golden MIRテストスイート
- [ ] 性能回帰検出CI
## ✅ 成功基準
### 必須基準
- [ ] 25命令セマンティクス完全実装
- [ ] 全バックエンドで機能保持
- [ ] パフォーマンス劣化なし(ベンチマーク基準)
- [ ] Golden MIRテスト全PASS
### 理想基準
- [ ] JIT/AOTでの最適化効果確認
- [ ] WASM降格パスでも実用性能
- [ ] 開発・デバッグ体験向上
## 🤖 Copilot向け実装ガイド
### 重要なポイント
- **BoxFieldLoad/Store重視**: Everything is Box哲学の核心
- **TypeTest活用**: 動的型検査最適化
- **WeakUpgrade**: GC協調の要
- **二相設計**: 高度バックエンドと最小バックエンドの両立
### デバッグ支援
```bash
# セマンティクス確認
./target/release/nyash --dump-mir-semantic test.nyash
# 降格パス確認
./target/release/nyash --dump-mir-lowered test.nyash
# 性能比較
./target/release/nyash --benchmark-mir-passes test.nyash
```
## 📊 期待される効果
### 技術的効果
- Everything is Box哲学のMIRレベル実現
- JIT/AOTでの高度最適化基盤確立
- バックエンド実装の柔軟性向上
### 開発効率向上
- MIR可読性・デバッグ性大幅改善
- 最適化パス開発の容易化
- 長期保守コスト削減
---
**優先度**: HighPhase 8.4完了後)
**担当**: Copilot + Claude協調実装
**AI大会議結論**: Gemini+Codex両先生完全一致推奨

View File

@ -0,0 +1,438 @@
# Phase 8.6: VM性能改善実装緊急修正
## 🚨 Issue概要
**緊急課題**: VMがインタープリターより性能劣化0.9倍)している根本問題の解決
**発見経緯**: Phase 8.4完成時のベンチマーク測定で発覚
- **VM実行**: 119.80ms(期待より遅い)
- **Interpreter**: 110.10ms(ベースライン)
- **性能比**: 0.9倍(劣化)+ BoxCall戻り値`void`問題
**目標**: VM → Interpreter超え最低2倍高速化の達成
## 📊 現状問題の詳細分析
### 🚨 主要問題
#### 1. VM性能劣化0.9倍問題)
```
期待: VM > InterpreterMIR最適化効果
実態: VM < Interpreter性能劣化
差異: 119.80ms vs 110.10ms = +9.70ms劣化
```
#### 2. BoxCall戻り値問題
```
症状: VM BoxCall実行後の戻り値が`void`
影響: ユーザー定義Box操作が正常動作しない
優先度: Critical機能的致命的
```
#### 3. MIR変換オーバーヘッド
```
推定: AST→MIR→VM変換コストがInterpreterのAST直接実行を上回る
疑い: MIR Builder / VM Compiler の非効率性
```
### 🔍 推定原因分析
#### A. VM命令ディスパッチ非効率
```rust
// 現在の推定実装(効率悪い)
match instruction {
MirInstruction::Const { .. } => { /* 処理 */ },
MirInstruction::BinOp { .. } => { /* 処理 */ },
// ... 毎回match分岐でオーバーヘッド
}
```
#### B. メモリ管理オーバーヘッド
- VM値スタック/レジスタの頻繁な割り当て・解放
- MIR ValueId → VM値の変換コスト
- Box参照管理の重複処理
#### C. BoxCall実装バグ
- VM内BoxCall処理での戻り値設定漏れ
- Interpreterとの実装差異
## 🛠️ 技術的実装戦略
### Phase 1: プロファイリング・ボトルネック特定1週間
#### 🔍 VM実行時間詳細測定
```rust
// 測定対象
struct VMProfiler {
instruction_dispatch_time: Duration, // 命令ディスパッチ時間
memory_allocation_time: Duration, // メモリ割り当て時間
boxcall_execution_time: Duration, // BoxCall実行時間
mir_conversion_time: Duration, // MIR変換時間
value_conversion_time: Duration, // 値変換時間
}
```
#### 📊 ベンチマーク計測拡張
```bash
# 詳細プロファイリングコマンド
./target/release/nyash --benchmark --profile-vm --iterations 1000 program.nyash
# 出力例
VM Performance Profile:
- Instruction Dispatch: 45.2ms (37.8%)
- Memory Management: 32.1ms (26.8%)
- BoxCall Operations: 28.7ms (24.0%)
- MIR Conversion: 13.9ms (11.6%)
```
### Phase 2: 命令ディスパッチ最適化1週間
#### 🚀 Direct Threading実装
```rust
// 最適化案: コンパイル時命令ポインタ配列
type InstructionHandler = fn(&mut VM, &MirInstruction) -> VMResult;
struct OptimizedVM {
handlers: [InstructionHandler; 64], // 命令種別ごとの直接ハンドラ
instruction_cache: Vec<InstructionHandler>, // 実行時キャッシュ
}
impl OptimizedVM {
fn execute_optimized(&mut self, instructions: &[MirInstruction]) {
for instr in instructions {
// match分岐なし直接関数呼び出し
self.handlers[instr.opcode()](self, instr);
}
}
}
```
#### ⚡ Register-based VM検討
```rust
// スタックマシン → レジスタマシン移行案
struct RegisterVM {
registers: [VMValue; 256], // 固定レジスタファイル
register_allocator: BitSet, // レジスタ割り当て管理
}
// 利点: push/pop オーバーヘッド削減
// 欠点: レジスタ割り当て複雑化
```
### Phase 3: BoxCall実装修正3日
#### 🔧 BoxCall戻り値修正
```rust
// 現在の問題を修正
impl VM {
fn execute_boxcall(&mut self, dst: Option<ValueId>, box_val: ValueId,
method: &str, args: &[ValueId]) -> VMResult {
let result = self.call_box_method(box_val, method, args)?;
// 🚨 修正必要:戻り値設定
if let Some(dst_id) = dst {
self.set_value(dst_id, result); // ←これが漏れている疑い
}
Ok(())
}
}
```
#### ✅ Interpreter整合性確保
```rust
// Interpreterと同一の戻り値処理を実装
```
### Phase 4: メモリ最適化1週間
#### 🏊 メモリプール導入
```rust
struct VMMemoryPool {
value_pool: Pool<VMValue>, // VM値の使い回し
instruction_pool: Pool<VMInstruction>, // 命令オブジェクト使い回し
small_alloc_pool: SmallAllocator, // 小さなアロケーション専用
}
```
#### 📦 Zero-Copy最適化
```rust
// MIR ValueId → VM値の変換最小化
struct ZeroCopyVM {
mir_values: &[MirValue], // MIR値への直接参照
vm_values: SparseVec<VMValue>, // スパース配列でメモリ効率化
}
```
## 🎯 成功基準・測定指標
### 必須達成基準
- [ ] **VM > Interpreter**: 最低2倍高速化110ms → 55ms以下
- [ ] **BoxCall正常化**: 戻り値が正しく返される
- [ ] **メモリ使用量**: VM実行時メモリ使用量 < Interpreter50%目標
### 追加目標
- [ ] **MIR変換高速化**: ASTMIR変換時間 < 5ms
- [ ] **スケーラビリティ**: 大規模プログラムで線形性能維持
- [ ] **実行安定性**: 1000回連続実行でメモリリークなし
### 品質指標
- [ ] **機能互換性**: 全てのNyash機能がVMInterpreterで同一動作
- [ ] **デバッグ性**: プロファイリング情報出力機能
- [ ] **後方互換性**: 既存のMIRコードが無修正で高速動作
## 🧪 専用テストケース作成
### VM性能測定テスト
各テストをInterpreter/VM/WASMで比較実行し性能プロファイル収集
#### test_vm_performance_basic.nyash
```nyash
// 基本演算性能テストCPU集約
static box VMPerfTest {
main() {
me.console = new ConsoleBox()
// 1. 基本演算ベンチマーク10000回
local start_time = 0
local sum = 0
local i = 0
loop(i < 10000) {
sum = sum + (i * 2 + 1) / 3
i = i + 1
}
me.console.log("基本演算完了: " + sum)
// 2. Box生成・破棄ベンチマーク1000回
local j = 0
loop(j < 1000) {
local temp_box = new DataBox(j)
temp_box.process()
j = j + 1
}
me.console.log("Box操作完了")
}
}
box DataBox {
init { value }
pack(initial_value) {
me.value = initial_value
}
process() {
me.value = me.value * 2 + 1
return me.value
}
}
```
#### test_vm_boxcall_return.nyash
```nyash
// BoxCall戻り値問題専用テスト
static box BoxCallTest {
main() {
me.console = new ConsoleBox()
// 1. 基本BoxCall戻り値テスト
local calculator = new Calculator()
local result1 = calculator.add(10, 20)
me.console.log("加算結果: " + result1) // 期待値: 30
// 2. チェーンBoxCall戻り値テスト
local result2 = calculator.multiply(result1, 2)
me.console.log("乗算結果: " + result2) // 期待値: 60
// 3. 複雑BoxCall戻り値テスト
local complex = new ComplexBox()
local result3 = complex.nested_calculation(5)
me.console.log("複雑計算結果: " + result3) // 期待値: 要計算
// 🚨 VMで void が返される場合はここで判明
if result1 == null {
me.console.log("🚨 ERROR: BoxCall returned void in VM!")
}
}
}
box Calculator {
add(a, b) {
return a + b
}
multiply(a, b) {
return a * b
}
}
box ComplexBox {
nested_calculation(input) {
local calc = new Calculator()
local step1 = calc.add(input, 10)
local step2 = calc.multiply(step1, 3)
return calc.add(step2, 7)
}
}
```
#### test_vm_memory_usage.nyash
```nyash
// メモリ使用量測定テスト
static box MemoryTest {
main() {
me.console = new ConsoleBox()
me.debug = new DebugBox()
// メモリ測定開始
me.debug.startMemoryTracking()
// 1. 大量Box生成テストメモリプール効果測定
local boxes = new ArrayBox()
local i = 0
loop(i < 5000) {
local data = new LargeDataBox(i)
boxes.push(data)
i = i + 1
}
me.console.log("大量Box生成完了: " + boxes.size())
// 2. 参照操作テスト(参照管理オーバーヘッド測定)
local j = 0
loop(j < 1000) {
local item = boxes.get(j % boxes.size())
item.update_data()
j = j + 1
}
// メモリ使用量レポート
me.console.log(me.debug.memoryReport())
me.debug.stopMemoryTracking()
}
}
box LargeDataBox {
init { id, data1, data2, data3, data4, data5 }
pack(identifier) {
me.id = identifier
me.data1 = "Large data string " + identifier
me.data2 = identifier * 1000
me.data3 = new ArrayBox()
me.data4 = identifier + 0.5
me.data5 = identifier % 2 == 0
}
update_data() {
me.data2 = me.data2 + 1
me.data3.push(me.data2)
return me.data2
}
}
```
#### test_vm_instruction_dispatch.nyash
```nyash
// 命令ディスパッチ性能特化テスト
static box DispatchTest {
main() {
me.console = new ConsoleBox()
// 1. 大量の異なる命令種別実行(ディスパッチオーバーヘッド測定)
local result = 0
local i = 0
loop(i < 50000) {
// 様々な命令を組み合わせ
local a = i % 10 // Const, BinOp
local b = (i + 1) % 10 // Const, BinOp
local c = a + b // BinOp
local d = c * 2 // BinOp
local e = d > 15 // Compare
if e { // Branch
result = result + d // BinOp
} else {
result = result - d // BinOp
}
// BoxCall挿入
local box_result = me.simple_calc(a, b) // BoxCall
result = result + box_result
i = i + 1
}
me.console.log("ディスパッチテスト完了: " + result)
}
simple_calc(x, y) {
return (x + y) * 2
}
}
```
## 🔧 実装支援スクリプト
### ベンチマーク実行スクリプト
```bash
#!/bin/bash
# benchmark_vm_performance.sh
echo "🚀 Phase 8.6 VM性能改善テスト実行"
# 各テストを3バックエンドで実行
TESTS=(
"test_vm_performance_basic"
"test_vm_boxcall_return"
"test_vm_memory_usage"
"test_vm_instruction_dispatch"
)
for test in "${TESTS[@]}"; do
echo "📊 $test.nyash テスト実行中..."
echo " - Interpreter実行..."
time ./target/release/nyash --backend interpreter "tests/vm_performance/$test.nyash"
echo " - VM実行..."
time ./target/release/nyash --backend vm "tests/vm_performance/$test.nyash"
echo " - WASM実行..."
time ./target/release/nyash --backend wasm "tests/vm_performance/$test.nyash"
echo ""
done
echo "✅ 全テスト完了"
```
## 🏆 期待される成果
### 短期成果2週間
- [ ] **VM性能2倍達成**: 119.80ms 55ms以下
- [ ] **BoxCall問題解決**: 戻り値正常動作
- [ ] **プロファイリング環境**: 詳細性能測定機能
### 中期成果1ヶ月
- [ ] **最適化基盤確立**: Phase 9 JIT準備完了
- [ ] **メモリ効率向上**: 実行時メモリ使用量50%削減
- [ ] **開発効率向上**: デバッグプロファイリング環境
### 長期インパクト
- [ ] **JIT開発加速**: 最適化されたVM JIT移行が容易
- [ ] **実用性向上**: VM実行で実用的なアプリケーション開発可能
- [ ] **競争力確立**: 他言語VM実装との性能競争力
---
**作成**: 2025-08-14
**優先度**: 🚨 Critical次期最優先
**期間**: 2週間
**担当**: Copilot + Claude協調
この問題解決によりNyash言語のVM実行性能が飛躍的に向上しPhase 9 JIT実装への道筋が確立されます 🚀

View File

@ -0,0 +1,300 @@
# Phase 8.7: Real-world Memory Management Testing + VM BoxCall修正統合版
## 🎯 Issue概要
**主目的**: 実用アプリケーション開発によるNyashメモリ管理システムの実証テスト
**統合目的**: VM BoxCall戻り値問題の修正を実用アプリ実装と同時に実施
**戦略的背景**:
- Phase 8.4完了でAST→MIR Lowering完成
- Phase 8.5完了でMIR 25命令階層化完成
- **発見された課題**: VM BoxCall実行後の戻り値が`void`になる問題
- **合理的統合**: kilo実装とBoxCall修正を同時実施で効率最大化
**統合効果**:
```
kilo実装 = ユーザー定義Box + メソッド呼び出し重用
BoxCall正常動作 = kilo正常動作の前提条件
統合実装 = 一石二鳥の効率性
```
## 🎯 Phase 8.7A: kiloテキストエディタ
### 技術的特徴
- **サイズ**: <1k LOC超小型
- **メモリパターン**: Editor -> (Rows -> Syntax) 木構造+相互参照
- **fini戦略**: Editor削除でRows自動解放、逆参照をweak化
- **BoxCall実証**: ユーザー定義Boxメソッド呼び出しでVM戻り値正常化確認
- **統合検証**: メモリ管理 + VM BoxCall動作の同時実証
### 実装仕様
#### 基本構造
```nyash
box Editor {
init { rows, current_row, screen_rows, filename }
pack() {
me.rows = new ArrayBox()
me.current_row = 0
me.screen_rows = 24
me.filename = ""
}
fini() {
// ArrayBox自動解放でRows全解放
// weak参照は自動null化される
}
}
box Row {
init { text, size, editor } // editor: weak参照
pack(text_content, parent_editor) {
me.text = text_content
me.size = text_content.length()
me.editor = weak parent_editor // 循環参照回避
}
render() {
if me.editor == null {
return "ERROR: Editor already freed"
}
return me.text
}
}
box EditorState {
init { cursor_x, cursor_y, editor } // editor: weak参照
pack(editor_ref) {
me.cursor_x = 0
me.cursor_y = 0
me.editor = weak editor_ref
}
}
```
#### メイン処理
```nyash
static box Main {
main() {
local editor = new Editor()
// ファイル読み込み
editor.loadFile("test.txt")
// 編集操作
editor.insertLine(0, "Hello Nyash Editor!")
editor.insertLine(1, "This tests memory management")
// 状態作成
local state = new EditorState(editor)
// editor削除 → Rows自動解放、state.editorは自動null化
editor.fini()
// weak参照確認
if state.editor == null {
print("✅ Editor properly freed, weak ref nullified")
return 1
} else {
print("❌ Memory leak detected!")
return 0
}
}
}
```
### 🧪 検証テストケース
#### Test 1: 基本メモリ管理
```nyash
// test_kilo_basic_memory.nyash
box Editor {
init { rows }
pack() { me.rows = new ArrayBox() }
fini() { print("Editor freed") }
}
box Row {
init { editor }
pack(ed) { me.editor = weak ed }
}
static box Main {
main() {
local editor = new Editor()
local row = new Row(editor)
// editor削除
editor.fini()
// weak参照確認
return row.editor == null ? 1 : 0
}
}
```
#### Test 2: 複雑な相互参照
```nyash
// test_kilo_circular_refs.nyash
box Editor {
init { rows, state }
pack() {
me.rows = new ArrayBox()
me.state = new EditorState(me) // 循環参照テスト
}
}
box EditorState {
init { editor }
pack(ed) { me.editor = weak ed }
}
static box Main {
main() {
local editor = new Editor()
editor.pack()
// 循環参照があっても正常解放されるか
editor.fini()
return 1 // メモリリークなしで完了すればOK
}
}
```
#### Test 3: 大量オブジェクト管理
```nyash
// test_kilo_mass_objects.nyash
static box Main {
main() {
local editor = new Editor()
// 大量行作成
loop(i < 1000) {
editor.addRow("Line " + i)
}
print("Created 1000 rows")
// 一括削除
editor.fini()
print("Editor freed with all rows")
return 1
}
}
```
### ✅ 成功基準(統合版)
#### 必須基準(メモリ管理)
- [ ] 全テストケースでメモリリークなし
- [ ] weak参照の自動null化動作確認
- [ ] fini()伝播の正確性確認
- [ ] 循環参照でも正常解放確認
#### 必須基準VM BoxCall修正
- [ ] VM BoxCall実行後の戻り値が正常に返される
- [ ] ユーザー定義Boxメソッド呼び出しがVMで正常動作
- [ ] Interpreter/VM/WASMで同一BoxCall動作
- [ ] kilo実装でBoxCallが期待通り動作
#### 理想基準
- [ ] 1000+オブジェクトでも高速動作
- [ ] WASM実行でもメモリ管理正常
- [ ] ベンチマーク性能劣化なし
- [ ] VM BoxCall性能がInterpreterと同等以上
## 🚀 Phase 9.5: tiny-web-server将来実装
### 技術的特徴
- **複雑度**: 中〜高
- **メモリパターン**: Server -> Clients -> Requests並行処理
- **I/O管理**: ソケット・ファイルハンドルの確実解放
### 基本設計
```nyash
box Server {
init { clients, port }
fini() {
// 全クライアント接続を確実切断
me.clients.forEach(client => client.fini())
}
}
box Client {
init { socket, server } // server: weak参照
fini() {
me.socket.close() // 確実なソケット解放
}
}
```
## 🤖 Copilot向け実装ガイド
### 実装順序(統合版)
1. **Phase 1**: VM BoxCall戻り値修正 + Editor/Row基本構造実装
2. **Phase 2**: weak参照・fini()システム統合 + BoxCall動作確認
3. **Phase 3**: テストケース実装・検証(メモリ管理 + BoxCall統合テスト
4. **Phase 4**: パフォーマンス最適化・3バックエンド互換性確認
### 重要注意点
- **weak参照構文**: `me.editor = weak editor_ref`
- **fini()自動呼び出し**: ガベージコレクション時
- **メモリリーク検出**: デバッグ出力で確認
- **WASM互換性**: ブラウザ環境でも動作
### デバッグ支援(統合版)
```bash
# メモリ使用量監視
./target/release/nyash --debug-memory test_kilo_basic.nyash
# weak参照追跡
./target/release/nyash --trace-weak test_kilo_circular.nyash
# fini呼び出し追跡
./target/release/nyash --trace-fini test_kilo_mass.nyash
# BoxCall戻り値デバッグ新規
./target/release/nyash --debug-boxcall test_kilo_basic.nyash
# VM/Interpreter/WASM BoxCall比較新規
./target/release/nyash --compare-boxcall test_kilo_basic.nyash
# 統合デバッグ(メモリ + BoxCall
./target/release/nyash --debug-all test_kilo_basic.nyash
```
## 📊 期待される効果(統合版)
### 技術的効果
- **メモリ管理実証**: Nyashメモリ管理システムの実用性実証
- **VM実行基盤確立**: BoxCall正常動作によるVM実用性確保
- **Everything is Box実証**: Box哲学の実用レベル確認
- **fini/weak参照実証**: システムの堅牢性確認
- **3バックエンド統一**: Interpreter/VM/WASMでの一貫動作
### 開発体験向上
- **実用アプリ開発実現**: kiloエディタによる実証
- **メモリ安全パターン**: プログラミングパターン確立
- **デバッグ環境整備**: 包括的デバッグ支援機能
- **移行容易性**: 他言語からの移行促進
- **Phase 9準備完了**: JIT実装への安全な基盤確立
---
**優先度**: 🚨 CriticalPhase 8.5完了直後の最優先)
**期間**: 2週間Phase 8.6統合により3日短縮
**担当**: Copilot + Claude協調実装
**統合目標**:
- ✅ メモリ安全な実用アプリケーション完成kilo
- ✅ VM BoxCall戻り値問題完全解決
- ✅ Phase 9 JIT実装への安全な基盤確立
**戦略的価値**: 効率性最大化(統合実装)+ 品質保証(実証テスト)+ Phase 9準備完了

View File

@ -0,0 +1,53 @@
# Phase 9.10: NyIR v1 仕様・フォーマット・検証器Copilot実装用タスク
目的What/Why
- NyashのMIRを公開IRNyIR v1として凍結し、あらゆるフロントエンド/バックエンドの共通契約にする。
- 仕様・テキスト/バイナリフォーマット・厳格検証器・ツール群を整備し、移植性と一貫性を保証する。
- 設計の正本は `docs/nyir/spec.md`CoreExtの骨子。本ファイルはCopilotが実装を進めるための具体タスク集。
スコープDeliverables
- 仕様書(骨子は既存): `docs/nyir/spec.md` に沿ったv1確定版の追補
- フォーマット: `.nyir`(テキスト), `.nybc`(バイナリ)
- 検証器: `nyir-verify`CLI/ライブラリ)
- 変換/実行ツール:
- `nyashel -S`Nyash→NyIRダンプ
- `nyir-run`NyIRインタプリタ
- 参考: `nyir-ll`NyIR→LLVM IR、Phase 10で拡張
- Golden NyIR: `golden/*.nyir`代表サンプルを固定、CIで全バックエンド一致を検証
実装タスクCopilot TODO
1) 仕様固定
- `docs/nyir/spec.md` に従い、25命令CoreEffectOwnershipWeakBusをv1として明文化。
- NyIR-Extexceptions/concurrency/atomicsの章は骨子のみ維持別Phase
2) `.nyir` パーサ/プリンタ(最小)
- 構造: moduleヘッダ / features / const pool / functionsblocks, instrs
- コメント/メタ/featureビットを許容v1最小でもOK
3) `.nybc` エンコーダ/デコーダ(最小)
- セクション: header / features / const pool / functions / metadata
- エンコード: LEB128等。識別子はstring table参照
4) `nyir-verify`(厳格検証器)
- 検査: 所有森/強循環/weak規則/効果整合/到達性/終端性/Phi入力整合
- 失敗時は明確なエラーを返し、ロード拒否
5) `nyashel -S` をNyIR出力対応に
- 既存MIRダンプ経路から移行。`.nyir`で出力
6) GoldenサンプルCI
- `golden/*.nyir` 作成3〜5本
- CIで interp/vm/wasm順次llvmに投げ、出力一致を確認
受け入れ基準Acceptance
- 代表サンプルが `.nyir` で表現・検証・実行可能(`nyir-run`
- `.nybc` 読み書き往復で等価
- CIでinterp/vm/wasmの結果一致最小ケース
非スコープOut of Scope
- NyIR-Ext の実装(例外/非同期/アトミックは別Phase9.12/9.13/9.14想定)
- 高度最適化/再配線は対象外(意味保存に限定)
参照References
- NyIR 骨子: `docs/nyir/spec.md`
- ABI/BIDドラフト: `docs/予定/native-plan/box_ffi_abi.md`
- 計画9.7以降フルテキスト): `docs/予定/native-plan/copilot_issues.txt`
メモ(運用)
- 仕様の正本は `docs/nyir/`。本Issueは実装タスクと受け入れ基準を明快に維持。
- Golden/Diffテストを並行で用意して、バックエンド横断の一貫性を早期に担保。

View File

@ -0,0 +1,36 @@
# Phase 9.12: Universal Frontends各言語→NyIR 落とし込み PoC
目的What/Why
- 「All Languages → NyIR」を実証するため、代表的な言語サブセットのフロントエンドPoCを作る。
- 最適化は脇に置き、意味保存とエッジケースの把握を最優先にする。
対象Initial set
- Cサブセット例外なし/CASあり
- JavaScript/TypeScriptサブセット辞書/例外/非同期の最小)
- Pythonサブセット辞書/例外/awaitの最小
- JVMサブセットbytecode 経由:例外/スレッド)
成果物Deliverables
- `lang2nyir-<lang>` ツールAST/IR→NyIR
- Golden NyIR各サンプルの `.nyir`
- 変換ガイド言語機能→NyIR/Ext/標準Box の対応表)
スコープScope
1) C-subset → NyIR
- if/loop/call/return、構造体の最小投影、CASAtomicExt
2) JS/TS-subset → NyIR
- 例外Try/Throw、Promise/awaitAwait近似、辞書/配列→標準Box
3) Python-subset → NyIR
- 例外・awaitの最小、辞書/リスト→標準Box
4) JVM-subset → NyIR
- 例外/スレッド/同期の最小投影Ext準拠
受け入れ基準Acceptance
- 各言語サンプルが NyIR に落ち、interp/vm/wasm/llvm のいずれかで実行可能
- Golden NyIR を用いた Diff 一致が取れる
参照References
- NyIR 仕様/Ext: `docs/nyir/spec.md`
- ビジョン: `docs/nyir/vision_universal_exchange.md`
- ABI/BID: `docs/予定/native-plan/box_ffi_abi.md`

View File

@ -0,0 +1,47 @@
# Phase 9.8: BIDレジストリ + 自動コード生成ツールWASM/VM/LLVM/言語)
目的What/Why
- 外部ライブラリをBoxBIDとして配布・発見・利用するための基盤を用意する。
- BIDBox Interface Definitionから各ターゲットWASM/VM/LLVM/TS/Pythonのスタブや宣言を自動生成し、開発者の負担を最小化する。
成果物Deliverables
- BIDレジストリ仕様YAML/JSON スキーマ定義・バージョニング・依存関係・権限メタ)
- コードジェネレータCLI: `nyash bid gen --target wasm|vm|llvm|ts|py <bid.yaml>`
- 生成物(最低限):
- WASM: `(import ...)` 宣言テンプレ+ `importObject.env.*` のホスト実装雛形
- VM: 関数テーブル定義+ディスパッチ雛形
- LLVM: `declare` プロトタイプ群ヘッダ雛形C-ABI前提
- TypeScript/Python: ラッパFFI呼び出しAPIのプロキシ
- サンプルBIDからの生成例console/canvas
範囲Scope
1) スキーマ
- `version`, `interfaces[]`, `methods[]`, `params`, `returns`, `effect`, `permissions`9.9の権限連携)
- 例: `docs/nyir/bid_samples/console.yaml`, `docs/nyir/bid_samples/canvas.yaml`
2) CLI
- `nyash bid gen --target <t> <bid.yaml>``out/<t>/<name>/...` に生成
- オプション: `--out`, `--force`, `--dry-run`
3) テンプレート
- 各ターゲット用のMustache/Handlebars相当のテンプレート群
4) ドキュメント
- `docs/予定/native-plan/box_ffi_abi.md` にBID→生成の流れを追記
受け入れ基準Acceptance
- console/canvas のBIDから、WASM/VM/LLVM/TS/Python の最小スタブが生成される
- 生成物を用いて、9.7 のE2Econsole.log / canvas.fillRectが通る
- `--dry-run` で生成前にプレビューが確認できる
非スコープOut of Scope
- 高度な最適化生成、双方向同期、型高級機能(ジェネリクス/オーバーロード)
- 配布サーバやレジストリのネットワーク実装(ローカルファイル前提)
参照References
- ABI/BIDドラフト: `docs/予定/native-plan/box_ffi_abi.md`
- NyIR: `docs/nyir/spec.md`
- サンプルBID: `docs/nyir/bid_samples/console.yaml`, `docs/nyir/bid_samples/canvas.yaml`
- 計画: `docs/予定/native-plan/copilot_issues.txt`9.7/9.8/9.9
メモ(運用)
- 将来的に「BID→RuntimeImports/ExternCall宣言」の自動接続まで拡張予定WASM/VM/LLVM
- 権限メタpermissionsは 9.9 のモデルに合わせて必須化を検討。

View File

@ -0,0 +1,44 @@
# Phase 9.9: ExternCall 権限/ケイパビリティモデルSandbox/Allowlist
目的What/Why
- ExternCall外部API呼び出しに対する権限制御を導入し、安全な実行を担保する。
- BIDで必要権限を宣言し、ホスト側でAllowlist/設定により許可・拒否できる仕組みを整える。
成果物Deliverables
- 権限モデル仕様permissionカテゴリ、宣言/検証ルール、失権時挙動)
- 実行時制御WASM/VM/LLVM各実装
- WASM: import allowlist許可された `env.*` のみ解決)
- VM/LLVM: 関数テーブル/リンク時のゲート(未許可はスタブで拒否)
- 構成手段
- 設定ファイル(例: `nyash_permissions.toml`
- 環境変数/CLIフラグ`--allow console,canvas` など)
- (将来)対話プロンプト/UI
範囲Scope
- 権限カテゴリ(初版)
- `console`, `canvas`, `storage`, `net`, `audio`, `time`, `clipboard` など
- BID拡張
- 各methodに `permissions: [ ... ]` を必須化v0は任意→将来必須
- 検証/実行
- 生成時BID→コード生成: 権限メタを埋め込む
- 実行時: 設定に基づき、未許可のExternCallは即エラー
- 失権時の標準挙動
- 明示エラー(例: `PermissionDenied: env.canvas.fillRect requires [canvas]`
受け入れ基準Acceptance
- `console` のみ許可した設定で、`console.log` は成功、`canvas.fillRect` は拒否される
- WASM/VM/LLVM いずれでも、未許可呼び出しが正しくブロックされ、メッセージが一貫
- BIDの `permissions` を外す/変えると、生成物の権限制御が反映される
非スコープOut of Scope
- ユーザー対話UI/OSネイティブ権限ダイアログ将来
- 細粒度URL/ドメイン単位など)のネット権限制御(将来)
参照References
- BID/ABI: `docs/予定/native-plan/box_ffi_abi.md`
- NyIR/ExternCall: `docs/nyir/spec.md`
- 計画: `docs/予定/native-plan/copilot_issues.txt`9.7/9.8/9.9
メモ(運用)
- 9.8 のコードジェネレータに `permissions` を伝播させ、テンプレートに権限チェックを組み込む。
- 権限のデフォルトは「Deny All」明示許可のみ通すを推奨。

View File

@ -0,0 +1,306 @@
# 🚨 緊急修正 Issue: Everything is Box設計でのclone_box()問題根本解決
## 📋 Issue概要
**優先度**: 🔴 **URGENT** - 全ステートフルBoxSocketBox, P2PBox等に影響
**期間**: 2-3日
**担当**: Copilot様
## 🎯 問題の核心
**ユーザー指摘**: 「いや 単純に rustの使い方 へたなだけじゃーーい
**Gemini先生確認**: Everything is Box設計は正しい。問題は `clone_box()` を使うべきでない場所で使っていること
### 🚨 真犯人特定済み3箇所
1. **`src/interpreter/core.rs:366`** - `resolve_variable()`
2. **`src/instance.rs:275`** - `get_field()`
3. **`src/interpreter/expressions.rs:779`** - `execute_field_access()`
### 💥 現在の症状
```nyash
me.server.bind("127.0.0.1", 8080) // ✅ SocketBox ID=10, is_server=true
me.server.isServer() // ❌ SocketBox ID=19, is_server=false (別インスタンス!)
```
## 🛠️ 解決策Arc<dyn NyashBox>への段階的移行
**Gemini先生推奨**: `Box<dyn NyashBox>``Arc<dyn NyashBox>` で参照共有実現
---
## 📋 段階的修正手順Copilot実装ガイド
### **Phase 1: 型エイリアス導入**
#### 1.1 `src/box_trait.rs`に型エイリアス追加
```rust
// ファイル先頭のuse文の後に追加
use std::sync::Arc;
// 新しい型エイリアス - 将来的にBox<dyn NyashBox>を全て置き換える
pub type SharedNyashBox = Arc<dyn NyashBox>;
```
#### 1.2 NyashBoxトレイトに新メソッド追加
```rust
// src/box_trait.rs のNyashBoxトレイト内に追加
pub trait NyashBox: BoxCore + Debug {
// 既存メソッド...
/// Arc参照を返す新しいcloneメソッド参照共有
fn clone_arc(&self) -> SharedNyashBox {
Arc::new(self.clone())
}
/// 従来のclone_box互換性維持のため残す
fn clone_box(&self) -> Box<dyn NyashBox>;
}
```
### **Phase 2: データ構造変更**
#### 2.1 `src/instance.rs` - InstanceBox修正
```rust
// InstanceBox構造体のfields型変更
pub struct InstanceBox {
pub base: BoxBase,
pub class_name: String,
pub fields: Arc<Mutex<HashMap<String, SharedNyashBox>>>, // ← Box→Arc
// 他フィールドはそのまま
}
// コンストラクタ修正
impl InstanceBox {
pub fn new(class_name: String, fields: Vec<String>) -> Self {
let mut field_map: HashMap<String, SharedNyashBox> = HashMap::new();
for field in fields {
field_map.insert(field, Arc::new(VoidBox::new())); // Box::new → Arc::new
}
InstanceBox {
base: BoxBase::new(),
class_name,
fields: Arc::new(Mutex::new(field_map)),
}
}
}
```
#### 2.2 `src/interpreter/core.rs` - NyashInterpreter修正
```rust
// NyashInterpreter構造体の変数管理型変更
pub struct NyashInterpreter {
// 既存フィールド...
pub local_vars: HashMap<String, SharedNyashBox>, // ← Box→Arc
pub outbox_vars: HashMap<String, SharedNyashBox>, // ← Box→Arc
// 他フィールドはそのまま
}
```
### **Phase 3: 問題箇所修正(真犯人退治)**
#### 3.1 `src/interpreter/core.rs:366` - resolve_variable修正
```rust
// 修正前:
let cloned_value = local_value.clone_box(); // ← 新インスタンス作成(問題)
return Ok(cloned_value);
// 修正後:
pub(super) fn resolve_variable(&self, name: &str) -> Result<SharedNyashBox, RuntimeError> {
// ... 既存のログ処理
// 2. local変数をチェック
if let Some(local_value) = self.local_vars.get(name) {
eprintln!("🔍 DEBUG: Found '{}' in local_vars", name);
// 🔧 修正clone_box() → Arc::clone() で参照共有
let shared_value = Arc::clone(local_value);
core_deep_debug_log(&format!("✅ RESOLVE_VARIABLE shared reference: {} id={}",
name, shared_value.box_id()));
return Ok(shared_value);
}
// 残りの処理も同様にSharedNyashBoxを返すよう修正
// ...
}
```
#### 3.2 `src/instance.rs:275` - get_field修正
```rust
// 修正前:
pub fn get_field(&self, field_name: &str) -> Option<Box<dyn NyashBox>> {
self.fields.lock().unwrap().get(field_name).map(|v| v.clone_box()) // ← 複製(問題)
}
// 修正後:
pub fn get_field(&self, field_name: &str) -> Option<SharedNyashBox> {
eprintln!("✅ FIX: get_field('{}') returning shared Arc reference", field_name);
// 🔧 修正v.clone_box() → Arc::clone(v) で参照共有
self.fields.lock().unwrap().get(field_name).map(Arc::clone)
}
```
#### 3.3 `src/interpreter/expressions.rs:779` - execute_field_access修正
```rust
// 修正前:
let field_value = instance.get_field(field) // get_fieldがBoxを返していた
// 修正後:
fn execute_field_access(&mut self, object: &ASTNode, field: &str)
-> Result<SharedNyashBox, RuntimeError> { // ← 戻り値型変更
// オブジェクト評価
let obj_value = self.execute_expression(object)?;
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
// フィールドアクセス - get_fieldがArc参照を返すように修正済み
let field_value = instance.get_field(field)
.ok_or_else(|| RuntimeError::InvalidOperation {
message: format!("Field '{}' not found in {}", field, instance.class_name),
})?;
eprintln!("✅ FIELD ACCESS: Returning shared reference id={}", field_value.box_id());
Ok(field_value) // Arc参照を返す
} else {
// エラー処理...
}
}
```
### **Phase 4: set_field修正**
#### 4.1 `src/instance.rs` - set_field修正
```rust
// set_fieldも引数の型をSharedNyashBoxに変更
pub fn set_field(&self, field_name: &str, value: SharedNyashBox) -> Result<(), String> {
eprintln!("🔧 INSTANCE: set_field('{}') with shared Arc reference id={}",
field_name, value.box_id());
let mut fields = self.fields.lock().unwrap();
if fields.contains_key(field_name) {
if let Some(old_value) = fields.get(field_name) {
eprintln!("🔧 INSTANCE: Replacing field '{}': old_id={} -> new_id={}",
field_name, old_value.box_id(), value.box_id());
}
fields.insert(field_name.to_string(), value);
Ok(())
} else {
Err(format!("Field '{}' does not exist in {}", field_name, self.class_name))
}
}
```
---
## 🧪 テスト方法
### テストファイル作成
```bash
# テスト用Nyashコード
echo 'static box Main {
init { server }
main() {
me.server = new SocketBox()
print("=== Before bind ===")
print("isServer: " + me.server.isServer())
me.server.bind("127.0.0.1", 8080)
print("=== After bind ===")
print("isServer: " + me.server.isServer()) // これがtrueになれば修正成功
return me.server.isServer()
}
}' > test_arc_fix.nyash
```
### 実行・検証
```bash
# ビルド・実行
cargo build --release
./target/release/nyash test_arc_fix.nyash
# 期待される結果:
# === Before bind ===
# isServer: false
# === After bind ===
# isServer: true ← これが true になれば成功!
```
---
## 📋 修正対象ファイル一覧
### 必須修正ファイル
1. **`src/box_trait.rs`** - 型エイリアス・clone_arcメソッド追加
2. **`src/instance.rs`** - InstanceBox構造体・get_field・set_field修正
3. **`src/interpreter/core.rs`** - NyashInterpreter・resolve_variable修正
4. **`src/interpreter/expressions.rs`** - execute_field_access修正
### 追加修正が必要になる可能性があるファイル
- `src/interpreter/statements.rs` - 代入処理
- `src/interpreter/objects.rs` - オブジェクト生成処理
- その他 `Box<dyn NyashBox>` を使用している箇所
## 🎯 修正完了条件
### ✅ 成功条件
1. **テスト成功**: `test_arc_fix.nyash``isServer: true` が表示される
2. **コンパイル成功**: `cargo build --release` でエラーなし
3. **既存テスト成功**: `cargo test` でテスト通過
4. **デバッグログ確認**: 同一SocketBox IDが維持される
### 🔍 確認ポイント
- SocketBoxログで同じIDが表示されるID変化なし
- 状態が正しく保持されるbind後にisServer=true
- メモリリークが発生しないArc参照カウント正常
---
## 💡 実装のコツCopilot向け
### 段階的実装推奨
1. **まず型エイリアス追加** → コンパイルエラー確認
2. **データ構造を段階的に変更** → 各ファイル別に修正
3. **最後に問題の3箇所修正** → 動作テスト実行
### よくあるコンパイルエラー対処
- **型不一致**: `Box<dyn NyashBox>``SharedNyashBox` の混在
→ 段階的に `SharedNyashBox` に統一
- **ライフタイム問題**: Arc使用により大部分が解決
- **メソッドシグネチャ不一致**: 戻り値型を `SharedNyashBox` に変更
### デバッグのポイント
- 修正前後でSocketBox IDが同じになることを確認
- `Arc::strong_count()` で参照数確認(デバッグ用)
---
## 🚀 期待される効果
### 🎉 修正後の動作
```nyash
me.server.bind("127.0.0.1", 8080) // ✅ SocketBox ID=10, is_server=true
me.server.isServer() // ✅ SocketBox ID=10, is_server=true (同じインスタンス!)
```
### 📈 影響範囲
- **全ステートフルBox**: SocketBox, P2PBox, HTTPServerBox等が正常動作
- **全フィールドアクセス**: `obj.field` で状態保持
- **全変数アクセス**: `me`変数で状態保持
- **性能向上**: 不要なclone処理削減
### 🏆 Everything is Box設計完成
ユーザー指摘通り、設計は正しく、**Rustの所有権システムを正しく使う**ことで、真の「Everything is Box」が実現されます
---
**実装担当**: Copilot様
**レビュー**: Claude & User
**完了目標**: 2-3日以内

View File

@ -0,0 +1,48 @@
Rustのプログラミングに関して深い技術的質問があります。
【状況】
Arc<Mutex<bool>>を使った構造体があります:
```rust
struct SocketBox {
is_server: Arc<Mutex<bool>>,
// ...他のフィールド
}
impl Clone for SocketBox {
fn clone(&self) -> Self {
Self {
is_server: Arc::clone(&self.is_server), // 同じArcを共有
// ...
}
}
}
```
【期待される動作】
- 一つのクローンで *self.is_server.lock().unwrap() = true すると
- 他のクローンでも同じArcを参照しているので true が見えるはず
【実際に起きた問題】
- bind()メソッドで is_server を true に設定
- その後 isServer()メソッドで確認すると false のまま
- Arc::clone()で同じArcインスタンスを共有しているはずなのに状態変更が見えない
【デバッグ情報】
- Arcポインタアドレスは同じ (例: 5645546739b0)
- しかしbind()後にisServer()を呼ぶと別のBox IDで実行される
- 「同じArcアドレスなのに中身がNone」のような現象も観測された
【質問】
1. Arc::clone()で共有されたMutex<bool>の状態変更が他のクローンで見えない原因は何が考えられますか?
2. RustのArc<Mutex<T>>で状態共有がうまくいかないパターンはありますか?
3. Box IDが変わることがArc共有に影響する可能性はありますか
4. 「同じArcポインタアドレスなのに中身が変化する」現象の技術的説明は
5. unsafe操作やメモリ破壊が関係している可能性はありますか
【環境】
- Rust実装のインタープリター言語Nyash
- Everything is Box哲学でArc<Mutex<dyn NyashBox>>統一設計
- clone()時に新しいBox IDが生成される設計
Rustの所有権システムやArc/Mutexの実装レベルでの深い知識をお聞かせください。

155
issue_phase951.md Normal file
View File

@ -0,0 +1,155 @@
## 🔴 Critical Issue: Phase 9実用化ブロッカー
**優先度**: 🔴 **最高(実用性ブロッカー)**
**期間**: 1週間
**前提**: Phase 9 (PR #67) マージ済み
## 🎯 概要
Phase 9で実装されたWASM/AOTとHTTPサーバー機能に重大な制約があり、実用化を阻害しています。本issueではこれらを修正し、真の実用レベルに到達させます。
## 🔍 現在の問題
### 1. **WASM/AOT コンパイルエラー(最重要)**
```bash
# 現象
$ ./target/release/nyash --compile-wasm test_simple_loop.nyash
❌ WASM compilation error: Unsupported instruction: Jump { target: BasicBlockId(1) }
```
**原因**: `src/backend/wasm/codegen.rs`にJump/Branch命令が未実装
**影響**: **ループ・条件分岐を含む全プログラムがWASM/AOT化不可**
### 2. **HTTPServerBox listen()常に失敗**
```nyash
// 現象
server.bind("127.0.0.1", 8080) // ✅ true
server.listen(10) // ❌ always false
```
**原因**: `src/boxes/socket_box.rs`のlisten()実装が不完全
**影響**: HTTPサーバーが実際には動作しない
### 3. **エラーハンドリング脆弱性**
```bash
$ grep -n "unwrap()" src/boxes/http_server_box.rs | wc -l
26
```
**原因**: 26箇所のunwrap()使用
**影響**: 本番環境でパニック多発の可能性
## 📋 実装タスク
### Task 1: WASM Jump/Branch命令実装2日
**ファイル**: `src/backend/wasm/codegen.rs`
```rust
// 追加実装箇所358行目付近
MirInstruction::Jump { target } => {
// 無条件ジャンプ
// WASMのbr命令を使用
Ok(vec![
format!("br $block_{}", target.0),
])
},
MirInstruction::Branch { cond, then_block, else_block } => {
// 条件分岐
// WASMのbr_if命令を使用
self.emit_value_load(cond)?;
Ok(vec![
"i32.eqz".to_string(),
format!("br_if $block_{}", else_block.0),
format!("br $block_{}", then_block.0),
])
},
```
**必要な補助実装**:
- ブロック深度管理(`get_block_depth`メソッド)
- ループ構造のblock/loop/end生成
### Task 2: SocketBox listen()修正1日
**ファイル**: `src/boxes/socket_box.rs`
```rust
pub fn listen(&self, backlog: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
let backlog_num = backlog.to_string_box().value.parse::<i32>().unwrap_or(128);
// 実際にlisten状態を管理
if let Some(ref listener) = *self.listener.lock().unwrap() {
// TcpListenerは既にlisten状態
// 内部状態を更新
*self.status.lock().unwrap() = SocketStatus::Listening;
Box::new(BoolBox::new(true))
} else {
Box::new(BoolBox::new(false))
}
}
```
### Task 3: エラーハンドリング改善2日
**対象ファイル**:
- `src/boxes/http_server_box.rs`
- `src/boxes/socket_box.rs`
- `src/boxes/http_message_box.rs`
**変更例**:
```rust
// Before
let listener = self.listener.lock().unwrap();
// After
let listener = match self.listener.lock() {
Ok(l) => l,
Err(_) => return Box::new(StringBox::new("Error: Failed to acquire lock")),
};
```
### Task 4: HTTPサーバー実用化2日
**ファイル**: `src/boxes/http_server_box.rs`
1. **スレッドプール実装**
2. **適切なシャットダウン**
## 🎯 完了条件
1. **WASM/AOT成功**
```bash
$ ./target/release/nyash --compile-wasm test_wasm_loop.nyash
✅ WASM compilation completed successfully!
```
2. **HTTPサーバー実動作**
```bash
$ ./target/release/nyash test_http_server_real.nyash &
$ curl http://localhost:8080/
<h1>Nyash Server Running!</h1>
```
3. **エラーハンドリング**
- unwrap()使用箇所: 26 → 5以下
## 📊 性能目標
- **WASM実行**: 現在11.5倍 → **13.5倍以上**
- **HTTPサーバー**: 100 req/sec以上
## 🔧 参考資料
- [WebAssembly Control Instructions](https://webassembly.github.io/spec/core/syntax/instructions.html#control-instructions)
- [wasmtime compile documentation](https://docs.wasmtime.dev/cli-compile.html)
## 🎉 期待される成果
Phase 9.51完了により、Nyashは
- **実用的なWebアプリケーション開発**が可能に
- **高速なAOT実行ファイル配布**が実現
- **本番環境での安定動作**を保証
Everything is Box哲学を守りながら、実用性を達成します🐱

View File

@ -0,0 +1,44 @@
Nyashプログラミング言語のRust実装で困っています。
【現在の問題】
Everything is Box設計で、全てのデータがBox<dyn NyashBox>として管理されています。
しかし以下の3箇所で clone_box() を使って毎回新しいインスタンスを作成してしまい、
ステートフルなオブジェクトSocketBoxなどの状態が保持されない問題が発生しています。
【問題箇所】
1. resolve_variable() - src/interpreter/core.rs:366
```rust
let cloned_value = local_value.clone_box(); // ← 毎回新インスタンス
return Ok(cloned_value);
```
2. get_field() - src/instance.rs:275
```rust
self.fields.lock().unwrap().get(field_name).map(|v| v.clone_box()) // ← フィールド複製
```
3. execute_field_access() - src/interpreter/expressions.rs:779
```rust
let field_value = instance.get_field(field) // ← 上記を呼び出し
```
【現在のデータ構造】
- local_vars: HashMap<String, Box<dyn NyashBox>>
- fields: Arc<Mutex<HashMap<String, Box<dyn NyashBox>>>>
- 全てのBoxは Arc<Mutex> で内部状態を管理
【症状】
me.server.bind() → SocketBox ID=10で成功、is_server=true
me.server.isServer() → SocketBox ID=19で失敗、is_server=false
毎回別インスタンスになってしまう
【質問】
Rustの所有権システムを正しく使って、clone_box()ではなく「同じBoxインスタンスへの参照」を返すにはどう実装すべきでしょうか
考えられるアプローチ:
1. Arc<dyn NyashBox>に統一する
2. Rc<dyn NyashBox>を使う
3. 参照を返す(ライフタイム管理)
4. 他の適切なパターン
具体的なコード例を交えて、Rust的に正しい設計を教えてください。

8
simple_test.wat Normal file
View File

@ -0,0 +1,8 @@
(module
(func $main (result i32)
i32.const 10
i32.const 20
i32.add
)
(export "main" (func $main))
)

261
socketbox_deadlock_issue.md Normal file
View File

@ -0,0 +1,261 @@
# 🚨 緊急Issue: SocketBoxメソッド呼び出しデッドロック問題
**Issue Priority**: 🔥 **CRITICAL - 最高緊急度**
**Status**: 🚨 **SocketBox完全機能停止**
**Impact**: Phase 9実装HTTPサーバー等が完全に使用不能
**Discovery Date**: 2025-08-14
## 📋 **問題概要**
SocketBoxのすべてのメソッド`bind()`, `listen()`, `isServer()`, `toString()`等)が無限ブロックし、一切の操作が不可能。
**他のBox型StringBox, IntegerBox, ArrayBox等は正常動作** - SocketBox特有の問題。
## 🎯 **詳細分析結果**
### ✅ **正常動作確認済み**
- **SocketBox作成**: `new SocketBox()`
- **Clone機能**: Arc参照共有 `Arc addresses match = true`
- **状態管理**: Arc<Mutex>内部状態正常 ✅
### ❌ **問題箇所特定済み**
```rust
// src/interpreter/expressions.rs:462-464 (問題発生箇所)
if let Some(socket_box) = obj_value.as_any().downcast_ref::<SocketBox>() {
let result = self.execute_socket_method(socket_box, method, arguments)?;
// ↑↑↑ この行に到達しないexecute_socket_methodが呼ばれない
```
**問題の核心**: `downcast_ref::<SocketBox>()` または `obj_value` 取得段階でデッドロック
## 📊 **実行ログ証拠**
### 🔥 **デッドロック再現ログ**
```bash
[Console LOG] SocketBox作成完了
[Console LOG] bind実行開始...
🔥 SOCKETBOX CLONE DEBUG:
🔥 Original Socket ID = 12
🔥 Arc addresses match = true # ← Clone処理正常
# ここで無限ブロック
# 🔥 SOCKET_METHOD: bind() called が出力されない
```
### ✅ **正常動作比較 (他のBox)**
```bash
[Console LOG] ArrayBox作成完了
[Console LOG] push実行開始...
✅ ARRAY_METHOD: push() called # ← 正常にメソッド到達
✅ ArrayBox push completed # ← 正常完了
```
## 🧪 **完全再現テストケース**
### **Test 1: 最小再現ケース**
```nyash
# test_socket_deadlock_minimal.nyash
static box Main {
init { console }
main() {
me.console = new ConsoleBox()
local socket = new SocketBox()
me.console.log("SocketBox作成成功")
# ここで無限ブロック
local result = socket.bind("127.0.0.1", 19999)
me.console.log("これは出力されない")
}
}
```
**実行コマンド**: `timeout 10s ./target/release/nyash test_socket_deadlock_minimal.nyash`
**期待結果**: タイムアウト (デッドロック)
### **Test 2: 他メソッドでの動作確認**
```nyash
# test_socket_methods_comprehensive.nyash
static box Main {
init { console }
main() {
me.console = new ConsoleBox()
local socket = new SocketBox()
# 全メソッドテスト
local result1 = socket.isServer() # デッドロック
local result2 = socket.toString() # デッドロック
local result3 = socket.close() # デッドロック
return "全て失敗"
}
}
```
### **Test 3: 他のBox正常動作確認**
```nyash
# test_other_boxes_working.nyash
static box Main {
init { console }
main() {
me.console = new ConsoleBox()
# ArrayBox - 正常動作確認
local array = new ArrayBox()
array.push("test")
me.console.log("ArrayBox正常: " + array.size().toString())
# MapBox - 正常動作確認
local map = new MapBox()
map.set("key", "value")
me.console.log("MapBox正常: " + map.get("key").toString())
return "他のBoxは正常動作"
}
}
```
**実行コマンド**: `./target/release/nyash test_other_boxes_working.nyash`
**期待結果**: 正常完了
## 🔍 **詳細調査要求 - 根本的原因特定**
### **❌ 禁止: 場当たり的修正**
- symptom-based修正禁止
- 推測による部分修正禁止
- 表面的デバッグログ追加のみ禁止
### **✅ 要求: システマティック根本調査**
#### **Phase 1: アーキテクチャレベル分析**
- **Mutex Chain分析**: SocketBox特有のArc<Mutex>チェーンがデッドロック原因か
- **Memory Layout分析**: SocketBox vs 他Boxのメモリ配置差異
- **Ownership Pattern分析**: Arc参照パターンでの循環参照確認
#### **Phase 2: コンパイラ・ランタイムレベル**
- **Type System分析**: SocketBox専用の型解決問題
- **Trait Resolution分析**: downcast_refでのtrait解決スタック
- **Runtime Stack分析**: メソッド解決でのスタックオーバーフロー確認
#### **Phase 3: パーサー・AST・インタープリターレベル**
- **Parser Level**: SocketBoxメソッド呼び出しAST生成問題
- **AST Structure**: SocketBox専用のAST構造異常
- **Interpreter Pipeline**: 全実行パイプラインでのボトルネック特定
#### **Phase 4: Box実装アーキテクチャ比較**
```rust
// 系統的比較調査対象
StringBox // ✅ 正常 - Arc<String>のみ
ArrayBox // ✅ 正常 - Arc<Mutex<Vec>>のみ
MapBox // ✅ 正常 - Arc<Mutex<HashMap>>のみ
SocketBox // ❌ 問題 - Arc<Mutex<TcpListener>> + Arc<Mutex<bool>> × 複数
```
**仮説**: SocketBox特有の**複数Arc<Mutex>組み合わせ**が循環デッドロック原因
#### **Phase 5: Concurrent Access Pattern分析**
- **Lock Order**: 複数Mutex取得順序問題
- **Recursive Lock**: 同じMutex再帰ロック問題
- **Cross-Reference**: Arc間の相互参照デッドロック
## ⚙️ **デバッグ環境**
### **ビルド設定**
```bash
cargo build --release -j32
```
### **実行環境**
- **Platform**: WSL2 Linux
- **Rust**: latest stable
- **Nyash**: PR #75マージ後
### **追加デバッグログ**
以下のログが既に追加済み:
- SocketBox Clone処理: ✅ 動作
- execute_socket_method: ❌ 到達しない
- 他Boxメソッド: ✅ 動作
## 🎯 **完了条件**
### **必須達成項目**
1.**SocketBox.bind()正常動作**:
```bash
local result = socket.bind("127.0.0.1", 8080)
# result.equals(true) == true
```
2. ✅ **SocketBox.isServer()正常動作**:
```bash
socket.bind("127.0.0.1", 8080)
local isServer = socket.isServer()
# isServer.equals(true) == true
```
3. ✅ **SocketBox.toString()正常動作**:
```bash
local socketStr = socket.toString()
# デッドロックなし・文字列返却
```
### **テスト実行必須**
```bash
# 基本動作テスト
./target/release/nyash test_socket_deadlock_minimal.nyash
# 期待結果: 正常完了・デッドロックなし
# 包括的機能テスト
./target/release/nyash test_socket_methods_comprehensive.nyash
# 期待結果: 全メソッド正常動作
# 状態保持テスト
./target/release/nyash test_socket_state_preservation.nyash
# 期待結果: bind() → isServer() == true
```
## 📊 **構造的分析ツール提供**
### **Architecture Comparison Script**
```bash
# Box構造比較スクリプト作成推奨
rg "struct.*Box" src/boxes/ -A 10 > box_structures.txt
rg "Arc<Mutex" src/boxes/ > arc_mutex_patterns.txt
rg "impl.*for.*Box" src/boxes/ > box_implementations.txt
```
### **Deadlock Detection Strategy**
```rust
// 推奨調査コード
// src/boxes/socket_box.rs に一時的追加
impl SocketBox {
fn debug_mutex_state(&self) {
eprintln!("🔍 MUTEX STATE:");
eprintln!(" listener strong_count: {}", Arc::strong_count(&self.listener));
eprintln!(" is_server strong_count: {}", Arc::strong_count(&self.is_server));
eprintln!(" thread_id: {:?}", std::thread::current().id());
}
}
```
## 📝 **報告要求 - システマティック**
### **必須分析項目**
1. **Root Cause Architecture** - システムレベルでの構造的問題特定
2. **Comparative Analysis** - 他Boxとの決定的差異メモリ・型・実装
3. **Pipeline Bottleneck** - パーサー→AST→インタープリター→実行の問題段階
4. **Concurrency Model** - Arc<Mutex>モデルでのデッドロック形成メカニズム
5. **Fix Strategy** - 根本解決戦略(アーキテクチャ変更含む)
### **技術実証要求**
- **Before/After比較**: 修正前後の詳細動作比較
- **Performance Impact**: 修正による他機能への性能影響
- **Memory Safety**: 修正がメモリ安全性に与える影響
- **Concurrent Safety**: 修正が並行安全性に与える影響
### **❌ 厳格禁止事項**
- **Surface-level修正**: 症状のみ修正・根本原因放置
- **Guesswork Solutions**: 実証なしの推測ベース修正
- **Partial Validation**: 一部テストのみで完了報告
- **Architecture Debt**: 技術負債を生む応急処置
---
**🚨 この問題はPhase 9HTTPサーバー実装の完全阻害要因です。最優先で完全解決をお願いします。**

View File

@ -56,15 +56,33 @@ pub struct SocketBox {
impl Clone for SocketBox {
fn clone(&self) -> Self {
// 🔧 FIX: Share state containers for "Everything is Box" reference sharing
// This ensures that clones of the same SocketBox share mutable state
Self {
eprintln!("🔥 SOCKETBOX CLONE DEBUG:");
eprintln!("🔥 Original Socket ID = {}", self.base.id);
eprintln!("🔥 Original Arc pointer = {:p}", &self.is_server);
eprintln!("🔥 Arc strong_count BEFORE = {}", std::sync::Arc::strong_count(&self.is_server));
let cloned = Self {
base: BoxBase::new(), // New unique ID for clone (for debugging/identity)
listener: Arc::clone(&self.listener), // Share the same listener
stream: Arc::clone(&self.stream), // Share the same stream
is_server: Arc::clone(&self.is_server), // 🔧 Share the same state container
is_connected: Arc::clone(&self.is_connected), // 🔧 Share the same state container
};
eprintln!("🔥 Cloned Socket ID = {}", cloned.base.id);
eprintln!("🔥 Cloned Arc pointer = {:p}", &cloned.is_server);
eprintln!("🔥 Arc strong_count AFTER = {}", std::sync::Arc::strong_count(&self.is_server));
eprintln!("🔥 Arc addresses match = {}",
std::ptr::eq(&*self.is_server as *const _, &*cloned.is_server as *const _));
// 状態共有テスト
if let (Ok(orig_guard), Ok(clone_guard)) = (self.is_server.lock(), cloned.is_server.lock()) {
eprintln!("🔥 Original state = {}", *orig_guard);
eprintln!("🔥 Cloned state = {}", *clone_guard);
eprintln!("🔥 States match = {}", *orig_guard == *clone_guard);
}
cloned
}
}
@ -86,28 +104,69 @@ impl SocketBox {
let socket_addr = format!("{}:{}", addr_str, port_str);
eprintln!("🔥 SOCKETBOX DEBUG: bind() called");
eprintln!("🔥 Socket ID = {}", self.base.id);
eprintln!("🔥 Address = {}", socket_addr);
eprintln!("🔥 Arc pointer = {:p}", &self.is_server);
match TcpListener::bind(&socket_addr) {
Ok(listener) => {
eprintln!("✅ TCP bind successful");
// listener設定
match self.listener.lock() {
Ok(mut listener_guard) => {
*listener_guard = Some(listener);
eprintln!("✅ Listener stored successfully");
},
Err(_) => {
Err(e) => {
eprintln!("❌ Failed to lock listener mutex: {}", e);
return Box::new(BoolBox::new(false));
}
}
// is_server状態設定 - 徹底デバッグ
match self.is_server.lock() {
Ok(mut is_server_guard) => {
eprintln!("🔥 BEFORE MUTATION:");
eprintln!("🔥 is_server value = {}", *is_server_guard);
eprintln!("🔥 Arc strong_count = {}", std::sync::Arc::strong_count(&self.is_server));
eprintln!("🔥 Arc weak_count = {}", std::sync::Arc::weak_count(&self.is_server));
eprintln!("🔥 Guard pointer = {:p}", &*is_server_guard);
// 状態変更
*is_server_guard = true;
eprintln!("🔥 AFTER MUTATION:");
eprintln!("🔥 is_server value = {}", *is_server_guard);
eprintln!("🔥 Value confirmed = {}", *is_server_guard == true);
// 明示的にドロップしてロック解除
drop(is_server_guard);
eprintln!("✅ is_server guard dropped");
// 再確認テスト
match self.is_server.lock() {
Ok(check_guard) => {
eprintln!("🔥 RECHECK AFTER DROP:");
eprintln!("🔥 is_server value = {}", *check_guard);
},
Err(_) => {
// Non-critical error, continue
Err(e) => {
eprintln!("❌ Failed to recheck: {}", e);
}
}
},
Err(e) => {
eprintln!("❌ SOCKETBOX: Failed to lock is_server mutex: {}", e);
return Box::new(BoolBox::new(false));
}
}
eprintln!("✅ bind() completed successfully");
Box::new(BoolBox::new(true))
},
Err(_e) => {
// Port might be in use, return false
Err(e) => {
eprintln!("❌ TCP bind failed: {}", e);
Box::new(BoolBox::new(false))
}
}
@ -316,8 +375,27 @@ impl SocketBox {
/// サーバーモード確認
pub fn is_server(&self) -> Box<dyn NyashBox> {
let is_server_value = *self.is_server.lock().unwrap();
eprintln!("🔥 SOCKETBOX DEBUG: is_server() called");
eprintln!("🔥 Socket ID = {}", self.base.id);
eprintln!("🔥 Arc pointer = {:p}", &self.is_server);
match self.is_server.lock() {
Ok(is_server_guard) => {
let is_server_value = *is_server_guard;
eprintln!("🔥 IS_SERVER READ:");
eprintln!("🔥 is_server value = {}", is_server_value);
eprintln!("🔥 Arc strong_count = {}", std::sync::Arc::strong_count(&self.is_server));
eprintln!("🔥 Arc weak_count = {}", std::sync::Arc::weak_count(&self.is_server));
eprintln!("🔥 Guard pointer = {:p}", &*is_server_guard);
eprintln!("🔥 Returning BoolBox with value = {}", is_server_value);
Box::new(BoolBox::new(is_server_value))
},
Err(e) => {
eprintln!("❌ SOCKETBOX: Failed to lock is_server mutex in is_server(): {}", e);
Box::new(BoolBox::new(false))
}
}
}
}
@ -327,8 +405,30 @@ impl NyashBox for SocketBox {
}
fn to_string_box(&self) -> StringBox {
let is_server = *self.is_server.lock().unwrap();
let is_connected = *self.is_connected.lock().unwrap();
eprintln!("🔥 SOCKETBOX to_string_box() called - Socket ID = {}", self.base.id);
eprintln!("🔥 Arc pointer = {:p}", &self.is_server);
let is_server = match self.is_server.lock() {
Ok(guard) => {
eprintln!("✅ is_server.lock() successful");
*guard
},
Err(e) => {
eprintln!("❌ is_server.lock() failed: {}", e);
false // デフォルト値
}
};
let is_connected = match self.is_connected.lock() {
Ok(guard) => {
eprintln!("✅ is_connected.lock() successful");
*guard
},
Err(e) => {
eprintln!("❌ is_connected.lock() failed: {}", e);
false // デフォルト値
}
};
let status = if is_server {
"Server"
@ -364,8 +464,23 @@ impl BoxCore for SocketBox {
}
fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let is_server = *self.is_server.lock().unwrap();
let is_connected = *self.is_connected.lock().unwrap();
eprintln!("🔥 SOCKETBOX fmt_box() called - Socket ID = {}", self.base.id);
let is_server = match self.is_server.lock() {
Ok(guard) => *guard,
Err(e) => {
eprintln!("❌ fmt_box: is_server.lock() failed: {}", e);
false
}
};
let is_connected = match self.is_connected.lock() {
Ok(guard) => *guard,
Err(e) => {
eprintln!("❌ fmt_box: is_connected.lock() failed: {}", e);
false
}
};
let status = if is_server {
"Server"

View File

@ -78,7 +78,7 @@ impl InstanceBox {
// フィールドをVoidBoxで初期化
let mut field_map = HashMap::new();
for field in &fields {
field_map.insert(field.clone(), Box::new(VoidBox::new()) as Box<dyn NyashBox>);
field_map.insert(field.clone(), Arc::new(VoidBox::new()) as Arc<dyn NyashBox>);
}
// Weak fields をHashSetに変換高速判定用
@ -131,7 +131,7 @@ impl InstanceBox {
if let Ok(legacy_box) = value.to_box() {
// Convert Arc<Mutex<dyn NyashBox>> to Box<dyn NyashBox>
if let Ok(inner_box) = legacy_box.try_lock() {
self.fields.lock().unwrap().insert(field_name, inner_box.clone_box());
self.fields.lock().unwrap().insert(field_name, Arc::from(inner_box.clone_box()));
}
}
}

View File

@ -669,7 +669,7 @@ impl NyashInterpreter {
};
// 🌍 this変数をバインドしてstatic初期化実行me構文のため
self.declare_local_variable("me", static_instance);
self.declare_local_variable("me", (*static_instance).clone_box());
for stmt in init_statements {
self.execute_statement(stmt)?;
@ -722,7 +722,7 @@ impl NyashInterpreter {
// GlobalBoxのfieldsに直接挿入
{
let mut fields = global_box.fields.lock().unwrap();
fields.insert("statics".to_string(), Box::new(statics_box));
fields.insert("statics".to_string(), Arc::new(statics_box));
}
eprintln!("🌍 statics namespace created in GlobalBox successfully");
@ -751,7 +751,7 @@ impl NyashInterpreter {
// statics InstanceBoxのfieldsに直接挿入動的フィールド追加
{
let mut fields = statics_instance.fields.lock().unwrap();
fields.insert(name.to_string(), Box::new(instance));
fields.insert(name.to_string(), Arc::new(instance));
}
eprintln!("🔥 Static box '{}' instance registered in statics namespace", name);

View File

@ -10,8 +10,9 @@ use super::*;
use crate::ast::UnaryOperator;
use crate::boxes::{buffer::BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
use crate::boxes::{FloatBox, MathBox, ConsoleBox, TimeBox, DateTimeBox, RandomBox, SoundBox, DebugBox, file::FileBox, MapBox};
use crate::box_trait::BoolBox;
use crate::box_trait::{BoolBox, SharedNyashBox};
use crate::operator_traits::OperatorResolver;
use std::sync::Arc;
// TODO: Fix NullBox import issue later
// use crate::NullBox;
@ -65,7 +66,7 @@ impl NyashInterpreter {
.map_err(|_| RuntimeError::InvalidOperation {
message: "'this' is only available inside methods".to_string(),
})?;
Ok((**shared_this).clone_box()) // Convert for external interface
Ok((*shared_this).clone_box()) // Convert for external interface
}
ASTNode::Me { .. } => {
@ -76,7 +77,7 @@ impl NyashInterpreter {
message: "'me' is only available inside methods".to_string(),
})?;
Ok((**shared_me).clone_box()) // Convert for external interface
Ok((*shared_me).clone_box()) // Convert for external interface
}
ASTNode::ThisField { field, .. } => {
@ -86,12 +87,12 @@ impl NyashInterpreter {
message: "'this' is not bound in the current context".to_string(),
})?;
if let Some(instance) = (**this_value).as_any().downcast_ref::<InstanceBox>() {
if let Some(instance) = (*this_value).as_any().downcast_ref::<InstanceBox>() {
let shared_field = instance.get_field(field)
.ok_or_else(|| RuntimeError::InvalidOperation {
message: format!("Field '{}' not found on this", field)
})?;
Ok((**shared_field).clone_box()) // Convert for external interface
Ok((*shared_field).clone_box()) // Convert for external interface
} else {
Err(RuntimeError::TypeError {
message: "'this' is not an instance".to_string(),
@ -106,12 +107,12 @@ impl NyashInterpreter {
message: "'this' is not bound in the current context".to_string(),
})?;
if let Some(instance) = (**me_value).as_any().downcast_ref::<InstanceBox>() {
if let Some(instance) = (*me_value).as_any().downcast_ref::<InstanceBox>() {
let shared_field = instance.get_field(field)
.ok_or_else(|| RuntimeError::InvalidOperation {
message: format!("Field '{}' not found on me", field)
})?;
Ok((**shared_field).clone_box()) // Convert for external interface
Ok((*shared_field).clone_box()) // Convert for external interface
} else {
Err(RuntimeError::TypeError {
message: "'this' is not an instance".to_string(),
@ -464,14 +465,30 @@ impl NyashInterpreter {
// 🔧 FIX: Update stored variable for stateful SocketBox methods
// These methods modify the SocketBox internal state, so we need to update
// the stored local variable to ensure subsequent accesses get the updated state
// the stored variable/field to ensure subsequent accesses get the updated state
if matches!(method, "bind" | "connect" | "close") {
if let ASTNode::Variable { name, .. } = object {
if let Some(stored_var) = self.local_vars.get_mut(name) {
// Replace the stored instance with the modified one
let updated_instance = socket_box.clone();
*stored_var = Box::new(updated_instance);
match object {
ASTNode::Variable { name, .. } => {
// Handle local variables
if let Some(stored_var) = self.local_vars.get_mut(name) {
*stored_var = Arc::new(updated_instance);
}
},
ASTNode::FieldAccess { object: field_obj, field, .. } => {
// Handle StaticBox fields like me.server
if let ASTNode::Variable { name, .. } = field_obj.as_ref() {
if name == "me" {
if let Ok(me_instance) = self.resolve_variable("me") {
if let Some(instance) = (*me_instance).as_any().downcast_ref::<InstanceBox>() {
let _ = instance.set_field(field, Arc::new(updated_instance));
}
}
}
}
},
_ => {}
}
}
@ -554,7 +571,7 @@ impl NyashInterpreter {
if name == "me" {
// Get current instance to check if field is weak
if let Ok(current_me) = self.resolve_variable("me") {
if let Some(current_instance) = (**current_me).as_any().downcast_ref::<InstanceBox>() {
if let Some(current_instance) = (*current_me).as_any().downcast_ref::<InstanceBox>() {
if current_instance.is_weak_field(field) {
return Err(RuntimeError::InvalidOperation {
message: format!(
@ -682,7 +699,8 @@ impl NyashInterpreter {
if let ASTNode::Variable { name, .. } = object {
// Static boxの可能性をチェック
if self.is_static_box(name) {
return self.execute_static_field_access(name, field);
let static_result = self.execute_static_field_access(name, field)?;
return Ok(Arc::from(static_result));
}
}
@ -721,14 +739,14 @@ impl NyashInterpreter {
crate::value::NyashValue::Null => {
eprintln!("🔗 DEBUG: Weak field '{}' is null (reference dropped)", field);
// Return null box for compatibility
return Ok(Box::new(crate::boxes::null_box::NullBox::new()));
return Ok(Arc::new(crate::boxes::null_box::NullBox::new()));
}
_ => {
eprintln!("🔗 DEBUG: Weak field '{}' still has valid reference", field);
// Convert back to Box<dyn NyashBox> for now
if let Ok(box_value) = weak_value.to_box() {
if let Ok(inner_box) = box_value.try_lock() {
return Ok(inner_box.clone_box());
return Ok(Arc::from(inner_box.clone_box()));
}
}
}
@ -782,10 +800,13 @@ impl NyashInterpreter {
})?;
// 3. フィールドアクセス
instance.get_field(field)
let shared_field = instance.get_field(field)
.ok_or(RuntimeError::InvalidOperation {
message: format!("Field '{}' not found in static box '{}'", field, static_box_name),
})
})?;
// Convert Arc to Box for compatibility
Ok((*shared_field).clone_box())
}
@ -865,7 +886,7 @@ impl NyashInterpreter {
message: "'from' can only be used inside methods".to_string(),
})?;
let current_instance = (**current_instance_val).as_any().downcast_ref::<InstanceBox>()
let current_instance = (*current_instance_val).as_any().downcast_ref::<InstanceBox>()
.ok_or(RuntimeError::TypeError {
message: "'from' requires current instance to be InstanceBox".to_string(),
})?;

View File

@ -17,15 +17,25 @@ impl NyashInterpreter {
) -> Result<Box<dyn NyashBox>, RuntimeError> {
match method {
"bind" => {
eprintln!("🔥 SOCKET_METHOD: bind() called");
if arguments.len() != 2 {
return Err(RuntimeError::InvalidOperation {
message: format!("bind() expects 2 arguments, got {}", arguments.len()),
});
}
eprintln!("🔥 SOCKET_METHOD: Evaluating address argument...");
let address = self.execute_expression(&arguments[0])?;
eprintln!("🔥 SOCKET_METHOD: Address evaluated: {}", address.to_string_box().value);
eprintln!("🔥 SOCKET_METHOD: Evaluating port argument...");
let port = self.execute_expression(&arguments[1])?;
Ok(socket_box.bind(address, port))
eprintln!("🔥 SOCKET_METHOD: Port evaluated: {}", port.to_string_box().value);
eprintln!("🔥 SOCKET_METHOD: Calling socket_box.bind()...");
let result = socket_box.bind(address, port);
eprintln!("🔥 SOCKET_METHOD: bind() completed");
Ok(result)
}
"listen" => {
if arguments.len() != 1 {

View File

@ -9,6 +9,7 @@
use super::*;
use crate::boxes::{NullBox, ConsoleBox, FloatBox, DateTimeBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
// use crate::boxes::intent_box_wrapper::IntentBoxWrapper;
use crate::box_trait::SharedNyashBox;
use std::sync::Arc;
impl NyashInterpreter {
@ -708,6 +709,9 @@ impl NyashInterpreter {
// 現在のスコープでBoxを追跡自動解放のため
// 🌍 革命的実装Environment tracking廃止
// Create Arc outside if block so it's available in all scopes
let instance_arc = Arc::from(instance_box);
// コンストラクタを呼び出す
// "pack/引数数"、"init/引数数"、"Box名/引数数" の順で試す
let pack_key = format!("pack/{}", arguments.len());
@ -718,7 +722,6 @@ impl NyashInterpreter {
.or_else(|| final_box_decl.constructors.get(&init_key))
.or_else(|| final_box_decl.constructors.get(&box_name_key)) {
// コンストラクタを実行
let instance_arc = Arc::from(instance_box);
self.execute_constructor(&instance_arc, constructor, arguments, &final_box_decl)?;
} else if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {

View File

@ -298,13 +298,13 @@ impl NyashInterpreter {
// 既存のフィールド値があればfini()を呼ぶ
if let Some(old_field_value) = instance.get_field(field) {
if let Some(old_instance) = old_field_value.as_any().downcast_ref::<InstanceBox>() {
if let Some(old_instance) = (*old_field_value).as_any().downcast_ref::<InstanceBox>() {
let _ = old_instance.fini();
finalization::mark_as_finalized(old_instance.box_id());
}
}
instance.set_field(field, val.clone_box())
instance.set_field(field, Arc::from(val.clone_box()))
.map_err(|e| RuntimeError::InvalidOperation { message: e })?;
Ok(val)
} else {
@ -321,7 +321,7 @@ impl NyashInterpreter {
message: "'this' is not bound in the current context".to_string(),
})?;
if let Some(instance) = (**this_value).as_any().downcast_ref::<InstanceBox>() {
if let Some(instance) = (*this_value).as_any().downcast_ref::<InstanceBox>() {
// 🔥 Usage prohibition guard - check if instance is finalized
if instance.is_finalized() {
return Err(RuntimeError::InvalidOperation {
@ -331,13 +331,13 @@ impl NyashInterpreter {
// 既存のthis.field値があればfini()を呼ぶ
if let Some(old_field_value) = instance.get_field(field) {
if let Some(old_instance) = old_field_value.as_any().downcast_ref::<InstanceBox>() {
if let Some(old_instance) = (*old_field_value).as_any().downcast_ref::<InstanceBox>() {
let _ = old_instance.fini();
finalization::mark_as_finalized(old_instance.box_id());
}
}
instance.set_field(field, val.clone_box())
instance.set_field(field, Arc::from(val.clone_box()))
.map_err(|e| RuntimeError::InvalidOperation { message: e })?;
Ok(val)
} else {
@ -354,7 +354,7 @@ impl NyashInterpreter {
message: "'this' is not bound in the current context".to_string(),
})?;
if let Some(instance) = (**me_value).as_any().downcast_ref::<InstanceBox>() {
if let Some(instance) = (*me_value).as_any().downcast_ref::<InstanceBox>() {
// 🔥 Usage prohibition guard - check if instance is finalized
if instance.is_finalized() {
return Err(RuntimeError::InvalidOperation {
@ -364,13 +364,13 @@ impl NyashInterpreter {
// 既存のme.field値があればfini()を呼ぶ
if let Some(old_field_value) = instance.get_field(field) {
if let Some(old_instance) = old_field_value.as_any().downcast_ref::<InstanceBox>() {
if let Some(old_instance) = (*old_field_value).as_any().downcast_ref::<InstanceBox>() {
let _ = old_instance.fini();
finalization::mark_as_finalized(old_instance.box_id());
}
}
instance.set_field(field, val.clone_box())
instance.set_field(field, Arc::from(val.clone_box()))
.map_err(|e| RuntimeError::InvalidOperation { message: e })?;
Ok(val)
} else {

View File

@ -201,7 +201,7 @@ impl EphemeralInstance {
let inst = parent.lock().unwrap();
if let Some(instance_box) = inst.as_any().downcast_ref::<InstanceBox>() {
if let Some(field_value) = instance_box.get_field(name) {
return Some(field_value);
return Some((*field_value).clone_box());
}
}
}

62
test_arc_mutex_bug.nyash Normal file
View File

@ -0,0 +1,62 @@
// 🔥 Arc<Mutex>状態共有破壊バグの最小再現テスト
static box Main {
init { console, server, result }
main() {
me.console = new ConsoleBox()
// 🎯 テスト1: SocketBox作成・bind・状態確認
me.console.log("=== Arc<Mutex>状態共有破壊バグ再現テスト ===")
// Step 1: SocketBox作成
me.server = new SocketBox()
me.console.log("1. SocketBox作成完了")
// Step 2: bind実行is_server = trueに設定されるはず
local bind_result
bind_result = me.server.bind("127.0.0.1", 18080)
me.console.log("2. bind完了, 結果: " + bind_result.toString())
// Step 3: 状態確認ここでclone()が発生する可能性)
local is_server_check1
is_server_check1 = me.server.isServer()
me.console.log("3. isServer()チェック1: " + is_server_check1.toString())
// Step 4: 変数再代入clone()確実に発生)
local server_copy
server_copy = me.server
me.console.log("4. サーバー変数コピー完了")
// Step 5: コピー後の状態確認
local is_server_check2
is_server_check2 = server_copy.isServer()
me.console.log("5. コピー後isServer()チェック2: " + is_server_check2.toString())
// Step 6: 元の変数での状態確認
local is_server_check3
is_server_check3 = me.server.isServer()
me.console.log("6. 元変数isServer()チェック3: " + is_server_check3.toString())
// 🔍 期待結果 vs 実際結果
me.console.log("")
me.console.log("=== 結果分析 ===")
me.console.log("期待結果: 全てtrueであるべきArc共有なら")
me.console.log("実際結果:")
me.console.log(" bind後: " + is_server_check1.toString())
me.console.log(" copy後: " + is_server_check2.toString())
me.console.log(" 元変数: " + is_server_check3.toString())
if is_server_check1.toString() == "true" and is_server_check2.toString() == "false" {
me.console.log("")
me.console.log("🔥 BUG CONFIRMED: clone()でArc共有が破壊されています")
me.result = "bug_confirmed"
} else {
me.console.log("")
me.console.log("✅ 予想外: 問題が修正されている可能性")
me.result = "unexpected_fix"
}
return me.result
}
}

7
test_basic_wasm.nyash Normal file
View File

@ -0,0 +1,7 @@
static box Main {
main() {
print("WASM Box Operations Test")
print(42 + 8)
return 50
}
}

14
test_box_creation.nyash Normal file
View File

@ -0,0 +1,14 @@
box SimpleBox {
init { value }
pack(v) {
me.value = v
}
}
static box Main {
main() {
local obj = new SimpleBox(100)
return 200
}
}

View File

@ -0,0 +1,63 @@
# 🔥 SocketBox完全デバッグトレース
# ファイルログ出力 + パーサーレベル追跡
static box Main {
init { console, server, result, debug_id }
main() {
me.console = new ConsoleBox()
me.debug_id = "TRACE_MAIN"
me.console.log("🔥 SocketBox完全デバッグトレース開始")
me.console.log("Debug ID: " + me.debug_id)
# Step 1: SocketBox作成
me.console.log("=== Step 1: SocketBox作成 ===")
me.server = new SocketBox()
me.console.log("✅ SocketBox作成完了")
me.console.log("作成されたSocketBox: " + me.server.toString())
# Step 2: 初期状態確認
me.console.log("=== Step 2: 初期状態確認 ===")
local initialState = me.server.isServer()
me.console.log("初期isServer状態: " + initialState.toString())
# Step 3: bind実行 (詳細ログ出力)
me.console.log("=== Step 3: bind実行 ===")
me.console.log("bind呼び出し前のSocketBox: " + me.server.toString())
local bindResult = me.server.bind("127.0.0.1", 18080)
me.console.log("bind戻り値: " + bindResult.toString())
# Step 4: bind後状態確認
me.console.log("=== Step 4: bind後状態確認 ===")
me.console.log("bind実行後のSocketBox: " + me.server.toString())
local postBindState = me.server.isServer()
me.console.log("bind後isServer状態: " + postBindState.toString())
# Step 5: 再確認テスト
me.console.log("=== Step 5: 再確認テスト ===")
local recheck1 = me.server.isServer()
local recheck2 = me.server.isServer()
me.console.log("再確認1: " + recheck1.toString())
me.console.log("再確認2: " + recheck2.toString())
# Step 6: 結果判定
me.console.log("=== Step 6: 結果判定 ===")
if postBindState.equals(true) {
me.result = "🎉 SUCCESS: 状態保持正常"
me.console.log(me.result)
} else {
me.result = "❌ FAILED: 状態保持失敗"
me.console.log(me.result)
me.console.log("bind結果: " + bindResult.toString())
me.console.log("期待値: true, 実際値: " + postBindState.toString())
}
# クリーンアップ
me.server.close()
me.console.log("🧹 クリーンアップ完了")
return me.result
}
}

44
test_detailed_debug.nyash Normal file
View File

@ -0,0 +1,44 @@
// 🔍 詳細デバッグテスト - Box IDとArcポインタ追跡
static box Main {
init { console, server }
main() {
me.console = new ConsoleBox()
me.console.log("=== 詳細デバッグ: Box ID & Arc ポインタ追跡 ===")
// Step 1: SocketBox作成直後
me.server = new SocketBox()
me.console.log("1. SocketBox作成直後:")
me.console.log(" Box toString: " + me.server.toString())
me.console.log(" isServer: " + me.server.isServer().toString())
// Step 2: bind実行
me.console.log("")
me.console.log("2. bind実行...")
local bind_result
bind_result = me.server.bind("127.0.0.1", 18080)
me.console.log(" bind結果: " + bind_result.toString())
// Step 3: bind直後の状態
me.console.log("")
me.console.log("3. bind直後:")
me.console.log(" Box toString: " + me.server.toString())
me.console.log(" isServer: " + me.server.isServer().toString())
// Step 4: 明示的な変数代入なし - 直接アクセス
me.console.log("")
me.console.log("4. 直接アクセス:")
me.console.log(" me.server.isServer(): " + me.server.isServer().toString())
// Step 5: 複数回連続アクセス
me.console.log("")
me.console.log("5. 複数回アクセス:")
me.console.log(" 1回目: " + me.server.isServer().toString())
me.console.log(" 2回目: " + me.server.isServer().toString())
me.console.log(" 3回目: " + me.server.isServer().toString())
return "debug_completed"
}
}

7
test_local_vars.nyash Normal file
View File

@ -0,0 +1,7 @@
static box Main {
main() {
local x = 10
local y = 20
return x + y
}
}

BIN
test_local_vars.wasm Normal file

Binary file not shown.

207
test_local_vars.wat Normal file
View File

@ -0,0 +1,207 @@
🌐 Nyash WASM Compiler - Processing file: test_local_vars.nyash 🌐
✅ WASM compilation completed successfully!
📄 Generated WAT:
(module
(import "env" "print" (func $print (param i32) ))
(memory (export "memory") 1)
(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)
nop
i32.const 10
local.set $0
i32.const 20
local.set $1
local.get $0
local.get $1
i32.add
local.set $2
local.get $2
return
)
(export "main" (func $main))
)

19
test_me_field_fix.nyash Normal file
View File

@ -0,0 +1,19 @@
static box Main {
init { server }
main() {
me.server = new SocketBox()
me.server.bind("127.0.0.1", 8080)
local result = me.server.isServer()
print("isServer result: " + result)
if (result) {
print("✅ me フィールドが正しく更新されています!")
} else {
print("❌ me フィールドが更新されていません")
}
return result
}
}

View File

@ -0,0 +1,19 @@
# 🔍 SocketBox最小テスト - メソッド呼び出しなし
static box Main {
init { console }
main() {
me.console = new ConsoleBox()
me.console.log("SocketBox最小テスト開始")
# SocketBox作成のみ
local socket = new SocketBox()
me.console.log("SocketBox作成完了")
# メソッド呼び出し一切なし
me.console.log("テスト完了")
return "SUCCESS_MINIMAL"
}
}

31
test_minimal_socket.nyash Normal file
View File

@ -0,0 +1,31 @@
# 🔥 最小限SocketBoxテスト - bind()のみ
static box Main {
init { console }
main() {
me.console = new ConsoleBox()
me.console.log("最小限SocketBoxテスト開始")
# SocketBox作成
local socket = new SocketBox()
me.console.log("SocketBox作成完了")
# bind前状態
local beforeBind = socket.isServer()
me.console.log("Before: " + beforeBind.toString())
# bind実行
local bindResult = socket.bind("127.0.0.1", 19999)
me.console.log("Bind: " + bindResult.toString())
# bind後状態
local afterBind = socket.isServer()
me.console.log("After: " + afterBind.toString())
# クリーンアップ
socket.close()
return "DONE"
}
}

30
test_no_isserver.nyash Normal file
View File

@ -0,0 +1,30 @@
# 🔍 isServer()を使わないテスト - 問題箇所特定
static box Main {
init { console }
main() {
me.console = new ConsoleBox()
me.console.log("isServer()なしテスト開始")
# SocketBox作成
local socket = new SocketBox()
me.console.log("SocketBox作成完了")
# toString()テストisServer()を内部で呼んでいるかも)
me.console.log("toString()テスト開始")
local socketStr = socket.toString()
me.console.log("SocketBox: " + socketStr)
# bind実行isServer()を呼ばずに)
me.console.log("bind実行開始")
local bindResult = socket.bind("127.0.0.1", 19999)
me.console.log("Bind結果: " + bindResult.toString())
# クリーンアップ
socket.close()
me.console.log("テスト完了")
return "SUCCESS_NO_ISSERVER"
}
}

10
test_normal_field.nyash Normal file
View File

@ -0,0 +1,10 @@
static box Main {
init { obj }
main() {
me.obj = new StringBox("test")
local result = me.obj.length()
print(result)
return result
}
}

5
test_numeric_wasm.nyash Normal file
View File

@ -0,0 +1,5 @@
static box Main {
main() {
return 42 + 8
}
}

View File

@ -0,0 +1,63 @@
# 🔍 他のBox動作確認 - SocketBoxとの比較分析
# 正常に動作するBoxの状態保持を検証
static box Main {
init { console, result }
main() {
me.console = new ConsoleBox()
me.console.log("🔍 他のBox動作確認テスト開始")
# ===== MapBox状態テスト =====
me.console.log("=== MapBox状態テスト ===")
local testMap = new MapBox()
me.console.log("MapBox作成: " + testMap.toString())
testMap.set("key1", "value1")
local getValue = testMap.get("key1")
me.console.log("MapBox set/get: " + getValue.toString())
# ===== ArrayBox状態テスト =====
me.console.log("=== ArrayBox状態テスト ===")
local testArray = new ArrayBox()
me.console.log("ArrayBox作成: " + testArray.toString())
testArray.push("item1")
local arraySize = testArray.size()
me.console.log("ArrayBox push/size: " + arraySize.toString())
# ===== MathBox状態テスト =====
me.console.log("=== MathBox状態テスト ===")
local testMath = new MathBox()
me.console.log("MathBox作成: " + testMath.toString())
local mathResult = testMath.add(5, 3)
me.console.log("MathBox add: " + mathResult.toString())
# ===== SocketBox状態テスト問題箇所 =====
me.console.log("=== SocketBox状態テスト問題箇所 ===")
local testSocket = new SocketBox()
me.console.log("SocketBox作成: " + testSocket.toString())
local beforeBind = testSocket.isServer()
me.console.log("Before bind: isServer = " + beforeBind.toString())
local bindResult = testSocket.bind("127.0.0.1", 18080)
me.console.log("Bind result = " + bindResult.toString())
local afterBind = testSocket.isServer()
me.console.log("After bind: isServer = " + afterBind.toString())
testSocket.close()
# ===== 結果判定 =====
if afterBind.equals(true) {
me.result = "SocketBox正常動作"
} else {
me.result = "SocketBox状態保持失敗 - 他のBoxは正常"
}
me.console.log("🎯 テスト結果: " + me.result)
return me.result
}
}

View File

@ -0,0 +1,47 @@
# test_other_boxes_working.nyash
# ✅ 他のBox型正常動作確認SocketBoxとの対比
static box Main {
init { console, results }
main() {
me.console = new ConsoleBox()
me.console.log("✅ 他のBox正常動作確認テスト開始")
me.results = new ArrayBox()
# Test 1: ArrayBox正常動作確認
me.console.log("Test 1: ArrayBox...")
local array = new ArrayBox()
array.push("test_item")
local arraySize = array.size()
me.console.log("✅ ArrayBox正常: size=" + arraySize.toString())
me.results.push("ArrayBox:OK")
# Test 2: MapBox正常動作確認
me.console.log("Test 2: MapBox...")
local map = new MapBox()
map.set("test_key", "test_value")
local mapValue = map.get("test_key")
me.console.log("✅ MapBox正常: value=" + mapValue.toString())
me.results.push("MapBox:OK")
# Test 3: IntegerBox正常動作確認
me.console.log("Test 3: IntegerBox...")
local num = new IntegerBox(42)
local numStr = num.toString()
me.console.log("✅ IntegerBox正常: " + numStr)
me.results.push("IntegerBox:OK")
# Test 4: StringBox正常動作確認
me.console.log("Test 4: StringBox...")
local str = new StringBox("Hello")
local strLen = str.length()
me.console.log("✅ StringBox正常: length=" + strLen.toString())
me.results.push("StringBox:OK")
local totalResults = me.results.size()
me.console.log("🎉 他のBox全て正常動作: " + totalResults.toString() + "件成功")
return "OTHER_BOXES_ALL_OK"
}
}

47
test_runner.js Normal file
View File

@ -0,0 +1,47 @@
// Node.js用WASM実行テストランナー
const fs = require('fs');
async function runWasm() {
try {
// WASMバイナリ読み込み
const wasmBuffer = fs.readFileSync('test_local_vars.wasm');
// Import関数定義
const importObject = {
env: {
print: (value) => {
console.log(`WASM print: ${value}`);
}
}
};
// WASM インスタンス作成・実行
const wasmModule = await WebAssembly.instantiate(wasmBuffer, importObject);
console.log('🌐 WASM module loaded successfully!');
// main関数実行
const startTime = performance.now();
const result = wasmModule.instance.exports.main();
const endTime = performance.now();
console.log(`🏆 WASM Execution Result: ${result}`);
console.log(`⚡ WASM Execution Time: ${(endTime - startTime).toFixed(3)} ms`);
return {
result: result,
executionTime: endTime - startTime
};
} catch (error) {
console.error('❌ WASM execution error:', error);
return null;
}
}
// 実行
runWasm().then(result => {
if (result) {
console.log(`✅ Test completed - Result: ${result.result}, Time: ${result.executionTime.toFixed(3)}ms`);
}
});

View File

@ -0,0 +1,34 @@
# 🔥 SocketBox bind()のみテスト - toString()なし
static box Main {
init { console, result }
main() {
me.console = new ConsoleBox()
me.console.log("SocketBox bind()テスト開始")
# SocketBox作成
local socket = new SocketBox()
me.console.log("SocketBox作成完了")
# bind実行toString()やisServer()を避ける)
me.console.log("bind実行開始...")
local bindResult = socket.bind("127.0.0.1", 19999)
me.console.log("bind実行完了")
# bindResultの状態だけ確認
if bindResult.equals(true) {
me.result = "BIND_SUCCESS"
me.console.log("bind成功!")
} else {
me.result = "BIND_FAILED"
me.console.log("bind失敗!")
}
# クリーンアップ
socket.close()
me.console.log("テスト完了")
return me.result
}
}

View File

@ -0,0 +1,21 @@
# test_socket_deadlock_minimal.nyash
# 🚨 Issue #76: SocketBoxデッドロック最小再現ケース
static box Main {
init { console }
main() {
me.console = new ConsoleBox()
me.console.log("🔥 SocketBoxデッドロック最小テスト開始")
local socket = new SocketBox()
me.console.log("✅ SocketBox作成成功")
# ここで無限ブロック予想
me.console.log("bind()実行開始...")
local result = socket.bind("127.0.0.1", 19999)
me.console.log("❌ この行は出力されない(デッドロック)")
return "SHOULD_NOT_REACH"
}
}

View File

@ -0,0 +1,42 @@
# test_socket_methods_comprehensive.nyash
# 🚨 Issue #76: SocketBox全メソッドデッドロック確認
static box Main {
init { console, results }
main() {
me.console = new ConsoleBox()
me.console.log("🔥 SocketBox全メソッドテスト開始")
me.results = new ArrayBox()
local socket = new SocketBox()
me.console.log("✅ SocketBox作成完了")
# Test 1: toString() メソッド
me.console.log("Test 1: toString()実行...")
local socketStr = socket.toString() # デッドロック予想
me.console.log("❌ toString()完了: " + socketStr)
me.results.push("toString:OK")
# Test 2: isServer() メソッド
me.console.log("Test 2: isServer()実行...")
local isServer = socket.isServer() # デッドロック予想
me.console.log("❌ isServer()完了: " + isServer.toString())
me.results.push("isServer:OK")
# Test 3: bind() メソッド
me.console.log("Test 3: bind()実行...")
local bindResult = socket.bind("127.0.0.1", 19999) # デッドロック予想
me.console.log("❌ bind()完了: " + bindResult.toString())
me.results.push("bind:OK")
# Test 4: close() メソッド
me.console.log("Test 4: close()実行...")
local closeResult = socket.close() # デッドロック予想
me.console.log("❌ close()完了: " + closeResult.toString())
me.results.push("close:OK")
me.console.log("🎉 全テスト完了: " + me.results.size().toString() + "件成功")
return "ALL_METHODS_OK"
}
}

View File

@ -0,0 +1,42 @@
# PR #75 SocketBox状態保持テスト
# Arc<dyn NyashBox>修正効果の検証
static box Main {
init { console, server, result }
main() {
me.console = new ConsoleBox()
me.console.log("🔥 SocketBox状態保持テスト開始")
# SocketBox作成
me.server = new SocketBox()
me.console.log("✅ SocketBox作成完了")
# bind前のisServer確認
local isServerBefore = me.server.isServer()
me.console.log("Before bind: isServer = " + isServerBefore.toString())
# bind実行状態設定
local bindResult = me.server.bind("127.0.0.1", 18080)
me.console.log("Bind result = " + bindResult.toString())
# bind後のisServer確認🎯 重要これがtrueになるべき
local isServerAfter = me.server.isServer()
me.console.log("After bind: isServer = " + isServerAfter.toString())
# テスト結果判定
if isServerAfter.equals(true) {
me.console.log("🎉 SUCCESS: SocketBox状態保持修正完了!")
me.result = "PASS: State preservation works"
} else {
me.console.log("❌ FAILED: SocketBox状態が失われている")
me.result = "FAIL: State preservation broken"
}
# クリーンアップ
me.server.close()
me.console.log("🧹 SocketBox closed")
return me.result
}
}

7
test_wasm_box_ops.nyash Normal file
View File

@ -0,0 +1,7 @@
static box Main {
main() {
local obj = new DataBox(42)
print(obj.value)
return obj.value
}
}

10
test_with_local.nyash Normal file
View File

@ -0,0 +1,10 @@
static box Main {
init { result }
main() {
local x = 10
local y = 20
me.result = x + y
return me.result
}
}