fix(joinir): Phase 241-EX - Remove hardcoded 'sum' check from Pattern3
Remove legacy hardcoded 'sum' carrier validation that was blocking array_filter patterns with different accumulator names (e.g., 'out'). Before: Pattern3 required carrier named 'sum' to exist After: Pattern3 uses carrier_info generically (any carrier name works) Test results: - phase49_joinir_array_filter_smoke: PASS ✅ - phase49_joinir_array_filter_fallback: PASS ✅ - phase49_joinir_array_filter_ab_comparison: PASS ✅ - Full suite: 909/909 PASS, 0 FAIL Also: Archive old roadmap documentation (67k lines moved to docs/archive/) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -1,241 +0,0 @@
|
||||
# 🌟 Nyash アーキテクチャ再設計提案
|
||||
|
||||
*by Codex exec (2025-08-21)*
|
||||
|
||||
## 🎯 核心的洞察
|
||||
|
||||
**「実装詳細共有」から「モデル共有・実行時共有」への転換**
|
||||
|
||||
現在の問題の本質は、InterpreterとVMが「実装詳細」を共有しようとしていること。正しいアプローチは「モデル(宣言)」と「ランタイム(実行環境)」を共有し、実行戦略だけを分離すること。
|
||||
|
||||
## 🏗️ 新アーキテクチャ層構造
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ AST/Model │ ← 純粋なデータモデル(依存なし)
|
||||
└──────┬──────┘
|
||||
│
|
||||
┌──────▼──────┐
|
||||
│ Runtime │ ← 型システム・クラス管理・インスタンス生成
|
||||
└──────┬──────┘
|
||||
│
|
||||
┌──────┴──────┬──────────┬────────────┐
|
||||
│ Interpreter │ VM │ Plugins │
|
||||
└─────────────┴──────────┴────────────┘
|
||||
```
|
||||
|
||||
### 各層の責務
|
||||
|
||||
**AST/Model層**
|
||||
- 言語の純データモデル
|
||||
- BoxDeclaration、ASTNode、型シグネチャ
|
||||
- 実行時情報を含まない
|
||||
|
||||
**Runtime層**
|
||||
- BoxClass/BoxFactoryによる型システム
|
||||
- インスタンス生成とライフサイクル管理
|
||||
- メソッドディスパッチと呼び出し規約
|
||||
|
||||
**Backend層**
|
||||
- Interpreter: AST直接実行
|
||||
- VM: MIR/Bytecode実行
|
||||
- 両者ともRuntimeを通じてBoxを操作
|
||||
|
||||
## 🔧 具体的な設計
|
||||
|
||||
### 1. BoxDeclarationの移動
|
||||
|
||||
```rust
|
||||
// core::model::box_declaration.rs
|
||||
pub struct BoxDeclaration {
|
||||
pub name: String,
|
||||
pub type_params: Vec<TypeParam>,
|
||||
pub fields: Vec<FieldDecl>,
|
||||
pub methods: Vec<MethodDecl>,
|
||||
pub static_methods: Vec<StaticDecl>,
|
||||
pub attrs: AttrSet,
|
||||
pub source_span: Option<Span>,
|
||||
}
|
||||
|
||||
pub struct FieldDecl {
|
||||
pub name: String,
|
||||
pub ty: TypeRef,
|
||||
pub attrs: AttrSet,
|
||||
}
|
||||
|
||||
pub struct MethodDecl {
|
||||
pub name: String,
|
||||
pub sig: FnSig,
|
||||
pub body: FnBodyRef, // AST or MIR reference
|
||||
}
|
||||
```
|
||||
|
||||
### 2. NyashRuntimeの導入
|
||||
|
||||
```rust
|
||||
// runtime::mod.rs
|
||||
pub struct NyashRuntime {
|
||||
box_registry: BoxRegistry,
|
||||
type_space: TypeSpace,
|
||||
fn_space: FnSpace,
|
||||
}
|
||||
|
||||
pub struct ExecutionSession {
|
||||
runtime: Arc<NyashRuntime>,
|
||||
root_box: SharedBox,
|
||||
frames: Vec<Frame>,
|
||||
env: Environment,
|
||||
}
|
||||
|
||||
// SharedBox = Arc<dyn NyashBox>
|
||||
pub type SharedBox = Arc<dyn NyashBox>;
|
||||
```
|
||||
|
||||
### 3. BoxClass/Factoryシステム
|
||||
|
||||
```rust
|
||||
// runtime::box_class.rs
|
||||
pub trait BoxClass: Send + Sync {
|
||||
fn name(&self) -> &str;
|
||||
fn instantiate(
|
||||
&self,
|
||||
args: &[SharedBox],
|
||||
sess: &mut ExecutionSession
|
||||
) -> Result<SharedBox>;
|
||||
fn lookup_method(&self, name: &str) -> Option<MethodHandle>;
|
||||
fn lifecycle(&self) -> Option<&dyn BoxLifecycle>;
|
||||
}
|
||||
|
||||
pub trait BoxFactory: Send + Sync {
|
||||
fn can_build(&self, decl: &BoxDeclaration) -> bool;
|
||||
fn build_class(
|
||||
&self,
|
||||
decl: &BoxDeclaration,
|
||||
rt: &NyashRuntime
|
||||
) -> Result<Arc<dyn BoxClass>>;
|
||||
}
|
||||
|
||||
pub trait BoxLifecycle {
|
||||
fn on_birth(&self, ctx: &mut InstanceCtx) -> Result<()>;
|
||||
fn on_fini(&self, ctx: &mut InstanceCtx);
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 統一されたBox管理
|
||||
|
||||
```rust
|
||||
// runtime::registry.rs
|
||||
pub struct BoxRegistry {
|
||||
classes: RwLock<HashMap<String, Arc<dyn BoxClass>>>,
|
||||
factories: RwLock<Vec<Arc<dyn BoxFactory>>>,
|
||||
}
|
||||
|
||||
impl BoxRegistry {
|
||||
pub fn register_class(&self, class: Arc<dyn BoxClass>) {
|
||||
// 登録処理
|
||||
}
|
||||
|
||||
pub fn get_class(&self, name: &str) -> Option<Arc<dyn BoxClass>> {
|
||||
// クラス取得
|
||||
}
|
||||
|
||||
pub fn create_instance(
|
||||
&self,
|
||||
class_name: &str,
|
||||
args: &[SharedBox],
|
||||
sess: &mut ExecutionSession
|
||||
) -> Result<SharedBox> {
|
||||
let class = self.get_class(class_name)?;
|
||||
class.instantiate(args, sess)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📋 実装手順(最小破壊的移行)
|
||||
|
||||
### Step 1: BoxDeclarationの移動
|
||||
```rust
|
||||
// 1. core::model モジュールを作成
|
||||
// 2. BoxDeclarationを移動
|
||||
// 3. インタープリターで一時的に別名を使用
|
||||
use core::model::BoxDeclaration as InterpreterBoxDecl;
|
||||
```
|
||||
|
||||
### Step 2: NyashRuntimeの骨組み作成
|
||||
```rust
|
||||
// 最初は空の実装から始める
|
||||
pub struct NyashRuntime {
|
||||
// 段階的に追加
|
||||
}
|
||||
|
||||
pub struct NyashRuntimeBuilder {
|
||||
// SharedStateからの移行を支援
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: BoxFactoryのdyn化
|
||||
```rust
|
||||
// 現在の trait BoxFactory を使用
|
||||
// すべて Arc<dyn BoxFactory> として扱う
|
||||
```
|
||||
|
||||
### Step 4: グローバル登録の排除
|
||||
```rust
|
||||
// 削除: register_user_defined_factory(...)
|
||||
// 追加: NyashRuntimeBuilder::with_factory(...)
|
||||
```
|
||||
|
||||
### Step 5: SharedStateの段階的分解
|
||||
```rust
|
||||
// 一時的なシム
|
||||
pub struct SharedStateShim {
|
||||
runtime: Arc<NyashRuntime>,
|
||||
session: ExecutionSession,
|
||||
}
|
||||
|
||||
// 互換性のためのFrom実装
|
||||
impl From<SharedState> for SharedStateShim {
|
||||
// 移行ロジック
|
||||
}
|
||||
```
|
||||
|
||||
### Step 6-8: 統一と最適化
|
||||
- Interpreter/VMのコンストラクタ統一
|
||||
- birth/finiライフサイクルの一元化
|
||||
- 最終的なSharedState削除
|
||||
|
||||
## 🎯 得られる利点
|
||||
|
||||
1. **依存関係の明確化**
|
||||
- VM→Interpreter依存が完全に解消
|
||||
- 両者はRuntimeのみに依存
|
||||
|
||||
2. **テスタビリティ向上**
|
||||
- グローバル状態なし
|
||||
- 並行テスト可能
|
||||
|
||||
3. **保守性向上**
|
||||
- 責務が明確に分離
|
||||
- 新しいBackend追加が容易
|
||||
|
||||
4. **Everything is Box哲学の貫徹**
|
||||
- 統一的なBox管理
|
||||
- birth/finiライフサイクルの一元化
|
||||
|
||||
## ⚠️ 実装上の注意点
|
||||
|
||||
1. **trait objectは必ず`Arc<dyn Trait>`**
|
||||
- `Arc<Trait>`は使わない
|
||||
- dynキーワードを忘れない
|
||||
|
||||
2. **段階的移行**
|
||||
- 各ステップでテストが通ることを確認
|
||||
- 互換性レイヤーを活用
|
||||
|
||||
3. **ロックの最小化**
|
||||
- Runtimeは基本的に不変
|
||||
- 必要最小限のRwLock使用
|
||||
|
||||
---
|
||||
|
||||
この設計により、Nyashはよりシンプルでエレガントなアーキテクチャとなり、InterpreterとVMの統合が自然に実現されます。
|
||||
@ -1,5 +1,8 @@
|
||||
# Comprehensive Rust Code Refactoring Discovery
|
||||
|
||||
Status: Active
|
||||
Scope: Rust コード全体のリファクタリング候補を洗い出した調査結果の現行まとめ(2025-12-05 時点)。
|
||||
|
||||
**Date**: 2025-12-05
|
||||
**Scope**: Entire `/home/tomoaki/git/hakorune-selfhost/src` directory
|
||||
**Methodology**: Line count + complexity analysis + activity analysis + Phase 188 context
|
||||
|
||||
@ -1,77 +0,0 @@
|
||||
# Nyash Concurrency — Box Model (Proposal, docs-only)
|
||||
|
||||
Status: design-only during the feature‑pause. No runtime or spec changes. Implement after Mini‑VM baseline is stable.
|
||||
|
||||
Intent
|
||||
- Bring Go-like CSP (goroutine/channels/select) into Nyash via “Everything is Box”.
|
||||
- Keep semantics explicit, lifecycle safe (birth/fini), and observable. Phase-in from userland → runtime.
|
||||
|
||||
Scope (Phase‑0: userland MVP)
|
||||
- RoutineBox: lightweight task wrapper over `nowait` (state, join/cancel, status).
|
||||
- ChannelBox: bounded/unbounded queue + blocking/non-blocking ops + close semantics.
|
||||
- SelectBox: multi-channel wait (first-ready) with simple fairness.
|
||||
- RoutineScopeBox: structured concurrency; children are canceled on scope fini.
|
||||
- Observability: JSONL trace toggled by `NYASH_CONC_TRACE=1`.
|
||||
|
||||
Non‑Goals (Phase‑0)
|
||||
- M:N scheduler, OS-level park/unpark, net poller integration (deferred to Phase‑2 runtime work).
|
||||
|
||||
API Sketch (userland)
|
||||
- RoutineBox
|
||||
- birth(fn)
|
||||
- start(): Void
|
||||
- join(timeout_ms?: Int) -> Bool // true if joined; false on timeout
|
||||
- cancel(): Void
|
||||
- status() -> String // ready|running|done|canceled|error
|
||||
- ChannelBox(capacity: Int=0)
|
||||
- send(v): Void // blocks if full (Phase‑0: simulated park)
|
||||
- try_send(v) -> Bool
|
||||
- receive() -> Any // blocks if empty (Phase‑0: simulated park)
|
||||
- try_receive() -> (Bool, Any?)
|
||||
- receive_timeout(ms: Int) -> (Bool, Any?)
|
||||
- close(): Void // further send fails; recv drains until empty then End
|
||||
- SelectBox
|
||||
- birth()
|
||||
- when(ch: ChannelBox, handler: Fn): Void
|
||||
- await() -> Bool // returns after one handler runs; false if none ready and no wait policy
|
||||
- await_timeout(ms: Int) -> Bool
|
||||
- RoutineScopeBox
|
||||
- birth()
|
||||
- spawn(fn) -> RoutineBox
|
||||
- fini() // cancels pending routines and waits boundedly
|
||||
|
||||
Semantics
|
||||
- Capacity:
|
||||
- 0: rendezvous channel (send/recv rendezvous).
|
||||
- N>0: bounded ring buffer.
|
||||
- Close:
|
||||
- close() marks channel as closed. send() after close -> error. receive() returns buffered items; when empty -> (false, End) style result; exact return shape defined per API.
|
||||
- Blocking:
|
||||
- Phase‑0 userland uses cooperative wait queues; no busy loops. try_* and timeout variants provided.
|
||||
- Select fairness:
|
||||
- If multiple ready, choose random/round‑robin. Starvation avoidance is a design requirement; precise algorithm can evolve.
|
||||
- Types:
|
||||
- `TypedChannelBox<T>` is a future extension; Phase‑0 uses runtime tags/guards documented in reference.
|
||||
- Cancellation:
|
||||
- RoutineScopeBox cancels children on fini; Channel waits should return (canceled) promptly.
|
||||
|
||||
Phases
|
||||
- Phase‑0 (userland MVP / PyVM first)
|
||||
- Implement the 4 boxes above with minimal queues/waits, plus trace hooks.
|
||||
- Smokes: ping‑pong, bounded producer/consumer, two‑way select, close semantics, scope cancel.
|
||||
- Phase‑1 (park/unpark abstraction)
|
||||
- Introduce `WaiterBox`/`CondBox` that map to efficient OS waits where available. Keep same APIs.
|
||||
- Phase‑2 (runtime integration)
|
||||
- Scheduler (M:N), GC and net poller integration, fairness and profiling. Keep Box APIs stable.
|
||||
|
||||
Observability
|
||||
- `NYASH_CONC_TRACE=1` → JSONL events: spawn/join/cancel/send/recv/park/unpark/select/close with routine IDs, channel IDs, timestamps.
|
||||
|
||||
Safety & Diagnostics
|
||||
- Deadlock hints: trace dependent waits; optional detector (dev only) can dump wait‑for graph.
|
||||
- API contracts explicitly define error return for misuse (send on closed, double close, etc.).
|
||||
|
||||
Deliverables (docs‑only during the feature‑pause)
|
||||
- This proposal (boxes & semantics).
|
||||
- Reference page with blocking/close/select rules (see reference/concurrency/semantics.md).
|
||||
- Test plan with named smokes and expected outputs.
|
||||
@ -1,158 +0,0 @@
|
||||
# 純粋関数型[]ブロック vs 通常{}ブロック設計案
|
||||
|
||||
## 概要
|
||||
|
||||
Nyashにおける**{}ローカルスコープ**と**[]純粋スコープ**の明確な差別化設計。
|
||||
「すべてはBox」哲学の中で、副作用を含む通常処理と純粋関数型処理を共存させる革命的アプローチ。
|
||||
|
||||
## 基本的な差別化
|
||||
|
||||
### {}ブロック(既存)- 通常のNyashスコープ
|
||||
```nyash
|
||||
{
|
||||
local counter = new IntegerBox(0) // Box生成OK
|
||||
counter.set(counter.get() + 1) // 副作用OK
|
||||
SomeGlobalBox.modify() // 外部状態変更OK
|
||||
ChannelBox.send("data") // I/O副作用OK
|
||||
// 普通のNyash文法、制約なし
|
||||
}
|
||||
```
|
||||
|
||||
### []ブロック(提案)- 純粋関数型スコープ
|
||||
```nyash
|
||||
[
|
||||
// コンパイラが以下を厳密にチェック:
|
||||
input.map(x => x * 2) // ✅ 純粋変換のみ
|
||||
.filter(x => x > 10) // ✅ 副作用なし
|
||||
.reduce((a, b) => a + b, 0) // ✅ 参照透過性保証
|
||||
|
||||
// 以下はコンパイルエラー:
|
||||
// SomeBox.mutate() // ❌ 外部状態変更禁止
|
||||
// print("debug") // ❌ I/O副作用禁止
|
||||
// local x = 1; x = 2 // ❌ 変数再代入禁止
|
||||
]
|
||||
```
|
||||
|
||||
## 深い差別化ポイント
|
||||
|
||||
### 1. コンパイラレベルの制約
|
||||
- **{}**: 制約なし、通常のNyash文法
|
||||
- **[]**: 厳密な純粋性チェック、副作用検出でコンパイルエラー
|
||||
|
||||
### 2. メモリモデル
|
||||
- **{}**: 新しいBoxの生成・変更可能
|
||||
- **[]**: 既存データの変換のみ、新しい状態作成禁止
|
||||
|
||||
### 3. 並行安全性
|
||||
- **{}**: データ競合の可能性あり
|
||||
- **[]**: 副作用なしなので自動的にthread-safe
|
||||
|
||||
### 4. 最適化
|
||||
- **{}**: 通常の最適化
|
||||
- **[]**: コンパイラが大胆な最適化可能(純粋性保証されているため)
|
||||
|
||||
### 5. デバッグ性
|
||||
- **{}**: 通常のデバッガ
|
||||
- **[]**: 入力→出力のみ追跡すればOK、デバッグ超簡単
|
||||
|
||||
## 実用的な使い分け例
|
||||
|
||||
```nyash
|
||||
box DataProcessor {
|
||||
processData(input: ArrayBox) -> ArrayBox {
|
||||
// 通常の{}スコープ: 準備・後処理
|
||||
{
|
||||
local logger = new LoggerBox()
|
||||
logger.info("Processing started")
|
||||
|
||||
// 純粋な[]スコープ: コア計算
|
||||
local result = [
|
||||
input
|
||||
.filter(x => x > 0)
|
||||
.map(x => Math.sqrt(x))
|
||||
.sort()
|
||||
]
|
||||
|
||||
logger.info("Processing completed")
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## []ブロックの真の価値
|
||||
|
||||
### 1. 数学的証明可能性
|
||||
[]内の処理は数学的に証明できる
|
||||
|
||||
### 2. 完全な再現性
|
||||
同じ入力→必ず同じ出力
|
||||
|
||||
### 3. 並列化自動最適化
|
||||
コンパイラが自動で並列化可能
|
||||
|
||||
### 4. ホットスワップ可能
|
||||
実行中でも[]部分だけ安全に入れ替え可能
|
||||
|
||||
## Box化による実装戦略
|
||||
|
||||
### PureCalculatorBox例
|
||||
```nyash
|
||||
box PureCalculatorBox {
|
||||
birth() { /* 状態なし、初期化も最小限 */ }
|
||||
|
||||
calculate(input: ArrayBox) -> ArrayBox {
|
||||
// []ブロックを使って、純粋性を言語レベルで保証
|
||||
local result = [
|
||||
input.map(x => x * 2).filter(x => x > 10)
|
||||
]
|
||||
return result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### コンパイラもBox化
|
||||
「[]だけ解析する箱をつくる」アプローチ:
|
||||
- `PurityCheckerBox`: []ブロックの純粋性を厳密チェック
|
||||
- `ParserBox`: []専用構文解析
|
||||
- `OptimizerBox`: []専用最適化
|
||||
|
||||
## 哲学的統合
|
||||
|
||||
### {}ブロックと[]ブロックの共存
|
||||
- **{}**: "現実世界とのインターフェース"(副作用、状態管理)
|
||||
- **[]**: "純粋な計算の核心"(ロジック、変換、計算)
|
||||
|
||||
この差別化により、Nyashは:
|
||||
- **実用性** ({}での柔軟な状態管理)
|
||||
- **数学的美しさ** ([]での純粋性)
|
||||
|
||||
という**矛盾する要求を同時に満たす**ことができる。
|
||||
|
||||
## 「すべてはBox」哲学との整合性
|
||||
|
||||
これは「すべてはBox」哲学を破るのではなく、**異なる種類のBox(副作用Box vs 純粋Box)を明確に分離**する革命的なアプローチ。
|
||||
|
||||
- 副作用のあるBoxは{}内で使用
|
||||
- 純粋なBoxは[]内で使用
|
||||
- それぞれのBoxが適切なスコープで最大限の力を発揮
|
||||
|
||||
## 実装上の課題と解決策
|
||||
|
||||
### 課題
|
||||
1. コンパイラの複雑性増加
|
||||
2. []と{}間のデータやり取り
|
||||
3. エラーメッセージの分かりやすさ
|
||||
|
||||
### 解決策
|
||||
1. Box化されたコンパイラ(PurityCheckerBox等)で複雑性を分離
|
||||
2. 明確なデータ変換API([]→{}は常に安全、{}→[]は純粋性チェック)
|
||||
3. 文脈に応じた専用エラーメッセージ
|
||||
|
||||
## 結論
|
||||
|
||||
この設計により、Nyashは純粋関数型プログラミングの利点を享受しつつ、実用的な副作用処理も自然に行える、世界初の「ハイブリッド純粋言語」となる可能性がある。
|
||||
|
||||
**Date**: 2025-09-22
|
||||
**Status**: アイデア段階
|
||||
**Priority**: Phase 16以降での検討推奨
|
||||
@ -1,40 +0,0 @@
|
||||
# CAX (C-ABI Explorer) - Revolutionary Debugging Tool
|
||||
|
||||
**Status**: Post‑Bootstrap Implementation (Core Idea Complete)
|
||||
**Priority**: High (World-First Tool)
|
||||
**Origin**: 1-minute inspiration (C ABI dynamic → C ABI Debugger)
|
||||
**Date**: 2025-09-21
|
||||
|
||||
## 🌟 Core Concept
|
||||
|
||||
C-ABI境界デバッグのGUIツール。**「ぽいっと付け外し」「視覚的ログ監視」「マクロ自動化」「ホットスワップ」**を実現。
|
||||
|
||||
### Revolutionary Aspects
|
||||
- **Nyash箱理論**でC境界を完全トレース
|
||||
- **Record/Replay**で回帰テスト・CI再現性
|
||||
- **GUI Explorer**でプラグイン管理
|
||||
- **Type Safety**境界での型検証・所有権チェック
|
||||
|
||||
## 📁 Files Structure
|
||||
|
||||
- `gemini-ipc-implementation.hako` - Geminiの172行実装コード
|
||||
- `chatgpt-design-spec.md` - ChatGPTの設計仕様
|
||||
- `inspiration-process.md` - 1分発想プロセスの記録
|
||||
- `technical-roadmap.md` - 実装ロードマップ(2週間MVP)
|
||||
|
||||
## 🎯 Implementation Priority
|
||||
|
||||
**Phase 1** (Post Mini-VM): IPC層 + Timeline GUI
|
||||
**Phase 2**: Record/Replay + Hot-swap
|
||||
**Phase 3**: Advanced Analytics + 可視化
|
||||
|
||||
## 💡 Technical Innovation
|
||||
|
||||
- **境界フック**: PluginHost.Invoke 層で完全インターセプト
|
||||
- **統一観測**: すべてのBoxで統一されたイベントログ
|
||||
- **型安全**: TypeBox境界での実時間検証
|
||||
- **構造化**: RoutineBox/ChannelBox での並行デバッグ
|
||||
|
||||
---
|
||||
|
||||
**Note**: このアイデアは、C ABI動的呼び出しからわずか1分で到達した革新的発想の記録です。
|
||||
@ -1,145 +0,0 @@
|
||||
# CAX Design Specification (ChatGPT Analysis)
|
||||
|
||||
**Generated by**: ChatGPT
|
||||
**Date**: 2025-09-21
|
||||
**Context**: 30分集中設計セッション
|
||||
|
||||
## 🎯 Core Vision
|
||||
|
||||
**Nyash C-ABI Explorer (CAX)** - GUIでC ABI境界を「ぽいっと付け外し」「視覚化」「録って再生」「スクリプトで自動化」
|
||||
|
||||
## 🏗️ Architecture Design
|
||||
|
||||
### Core + GUI 分離アーキテクチャ
|
||||
```
|
||||
Core (Rust/Nyash): 既存cabi-debuggerフック + IPCサーバ
|
||||
↕ JSON-RPC/WebSocket
|
||||
GUI (Tauri/Electron): Svelte/React/TypeScript フロントエンド
|
||||
```
|
||||
|
||||
### データフロー
|
||||
```
|
||||
PluginHost.Invoke → CABIDebugger → IPC → GUI Timeline
|
||||
C ABI Calls → Real-time Logs → JSON Stream → 可視化
|
||||
```
|
||||
|
||||
## 🎨 UX Design
|
||||
|
||||
### 画面レイアウト (5パネル構成)
|
||||
```
|
||||
┌─────────────┬─────────────────┬─────────────┐
|
||||
│ Explorer │ Live Timeline │ Inspector │
|
||||
│ (attach/detach) │ (call flow) │ (call details)│
|
||||
├─────────────┴─────────────────┴─────────────┤
|
||||
│ Record/Replay Controls │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ Console & Macros (Scripts) │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 操作体験
|
||||
1. **1クリック Attach**: `map.so` の行をクリック→即時ログ流れる
|
||||
2. **色分け表示**: 緑=Ok、黄=by-name、赤=Err/timeout、紫=ownership警告
|
||||
3. **録画/再生**: ワンボタンでJSONL/TLV保存→プラグイン無しで再現
|
||||
4. **ホットスワップ**: `disable→quiesce→reload` をGUIウィザードで
|
||||
|
||||
## 🔧 Technical Features
|
||||
|
||||
### 1. Real-time Monitoring
|
||||
- **Live Timeline**: Swimlane(プラグイン別/スレッド別)
|
||||
- **Call Inspector**: 引数/戻り値/実行時間/ソース位置
|
||||
- **Filter System**: `outcome:warn plugin:map` 形式
|
||||
|
||||
### 2. Record/Replay System
|
||||
```json
|
||||
// ログ1行例
|
||||
{
|
||||
"ts": 1737153845.123456,
|
||||
"plugin": "map.so",
|
||||
"type_id": 17,
|
||||
"method": "get/1",
|
||||
"args": [{"str":"key"}],
|
||||
"ret": {"str":"value"},
|
||||
"outcome": "Ok",
|
||||
"elapsed_us": 87,
|
||||
"by_name": false,
|
||||
"site": {"file":"apps/x.hako","line":42}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Hot-Swap Management
|
||||
```
|
||||
安全手順: disable → wait(0 inflight) → fini → dlclose → dlopen → init → re-enable
|
||||
GUI支援: 進捗表示 + state snapshot/restore(任意)
|
||||
```
|
||||
|
||||
### 4. Macro Automation
|
||||
```nyash
|
||||
// CAX API例
|
||||
cax.filter({outcome:'warn'})
|
||||
cax.attach("map.so")
|
||||
cax.replay("trace.tlv")
|
||||
cax.hotswap("map.so", "/tmp/map_new.so")
|
||||
```
|
||||
|
||||
## 📋 Implementation Roadmap
|
||||
|
||||
### Week 1 (MVP Core)
|
||||
- ✅ IPCサーバ(subscribe/attach/detach)
|
||||
- ✅ Explorer + Timeline(基本表示)
|
||||
- ✅ Inspector(引数/戻り値表示)
|
||||
- ✅ 記録(JSONL形式)
|
||||
|
||||
### Week 2 (Advanced Features)
|
||||
- ✅ Signature Checker(extern宣言 vs 実装差分)
|
||||
- ✅ Record/Replay(ファイル形式)
|
||||
- ✅ 簡易マクロ(フィルタ・基本操作)
|
||||
- ✅ Hot-swap wizard(dry-run)
|
||||
|
||||
## 🎨 GUI Implementation
|
||||
|
||||
### Technology Stack
|
||||
- **Frontend**: Tauri + Svelte/React + TypeScript
|
||||
- **IPC**: JSON-RPC over WebSocket
|
||||
- **Styling**: TailwindCSS + 可視化ライブラリ
|
||||
|
||||
### Key Components
|
||||
```typescript
|
||||
// IPC API例
|
||||
interface CaxApi {
|
||||
subscribe(params: {plugins: string[], level: string}): void
|
||||
attach(params: {plugin: string}): void
|
||||
hotswap(params: {plugin: string, path: string}): void
|
||||
record: {
|
||||
start(params: {file: string}): void
|
||||
stop(): void
|
||||
}
|
||||
replay(params: {file: string, mode: string}): void
|
||||
}
|
||||
```
|
||||
|
||||
## 🚧 Risk Mitigation
|
||||
|
||||
### Performance
|
||||
- **オーバーヘッド**: 既定軽量(log sampling、構造化は遅延ダンプ)
|
||||
- **再入防止**: スレッドローカルで抑止
|
||||
|
||||
### Safety
|
||||
- **クラッシュ隔離**: detach≠dlclose(最初は"ロード専用")
|
||||
- **権限管理**: プロセス境界越えはエージェント方式
|
||||
|
||||
## 💡 Competitive Advantages
|
||||
|
||||
### vs 既存デバッガ
|
||||
- **境界特化**: C↔Nyash境界に最適化された可視化
|
||||
- **型安全**: TypeBox境界での実時間検証
|
||||
- **構造化**: ライフサイクル・所有権の一元観測
|
||||
|
||||
### Innovation Points
|
||||
- **Record/Replay**: ABIコール完全再現(回帰テスト革命)
|
||||
- **GUI Integration**: コマンドライン→GUI操作の体験革新
|
||||
- **Hot-Swap**: 無停止デバッグ・プラグイン更新
|
||||
|
||||
---
|
||||
|
||||
**Note**: この設計は、C ABI動的呼び出しからの1分発想を30分で具体化したもの。実装の現実性と革新性を両立した世界初級ツールの仕様です。
|
||||
@ -1,165 +0,0 @@
|
||||
// CAX IPC Implementation (Gemini Draft)
|
||||
// Generated by Gemini AI - 2025-09-21
|
||||
// 172 lines of production-ready Nyash code
|
||||
|
||||
// IpcServerBox - CAXのIPCサーバーのメインとなるBox
|
||||
// クライアント(GUI)からの接続を受け付け、CABIDebuggerBoxと連携
|
||||
box IpcServerBox {
|
||||
cabiDebugger: CABIDebuggerBox
|
||||
clientConnections: MapBox<String, ClientConnectionBox>
|
||||
|
||||
birth() {
|
||||
me.cabiDebugger = new CABIDebuggerBox()
|
||||
me.clientConnections = new MapBox()
|
||||
}
|
||||
|
||||
// IPCリスナーを開始するルーチン(メインスレッド)
|
||||
startIpcListener() {
|
||||
loop {
|
||||
// 新しいクライアント接続を待つ
|
||||
local clientConnection = me.acceptNewClientConnection()
|
||||
if clientConnection == null { break }
|
||||
|
||||
local clientId = clientConnection.id()
|
||||
me.clientConnections.set(clientId, clientConnection)
|
||||
|
||||
// 各クライアント用の処理ルーチンを起動
|
||||
local commandChannel = new ChannelBox()
|
||||
local logChannel = new ChannelBox()
|
||||
|
||||
// クライアントコマンド処理用ルーチン
|
||||
nowait {
|
||||
me.handleClientCommands(clientConnection, clientId, logChannel)
|
||||
}
|
||||
|
||||
// デバッガーログをクライアントに転送するルーチン
|
||||
nowait {
|
||||
me.forwardDebuggerLogsToClient(clientId, logChannel)
|
||||
}
|
||||
|
||||
// 接続切断時の清掃
|
||||
clientConnection.onClose(() => {
|
||||
me.clientConnections.remove(clientId)
|
||||
me.cabiDebugger.removeLogSubscriber(clientId)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// クライアントからのコマンドを処理するルーチン
|
||||
handleClientCommands(clientConnection: ClientConnectionBox, clientId: String, clientChannel: ChannelBox) {
|
||||
loop {
|
||||
local command = clientConnection.receiveCommand() // クライアントからコマンドを受信
|
||||
if command == null { break } // 接続が切れたらループを抜ける
|
||||
|
||||
when command.method {
|
||||
"subscribe" => {
|
||||
local logLevel = command.params.logLevel
|
||||
me.cabiDebugger.addLogSubscriber(clientId, clientChannel, logLevel)
|
||||
clientConnection.sendResponse(command.id, new OkBox())
|
||||
}
|
||||
"attach" => {
|
||||
local pluginId = command.params.pluginId
|
||||
me.cabiDebugger.attachPlugin(pluginId)
|
||||
clientConnection.sendResponse(command.id, new OkBox())
|
||||
}
|
||||
// ... その他のコマンド (detach, record.start, replayなど)
|
||||
else => {
|
||||
clientConnection.sendResponse(command.id, new ErrorBox("Unknown command"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// C ABIデバッガーからのログを特定のクライアントに転送するルーチン
|
||||
forwardDebuggerLogsToClient(clientId: String, clientChannel: ChannelBox) {
|
||||
loop {
|
||||
// CABIDebuggerBoxから、このクライアントID宛のログを取得する
|
||||
// 実際には、CABIDebuggerBoxがログを生成し、購読しているチャネルに送る形になる
|
||||
local logEntry = me.cabiDebugger.getLogEntryForClient(clientId)
|
||||
if logEntry == null { break } // ログがなければ待機または終了
|
||||
|
||||
clientChannel.send(logEntry) // クライアントにログを送信
|
||||
}
|
||||
}
|
||||
|
||||
// 抽象的なクライアント接続を受け付けるメソッド (具体的なIPC実装に依存)
|
||||
acceptNewClientConnection() -> ClientConnectionBox {
|
||||
// ここに新しいクライアント接続を受け付ける具体的なロジック
|
||||
// 例: return listener.accept()
|
||||
return new ClientConnectionBox("dummy-client-id") // ダミー実装
|
||||
}
|
||||
}
|
||||
|
||||
// CABIDebuggerBox (cabi-debugger.mdで定義された機能を持つBox)
|
||||
// IpcServerBoxから呼び出されるコアロジック
|
||||
box CABIDebuggerBox {
|
||||
// ... 既存のフック、検証、記録機能 ...
|
||||
|
||||
// ログ購読者リスト (クライアントID -> ログ送信チャネル)
|
||||
// 実際には、ログレベルなどの購読設定も持つ
|
||||
logSubscribers: MapBox<String, ChannelBox>
|
||||
|
||||
birth() {
|
||||
me.logSubscribers = new MapBox()
|
||||
// ...
|
||||
}
|
||||
|
||||
// ログ購読者を登録する
|
||||
addLogSubscriber(clientId: String, clientChannel: ChannelBox, logLevel: String) {
|
||||
me.logSubscribers.set(clientId, clientChannel)
|
||||
print("Client " + clientId + " subscribed with level " + logLevel)
|
||||
// ログレベル設定など、購読の詳細を保存
|
||||
}
|
||||
|
||||
// プラグインをアタッチする
|
||||
attachPlugin(pluginId: String) {
|
||||
print("Attaching plugin: " + pluginId)
|
||||
// 実際のプラグインアタッチロジック
|
||||
// ...
|
||||
}
|
||||
|
||||
// ログエントリを生成し、購読しているクライアントに送信する
|
||||
// このメソッドは、C ABIフックから呼び出されることを想定
|
||||
generateAndDistributeLog(logEntry: LogEntryBox) {
|
||||
me.logSubscribers.forEach((clientId, channel) => {
|
||||
// クライアントの購読設定(ログレベルなど)に基づいてフィルタリング
|
||||
if me.shouldSendLogToClient(clientId, logEntry) {
|
||||
channel.send(logEntry)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 特定のクライアントID宛のログを取得する (forwardDebuggerLogsToClientから呼び出される)
|
||||
getLogEntryForClient(clientId: String) -> LogEntryBox {
|
||||
// このメソッドは、実際にはgenerateAndDistributeLogがチャネルに送ったログを
|
||||
// クライアントのforwardDebuggerLogsToClientルーチンが受け取る形になる
|
||||
// ここでは簡略化のためダミーを返す
|
||||
return new LogEntryBox("Dummy log for " + clientId)
|
||||
}
|
||||
|
||||
shouldSendLogToClient(clientId: String, logEntry: LogEntryBox) -> Bool {
|
||||
// ログレベルフィルタリングなどのロジック
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// ダミーのBox定義 (実際のIPC実装やログエントリの構造に合わせる)
|
||||
box ClientConnectionBox {
|
||||
id: String
|
||||
birth(id: String) { me.id = id }
|
||||
id() -> String { return me.id }
|
||||
receiveCommand() -> CommandBox { /* ダミー */ return new CommandBox("subscribe", "info") }
|
||||
sendResponse(id: String, response: Box) { /* ダミー */ }
|
||||
onClose(handler: Function) { /* ダミー */ }
|
||||
}
|
||||
|
||||
box CommandBox {
|
||||
method: String
|
||||
params: MapBox<String, Box>
|
||||
id: String
|
||||
birth(method: String, param: String) { me.method = method; me.params = new MapBox(); me.id = "1" }
|
||||
}
|
||||
|
||||
box OkBox { birth() {} }
|
||||
box ErrorBox { birth(msg: String) {} }
|
||||
box LogEntryBox { birth(msg: String) {} }
|
||||
@ -1,125 +0,0 @@
|
||||
# CAX発想プロセス記録 - 1分間の技術的洞察
|
||||
|
||||
**発想者**: nyash開発者
|
||||
**発想時刻**: 2025-09-21
|
||||
**所要時間**: 約1分
|
||||
**背景**: Mini-VM開発中、C ABI動的呼び出し議論から
|
||||
|
||||
## 🧠 発想の直線的プロセス
|
||||
|
||||
### Initial Context (0秒)
|
||||
```
|
||||
議題: 「C ABIを動的にプラグインのように取り外しも まあ できるかにゃ やる意味はおいといて」
|
||||
↓
|
||||
ChatGPT回答: 「技術的にはほぼYES」(dlopen/dlsym/安全ガード等の詳細分析)
|
||||
```
|
||||
|
||||
### Breakthrough Moment (約10秒)
|
||||
```
|
||||
発想: 「やるいみ おもいついたかもしれない きいてー」
|
||||
↓
|
||||
直感: 「うふふふふふふふ C ABI デバッガーーーーー!!!!」
|
||||
↓
|
||||
確信: 「もしかして 最強に 需要あるかもしれにゃい」
|
||||
```
|
||||
|
||||
### Technical Insight (約30秒)
|
||||
```
|
||||
技術的根拠の即座な理解:
|
||||
- C/CPython/ネイティブの「ABIバグ」が最厄介
|
||||
- 既存gdb/ASANは境界の意味論が見えない
|
||||
- Nyash箱理論 → 境界で完全トレース可能
|
||||
→ 「世界でも珍しいレベルのABIデバッグ体験」
|
||||
```
|
||||
|
||||
### UX Vision (約60秒)
|
||||
```
|
||||
直感的体験設計:
|
||||
「GUIで エクスプローラーみたいながめんから ぽいっと付けたり外したり
|
||||
ログもGUIで 入力もマクロなど自由自在」
|
||||
```
|
||||
|
||||
## 🌟 発想の技術的妥当性
|
||||
|
||||
### なぜ1分で到達できたか
|
||||
|
||||
#### 1. **技術基盤の理解**
|
||||
- Nyash箱理論: TypeBox/PluginHost境界の明確性
|
||||
- 既存ABI: C ABI呼び出し機構の理解
|
||||
- 問題認識: 境界バグの困難性を体感済み
|
||||
|
||||
#### 2. **直感的問題発見**
|
||||
```
|
||||
C ABI動的 → 「取り外し可能?」
|
||||
↓
|
||||
境界操作 → 「デバッグが困難」
|
||||
↓
|
||||
観測・制御 → 「専用ツールが必要」
|
||||
```
|
||||
|
||||
#### 3. **解決策の即座構築**
|
||||
```
|
||||
観測: ログ・トレース・可視化
|
||||
制御: アタッチ・デタッチ・ホットスワップ
|
||||
体験: GUI・自動化・直感的操作
|
||||
```
|
||||
|
||||
## 💡 発想の独創性分析
|
||||
|
||||
### 既存アプローチとの差別化
|
||||
```
|
||||
従来: gdb/ASAN = 汎用デバッガでABI境界は副次的
|
||||
CAX: ABI境界専用 = 境界観測に特化した設計
|
||||
```
|
||||
|
||||
### Nyash特有の優位性
|
||||
```
|
||||
箱理論: 境界が明確 → フック位置の自明性
|
||||
統一ライフサイクル: birth/fini → 所有権追跡容易
|
||||
型安全: TypeBox → 実時間型検証可能
|
||||
```
|
||||
|
||||
## 🎯 発想の実現可能性
|
||||
|
||||
### 技術的実現性(ChatGPT分析)
|
||||
- **Core実装**: 2週間MVP可能
|
||||
- **GUI実装**: Tauri/Electron + 既存IPC
|
||||
- **アーキテクチャ**: 既存基盤活用可能
|
||||
|
||||
### 市場性(直感的評価)
|
||||
- **開発者需要**: ABI境界バグは普遍的問題
|
||||
- **差別化**: 既存ツールにない専用機能
|
||||
- **Nyash優位**: 箱理論による技術的アドバンテージ
|
||||
|
||||
## 🚀 発想の発展性
|
||||
|
||||
### ChatGPT展開(30分)
|
||||
- 具体的UX設計
|
||||
- アーキテクチャ詳細化
|
||||
- 実装ロードマップ
|
||||
- リスク分析・対策
|
||||
|
||||
### Gemini実装(直後)
|
||||
- 172行実装コード
|
||||
- IPC層具体化
|
||||
- RoutineBox/ChannelBox活用
|
||||
- 即実装可能レベルまで具体化
|
||||
|
||||
## 📝 技術史的意義
|
||||
|
||||
### 個人開発+AI協働の威力
|
||||
```
|
||||
1分: 核心アイデア発見(人間)
|
||||
30分: 設計具体化(ChatGPT)
|
||||
直後: 実装コード(Gemini)
|
||||
→ 数時間で「世界初ツール」のプロトタイプ完成
|
||||
```
|
||||
|
||||
### 発想の本質
|
||||
- **直感性**: 技術制約から新可能性を即座発見
|
||||
- **実用性**: 実際の開発痛点からのソリューション
|
||||
- **革新性**: 既存アプローチの根本的再設計
|
||||
|
||||
---
|
||||
|
||||
**結論**: この1分間の発想は、技術的直感・問題発見力・解決策構築力の集約であり、AI協働開発の理想的パターンを実証した記録である。
|
||||
@ -1,186 +0,0 @@
|
||||
# CAX Technical Roadmap - Post‑Bootstrap Implementation Plan
|
||||
|
||||
**Target**: Mini-VM完成後の即実装
|
||||
**Duration**: 2-3週間でMVP完成
|
||||
**Dependency**: Mini-VM安定化 + 既存PluginHost基盤
|
||||
|
||||
## 🏗️ Implementation Phases
|
||||
|
||||
### Phase 0: Foundation (Mini-VM安定化待ち)
|
||||
**Duration**: Mini-VM完成まで
|
||||
**Tasks**:
|
||||
- ✅ 設計文書化(完了)
|
||||
- ✅ Gemini実装コード保存(完了)
|
||||
- ✅ ChatGPT設計仕様保存(完了)
|
||||
- [ ] 既存PluginHost.Invoke調査
|
||||
- [ ] IPC実装方式決定(WebSocket/Unix Socket)
|
||||
|
||||
### Phase 1: Core Implementation (Week 1)
|
||||
**Duration**: 5日間
|
||||
**Deliverables**: 基本IPC + 最小GUI
|
||||
|
||||
#### Backend (3日)
|
||||
```rust
|
||||
// src/tools/cax_server/
|
||||
├── ipc_server.rs // IPC通信層
|
||||
├── cabi_debugger.rs // フック・ログ・検証
|
||||
├── plugin_manager.rs // アタッチ・デタッチ管理
|
||||
└── main.rs // サーバー起動
|
||||
```
|
||||
|
||||
#### Frontend (2日)
|
||||
```typescript
|
||||
// gui/cax/
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ ├── Explorer.svelte // プラグイン一覧
|
||||
│ │ ├── Timeline.svelte // ライブログ表示
|
||||
│ │ └── Inspector.svelte // 詳細表示
|
||||
│ ├── api/
|
||||
│ │ └── cax_client.ts // IPC通信
|
||||
│ └── App.svelte // メインアプリ
|
||||
└── tauri.conf.json
|
||||
```
|
||||
|
||||
#### MVP機能
|
||||
- [x] プラグイン一覧表示
|
||||
- [x] アタッチ/デタッチボタン
|
||||
- [x] リアルタイムログ表示(JSONL)
|
||||
- [x] 基本フィルタリング
|
||||
|
||||
### Phase 2: Advanced Features (Week 2)
|
||||
**Duration**: 5日間
|
||||
**Deliverables**: Record/Replay + Hot-swap
|
||||
|
||||
#### Record/Replay System
|
||||
```rust
|
||||
// レコーダー
|
||||
pub struct CallRecorder {
|
||||
output: BufWriter<File>,
|
||||
format: RecordFormat, // JSONL | TLV
|
||||
}
|
||||
|
||||
// リプレイヤー
|
||||
pub struct CallReplayer {
|
||||
calls: Vec<RecordedCall>,
|
||||
mock_mode: bool, // プラグイン無しで再生
|
||||
}
|
||||
```
|
||||
|
||||
#### Hot-Swap Management
|
||||
```rust
|
||||
// ホットスワップ管理
|
||||
pub struct PluginSwapper {
|
||||
state: SwapState, // Attached | Quiescing | Swapping
|
||||
pending_calls: AtomicU64,
|
||||
swap_queue: VecDeque<SwapRequest>,
|
||||
}
|
||||
```
|
||||
|
||||
#### GUI拡張
|
||||
- [x] 録画/再生コントロール
|
||||
- [x] ホットスワップウィザード
|
||||
- [x] コール詳細インスペクター
|
||||
- [x] 簡易スクリプト実行
|
||||
|
||||
### Phase 3: Polish & Advanced (Week 3)
|
||||
**Duration**: 5日間
|
||||
**Deliverables**: 本格運用可能版
|
||||
|
||||
#### Analytics & Visualization
|
||||
```typescript
|
||||
// ヒートマップ・統計表示
|
||||
interface CallStats {
|
||||
plugin: string
|
||||
method: string
|
||||
call_count: number
|
||||
avg_time_us: number
|
||||
error_rate: number
|
||||
hot_paths: string[]
|
||||
}
|
||||
```
|
||||
|
||||
#### Advanced Scripting
|
||||
```nyash
|
||||
// CAX Macro API
|
||||
using cax.api as CAX
|
||||
|
||||
CAX.enable({profile: true, assert: "warn"})
|
||||
CAX.attach("map.so")
|
||||
|
||||
// 自動化スクリプト例
|
||||
local errorCount = CAX.filter({outcome: "error"}).count()
|
||||
if errorCount > 10 {
|
||||
CAX.hotswap("map.so", "/backup/map_stable.so")
|
||||
}
|
||||
```
|
||||
|
||||
#### Production Features
|
||||
- [x] 詳細設定・永続化
|
||||
- [x] エクスポート(HTML/PDF レポート)
|
||||
- [x] プラグイン署名検証
|
||||
- [x] 権限・セキュリティ管理
|
||||
|
||||
## 🎯 Success Criteria
|
||||
|
||||
### MVP Success (Phase 1)
|
||||
- [x] プラグインアタッチ→ログ表示まで1クリック
|
||||
- [x] リアルタイム表示でパフォーマンス影響<5%
|
||||
- [x] 基本的なABIバグ(型ミスマッチ)を検出
|
||||
|
||||
### Advanced Success (Phase 2)
|
||||
- [x] Record→Replay でCI回帰テスト実現
|
||||
- [x] ホットスワップでサービス無停止更新
|
||||
- [x] 複雑なABIバグを根本特定
|
||||
|
||||
### Production Success (Phase 3)
|
||||
- [x] 日常開発ワークフローに統合
|
||||
- [x] 他言語(Python/C++)開発者も使用開始
|
||||
- [x] 学術発表・OSS公開で注目獲得
|
||||
|
||||
## 🔧 Technical Implementation Notes
|
||||
|
||||
### IPC選択基準
|
||||
```
|
||||
WebSocket: ブラウザベースGUI用(開発容易)
|
||||
Unix Socket: ネイティブGUI用(性能優先)
|
||||
→ 両対応、設定で選択可能
|
||||
```
|
||||
|
||||
### フック実装位置
|
||||
```rust
|
||||
// PluginHost::invoke の入口・出口
|
||||
impl PluginHost {
|
||||
pub fn invoke(&self, call: &PluginCall) -> Result<Value> {
|
||||
CAX_TRACER.pre_call(call); // 🎯 フック点1
|
||||
let result = self.invoke_impl(call);
|
||||
CAX_TRACER.post_call(call, &result); // 🎯 フック点2
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### パフォーマンス最適化
|
||||
```rust
|
||||
// 条件付きトレース(オーバーヘッド最小化)
|
||||
if CAX_ENABLED.load(Ordering::Relaxed) {
|
||||
tracer.log_call(call_info);
|
||||
}
|
||||
|
||||
// 非同期ログ書き込み
|
||||
async fn log_writer(mut receiver: Receiver<LogEntry>) {
|
||||
while let Some(entry) = receiver.recv().await {
|
||||
// バッファリング→バッチ書き込み
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📅 Realistic Timeline
|
||||
|
||||
**Prerequisite**: Mini-VM安定化(推定2-3週間)
|
||||
**Implementation**: CAX開発(3週間)
|
||||
**Total**: 約6週間でプロダクション品質版完成
|
||||
|
||||
---
|
||||
|
||||
**Note**: この実装計画は、Geminiの172行実装とChatGPTの設計仕様を基に、現実的なタイムラインで作成。Mini-VM完成後、即座に実装開始可能。
|
||||
@ -1,123 +0,0 @@
|
||||
# Instance v2 統一レジストリ設計メモ(提案)
|
||||
|
||||
目的: ユーザー定義 / ビルトイン / プラグインの3系統を instance_v2 で一元管理し、同一の生成(birth)/破棄(fini)ライフサイクルで扱えるようにする。また、wasm-bindgen ターゲットでプラグイン機構を安全に無効化できる切替を用意する。
|
||||
|
||||
---
|
||||
|
||||
## 現状の整理(実装済み)
|
||||
- ユーザー定義Box
|
||||
- インタプリタの AST → InstanceBox 生成で対応済み。
|
||||
- `execute_new` は最初に統一レジストリを呼び、ユーザー定義については最終的に `InstanceBox` を構築し、birth 相当のコンストラクタ実行を行う。
|
||||
- ビルトインBox
|
||||
- 統一レジストリ経由で生成可能。ユーザー定義と同じ呼び出し経路に乗る。
|
||||
- プラグインBox(v2)
|
||||
- `nyash.toml v2` を `PluginLoaderV2` が読み込み、`nyash_plugin_invoke` の birth 呼び出しでインスタンスを生成。
|
||||
- 現状、`PluginBoxV2` は `clone_box=新birth`、`share_box=同一 instance_id` を実装済み。
|
||||
|
||||
---
|
||||
|
||||
## 目標
|
||||
1. 3系統(ユーザー定義/ビルトイン/プラグイン)を「統一レジストリ→instance_v2」で一元管理。
|
||||
2. birth/fini ライフサイクルの整合をとる。
|
||||
3. wasm-bindgen ターゲット(`wasm32-unknown-unknown`)ではプラグイン機構をコンパイル時に無効化し、ビルド可能にする。
|
||||
|
||||
---
|
||||
|
||||
## 設計方針
|
||||
|
||||
### 1) 統一レジストリの責務
|
||||
- 名前(クラス名)と引数(`Box<dyn NyashBox>` の配列)を入力に、ユーザー定義/ビルトイン/プラグインの順で解決・生成を試みる。
|
||||
- 生成に成功したら `Box<dyn NyashBox>` を返す。
|
||||
- ユーザー定義: `InstanceBox` とし、インタプリタがコンストラクタ(birth)を実行。
|
||||
- ビルトイン: 直接生成(必要なら簡易birth相当の初期化)
|
||||
- プラグイン: `PluginLoaderV2` の `invoke_fn(type_id, method_id=0=birth, ...)` を呼ぶ。
|
||||
|
||||
### 2) birth / fini ライフサイクル
|
||||
- birth:
|
||||
- ユーザー定義: 既存通り AST 上のコンストラクタ(birth)を呼ぶ。
|
||||
- プラグイン: `nyash.toml` の `methods.birth` の method_id=0 を使い、`invoke_fn` 呼び出しで instance_id を取得済み。
|
||||
- fini:
|
||||
- InstanceBox のフィールド差し替え時、旧値が InstanceBox なら `fini()` を呼んで finalize 済みIDとしてマーキング(実装済み)。
|
||||
- プラグインBoxについても `nyash.toml` で `methods.fini`(例: 0xFFFF)を定義し、差し替えやスコープ終端で `invoke_fn(type_id, method_id=fini, instance_id, ...)` を呼ぶ。エラーは握りつぶさずログ化。
|
||||
|
||||
### 3) wasm-bindgen ターゲットでの切り替え
|
||||
- Cargo features によるコンパイル時ガードを導入:
|
||||
- `plugins`(デフォルトON)、`wasm-backend`(WASMビルド用)の2フラグを用意。
|
||||
- `#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]` のときのみ `plugin_loader_v2` 実体を有効化。
|
||||
- それ以外では `plugin_loader_v2` のスタブ実装を使う(常に `Err(BidError::PluginError)` を返すなど)。
|
||||
- 統一レジストリはプラグインFactoryの登録を `#[cfg(feature="plugins")]` でガードし、WASMビルドでもユーザー定義/ビルトインは動かせる。
|
||||
- `nyash.toml` のファイルI/O(`from_file`)も `cfg` で握り、WASMではロードしない。
|
||||
|
||||
---
|
||||
|
||||
## nyash.toml v2 との整合
|
||||
- 既存:
|
||||
- `libraries.<libname>.boxes = ["FileBox"]`
|
||||
- `libraries.<libname>.<BoxType>.methods.birth = { method_id = 0 }`
|
||||
- `... .fini = { method_id = 4294967295 }` など
|
||||
- 追加検討:
|
||||
- 将来、ユーザー定義Boxをプラグインで置換したい場合:
|
||||
- クラス名→プラグインBox型の上書きマップを `nyash.toml` に追加(例:`overrides = { "DataBox" = "libX::RemoteDataBox" }`)。
|
||||
- 統一レジストリがこのマップを見て、ユーザー定義をスキップしてプラグインへ委譲。
|
||||
|
||||
---
|
||||
|
||||
## API/コード上の具体案(抜粋)
|
||||
- features(`Cargo.toml`):
|
||||
```toml
|
||||
[features]
|
||||
default = ["plugins"]
|
||||
plugins = []
|
||||
wasm-backend = []
|
||||
```
|
||||
- プラグインローダ(`src/runtime/plugin_loader_v2.rs`):
|
||||
```rust
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
pub mod real_loader { /* 現在の実装 */ }
|
||||
|
||||
#[cfg(any(not(feature = "plugins"), target_arch = "wasm32"))]
|
||||
pub mod stub_loader {
|
||||
use crate::bid::{BidResult, BidError};
|
||||
use crate::box_trait::NyashBox;
|
||||
pub struct PluginLoaderV2; // ダミー
|
||||
impl PluginLoaderV2 { pub fn new() -> Self { Self } }
|
||||
impl PluginLoaderV2 {
|
||||
pub fn load_config(&mut self, _p: &str) -> BidResult<()> { Ok(()) }
|
||||
pub fn load_all_plugins(&self) -> BidResult<()> { Ok(()) }
|
||||
pub fn create_box(&self, _t: &str, _a: &[Box<dyn NyashBox>]) -> BidResult<Box<dyn NyashBox>> {
|
||||
Err(BidError::PluginError)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
- 統一レジストリのFactory登録部は `#[cfg(feature = "plugins")]` でプラグインFactoryの登録を条件化。
|
||||
|
||||
---
|
||||
|
||||
## マイグレーション手順(段階)
|
||||
1. Cargo features と cfg ガードの導入(プラグイン機構のスタブ化を含む)。
|
||||
2. 統一レジストリのプラグインFactory登録の条件化。
|
||||
3. プラグインBoxの `fini` 呼び出し用メソッドを InstanceBox 置換/破棄パスへ組み込む。
|
||||
4. 必要に応じて `nyash.toml` の `methods.fini` を明記。
|
||||
5. 追加要件(ユーザー定義のプラグイン置換)を `overrides` マップで設計 → 実装。
|
||||
|
||||
---
|
||||
|
||||
## テスト観点
|
||||
- ユニット:
|
||||
- birth/fini の呼び出し順と複数回置換時の `fini` 呼び出し保証。
|
||||
- `plugins` ON/OFF、`wasm-backend` ON の3軸でビルド/テストが通ること。
|
||||
- 統合テスト:
|
||||
- `nyash.toml` によるビルトイン→プラグインの透過切替。
|
||||
- ユーザー定義→ビルトイン→プラグインの優先順位が想定通り。
|
||||
|
||||
---
|
||||
|
||||
## メモ
|
||||
- すでに `execute_new` は統一レジストリ優先の実装になっており、この設計と整合が良い。
|
||||
- WASM ターゲットでは `libloading` が使えないため、コンパイル時に完全にプラグインコードを外す方針(cfg/feature)は自然。
|
||||
- `nyash.toml` のロードはネイティブ時のみで十分(WASM は将来、バンドルまたは JS 側から供給する計画があるなら別途)。
|
||||
|
||||
---
|
||||
|
||||
以上。必要であれば、この方針でPRを小さく分割(features→レジストリ→fini→overrides)して入れていきます。
|
||||
@ -1,80 +0,0 @@
|
||||
# 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')`.
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
# PoC Plan: TypeOp / WeakRef / Barrier Unification
|
||||
|
||||
Status: Draft (PoC design)
|
||||
Last Updated: 2025-08-23
|
||||
|
||||
## Goals
|
||||
- Reduce instruction surface without losing expressiveness or performance.
|
||||
- Provide a feature-gated PoC to validate that consolidation is safe and measurable.
|
||||
|
||||
## Scope
|
||||
- Unify TypeCheck + Cast → TypeOp (single instruction)
|
||||
- Unify WeakNew + WeakLoad → WeakRef (single instruction)
|
||||
- Unify BarrierRead + BarrierWrite → Barrier (single instruction)
|
||||
|
||||
## Out of Scope (PoC)
|
||||
- Remap language syntax or external APIs
|
||||
- Remove legacy instructions permanently (kept behind feature flags)
|
||||
|
||||
## Feature Flags (Cargo)
|
||||
Note: 2025-08 Phase 9.78h 時点で統合命令はデフォルトとなり、以下のflagsは非推奨(no-op)だよ:
|
||||
|
||||
- `mir_typeop_poc`: Builderは常に`TypeOp(Check/Cast)`を生成(旧`TypeCheck/Cast`は使わない)。
|
||||
- `mir_refbarrier_unify_poc`: Builderは常に`WeakRef/Barrier`を生成(旧`WeakNew/WeakLoad/BarrierRead/Write`は使わない)。
|
||||
|
||||
互換性のため、Optimizerに旧命令→統合命令への正規化パス(Pass 0)が入っているにゃ。
|
||||
|
||||
## Mapping (Current → PoC)
|
||||
- TypeCheck { value, expected_type } → TypeOp { op: Check, value, type } (bool)
|
||||
- Cast { value, target_type } → TypeOp { op: Cast, value, type } (value)
|
||||
- WeakNew { dst, box_val } → WeakRef { op: New, dst, box_val }
|
||||
- WeakLoad { dst, weak_ref } → WeakRef { op: Load, dst, weak_ref }
|
||||
- BarrierRead { ptr } → Barrier { op: Read, ptr }
|
||||
- BarrierWrite { ptr } → Barrier { op: Write, ptr }
|
||||
|
||||
## Implementation Steps
|
||||
1) MIR instruction additions
|
||||
- Add TypeOp/WeakRef/Barrier enums with minimal payloads
|
||||
- Keep legacy instructions compiled-in (no behavior change yet)
|
||||
2) Builder mapping (feature-gated)
|
||||
- Under flags, emit unified instructions instead of legacy
|
||||
3) VM execution mapping
|
||||
- Implement execute paths for TypeOp/WeakRef/Barrier
|
||||
- Legacy paths continue to work for fallback
|
||||
4) Printer/Stats
|
||||
- Name new ops distinctly; ensure stats collection reflects consolidated ops
|
||||
5) Tests
|
||||
- Snapshot tests for builder mapping (with/without flags)
|
||||
- VM exec parity tests for legacy vs unified
|
||||
|
||||
## Rollout / Migration
|
||||
- Phase A (PoC): flags off by default, CI job with flags on
|
||||
- Phase B (Dual): flags on by default in dev; legacy paths still supported
|
||||
- Phase C (Switch): remove legacy or keep as aliases (no-emit) depending on impact
|
||||
|
||||
## Impact Areas
|
||||
- `src/mir/instruction.rs` (add new ops; Display/used_values/dst_value)
|
||||
- `src/mir/builder.rs` (conditional emit)
|
||||
- `src/backend/vm.rs` (execution paths + stats key)
|
||||
- `src/mir/printer.rs` (print new ops)
|
||||
- Tests: MIR/VM/E2E minimal parity checks
|
||||
|
||||
## Acceptance Criteria
|
||||
- All current tests pass with flags off (default)
|
||||
- With flags on:
|
||||
- Unit/snapshot tests pass
|
||||
- vm-stats shows expected consolidation (TypeOp/WeakRef/Barrier vs legacy)
|
||||
- No regressions in FileBox/Net E2E under plugins
|
||||
|
||||
## Metrics to Watch
|
||||
- vm-stats: proportion of TypeOp/WeakRef/Barrier vs legacy in representative scenarios
|
||||
- Build time impact: negligible
|
||||
- Code size: small reduction after removal
|
||||
|
||||
## Risks / Mitigations
|
||||
- Risk: Unified ops obscure dataflow for some analyses
|
||||
- Mitigation: Verifier hooks to introspect TypeOp semantics; keep legacy printer names during PoC
|
||||
- Risk: Plugins or external tooling tied to legacy names
|
||||
- Mitigation: MIR remains internal; external ABI unaffected
|
||||
|
||||
## Next Steps
|
||||
- Land scaffolding (no behavior change)
|
||||
- Add builder mapping behind flags
|
||||
- Add VM execution behind flags
|
||||
- Gate CI job to run PoC flags on Linux
|
||||
@ -1,362 +0,0 @@
|
||||
# MIR 35→26→15命令削減: 詳細分析・移行戦略
|
||||
|
||||
*実装ベース完全マッピング - 2025年8月17日版*
|
||||
**注意**: このドキュメントは35→26命令への移行計画を記録しています。現在はさらに15命令に削減済みです。
|
||||
|
||||
## 🔍 **過去の実装35命令 vs 26命令仕様の完全マッピング(歴史的記録)**
|
||||
|
||||
### **維持する命令 (35命令実装 → 26命令仕様への移行計画)**
|
||||
|
||||
| 現在実装 | 26命令仕様 | 効果 | 変更 |
|
||||
|----------|------------|------|------|
|
||||
| `Const` | `Const` | pure | ✅ 維持 |
|
||||
| `BinOp` | `BinOp` | pure | ✅ 維持 |
|
||||
| `Compare` | `Compare` | pure | ✅ 維持 |
|
||||
| `Branch` | `Branch` | control | ✅ 維持 |
|
||||
| `Jump` | `Jump` | control | ✅ 維持 |
|
||||
| `Phi` | `Phi` | pure | ✅ 維持 |
|
||||
| `Call` | `Call` | context | ✅ 維持 |
|
||||
| `Return` | `Return` | control | ✅ 維持 |
|
||||
| `NewBox` | `NewBox` | mut | ✅ 維持 |
|
||||
| `BoxCall` | `BoxCall` | context | ✅ 維持 |
|
||||
| `ExternCall` | `ExternCall` | context | ✅ 維持 |
|
||||
| `Safepoint` | `Safepoint` | io | ✅ 維持 |
|
||||
| `RefGet` | `RefGet` | pure | ✅ 維持 |
|
||||
| `RefSet` | `RefSet` | mut | ✅ 維持 |
|
||||
| `WeakNew` | `WeakNew` | pure | ✅ 維持 |
|
||||
| `WeakLoad` | `WeakLoad` | pure | ✅ 維持 |
|
||||
|
||||
**小計**: 16命令維持
|
||||
|
||||
### **削除する命令 (17命令)**
|
||||
|
||||
#### **グループ1: BinOp統合 (1命令)**
|
||||
|
||||
| 削除命令 | 置換方法 | 実装例 |
|
||||
|----------|----------|--------|
|
||||
| `UnaryOp` | `BinOp`統合 | `not %a` → `%a xor true`<br>`neg %a` → `0 sub %a` |
|
||||
|
||||
#### **グループ2: BoxField操作統合 (4命令)**
|
||||
|
||||
| 削除命令 | 置換方法 | 実装例 |
|
||||
|----------|----------|--------|
|
||||
| `Load` | `BoxFieldLoad` | `load %ptr` → `%ptr.value` |
|
||||
| `Store` | `BoxFieldStore` | `store %val -> %ptr` → `%ptr.value = %val` |
|
||||
| `ArrayGet` | `BoxFieldLoad` | `%arr[%idx]` → `%arr.elements[%idx]` |
|
||||
| `ArraySet` | `BoxFieldStore` | `%arr[%idx] = %val` → `%arr.elements[%idx] = %val` |
|
||||
|
||||
#### **グループ3: intrinsic化 (6命令)**
|
||||
|
||||
| 削除命令 | intrinsic名 | 実装例 |
|
||||
|----------|-------------|--------|
|
||||
| `Print` | `@print` | `print %val` → `call @print, %val` |
|
||||
| `Debug` | `@debug` | `debug %val "msg"` → `call @debug, %val, "msg"` |
|
||||
| `TypeCheck` | `@type_check` | `type_check %val "Type"` → `call @type_check, %val, "Type"` |
|
||||
| `Cast` | `@cast` | `cast %val Type` → `call @cast, %val, Type` |
|
||||
| `Throw` | `@throw` | `throw %exc` → `call @throw, %exc` |
|
||||
| `Catch` | `@catch` | `catch Type -> %bb` → `call @catch, Type, %bb` |
|
||||
|
||||
#### **グループ4: 完全削除 (3命令)**
|
||||
|
||||
| 削除命令 | 削除理由 | 代替方法 |
|
||||
|----------|----------|----------|
|
||||
| `Copy` | 最適化パス専用 | 最適化段階でのみ使用 |
|
||||
| `Nop` | 不要 | 削除(プレースホルダー不要) |
|
||||
| `RefNew` | 冗長 | `RefGet`で代用可能 |
|
||||
|
||||
#### **グループ5: 統合・置換 (3命令)**
|
||||
|
||||
| 削除命令 | 統合先 | 実装例 |
|
||||
|----------|--------|--------|
|
||||
| `BarrierRead` | `AtomicFence` | `barrier_read %ptr` → `atomic_fence acquire` |
|
||||
| `BarrierWrite` | `AtomicFence` | `barrier_write %ptr` → `atomic_fence release` |
|
||||
| `FutureNew` | `NewBox + BoxCall` | `future_new %val` → `%f = new_box "Future"(%val)` |
|
||||
| `FutureSet` | `BoxCall` | `future_set %f = %val` → `%f.set(%val)` |
|
||||
| `Await` | `BoxCall` | `await %f` → `%f.await()` |
|
||||
|
||||
### **追加する命令 (10命令)**
|
||||
|
||||
| 新命令 | 効果 | 目的 | 実装必要度 |
|
||||
|--------|------|------|------------|
|
||||
| `BoxFieldLoad` | pure | Everything is Box核心 | 🔥 Critical |
|
||||
| `BoxFieldStore` | mut | Everything is Box核心 | 🔥 Critical |
|
||||
| `WeakCheck` | pure | weak参照完全対応 | ⚡ High |
|
||||
| `Send` | io | Bus操作一次市民化 | ⚡ High |
|
||||
| `Recv` | io | Bus操作一次市民化 | ⚡ High |
|
||||
| `TailCall` | control | JIT最適化基盤 | 📝 Medium |
|
||||
| `Adopt` | mut | 所有権移管明示 | 📝 Medium |
|
||||
| `Release` | mut | 所有権移管明示 | 📝 Medium |
|
||||
| `MemCopy` | mut | 最適化基盤 | 📝 Medium |
|
||||
| `AtomicFence` | io | 並行制御統一 | 📝 Medium |
|
||||
|
||||
## 🛠️ **具体的実装戦略**
|
||||
|
||||
### **Phase 1: 新命令実装**
|
||||
|
||||
#### **BoxFieldLoad/BoxFieldStore実装**
|
||||
```rust
|
||||
// src/mir/instruction.rs
|
||||
pub enum MirInstruction {
|
||||
// 新規追加
|
||||
BoxFieldLoad {
|
||||
dst: ValueId,
|
||||
box_val: ValueId,
|
||||
field: String,
|
||||
},
|
||||
BoxFieldStore {
|
||||
box_val: ValueId,
|
||||
field: String,
|
||||
value: ValueId,
|
||||
},
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### **WeakCheck実装**
|
||||
```rust
|
||||
WeakCheck {
|
||||
dst: ValueId,
|
||||
weak_ref: ValueId,
|
||||
}
|
||||
```
|
||||
|
||||
#### **Send/Recv実装**
|
||||
```rust
|
||||
Send {
|
||||
data: ValueId,
|
||||
target: ValueId,
|
||||
},
|
||||
Recv {
|
||||
dst: ValueId,
|
||||
source: ValueId,
|
||||
},
|
||||
```
|
||||
|
||||
### **Phase 2: intrinsic関数システム実装**
|
||||
|
||||
#### **intrinsic レジストリ**
|
||||
```rust
|
||||
// src/interpreter/intrinsics.rs
|
||||
pub struct IntrinsicRegistry {
|
||||
functions: HashMap<String, IntrinsicFunction>,
|
||||
}
|
||||
|
||||
impl IntrinsicRegistry {
|
||||
pub fn new() -> Self {
|
||||
let mut registry = Self { functions: HashMap::new() };
|
||||
registry.register("@print", intrinsic_print);
|
||||
registry.register("@debug", intrinsic_debug);
|
||||
registry.register("@type_check", intrinsic_type_check);
|
||||
registry.register("@cast", intrinsic_cast);
|
||||
registry.register("@array_get", intrinsic_array_get);
|
||||
registry.register("@array_set", intrinsic_array_set);
|
||||
registry
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **intrinsic関数実装例**
|
||||
```rust
|
||||
fn intrinsic_print(args: &[Value]) -> Result<Value, RuntimeError> {
|
||||
println!("{}", args[0]);
|
||||
Ok(Value::Void)
|
||||
}
|
||||
|
||||
fn intrinsic_array_get(args: &[Value]) -> Result<Value, RuntimeError> {
|
||||
let array = args[0].as_array_box()?;
|
||||
let index = args[1].as_integer()?;
|
||||
array.get_element(index as usize)
|
||||
}
|
||||
|
||||
fn intrinsic_array_set(args: &[Value]) -> Result<Value, RuntimeError> {
|
||||
let array = args[0].as_array_box_mut()?;
|
||||
let index = args[1].as_integer()?;
|
||||
let value = args[2].clone();
|
||||
array.set_element(index as usize, value)
|
||||
}
|
||||
```
|
||||
|
||||
### **Phase 3: AST→MIR生成更新**
|
||||
|
||||
#### **Load/Store → BoxFieldLoad/BoxFieldStore変換**
|
||||
```rust
|
||||
// src/mir/builder.rs
|
||||
impl MirBuilder {
|
||||
fn visit_field_access(&mut self, node: &FieldAccessNode) -> Result<ValueId, BuildError> {
|
||||
let box_val = self.visit_expression(&node.object)?;
|
||||
let dst = self.new_temp_var();
|
||||
|
||||
// 旧: Load命令生成
|
||||
// self.emit(MirInstruction::Load { dst, ptr: box_val });
|
||||
|
||||
// 新: BoxFieldLoad命令生成
|
||||
self.emit(MirInstruction::BoxFieldLoad {
|
||||
dst,
|
||||
box_val,
|
||||
field: node.field.clone(),
|
||||
});
|
||||
|
||||
Ok(dst)
|
||||
}
|
||||
|
||||
fn visit_field_assignment(&mut self, node: &FieldAssignmentNode) -> Result<(), BuildError> {
|
||||
let box_val = self.visit_expression(&node.object)?;
|
||||
let value = self.visit_expression(&node.value)?;
|
||||
|
||||
// 旧: Store命令生成
|
||||
// self.emit(MirInstruction::Store { value, ptr: box_val });
|
||||
|
||||
// 新: BoxFieldStore命令生成
|
||||
self.emit(MirInstruction::BoxFieldStore {
|
||||
box_val,
|
||||
field: node.field.clone(),
|
||||
value,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **配列操作 → BoxField + intrinsic変換**
|
||||
```rust
|
||||
fn visit_array_access(&mut self, node: &ArrayAccessNode) -> Result<ValueId, BuildError> {
|
||||
let array = self.visit_expression(&node.array)?;
|
||||
let index = self.visit_expression(&node.index)?;
|
||||
let dst = self.new_temp_var();
|
||||
|
||||
// intrinsic化
|
||||
self.emit(MirInstruction::Call {
|
||||
dst: Some(dst),
|
||||
func: self.get_intrinsic_id("@array_get"),
|
||||
args: vec![array, index],
|
||||
effects: EffectMask::PURE,
|
||||
});
|
||||
|
||||
Ok(dst)
|
||||
}
|
||||
```
|
||||
|
||||
### **Phase 4: バックエンド対応**
|
||||
|
||||
#### **Interpreter実装**
|
||||
```rust
|
||||
// src/backend/interpreter.rs
|
||||
impl Interpreter {
|
||||
fn execute_box_field_load(&mut self, dst: ValueId, box_val: ValueId, field: &str) -> Result<(), RuntimeError> {
|
||||
let box_obj = self.get_value(box_val)?;
|
||||
let field_value = box_obj.get_field(field)?;
|
||||
self.set_value(dst, field_value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_box_field_store(&mut self, box_val: ValueId, field: &str, value: ValueId) -> Result<(), RuntimeError> {
|
||||
let mut box_obj = self.get_value_mut(box_val)?;
|
||||
let field_value = self.get_value(value)?;
|
||||
box_obj.set_field(field, field_value)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **VM実装**
|
||||
```rust
|
||||
// src/backend/vm.rs
|
||||
impl VM {
|
||||
fn exec_box_field_load(&mut self, dst: RegId, box_val: RegId, field_id: FieldId) -> VMResult<()> {
|
||||
let box_ptr = self.registers[box_val as usize];
|
||||
let field_value = unsafe {
|
||||
self.load_field(box_ptr, field_id)
|
||||
};
|
||||
self.registers[dst as usize] = field_value;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **WASM実装**
|
||||
```rust
|
||||
// src/backend/wasm/codegen.rs
|
||||
impl WasmCodegen {
|
||||
fn generate_box_field_load(&mut self, dst: ValueId, box_val: ValueId, field: &str) -> Result<(), CodegenError> {
|
||||
let box_addr = self.get_value_address(box_val)?;
|
||||
let field_offset = self.get_field_offset(field)?;
|
||||
|
||||
// WASM: i32.load offset=field_offset
|
||||
self.emit_wasm(&format!("i32.load offset={}", field_offset));
|
||||
self.set_value_register(dst);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 **移行スケジュール詳細**
|
||||
|
||||
### **Week 1: 基盤実装 (8/18-8/24)**
|
||||
- [ ] 新命令構造体定義
|
||||
- [ ] intrinsicレジストリ実装
|
||||
- [ ] パーサー拡張(新旧両対応)
|
||||
|
||||
### **Week 2: フロントエンド移行 (8/25-8/31)**
|
||||
- [ ] AST→MIR変換更新
|
||||
- [ ] 配列操作intrinsic化
|
||||
- [ ] Load/Store→BoxField変換
|
||||
|
||||
### **Week 3: 最適化パス移行 (9/1-9/7)**
|
||||
- [ ] Effect分類実装
|
||||
- [ ] 所有権森検証
|
||||
- [ ] BoxFieldLoad/Store最適化
|
||||
|
||||
### **Week 4: バックエンド移行 (9/8-9/14)**
|
||||
- [ ] Interpreter新命令実装
|
||||
- [ ] VM新命令実装
|
||||
- [ ] WASM新命令実装
|
||||
|
||||
### **Week 5: クリーンアップ (9/15-9/21)**
|
||||
- [ ] 旧命令完全削除
|
||||
- [ ] テスト更新
|
||||
- [ ] ドキュメント整備
|
||||
|
||||
## 🧪 **テスト・検証計画**
|
||||
|
||||
### **段階的テスト**
|
||||
```bash
|
||||
# Week 1終了時
|
||||
./scripts/test_mir_parsing_26.sh
|
||||
|
||||
# Week 2終了時
|
||||
./scripts/test_frontend_migration.sh
|
||||
|
||||
# Week 3終了時
|
||||
./scripts/test_optimization_passes.sh
|
||||
|
||||
# Week 4終了時
|
||||
./scripts/test_all_backends.sh
|
||||
|
||||
# Week 5終了時
|
||||
./scripts/test_golden_mir_final.sh
|
||||
```
|
||||
|
||||
### **性能回帰テスト**
|
||||
```bash
|
||||
# 削減前後性能比較
|
||||
./scripts/benchmark_mir_reduction.sh
|
||||
```
|
||||
|
||||
## 🎯 **リスク対策**
|
||||
|
||||
### **高リスク箇所**
|
||||
1. **配列操作intrinsic化**: パフォーマンス影響大
|
||||
2. **BoxField統合**: Box型システムとの整合性
|
||||
3. **Effect分類変更**: 最適化ロジック全面見直し
|
||||
|
||||
### **対策**
|
||||
- **プロトタイプ実装**: 高リスク箇所の事前検証
|
||||
- **性能測定**: 各段階での性能チェック
|
||||
- **ロールバック**: 問題発生時の迅速復旧
|
||||
|
||||
---
|
||||
|
||||
**分析完了**: 2025年8月17日
|
||||
**実装開始**: 2025年8月18日
|
||||
**完了予定**: 2025年9月21日
|
||||
@ -1,267 +0,0 @@
|
||||
# nyash.linkシステム設計 - モジュール・依存関係管理革命
|
||||
|
||||
## 🎯 設計背景
|
||||
|
||||
### 📊 現状調査結果
|
||||
- **include使用状況**: 主にexamples/text_adventureで10件程度、実用性は限定的
|
||||
- **usingキーワード**: **未実装**(トークナイザーにも存在しない)
|
||||
- **namespace設計**: Phase 9.75eで仕様完成、実装待ち
|
||||
|
||||
### 🌟 Gemini先生の推奨
|
||||
> 「技術的に非常に妥当であり、現代的なプログラミング言語の設計として強く推奨される」
|
||||
|
||||
**結論**: includeほぼ未使用 + using未実装 = 完全に新設計で進められる!🎉
|
||||
|
||||
## 🚀 設計方針
|
||||
|
||||
### 💡 基本コンセプト
|
||||
```
|
||||
依存関係管理(nyash.link) + モジュールインポート(using) = 完璧な統合
|
||||
```
|
||||
|
||||
### 🎯 他言語成功モデル
|
||||
- **Rust**: `Cargo.toml + mod/use` - 厳格で分かりやすい
|
||||
- **Node.js**: `package.json + import/export` - エコシステム成功
|
||||
- **Python**: `pyproject.toml + import` - 依存関係分離
|
||||
|
||||
## 📋 nyash.linkファイル仕様
|
||||
|
||||
### 基本フォーマット
|
||||
```toml
|
||||
# nyash.link (プロジェクトルート)
|
||||
[project]
|
||||
name = "my-nyash-project"
|
||||
version = "0.1.0"
|
||||
description = "素晴らしいNyashプロジェクト"
|
||||
|
||||
[dependencies]
|
||||
# 標準ライブラリ
|
||||
nyashstd = { path = "./stdlib/nyashstd.hako" }
|
||||
|
||||
# ユーザーライブラリ
|
||||
mylib = { path = "./libs/mylib.hako" }
|
||||
utils = { path = "./src/utils.hako" }
|
||||
|
||||
# 将来の外部パッケージ(例)
|
||||
# http_client = { version = "1.0.0", registry = "nyash-pkg" }
|
||||
|
||||
[search_paths]
|
||||
stdlib = "./stdlib/"
|
||||
libs = "./libs/"
|
||||
src = "./src/"
|
||||
|
||||
[build]
|
||||
entry_point = "./src/main.hako"
|
||||
```
|
||||
|
||||
### 依存関係タイプ
|
||||
|
||||
#### 1. **ローカル依存**
|
||||
```toml
|
||||
[dependencies]
|
||||
my_module = { path = "./src/my_module.hako" }
|
||||
```
|
||||
|
||||
#### 2. **標準ライブラリ**
|
||||
```toml
|
||||
[dependencies]
|
||||
nyashstd = { stdlib = true } # 特別扱い
|
||||
```
|
||||
|
||||
#### 3. **将来の外部パッケージ**
|
||||
```toml
|
||||
[dependencies]
|
||||
awesome_lib = { version = "^1.2.0", registry = "nyash-pkg" }
|
||||
```
|
||||
|
||||
## 🔧 usingシステム設計
|
||||
|
||||
### 1. トークナイザー拡張
|
||||
```rust
|
||||
// src/tokenizer.rs に追加
|
||||
pub enum TokenType {
|
||||
// 既存...
|
||||
USING, // using (モジュールインポート)
|
||||
NAMESPACE, // namespace (名前空間宣言)
|
||||
}
|
||||
```
|
||||
|
||||
### 2. パーサー拡張
|
||||
```rust
|
||||
// AST拡張
|
||||
pub enum Statement {
|
||||
// 既存...
|
||||
UsingStatement {
|
||||
module_path: Vec<String>, // ["nyashstd", "string"]
|
||||
alias: Option<String>, // using nyashstd.string as str
|
||||
},
|
||||
NamespaceDeclaration {
|
||||
name: String,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 基本構文
|
||||
```nyash
|
||||
// ===== using構文パターン =====
|
||||
|
||||
// パターンA: 名前空間全体
|
||||
using nyashstd
|
||||
string.upper("hello") // nyashstd.string.upper
|
||||
math.sin(3.14) // nyashstd.math.sin
|
||||
|
||||
// パターンB: 特定機能(将来拡張)
|
||||
using nyashstd.string
|
||||
upper("hello") // string.upperを直接
|
||||
|
||||
// パターンC: エイリアス(将来拡張)
|
||||
using nyashstd.string as str
|
||||
str.upper("hello")
|
||||
|
||||
// パターンD: 完全修飾名(常時利用可能)
|
||||
nyashstd.string.upper("hello") // using不要
|
||||
```
|
||||
|
||||
## 📁 推奨ディレクトリ構造
|
||||
|
||||
### 基本プロジェクト構造
|
||||
```
|
||||
my-nyash-project/
|
||||
├── nyash.link # 依存関係定義
|
||||
├── src/
|
||||
│ ├── main.hako # エントリーポイント
|
||||
│ ├── utils.hako # ユーティリティモジュール
|
||||
│ └── models/
|
||||
│ └── user.hako # モデル定義
|
||||
├── libs/ # プロジェクト固有ライブラリ
|
||||
│ └── mylib.hako
|
||||
├── stdlib/ # 標準ライブラリ(システム配布)
|
||||
│ └── nyashstd.hako
|
||||
└── tests/ # テストファイル
|
||||
└── test_main.hako
|
||||
```
|
||||
|
||||
### 標準ライブラリ構造
|
||||
```
|
||||
stdlib/
|
||||
├── nyashstd.hako # メインエントリー
|
||||
├── string/
|
||||
│ └── mod.hako # string関連機能
|
||||
├── math/
|
||||
│ └── mod.hako # 数学関数
|
||||
├── http/
|
||||
│ └── mod.hako # HTTP関連
|
||||
└── io/
|
||||
└── mod.hako # I/O関連
|
||||
```
|
||||
|
||||
## 🔄 動作フロー
|
||||
|
||||
### 1. プロジェクト初期化
|
||||
```bash
|
||||
# 将来のCLI例
|
||||
nyash init my-project # nyash.linkテンプレート生成
|
||||
cd my-project
|
||||
```
|
||||
|
||||
### 2. 実行時解決
|
||||
```
|
||||
main.hako実行
|
||||
↓
|
||||
nyash.link読み込み
|
||||
↓
|
||||
using nyashstd解析
|
||||
↓
|
||||
./stdlib/nyashstd.hako読み込み
|
||||
↓
|
||||
namespace nyashstd解析・登録
|
||||
↓
|
||||
string.upper()利用可能
|
||||
```
|
||||
|
||||
### 3. 名前解決アルゴリズム
|
||||
```
|
||||
string.upper() 呼び出し
|
||||
↓
|
||||
1. ローカルスコープ検索
|
||||
2. usingでインポートされた名前空間検索
|
||||
3. 完全修飾名として解釈
|
||||
4. エラー(未定義)
|
||||
```
|
||||
|
||||
## 🧪 実装段階
|
||||
|
||||
### Phase 1: 最小実装
|
||||
```nyash
|
||||
// ✅ 実装目標
|
||||
using mylib // 単純パス解決
|
||||
mylib.hello() // 関数呼び出し
|
||||
|
||||
// nyash.link
|
||||
[dependencies]
|
||||
mylib = { path = "./mylib.hako" }
|
||||
```
|
||||
|
||||
### Phase 2: 名前空間サポート
|
||||
```nyash
|
||||
// ✅ 実装目標
|
||||
using nyashstd
|
||||
string.upper("hello")
|
||||
|
||||
// nyashstd.hako
|
||||
namespace nyashstd {
|
||||
static box string {
|
||||
static upper(str) { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: 高度機能
|
||||
- エイリアス(`using ... as ...`)
|
||||
- 選択インポート(`using nyashstd.string`)
|
||||
- 循環依存検出
|
||||
- パッケージレジストリ連携
|
||||
|
||||
## ⚡ 実装優先順位
|
||||
|
||||
### 🚨 Critical(即時)
|
||||
1. **UsingTokenizer実装** - Token::USINGを追加
|
||||
2. **基本パーサー** - using文AST構築
|
||||
3. **nyash.link解析** - TOML読み込み機能
|
||||
|
||||
### ⚡ High(今週)
|
||||
4. **名前解決エンジン** - モジュール→ファイル解決
|
||||
5. **基本テスト** - using mylib動作確認
|
||||
6. **エラー処理** - 未定義モジュール等
|
||||
|
||||
### 📝 Medium(来週)
|
||||
7. **namespace構文** - static box解析
|
||||
8. **標準ライブラリ設計** - nyashstd.hako作成
|
||||
9. **完全修飾名** - nyashstd.string.upper()
|
||||
|
||||
### 🔮 Future(今後)
|
||||
10. **IDE連携** - Language Server補完
|
||||
11. **パッケージマネージャー** - 外部レジストリ
|
||||
12. **循環依存検出** - 高度エラー処理
|
||||
|
||||
## 🎉 期待効果
|
||||
|
||||
### 📈 開発体験向上
|
||||
- **IDE補完**: `ny`→全標準機能表示
|
||||
- **探索可能性**: モジュール構造が明確
|
||||
- **エラー削減**: 名前衝突・未定義の事前検出
|
||||
|
||||
### 🏗️ プロジェクト管理
|
||||
- **依存関係明確化**: nyash.linkで一元管理
|
||||
- **ビルド再現性**: 他環境での確実な動作
|
||||
- **スケーラビリティ**: 大規模プロジェクト対応
|
||||
|
||||
### 🌍 エコシステム発展
|
||||
- **ライブラリ共有**: 標準化されたモジュール形式
|
||||
- **コミュニティ成長**: パッケージレジストリ基盤
|
||||
- **言語成熟度**: モダンな言語仕様
|
||||
|
||||
---
|
||||
|
||||
**🐾 この設計でNyashが真にモダンなプログラミング言語になるにゃ!**
|
||||
@ -1,654 +0,0 @@
|
||||
# BID×usingシステム統合:技術実装詳細
|
||||
|
||||
## 🎯 統合設計の核心
|
||||
|
||||
### 📊 既存システムとの整合性
|
||||
- ✅ **MIR ExternCall**: 既にFFI-ABI対応実装済み
|
||||
- ✅ **WASM RuntimeImports**: BID→WASM自動生成基盤あり
|
||||
- ✅ **VM ExternStub**: スタブ実行環境実装済み
|
||||
- 🔧 **統合課題**: usingシステムとBIDの橋渡し実装
|
||||
|
||||
### 🚀 統合アーキテクチャ概要
|
||||
```
|
||||
User Code (using statements)
|
||||
↓
|
||||
UniversalNamespaceRegistry
|
||||
↓
|
||||
CallTarget Resolution
|
||||
↓ ↓ ↓
|
||||
Builtin FFI-ABI NyashModule
|
||||
↓ ↓ ↓
|
||||
MIR Generation (BuiltinCall/ExternCall/ModuleCall)
|
||||
↓
|
||||
Backend Execution (VM/WASM/AOT)
|
||||
```
|
||||
|
||||
## 🏗️ 詳細技術実装
|
||||
|
||||
### 1. BID定義システム
|
||||
|
||||
#### **BIDファイル構造拡張**
|
||||
```yaml
|
||||
# apis/enhanced_canvas.yaml
|
||||
version: 1
|
||||
metadata:
|
||||
name: "Enhanced Canvas API"
|
||||
description: "Extended Canvas API with batch operations"
|
||||
target_environments: ["browser", "node-canvas", "skia"]
|
||||
nyash_namespace: "canvas_api" # usingで使用する名前空間
|
||||
|
||||
interfaces:
|
||||
- name: canvas_api.canvas
|
||||
box: Canvas
|
||||
methods:
|
||||
# 基本描画
|
||||
- name: fillRect
|
||||
params:
|
||||
- {string: canvas_id, description: "Canvas element ID"}
|
||||
- {i32: x, description: "X coordinate"}
|
||||
- {i32: y, description: "Y coordinate"}
|
||||
- {i32: width, description: "Rectangle width"}
|
||||
- {i32: height, description: "Rectangle height"}
|
||||
- {string: color, description: "Fill color (CSS format)"}
|
||||
returns: void
|
||||
effect: io
|
||||
optimization_hints:
|
||||
batch_compatible: true # バッチ処理可能
|
||||
gpu_accelerated: true # GPU加速対応
|
||||
|
||||
# バッチ描画(最適化版)
|
||||
- name: fillRectBatch
|
||||
params:
|
||||
- {string: canvas_id}
|
||||
- {array_of_rect: rects, element_type: "CanvasRect"}
|
||||
returns: void
|
||||
effect: io
|
||||
optimization_hints:
|
||||
prefer_over: ["fillRect"] # 複数fillRectの代替
|
||||
min_batch_size: 3
|
||||
|
||||
# テキスト描画
|
||||
- name: fillText
|
||||
params:
|
||||
- {string: canvas_id}
|
||||
- {string: text}
|
||||
- {i32: x}
|
||||
- {i32: y}
|
||||
- {string: font}
|
||||
- {string: color}
|
||||
returns: void
|
||||
effect: io
|
||||
|
||||
# カスタム型定義
|
||||
custom_types:
|
||||
- name: CanvasRect
|
||||
fields:
|
||||
- {i32: x}
|
||||
- {i32: y}
|
||||
- {i32: width}
|
||||
- {i32: height}
|
||||
- {string: color}
|
||||
```
|
||||
|
||||
#### **BID読み込み・検証システム**
|
||||
```rust
|
||||
// 新ファイル: src/bid/mod.rs
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct BidDefinition {
|
||||
pub version: u32,
|
||||
pub metadata: BidMetadata,
|
||||
pub interfaces: Vec<BidInterface>,
|
||||
pub custom_types: Option<Vec<BidCustomType>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct BidMetadata {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub target_environments: Vec<String>,
|
||||
pub nyash_namespace: String, // using文で使用する名前空間名
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct BidInterface {
|
||||
pub name: String, // "canvas_api.canvas"
|
||||
pub box_name: String, // "Canvas"
|
||||
pub methods: Vec<BidMethod>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct BidMethod {
|
||||
pub name: String,
|
||||
pub params: Vec<BidParam>,
|
||||
pub returns: BidType,
|
||||
pub effect: BidEffect,
|
||||
pub optimization_hints: Option<BidOptimizationHints>,
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct BidOptimizationHints {
|
||||
pub batch_compatible: Option<bool>,
|
||||
pub gpu_accelerated: Option<bool>,
|
||||
pub prefer_over: Option<Vec<String>>,
|
||||
pub min_batch_size: Option<usize>,
|
||||
}
|
||||
|
||||
impl BidDefinition {
|
||||
pub fn load_from_file(path: &Path) -> Result<Self, BidError> {
|
||||
let content = std::fs::read_to_string(path)?;
|
||||
let bid: BidDefinition = serde_yaml::from_str(&content)?;
|
||||
|
||||
// バリデーション
|
||||
bid.validate()?;
|
||||
|
||||
Ok(bid)
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> Result<(), BidError> {
|
||||
// バージョン確認
|
||||
if self.version > 1 {
|
||||
return Err(BidError::UnsupportedVersion(self.version));
|
||||
}
|
||||
|
||||
// 名前空間重複チェック
|
||||
let mut interface_names = HashSet::new();
|
||||
for interface in &self.interfaces {
|
||||
if interface_names.contains(&interface.name) {
|
||||
return Err(BidError::DuplicateInterface(interface.name.clone()));
|
||||
}
|
||||
interface_names.insert(interface.name.clone());
|
||||
}
|
||||
|
||||
// パラメータ型確認
|
||||
for interface in &self.interfaces {
|
||||
for method in &interface.methods {
|
||||
for param in &method.params {
|
||||
self.validate_type(¶m.param_type)?;
|
||||
}
|
||||
self.validate_type(&method.returns)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn resolve_method(&self, box_name: &str, method_name: &str)
|
||||
-> Option<&BidMethod> {
|
||||
|
||||
for interface in &self.interfaces {
|
||||
// インターフェース名から最後の部分を取得
|
||||
// "canvas_api.canvas" → "canvas"
|
||||
let interface_box_name = interface.name.split('.').last().unwrap_or(&interface.name);
|
||||
|
||||
if interface_box_name == box_name {
|
||||
for method in &interface.methods {
|
||||
if method.name == method_name {
|
||||
return Some(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 統合名前空間レジストリ詳細
|
||||
|
||||
#### **UniversalNamespaceRegistry実装**
|
||||
```rust
|
||||
// src/registry/universal.rs
|
||||
use crate::stdlib::BuiltinStdlib;
|
||||
use crate::bid::BidDefinition;
|
||||
use crate::module::ExternalModule;
|
||||
use crate::mir::Effect;
|
||||
|
||||
pub struct UniversalNamespaceRegistry {
|
||||
/// 組み込み標準ライブラリ
|
||||
builtin_stdlib: Arc<BuiltinStdlib>,
|
||||
|
||||
/// FFI-ABI定義(BID)
|
||||
bid_definitions: HashMap<String, Arc<BidDefinition>>,
|
||||
|
||||
/// Nyashモジュール(従来)
|
||||
nyash_modules: HashMap<String, Arc<ExternalModule>>,
|
||||
|
||||
/// ファイル別usingコンテキスト
|
||||
using_contexts: Arc<RwLock<HashMap<String, UsingContext>>>,
|
||||
|
||||
/// 最適化情報キャッシュ
|
||||
optimization_cache: Arc<RwLock<OptimizationCache>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UsingContext {
|
||||
pub file_id: String,
|
||||
pub builtin_namespaces: Vec<String>, // ["nyashstd"]
|
||||
pub bid_namespaces: Vec<String>, // ["canvas_api", "console_api"]
|
||||
pub module_namespaces: Vec<String>, // ["mylib", "utils"]
|
||||
}
|
||||
|
||||
impl UniversalNamespaceRegistry {
|
||||
pub fn new() -> Self {
|
||||
UniversalNamespaceRegistry {
|
||||
builtin_stdlib: Arc::new(BuiltinStdlib::new()),
|
||||
bid_definitions: HashMap::new(),
|
||||
nyash_modules: HashMap::new(),
|
||||
using_contexts: Arc::new(RwLock::new(HashMap::new())),
|
||||
optimization_cache: Arc::new(RwLock::new(OptimizationCache::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_from_nyash_link(&mut self, nyash_link: &NyashLink)
|
||||
-> Result<(), RegistryError> {
|
||||
|
||||
// BID依存関係読み込み
|
||||
for (namespace_name, dependency) in &nyash_link.dependencies {
|
||||
match dependency {
|
||||
Dependency::Bid { bid_path, .. } => {
|
||||
let bid = BidDefinition::load_from_file(Path::new(bid_path))?;
|
||||
self.bid_definitions.insert(namespace_name.clone(), Arc::new(bid));
|
||||
},
|
||||
Dependency::Path { path } => {
|
||||
let module = ExternalModule::load_from_file(Path::new(path))?;
|
||||
self.hako_modules.insert(namespace_name.clone(), Arc::new(module));
|
||||
},
|
||||
Dependency::Builtin { .. } => {
|
||||
// 組み込みライブラリは既に初期化済み
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 統合using処理
|
||||
pub fn process_using(&mut self, namespace_name: &str, file_id: &str)
|
||||
-> Result<(), RuntimeError> {
|
||||
|
||||
let mut contexts = self.using_contexts.write().unwrap();
|
||||
let context = contexts.entry(file_id.to_string()).or_insert_with(|| {
|
||||
UsingContext {
|
||||
file_id: file_id.to_string(),
|
||||
builtin_namespaces: Vec::new(),
|
||||
bid_namespaces: Vec::new(),
|
||||
module_namespaces: Vec::new(),
|
||||
}
|
||||
});
|
||||
|
||||
// 組み込み標準ライブラリチェック
|
||||
if self.builtin_stdlib.has_namespace(namespace_name) {
|
||||
if !context.builtin_namespaces.contains(&namespace_name.to_string()) {
|
||||
context.builtin_namespaces.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// BID定義チェック
|
||||
if let Some(bid) = self.bid_definitions.get(namespace_name) {
|
||||
if !context.bid_namespaces.contains(&namespace_name.to_string()) {
|
||||
context.bid_namespaces.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Nyashモジュールチェック
|
||||
if let Some(_module) = self.hako_modules.get(namespace_name) {
|
||||
if !context.module_namespaces.contains(&namespace_name.to_string()) {
|
||||
context.module_namespaces.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedNamespace(namespace_name.to_string()))
|
||||
}
|
||||
|
||||
/// 統合関数解決
|
||||
pub fn resolve_call(&self, file_id: &str, call_path: &[String])
|
||||
-> Result<ResolvedCall, RuntimeError> {
|
||||
|
||||
if call_path.len() != 2 {
|
||||
return Err(RuntimeError::InvalidCallPath(call_path.join(".")));
|
||||
}
|
||||
|
||||
let box_name = &call_path[0];
|
||||
let method_name = &call_path[1];
|
||||
|
||||
let contexts = self.using_contexts.read().unwrap();
|
||||
if let Some(context) = contexts.get(file_id) {
|
||||
|
||||
// 1. 組み込み標準ライブラリ解決
|
||||
for namespace in &context.builtin_namespaces {
|
||||
if let Some(method) = self.builtin_stdlib.resolve_method(namespace, box_name, method_name) {
|
||||
return Ok(ResolvedCall::Builtin {
|
||||
namespace: namespace.clone(),
|
||||
box_name: box_name.clone(),
|
||||
method_name: method_name.clone(),
|
||||
method_info: method,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 2. BID定義解決
|
||||
for namespace in &context.bid_namespaces {
|
||||
if let Some(bid) = self.bid_definitions.get(namespace) {
|
||||
if let Some(method) = bid.resolve_method(box_name, method_name) {
|
||||
return Ok(ResolvedCall::BidCall {
|
||||
namespace: namespace.clone(),
|
||||
interface_name: format!("{}.{}", namespace, box_name),
|
||||
method_name: method_name.clone(),
|
||||
method_info: method.clone(),
|
||||
bid_definition: bid.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Nyashモジュール解決
|
||||
for namespace in &context.module_namespaces {
|
||||
if let Some(module) = self.hako_modules.get(namespace) {
|
||||
if let Some(function) = module.resolve_function(box_name, method_name) {
|
||||
return Ok(ResolvedCall::ModuleCall {
|
||||
namespace: namespace.clone(),
|
||||
module_name: namespace.clone(),
|
||||
function_name: format!("{}.{}", box_name, method_name),
|
||||
function_info: function,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedMethod(format!("{}.{}", box_name, method_name)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ResolvedCall {
|
||||
Builtin {
|
||||
namespace: String,
|
||||
box_name: String,
|
||||
method_name: String,
|
||||
method_info: BuiltinMethodInfo,
|
||||
},
|
||||
BidCall {
|
||||
namespace: String,
|
||||
interface_name: String,
|
||||
method_name: String,
|
||||
method_info: BidMethod,
|
||||
bid_definition: Arc<BidDefinition>,
|
||||
},
|
||||
ModuleCall {
|
||||
namespace: String,
|
||||
module_name: String,
|
||||
function_name: String,
|
||||
function_info: ModuleFunctionInfo,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 3. MIR生成統合
|
||||
|
||||
#### **統合MIR Builder**
|
||||
```rust
|
||||
// src/mir/builder.rs拡張
|
||||
impl MirBuilder {
|
||||
pub fn build_unified_method_call(&mut self, resolved_call: ResolvedCall, args: Vec<ValueId>)
|
||||
-> Result<Option<ValueId>, MirError> {
|
||||
|
||||
match resolved_call {
|
||||
ResolvedCall::Builtin { method_info, .. } => {
|
||||
let result = self.new_value_id();
|
||||
|
||||
self.emit(MirInstruction::BuiltinCall {
|
||||
qualified_name: method_info.qualified_name(),
|
||||
args,
|
||||
result,
|
||||
effect: method_info.effect(),
|
||||
});
|
||||
|
||||
Ok(Some(result))
|
||||
},
|
||||
|
||||
ResolvedCall::BidCall { interface_name, method_name, method_info, .. } => {
|
||||
let result = if method_info.returns == BidType::Void {
|
||||
None
|
||||
} else {
|
||||
Some(self.new_value_id())
|
||||
};
|
||||
|
||||
self.emit(MirInstruction::ExternCall {
|
||||
interface: interface_name,
|
||||
method: method_name,
|
||||
args,
|
||||
result,
|
||||
effect: self.bid_effect_to_mir_effect(&method_info.effect),
|
||||
bid_signature: BidSignature::from_method(&method_info),
|
||||
});
|
||||
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
ResolvedCall::ModuleCall { module_name, function_name, function_info, .. } => {
|
||||
let result = self.new_value_id();
|
||||
|
||||
self.emit(MirInstruction::ModuleCall {
|
||||
module: module_name,
|
||||
function: function_name,
|
||||
args,
|
||||
result,
|
||||
effect: Effect::Io, // Nyashモジュールはデフォルトでio
|
||||
});
|
||||
|
||||
Ok(Some(result))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn bid_effect_to_mir_effect(&self, bid_effect: &BidEffect) -> Effect {
|
||||
match bid_effect {
|
||||
BidEffect::Pure => Effect::Pure,
|
||||
BidEffect::Mut => Effect::Mut,
|
||||
BidEffect::Io => Effect::Io,
|
||||
BidEffect::Control => Effect::Control,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. バックエンド統合
|
||||
|
||||
#### **WASM生成統合**
|
||||
```rust
|
||||
// src/backend/wasm/codegen.rs拡張
|
||||
impl WasmCodegen {
|
||||
pub fn generate_unified_call(&mut self, instruction: &MirInstruction)
|
||||
-> Result<(), WasmError> {
|
||||
|
||||
match instruction {
|
||||
MirInstruction::ExternCall { interface, method, args, bid_signature, .. } => {
|
||||
// BIDから自動生成されたWASM import名
|
||||
let wasm_import_name = self.bid_to_wasm_import_name(interface, method);
|
||||
|
||||
// 引数の型変換・マーシャリング
|
||||
let marshalled_args = self.marshal_args_for_wasm(args, &bid_signature.params)?;
|
||||
|
||||
// WASM関数呼び出し生成
|
||||
self.emit_call(&wasm_import_name, &marshalled_args)?;
|
||||
|
||||
// 戻り値のアンマーシャリング
|
||||
if bid_signature.returns != BidType::Void {
|
||||
self.unmarshal_return_value(&bid_signature.returns)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// 他の命令は既存実装
|
||||
_ => self.generate_instruction_legacy(instruction),
|
||||
}
|
||||
}
|
||||
|
||||
fn bid_to_wasm_import_name(&self, interface: &str, method: &str) -> String {
|
||||
// "canvas_api.canvas" + "fillRect" → "canvas_api_canvas_fillRect"
|
||||
format!("{}_{}", interface.replace(".", "_"), method)
|
||||
}
|
||||
|
||||
fn marshal_args_for_wasm(&mut self, args: &[ValueId], params: &[BidParam])
|
||||
-> Result<Vec<WasmValue>, WasmError> {
|
||||
|
||||
let mut marshalled = Vec::new();
|
||||
|
||||
for (i, param) in params.iter().enumerate() {
|
||||
let arg_value = self.get_value(args[i])?;
|
||||
|
||||
match ¶m.param_type {
|
||||
BidType::String => {
|
||||
// 文字列を (ptr, len) にマーシャル
|
||||
let (ptr, len) = self.string_to_wasm_memory(&arg_value)?;
|
||||
marshalled.push(WasmValue::I32(ptr));
|
||||
marshalled.push(WasmValue::I32(len));
|
||||
},
|
||||
BidType::I32 => {
|
||||
marshalled.push(WasmValue::I32(arg_value.to_i32()?));
|
||||
},
|
||||
BidType::F64 => {
|
||||
marshalled.push(WasmValue::F64(arg_value.to_f64()?));
|
||||
},
|
||||
// その他の型...
|
||||
}
|
||||
}
|
||||
|
||||
Ok(marshalled)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **VM実行統合**
|
||||
```rust
|
||||
// src/backend/vm.rs拡張
|
||||
impl VmBackend {
|
||||
pub fn execute_unified_instruction(&mut self, instruction: &MirInstruction)
|
||||
-> Result<(), VmError> {
|
||||
|
||||
match instruction {
|
||||
MirInstruction::ExternCall { interface, method, args, bid_signature, .. } => {
|
||||
// VM環境ではスタブまたはネイティブ呼び出し
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
|
||||
if let Some(native_impl) = self.find_native_implementation(interface, method) {
|
||||
// ネイティブ実装がある場合(例:ファイルI/O)
|
||||
let result = native_impl.call(evaluated_args, bid_signature)?;
|
||||
if let Some(result_id) = &instruction.result {
|
||||
self.set_value(*result_id, result);
|
||||
}
|
||||
} else {
|
||||
// スタブ実装(ログ出力等)
|
||||
self.execute_stub_call(interface, method, evaluated_args, bid_signature)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// 他の命令は既存実装
|
||||
_ => self.execute_instruction_legacy(instruction),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_native_implementation(&self, interface: &str, method: &str)
|
||||
-> Option<&dyn NativeImplementation> {
|
||||
|
||||
// VM環境で利用可能なネイティブ実装を検索
|
||||
match (interface, method) {
|
||||
("env.console", "log") => Some(&self.console_impl),
|
||||
("env.filesystem", "read") => Some(&self.filesystem_impl),
|
||||
("env.filesystem", "write") => Some(&self.filesystem_impl),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 統合テスト戦略
|
||||
|
||||
### Phase別テスト実装
|
||||
|
||||
#### **Phase 0: 基本統合テスト**
|
||||
```nyash
|
||||
# test_basic_integration.hako
|
||||
using nyashstd
|
||||
|
||||
# 組み込み標準ライブラリのみ
|
||||
assert(string.upper("test") == "TEST")
|
||||
assert(math.sin(0) == 0)
|
||||
```
|
||||
|
||||
#### **Phase 1: BID統合テスト**
|
||||
```nyash
|
||||
# test_bid_integration.hako
|
||||
using nyashstd
|
||||
using console_api
|
||||
|
||||
# 組み込み + FFI-ABI
|
||||
string.upper("hello") # 組み込み
|
||||
console.log("Testing") # FFI-ABI
|
||||
```
|
||||
|
||||
#### **Phase 2: 完全統合テスト**
|
||||
```nyash
|
||||
# test_full_integration.hako
|
||||
using nyashstd
|
||||
using console_api
|
||||
using mylib
|
||||
|
||||
# 3種類すべて
|
||||
string.upper("test") # 組み込み
|
||||
console.log("Integration") # FFI-ABI
|
||||
mylib.process("data") # Nyashモジュール
|
||||
```
|
||||
|
||||
### エラーハンドリングテスト
|
||||
```nyash
|
||||
# test_error_handling.hako
|
||||
try {
|
||||
using nonexistent_api
|
||||
} catch error {
|
||||
assert(error.type == "UndefinedNamespace")
|
||||
}
|
||||
|
||||
try {
|
||||
console.nonexistent_method("test")
|
||||
} catch error {
|
||||
assert(error.type == "UndefinedMethod")
|
||||
assert(error.message.contains("Available methods:"))
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 実装マイルストーン
|
||||
|
||||
### ✅ Phase 0完了条件
|
||||
- [ ] UniversalNamespaceRegistry基盤実装
|
||||
- [ ] 組み込み標準ライブラリ統合
|
||||
- [ ] 基本using文処理
|
||||
- [ ] MIR BuiltinCall生成
|
||||
|
||||
### ✅ Phase 1完了条件
|
||||
- [ ] BID定義読み込み・検証
|
||||
- [ ] BID→MIR ExternCall統合
|
||||
- [ ] WASM RuntimeImports自動生成
|
||||
- [ ] VM スタブ実行
|
||||
|
||||
### ✅ Phase 2完了条件
|
||||
- [ ] Nyashモジュール統合
|
||||
- [ ] 統合エラーハンドリング
|
||||
- [ ] 最適化キャッシュ
|
||||
- [ ] 全バックエンド対応
|
||||
|
||||
---
|
||||
|
||||
**🎯 この詳細実装により、BIDとusingシステムの完全統合が実現でき、「なんでもAPI計画」の技術基盤が完成するにゃ!🚀🐱**
|
||||
@ -1,456 +0,0 @@
|
||||
# 組み込みnyashstd名前空間アーキテクチャ設計
|
||||
|
||||
## 🏗️ 技術的実装アーキテクチャ
|
||||
|
||||
### 📊 現在のインタープリター構造分析
|
||||
|
||||
#### **NyashInterpreter構造**
|
||||
```rust
|
||||
pub struct NyashInterpreter {
|
||||
pub(super) shared: SharedState, // 共有状態
|
||||
pub(super) local_vars: HashMap<String, SharedNyashBox>,
|
||||
pub(super) outbox_vars: HashMap<String, SharedNyashBox>,
|
||||
// その他の制御フロー状態...
|
||||
}
|
||||
```
|
||||
|
||||
#### **設計判断:SharedStateに組み込み**
|
||||
- **理由**: 標準ライブラリは不変・全インタープリターで共有可能
|
||||
- **利点**: メモリ効率、パフォーマンス向上
|
||||
- **実装**: SharedStateに`builtin_stdlib`フィールド追加
|
||||
|
||||
## 🌟 最適化されたアーキテクチャ設計
|
||||
|
||||
### 1. SharedState拡張
|
||||
|
||||
#### **src/interpreter/core.rs**
|
||||
```rust
|
||||
#[derive(Clone)]
|
||||
pub struct SharedState {
|
||||
// 既存フィールド...
|
||||
pub global_vars: Arc<RwLock<HashMap<String, SharedNyashBox>>>,
|
||||
pub functions: Arc<RwLock<HashMap<String, Function>>>,
|
||||
pub box_definitions: Arc<RwLock<HashMap<String, Box<UserDefinedBoxDefinition>>>>,
|
||||
pub loop_counter: Arc<AtomicU64>,
|
||||
pub included_files: Arc<RwLock<HashSet<String>>>,
|
||||
|
||||
// 🌟 新規追加: 組み込み標準ライブラリ
|
||||
pub builtin_stdlib: Arc<BuiltinStdlib>,
|
||||
pub using_imports: Arc<RwLock<HashMap<String, UsingContext>>>, // ファイル別インポート管理
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UsingContext {
|
||||
pub imported_namespaces: Vec<String>, // ["nyashstd"]
|
||||
pub file_id: String, // インポート元ファイル識別
|
||||
}
|
||||
```
|
||||
|
||||
### 2. BuiltinStdlib効率化設計
|
||||
|
||||
#### **新ファイル: src/stdlib/builtin.rs**
|
||||
```rust
|
||||
//! 🚀 高性能組み込み標準ライブラリ
|
||||
//!
|
||||
//! 設計方針:
|
||||
//! - Zero-allocation関数実行
|
||||
//! - 高速名前解決
|
||||
//! - 既存Box実装の最大活用
|
||||
|
||||
use crate::boxes::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// 組み込み標準ライブラリのメイン構造体
|
||||
#[derive(Debug)]
|
||||
pub struct BuiltinStdlib {
|
||||
/// 高速アクセス用:フラットな関数マップ
|
||||
/// "string.upper" -> BuiltinFunction
|
||||
pub flat_functions: HashMap<String, BuiltinFunction>,
|
||||
|
||||
/// IDE補完用:階層構造
|
||||
/// "nyashstd" -> { "string" -> ["upper", "lower", ...] }
|
||||
pub hierarchical_map: HashMap<String, HashMap<String, Vec<String>>>,
|
||||
}
|
||||
|
||||
/// 組み込み関数の実装
|
||||
pub struct BuiltinFunction {
|
||||
pub namespace: &'static str, // "nyashstd"
|
||||
pub box_name: &'static str, // "string"
|
||||
pub method_name: &'static str, // "upper"
|
||||
pub implementation: BuiltinMethodImpl,
|
||||
pub arg_count: Option<usize>, // None = 可変長
|
||||
pub description: &'static str, // エラーメッセージ・ヘルプ用
|
||||
}
|
||||
|
||||
/// 高性能関数実装
|
||||
pub type BuiltinMethodImpl = fn(&[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError>;
|
||||
|
||||
impl BuiltinStdlib {
|
||||
/// 🚀 標準ライブラリ初期化(起動時1回のみ)
|
||||
pub fn new() -> Self {
|
||||
let mut stdlib = BuiltinStdlib {
|
||||
flat_functions: HashMap::new(),
|
||||
hierarchical_map: HashMap::new(),
|
||||
};
|
||||
|
||||
// 標準関数登録
|
||||
stdlib.register_all_functions();
|
||||
|
||||
stdlib
|
||||
}
|
||||
|
||||
/// ⚡ 高速関数解決
|
||||
pub fn get_function(&self, qualified_name: &str) -> Option<&BuiltinFunction> {
|
||||
// "string.upper" で直接アクセス
|
||||
self.flat_functions.get(qualified_name)
|
||||
}
|
||||
|
||||
/// 🔍 IDE補完用:利用可能関数一覧取得
|
||||
pub fn get_available_methods(&self, namespace: &str, box_name: &str) -> Option<&Vec<String>> {
|
||||
self.hierarchical_map.get(namespace)?.get(box_name)
|
||||
}
|
||||
|
||||
/// 📋 全名前空間取得(IDE補完用)
|
||||
pub fn get_all_namespaces(&self) -> Vec<&String> {
|
||||
self.hierarchical_map.keys().collect()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 標準関数実装(高性能版)
|
||||
|
||||
#### **文字列関数実装**
|
||||
```rust
|
||||
impl BuiltinStdlib {
|
||||
fn register_all_functions(&mut self) {
|
||||
// === nyashstd.string.* ===
|
||||
self.register_function("string.upper", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "upper",
|
||||
implementation: |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.upper(str) takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
// 🚀 既存StringBox実装活用
|
||||
let input_str = args[0].to_string_box().value;
|
||||
let result = StringBox::new(&input_str.to_uppercase());
|
||||
Ok(Box::new(result))
|
||||
},
|
||||
arg_count: Some(1),
|
||||
description: "Convert string to uppercase",
|
||||
});
|
||||
|
||||
self.register_function("string.lower", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "lower",
|
||||
implementation: |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.lower(str) takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let input_str = args[0].to_string_box().value;
|
||||
let result = StringBox::new(&input_str.to_lowercase());
|
||||
Ok(Box::new(result))
|
||||
},
|
||||
arg_count: Some(1),
|
||||
description: "Convert string to lowercase",
|
||||
});
|
||||
|
||||
self.register_function("string.split", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "split",
|
||||
implementation: |args| {
|
||||
if args.len() != 2 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.split(str, separator) takes exactly 2 arguments".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
// 🚀 既存StringBox.split()メソッド活用
|
||||
let string_box = StringBox::new(&args[0].to_string_box().value);
|
||||
let separator = &args[1].to_string_box().value;
|
||||
string_box.split(separator)
|
||||
},
|
||||
arg_count: Some(2),
|
||||
description: "Split string by separator into array",
|
||||
});
|
||||
|
||||
// === nyashstd.math.* ===
|
||||
self.register_function("math.sin", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "math",
|
||||
method_name: "sin",
|
||||
implementation: |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"math.sin(x) takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
// 🚀 既存MathBox実装活用
|
||||
let math_box = MathBox::new();
|
||||
let x = args[0].to_integer_box().value as f64;
|
||||
let result = math_box.sin(x)?;
|
||||
Ok(result)
|
||||
},
|
||||
arg_count: Some(1),
|
||||
description: "Calculate sine of x (in radians)",
|
||||
});
|
||||
|
||||
// 階層マップも同時構築
|
||||
self.build_hierarchical_map();
|
||||
}
|
||||
|
||||
fn register_function(&mut self, qualified_name: &str, function: BuiltinFunction) {
|
||||
self.flat_functions.insert(qualified_name.to_string(), function);
|
||||
}
|
||||
|
||||
fn build_hierarchical_map(&mut self) {
|
||||
for (qualified_name, function) in &self.flat_functions {
|
||||
let namespace_map = self.hierarchical_map
|
||||
.entry(function.namespace.to_string())
|
||||
.or_insert_with(HashMap::new);
|
||||
|
||||
let method_list = namespace_map
|
||||
.entry(function.box_name.to_string())
|
||||
.or_insert_with(Vec::new);
|
||||
|
||||
method_list.push(function.method_name.to_string());
|
||||
}
|
||||
|
||||
// ソートして一貫性確保
|
||||
for namespace_map in self.hierarchical_map.values_mut() {
|
||||
for method_list in namespace_map.values_mut() {
|
||||
method_list.sort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. インタープリター統合
|
||||
|
||||
#### **NyashInterpreter拡張**
|
||||
```rust
|
||||
impl NyashInterpreter {
|
||||
/// using文実行
|
||||
pub fn execute_using(&mut self, namespace_name: &str) -> Result<(), RuntimeError> {
|
||||
// 組み込み名前空間存在チェック
|
||||
if !self.shared.builtin_stdlib.hierarchical_map.contains_key(namespace_name) {
|
||||
return Err(RuntimeError::UndefinedNamespace(namespace_name.to_string()));
|
||||
}
|
||||
|
||||
// 現在ファイルのusingコンテキスト更新
|
||||
let file_id = self.get_current_file_id();
|
||||
let mut using_imports = self.shared.using_imports.write().unwrap();
|
||||
|
||||
let context = using_imports.entry(file_id.clone()).or_insert(UsingContext {
|
||||
imported_namespaces: Vec::new(),
|
||||
file_id: file_id.clone(),
|
||||
});
|
||||
|
||||
if !context.imported_namespaces.contains(&namespace_name.to_string()) {
|
||||
context.imported_namespaces.push(namespace_name.to_string());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// ⚡ 高速名前解決:string.upper() → nyashstd.string.upper()
|
||||
pub fn resolve_qualified_call(&self, path: &[String]) -> Option<String> {
|
||||
if path.len() != 2 {
|
||||
return None; // Phase 0では2段階のみ対応
|
||||
}
|
||||
|
||||
let box_name = &path[0];
|
||||
let method_name = &path[1];
|
||||
let file_id = self.get_current_file_id();
|
||||
|
||||
// 現在ファイルのusingインポート確認
|
||||
if let Ok(using_imports) = self.shared.using_imports.read() {
|
||||
if let Some(context) = using_imports.get(&file_id) {
|
||||
for namespace in &context.imported_namespaces {
|
||||
let qualified_name = format!("{}.{}", box_name, method_name);
|
||||
|
||||
// 実際に関数が存在するかチェック
|
||||
if self.shared.builtin_stdlib.get_function(&qualified_name).is_some() {
|
||||
return Some(qualified_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// 🚀 組み込み関数実行
|
||||
pub fn call_builtin_function(&self, qualified_name: &str, args: Vec<Box<dyn NyashBox>>)
|
||||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
|
||||
if let Some(function) = self.shared.builtin_stdlib.get_function(qualified_name) {
|
||||
// 引数数チェック
|
||||
if let Some(expected_count) = function.arg_count {
|
||||
if args.len() != expected_count {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
format!("{}.{}() takes exactly {} arguments, got {}",
|
||||
function.box_name, function.method_name,
|
||||
expected_count, args.len())
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// 関数実行
|
||||
(function.implementation)(&args)
|
||||
} else {
|
||||
Err(RuntimeError::UndefinedMethod(qualified_name.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 式実行統合
|
||||
|
||||
#### **src/interpreter/expressions.rs修正**
|
||||
```rust
|
||||
impl NyashInterpreter {
|
||||
pub fn execute_expression(&mut self, node: &ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
match node {
|
||||
// 既存のケース...
|
||||
|
||||
// メソッド呼び出し処理修正
|
||||
ASTNode::MethodCall { object, method, args, .. } => {
|
||||
// オブジェクトが単純な識別子かチェック
|
||||
if let ASTNode::Variable { name: box_name, .. } = object.as_ref() {
|
||||
// using経由での短縮呼び出しチェック
|
||||
let path = vec![box_name.clone(), method.clone()];
|
||||
if let Some(qualified_name) = self.resolve_qualified_call(&path) {
|
||||
// 引数評価
|
||||
let evaluated_args = self.evaluate_arguments(args)?;
|
||||
// 組み込み関数実行
|
||||
return self.call_builtin_function(&qualified_name, evaluated_args);
|
||||
}
|
||||
}
|
||||
|
||||
// 既存のメソッド呼び出し処理
|
||||
// ...
|
||||
}
|
||||
|
||||
// using文実行
|
||||
ASTNode::UsingStatement { namespace_name, .. } => {
|
||||
self.execute_using(namespace_name)?;
|
||||
Ok(Box::new(VoidBox::new()))
|
||||
}
|
||||
|
||||
// 他の既存ケース...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 パフォーマンス特性
|
||||
|
||||
### ⚡ 最適化ポイント
|
||||
|
||||
#### **1. Zero-Allocation関数解決**
|
||||
```rust
|
||||
// ❌ 遅い:毎回文字列生成
|
||||
let qualified = format!("{}.{}", box_name, method_name);
|
||||
|
||||
// ✅ 高速:事前計算済みマップ
|
||||
if let Some(func) = stdlib.flat_functions.get(&qualified_name) { ... }
|
||||
```
|
||||
|
||||
#### **2. 高速名前解決**
|
||||
```rust
|
||||
// O(1)アクセス:HashMap直接ルックアップ
|
||||
// "string.upper" -> BuiltinFunction
|
||||
```
|
||||
|
||||
#### **3. 既存Box実装活用**
|
||||
```rust
|
||||
// 既存の最適化済みStringBox.split()を直接使用
|
||||
string_box.split(separator) // 新規実装不要
|
||||
```
|
||||
|
||||
## 🧪 テストカバレッジ
|
||||
|
||||
### Phase 0必須テスト
|
||||
|
||||
#### **基本機能テスト**
|
||||
```nyash
|
||||
# test_builtin_stdlib_basic.hako
|
||||
using nyashstd
|
||||
|
||||
# 文字列操作
|
||||
assert(string.upper("hello") == "HELLO")
|
||||
assert(string.lower("WORLD") == "world")
|
||||
assert(string.split("a,b,c", ",").length() == 3)
|
||||
|
||||
# 数学関数
|
||||
assert(math.sin(0) == 0)
|
||||
assert(math.cos(0) == 1)
|
||||
|
||||
# 配列操作
|
||||
local arr = [1, 2, 3]
|
||||
assert(array.length(arr) == 3)
|
||||
assert(array.get(arr, 1) == 2)
|
||||
```
|
||||
|
||||
#### **エラーハンドリング**
|
||||
```nyash
|
||||
# test_builtin_stdlib_errors.hako
|
||||
using nyashstd
|
||||
|
||||
# 引数数エラー
|
||||
try {
|
||||
string.upper("hello", "extra") # 2引数でエラー
|
||||
assert(false, "Should have thrown error")
|
||||
} catch e {
|
||||
assert(e.contains("takes exactly 1 argument"))
|
||||
}
|
||||
|
||||
# 未定義名前空間
|
||||
try {
|
||||
using nonexistent
|
||||
assert(false, "Should have thrown error")
|
||||
} catch e {
|
||||
assert(e.contains("UndefinedNamespace"))
|
||||
}
|
||||
```
|
||||
|
||||
#### **IDE補完サポート**
|
||||
```rust
|
||||
// テスト:補完候補取得
|
||||
let methods = stdlib.get_available_methods("nyashstd", "string");
|
||||
assert!(methods.unwrap().contains(&"upper".to_string()));
|
||||
assert!(methods.unwrap().contains(&"lower".to_string()));
|
||||
```
|
||||
|
||||
## 🎯 実装順序
|
||||
|
||||
### 🚨 Critical(即時実装)
|
||||
1. **BuiltinStdlib基盤** - src/stdlib/builtin.rs作成
|
||||
2. **SharedState統合** - builtin_stdlibフィールド追加
|
||||
3. **using文パーサー** - ASTNode::UsingStatement
|
||||
|
||||
### ⚡ High(今週中)
|
||||
4. **string関数4種** - upper, lower, split, join
|
||||
5. **基本テスト** - using nyashstd動作確認
|
||||
6. **エラーハンドリング** - 適切なエラーメッセージ
|
||||
|
||||
### 📝 Medium(来週)
|
||||
7. **math関数5種** - sin, cos, sqrt, floor, random
|
||||
8. **array関数4種** - length, get, push, slice
|
||||
9. **io関数3種** - print, println, debug
|
||||
|
||||
---
|
||||
|
||||
**⚡ この高性能アーキテクチャで、複雑なファイル依存関係なしに即座に実用的なnamespace/usingが実現できるにゃ!🚀**
|
||||
@ -1,394 +0,0 @@
|
||||
# nyash.linkシステム使用例
|
||||
|
||||
## 🎯 基本的な使用例
|
||||
|
||||
### 📁 プロジェクト構造例
|
||||
```
|
||||
my-awesome-app/
|
||||
├── nyash.link # 依存関係定義
|
||||
├── src/
|
||||
│ ├── main.hako # メインファイル
|
||||
│ ├── models/
|
||||
│ │ └── user.hako # ユーザーモデル
|
||||
│ └── utils/
|
||||
│ └── helpers.hako # ヘルパー関数
|
||||
├── libs/
|
||||
│ └── custom_lib.hako # カスタムライブラリ
|
||||
└── stdlib/
|
||||
└── nyashstd.hako # 標準ライブラリ
|
||||
```
|
||||
|
||||
### 📋 nyash.linkファイル例
|
||||
```toml
|
||||
[project]
|
||||
name = "my-awesome-app"
|
||||
version = "1.0.0"
|
||||
description = "Everything is Box philosophy in action!"
|
||||
|
||||
[dependencies]
|
||||
# 標準ライブラリ
|
||||
nyashstd = { path = "./stdlib/nyashstd.hako" }
|
||||
|
||||
# プロジェクト内モジュール
|
||||
user_model = { path = "./src/models/user.hako" }
|
||||
helpers = { path = "./src/utils/helpers.hako" }
|
||||
|
||||
# カスタムライブラリ
|
||||
custom_lib = { path = "./libs/custom_lib.hako" }
|
||||
|
||||
[search_paths]
|
||||
stdlib = "./stdlib/"
|
||||
src = "./src/"
|
||||
libs = "./libs/"
|
||||
|
||||
[build]
|
||||
entry_point = "./src/main.hako"
|
||||
```
|
||||
|
||||
## 🌟 実用的なコード例
|
||||
|
||||
### 1. 基本的なusing使用
|
||||
```nyash
|
||||
# ===== src/main.hako =====
|
||||
using nyashstd
|
||||
using helpers
|
||||
|
||||
static box Main {
|
||||
init { console }
|
||||
|
||||
main() {
|
||||
me.console = new ConsoleBox()
|
||||
|
||||
# 標準ライブラリ使用
|
||||
local text = "hello world"
|
||||
local upper_text = string.upper(text) # nyashstd.string.upper
|
||||
me.console.log("Upper: " + upper_text)
|
||||
|
||||
# ヘルパー関数使用
|
||||
local processed = helpers.process_data("sample data")
|
||||
me.console.log("Processed: " + processed)
|
||||
|
||||
# 数学関数
|
||||
local result = math.sin(3.14159)
|
||||
me.console.log("Sin: " + result.toString())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 標準ライブラリ定義例
|
||||
```nyash
|
||||
# ===== stdlib/nyashstd.hako =====
|
||||
namespace nyashstd {
|
||||
static box string {
|
||||
static upper(str) {
|
||||
local string_box = new StringBox(str)
|
||||
return string_box.upper()
|
||||
}
|
||||
|
||||
static lower(str) {
|
||||
local string_box = new StringBox(str)
|
||||
return string_box.lower()
|
||||
}
|
||||
|
||||
static split(str, separator) {
|
||||
local string_box = new StringBox(str)
|
||||
return string_box.split(separator)
|
||||
}
|
||||
|
||||
static join(array, separator) {
|
||||
local sep_box = new StringBox(separator)
|
||||
return sep_box.join(array)
|
||||
}
|
||||
}
|
||||
|
||||
static box math {
|
||||
static sin(x) {
|
||||
local math_box = new MathBox()
|
||||
return math_box.sin(x)
|
||||
}
|
||||
|
||||
static cos(x) {
|
||||
local math_box = new MathBox()
|
||||
return math_box.cos(x)
|
||||
}
|
||||
|
||||
static random() {
|
||||
local random_box = new RandomBox()
|
||||
return random_box.nextFloat()
|
||||
}
|
||||
|
||||
static floor(x) {
|
||||
local math_box = new MathBox()
|
||||
return math_box.floor(x)
|
||||
}
|
||||
}
|
||||
|
||||
static box io {
|
||||
static read_file(path) {
|
||||
local file_box = new FileBox()
|
||||
return file_box.read(path)
|
||||
}
|
||||
|
||||
static write_file(path, content) {
|
||||
local file_box = new FileBox()
|
||||
return file_box.write(path, content)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. ヘルパーモジュール例
|
||||
```nyash
|
||||
# ===== src/utils/helpers.hako =====
|
||||
using nyashstd
|
||||
|
||||
static function process_data(data) {
|
||||
# データ処理のヘルパー
|
||||
local trimmed = string.trim(data)
|
||||
local upper = string.upper(trimmed)
|
||||
return "PROCESSED: " + upper
|
||||
}
|
||||
|
||||
static function calculate_score(points, multiplier) {
|
||||
local result = points * multiplier
|
||||
return math.floor(result)
|
||||
}
|
||||
|
||||
static function format_user_name(first, last) {
|
||||
return string.upper(first) + " " + string.upper(last)
|
||||
}
|
||||
```
|
||||
|
||||
### 4. モデル定義例
|
||||
```nyash
|
||||
# ===== src/models/user.hako =====
|
||||
using nyashstd
|
||||
using helpers
|
||||
|
||||
box User {
|
||||
init { name, email, score }
|
||||
|
||||
birth(user_name, user_email) {
|
||||
me.name = user_name
|
||||
me.email = user_email
|
||||
me.score = 0
|
||||
}
|
||||
|
||||
add_points(points) {
|
||||
me.score = me.score + points
|
||||
return me.score
|
||||
}
|
||||
|
||||
get_formatted_name() {
|
||||
local parts = string.split(me.name, " ")
|
||||
if parts.length() >= 2 {
|
||||
return helpers.format_user_name(parts.get(0), parts.get(1))
|
||||
} else {
|
||||
return string.upper(me.name)
|
||||
}
|
||||
}
|
||||
|
||||
save_to_file() {
|
||||
local data = "User: " + me.name + ", Email: " + me.email + ", Score: " + me.score.toString()
|
||||
local filename = "user_" + string.lower(me.name) + ".txt"
|
||||
io.write_file(filename, data)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎮 実用アプリケーション例
|
||||
|
||||
### 1. シンプルなWebサーバー
|
||||
```nyash
|
||||
# ===== web_server.hako =====
|
||||
using nyashstd
|
||||
using custom_lib
|
||||
|
||||
static box WebServer {
|
||||
init { server, port }
|
||||
|
||||
birth(server_port) {
|
||||
me.port = server_port
|
||||
me.server = new HttpServerBox()
|
||||
}
|
||||
|
||||
start() {
|
||||
me.server.bind("localhost", me.port)
|
||||
|
||||
me.server.on("request", me.handle_request)
|
||||
|
||||
local console = new ConsoleBox()
|
||||
console.log("Server started on port " + me.port.toString())
|
||||
|
||||
me.server.listen()
|
||||
}
|
||||
|
||||
handle_request(request, response) {
|
||||
local url = request.getUrl()
|
||||
|
||||
if url == "/" {
|
||||
local html = io.read_file("./public/index.html")
|
||||
response.setStatus(200)
|
||||
response.setHeader("Content-Type", "text/html")
|
||||
response.send(html)
|
||||
} else {
|
||||
response.setStatus(404)
|
||||
response.send("Not Found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# メイン実行
|
||||
local server = new WebServer(3000)
|
||||
server.start()
|
||||
```
|
||||
|
||||
### 2. データ処理パイプライン
|
||||
```nyash
|
||||
# ===== data_processor.hako =====
|
||||
using nyashstd
|
||||
using helpers
|
||||
|
||||
static box DataProcessor {
|
||||
init { input_file, output_file }
|
||||
|
||||
birth(input_path, output_path) {
|
||||
me.input_file = input_path
|
||||
me.output_file = output_path
|
||||
}
|
||||
|
||||
process() {
|
||||
# データ読み込み
|
||||
local raw_data = io.read_file(me.input_file)
|
||||
local lines = string.split(raw_data, "\n")
|
||||
|
||||
# 処理済みデータ配列
|
||||
local processed_lines = new ArrayBox()
|
||||
|
||||
# 各行を処理
|
||||
local i = 0
|
||||
loop(i < lines.length()) {
|
||||
local line = lines.get(i)
|
||||
local processed = helpers.process_data(line)
|
||||
processed_lines.push(processed)
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
# 結果をファイルに保存
|
||||
local result = string.join(processed_lines, "\n")
|
||||
io.write_file(me.output_file, result)
|
||||
|
||||
return processed_lines.length()
|
||||
}
|
||||
}
|
||||
|
||||
# メイン処理
|
||||
local processor = new DataProcessor("input.txt", "output.txt")
|
||||
local count = processor.process()
|
||||
|
||||
local console = new ConsoleBox()
|
||||
console.log("Processed " + count.toString() + " lines")
|
||||
```
|
||||
|
||||
## 🔧 高度な使用パターン
|
||||
|
||||
### 1. 条件付きモジュール読み込み(将来拡張)
|
||||
```nyash
|
||||
# 開発環境では詳細ログ、本番環境ではシンプルログ
|
||||
using nyashstd
|
||||
|
||||
static function get_logger() {
|
||||
local env = os.get_env("NYASH_ENV")
|
||||
|
||||
if env == "development" {
|
||||
using dev_logger
|
||||
return new dev_logger.DetailLogger()
|
||||
} else {
|
||||
using prod_logger
|
||||
return new prod_logger.SimpleLogger()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. エイリアス使用例(将来拡張)
|
||||
```nyash
|
||||
# 長い名前空間のエイリアス
|
||||
using very.long.namespace.name as short
|
||||
|
||||
local result = short.helper_function("data")
|
||||
|
||||
# 複数の類似ライブラリ
|
||||
using json_v1 as json1
|
||||
using json_v2 as json2
|
||||
|
||||
local data1 = json1.parse(input)
|
||||
local data2 = json2.parse(input)
|
||||
```
|
||||
|
||||
### 3. 部分インポート(将来拡張)
|
||||
```nyash
|
||||
# 名前空間全体ではなく特定機能のみ
|
||||
using nyashstd.string
|
||||
using nyashstd.math
|
||||
|
||||
# これで直接呼び出せる
|
||||
local result = upper("hello") # string.upper不要
|
||||
local sin_val = sin(3.14) # math.sin不要
|
||||
```
|
||||
|
||||
## 📊 移行例:既存includeからusingへ
|
||||
|
||||
### Before(現在のinclude使用)
|
||||
```nyash
|
||||
# ===== 既存のtext_adventure例 =====
|
||||
include "text_adventure/items.hako"
|
||||
include "text_adventure/rooms.hako"
|
||||
|
||||
# アイテム作成
|
||||
local sword = new Weapon("Sword", 10)
|
||||
```
|
||||
|
||||
### After(新しいusing使用)
|
||||
```nyash
|
||||
# ===== nyash.link =====
|
||||
[dependencies]
|
||||
game_items = { path = "./text_adventure/items.hako" }
|
||||
game_rooms = { path = "./text_adventure/rooms.hako" }
|
||||
|
||||
# ===== main.hako =====
|
||||
using game_items
|
||||
using game_rooms
|
||||
|
||||
# アイテム作成(名前空間経由)
|
||||
local sword = game_items.create_weapon("Sword", 10)
|
||||
```
|
||||
|
||||
## 🎉 期待される開発体験
|
||||
|
||||
### IDE補完の改善
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
# "st" と入力すると...
|
||||
st → string (補完候補)
|
||||
|
||||
# "string." と入力すると...
|
||||
string. → upper, lower, split, join, trim, ... (全メソッド表示)
|
||||
```
|
||||
|
||||
### エラーメッセージの改善
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
# 間違った呼び出し
|
||||
local result = string.uppper("hello") # typo
|
||||
|
||||
# エラー:
|
||||
# Error: Method 'uppper' not found in nyashstd.string
|
||||
# Did you mean: 'upper'?
|
||||
# Available methods: upper, lower, split, join, trim
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**🌟 これらの例でnyash.linkシステムの実用性と美しさが伝わるにゃ!🐱**
|
||||
@ -1,406 +0,0 @@
|
||||
# 最終実装戦略:標準関数優先namespace/usingシステム
|
||||
|
||||
## 🎯 実装戦略まとめ
|
||||
|
||||
### 📋 設計完了項目
|
||||
- ✅ **基本戦略**: nyash.link前の段階的実装
|
||||
- ✅ **アーキテクチャ**: SharedState統合による高性能設計
|
||||
- ✅ **標準関数**: 組み込みnyashstd名前空間
|
||||
- ✅ **実装順序**: Critical → High → Medium
|
||||
|
||||
### 🚀 最終実装ロードマップ
|
||||
|
||||
## Phase 0: 組み込みnyashstd基盤(1-2週間)
|
||||
|
||||
### 🚨 Critical実装(即時)
|
||||
|
||||
#### **1. トークナイザー拡張**
|
||||
```rust
|
||||
// src/tokenizer.rs
|
||||
pub enum TokenType {
|
||||
// 既存...
|
||||
USING, // using キーワード追加
|
||||
}
|
||||
|
||||
// キーワード認識
|
||||
fn tokenize_keyword(word: &str) -> TokenType {
|
||||
match word {
|
||||
// 既存...
|
||||
"using" => TokenType::USING,
|
||||
_ => TokenType::IDENTIFIER(word.to_string()),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **2. AST最小拡張**
|
||||
```rust
|
||||
// src/ast.rs
|
||||
pub enum ASTNode {
|
||||
// 既存...
|
||||
UsingStatement {
|
||||
namespace_name: String, // Phase 0: "nyashstd"のみ
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
#### **3. BuiltinStdlib基盤**
|
||||
```rust
|
||||
// 新ファイル: src/stdlib/mod.rs
|
||||
pub mod builtin;
|
||||
pub use builtin::*;
|
||||
|
||||
// 新ファイル: src/stdlib/builtin.rs
|
||||
// (前回設計したBuiltinStdlib実装)
|
||||
```
|
||||
|
||||
#### **4. SharedState統合**
|
||||
```rust
|
||||
// src/interpreter/core.rs
|
||||
#[derive(Clone)]
|
||||
pub struct SharedState {
|
||||
// 既存フィールド...
|
||||
pub builtin_stdlib: Arc<BuiltinStdlib>,
|
||||
pub using_imports: Arc<RwLock<HashMap<String, UsingContext>>>,
|
||||
}
|
||||
|
||||
impl SharedState {
|
||||
pub fn new() -> Self {
|
||||
SharedState {
|
||||
// 既存初期化...
|
||||
builtin_stdlib: Arc::new(BuiltinStdlib::new()),
|
||||
using_imports: Arc::new(RwLock::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ⚡ High実装(今週中)
|
||||
|
||||
#### **5. using文パーサー**
|
||||
```rust
|
||||
// src/parser/statements.rs
|
||||
impl NyashParser {
|
||||
pub fn parse_statement(&mut self) -> Result<ASTNode, ParseError> {
|
||||
match &self.current_token().token_type {
|
||||
// 既存ケース...
|
||||
TokenType::USING => self.parse_using(),
|
||||
// 他の既存ケース...
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_using(&mut self) -> Result<ASTNode, ParseError> {
|
||||
let start_span = self.current_token().span.clone();
|
||||
self.advance(); // consume 'using'
|
||||
|
||||
if let TokenType::IDENTIFIER(namespace_name) = &self.current_token().token_type {
|
||||
let name = namespace_name.clone();
|
||||
self.advance();
|
||||
|
||||
// Phase 0制限:nyashstdのみ許可
|
||||
if name != "nyashstd" {
|
||||
return Err(ParseError::UnsupportedFeature(
|
||||
format!("Only 'nyashstd' namespace is supported in Phase 0, got '{}'", name)
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ASTNode::UsingStatement {
|
||||
namespace_name: name,
|
||||
span: start_span,
|
||||
})
|
||||
} else {
|
||||
Err(ParseError::ExpectedIdentifier(
|
||||
"Expected namespace name after 'using'".to_string()
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **6. 基本string関数実装**
|
||||
```rust
|
||||
// src/stdlib/builtin.rs拡張
|
||||
impl BuiltinStdlib {
|
||||
fn register_string_functions(&mut self) {
|
||||
// string.upper
|
||||
self.register_function("string.upper", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "upper",
|
||||
implementation: |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.upper() takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let input = &args[0].to_string_box().value;
|
||||
let result = StringBox::new(&input.to_uppercase());
|
||||
Ok(Box::new(result))
|
||||
},
|
||||
arg_count: Some(1),
|
||||
description: "Convert string to uppercase",
|
||||
});
|
||||
|
||||
// string.lower
|
||||
self.register_function("string.lower", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "lower",
|
||||
implementation: |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.lower() takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let input = &args[0].to_string_box().value;
|
||||
let result = StringBox::new(&input.to_lowercase());
|
||||
Ok(Box::new(result))
|
||||
},
|
||||
arg_count: Some(1),
|
||||
description: "Convert string to lowercase",
|
||||
});
|
||||
|
||||
// string.split
|
||||
self.register_function("string.split", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "split",
|
||||
implementation: |args| {
|
||||
if args.len() != 2 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.split() takes exactly 2 arguments".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let string_box = StringBox::new(&args[0].to_string_box().value);
|
||||
let separator = &args[1].to_string_box().value;
|
||||
string_box.split(separator)
|
||||
},
|
||||
arg_count: Some(2),
|
||||
description: "Split string by separator",
|
||||
});
|
||||
|
||||
// string.join
|
||||
self.register_function("string.join", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "join",
|
||||
implementation: |args| {
|
||||
if args.len() != 2 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.join() takes exactly 2 arguments".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let array_arg = &args[0];
|
||||
let separator = &args[1].to_string_box().value;
|
||||
let separator_box = StringBox::new(separator);
|
||||
separator_box.join(array_arg.clone())
|
||||
},
|
||||
arg_count: Some(2),
|
||||
description: "Join array elements with separator",
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **7. インタープリター統合**
|
||||
```rust
|
||||
// src/interpreter/expressions.rs
|
||||
impl NyashInterpreter {
|
||||
pub fn execute_expression(&mut self, node: &ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
match node {
|
||||
// using文処理
|
||||
ASTNode::UsingStatement { namespace_name, .. } => {
|
||||
self.execute_using(namespace_name)?;
|
||||
Ok(Box::new(VoidBox::new()))
|
||||
}
|
||||
|
||||
// メソッド呼び出し処理拡張
|
||||
ASTNode::MethodCall { object, method, args, .. } => {
|
||||
// 組み込み関数チェック
|
||||
if let ASTNode::Variable { name: box_name, .. } = object.as_ref() {
|
||||
let path = vec![box_name.clone(), method.clone()];
|
||||
if let Some(qualified_name) = self.resolve_qualified_call(&path) {
|
||||
let evaluated_args = self.evaluate_arguments(args)?;
|
||||
return self.call_builtin_function(&qualified_name, evaluated_args);
|
||||
}
|
||||
}
|
||||
|
||||
// 既存のメソッド呼び出し処理
|
||||
// ...
|
||||
}
|
||||
|
||||
// 既存の他のケース...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 📝 Medium実装(来週)
|
||||
|
||||
#### **8. math関数実装**
|
||||
```rust
|
||||
// math.sin, cos, sqrt, floor, random
|
||||
```
|
||||
|
||||
#### **9. array関数実装**
|
||||
```rust
|
||||
// array.length, get, push, slice
|
||||
```
|
||||
|
||||
#### **10. io関数実装**
|
||||
```rust
|
||||
// io.print, println, debug
|
||||
```
|
||||
|
||||
## Phase 1: 拡張機能(2-3週間後)
|
||||
|
||||
### 🌟 完全修飾名対応
|
||||
```nyash
|
||||
# using不要でも使える
|
||||
nyashstd.string.upper("hello")
|
||||
nyashstd.math.sin(3.14)
|
||||
```
|
||||
|
||||
#### **実装**
|
||||
```rust
|
||||
// ASTNode::QualifiedCall追加
|
||||
ASTNode::QualifiedCall {
|
||||
path: Vec<String>, // ["nyashstd", "string", "upper"]
|
||||
args: Vec<ASTNode>,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
// パーサーで "identifier.identifier.identifier()" 構文解析
|
||||
```
|
||||
|
||||
### 🔧 エラーハンドリング強化
|
||||
```rust
|
||||
// より詳細なエラーメッセージ
|
||||
RuntimeError::UndefinedBuiltinMethod {
|
||||
namespace: String,
|
||||
box_name: String,
|
||||
method_name: String,
|
||||
available_methods: Vec<String>, // "Did you mean: ..."
|
||||
span: Span,
|
||||
}
|
||||
```
|
||||
|
||||
### 📊 IDE補完サポート
|
||||
```rust
|
||||
// Language Server連携用API
|
||||
impl BuiltinStdlib {
|
||||
pub fn get_completion_candidates(&self, prefix: &str) -> Vec<CompletionItem> {
|
||||
// "ny" -> ["nyashstd"]
|
||||
// "nyashstd." -> ["string", "math", "array", "io"]
|
||||
// "nyashstd.string." -> ["upper", "lower", "split", "join"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Phase 2: nyash.link準備(1ヶ月後)
|
||||
|
||||
### 🔗 外部モジュール対応基盤
|
||||
```rust
|
||||
// ModuleResolver拡張
|
||||
pub enum NamespaceSource {
|
||||
Builtin(Arc<BuiltinStdlib>), // 組み込み
|
||||
External(PathBuf), // nyash.linkで管理
|
||||
}
|
||||
|
||||
// NamespaceRegistry統合
|
||||
pub struct NamespaceRegistry {
|
||||
builtin: Arc<BuiltinStdlib>,
|
||||
external: HashMap<String, ExternalModule>,
|
||||
}
|
||||
```
|
||||
|
||||
### 📁 nyash.link対応
|
||||
```toml
|
||||
[dependencies]
|
||||
mylib = { path = "./mylib.hako" }
|
||||
|
||||
# using mylib # Phase 2で対応
|
||||
```
|
||||
|
||||
## 🧪 段階的テスト戦略
|
||||
|
||||
### Phase 0テスト
|
||||
```nyash
|
||||
# test_phase0_basic.hako
|
||||
using nyashstd
|
||||
|
||||
# 基本動作
|
||||
assert(string.upper("hello") == "HELLO")
|
||||
assert(string.lower("WORLD") == "world")
|
||||
|
||||
# エラー処理
|
||||
try {
|
||||
using unknown_namespace
|
||||
} catch e {
|
||||
assert(e.contains("nyashstd"))
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 1テスト
|
||||
```nyash
|
||||
# test_phase1_qualified.hako
|
||||
# using不要のテスト
|
||||
assert(nyashstd.string.upper("hello") == "HELLO")
|
||||
assert(nyashstd.math.sin(0) == 0)
|
||||
```
|
||||
|
||||
### Phase 2テスト
|
||||
```nyash
|
||||
# test_phase2_external.hako
|
||||
using mylib
|
||||
|
||||
assert(mylib.custom.process("data") == "processed: data")
|
||||
```
|
||||
|
||||
## 📊 実装マイルストーン
|
||||
|
||||
### ✅ Phase 0完了条件
|
||||
- [ ] USINGトークン認識
|
||||
- [ ] using nyashstd構文解析
|
||||
- [ ] 組み込みstring関数4種動作
|
||||
- [ ] 基本テスト全通過
|
||||
- [ ] エラーハンドリング適切
|
||||
|
||||
### ✅ Phase 1完了条件
|
||||
- [ ] 完全修飾名 nyashstd.string.upper() 動作
|
||||
- [ ] math/array/io関数実装
|
||||
- [ ] IDE補完候補API実装
|
||||
- [ ] 詳細エラーメッセージ
|
||||
|
||||
### ✅ Phase 2完了条件
|
||||
- [ ] 外部モジュール基盤実装
|
||||
- [ ] nyash.link基本対応
|
||||
- [ ] 依存関係解決機能
|
||||
- [ ] 全機能統合テスト
|
||||
|
||||
## 🔥 即座に開始すべき実装
|
||||
|
||||
### 今日やること
|
||||
1. **src/stdlib/mod.rs作成** - モジュール基盤
|
||||
2. **TokenType::USING追加** - トークナイザー拡張
|
||||
3. **BuiltinStdlib::new()実装** - 空の基盤作成
|
||||
|
||||
### 今週やること
|
||||
4. **using文パーサー実装** - 基本構文解析
|
||||
5. **string.upper()実装** - 最初の関数
|
||||
6. **基本テスト作成** - 動作確認
|
||||
|
||||
### 来週やること
|
||||
7. **string関数完成** - lower, split, join
|
||||
8. **math関数開始** - sin, cos, sqrt
|
||||
9. **IDE補完設計** - Language Server準備
|
||||
|
||||
---
|
||||
|
||||
**🎯 この段階的戦略で、複雑なnyash.linkなしに即座に実用的なnamespace/usingシステムが実現できるにゃ!**
|
||||
|
||||
**🚀 Phase 0実装を今すぐ開始して、Nyashをモダンなプログラミング言語に進化させよう!🐱✨**
|
||||
@ -1,471 +0,0 @@
|
||||
# nyash.linkシステム実装計画
|
||||
|
||||
## 🎯 実装戦略
|
||||
|
||||
### 📊 現状確認
|
||||
- ✅ **include**: 限定的使用(text_adventure例のみ)→廃止OK
|
||||
- ✅ **using**: 未実装→完全新規作成
|
||||
- ✅ **namespace**: 設計完了→実装のみ
|
||||
- ✅ **Gemini推奨**: 技術的妥当性確認済み
|
||||
|
||||
## 📋 段階的実装ロードマップ
|
||||
|
||||
### 🚀 **Phase 1: 基盤構築(1-2週間)**
|
||||
|
||||
#### 1.1 トークナイザー拡張
|
||||
```rust
|
||||
// src/tokenizer.rs
|
||||
pub enum TokenType {
|
||||
// 既存...
|
||||
USING, // using キーワード
|
||||
NAMESPACE, // namespace キーワード
|
||||
AS, // as キーワード(将来のエイリアス用)
|
||||
}
|
||||
|
||||
// キーワード認識追加
|
||||
fn tokenize_identifier(input: &str) -> TokenType {
|
||||
match input {
|
||||
// 既存...
|
||||
"using" => TokenType::USING,
|
||||
"namespace" => TokenType::NAMESPACE,
|
||||
"as" => TokenType::AS,
|
||||
_ => TokenType::IDENTIFIER(input.to_string()),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.2 AST拡張
|
||||
```rust
|
||||
// src/ast.rs
|
||||
pub enum ASTNode {
|
||||
// 既存...
|
||||
UsingStatement {
|
||||
module_path: Vec<String>, // ["nyashstd"] or ["mylib"]
|
||||
alias: Option<String>, // using mylib as lib
|
||||
span: Span,
|
||||
},
|
||||
NamespaceDeclaration {
|
||||
name: String,
|
||||
body: Vec<ASTNode>,
|
||||
span: Span,
|
||||
},
|
||||
QualifiedCall {
|
||||
path: Vec<String>, // ["nyashstd", "string", "upper"]
|
||||
args: Vec<ASTNode>,
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.3 パーサー基本実装
|
||||
```rust
|
||||
// src/parser/statements.rs
|
||||
impl NyashParser {
|
||||
pub fn parse_using(&mut self) -> Result<ASTNode, ParseError> {
|
||||
self.advance(); // consume 'using'
|
||||
|
||||
let module_path = self.parse_module_path()?;
|
||||
// using mylib → ["mylib"]
|
||||
// using nyashstd.string → ["nyashstd", "string"]
|
||||
|
||||
Ok(ASTNode::UsingStatement {
|
||||
module_path,
|
||||
alias: None, // Phase 1では未サポート
|
||||
span: self.current_span(),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_module_path(&mut self) -> Result<Vec<String>, ParseError> {
|
||||
let mut path = vec![];
|
||||
|
||||
// 最初の識別子
|
||||
if let TokenType::IDENTIFIER(name) = &self.current_token().token_type {
|
||||
path.push(name.clone());
|
||||
self.advance();
|
||||
} else {
|
||||
return Err(ParseError::ExpectedIdentifier);
|
||||
}
|
||||
|
||||
// ドット区切りで追加パス(将来拡張)
|
||||
// using nyashstd.string のような構文
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ⚡ **Phase 2: nyash.link基盤(2-3週間)**
|
||||
|
||||
#### 2.1 nyash.linkパーサー
|
||||
```rust
|
||||
// 新ファイル: src/link_file.rs
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct NyashLink {
|
||||
pub project: Option<ProjectInfo>,
|
||||
pub dependencies: HashMap<String, Dependency>,
|
||||
pub search_paths: Option<HashMap<String, String>>,
|
||||
pub build: Option<BuildConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct ProjectInfo {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Dependency {
|
||||
Path { path: String },
|
||||
Stdlib { stdlib: bool },
|
||||
Registry { version: String, registry: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct BuildConfig {
|
||||
pub entry_point: Option<String>,
|
||||
}
|
||||
|
||||
impl NyashLink {
|
||||
pub fn from_file(path: &Path) -> Result<Self, LinkError> {
|
||||
let content = std::fs::read_to_string(path)?;
|
||||
let link: NyashLink = toml::from_str(&content)?;
|
||||
Ok(link)
|
||||
}
|
||||
|
||||
pub fn resolve_dependency(&self, name: &str) -> Option<PathBuf> {
|
||||
if let Some(dep) = self.dependencies.get(name) {
|
||||
match dep {
|
||||
Dependency::Path { path } => Some(PathBuf::from(path)),
|
||||
Dependency::Stdlib { .. } => {
|
||||
// 標準ライブラリパス解決ロジック
|
||||
self.resolve_stdlib_path(name)
|
||||
}
|
||||
_ => None, // Phase 2では未サポート
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 依存関係解決エンジン
|
||||
```rust
|
||||
// 新ファイル: src/module_resolver.rs
|
||||
pub struct ModuleResolver {
|
||||
nyash_link: NyashLink,
|
||||
loaded_modules: HashMap<String, Arc<ParsedModule>>,
|
||||
loading_stack: Vec<String>, // 循環依存検出用
|
||||
}
|
||||
|
||||
impl ModuleResolver {
|
||||
pub fn new(link_path: &Path) -> Result<Self, ResolverError> {
|
||||
let nyash_link = NyashLink::from_file(link_path)?;
|
||||
Ok(ModuleResolver {
|
||||
nyash_link,
|
||||
loaded_modules: HashMap::new(),
|
||||
loading_stack: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resolve_using(&mut self, module_name: &str) -> Result<Arc<ParsedModule>, ResolverError> {
|
||||
// 既にロード済みかチェック
|
||||
if let Some(module) = self.loaded_modules.get(module_name) {
|
||||
return Ok(module.clone());
|
||||
}
|
||||
|
||||
// 循環依存チェック
|
||||
if self.loading_stack.contains(&module_name.to_string()) {
|
||||
return Err(ResolverError::CircularDependency(
|
||||
self.loading_stack.clone()
|
||||
));
|
||||
}
|
||||
|
||||
// ファイルパス解決
|
||||
let file_path = self.hako_link.resolve_dependency(module_name)
|
||||
.ok_or(ResolverError::ModuleNotFound(module_name.to_string()))?;
|
||||
|
||||
// 再帰的読み込み防止
|
||||
self.loading_stack.push(module_name.to_string());
|
||||
|
||||
// ファイル読み込み・パース
|
||||
let content = std::fs::read_to_string(&file_path)?;
|
||||
let ast = NyashParser::parse_from_string(&content)?;
|
||||
|
||||
// モジュール作成
|
||||
let module = Arc::new(ParsedModule {
|
||||
name: module_name.to_string(),
|
||||
file_path,
|
||||
ast,
|
||||
exports: self.extract_exports(&ast)?,
|
||||
});
|
||||
|
||||
// キャッシュに保存
|
||||
self.loaded_modules.insert(module_name.to_string(), module.clone());
|
||||
self.loading_stack.pop();
|
||||
|
||||
Ok(module)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 📈 **Phase 3: 名前空間システム(3-4週間)**
|
||||
|
||||
#### 3.1 namespace解析
|
||||
```rust
|
||||
impl NyashParser {
|
||||
pub fn parse_namespace(&mut self) -> Result<ASTNode, ParseError> {
|
||||
self.advance(); // consume 'namespace'
|
||||
|
||||
let name = self.expect_identifier()?;
|
||||
self.expect_token(TokenType::LBRACE)?;
|
||||
|
||||
let mut body = vec![];
|
||||
while !self.check_token(&TokenType::RBRACE) {
|
||||
body.push(self.parse_statement()?);
|
||||
}
|
||||
|
||||
self.expect_token(TokenType::RBRACE)?;
|
||||
|
||||
Ok(ASTNode::NamespaceDeclaration {
|
||||
name,
|
||||
body,
|
||||
span: self.current_span(),
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2 名前空間レジストリ
|
||||
```rust
|
||||
// 新ファイル: src/namespace_registry.rs
|
||||
pub struct NamespaceRegistry {
|
||||
namespaces: HashMap<String, Namespace>,
|
||||
using_imports: HashMap<String, Vec<String>>, // ファイル別インポート
|
||||
}
|
||||
|
||||
pub struct Namespace {
|
||||
pub name: String,
|
||||
pub static_boxes: HashMap<String, StaticBox>,
|
||||
}
|
||||
|
||||
pub struct StaticBox {
|
||||
pub name: String,
|
||||
pub static_methods: HashMap<String, MethodSignature>,
|
||||
}
|
||||
|
||||
impl NamespaceRegistry {
|
||||
pub fn register_namespace(&mut self, name: String, namespace: Namespace) {
|
||||
self.namespaces.insert(name, namespace);
|
||||
}
|
||||
|
||||
pub fn add_using_import(&mut self, file_id: String, namespace_name: String) {
|
||||
self.using_imports
|
||||
.entry(file_id)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(namespace_name);
|
||||
}
|
||||
|
||||
pub fn resolve_call(&self, file_id: &str, path: &[String]) -> Option<MethodSignature> {
|
||||
// 例: string.upper() → nyashstd.string.upper()
|
||||
if path.len() == 2 {
|
||||
let box_name = &path[0];
|
||||
let method_name = &path[1];
|
||||
|
||||
// usingでインポートされた名前空間を検索
|
||||
if let Some(imports) = self.using_imports.get(file_id) {
|
||||
for namespace_name in imports {
|
||||
if let Some(namespace) = self.namespaces.get(namespace_name) {
|
||||
if let Some(static_box) = namespace.static_boxes.get(box_name) {
|
||||
if let Some(method) = static_box.static_methods.get(method_name) {
|
||||
return Some(method.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 🎯 **Phase 4: インタープリター統合(4-5週間)**
|
||||
|
||||
#### 4.1 using文実行
|
||||
```rust
|
||||
// src/interpreter/core.rs
|
||||
impl NyashInterpreter {
|
||||
pub fn execute_using(&mut self, module_path: &[String]) -> Result<(), RuntimeError> {
|
||||
let module_name = module_path.join(".");
|
||||
|
||||
// モジュール解決・読み込み
|
||||
let module = self.module_resolver.resolve_using(&module_name)?;
|
||||
|
||||
// 名前空間登録
|
||||
if let Some(namespace) = self.extract_namespace_from_module(&module) {
|
||||
self.namespace_registry.register_namespace(module_name.clone(), namespace);
|
||||
self.namespace_registry.add_using_import(
|
||||
self.current_file_id.clone(),
|
||||
module_name
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn extract_namespace_from_module(&self, module: &ParsedModule) -> Option<Namespace> {
|
||||
// ASTからnamespace宣言を探して解析
|
||||
for node in &module.ast {
|
||||
if let ASTNode::NamespaceDeclaration { name, body, .. } = node {
|
||||
return Some(self.build_namespace_from_body(name, body));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.2 qualified call実行
|
||||
```rust
|
||||
impl NyashInterpreter {
|
||||
pub fn execute_qualified_call(&mut self, path: &[String], args: &[ASTNode])
|
||||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
|
||||
// 名前解決
|
||||
if let Some(method_sig) = self.namespace_registry.resolve_call(
|
||||
&self.current_file_id,
|
||||
path
|
||||
) {
|
||||
// 引数評価
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
|
||||
// メソッド実行(既存のBox呼び出しシステム活用)
|
||||
return self.call_static_method(&method_sig, evaluated_args);
|
||||
}
|
||||
|
||||
// 完全修飾名として試行
|
||||
if path.len() >= 3 {
|
||||
// nyashstd.string.upper() の場合
|
||||
let namespace_name = &path[0];
|
||||
let box_name = &path[1];
|
||||
let method_name = &path[2];
|
||||
|
||||
if let Some(namespace) = self.namespace_registry.namespaces.get(namespace_name) {
|
||||
if let Some(static_box) = namespace.static_boxes.get(box_name) {
|
||||
if let Some(method) = static_box.static_methods.get(method_name) {
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
return self.call_static_method(method, evaluated_args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedMethod(path.join(".")))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 テスト戦略
|
||||
|
||||
### Phase 1テスト
|
||||
```nyash
|
||||
# test_basic_using.hako
|
||||
# 基本using文テスト
|
||||
|
||||
# ファイル: mylib.hako
|
||||
static function hello() {
|
||||
return "Hello from mylib!"
|
||||
}
|
||||
|
||||
# ファイル: main.hako
|
||||
using mylib
|
||||
local result = mylib.hello()
|
||||
assert(result == "Hello from mylib!")
|
||||
```
|
||||
|
||||
### Phase 2テスト
|
||||
```nyash
|
||||
# test_nyash_link.hako
|
||||
# nyash.linkファイル連携テスト
|
||||
|
||||
# nyash.link内容:
|
||||
# [dependencies]
|
||||
# mylib = { path = "./mylib.hako" }
|
||||
|
||||
using mylib
|
||||
local result = mylib.process("data")
|
||||
assert(result == "processed: data")
|
||||
```
|
||||
|
||||
### Phase 3テスト
|
||||
```nyash
|
||||
# test_namespace.hako
|
||||
# 名前空間システムテスト
|
||||
|
||||
# nyashstd.hako:
|
||||
# namespace nyashstd {
|
||||
# static box string {
|
||||
# static upper(str) { ... }
|
||||
# }
|
||||
# }
|
||||
|
||||
using nyashstd
|
||||
local result = string.upper("hello")
|
||||
assert(result == "HELLO")
|
||||
|
||||
# 完全修飾名
|
||||
local result2 = nyashstd.string.upper("world")
|
||||
assert(result2 == "WORLD")
|
||||
```
|
||||
|
||||
## 📊 実装マイルストーン
|
||||
|
||||
### ✅ 完了条件
|
||||
|
||||
#### Phase 1
|
||||
- [ ] USING/NAMESPACE トークン認識
|
||||
- [ ] using文AST構築
|
||||
- [ ] 基本パーサーテスト通過
|
||||
|
||||
#### Phase 2
|
||||
- [ ] nyash.linkファイル読み込み
|
||||
- [ ] 依存関係解決
|
||||
- [ ] モジュールキャッシュ機能
|
||||
|
||||
#### Phase 3
|
||||
- [ ] namespace宣言解析
|
||||
- [ ] 名前空間レジストリ動作
|
||||
- [ ] 静的メソッド解決
|
||||
|
||||
#### Phase 4
|
||||
- [ ] インタープリター統合
|
||||
- [ ] qualified call実行
|
||||
- [ ] 全テストケース通過
|
||||
|
||||
## 🔮 将来拡張
|
||||
|
||||
### Phase 5: 高度機能
|
||||
- エイリアス(`using mylib as lib`)
|
||||
- 選択インポート(`using nyashstd.string`)
|
||||
- 動的モジュール読み込み
|
||||
|
||||
### Phase 6: 標準ライブラリ
|
||||
- nyashstd.hako完全実装
|
||||
- string/math/io/http モジュール
|
||||
- ドキュメント生成
|
||||
|
||||
### Phase 7: エコシステム
|
||||
- パッケージレジストリ設計
|
||||
- CLI ツール(nyash init/install)
|
||||
- IDE Language Server連携
|
||||
|
||||
---
|
||||
|
||||
**🎯 この実装計画でnyash.linkシステムを段階的に完成させるにゃ!**
|
||||
@ -1,372 +0,0 @@
|
||||
# なんでもAPI計画:最終統合アーキテクチャ
|
||||
|
||||
## 🌟 革命的ビジョンの実現
|
||||
|
||||
### 📊 統合設計完了状況
|
||||
- ✅ **nyash.link基盤**: 依存関係管理システム設計完了
|
||||
- ✅ **FFI-ABI統合**: BID×MIR×バックエンド統合設計完了
|
||||
- ✅ **usingシステム**: 3種類API統一インポート設計完了
|
||||
- ✅ **実世界例**: ゲーム・データサイエンス・Web・システムプログラミング実証
|
||||
- 🎯 **最終統合**: 全システム統合による革命的開発体験実現
|
||||
|
||||
### 🚀 完成後の開発体験
|
||||
```nyash
|
||||
# === たった一つの構文ですべてが使える ===
|
||||
using nyashstd # 組み込み標準ライブラリ
|
||||
using browser_api # ブラウザAPI(Canvas, DOM, WebAudio...)
|
||||
using system_api # システムAPI(libc, filesystem, network...)
|
||||
using ml_api # 機械学習(TensorFlow, PyTorch, OpenCV...)
|
||||
using game_api # ゲーム開発(SDL, OpenGL, Vulkan...)
|
||||
using mylib # 自作Nyashモジュール
|
||||
|
||||
# 全部同じ記法・同じパフォーマンス・同じエラーハンドリング!
|
||||
string.upper("hello") # 組み込み標準
|
||||
browser.canvas.fillRect("game", 10, 10, 100, 100, "red") # ブラウザAPI
|
||||
system.file.read("/etc/passwd") # システムAPI
|
||||
ml.opencv.loadImage("photo.jpg") # 機械学習API
|
||||
game.sdl.createWindow("Game", 800, 600) # ゲームAPI
|
||||
mylib.processData("input") # 自作モジュール
|
||||
```
|
||||
|
||||
## 🏗️ 最終統合アーキテクチャ
|
||||
|
||||
### 1. 全体システム構成
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Nyash Code │ │ nyash.link │ │ BID Files │
|
||||
│ │ │ │ │ │
|
||||
│ using browser_api│ │ [dependencies] │ │ browser_api: │
|
||||
│ using system_api │───▶│ browser_api = │───▶│ canvas.yaml │
|
||||
│ using mylib │ │ {bid=...} │ │ dom.yaml │
|
||||
│ canvas.fillRect │ │ system_api = │ │ system_api: │
|
||||
│ file.read │ │ {bid=...} │ │ libc.yaml │
|
||||
│ mylib.process │ │ mylib = {path} │ │ filesystem.yaml│
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
└────────────────────────┼────────────────────────┘
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ UniversalNamespaceRegistry │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
||||
│ │BuiltinStdlib│ │BidDefinition│ │ExternalModules │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │nyashstd.* │ │browser_api.*│ │mylib.* │ │
|
||||
│ │string.upper │ │canvas.fill* │ │custom functions │ │
|
||||
│ │math.sin │ │dom.events │ │ │ │
|
||||
│ │array.length │ │system.file* │ │ │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ MIR Generation │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
||||
│ │BuiltinCall │ │ExternCall │ │ModuleCall │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │string.upper │ │canvas.fill* │ │mylib.process │ │
|
||||
│ │effect:pure │ │effect:io │ │effect:io │ │
|
||||
│ │optimize:yes │ │gpu_accel:yes│ │ │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Backend Execution │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
||||
│ │ VM │ │ WASM │ │ AOT │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │Native Impl │ │RuntimeImport│ │LLVM ExternFunc │ │
|
||||
│ │Stub Calls │ │Auto-generated│ │Native Libraries │ │
|
||||
│ │ │ │from BID │ │ │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2. nyash.link統合仕様(最終版)
|
||||
```toml
|
||||
# nyash.link - 全API統一管理設定
|
||||
[project]
|
||||
name = "ultimate-nyash-app"
|
||||
version = "2.0.0"
|
||||
description = "Everything is accessible through unified APIs"
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
# === 組み込み標準ライブラリ ===
|
||||
nyashstd = { builtin = true }
|
||||
|
||||
# === ブラウザ・Web API ===
|
||||
browser_api = {
|
||||
bid = ["./apis/canvas.yaml", "./apis/dom.yaml", "./apis/webaudio.yaml"],
|
||||
target_environments = ["browser"]
|
||||
}
|
||||
webgl_api = {
|
||||
bid = "./apis/webgl.yaml",
|
||||
target_environments = ["browser"]
|
||||
}
|
||||
|
||||
# === システム・OS API ===
|
||||
system_api = {
|
||||
bid = ["./apis/libc.yaml", "./apis/filesystem.yaml", "./apis/network.yaml"],
|
||||
library = "system",
|
||||
target_environments = ["linux", "macos", "windows"]
|
||||
}
|
||||
posix_api = {
|
||||
bid = "./apis/posix.yaml",
|
||||
library = "system",
|
||||
target_environments = ["linux", "macos"]
|
||||
}
|
||||
|
||||
# === 機械学習・データサイエンス ===
|
||||
ml_api = {
|
||||
bid = ["./apis/opencv.yaml", "./apis/numpy.yaml"],
|
||||
library = ["./libs/opencv.so", "./libs/numpy.so"],
|
||||
target_environments = ["linux", "macos"]
|
||||
}
|
||||
tensorflow_api = {
|
||||
bid = "./apis/tensorflow.yaml",
|
||||
library = "./libs/tensorflow.so",
|
||||
optional = true # 環境によってオプション
|
||||
}
|
||||
|
||||
# === ゲーム開発 ===
|
||||
game_api = {
|
||||
bid = ["./apis/sdl.yaml", "./apis/opengl.yaml"],
|
||||
library = ["SDL2", "OpenGL"],
|
||||
target_environments = ["linux", "macos", "windows"]
|
||||
}
|
||||
|
||||
# === データベース ===
|
||||
database_api = {
|
||||
bid = ["./apis/sqlite.yaml", "./apis/postgresql.yaml"],
|
||||
library = ["sqlite3", "pq"],
|
||||
}
|
||||
|
||||
# === ネットワーク・Web ===
|
||||
http_api = {
|
||||
bid = "./apis/http_client.yaml",
|
||||
library = "curl"
|
||||
}
|
||||
|
||||
# === Nyashモジュール(従来通り) ===
|
||||
mylib = { path = "./src/mylib.hako" }
|
||||
utils = { path = "./src/utils/" }
|
||||
models = { path = "./src/models.hako" }
|
||||
|
||||
# === 将来の外部パッケージ ===
|
||||
awesome_lib = {
|
||||
version = "^1.2.0",
|
||||
registry = "nyash-pkg",
|
||||
bid = "auto" # パッケージレジストリから自動取得
|
||||
}
|
||||
|
||||
[build]
|
||||
entry_point = "./src/main.hako"
|
||||
backends = ["vm", "wasm", "aot"]
|
||||
optimization_level = "release"
|
||||
|
||||
[targets]
|
||||
browser = ["browser_api", "webgl_api"]
|
||||
desktop = ["system_api", "game_api", "ml_api"]
|
||||
server = ["system_api", "database_api", "http_api"]
|
||||
|
||||
[optimization]
|
||||
# MIRレベル最適化設定
|
||||
enable_effect_optimization = true
|
||||
enable_batch_optimization = true # FFI-ABI呼び出しバッチ化
|
||||
enable_gpu_acceleration = true
|
||||
cache_bid_compilation = true
|
||||
```
|
||||
|
||||
### 3. BIDエコシステム(標準API集)
|
||||
```
|
||||
nyash-std-apis/ # 標準APIライブラリ
|
||||
├── browser/
|
||||
│ ├── canvas.yaml # Canvas API
|
||||
│ ├── dom.yaml # DOM API
|
||||
│ ├── webaudio.yaml # Web Audio API
|
||||
│ ├── webgl.yaml # WebGL API
|
||||
│ └── fetch.yaml # Fetch API
|
||||
├── system/
|
||||
│ ├── libc.yaml # C標準ライブラリ
|
||||
│ ├── filesystem.yaml # ファイルシステム
|
||||
│ ├── network.yaml # ネットワーク
|
||||
│ ├── process.yaml # プロセス管理
|
||||
│ └── threads.yaml # スレッド・並行処理
|
||||
├── ml/
|
||||
│ ├── opencv.yaml # コンピューターヴィジョン
|
||||
│ ├── numpy.yaml # 数値計算
|
||||
│ ├── tensorflow.yaml # 機械学習
|
||||
│ └── pytorch.yaml # 深層学習
|
||||
├── game/
|
||||
│ ├── sdl.yaml # SDL2ライブラリ
|
||||
│ ├── opengl.yaml # OpenGL API
|
||||
│ ├── vulkan.yaml # Vulkan API
|
||||
│ └── physics.yaml # 物理エンジン
|
||||
├── database/
|
||||
│ ├── sqlite.yaml # SQLite
|
||||
│ ├── postgresql.yaml # PostgreSQL
|
||||
│ ├── mysql.yaml # MySQL
|
||||
│ └── redis.yaml # Redis
|
||||
└── crypto/
|
||||
├── openssl.yaml # OpenSSL
|
||||
├── libsodium.yaml # libsodium
|
||||
└── bcrypt.yaml # bcrypt
|
||||
```
|
||||
|
||||
## 🚀 段階的実装戦略(現実的ロードマップ)
|
||||
|
||||
### Phase 0: 基盤構築(2-3週間)
|
||||
```rust
|
||||
// 🎯 最小実装目標
|
||||
// using nyashstd → 動作
|
||||
```
|
||||
|
||||
#### **実装内容**
|
||||
1. **USINGトークナイザー** - `TokenType::USING`追加
|
||||
2. **基本パーサー** - `using nyashstd`構文解析
|
||||
3. **BuiltinStdlib基盤** - 組み込み標準ライブラリ
|
||||
4. **基本string関数** - upper, lower, split, join
|
||||
|
||||
#### **テスト**
|
||||
```nyash
|
||||
using nyashstd
|
||||
assert(string.upper("hello") == "HELLO")
|
||||
```
|
||||
|
||||
### Phase 1: BID基盤(4-6週間)
|
||||
```rust
|
||||
// 🎯 外部API基盤目標
|
||||
// using console_api → 動作(VM Stub)
|
||||
```
|
||||
|
||||
#### **実装内容**
|
||||
1. **BID読み込み** - YAML解析・検証システム
|
||||
2. **UniversalNamespaceRegistry** - 統合名前空間管理
|
||||
3. **MIR ExternCall統合** - BID→MIR変換
|
||||
4. **VM Stub実装** - console.log等の基本スタブ
|
||||
|
||||
#### **テスト**
|
||||
```nyash
|
||||
using nyashstd
|
||||
using console_api
|
||||
string.upper("test")
|
||||
console.log("BID integration works!")
|
||||
```
|
||||
|
||||
### Phase 2: WASM統合(6-8週間)
|
||||
```rust
|
||||
// 🎯 WASM動作目標
|
||||
// ブラウザでCanvas API動作
|
||||
```
|
||||
|
||||
#### **実装内容**
|
||||
1. **WASM RuntimeImports自動生成** - BID→WASM import
|
||||
2. **文字列マーシャリング** - UTF-8 (ptr,len)対応
|
||||
3. **Canvas API完全実装** - fillRect, fillText等
|
||||
4. **ブラウザテスト環境** - HTML/JS統合
|
||||
|
||||
#### **テスト**
|
||||
```nyash
|
||||
using browser_api
|
||||
canvas.fillRect("game-canvas", 10, 10, 100, 100, "red")
|
||||
```
|
||||
|
||||
### Phase 3: システムAPI統合(8-12週間)
|
||||
```rust
|
||||
// 🎯 ネイティブライブラリ動作目標
|
||||
// ファイルI/O, システムコール等
|
||||
```
|
||||
|
||||
#### **実装内容**
|
||||
1. **AOTバックエンド統合** - LLVM IR外部関数
|
||||
2. **システムライブラリ連携** - libc, filesystem等
|
||||
3. **エラーハンドリング統合** - 統一エラーモデル
|
||||
4. **パフォーマンス最適化** - バッチ処理・GPU加速
|
||||
|
||||
#### **テスト**
|
||||
```nyash
|
||||
using system_api
|
||||
local content = file.read("/etc/passwd")
|
||||
file.write("./output.txt", content)
|
||||
```
|
||||
|
||||
### Phase 4: 完全エコシステム(12-16週間)
|
||||
```rust
|
||||
// 🎯 実用的アプリケーション開発
|
||||
// ゲーム・ML・Webアプリ等
|
||||
```
|
||||
|
||||
#### **実装内容**
|
||||
1. **標準APIライブラリ** - nyash-std-apis完成
|
||||
2. **パッケージレジストリ** - BID共有システム
|
||||
3. **IDE Language Server** - 統合補完・エラー検出
|
||||
4. **最適化エンジン** - Effect System活用
|
||||
|
||||
#### **実用例**
|
||||
```nyash
|
||||
# 本格的なゲーム開発
|
||||
using game_api
|
||||
using audio_api
|
||||
game.sdl.createWindow("My Game", 1024, 768)
|
||||
audio.mixer.playMusic("bgm.ogg")
|
||||
```
|
||||
|
||||
## 📊 既存実装との整合性
|
||||
|
||||
### Phase 9.75eとの関係
|
||||
```
|
||||
Phase 9.75e (既存計画) なんでもAPI計画 (新設計)
|
||||
↓ ↓
|
||||
namespace構文 using統一構文
|
||||
依存関係システム → nyash.link統合管理
|
||||
外部ファイル読み込み → BID統合システム
|
||||
↓
|
||||
完全統合アーキテクチャ
|
||||
```
|
||||
|
||||
### 既存MIR/バックエンドとの統合
|
||||
- ✅ **MIR ExternCall**: 既存実装活用
|
||||
- ✅ **WASM RuntimeImports**: 既存基盤拡張
|
||||
- ✅ **VM Backend**: 既存スタブシステム活用
|
||||
- 🔧 **統合課題**: usingシステムとの橋渡し
|
||||
|
||||
## 🌟 長期ビジョン:Nyashの未来
|
||||
|
||||
### 2025年目標
|
||||
- **Phase 0-1完了**: 基盤・BID統合
|
||||
- **実用アプリ**: シンプルなブラウザゲーム・ツール
|
||||
- **コミュニティ**: 開発者コミュニティ形成
|
||||
|
||||
### 2026年目標
|
||||
- **Phase 2-3完了**: WASM・システムAPI統合
|
||||
- **本格アプリ**: ゲーム・データサイエンス・Webアプリ
|
||||
- **エコシステム**: BIDライブラリエコシステム
|
||||
|
||||
### 2027年目標
|
||||
- **Phase 4完了**: 完全エコシステム
|
||||
- **産業利用**: 企業での実用的活用
|
||||
- **言語標準化**: BID標準の業界採用
|
||||
|
||||
## 🎯 即座に開始すべき実装
|
||||
|
||||
### 今日のアクション
|
||||
1. **src/stdlib/mod.rs作成** - 組み込み標準ライブラリ基盤
|
||||
2. **TokenType::USING追加** - トークナイザー拡張
|
||||
3. **Phase 0実装開始** - using nyashstd基本動作
|
||||
|
||||
### 今週のアクション
|
||||
4. **BuiltinStdlib::new()実装** - string関数4種
|
||||
5. **基本テスト作成** - using動作確認
|
||||
6. **Phase 1設計** - BID統合詳細設計
|
||||
|
||||
### 来週のアクション
|
||||
7. **BID読み込み基盤** - YAML解析システム
|
||||
8. **UniversalNamespaceRegistry** - 統合名前空間管理
|
||||
9. **console.log実装** - 最初のBID統合テスト
|
||||
|
||||
---
|
||||
|
||||
**🎉 この最終統合アーキテクチャにより、Nyashが真に「なんでもできる」革命的プログラミング言語になるにゃ!**
|
||||
|
||||
**🚀 今すぐPhase 0実装を開始して、プログラミング言語の未来を創造しよう!🐱✨**
|
||||
@ -1,435 +0,0 @@
|
||||
# 最小実装:標準関数優先namespace/usingシステム
|
||||
|
||||
## 🎯 基本戦略:nyash.link前の段階的実装
|
||||
|
||||
### 📊 現状分析
|
||||
- **既存Box型**: 25種類以上の豊富なBox実装
|
||||
- **include使用**: 限定的(text_adventure例のみ)
|
||||
- **using実装**: 完全未実装→新規作成可能
|
||||
- **最優先課題**: 複雑なファイル依存関係システムより、まず標準関数のIDE補完
|
||||
|
||||
### 🌟 段階的実装アプローチ
|
||||
|
||||
#### **Phase 0: 組み込みnyashstd(最小実装)**
|
||||
```
|
||||
ファイル読み込み一切なし → インタープリターに直接組み込み
|
||||
```
|
||||
|
||||
#### **Phase 1: using構文**
|
||||
```nyash
|
||||
using nyashstd
|
||||
string.upper("hello") # ✅ 動作
|
||||
```
|
||||
|
||||
#### **Phase 2: 将来のnyash.link対応**
|
||||
```
|
||||
外部ファイル・依存関係システム(後日実装)
|
||||
```
|
||||
|
||||
## 🏗️ 組み込みnyashstd設計
|
||||
|
||||
### 優先順位別Box分類
|
||||
|
||||
#### 🚨 **Tier 1: 最優先基本機能**
|
||||
```rust
|
||||
// 使用頻度最高・IDE補完必須
|
||||
- string_box.rs → nyashstd.string.*
|
||||
- math_box.rs → nyashstd.math.*
|
||||
- array/mod.rs → nyashstd.array.*
|
||||
- console_box.rs → nyashstd.io.*
|
||||
```
|
||||
|
||||
#### ⚡ **Tier 2: 重要機能**
|
||||
```rust
|
||||
// 標準的な機能
|
||||
- time_box.rs → nyashstd.time.*
|
||||
- random_box.rs → nyashstd.random.*
|
||||
- map_box.rs → nyashstd.map.*
|
||||
```
|
||||
|
||||
#### 📝 **Tier 3: 特殊用途**
|
||||
```rust
|
||||
// 特定用途・後で追加
|
||||
- debug_box.rs → nyashstd.debug.*
|
||||
- http_server_box.rs → nyashstd.http.*
|
||||
- p2p_box.rs → nyashstd.p2p.*
|
||||
```
|
||||
|
||||
### 最小実装スコープ(Phase 0)
|
||||
|
||||
#### **nyashstd.string機能**
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
string.upper("hello") # "HELLO"
|
||||
string.lower("WORLD") # "world"
|
||||
string.split("a,b,c", ",") # ["a", "b", "c"]
|
||||
string.join(["a","b"], "-") # "a-b"
|
||||
string.length("test") # 4
|
||||
```
|
||||
|
||||
#### **nyashstd.math機能**
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
math.sin(3.14159) # 0.0 (approximately)
|
||||
math.cos(0) # 1.0
|
||||
math.sqrt(16) # 4.0
|
||||
math.floor(3.7) # 3
|
||||
math.random() # 0.0-1.0のランダム値
|
||||
```
|
||||
|
||||
#### **nyashstd.array機能**
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
array.length([1,2,3]) # 3
|
||||
array.push([1,2], 3) # [1,2,3]
|
||||
array.get([1,2,3], 1) # 2
|
||||
array.slice([1,2,3,4], 1, 3) # [2,3]
|
||||
```
|
||||
|
||||
#### **nyashstd.io機能**
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
io.print("Hello") # コンソール出力
|
||||
io.println("World") # 改行付き出力
|
||||
io.debug("Debug info") # デバッグ出力
|
||||
```
|
||||
|
||||
## 💻 技術実装戦略
|
||||
|
||||
### 1. インタープリター組み込み方式
|
||||
|
||||
#### **新ファイル: `src/stdlib/mod.rs`**
|
||||
```rust
|
||||
//! 組み込み標準ライブラリ
|
||||
//! nyash.linkなしで動作する基本的な標準関数群
|
||||
|
||||
use crate::boxes::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct BuiltinStdlib {
|
||||
pub namespaces: HashMap<String, BuiltinNamespace>,
|
||||
}
|
||||
|
||||
pub struct BuiltinNamespace {
|
||||
pub name: String,
|
||||
pub static_boxes: HashMap<String, BuiltinStaticBox>,
|
||||
}
|
||||
|
||||
pub struct BuiltinStaticBox {
|
||||
pub name: String,
|
||||
pub methods: HashMap<String, BuiltinMethod>,
|
||||
}
|
||||
|
||||
pub type BuiltinMethod = fn(&[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError>;
|
||||
|
||||
impl BuiltinStdlib {
|
||||
pub fn new() -> Self {
|
||||
let mut stdlib = BuiltinStdlib {
|
||||
namespaces: HashMap::new(),
|
||||
};
|
||||
|
||||
// nyashstd名前空間登録
|
||||
stdlib.register_nyashstd();
|
||||
|
||||
stdlib
|
||||
}
|
||||
|
||||
fn register_nyashstd(&mut self) {
|
||||
let mut nyashstd = BuiltinNamespace {
|
||||
name: "nyashstd".to_string(),
|
||||
static_boxes: HashMap::new(),
|
||||
};
|
||||
|
||||
// string static box
|
||||
nyashstd.static_boxes.insert("string".to_string(), self.create_string_box());
|
||||
// math static box
|
||||
nyashstd.static_boxes.insert("math".to_string(), self.create_math_box());
|
||||
// array static box
|
||||
nyashstd.static_boxes.insert("array".to_string(), self.create_array_box());
|
||||
// io static box
|
||||
nyashstd.static_boxes.insert("io".to_string(), self.create_io_box());
|
||||
|
||||
self.namespaces.insert("nyashstd".to_string(), nyashstd);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **文字列関数実装例**
|
||||
```rust
|
||||
impl BuiltinStdlib {
|
||||
fn create_string_box(&self) -> BuiltinStaticBox {
|
||||
let mut string_box = BuiltinStaticBox {
|
||||
name: "string".to_string(),
|
||||
methods: HashMap::new(),
|
||||
};
|
||||
|
||||
// string.upper(str) -> String
|
||||
string_box.methods.insert("upper".to_string(), |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.upper() takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let string_arg = args[0].to_string_box();
|
||||
let result = StringBox::new(&string_arg.value.to_uppercase());
|
||||
Ok(Box::new(result))
|
||||
});
|
||||
|
||||
// string.lower(str) -> String
|
||||
string_box.methods.insert("lower".to_string(), |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.lower() takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let string_arg = args[0].to_string_box();
|
||||
let result = StringBox::new(&string_arg.value.to_lowercase());
|
||||
Ok(Box::new(result))
|
||||
});
|
||||
|
||||
// string.split(str, separator) -> Array
|
||||
string_box.methods.insert("split".to_string(), |args| {
|
||||
if args.len() != 2 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.split() takes exactly 2 arguments".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let string_arg = args[0].to_string_box();
|
||||
let sep_arg = args[1].to_string_box();
|
||||
|
||||
let string_box = StringBox::new(&string_arg.value);
|
||||
let result = string_box.split(&sep_arg.value)?;
|
||||
Ok(result)
|
||||
});
|
||||
|
||||
string_box
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. インタープリター統合
|
||||
|
||||
#### **インタープリター拡張: `src/interpreter/core.rs`**
|
||||
```rust
|
||||
use crate::stdlib::BuiltinStdlib;
|
||||
|
||||
pub struct NyashInterpreter {
|
||||
// 既存フィールド...
|
||||
pub builtin_stdlib: BuiltinStdlib,
|
||||
pub using_imports: HashMap<String, Vec<String>>, // ファイル別インポート
|
||||
}
|
||||
|
||||
impl NyashInterpreter {
|
||||
pub fn new() -> Self {
|
||||
NyashInterpreter {
|
||||
// 既存初期化...
|
||||
builtin_stdlib: BuiltinStdlib::new(),
|
||||
using_imports: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
// using文実行
|
||||
pub fn execute_using(&mut self, namespace_name: &str) -> Result<(), RuntimeError> {
|
||||
// 組み込み名前空間かチェック
|
||||
if self.builtin_stdlib.namespaces.contains_key(namespace_name) {
|
||||
// 現在ファイルのインポートリストに追加
|
||||
self.using_imports
|
||||
.entry(self.current_file_id.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(namespace_name.to_string());
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err(RuntimeError::UndefinedNamespace(namespace_name.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
// 短縮名解決: string.upper() -> nyashstd.string.upper()
|
||||
pub fn resolve_short_call(&self, box_name: &str, method_name: &str)
|
||||
-> Option<(&str, &str, &str)> { // (namespace, box, method)
|
||||
|
||||
if let Some(imports) = self.using_imports.get(&self.current_file_id) {
|
||||
for namespace_name in imports {
|
||||
if let Some(namespace) = self.builtin_stdlib.namespaces.get(namespace_name) {
|
||||
if namespace.static_boxes.contains_key(box_name) {
|
||||
return Some((namespace_name, box_name, method_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
// 組み込み関数呼び出し
|
||||
pub fn call_builtin_method(&self, namespace: &str, box_name: &str, method_name: &str, args: Vec<Box<dyn NyashBox>>)
|
||||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
|
||||
if let Some(ns) = self.builtin_stdlib.namespaces.get(namespace) {
|
||||
if let Some(static_box) = ns.static_boxes.get(box_name) {
|
||||
if let Some(method) = static_box.methods.get(method_name) {
|
||||
return method(&args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedMethod(
|
||||
format!("{}.{}.{}", namespace, box_name, method_name)
|
||||
))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. パーサー最小拡張
|
||||
|
||||
#### **トークナイザー: `src/tokenizer.rs`**
|
||||
```rust
|
||||
pub enum TokenType {
|
||||
// 既存...
|
||||
USING, // using キーワード
|
||||
// NAMESPACE は後のPhaseで追加
|
||||
}
|
||||
```
|
||||
|
||||
#### **AST最小拡張: `src/ast.rs`**
|
||||
```rust
|
||||
pub enum ASTNode {
|
||||
// 既存...
|
||||
UsingStatement {
|
||||
namespace_name: String, // "nyashstd" のみ対応
|
||||
span: Span,
|
||||
},
|
||||
// QualifiedCall は後のPhaseで追加
|
||||
}
|
||||
```
|
||||
|
||||
#### **パーサー: `src/parser/statements.rs`**
|
||||
```rust
|
||||
impl NyashParser {
|
||||
pub fn parse_using(&mut self) -> Result<ASTNode, ParseError> {
|
||||
self.advance(); // consume 'using'
|
||||
|
||||
if let TokenType::IDENTIFIER(namespace_name) = &self.current_token().token_type {
|
||||
let name = namespace_name.clone();
|
||||
self.advance();
|
||||
|
||||
// Phase 0では "nyashstd" のみ許可
|
||||
if name != "nyashstd" {
|
||||
return Err(ParseError::UnsupportedNamespace(name));
|
||||
}
|
||||
|
||||
Ok(ASTNode::UsingStatement {
|
||||
namespace_name: name,
|
||||
span: self.current_span(),
|
||||
})
|
||||
} else {
|
||||
Err(ParseError::ExpectedIdentifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 テスト戦略
|
||||
|
||||
### Phase 0テストケース
|
||||
|
||||
#### **基本using文テスト**
|
||||
```nyash
|
||||
# test_using_basic.hako
|
||||
using nyashstd
|
||||
|
||||
local result = string.upper("hello")
|
||||
assert(result == "HELLO")
|
||||
|
||||
local lower = string.lower("WORLD")
|
||||
assert(lower == "world")
|
||||
```
|
||||
|
||||
#### **数学関数テスト**
|
||||
```nyash
|
||||
# test_math_basic.hako
|
||||
using nyashstd
|
||||
|
||||
local sin_result = math.sin(0)
|
||||
assert(sin_result == 0)
|
||||
|
||||
local sqrt_result = math.sqrt(16)
|
||||
assert(sqrt_result == 4)
|
||||
```
|
||||
|
||||
#### **配列操作テスト**
|
||||
```nyash
|
||||
# test_array_basic.hako
|
||||
using nyashstd
|
||||
|
||||
local arr = [1, 2, 3]
|
||||
local length = array.length(arr)
|
||||
assert(length == 3)
|
||||
|
||||
local item = array.get(arr, 1)
|
||||
assert(item == 2)
|
||||
```
|
||||
|
||||
## 📊 実装マイルストーン
|
||||
|
||||
### ✅ Phase 0完了条件
|
||||
- [ ] USING トークン認識
|
||||
- [ ] using nyashstd 構文解析
|
||||
- [ ] 組み込みnyashstd.string実装
|
||||
- [ ] 組み込みnyashstd.math実装
|
||||
- [ ] 組み込みnyashstd.array実装
|
||||
- [ ] 組み込みnyashstd.io実装
|
||||
- [ ] 基本テストケース全通過
|
||||
|
||||
### 🔮 将来の発展
|
||||
|
||||
#### **Phase 1: 完全修飾名対応**
|
||||
```nyash
|
||||
# using不要でも使える
|
||||
nyashstd.string.upper("hello")
|
||||
```
|
||||
|
||||
#### **Phase 2: namespace構文対応**
|
||||
```nyash
|
||||
# 組み込み以外の名前空間
|
||||
namespace mylib {
|
||||
static box utils {
|
||||
static process(data) { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **Phase 3: nyash.link統合**
|
||||
```toml
|
||||
# nyash.link
|
||||
[dependencies]
|
||||
mylib = { path = "./mylib.hako" }
|
||||
```
|
||||
|
||||
## 🎯 実装優先順位
|
||||
|
||||
### 🚨 Critical(今すぐ)
|
||||
1. **USINGトークナイザー** - Token::USING追加
|
||||
2. **using文パーサー** - "using nyashstd"解析
|
||||
3. **BuiltinStdlib基盤** - src/stdlib/mod.rs作成
|
||||
|
||||
### ⚡ High(今週中)
|
||||
4. **string関数実装** - upper, lower, split, join
|
||||
5. **math関数実装** - sin, cos, sqrt, floor
|
||||
6. **基本テスト** - using nyashstd動作確認
|
||||
|
||||
### 📝 Medium(来週)
|
||||
7. **array関数実装** - length, get, push, slice
|
||||
8. **io関数実装** - print, println, debug
|
||||
9. **エラーハンドリング** - 適切なエラーメッセージ
|
||||
|
||||
---
|
||||
|
||||
**🎉 この戦略なら複雑なファイル依存関係システムなしで、すぐに実用的なnamespace/usingが実現できるにゃ!🐱**
|
||||
@ -1,625 +0,0 @@
|
||||
# なんでもAPI計画:実世界での具体例
|
||||
|
||||
## 🌟 革命的開発体験の実例
|
||||
|
||||
### 🎮 ゲーム開発例:Nyashブラウザゲーム
|
||||
```nyash
|
||||
# === nyash.link ===
|
||||
[dependencies]
|
||||
nyashstd = { builtin = true }
|
||||
canvas_api = { bid = "./apis/canvas.yaml" }
|
||||
dom_api = { bid = "./apis/dom.yaml" }
|
||||
audio_api = { bid = "./apis/webaudio.yaml" }
|
||||
|
||||
# === game.hako ===
|
||||
using nyashstd
|
||||
using canvas_api
|
||||
using dom_api
|
||||
using audio_api
|
||||
|
||||
static box Game {
|
||||
init { canvas_id, score, player_x, player_y, enemies }
|
||||
|
||||
main() {
|
||||
me.canvas_id = "game-canvas"
|
||||
me.score = 0
|
||||
me.player_x = 200
|
||||
me.player_y = 300
|
||||
me.enemies = new ArrayBox()
|
||||
|
||||
# DOMイベント設定(FFI-ABI経由)
|
||||
dom.addEventListener("keydown", me.handleKeyDown)
|
||||
|
||||
# ゲームループ開始
|
||||
me.gameLoop()
|
||||
}
|
||||
|
||||
gameLoop() {
|
||||
loop(true) {
|
||||
me.update()
|
||||
me.render()
|
||||
|
||||
# ブラウザのrequestAnimationFrame(FFI-ABI)
|
||||
dom.requestAnimationFrame(me.gameLoop)
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
# 敵の移動(組み込み標準ライブラリ)
|
||||
local i = 0
|
||||
loop(i < array.length(me.enemies)) {
|
||||
local enemy = array.get(me.enemies, i)
|
||||
enemy.y = enemy.y + enemy.speed
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
# 当たり判定(組み込み数学関数)
|
||||
local distance = math.sqrt(
|
||||
math.pow(me.player_x - enemy.x, 2) +
|
||||
math.pow(me.player_y - enemy.y, 2)
|
||||
)
|
||||
|
||||
if distance < 30 {
|
||||
me.gameOver()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
# 画面クリア(Canvas API - FFI-ABI)
|
||||
canvas.fillRect(me.canvas_id, 0, 0, 800, 600, "black")
|
||||
|
||||
# プレイヤー描画
|
||||
canvas.fillRect(me.canvas_id, me.player_x, me.player_y, 20, 20, "blue")
|
||||
|
||||
# 敵描画
|
||||
local i = 0
|
||||
loop(i < array.length(me.enemies)) {
|
||||
local enemy = array.get(me.enemies, i)
|
||||
canvas.fillRect(me.canvas_id, enemy.x, enemy.y, 15, 15, "red")
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
# スコア表示
|
||||
local score_text = "Score: " + string.toString(me.score)
|
||||
canvas.fillText(me.canvas_id, score_text, 10, 30, "20px Arial", "white")
|
||||
}
|
||||
|
||||
handleKeyDown(event) {
|
||||
# キーボード入力処理(DOM API経由)
|
||||
local key = dom.getEventKey(event)
|
||||
|
||||
if key == "ArrowLeft" {
|
||||
me.player_x = me.player_x - 10
|
||||
} else if key == "ArrowRight" {
|
||||
me.player_x = me.player_x + 10
|
||||
} else if key == " " { # スペースキー
|
||||
me.shoot()
|
||||
}
|
||||
}
|
||||
|
||||
shoot() {
|
||||
# 効果音再生(Web Audio API - FFI-ABI)
|
||||
audio.playSound("shoot.wav")
|
||||
|
||||
# 弾の生成・発射処理
|
||||
# ...
|
||||
}
|
||||
|
||||
gameOver() {
|
||||
# ゲームオーバー処理
|
||||
audio.playSound("gameover.wav")
|
||||
dom.alert("Game Over! Score: " + string.toString(me.score))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 🔬 データサイエンス例:画像処理アプリ
|
||||
```nyash
|
||||
# === nyash.link ===
|
||||
[dependencies]
|
||||
nyashstd = { builtin = true }
|
||||
opencv_api = { bid = "./apis/opencv.yaml", library = "./libs/opencv.so" }
|
||||
numpy_api = { bid = "./apis/numpy.yaml", library = "./libs/numpy.so" }
|
||||
matplotlib_api = { bid = "./apis/matplotlib.yaml", library = "./libs/matplotlib.so" }
|
||||
file_api = { bid = "./apis/file.yaml" }
|
||||
|
||||
# === image_processor.hako ===
|
||||
using nyashstd
|
||||
using opencv_api
|
||||
using numpy_api
|
||||
using matplotlib_api
|
||||
using file_api
|
||||
|
||||
static box ImageProcessor {
|
||||
init { input_path, output_path, processed_data }
|
||||
|
||||
main() {
|
||||
me.input_path = "./images/input.jpg"
|
||||
me.output_path = "./images/output.jpg"
|
||||
|
||||
# 画像読み込み(OpenCV - FFI-ABI)
|
||||
local image = opencv.imread(me.input_path)
|
||||
|
||||
# 前処理
|
||||
local gray = opencv.cvtColor(image, "BGR2GRAY")
|
||||
local blurred = opencv.gaussianBlur(gray, 5, 5)
|
||||
|
||||
# エッジ検出
|
||||
local edges = opencv.canny(blurred, 50, 150)
|
||||
|
||||
# NumPy配列操作(NumPy - FFI-ABI)
|
||||
local edge_array = numpy.fromOpenCV(edges)
|
||||
local normalized = numpy.normalize(edge_array, 0, 255)
|
||||
|
||||
# 統計計算(組み込み標準ライブラリ)
|
||||
local edge_count = me.countEdgePixels(normalized)
|
||||
local percentage = (edge_count * 100) / (image.width * image.height)
|
||||
|
||||
# 結果表示
|
||||
io.println("Edge pixels: " + string.toString(edge_count))
|
||||
io.println("Edge percentage: " + string.toString(percentage) + "%")
|
||||
|
||||
# 結果画像保存(OpenCV)
|
||||
opencv.imwrite(me.output_path, edges)
|
||||
|
||||
# グラフ生成(Matplotlib - FFI-ABI)
|
||||
me.generateHistogram(normalized)
|
||||
}
|
||||
|
||||
countEdgePixels(image_array) {
|
||||
local count = 0
|
||||
local height = numpy.shape(image_array, 0)
|
||||
local width = numpy.shape(image_array, 1)
|
||||
|
||||
local y = 0
|
||||
loop(y < height) {
|
||||
local x = 0
|
||||
loop(x < width) {
|
||||
local pixel = numpy.get(image_array, y, x)
|
||||
if pixel > 0 {
|
||||
count = count + 1
|
||||
}
|
||||
x = x + 1
|
||||
}
|
||||
y = y + 1
|
||||
}
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
generateHistogram(image_array) {
|
||||
# ヒストグラム計算(NumPy)
|
||||
local histogram = numpy.histogram(image_array, 256)
|
||||
|
||||
# グラフ描画(Matplotlib)
|
||||
matplotlib.figure(800, 600)
|
||||
matplotlib.plot(histogram.bins, histogram.values)
|
||||
matplotlib.title("Edge Pixel Histogram")
|
||||
matplotlib.xlabel("Pixel Intensity")
|
||||
matplotlib.ylabel("Frequency")
|
||||
matplotlib.savefig("./images/histogram.png")
|
||||
matplotlib.show()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 🌐 Webサーバー例:RESTful API
|
||||
```nyash
|
||||
# === nyash.link ===
|
||||
[dependencies]
|
||||
nyashstd = { builtin = true }
|
||||
http_server_api = { bid = "./apis/http_server.yaml" }
|
||||
sqlite_api = { bid = "./apis/sqlite.yaml", library = "./libs/sqlite.so" }
|
||||
json_api = { bid = "./apis/json.yaml" }
|
||||
crypto_api = { bid = "./apis/crypto.yaml", library = "./libs/openssl.so" }
|
||||
|
||||
# === api_server.hako ===
|
||||
using nyashstd
|
||||
using http_server_api
|
||||
using sqlite_api
|
||||
using json_api
|
||||
using crypto_api
|
||||
|
||||
static box ApiServer {
|
||||
init { server, database, port }
|
||||
|
||||
main() {
|
||||
me.port = 8080
|
||||
me.server = http_server.create()
|
||||
me.database = sqlite.open("./data/app.db")
|
||||
|
||||
# データベース初期化
|
||||
me.initDatabase()
|
||||
|
||||
# ルート設定
|
||||
http_server.route(me.server, "GET", "/api/users", me.getUsers)
|
||||
http_server.route(me.server, "POST", "/api/users", me.createUser)
|
||||
http_server.route(me.server, "PUT", "/api/users/:id", me.updateUser)
|
||||
http_server.route(me.server, "DELETE", "/api/users/:id", me.deleteUser)
|
||||
|
||||
# サーバー開始
|
||||
io.println("Server starting on port " + string.toString(me.port))
|
||||
http_server.listen(me.server, me.port)
|
||||
}
|
||||
|
||||
initDatabase() {
|
||||
local sql = "CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
password_hash TEXT NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)"
|
||||
|
||||
sqlite.exec(me.database, sql)
|
||||
}
|
||||
|
||||
getUsers(request, response) {
|
||||
# クエリ実行(SQLite - FFI-ABI)
|
||||
local sql = "SELECT id, name, email, created_at FROM users"
|
||||
local results = sqlite.query(me.database, sql)
|
||||
|
||||
# JSON変換(JSON API - FFI-ABI)
|
||||
local json_response = json.stringify(results)
|
||||
|
||||
# レスポンス送信(HTTP Server API)
|
||||
http_server.setHeader(response, "Content-Type", "application/json")
|
||||
http_server.setStatus(response, 200)
|
||||
http_server.send(response, json_response)
|
||||
}
|
||||
|
||||
createUser(request, response) {
|
||||
# リクエストボディ解析
|
||||
local body = http_server.getBody(request)
|
||||
local user_data = json.parse(body)
|
||||
|
||||
# バリデーション(組み込み標準ライブラリ)
|
||||
if string.length(user_data.name) < 2 {
|
||||
me.sendError(response, 400, "Name must be at least 2 characters")
|
||||
return
|
||||
}
|
||||
|
||||
if not me.isValidEmail(user_data.email) {
|
||||
me.sendError(response, 400, "Invalid email format")
|
||||
return
|
||||
}
|
||||
|
||||
# パスワードハッシュ化(Crypto API - FFI-ABI)
|
||||
local password_hash = crypto.hashPassword(user_data.password)
|
||||
|
||||
# データベース挿入
|
||||
local sql = "INSERT INTO users (name, email, password_hash) VALUES (?, ?, ?)"
|
||||
local params = [user_data.name, user_data.email, password_hash]
|
||||
|
||||
try {
|
||||
local user_id = sqlite.insert(me.database, sql, params)
|
||||
|
||||
# 作成されたユーザー情報を返す
|
||||
local created_user = map.create()
|
||||
map.set(created_user, "id", user_id)
|
||||
map.set(created_user, "name", user_data.name)
|
||||
map.set(created_user, "email", user_data.email)
|
||||
|
||||
local json_response = json.stringify(created_user)
|
||||
|
||||
http_server.setHeader(response, "Content-Type", "application/json")
|
||||
http_server.setStatus(response, 201)
|
||||
http_server.send(response, json_response)
|
||||
|
||||
} catch error {
|
||||
io.println("Database error: " + error.message)
|
||||
me.sendError(response, 500, "Failed to create user")
|
||||
}
|
||||
}
|
||||
|
||||
isValidEmail(email) {
|
||||
# 簡単なメール検証(組み込み文字列関数)
|
||||
local at_pos = string.indexOf(email, "@")
|
||||
local dot_pos = string.lastIndexOf(email, ".")
|
||||
|
||||
return at_pos > 0 and dot_pos > at_pos and dot_pos < string.length(email) - 1
|
||||
}
|
||||
|
||||
sendError(response, status, message) {
|
||||
local error_obj = map.create()
|
||||
map.set(error_obj, "error", message)
|
||||
|
||||
local json_error = json.stringify(error_obj)
|
||||
|
||||
http_server.setHeader(response, "Content-Type", "application/json")
|
||||
http_server.setStatus(response, status)
|
||||
http_server.send(response, json_error)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 🔧 システムプログラミング例:ファイル監視ツール
|
||||
```nyash
|
||||
# === nyash.link ===
|
||||
[dependencies]
|
||||
nyashstd = { builtin = true }
|
||||
libc_api = { bid = "./apis/libc.yaml", library = "system" }
|
||||
inotify_api = { bid = "./apis/inotify.yaml", library = "system" }
|
||||
filesystem_api = { bid = "./apis/filesystem.yaml" }
|
||||
|
||||
# === file_monitor.hako ===
|
||||
using nyashstd
|
||||
using libc_api
|
||||
using inotify_api
|
||||
using filesystem_api
|
||||
|
||||
static box FileMonitor {
|
||||
init { watch_path, inotify_fd, watch_descriptors, callbacks }
|
||||
|
||||
main() {
|
||||
me.watch_path = "./watched_directory"
|
||||
me.watch_descriptors = new ArrayBox()
|
||||
me.callbacks = map.create()
|
||||
|
||||
# inotify初期化(Linux inotify - FFI-ABI)
|
||||
me.inotify_fd = inotify.init()
|
||||
|
||||
if me.inotify_fd < 0 {
|
||||
io.println("Failed to initialize inotify")
|
||||
return
|
||||
}
|
||||
|
||||
# ディレクトリ監視設定
|
||||
me.addWatch(me.watch_path)
|
||||
|
||||
# コールバック設定
|
||||
me.setupCallbacks()
|
||||
|
||||
io.println("File monitor started. Watching: " + me.watch_path)
|
||||
|
||||
# メインループ
|
||||
me.eventLoop()
|
||||
}
|
||||
|
||||
addWatch(path) {
|
||||
# 監視フラグ(inotify constants)
|
||||
local flags = inotify.IN_CREATE or inotify.IN_DELETE or
|
||||
inotify.IN_MODIFY or inotify.IN_MOVED_FROM or
|
||||
inotify.IN_MOVED_TO
|
||||
|
||||
local wd = inotify.addWatch(me.inotify_fd, path, flags)
|
||||
|
||||
if wd >= 0 {
|
||||
array.push(me.watch_descriptors, wd)
|
||||
io.println("Added watch for: " + path)
|
||||
} else {
|
||||
io.println("Failed to add watch for: " + path)
|
||||
}
|
||||
}
|
||||
|
||||
setupCallbacks() {
|
||||
# ファイル作成コールバック
|
||||
map.set(me.callbacks, "CREATE", static function(event) {
|
||||
io.println("File created: " + event.name)
|
||||
|
||||
# ファイル情報取得(Filesystem API)
|
||||
local file_info = filesystem.stat(event.path)
|
||||
local size = file_info.size
|
||||
local permissions = file_info.permissions
|
||||
|
||||
io.println(" Size: " + string.toString(size) + " bytes")
|
||||
io.println(" Permissions: " + permissions)
|
||||
})
|
||||
|
||||
# ファイル変更コールバック
|
||||
map.set(me.callbacks, "MODIFY", static function(event) {
|
||||
io.println("File modified: " + event.name)
|
||||
|
||||
# 変更時刻記録
|
||||
local timestamp = time.now()
|
||||
local formatted_time = time.format(timestamp, "%Y-%m-%d %H:%M:%S")
|
||||
io.println(" Modified at: " + formatted_time)
|
||||
})
|
||||
|
||||
# ファイル削除コールバック
|
||||
map.set(me.callbacks, "DELETE", static function(event) {
|
||||
io.println("File deleted: " + event.name)
|
||||
|
||||
# ログファイルに記録
|
||||
me.logEvent("DELETE", event.name, time.now())
|
||||
})
|
||||
}
|
||||
|
||||
eventLoop() {
|
||||
local buffer_size = 4096
|
||||
local buffer = libc.malloc(buffer_size)
|
||||
|
||||
loop(true) {
|
||||
# inotify eventsを読み取り(blocking read)
|
||||
local bytes_read = libc.read(me.inotify_fd, buffer, buffer_size)
|
||||
|
||||
if bytes_read > 0 {
|
||||
me.processEvents(buffer, bytes_read)
|
||||
} else if bytes_read == 0 {
|
||||
# EOF
|
||||
break
|
||||
} else {
|
||||
# エラー
|
||||
local error_code = libc.errno()
|
||||
io.println("Read error: " + string.toString(error_code))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
libc.free(buffer)
|
||||
}
|
||||
|
||||
processEvents(buffer, bytes_read) {
|
||||
local offset = 0
|
||||
|
||||
loop(offset < bytes_read) {
|
||||
# inotify_event構造体解析(libc memory operations)
|
||||
local event = inotify.parseEvent(buffer, offset)
|
||||
|
||||
# イベントタイプ判定
|
||||
local event_type = me.getEventType(event.mask)
|
||||
|
||||
# 対応するコールバック実行
|
||||
if map.has(me.callbacks, event_type) {
|
||||
local callback = map.get(me.callbacks, event_type)
|
||||
callback(event)
|
||||
}
|
||||
|
||||
# 次のイベントへ
|
||||
offset = offset + event.size
|
||||
}
|
||||
}
|
||||
|
||||
getEventType(mask) {
|
||||
if mask and inotify.IN_CREATE {
|
||||
return "CREATE"
|
||||
} else if mask and inotify.IN_MODIFY {
|
||||
return "MODIFY"
|
||||
} else if mask and inotify.IN_DELETE {
|
||||
return "DELETE"
|
||||
} else if mask and inotify.IN_MOVED_FROM {
|
||||
return "MOVE_FROM"
|
||||
} else if mask and inotify.IN_MOVED_TO {
|
||||
return "MOVE_TO"
|
||||
} else {
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
logEvent(event_type, filename, timestamp) {
|
||||
local log_entry = time.format(timestamp, "%Y-%m-%d %H:%M:%S") +
|
||||
" [" + event_type + "] " + filename + "\n"
|
||||
|
||||
# ログファイルに追記(Filesystem API)
|
||||
filesystem.appendFile("./file_monitor.log", log_entry)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 MIR同時拡張による最適化効果
|
||||
|
||||
### 🚀 最適化前後の比較
|
||||
|
||||
#### **従来の実装(最適化なし)**
|
||||
```mir
|
||||
; 非効率:毎回関数呼び出し
|
||||
%1 = ExternCall env.canvas.fillRect ["canvas", 10, 10, 100, 100, "red"]
|
||||
%2 = ExternCall env.canvas.fillRect ["canvas", 110, 10, 100, 100, "blue"]
|
||||
%3 = ExternCall env.canvas.fillRect ["canvas", 220, 10, 100, 100, "green"]
|
||||
```
|
||||
|
||||
#### **MIR最適化後(バッチ処理)**
|
||||
```mir
|
||||
; 効率化:バッチ処理
|
||||
%rects = ArrayConstruct [
|
||||
{x: 10, y: 10, w: 100, h: 100, color: "red"},
|
||||
{x: 110, y: 10, w: 100, h: 100, color: "blue"},
|
||||
{x: 220, y: 10, w: 100, h: 100, color: "green"}
|
||||
]
|
||||
%1 = ExternCall env.canvas.fillRectBatch ["canvas", %rects]
|
||||
```
|
||||
|
||||
#### **Effect Systemによる並列化**
|
||||
```mir
|
||||
; pure関数は並列実行可能
|
||||
%1 = BuiltinCall string.upper ["hello"] ; effect: pure
|
||||
%2 = BuiltinCall math.sin [3.14] ; effect: pure
|
||||
%3 = BuiltinCall string.lower ["WORLD"] ; effect: pure
|
||||
; ↑ これらは並列実行される
|
||||
|
||||
%4 = ExternCall env.console.log [%1] ; effect: io
|
||||
%5 = ExternCall env.console.log [%2] ; effect: io
|
||||
; ↑ これらは順序保持される
|
||||
```
|
||||
|
||||
### 🎯 バックエンド別最適化
|
||||
|
||||
#### **WASM最適化**
|
||||
```wasm
|
||||
;; BIDから自動生成された最適化WASM
|
||||
(func $optimized_canvas_batch
|
||||
(param $canvas_id i32) (param $canvas_id_len i32)
|
||||
(param $rects_ptr i32) (param $rect_count i32)
|
||||
|
||||
;; ループ展開による高速化
|
||||
(local $i i32)
|
||||
(local $rect_ptr i32)
|
||||
|
||||
loop $rect_loop
|
||||
;; 直接メモリアクセス(境界チェック済み)
|
||||
local.get $rect_ptr
|
||||
i32.load ;; x
|
||||
local.get $rect_ptr
|
||||
i32.load offset=4 ;; y
|
||||
;; ... 高速描画処理
|
||||
|
||||
local.get $rect_ptr
|
||||
i32.const 20
|
||||
i32.add
|
||||
local.set $rect_ptr
|
||||
|
||||
local.get $i
|
||||
i32.const 1
|
||||
i32.add
|
||||
local.tee $i
|
||||
local.get $rect_count
|
||||
i32.lt_u
|
||||
br_if $rect_loop
|
||||
end
|
||||
)
|
||||
```
|
||||
|
||||
#### **AOT最適化(LLVM IR)**
|
||||
```llvm
|
||||
; LLVM IRレベルでの最適化
|
||||
define void @optimized_image_processing(i8* %image_data, i32 %width, i32 %height) {
|
||||
entry:
|
||||
; ベクトル化された画像処理
|
||||
%0 = bitcast i8* %image_data to <16 x i8>*
|
||||
|
||||
; SIMD命令による並列処理
|
||||
br label %loop.header
|
||||
|
||||
loop.header:
|
||||
%i = phi i32 [ 0, %entry ], [ %i.next, %loop.body ]
|
||||
%cmp = icmp ult i32 %i, %height
|
||||
br i1 %cmp, label %loop.body, label %exit
|
||||
|
||||
loop.body:
|
||||
; 16ピクセル同時処理(AVX2/NEON活用)
|
||||
%pixel_ptr = getelementptr <16 x i8>, <16 x i8>* %0, i32 %i
|
||||
%pixels = load <16 x i8>, <16 x i8>* %pixel_ptr
|
||||
|
||||
; ベクトル化されたエッジ検出
|
||||
%edges = call <16 x i8> @vectorized_edge_detection(<16 x i8> %pixels)
|
||||
|
||||
store <16 x i8> %edges, <16 x i8>* %pixel_ptr
|
||||
|
||||
%i.next = add i32 %i, 1
|
||||
br label %loop.header
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
```
|
||||
|
||||
## 🌟 革命的効果
|
||||
|
||||
### 🚀 開発者体験の向上
|
||||
- **学習コスト**: 一つの構文ですべてのAPIが使える
|
||||
- **IDE統合**: 全APIの統一補完・エラー検出
|
||||
- **デバッグ**: 統一エラーモデルによる一貫したデバッグ体験
|
||||
|
||||
### ⚡ パフォーマンス向上
|
||||
- **MIRレベル最適化**: すべてのAPIで同じ最適化技術
|
||||
- **Effect System**: 安全な並列化・順序最適化
|
||||
- **バックエンド最適化**: WASM/AOT固有の最適化
|
||||
|
||||
### 🌍 エコシステム拡大
|
||||
- **ライブラリ統合**: 既存C/Rustライブラリの簡単統合
|
||||
- **クロスプラットフォーム**: 同じコードが全環境で動作
|
||||
- **標準化**: BIDによる外部API標準化
|
||||
|
||||
---
|
||||
|
||||
**🎉 これが「なんでもAPI計画」の真の実力だにゃ!あらゆる開発が統一された美しい構文で実現できるにゃ!🚀🐱**
|
||||
@ -1,563 +0,0 @@
|
||||
# なんでもAPI計画:nyash.link × FFI-ABI × MIR 統合設計
|
||||
|
||||
## 🌟 革命的統合ビジョン
|
||||
|
||||
### 📊 現状把握
|
||||
- ✅ **nyash.linkシステム**: 標準関数・モジュール管理設計完了
|
||||
- ✅ **FFI-ABI仕様**: BID(Box Interface Definition)による外部API統一
|
||||
- ✅ **MIR ExternCall**: 外部関数呼び出しのMIRレベル実装
|
||||
- 🎯 **統合目標**: 3つのシステムを統合し「なんでもAPI」を実現
|
||||
|
||||
### 🚀 統合後の開発体験
|
||||
```nyash
|
||||
# === 単一のusing構文ですべてが使える! ===
|
||||
using nyashstd # 組み込み標準ライブラリ
|
||||
using console_api # ブラウザConsole API (FFI-ABI)
|
||||
using canvas_api # Canvas API (FFI-ABI)
|
||||
using opencv_api # OpenCV外部ライブラリ (FFI-ABI)
|
||||
using mylib # 自作Nyashモジュール
|
||||
|
||||
# 全部同じ記法で使える!
|
||||
string.upper("hello") # 組み込み標準ライブラリ
|
||||
console.log("Hello Nyash!") # ブラウザAPI
|
||||
canvas.fillRect("game", 10, 10, 80, 60, "red") # Canvas API
|
||||
opencv.loadImage("photo.jpg") # 外部ライブラリ
|
||||
mylib.processData("input") # 自作モジュール
|
||||
```
|
||||
|
||||
## 🏗️ 統合アーキテクチャ設計
|
||||
|
||||
### 1. 拡張nyash.link仕様
|
||||
|
||||
#### **依存関係タイプの統合**
|
||||
```toml
|
||||
# nyash.link - 全API統一管理
|
||||
[project]
|
||||
name = "awesome-nyash-app"
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies]
|
||||
# === 組み込み標準ライブラリ ===
|
||||
nyashstd = { builtin = true }
|
||||
|
||||
# === FFI-ABI経由外部API ===
|
||||
console_api = { bid = "./apis/console.yaml" }
|
||||
canvas_api = { bid = "./apis/canvas.yaml" }
|
||||
webgl_api = { bid = "./apis/webgl.yaml" }
|
||||
dom_api = { bid = "./apis/dom.yaml" }
|
||||
|
||||
# === システムライブラリ ===
|
||||
libc = { bid = "./apis/libc.yaml", library = "system" }
|
||||
math_lib = { bid = "./apis/math.yaml", library = "libm" }
|
||||
|
||||
# === 外部共有ライブラリ ===
|
||||
opencv = { bid = "./apis/opencv.yaml", library = "./libs/opencv.so" }
|
||||
sqlite = { bid = "./apis/sqlite.yaml", library = "./libs/sqlite.so" }
|
||||
|
||||
# === Nyashモジュール(従来通り) ===
|
||||
mylib = { path = "./src/mylib.hako" }
|
||||
utils = { path = "./src/utils.hako" }
|
||||
models = { path = "./src/models/" }
|
||||
|
||||
# === 将来の外部パッケージ ===
|
||||
# http_client = { version = "1.0.0", registry = "nyash-pkg" }
|
||||
|
||||
[build]
|
||||
entry_point = "./src/main.hako"
|
||||
backends = ["vm", "wasm", "aot"] # 対象バックエンド指定
|
||||
```
|
||||
|
||||
#### **BIDファイル例**
|
||||
```yaml
|
||||
# apis/console.yaml - Console API定義
|
||||
version: 0
|
||||
metadata:
|
||||
name: "Browser Console API"
|
||||
description: "Standard browser console interface"
|
||||
target_environments: ["browser", "node"]
|
||||
|
||||
interfaces:
|
||||
- name: console_api.console
|
||||
box: Console
|
||||
namespace: console_api
|
||||
methods:
|
||||
- name: log
|
||||
params: [ {string: message} ]
|
||||
returns: void
|
||||
effect: io
|
||||
description: "Output message to console"
|
||||
|
||||
- name: warn
|
||||
params: [ {string: message} ]
|
||||
returns: void
|
||||
effect: io
|
||||
|
||||
- name: error
|
||||
params: [ {string: message} ]
|
||||
returns: void
|
||||
effect: io
|
||||
|
||||
# apis/canvas.yaml - Canvas API定義
|
||||
version: 0
|
||||
interfaces:
|
||||
- name: canvas_api.canvas
|
||||
box: Canvas
|
||||
namespace: canvas_api
|
||||
methods:
|
||||
- name: fillRect
|
||||
params:
|
||||
- {string: canvas_id}
|
||||
- {i32: x}
|
||||
- {i32: y}
|
||||
- {i32: width}
|
||||
- {i32: height}
|
||||
- {string: color}
|
||||
returns: void
|
||||
effect: io
|
||||
|
||||
- name: fillText
|
||||
params:
|
||||
- {string: canvas_id}
|
||||
- {string: text}
|
||||
- {i32: x}
|
||||
- {i32: y}
|
||||
- {string: font}
|
||||
- {string: color}
|
||||
returns: void
|
||||
effect: io
|
||||
```
|
||||
|
||||
### 2. 統合名前空間レジストリ
|
||||
|
||||
#### **UniversalNamespaceRegistry設計**
|
||||
```rust
|
||||
// 新ファイル: src/registry/universal.rs
|
||||
use crate::stdlib::BuiltinStdlib;
|
||||
use crate::bid::BidDefinition;
|
||||
use crate::module::ExternalModule;
|
||||
|
||||
pub struct UniversalNamespaceRegistry {
|
||||
/// 組み込み標準ライブラリ
|
||||
builtin: Arc<BuiltinStdlib>,
|
||||
|
||||
/// FFI-ABI経由の外部API
|
||||
ffi_apis: HashMap<String, Arc<BidDefinition>>,
|
||||
|
||||
/// Nyashモジュール
|
||||
nyash_modules: HashMap<String, Arc<ExternalModule>>,
|
||||
|
||||
/// using imports(ファイル別)
|
||||
using_imports: Arc<RwLock<HashMap<String, UsingContext>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UsingContext {
|
||||
pub builtin_imports: Vec<String>, // ["nyashstd"]
|
||||
pub ffi_imports: Vec<String>, // ["console_api", "canvas_api"]
|
||||
pub module_imports: Vec<String>, // ["mylib", "utils"]
|
||||
pub file_id: String,
|
||||
}
|
||||
|
||||
impl UniversalNamespaceRegistry {
|
||||
pub fn new(nyash_link: &NyashLink) -> Result<Self, RegistryError> {
|
||||
let mut registry = UniversalNamespaceRegistry {
|
||||
builtin: Arc::new(BuiltinStdlib::new()),
|
||||
ffi_apis: HashMap::new(),
|
||||
nyash_modules: HashMap::new(),
|
||||
using_imports: Arc::new(RwLock::new(HashMap::new())),
|
||||
};
|
||||
|
||||
// nyash.linkからFFI-ABI定義読み込み
|
||||
registry.load_ffi_apis(nyash_link)?;
|
||||
|
||||
// Nyashモジュール読み込み
|
||||
registry.load_nyash_modules(nyash_link)?;
|
||||
|
||||
Ok(registry)
|
||||
}
|
||||
|
||||
/// 統合using文処理
|
||||
pub fn execute_using(&mut self, namespace_name: &str, file_id: &str)
|
||||
-> Result<(), RuntimeError> {
|
||||
|
||||
let context = self.using_imports
|
||||
.write().unwrap()
|
||||
.entry(file_id.to_string())
|
||||
.or_insert_with(|| UsingContext {
|
||||
builtin_imports: Vec::new(),
|
||||
ffi_imports: Vec::new(),
|
||||
module_imports: Vec::new(),
|
||||
file_id: file_id.to_string(),
|
||||
});
|
||||
|
||||
// 組み込み標準ライブラリ
|
||||
if self.builtin.has_namespace(namespace_name) {
|
||||
if !context.builtin_imports.contains(&namespace_name.to_string()) {
|
||||
context.builtin_imports.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// FFI-ABI API
|
||||
if self.ffi_apis.contains_key(namespace_name) {
|
||||
if !context.ffi_imports.contains(&namespace_name.to_string()) {
|
||||
context.ffi_imports.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Nyashモジュール
|
||||
if self.hako_modules.contains_key(namespace_name) {
|
||||
if !context.module_imports.contains(&namespace_name.to_string()) {
|
||||
context.module_imports.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedNamespace(namespace_name.to_string()))
|
||||
}
|
||||
|
||||
/// 統合関数解決
|
||||
pub fn resolve_call(&self, file_id: &str, path: &[String])
|
||||
-> Result<CallTarget, RuntimeError> {
|
||||
|
||||
if path.len() != 2 {
|
||||
return Err(RuntimeError::InvalidQualifiedName(path.join(".")));
|
||||
}
|
||||
|
||||
let box_name = &path[0];
|
||||
let method_name = &path[1];
|
||||
|
||||
if let Ok(imports) = self.using_imports.read() {
|
||||
if let Some(context) = imports.get(file_id) {
|
||||
|
||||
// 1. 組み込み標準ライブラリ検索
|
||||
for namespace in &context.builtin_imports {
|
||||
if let Some(target) = self.builtin.resolve_call(namespace, box_name, method_name) {
|
||||
return Ok(CallTarget::Builtin(target));
|
||||
}
|
||||
}
|
||||
|
||||
// 2. FFI-ABI API検索
|
||||
for namespace in &context.ffi_imports {
|
||||
if let Some(bid) = self.ffi_apis.get(namespace) {
|
||||
if let Some(target) = bid.resolve_method(box_name, method_name) {
|
||||
return Ok(CallTarget::FfiAbi(target));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Nyashモジュール検索
|
||||
for namespace in &context.module_imports {
|
||||
if let Some(module) = self.hako_modules.get(namespace) {
|
||||
if let Some(target) = module.resolve_method(box_name, method_name) {
|
||||
return Ok(CallTarget::NyashModule(target));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedMethod(format!("{}.{}", box_name, method_name)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CallTarget {
|
||||
Builtin(BuiltinMethodTarget),
|
||||
FfiAbi(FfiMethodTarget),
|
||||
NyashModule(NyashMethodTarget),
|
||||
}
|
||||
```
|
||||
|
||||
### 3. MIRレベル統合
|
||||
|
||||
#### **MIR命令拡張**
|
||||
```rust
|
||||
// src/mir/instruction.rs拡張
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MirInstruction {
|
||||
// 既存命令...
|
||||
|
||||
// === 統合関数呼び出し ===
|
||||
|
||||
/// 組み込み標準ライブラリ呼び出し
|
||||
BuiltinCall {
|
||||
target: String, // "string.upper"
|
||||
args: Vec<ValueId>,
|
||||
result: ValueId,
|
||||
effect: Effect,
|
||||
},
|
||||
|
||||
/// FFI-ABI外部API呼び出し
|
||||
ExternCall {
|
||||
interface: String, // "console_api.console"
|
||||
method: String, // "log"
|
||||
args: Vec<ValueId>,
|
||||
result: Option<ValueId>,
|
||||
effect: Effect,
|
||||
bid_signature: BidMethodSignature,
|
||||
},
|
||||
|
||||
/// Nyashモジュール関数呼び出し
|
||||
ModuleCall {
|
||||
module: String, // "mylib"
|
||||
function: String, // "processData"
|
||||
args: Vec<ValueId>,
|
||||
result: ValueId,
|
||||
effect: Effect,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Effect {
|
||||
Pure, // 副作用なし、並び替え可能
|
||||
Mut, // 同リソース内で順序保持
|
||||
Io, // プログラム順序保持
|
||||
Control, // 制御フロー影響
|
||||
}
|
||||
```
|
||||
|
||||
#### **MIR生成統合**
|
||||
```rust
|
||||
// src/mir/builder.rs拡張
|
||||
impl MirBuilder {
|
||||
pub fn build_unified_call(&mut self, target: CallTarget, args: Vec<ValueId>)
|
||||
-> Result<ValueId, MirError> {
|
||||
|
||||
match target {
|
||||
CallTarget::Builtin(builtin_target) => {
|
||||
let result = self.new_value_id();
|
||||
self.emit(MirInstruction::BuiltinCall {
|
||||
target: builtin_target.qualified_name(),
|
||||
args,
|
||||
result,
|
||||
effect: builtin_target.effect(),
|
||||
});
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
CallTarget::FfiAbi(ffi_target) => {
|
||||
let result = if ffi_target.returns_void() {
|
||||
None
|
||||
} else {
|
||||
Some(self.new_value_id())
|
||||
};
|
||||
|
||||
self.emit(MirInstruction::ExternCall {
|
||||
interface: ffi_target.interface_name(),
|
||||
method: ffi_target.method_name(),
|
||||
args,
|
||||
result,
|
||||
effect: ffi_target.effect(),
|
||||
bid_signature: ffi_target.signature().clone(),
|
||||
});
|
||||
|
||||
result.ok_or(MirError::VoidReturn)
|
||||
},
|
||||
|
||||
CallTarget::NyashModule(module_target) => {
|
||||
let result = self.new_value_id();
|
||||
self.emit(MirInstruction::ModuleCall {
|
||||
module: module_target.module_name(),
|
||||
function: module_target.function_name(),
|
||||
args,
|
||||
result,
|
||||
effect: Effect::Io, // デフォルト
|
||||
});
|
||||
Ok(result)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. バックエンド統合実装
|
||||
|
||||
#### **VM実行統合**
|
||||
```rust
|
||||
// src/backend/vm.rs拡張
|
||||
impl VmBackend {
|
||||
pub fn execute_instruction(&mut self, instr: &MirInstruction)
|
||||
-> Result<(), VmError> {
|
||||
|
||||
match instr {
|
||||
MirInstruction::BuiltinCall { target, args, result, .. } => {
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
let output = self.builtin_executor.call(target, evaluated_args)?;
|
||||
self.set_value(*result, output);
|
||||
Ok(())
|
||||
},
|
||||
|
||||
MirInstruction::ExternCall { interface, method, args, result, bid_signature, .. } => {
|
||||
// VM環境ではスタブ実装
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
let output = self.extern_stub.call(interface, method, evaluated_args, bid_signature)?;
|
||||
if let Some(res_id) = result {
|
||||
self.set_value(*res_id, output);
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
|
||||
MirInstruction::ModuleCall { module, function, args, result, .. } => {
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
let output = self.module_executor.call(module, function, evaluated_args)?;
|
||||
self.set_value(*result, output);
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// 既存命令処理...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **WASM生成統合**
|
||||
```rust
|
||||
// src/backend/wasm/codegen.rs拡張
|
||||
impl WasmCodegen {
|
||||
pub fn generate_instruction(&mut self, instr: &MirInstruction)
|
||||
-> Result<(), WasmError> {
|
||||
|
||||
match instr {
|
||||
MirInstruction::BuiltinCall { target, args, result, .. } => {
|
||||
// 組み込み関数は直接実装
|
||||
self.generate_builtin_call(target, args, *result)
|
||||
},
|
||||
|
||||
MirInstruction::ExternCall { interface, method, args, bid_signature, .. } => {
|
||||
// BIDから自動生成されたWASM import呼び出し
|
||||
let import_name = format!("{}_{}",
|
||||
interface.replace(".", "_"),
|
||||
method
|
||||
);
|
||||
|
||||
self.generate_extern_call(&import_name, args, bid_signature)
|
||||
},
|
||||
|
||||
MirInstruction::ModuleCall { module, function, args, result, .. } => {
|
||||
// 内部関数呼び出し
|
||||
let function_name = format!("{}_{}", module, function);
|
||||
self.generate_function_call(&function_name, args, *result)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// BIDからWASM RuntimeImports自動生成
|
||||
pub fn generate_runtime_imports(&mut self, bid_definitions: &[BidDefinition])
|
||||
-> Result<String, WasmError> {
|
||||
|
||||
let mut imports = String::new();
|
||||
|
||||
for bid in bid_definitions {
|
||||
for interface in &bid.interfaces {
|
||||
for method in &interface.methods {
|
||||
let import_name = format!("{}_{}",
|
||||
interface.name.replace(".", "_"),
|
||||
method.name
|
||||
);
|
||||
|
||||
let signature = self.bid_to_wasm_signature(&method.params, &method.returns)?;
|
||||
imports.push_str(&format!(
|
||||
"(import \"env\" \"{}\" {})\n",
|
||||
import_name, signature
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(imports)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **AOT生成統合**
|
||||
```rust
|
||||
// src/backend/aot/compiler.rs拡張
|
||||
impl AotCompiler {
|
||||
pub fn compile_instruction(&mut self, instr: &MirInstruction)
|
||||
-> Result<(), AotError> {
|
||||
|
||||
match instr {
|
||||
MirInstruction::ExternCall { interface, method, args, bid_signature, .. } => {
|
||||
// LLVM IR外部関数宣言生成
|
||||
let extern_func_name = format!("{}_{}",
|
||||
interface.replace(".", "_"),
|
||||
method
|
||||
);
|
||||
|
||||
let signature = self.bid_to_llvm_signature(bid_signature)?;
|
||||
self.declare_external_function(&extern_func_name, &signature)?;
|
||||
self.generate_call(&extern_func_name, args)?;
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// その他の命令処理...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 段階的実装戦略
|
||||
|
||||
### Phase 0: 基盤統合(2-3週間)
|
||||
1. **UniversalNamespaceRegistry実装** - 全API統一管理
|
||||
2. **nyash.link拡張** - BID依存関係サポート
|
||||
3. **統合using文** - 3種類のAPI統一インポート
|
||||
|
||||
### Phase 1: FFI-ABI統合(3-4週間)
|
||||
1. **BID読み込み機能** - YAML解析・検証
|
||||
2. **MIR ExternCall統合** - FFI-ABI→MIR変換
|
||||
3. **WASM RuntimeImports自動生成** - BID→WASM import
|
||||
|
||||
### Phase 2: 完全統合(4-6週間)
|
||||
1. **全バックエンド対応** - VM/WASM/AOT統合実装
|
||||
2. **エラーハンドリング統合** - 統一エラーモデル
|
||||
3. **パフォーマンス最適化** - 高速名前解決
|
||||
|
||||
## 🧪 統合テスト戦略
|
||||
|
||||
### 基本統合テスト
|
||||
```nyash
|
||||
# test_universal_integration.hako
|
||||
using nyashstd
|
||||
using console_api
|
||||
using mylib
|
||||
|
||||
# 3種類のAPIが同じように使える
|
||||
assert(string.upper("test") == "TEST") # 組み込み
|
||||
console.log("Integration test successful") # FFI-ABI
|
||||
assert(mylib.process("data") == "processed") # Nyash
|
||||
```
|
||||
|
||||
### FFI-ABI統合テスト
|
||||
```nyash
|
||||
# test_ffi_abi_integration.hako
|
||||
using canvas_api
|
||||
|
||||
# Canvas API経由での描画
|
||||
canvas.fillRect("game-canvas", 10, 10, 100, 100, "red")
|
||||
canvas.fillText("game-canvas", "Score: 100", 10, 30, "16px Arial", "white")
|
||||
```
|
||||
|
||||
## 🌟 期待される革命的効果
|
||||
|
||||
### 🚀 開発者体験
|
||||
- **統一API**: 組み込み・外部・自作すべて同じ書き方
|
||||
- **IDE補完**: すべてのAPIが`ny`で補完される
|
||||
- **エラー処理**: 統一エラーモデルで一貫性
|
||||
|
||||
### 🏗️ アーキテクチャ
|
||||
- **MIRレベル統合**: 全バックエンドで同じパフォーマンス最適化
|
||||
- **Effect System**: pure/mut/io/controlによる安全性保証
|
||||
- **言語非依存**: BIDによる外部ライブラリ標準化
|
||||
|
||||
### 🌍 エコシステム
|
||||
- **なんでもAPI**: あらゆる外部ライブラリがNyashから使える
|
||||
- **バックエンド統一**: 同じコードがVM/WASM/AOTで動作
|
||||
- **将来拡張**: パッケージレジストリでBID共有
|
||||
|
||||
---
|
||||
|
||||
**🎉 この統合設計で、Nyashが真に「なんでもできる」モダン言語になるにゃ!🚀🐱**
|
||||
@ -1,106 +0,0 @@
|
||||
# Phase 195: Pattern 4 (Loop with Continue) Implementation Plan
|
||||
|
||||
**Status**: Deferred (not yet implemented)
|
||||
|
||||
## Overview
|
||||
|
||||
Pattern 4 handles loops with `continue` statements that skip to the next iteration. This is the most complex loop pattern due to additional control flow requirements.
|
||||
|
||||
## Why Deferred?
|
||||
|
||||
1. **Continue semantics require additional PHI and control flow analysis**
|
||||
- Continue creates an additional edge to the loop header
|
||||
- Requires phi nodes for both continue and normal paths
|
||||
- More complex than break (which exits the loop)
|
||||
|
||||
2. **Pattern 3 covers most practical cases**
|
||||
- Pattern 1: Simple while loops
|
||||
- Pattern 2: Loops with break
|
||||
- Pattern 3: Loops with if + PHI (most common complex pattern)
|
||||
- Pattern 4: Loops with continue (less common in practice)
|
||||
|
||||
3. **Lower priority than break/if patterns**
|
||||
- Break patterns (Pattern 2) are more common
|
||||
- If + PHI patterns (Pattern 3) handle complex control flow
|
||||
- Continue can often be refactored using if statements
|
||||
|
||||
## Example Use Case
|
||||
|
||||
```nyash
|
||||
local i = 0
|
||||
local sum = 0
|
||||
loop(i < 10) {
|
||||
i = i + 1
|
||||
if (i % 2 == 0) {
|
||||
continue // Skip even numbers
|
||||
}
|
||||
sum = sum + i
|
||||
}
|
||||
// sum = 25 (1+3+5+7+9)
|
||||
```
|
||||
|
||||
## Implementation Requirements
|
||||
|
||||
When implemented, Pattern 4 lowering will need to:
|
||||
|
||||
1. **Detect continue statements** in the loop body
|
||||
2. **Generate PHI nodes** for continue target (loop header)
|
||||
3. **Handle carrier variables** (i, sum) across continue boundaries
|
||||
4. **Generate exit PHI nodes** for final values after loop
|
||||
|
||||
## Control Flow Diagram
|
||||
|
||||
```
|
||||
header
|
||||
|
|
||||
v
|
||||
body
|
||||
|
|
||||
/----+----\
|
||||
/ \
|
||||
v v
|
||||
continue normal
|
||||
| |
|
||||
\-----+-------/
|
||||
|
|
||||
v
|
||||
latch
|
||||
|
|
||||
/---+---\
|
||||
/ \
|
||||
v v
|
||||
loop exit
|
||||
```
|
||||
|
||||
## Workaround
|
||||
|
||||
Until Pattern 4 is implemented, use Pattern 3 (if + PHI) instead:
|
||||
|
||||
```nyash
|
||||
local i = 0
|
||||
local sum = 0
|
||||
loop(i < 10) {
|
||||
i = i + 1
|
||||
if (not (i % 2 == 0)) { // Invert condition
|
||||
sum = sum + i
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Migration Path
|
||||
|
||||
1. **Pattern 1**: Simple while loops (no break/continue)
|
||||
2. **Pattern 2**: Loops with break
|
||||
3. **Pattern 3**: Loops with if + PHI
|
||||
4. **Pattern 4**: (FUTURE) Loops with continue statements
|
||||
|
||||
## Related Files
|
||||
|
||||
- `src/mir/builder/control_flow/joinir/patterns/pattern4_with_continue.rs` - Stub implementation
|
||||
- `src/mir/join_ir/lowering/loop_with_continue_minimal.rs` - Lowering logic (TODO)
|
||||
|
||||
## Timeline
|
||||
|
||||
- Phase 195+: Implementation planned but deferred
|
||||
- Priority: Lower than Pattern 1-3
|
||||
- Complexity: High (additional control flow edges)
|
||||
@ -1,74 +0,0 @@
|
||||
# Scope Reuse Blocks (MVP Proposal)
|
||||
|
||||
Status: design-only during the feature‑pause (no implementation)
|
||||
|
||||
Summary
|
||||
- Give short, reusable logic a name within the current scope without promoting it to a top-level function.
|
||||
- Keep the core small: block body + postfix header sugar; desugar to local function + normal calls.
|
||||
- Zero runtime cost: lowers to let/if/call/ret only (no new instructions/closures).
|
||||
|
||||
Syntax (postfix header; Nyash style)
|
||||
- Block form (multi-statement):
|
||||
```nyash
|
||||
{ /* BODY */ } scope name(arglist?) (-> Ret)?
|
||||
// call within the same scope
|
||||
name(args)
|
||||
```
|
||||
- Expression form (one-liner):
|
||||
```nyash
|
||||
=> EXPR scope name(arglist?) (-> Ret)?
|
||||
```
|
||||
|
||||
Semantics
|
||||
- Visibility: `name` is local to the defining scope; not exported.
|
||||
- Capture: by reference by default. Mutating captured vars requires explicit `mut` on those bindings.
|
||||
- Recursion: disallowed in MVP (can be lifted later).
|
||||
- Errors/exits: same as regular functions (return/cleanup/catch apply at the function boundary).
|
||||
|
||||
Lowering (desugaring)
|
||||
- Transform into a local function plus a local binding for convenience calls.
|
||||
```nyash
|
||||
// { BODY } scope check(a:Int)->Str
|
||||
// ↓ (conceptual)
|
||||
let __cap_me = me; let __cap_locals = { /* needed refs */ };
|
||||
method __scope_check__(a:Int)->Str {
|
||||
return BODY
|
||||
}
|
||||
let check = (x) => __scope_check__(x)
|
||||
```
|
||||
- Captures are passed via hidden arguments or an environment box; no new VM opcodes.
|
||||
|
||||
Examples
|
||||
```nyash
|
||||
{ if x % 2 == 0 { return "even" } return "odd" } scope parity(x:Int)->StringBox
|
||||
|
||||
for i in range(0,10) {
|
||||
print(parity(i))
|
||||
}
|
||||
```
|
||||
|
||||
Safety rules (MVP)
|
||||
- Capture: read-only by default; writes allowed only when the captured binding is declared `mut`.
|
||||
- Name uniqueness: `scope name` must be unique within the scope.
|
||||
- No cross-scope escape: values may be returned but the function reference itself is not exported.
|
||||
|
||||
Observability & Tooling
|
||||
- Add trace toggles (design only):
|
||||
- `NYASH_SCOPE_TRACE=1|json` to emit enter/exit and capture lists as JSONL.
|
||||
- Example: `{ "ev":"enter","sid":42,"caps":["me","cfg","mut total"] }`.
|
||||
- Lints (design only):
|
||||
- Single-use scope → suggest inline.
|
||||
- Excess captures → suggest narrowing.
|
||||
|
||||
Interactions
|
||||
- Works with guard/with/await sugars (it’s just a call).
|
||||
- Compatible with ASI and postfix aesthetics; no new top-level keywords beyond `scope` suffix.
|
||||
|
||||
Tests (syntax-only smokes; design)
|
||||
- scope_basic: called twice → same result.
|
||||
- scope_capture_read: reads `me/foo`.
|
||||
- scope_capture_mut: mutation only allowed when `mut` is present.
|
||||
- scope_with_catch_cleanup: postfix catch/cleanup applied at local-function boundary.
|
||||
|
||||
Pause note
|
||||
- This is documentation and design intent only. Implementation is deferred until after the feature‑pause (post‑bootstrap).
|
||||
@ -1,629 +0,0 @@
|
||||
# Stage1セルフホスティング起動アーキテクチャ改善提案
|
||||
|
||||
## 📋 エグゼクティブサマリー
|
||||
|
||||
Nyashのセルフホスティング実装で、Stage0(Rust)→ Stage1(.hako script)の起動が**環境変数25個**と**3つの引数経路**で複雑化している問題を整理し、業界標準パターンに基づいた改善案を提示する。
|
||||
|
||||
**現状の痛み**:
|
||||
- 環境変数25個(NYASH_*/STAGE1_*/HAKO_*)が15個以上のファイルに散在
|
||||
- Stage0とStage1の役割境界が曖昧(汎用ランチャー vs 専用CLI)
|
||||
- 引数経路が3つ(CLI args / env vars / JSON)で混在
|
||||
- 巨大prelude(70+ファイル結合)でデバッグ困難(エラーが`line 10433`と表示)
|
||||
|
||||
**改善目標**:
|
||||
- 環境変数を**5個以下**に削減
|
||||
- 引数経路を**1つ**に統一
|
||||
- デバッグビリティ向上(source map対応)
|
||||
- 短期(Phase 25.2)と長期(Phase 26+)の段階実装
|
||||
|
||||
---
|
||||
|
||||
## 🔍 A. 他言語の事例調査
|
||||
|
||||
### A-1. Rustコンパイラのブートストラップ(3段階明確化)
|
||||
|
||||
**アーキテクチャ**:
|
||||
```
|
||||
Stage 0: 事前ビルド済みベータ版rustc(CI artifactsからダウンロード)
|
||||
↓
|
||||
Stage 1: Stage0でビルドしたrustc + 標準ライブラリ(機能完全)
|
||||
↓
|
||||
Stage 2: Stage1で再ビルドしたrustc(検証用・本番利用)
|
||||
↓
|
||||
Stage 3: Stage2で再ビルドしたrustc(完全自己再現性検証)
|
||||
```
|
||||
|
||||
**特徴**:
|
||||
- **明確な責務分離**: Stage0は「ビルドツール」、Stage1以降は「開発コンパイラ」
|
||||
- **環境変数最小**: `RUSTC_BOOTSTRAP`など**4個のみ**
|
||||
- **CLI引数優先**: 環境変数はビルドシステム内部のみ、ユーザーは`x build --stage N`でシンプル操作
|
||||
- **2024年改善**: Stage0でstdも事前ビルド版を使用し、`cfg(bootstrap)`を削除(複雑性削減)
|
||||
|
||||
**参考**: [Rust Compiler Development Guide - Bootstrapping](https://rustc-dev-guide.rust-lang.org/building/bootstrapping/what-bootstrapping-does.html)
|
||||
|
||||
---
|
||||
|
||||
### A-2. Goコンパイラのブートストラップ(段階自動化)
|
||||
|
||||
**アーキテクチャ**:
|
||||
```
|
||||
Bootstrap Compiler: Go 1.N-2(最小2バージョン前)
|
||||
↓
|
||||
cmd/dist: ブートストラップビルドツール(Go製)
|
||||
↓
|
||||
Toolchain1 → Toolchain2 → Toolchain3(自動多段階ビルド)
|
||||
```
|
||||
|
||||
**特徴**:
|
||||
- **自動段階切り替え**: `cmd/dist`が段階を自動制御、ユーザーは意識不要
|
||||
- **環境変数ゼロ**: すべてCLI引数で制御(`GOROOT`, `GOPATH`のみ)
|
||||
- **最適化重視**: 無関係アーキテクチャ向けファイルはダミー化(6秒短縮)
|
||||
- **バージョンポリシー明確**: 1.24/1.25は1.22が必須(N-2ルール)
|
||||
|
||||
**参考**: [How Go uses Go to build itself](https://dave.cheney.net/2013/06/04/how-go-uses-go-to-build-itself)
|
||||
|
||||
---
|
||||
|
||||
### A-3. Nimコンパイラのブートストラップ(C経由2段階)
|
||||
|
||||
**アーキテクチャ**:
|
||||
```
|
||||
csources_v3: C言語生成コード(Nim古バージョンから生成)
|
||||
↓
|
||||
koch.nim: ブートストラップツール
|
||||
↓
|
||||
Nim Compiler v1: 完全機能版
|
||||
↓
|
||||
Nim Compiler v2: 自己再ビルド版(検証)
|
||||
```
|
||||
|
||||
**特徴**:
|
||||
- **Cソース安定化**: `csources_v3`リポジトリで分離管理
|
||||
- **ツール一本化**: `koch`が「ビルド・テスト・ドキュメント生成」すべて担当
|
||||
- **環境変数なし**: すべて`koch`のサブコマンドで制御
|
||||
- **2024年改革**: NIR中間言語導入で、フロントエンド複数バージョン対応予定
|
||||
|
||||
**参考**: [Nim GitHub - Internals](https://nim-lang.org/docs/intern.html)
|
||||
|
||||
---
|
||||
|
||||
### A-4. 設定管理の業界標準パターン
|
||||
|
||||
**優先度階層(POSIX標準準拠)**:
|
||||
```
|
||||
1. CLI引数(最優先) ← ユーザーの明示的意図
|
||||
2. 環境変数 ← セッション固有設定
|
||||
3. ローカル設定ファイル ← プロジェクト設定
|
||||
4. グローバル設定ファイル ← システム設定
|
||||
5. デフォルト値(最低優先)
|
||||
```
|
||||
|
||||
**設計原則**(ASP.NET Core / AWS CLI / Typerなどで共通):
|
||||
- **CLI引数が常に勝つ**: 環境変数よりCLI引数が優先(明示性)
|
||||
- **環境変数は「上書き」専用**: デフォルト値の一時変更に限定
|
||||
- **設定ファイルは「永続化」**: プロジェクト設定は`~/.config`や`.toml`に
|
||||
- **Chain of Responsibility**: 見つかるまで順に探索、最後に見つかった値が勝つ
|
||||
|
||||
**参考**: [Stack Overflow - Configuration Precedence](https://stackoverflow.com/questions/11077223/what-order-of-reading-configuration-values)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 B. Nyash向け具体的改善案
|
||||
|
||||
### B-1. 優先度1: 環境変数の階層化(15個→5個)
|
||||
|
||||
**現状の問題**:
|
||||
```bash
|
||||
# 現在の25個の環境変数(抜粋)
|
||||
NYASH_USE_STAGE1_CLI=1
|
||||
STAGE1_EMIT_PROGRAM_JSON=1
|
||||
STAGE1_EMIT_MIR_JSON=1
|
||||
STAGE1_BACKEND=vm
|
||||
STAGE1_SOURCE=/path/to/file.hako
|
||||
STAGE1_PROGRAM_JSON=/path/to/prog.json
|
||||
STAGE1_SOURCE_TEXT="..."
|
||||
STAGE1_CLI_ENTRY=/path/to/cli.hako
|
||||
HAKO_STAGEB_APPLY_USINGS=1
|
||||
NYASH_ENABLE_USING=1
|
||||
HAKO_ENABLE_USING=1
|
||||
NYASH_PARSER_STAGE3=1
|
||||
HAKO_PARSER_STAGE3=1
|
||||
NYASH_FILEBOX_MODE=auto
|
||||
NYASH_BOX_FACTORY_POLICY=builtin_first
|
||||
# ... さらに10個以上
|
||||
```
|
||||
|
||||
**改善後(5個に集約)**:
|
||||
```bash
|
||||
# 1. モード制御(単一変数でサブコマンド切り替え)
|
||||
NYASH_STAGE1_MODE=emit-program-json # emit-mir-json / run-vm / run-llvm
|
||||
# → 7個の環境変数を1個に統合
|
||||
|
||||
# 2. 入力ソース(パスまたはインライン)
|
||||
NYASH_STAGE1_INPUT=/path/to/source.hako # または STDIN: "-"
|
||||
# → STAGE1_SOURCE / STAGE1_SOURCE_TEXT / STAGE1_INPUT を統合
|
||||
|
||||
# 3. 機能トグル(ビットフラグまたはカンマ区切り)
|
||||
NYASH_FEATURES=using,parser-stage3,plugins # または空文字でデフォルト
|
||||
# → ENABLE_USING / PARSER_STAGE3 / DISABLE_PLUGINS を統合
|
||||
|
||||
# 4. デバッグ/ログ(現状は NYASH_CLI_VERBOSE / STAGE1_CLI_DEBUG を併用)
|
||||
# → 将来 NYASH_STAGE1_MODE に統合する想定(NYASH_DEBUG は未使用のため削除済み)
|
||||
|
||||
# 5. ランタイムポリシー(設定ファイル移行推奨)
|
||||
# 現状は個別 env を使用(NYASH_RUNTIME_CONFIG は未使用のため削除済み)
|
||||
```
|
||||
|
||||
**実装戦略**:
|
||||
- **Phase 1(短期)**: 新環境変数を追加し、旧環境変数を内部変換(後方互換)
|
||||
- **Phase 2(中期)**: ドキュメントで新方式を推奨、旧環境変数に非推奨警告
|
||||
- **Phase 3(長期)**: 旧環境変数を削除、新方式のみサポート
|
||||
|
||||
---
|
||||
|
||||
### B-2. 優先度2: アーキテクチャ統一(役割明確化)
|
||||
|
||||
**現状の問題**:
|
||||
- Stage0(Rust): 汎用ランチャー(`Main.main` / `main` を探す)
|
||||
- Stage1(.hako): 専用CLI(`stage1_cli emit program-json ...`)
|
||||
- 第三の経路: Stage0が子プロセスでStage1を起動(環境変数渡し)
|
||||
- → どれが「正」か不明瞭、エントリ解決ルールが衝突
|
||||
|
||||
**改善後(Rust流3段階明確化)**:
|
||||
```
|
||||
Stage 0(Rust VM/LLVM):
|
||||
役割: ビルド済み実行器(Rustでビルド、本番利用)
|
||||
入力: MIR(JSON)、.hako(パーサー組み込み)
|
||||
出力: 実行結果、オブジェクトファイル
|
||||
制約: セルフホスト不要、安定版として配布
|
||||
|
||||
Stage 1(.hako script - UsingResolver + MirBuilder):
|
||||
役割: セルフホスト開発コンパイラ(Stage0で実行)
|
||||
入力: .hako(ソースコード)
|
||||
出力: Program(JSON v0) → MIR(JSON)
|
||||
制約: Stage0に依存、開発者向け
|
||||
|
||||
Stage 2(将来: 完全セルフホスト):
|
||||
役割: Stage1でビルドしたStage1(自己再現性検証)
|
||||
入力/出力: Stage1と同一
|
||||
制約: Phase 26以降で実装
|
||||
```
|
||||
|
||||
**CLI統一案**:
|
||||
```bash
|
||||
# 1. 本番利用(Stage0直接実行)- 現状維持
|
||||
nyash program.hako # Rust VMで直接実行
|
||||
nyash --backend llvm prog.hako # LLVM AOTコンパイル
|
||||
|
||||
# 2. セルフホスト開発(Stage1経由)- 新CLI
|
||||
nyash --stage1 emit program-json source.hako > program.json
|
||||
nyash --stage1 emit mir-json source.hako > mir.json
|
||||
nyash --stage1 run --backend vm source.hako
|
||||
|
||||
# 3. 検証用(Stage2自己ビルド)- 将来拡張
|
||||
nyash --stage2 build stage1_compiler.hako -o stage1_new
|
||||
```
|
||||
|
||||
**実装戦略**:
|
||||
- `--stage1`フラグで明示的にStage1経由を選択(環境変数なし)
|
||||
- Stage0とStage1の責務を完全分離(エントリ解決ルールの衝突解消)
|
||||
- `NYASH_USE_STAGE1_CLI`は非推奨化、`--stage1`で置き換え
|
||||
|
||||
---
|
||||
|
||||
### B-3. 優先度3: 引数経路の統一(3経路→1経路)
|
||||
|
||||
**現状の問題**:
|
||||
```
|
||||
経路1: CLI引数 → stage1_args → stage1_main(args)
|
||||
経路2: 環境変数 → STAGE1_SOURCE / STAGE1_PROGRAM_JSON
|
||||
経路3: JSON → NYASH_SCRIPT_ARGS_JSON
|
||||
```
|
||||
→ どの経路で値が渡るか実行時まで不明
|
||||
|
||||
**改善後(CLI引数一本化)**:
|
||||
```bash
|
||||
# 1. サブコマンド形式(Git/Cargo風)
|
||||
nyash stage1 emit program-json source.hako
|
||||
nyash stage1 emit mir-json source.hako
|
||||
nyash stage1 run --backend vm source.hako -- arg1 arg2
|
||||
|
||||
# 2. 引数の優先度階層(業界標準)
|
||||
CLI引数 > 環境変数 > nyash.toml > デフォルト値
|
||||
|
||||
# 3. 環境変数は「一時上書き」のみ
|
||||
NYASH_STAGE1_MODE=emit-program-json nyash source.hako # 開発時のみ
|
||||
```
|
||||
|
||||
**実装戦略**:
|
||||
- Stage1側で`clap`相当の引数パーサーを実装(`LoopOptsBox`を拡張)
|
||||
- `NYASH_SCRIPT_ARGS_JSON`は廃止、すべて`--`以降のCLI引数で渡す
|
||||
- 環境変数は「デフォルト値の一時上書き」に限定(永続設定は`nyash.toml`へ)
|
||||
|
||||
---
|
||||
|
||||
### B-4. 優先度4: デバッグビリティ向上(source map対応)
|
||||
|
||||
**現状の問題**:
|
||||
```
|
||||
[error] Syntax error at line 10433
|
||||
```
|
||||
→ 70+ファイルを結合したpreludeで、どのファイルのどの行か特定不可
|
||||
|
||||
**改善案(3段階)**:
|
||||
|
||||
**Stage 1(短期): 行番号マップの埋め込み**
|
||||
```json
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"source_map": [
|
||||
{"line": 1, "file": "prelude/array_box.hako", "orig_line": 1},
|
||||
{"line": 50, "file": "prelude/string_box.hako", "orig_line": 1},
|
||||
{"line": 150, "file": "user/main.hako", "orig_line": 1}
|
||||
],
|
||||
"body": [...]
|
||||
}
|
||||
```
|
||||
- Program(JSON v0)に`source_map`フィールドを追加
|
||||
- エラー時に「line 10433 (prelude/array_box.hako:42)」と表示
|
||||
|
||||
**Stage 2(中期): Source Map v3形式**
|
||||
```json
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["prelude/array_box.hako", "main.hako"],
|
||||
"mappings": "AAAA,CAAC;AAAD,CAAC...",
|
||||
"sourcesContent": ["...", "..."]
|
||||
}
|
||||
```
|
||||
- JavaScript/TypeScript標準のSource Map v3に準拠
|
||||
- デバッガー連携可能(VSCode/gdb対応)
|
||||
|
||||
**Stage 3(長期): プリコンパイル分離**
|
||||
```
|
||||
prelude.hako (70ファイル)
|
||||
↓ 事前コンパイル
|
||||
prelude.mir (MIRバイナリ)
|
||||
↓ リンク
|
||||
user_program.mir + prelude.mir → final.exe
|
||||
```
|
||||
- プリコンパイル済みプレリュードを配布(起動高速化)
|
||||
- ユーザーコードのみパース(エラー箇所明確化)
|
||||
|
||||
**実装戦略**:
|
||||
- Phase 25.2でStage 1実装(JSON v0に`source_map`追加)
|
||||
- Phase 26でStage 2実装(Source Map v3対応)
|
||||
- Phase 27以降でStage 3検討(MIRバイナリフォーマット設計)
|
||||
|
||||
---
|
||||
|
||||
## 📊 C. 優先順位と実装ロードマップ
|
||||
|
||||
### C-1. 短期解決(Phase 25.2: 今すぐできる)
|
||||
|
||||
**目標**: 開発者の混乱を即座に解消
|
||||
|
||||
**タスク**:
|
||||
1. **環境変数ドキュメント整備**(1日)
|
||||
- 現在の25個を用途別に分類(必須/推奨/非推奨)
|
||||
- `docs/reference/environment-variables.md`作成
|
||||
- 各変数の相互作用を図解
|
||||
|
||||
2. **デバッグ用ヘルパースクリプト**(2日)
|
||||
- `tools/stage1_debug.sh`: 環境変数を自動設定・ログ出力
|
||||
- `tools/stage1_minimal.sh`: 最小限の5変数で実行
|
||||
- エラー時に「どの環境変数が未設定か」を診断
|
||||
|
||||
3. **行番号マップ簡易版**(3日)
|
||||
- Stage-B側で`#line <num> "<file>"`コメント挿入
|
||||
- Rust側のパーサーエラーで元ファイル名を表示
|
||||
- 完全なsource mapは後回し(まず動く最小実装)
|
||||
|
||||
**成果物**:
|
||||
- 開発者が「何を設定すればいいか」明確化
|
||||
- エラー箇所の特定時間を50%削減
|
||||
- 後方互換性100%(既存コード無変更)
|
||||
|
||||
---
|
||||
|
||||
### C-2. 中期解決(Phase 25.3-25.5: 3-6ヶ月)
|
||||
|
||||
**目標**: アーキテクチャの根本整理
|
||||
|
||||
**タスク**:
|
||||
1. **新環境変数への移行**(2週間)
|
||||
- `NYASH_STAGE1_MODE`など5個の新変数実装
|
||||
- 旧変数→新変数の自動変換レイヤー追加
|
||||
- 非推奨警告を出力(2週間後から)
|
||||
|
||||
2. **CLI統一インターフェース**(1ヶ月)
|
||||
- `nyash stage1 <subcommand>`形式を実装
|
||||
- `clap`相当の引数パーサーを.hako側に実装
|
||||
- `--`以降の引数処理を標準化
|
||||
|
||||
3. **Source Map v3対応**(1ヶ月)
|
||||
- Program(JSON v0)にsource_mapフィールド追加
|
||||
- MIRビルダー側でマッピング情報を保持
|
||||
- エラーメッセージで元ファイル・行番号を表示
|
||||
|
||||
4. **設定ファイル統合**(2週間)
|
||||
- `nyash.toml`に`[stage1]`セクション追加
|
||||
- ランタイムポリシーを環境変数から移行
|
||||
- 優先度階層テスト(CLI > env > toml > default)
|
||||
|
||||
**成果物**:
|
||||
- 環境変数25個→5個に削減(80%削減)
|
||||
- 引数経路を1つに統一
|
||||
- デバッグ体験が劇的改善
|
||||
|
||||
---
|
||||
|
||||
### C-3. 長期解決(Phase 26+: 6ヶ月以降)
|
||||
|
||||
**目標**: 完全セルフホスティング達成
|
||||
|
||||
**タスク**:
|
||||
1. **Stage 2自己ビルド**(3ヶ月)
|
||||
- Stage1でStage1をビルド可能に
|
||||
- 再現性検証テスト自動化
|
||||
- ブートストラップ時間の最適化
|
||||
|
||||
2. **プリコンパイル済みプレリュード**(2ヶ月)
|
||||
- MIRバイナリフォーマット設計
|
||||
- プレリュード事前コンパイル機能
|
||||
- リンク機構実装
|
||||
|
||||
3. **旧環境変数完全削除**(1ヶ月)
|
||||
- 非推奨警告を1年間継続後
|
||||
- 旧変数サポートコード削除
|
||||
- クリーンアップ・最終テスト
|
||||
|
||||
**成果物**:
|
||||
- Rustコンパイラ並みの成熟度
|
||||
- セルフホスティング完全動作
|
||||
- 保守性・拡張性の根本確立
|
||||
|
||||
---
|
||||
|
||||
## 🎯 D. 最小限の環境変数セット(5個)
|
||||
|
||||
### D-1. 推奨セット(開発・本番両用)
|
||||
|
||||
```bash
|
||||
# 1. モード制御(サブコマンド相当)
|
||||
NYASH_STAGE1_MODE=run-vm # emit-program-json | emit-mir-json | run-vm | run-llvm
|
||||
|
||||
# 2. 入力ファイル(または "-" でSTDIN)
|
||||
NYASH_STAGE1_INPUT=source.hako
|
||||
|
||||
# 3. 機能トグル(カンマ区切り)
|
||||
NYASH_FEATURES=using,parser-stage3,plugins
|
||||
|
||||
# 4. デバッグ/ログは NYASH_CLI_VERBOSE / STAGE1_CLI_DEBUG を併用(暫定)
|
||||
# 5. 設定ファイルパスは現状なし(NYASH_CONFIG は未使用のため削除済み)
|
||||
```
|
||||
|
||||
### D-2. 設定ファイル形式(nyash.toml)
|
||||
|
||||
```toml
|
||||
[stage1]
|
||||
mode = "run-vm" # デフォルトモード
|
||||
backend = "vm" # run時のバックエンド
|
||||
|
||||
[runtime]
|
||||
box_factory_policy = "builtin_first"
|
||||
filebox_mode = "auto"
|
||||
|
||||
[debug]
|
||||
level = 1 # 0-3
|
||||
dump_mir = false
|
||||
dump_program_json = false
|
||||
|
||||
[features]
|
||||
using = true
|
||||
parser_stage3 = true
|
||||
plugins = true
|
||||
```
|
||||
|
||||
### D-3. 優先度階層の実装例
|
||||
|
||||
```rust
|
||||
// CLI引数 > 環境変数 > 設定ファイル > デフォルト値
|
||||
fn resolve_config(cli_args: &CliArgs) -> Config {
|
||||
let mode = cli_args.mode // 1. CLI引数(最優先)
|
||||
.or_else(|| std::env::var("NYASH_STAGE1_MODE").ok()) // 2. 環境変数
|
||||
.or_else(|| load_from_toml("stage1.mode")) // 3. 設定ファイル
|
||||
.unwrap_or("run-vm".to_string()); // 4. デフォルト値
|
||||
|
||||
Config {
|
||||
mode,
|
||||
debug_level: resolve_debug_level(cli_args),
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📈 E. 期待される効果
|
||||
|
||||
### E-1. 定量的効果
|
||||
|
||||
| 項目 | 改善前 | 改善後 | 改善率 |
|
||||
|-----|-------|-------|-------|
|
||||
| 環境変数数 | 25個 | 5個 | **80%削減** |
|
||||
| 引数経路 | 3つ | 1つ | **67%削減** |
|
||||
| エラー特定時間 | 30分 | 5分 | **83%削減** |
|
||||
| ドキュメント理解時間 | 2時間 | 15分 | **87%削減** |
|
||||
| ブートストラップ失敗率 | 30% | 5% | **83%削減** |
|
||||
|
||||
### E-2. 定性的効果
|
||||
|
||||
**開発者体験**:
|
||||
- ✅ 「何を設定すればいいか」が一目瞭然
|
||||
- ✅ エラー箇所が即座に特定可能
|
||||
- ✅ 他言語経験者がすぐ理解(Rust/Go流標準パターン)
|
||||
|
||||
**保守性**:
|
||||
- ✅ 環境変数の相互作用が最小化
|
||||
- ✅ 新機能追加時の複雑性増大を抑制
|
||||
- ✅ テストケースが大幅削減(組み合わせ爆発回避)
|
||||
|
||||
**拡張性**:
|
||||
- ✅ Stage 2自己ビルドへの道筋が明確
|
||||
- ✅ プリコンパイル済みプレリュード実装が容易
|
||||
- ✅ 将来のIDEプラグイン開発が簡単
|
||||
|
||||
---
|
||||
|
||||
## 🚀 F. 実装開始ガイド
|
||||
|
||||
### F-1. Phase 25.2タスク(今すぐ開始)
|
||||
|
||||
**Week 1: ドキュメント整備**
|
||||
```bash
|
||||
# 1. 環境変数リスト作成
|
||||
docs/reference/environment-variables.md
|
||||
- 現在の25個を分類(必須/推奨/非推奨/削除予定)
|
||||
- 相互作用図を追加(Mermaid図解)
|
||||
|
||||
# 2. クイックスタートガイド更新
|
||||
docs/guides/selfhosting-quickstart.md
|
||||
- 最小5変数での起動例
|
||||
- トラブルシューティングチェックリスト
|
||||
```
|
||||
|
||||
**Week 2: ヘルパースクリプト**
|
||||
```bash
|
||||
# 1. デバッグヘルパー実装
|
||||
tools/stage1_debug.sh
|
||||
- 環境変数を自動設定・ログ出力
|
||||
- 未設定変数の診断機能
|
||||
|
||||
# 2. 最小実行スクリプト
|
||||
tools/stage1_minimal.sh
|
||||
- 5変数のみで実行
|
||||
- 成功時のテンプレートとして提供
|
||||
```
|
||||
|
||||
実装メモ(2025-11 時点の足場)
|
||||
- `tools/stage1_debug.sh` と `tools/stage1_minimal.sh` は「新5変数」の実装前の足場として、
|
||||
既存の `NYASH_USE_STAGE1_CLI` / `STAGE1_EMIT_PROGRAM_JSON` などにマッピングする薄いラッパとして先行実装しておく。
|
||||
- これにより:
|
||||
- 開発者は「まずこの2スクリプト経由で」 Stage‑1 経路を叩けばよくなる。
|
||||
- 後続で Rust 側に `NYASH_STAGE1_MODE` などを実装しても、スクリプト側の I/F を変えずに内部マッピングだけ差し替えられる。
|
||||
- CI やドキュメントも「スクリプト経由」の説明に統一できる。
|
||||
|
||||
**Week 3-4: 行番号マップ簡易版**
|
||||
```rust
|
||||
// src/runner/stage1_bridge.rs
|
||||
impl Stage1Bridge {
|
||||
fn inject_line_markers(source: &str, filename: &str) -> String {
|
||||
// #line <num> "<file>" コメント挿入
|
||||
}
|
||||
|
||||
fn parse_error_with_source_map(error: &str) -> String {
|
||||
// エラーメッセージから元ファイル・行番号を復元
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### F-2. Phase 25.3-25.5タスク(中期実装)
|
||||
|
||||
**Month 1: 新環境変数への移行**
|
||||
- `NYASH_STAGE1_MODE`など5変数の実装
|
||||
- 旧変数→新変数の互換レイヤー
|
||||
- 非推奨警告の実装
|
||||
|
||||
**Month 2: CLI統一インターフェース**
|
||||
- `nyash stage1 <subcommand>`形式
|
||||
- 引数パーサーの実装(.hako側)
|
||||
|
||||
**Month 3: Source Map v3対応**
|
||||
- Program(JSON v0)へのsource_map追加
|
||||
- エラーメッセージの改善
|
||||
|
||||
**Month 4-6: 設定ファイル統合・テスト**
|
||||
- `nyash.toml`への移行
|
||||
- 優先度階層の完全テスト
|
||||
|
||||
---
|
||||
|
||||
## 📚 G. 参考資料
|
||||
|
||||
### G-1. 業界標準ドキュメント
|
||||
|
||||
- **Rust Compiler Development Guide**: https://rustc-dev-guide.rust-lang.org/building/bootstrapping/
|
||||
- **Go Command Documentation**: https://go.dev/doc/install/source
|
||||
- **POSIX Utility Conventions**: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
|
||||
- **Source Map v3 Spec**: https://sourcemaps.info/spec.html
|
||||
|
||||
### G-2. 設定管理設計パターン
|
||||
|
||||
- **Stack Overflow - Configuration Precedence**: https://stackoverflow.com/questions/11077223/what-order-of-reading-configuration-values
|
||||
- **Microsoft - ASP.NET Core Configuration**: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/
|
||||
- **AWS CLI Environment Variables**: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html
|
||||
|
||||
### G-3. Nyash内部ドキュメント
|
||||
|
||||
- `CURRENT_TASK.md`: Phase 25.1-25.2の進捗状況
|
||||
- `docs/private/roadmap2/phases/phase-25.1/stage1-usingresolver-loopform.md`: Stage1設計詳細
|
||||
- `docs/development/runtime/cli-hakorune-stage1.md`: CLI仕様(SSOT)
|
||||
- `src/runner/stage1_bridge.rs`: Rust側ブリッジ実装
|
||||
- `lang/src/runner/stage1_cli.hako`: Stage1 CLI本体
|
||||
|
||||
---
|
||||
|
||||
## ✅ H. チェックリスト
|
||||
|
||||
### H-1. 短期実装(Phase 25.2)
|
||||
|
||||
- [ ] 環境変数ドキュメント作成(`docs/reference/environment-variables.md`)
|
||||
- [ ] デバッグヘルパースクリプト実装(`tools/stage1_debug.sh`)
|
||||
- [ ] 最小実行スクリプト実装(`tools/stage1_minimal.sh`)
|
||||
- [ ] 行番号マップ簡易版実装(`#line`コメント挿入)
|
||||
- [ ] エラーメッセージ改善(元ファイル名・行番号表示)
|
||||
|
||||
### H-2. 中期実装(Phase 25.3-25.5)
|
||||
|
||||
- [ ] 新環境変数5個の実装
|
||||
- [ ] 旧変数→新変数の互換レイヤー
|
||||
- [ ] 非推奨警告の実装
|
||||
- [ ] `nyash stage1 <subcommand>` CLI実装
|
||||
- [ ] Source Map v3対応
|
||||
- [ ] `nyash.toml`への設定移行
|
||||
- [ ] 優先度階層の完全テスト
|
||||
|
||||
### H-3. 長期実装(Phase 26+)
|
||||
|
||||
- [ ] Stage 2自己ビルド実装
|
||||
- [ ] プリコンパイル済みプレリュード
|
||||
- [ ] 旧環境変数の完全削除
|
||||
- [ ] ドキュメント最終整備
|
||||
|
||||
---
|
||||
|
||||
## 🎉 まとめ
|
||||
|
||||
**現状**: 環境変数25個、引数経路3つ、デバッグ困難
|
||||
|
||||
**改善案**:
|
||||
1. **環境変数を5個に削減**(階層化・統合)
|
||||
2. **CLI引数を1経路に統一**(Git/Cargo流サブコマンド)
|
||||
3. **Source Map対応**(エラー箇所即座特定)
|
||||
4. **段階実装**(短期・中期・長期で分割)
|
||||
|
||||
**期待効果**:
|
||||
- 開発者の混乱を**80%削減**
|
||||
- エラー特定時間を**83%削減**
|
||||
- Rust/Goと同等の成熟度達成
|
||||
|
||||
**実装開始**: Phase 25.2から段階的にスタート、後方互換性100%維持
|
||||
|
||||
---
|
||||
|
||||
**Document Version**: 1.0
|
||||
**Date**: 2025-11-21
|
||||
**Author**: Claude (Anthropic Claude Sonnet 4.5)
|
||||
**Status**: Proposal - Ready for Review
|
||||
@ -1,137 +0,0 @@
|
||||
# Property System Revolution for Nyash (2025-09-18 Breakthrough)
|
||||
|
||||
Status: **BREAKTHROUGH COMPLETED** - Final syntax decided through AI collaboration with ChatGPT, Claude, and Codex.
|
||||
|
||||
## 🌟 Revolutionary Achievement
|
||||
Today we achieved the **Property System Revolution** - a complete unification of stored fields, computed properties, lazy evaluation, and birth-time initialization into a single, elegant syntax system through AI collaboration with ChatGPT5, Claude, and Codex.
|
||||
|
||||
## 🎯 Final Property System Design
|
||||
|
||||
### The Four-Category Breakthrough
|
||||
After dialectical discussion with multiple AI agents, we reached the perfect synthesis:
|
||||
|
||||
#### 1. **stored** - Traditional Field Storage
|
||||
```nyash
|
||||
box Example {
|
||||
name: StringBox // Default initialization
|
||||
count: IntegerBox = 0 // Explicit initialization
|
||||
}
|
||||
```
|
||||
- **Semantics**: O(1) slot read/write, assignment allowed
|
||||
- **Use Case**: Traditional object fields, counters, configurations
|
||||
|
||||
#### 2. **computed** - Calculated Every Access
|
||||
```nyash
|
||||
box Example {
|
||||
size: IntegerBox { me.items.count() }
|
||||
full_name: StringBox { me.first + " " + me.last }
|
||||
}
|
||||
```
|
||||
- **Semantics**: Evaluate body on each read, assignment error unless setter declared
|
||||
- **Use Case**: Derived values, dynamic calculations, Python @property equivalent
|
||||
|
||||
#### 3. **once** - Lazy Evaluation with Caching
|
||||
```nyash
|
||||
box Example {
|
||||
once expensive_data: DataBox { heavy_computation() }
|
||||
once config: ConfigBox { loadConfiguration() }
|
||||
}
|
||||
```
|
||||
- **Semantics**: Evaluate on first read, cache result, return cached value thereafter
|
||||
- **Use Case**: Heavy computations, file loading, Python @cached_property equivalent
|
||||
- **Exception Handling**: Poison-on-throw strategy for safety
|
||||
|
||||
#### 4. **birth_once** - Eager Evaluation at Object Creation
|
||||
```nyash
|
||||
box Example {
|
||||
birth_once startup_data: DataBox { initialize_system() }
|
||||
|
||||
birth() {
|
||||
// birth_once properties already initialized!
|
||||
me.ready = true
|
||||
}
|
||||
}
|
||||
```
|
||||
- **Semantics**: Evaluated before user birth() in declaration order
|
||||
- **Use Case**: System initialization, dependency setup, startup-critical data
|
||||
|
||||
## 🌟 Revolutionary Python Integration
|
||||
|
||||
### Perfect Mapping Strategy
|
||||
```python
|
||||
# Python side
|
||||
class DataProcessor:
|
||||
def __init__(self):
|
||||
self.value = 42 # → stored
|
||||
|
||||
@property
|
||||
def computed_result(self): # → computed
|
||||
return self.value * 2
|
||||
|
||||
@functools.cached_property
|
||||
def expensive_data(self): # → once
|
||||
return heavy_computation()
|
||||
```
|
||||
|
||||
```nyash
|
||||
// Auto-generated Nyash (revolutionary 1:1 mapping!)
|
||||
box DataProcessor {
|
||||
value: IntegerBox // stored
|
||||
computed_result: IntegerBox { me.value * 2 } // computed
|
||||
once expensive_data: ResultBox { heavy_computation() } // once
|
||||
|
||||
birth() {
|
||||
me.value = 42
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Performance Revolution
|
||||
- **computed properties**: No caching overhead, pure calculation
|
||||
- **once properties**: 10-50x faster than Python cached_property (LLVM optimization)
|
||||
- **birth_once properties**: Startup optimization, dependency injection pattern
|
||||
- **Overall**: Python code → 5-20x faster native binary
|
||||
|
||||
Handlers (Stage‑3)
|
||||
- Postfix `catch/cleanup` are allowed for computed/once/birth_once/method blocks.
|
||||
- Stored does not accept handlers.
|
||||
|
||||
Semantics
|
||||
- stored: O(1) slot read; `= expr` evaluated once during construction; assignment allowed.
|
||||
- computed: evaluate on each read; assignment is an error unless a setter is declared.
|
||||
- once: evaluate on first read, cache the result, and return it thereafter. If the first evaluation throws and there is no `catch`, mark poisoned and rethrow the same error on later reads (no retry).
|
||||
- birth_once: evaluated before user `birth` body in declaration order; uncaught error aborts construction. Cycles are rejected.
|
||||
|
||||
Lowering (no JSON v0 change)
|
||||
- stored → slot
|
||||
- computed → synthesize `__get_name():T { try body; catch; finally }`, resolve reads to call
|
||||
- once → add hidden `__name: Option<T>` and first-read initialization in `__get_name()`; poison on uncaught error
|
||||
- birth_once → hidden `__name: T` initialized before user `birth` body in declaration order; handler blocks apply per initializer
|
||||
- method → unchanged; postfix handlers lower to try/catch/finally
|
||||
|
||||
EBNF (delta)
|
||||
```
|
||||
box_decl := 'box' IDENT '{' member* '}'
|
||||
member := stored | computed | once_decl | birth_once_decl | method_decl
|
||||
stored := IDENT ':' TYPE ( '=' expr )?
|
||||
computed := IDENT ':' TYPE block handler_tail?
|
||||
once_decl := 'once' IDENT ':' TYPE block handler_tail?
|
||||
birth_once_decl:= 'birth_once' IDENT ':' TYPE block handler_tail?
|
||||
method_decl := IDENT '(' params? ')' ( ':' TYPE )? block handler_tail?
|
||||
handler_tail := ( catch_block )? ( cleanup_block )?
|
||||
catch_block := 'catch' ( '(' ( IDENT IDENT | IDENT )? ')' )? block
|
||||
cleanup_block := 'cleanup' block
|
||||
```
|
||||
|
||||
Diagnostics
|
||||
- Assignment to computed/once/birth_once: error with fix-it (“define a setter or use stored property”).
|
||||
- Once poison: first read throws → remember error; subsequent reads rethrow immediately.
|
||||
- Birth order: evaluated before user `birth`, in declaration order; cycle detection emits a clear error with the chain.
|
||||
|
||||
Flags
|
||||
- Parser gate: `NYASH_ENABLE_UNIFIED_MEMBERS=1`
|
||||
- Stage‑3 for handlers: `NYASH_PARSER_STAGE3=1`
|
||||
|
||||
Notes
|
||||
- User experience: read is uniform (`obj.name`), write differs by kind; this keeps mental model simple.
|
||||
- Future: setter syntax (`name: T { get {…} set(v) {…} }`) and aliases (`slot/calc/lazy`) can be added without breaking this core.
|
||||
@ -1,306 +0,0 @@
|
||||
# 🚨 緊急修正 Issue: Everything is Box設計でのclone_box()問題根本解決
|
||||
|
||||
## 📋 Issue概要
|
||||
**優先度**: 🔴 **URGENT** - 全ステートフルBox(SocketBox, 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.hako
|
||||
```
|
||||
|
||||
### 実行・検証
|
||||
```bash
|
||||
# ビルド・実行
|
||||
cargo build --release
|
||||
./target/release/nyash test_arc_fix.hako
|
||||
|
||||
# 期待される結果:
|
||||
# === 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.hako` で `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日以内
|
||||
@ -1,104 +0,0 @@
|
||||
# Phase 10.1: JIT→EXE via Plugin Box Unification
|
||||
|
||||
## 🎯 革新的発見:すべてはプラグインになる
|
||||
|
||||
### 核心的洞察
|
||||
既存のプラグインシステム(BID-FFI)がすでに完全なC ABIを持っている。
|
||||
これを活用することで、JIT→EXE変換が現実的に可能。
|
||||
|
||||
## 📊 フェーズ概要
|
||||
|
||||
### 目標
|
||||
- ビルトインBoxをプラグイン化してC ABI統一
|
||||
- JITから統一されたプラグインAPIを呼び出し
|
||||
- スタティックリンクによるスタンドアロンEXE生成
|
||||
|
||||
### 背景
|
||||
```
|
||||
現在の構造:
|
||||
- JIT → HostCall → Rustビルトイン(複雑)
|
||||
- JIT → PluginInvoke → プラグインBox(C FFI)
|
||||
|
||||
統一後:
|
||||
- JIT → PluginInvoke → すべてのBox(統一!)
|
||||
- EXE → PluginInvoke → スタティックリンクされたBox
|
||||
```
|
||||
|
||||
## 🚀 実装計画
|
||||
|
||||
### Week 1: ArrayBoxプラグイン化PoC(詳細は phase_plan.md 参照)
|
||||
- ArrayBoxをプラグインとして再実装
|
||||
- JITからのプラグイン呼び出しテスト
|
||||
- パフォーマンス測定(HostCall vs Plugin)
|
||||
|
||||
### Week 2: 主要Box移行(詳細は phase_plan.md 参照)
|
||||
- StringBox、IntegerBox、BoolBoxのプラグイン化
|
||||
- JIT lowering層の統一(plugin_invoke経由)
|
||||
- 既存HostCallとの共存メカニズム
|
||||
|
||||
### Week 3: 静的リンク基盤(詳細は phase_plan.md 参照)
|
||||
- プラグインの`.a`ライブラリビルド
|
||||
- 最小ランタイム(nyash-runtime)設計
|
||||
- リンカースクリプト作成
|
||||
|
||||
### Week 4: EXE生成実証(詳細は phase_plan.md 参照)
|
||||
- Hello Worldレベルのスタンドアロン実行
|
||||
- Linux/macOSでの動作確認
|
||||
- デバッグ情報とunwind対応
|
||||
|
||||
## 📁 ディレクトリ構造(予定)
|
||||
|
||||
```
|
||||
plugins/
|
||||
├── nyash-core-boxes/ # ビルトインBox群
|
||||
│ ├── nyash-array-plugin/
|
||||
│ ├── nyash-string-plugin/
|
||||
│ └── nyash-integer-plugin/
|
||||
├── nyash-runtime-minimal/ # 最小ランタイム
|
||||
└── existing/ # 既存プラグイン
|
||||
├── nyash-file-plugin/
|
||||
└── nyash-net-plugin/
|
||||
```
|
||||
|
||||
## 🔗 関連資料(整備済み)
|
||||
|
||||
- フェーズ計画の詳細: [phase_plan.md](./phase_plan.md)
|
||||
- C ABI v0 仕様(JIT/AOT/Plugin共通): ../../../../docs/reference/abi/nyrt_c_abi_v0.md
|
||||
- 命名: `nyrt_*`(コア)/ `nyplug_{name}_*`(プラグイン)
|
||||
- 呼出規約: x86_64 SysV / aarch64 AAPCS64 / Win64
|
||||
- `*_abi_version()` で fail-fast(v0=1)
|
||||
|
||||
## ストリームエラー対策(長文/大出力を避ける)
|
||||
- 先頭に短い要約(サマリ)を置く(本READMEの冒頭にあり)
|
||||
- 詳細設計や長いコードは分割して参照(phase_plan.md / nyrt_c_abi_v0.md)
|
||||
- コマンドやコードは三連バッククォートで閉じ忘れ防止
|
||||
|
||||
- [革新的アプローチ詳細](../../../ideas/new-features/2025-08-28-jit-exe-via-plugin-unification.md)
|
||||
- [プラグインAPI仕様](../../../../reference/plugin-system/)
|
||||
- [Phase 10.5: Python統合計画](../phase-10.5/) (旧10.1)
|
||||
- [Phase 10.10: 前段階の成果](../phase-10/phase_10_10/)
|
||||
|
||||
## ⚡ 成功指標
|
||||
|
||||
1. **技術的検証**
|
||||
- ArrayBoxがプラグインとして動作
|
||||
- JITからの呼び出し成功
|
||||
- 性能劣化10%以内
|
||||
|
||||
2. **統合達成**
|
||||
- 5つ以上のビルトインBoxがプラグイン化
|
||||
- JIT lowering層の完全統一
|
||||
|
||||
3. **EXE生成**
|
||||
- スタンドアロン実行ファイル生成
|
||||
- 基本的なNyashプログラムの動作
|
||||
|
||||
## 🎉 期待される成果
|
||||
|
||||
- **Everything is Plugin** - 新たな設計哲学の確立
|
||||
- 自己ホスティングへの現実的な道筋
|
||||
- プラグインエコシステムの拡大可能性
|
||||
|
||||
---
|
||||
|
||||
*"Everything is Box → Everything is Plugin → Everything is Possible"*
|
||||
@ -1,157 +0,0 @@
|
||||
# C ABI統一設計 - JIT/AOT共通基盤
|
||||
|
||||
*ChatGPT5さんからのアドバイスに基づく設計文書*
|
||||
|
||||
## 🎯 核心的洞察
|
||||
|
||||
**プラグインBoxのC ABI = そのままJIT/AOTの呼び出し土台**
|
||||
|
||||
JITで今呼んでいるC ABIをAOTでは静的リンクに差し替えるだけでexe化まで一直線!
|
||||
|
||||
## 📊 全体アーキテクチャ
|
||||
|
||||
```
|
||||
Nyash → MIR → VM/JIT/Cranelift ──┐
|
||||
├─ 呼ぶ先は全部 C ABI: nyrt_* / nyplug_*
|
||||
NyRT (libnyrt.a/.so) ←──────────┘
|
||||
PluginBox 実装 (libnyplug_*.a/.so)
|
||||
```
|
||||
|
||||
- **JIT**: `extern "C"` シンボル(`nyrt_*`/`nyplug_*`)をその場で呼ぶ
|
||||
- **AOT**: 同じシンボルを`.o`に未解決のまま出力→`libnyrt.a`とプラグイン`.a`をリンク
|
||||
- **動的配布**: `.so/.dll`に差し替え(同じC ABIでOK)
|
||||
|
||||
## 🔧 C ABIルール(小さく強い)
|
||||
|
||||
### 1. 命名/可視性
|
||||
- コア: `nyrt_*`(Box/weak/bus/gc/sync/alloc...)
|
||||
- プラグイン: `nyplug_{name}_*`(ArrayBox, StringBox など)
|
||||
- `extern "C"` + 明示の可視性(ELF: `__attribute__((visibility("default")))`)
|
||||
|
||||
### 2. ABIの型
|
||||
- 引数/戻り: `int32_t/int64_t/uint64_t/double/void*` のみに限定
|
||||
- `bool`は`uint8_t`統一、構造体は不透明ポインタ(ハンドル)
|
||||
- `varargs`と例外のABI横断は**禁止**(戻り値でエラーコード/out-paramで返す)
|
||||
|
||||
### 3. レイアウト/アライン
|
||||
```c
|
||||
// Boxハンドル例
|
||||
struct NyBox {
|
||||
void* data;
|
||||
uint64_t typeid;
|
||||
uint32_t flags;
|
||||
uint32_t gen;
|
||||
};
|
||||
```
|
||||
※JIT側は中身に触らない。操作はAPI経由のみ。
|
||||
|
||||
### 4. 呼び出し規約
|
||||
- x86_64 SysV / aarch64 AAPCS64 / Win64 をターゲットごとに固定
|
||||
- Craneliftの`call_conv`を上記に合わせる(JIT/AOT共通)
|
||||
|
||||
### 5. バージョン管理(fail-fast)
|
||||
- `nyrt_abi_version()` / `nyplug_{name}_abi_version()`(v0=1)。不一致は起動時に即fail(ローダ側で検査)。
|
||||
|
||||
## 📝 最小ヘッダ雛形
|
||||
|
||||
### nyrt.h(コアランタイム)
|
||||
```c
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct NyBox {
|
||||
void* data;
|
||||
uint64_t typeid;
|
||||
uint32_t flags;
|
||||
uint32_t gen;
|
||||
} NyBox;
|
||||
|
||||
int32_t nyrt_abi_version(void);
|
||||
|
||||
// Box/weak
|
||||
NyBox nyrt_box_new(uint64_t typeid, uint64_t size);
|
||||
void nyrt_box_free(NyBox b);
|
||||
int32_t nyrt_adopt(NyBox parent, NyBox child);
|
||||
int32_t nyrt_release(NyBox parent, NyBox child, NyBox* out_weak);
|
||||
NyBox nyrt_weak_load(NyBox weak); // gen一致ならBox, 失効なら{0}
|
||||
|
||||
// GC/epoch
|
||||
void nyrt_epoch_collect(void);
|
||||
|
||||
// Sync(最低限)
|
||||
void* nyrt_mutex_lock(NyBox sync);
|
||||
void nyrt_mutex_unlock(void* guard);
|
||||
|
||||
// Bus
|
||||
int32_t nyrt_bus_send(NyBox port, NyBox msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### nyplug_array.h(プラグイン例:ArrayBox)
|
||||
```c
|
||||
#pragma once
|
||||
#include "nyrt.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int32_t nyplug_array_abi_version(void);
|
||||
NyBox nyplug_array_new(void);
|
||||
int32_t nyplug_array_get(NyBox arr, uint64_t i, NyBox* out);
|
||||
int32_t nyplug_array_set(NyBox arr, uint64_t i, NyBox v);
|
||||
uint64_t nyplug_array_len(NyBox arr);
|
||||
int32_t nyplug_array_push(NyBox arr, NyBox v);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
## 🚀 ビルド・配布フロー(AOT静的リンク)
|
||||
|
||||
1. **JITと同じLowering**でCLIF生成
|
||||
2. **ObjectWriter**で`mod.o`出力(未解決:`nyrt_*`/`nyplug_*`)
|
||||
3. **リンク**
|
||||
- Linux/macOS: `cc mod.o -static -L. -lnyrt -lnyplug_array -o app`
|
||||
- Windows: `link mod.obj nyrt.lib nyplug_array.lib /OUT:app.exe`
|
||||
4. 実行:`./app`でJIT無しに動作
|
||||
|
||||
補足: 現行実装ではプラグインは `nyash_plugin_invoke`(BID-FFI v1, TLV)を用いる。v0ではこれを固定し、将来的に `nyplug_*` 直関数を併置する場合も `*_abi_version()` で互換を担保する。
|
||||
|
||||
## ⚡ 実装順序(重要!)
|
||||
|
||||
1. **必要なビルトインBoxをプラグインBoxに変換**
|
||||
2. **VM動作確認**
|
||||
3. **JIT動作確認**
|
||||
4. **AOT実装**
|
||||
|
||||
## ⚠️ 地雷と回避策
|
||||
|
||||
- **名前修飾/装飾**: C++で実装するなら`extern "C"`を絶対忘れない
|
||||
- **サイズ違い**: `bool`/`size_t`のプラットフォーム差 → 明示幅型で統一
|
||||
- **例外越境**: C ABI越しに`throw`/`panic`禁止。エラーコード+out-paramで返す
|
||||
- **並行**: JITから`nyrt_mutex_*`を呼ぶ箇所はSafepointとも整合するように(長保持しない)
|
||||
|
||||
## 📋 即実行ToDo(30分で前進)
|
||||
|
||||
- [ ] `nyrt.h`最小セット確定(上の雛形でOK)
|
||||
- [ ] Craneliftの`call_conv`をターゲットに合わせて固定
|
||||
- [ ] JIT経路で`nyrt_abi_version()==NYRT_ABI`を起動時チェック
|
||||
- [ ] AOT試作:`add.o`を吐いて`libnyrt.a`とリンク→`add()`を呼ぶ最小exe
|
||||
|
||||
## 💡 まとめ
|
||||
|
||||
> プラグインBoxのC ABI=JIT/AOTの土台だから、
|
||||
> **いまのJITが動いている=静的リンクexeの最短ルートはもう目の前。**
|
||||
> まずは`nyrt.h`を固定して、JITとAOTの両方で同じシンボルを呼ぶ状態にしよう。
|
||||
> それで**"今日のJIT"が"明日のexe"**に化けるにゃ。
|
||||
|
||||
---
|
||||
|
||||
*最終更新: 2025-08-28*
|
||||
@ -1,180 +0,0 @@
|
||||
# Phase 10.1 実装ステップガイド
|
||||
|
||||
## 🎯 実装の鉄則:必ずこの順序で!
|
||||
|
||||
ChatGPT5さんの指摘通り、緻密な計画と順序が成功の鍵にゃ。
|
||||
|
||||
## 📊 実装ステップ
|
||||
|
||||
### Step 1: ArrayBoxのプラグイン化(最小実装)
|
||||
|
||||
#### 1.1 プロジェクト作成
|
||||
```bash
|
||||
cd plugins/
|
||||
cargo new nyash-array-plugin --lib
|
||||
cd nyash-array-plugin
|
||||
```
|
||||
|
||||
#### 1.2 最小限のC FFI実装
|
||||
```rust
|
||||
// src/lib.rs
|
||||
#[repr(C)]
|
||||
pub struct NyBox {
|
||||
data: *mut u8,
|
||||
typeid: u64,
|
||||
flags: u32,
|
||||
gen: u32,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyplug_array_abi_version() -> i32 { 1 }
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyplug_array_new() -> NyBox {
|
||||
// 簡略実装:Vec<i64>のみサポート
|
||||
let vec = Box::new(Vec::<i64>::new());
|
||||
NyBox {
|
||||
data: Box::into_raw(vec) as *mut u8,
|
||||
typeid: 3, // ArrayBox
|
||||
flags: 0,
|
||||
gen: 1,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyplug_array_len(arr: NyBox) -> u64 {
|
||||
unsafe {
|
||||
let vec = &*(arr.data as *const Vec<i64>);
|
||||
vec.len() as u64
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.3 ビルド設定
|
||||
```toml
|
||||
# Cargo.toml
|
||||
[lib]
|
||||
crate-type = ["cdylib", "staticlib"] # 動的・静的両対応
|
||||
```
|
||||
|
||||
### Step 2: VM動作確認
|
||||
|
||||
#### 2.1 プラグインローダーとの統合
|
||||
```rust
|
||||
// src/runtime/plugin_loader_v2.rsに追加
|
||||
fn load_builtin_plugins(&mut self) {
|
||||
// 既存のFileBox等に加えて
|
||||
self.register_plugin("nyash-array-plugin", 3); // ArrayBox type_id = 3
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 テストプログラム
|
||||
```nyash
|
||||
// test_array_plugin.hako
|
||||
local arr
|
||||
arr = new ArrayBox() // プラグイン版を呼ぶ
|
||||
print(arr.length()) // 0が出力されれば成功
|
||||
```
|
||||
|
||||
#### 2.3 VM実行
|
||||
```bash
|
||||
./target/release/nyash --backend vm test_array_plugin.hako
|
||||
```
|
||||
|
||||
### Step 3: JIT動作確認
|
||||
|
||||
#### 3.1 LowerCoreの修正
|
||||
```rust
|
||||
// src/jit/lower/core.rs
|
||||
match box_type {
|
||||
"ArrayBox" => {
|
||||
// HostCallからPluginInvokeに切り替え
|
||||
b.emit_plugin_invoke(3, method_id, args);
|
||||
}
|
||||
// 他のBoxは従来通り
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2 JIT実行テスト
|
||||
```bash
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 ./target/release/nyash --backend vm test_array_plugin.hako
|
||||
```
|
||||
|
||||
### Step 4: 段階的移行
|
||||
|
||||
#### 4.1 移行優先順位
|
||||
1. **ArrayBox** - 最も使用頻度が高い
|
||||
2. **StringBox** - 基本的なデータ型
|
||||
3. **IntegerBox/BoolBox** - プリミティブ型
|
||||
4. **MapBox** - コレクション型
|
||||
5. **その他** - 順次移行
|
||||
|
||||
#### 4.2 互換性維持
|
||||
```rust
|
||||
// フラグで切り替え可能に
|
||||
if env::var("NYASH_USE_PLUGIN_BUILTINS").is_ok() {
|
||||
// プラグイン版を使用
|
||||
} else {
|
||||
// 従来のビルトイン版
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: パフォーマンス測定
|
||||
|
||||
#### 5.1 ベンチマーク作成
|
||||
```nyash
|
||||
// bench_array_ops.hako
|
||||
local arr = new ArrayBox()
|
||||
local start = Timer.now()
|
||||
loop(i in 0..1000000) {
|
||||
arr.push(i)
|
||||
}
|
||||
local elapsed = Timer.now() - start
|
||||
print("Time: " + elapsed)
|
||||
```
|
||||
|
||||
#### 5.2 比較測定
|
||||
```bash
|
||||
# 従来版
|
||||
./target/release/nyash --benchmark bench_array_ops.hako
|
||||
|
||||
# プラグイン版
|
||||
NYASH_USE_PLUGIN_BUILTINS=1 ./target/release/nyash --benchmark bench_array_ops.hako
|
||||
```
|
||||
|
||||
## 🎯 成功基準
|
||||
|
||||
### Phase 1(1週間)
|
||||
- [ ] ArrayBoxプラグインが動作
|
||||
- [ ] VM経由で基本操作(new, length, push, get)が可能
|
||||
- [ ] パフォーマンス劣化が10%以内
|
||||
|
||||
### Phase 2(2週間)
|
||||
- [ ] JIT経由でも動作
|
||||
- [ ] 5つ以上のビルトインBoxがプラグイン化
|
||||
- [ ] 既存テストがすべてパス
|
||||
|
||||
### Phase 3(1ヶ月)
|
||||
- [ ] すべての主要ビルトインBoxがプラグイン化
|
||||
- [ ] 静的リンクでの最小exe生成
|
||||
- [ ] Linux/macOSで動作確認
|
||||
|
||||
## ⚠️ 注意事項
|
||||
|
||||
1. **TLVエンコーディング**: 既存のプラグインシステムに合わせる
|
||||
2. **エラー処理**: panicではなくエラーコードを返す
|
||||
3. **メモリ管理**: Box化されたデータのライフサイクルに注意
|
||||
|
||||
## 💡 デバッグ時のヒント
|
||||
|
||||
```bash
|
||||
# プラグインロード確認
|
||||
NYASH_DEBUG_PLUGIN=1 ./target/release/nyash test.hako
|
||||
|
||||
# JIT呼び出し確認
|
||||
NYASH_JIT_EVENTS=1 ./target/release/nyash --backend vm test.hako
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*"手順を守れば大丈夫" - 一歩ずつ確実に進めるにゃ!*
|
||||
@ -1,87 +0,0 @@
|
||||
# Phase 10.1 – Plugin Unification Path (MIR→JIT/AOT via C ABI)
|
||||
|
||||
This plan refines how we leverage the existing plugin system (BID-FFI) to unify JIT and AOT (EXE) paths using a single C ABI surface.
|
||||
|
||||
## Goals
|
||||
- Unify calls from JIT and AOT to the same C ABI (`nyrt_*` / `nyplug_*`).
|
||||
- Convert builtin Boxes to Plugin Boxes in small steps (read-only first).
|
||||
- Produce a minimal standalone EXE via static linking after unification.
|
||||
|
||||
## Feasibility Summary
|
||||
- JIT: emit calls to `extern "C"` symbols (no change in semantics, only target).
|
||||
- AOT: emit `.o` with unresolved `nyrt_*` / `nyplug_*` and link with `libnyrt.a` + plugin `.a`.
|
||||
- Compatibility: guard with `NYASH_USE_PLUGIN_BUILTINS` and keep HostCall fallback.
|
||||
|
||||
## Phase Breakdown
|
||||
|
||||
### 10.1: Plugin PoC + C ABI base (1 week)
|
||||
- Deliverables:
|
||||
- Minimal headers: `nyrt.h` (runtime), `nyplug_array.h` (ArrayBox plugin).
|
||||
- ArrayBox as a plugin (`cdylib` + `staticlib`), ABI version functions.
|
||||
- VM loader integration and `NYASH_USE_PLUGIN_BUILTINS` switch.
|
||||
- Smoke: `new/len/push/get` working via plugin.
|
||||
- DoD:
|
||||
- Array plugin works on VM path; perf regression ≤10% on micro bench.
|
||||
|
||||
### 10.2: JIT Lowering unification (Array first) (1–1.5 weeks)
|
||||
- Deliverables:
|
||||
- IRBuilder: `emit_plugin_invoke(type_id, method_id, args, sig)`.
|
||||
- LowerCore BoxCall for Array routes to `plugin_invoke` (events/stats intact).
|
||||
- Feature-flagged enablement: `NYASH_USE_PLUGIN_BUILTINS=1`.
|
||||
- DoD:
|
||||
- JIT execution of Array read/write (policy-constrained) via plugin path.
|
||||
- Behavior parity with HostCall; no regressions on CI smoke.
|
||||
|
||||
### 10.2b: JIT Coverage Unblockers (0.5–1 week)
|
||||
- Goal:
|
||||
- Remove practical blockers so plugin_invoke can be exercised in typical Nyash functions and `.o` can be produced.
|
||||
- Deliverables:
|
||||
- Lowering for `NewBox` of pluginized builtins → translate `new <Box>()` to plugin `birth()` via `emit_plugin_invoke(type_id, 0, argc=1 recvr-param)` with appropriate handle threading.
|
||||
- Treat `Print/Debug` as no-op/hostcall for v0 to avoid function-wide skip.
|
||||
- Keep conservative skip policy by default; document `NYASH_AOT_ALLOW_UNSUPPORTED=1` for validation-only `.o` emission.
|
||||
- DoD:
|
||||
- Minimal demo function with `String.length()` compiled by JIT (Cranelift) and `.o` emitted. Plugin events visible under JIT.
|
||||
|
||||
### 10.3: Broaden plugin coverage + Compatibility (2 weeks)
|
||||
- Targets: String/Integer/Bool/Map (read-only first).
|
||||
- Deliverables:
|
||||
- Pluginized Boxes and `plugin_invoke` lowering for BoxCall.
|
||||
- HostCall route retained; whitelist-driven co-existence.
|
||||
- Added smoke and microbenches comparing HostCall vs Plugin.
|
||||
- DoD:
|
||||
- ≥5 builtin Boxes pluginized; `NYASH_USE_PLUGIN_BUILTINS=1` green on smoke.
|
||||
|
||||
### 10.4: AOT/EXE minimal pipeline (2–3 weeks)
|
||||
- Deliverables:
|
||||
- ObjectWriter path to emit `.o` with unresolved `nyrt_*`/`nyplug_*`.
|
||||
- `libnyrt.a` minimal runtime + selected plugin `.a`.
|
||||
- Link scripts and `nyc build-aot` proof-of-concept.
|
||||
- Hello World-level standalone EXE on Linux/macOS.
|
||||
- DoD:
|
||||
- `nyc build-aot <file.hako> -o app` runs without JIT/VM.
|
||||
- Basic debug info and minimal unwind.
|
||||
|
||||
### 10.5: Python Integration (moved; separate phase)
|
||||
- Python work is deferred to 10.5 and builds on the plugin/AOT foundation.
|
||||
|
||||
## Flags & Compatibility
|
||||
- `NYASH_USE_PLUGIN_BUILTINS=1` – enables plugin path for builtin Boxes.
|
||||
- `NYASH_JIT_HOSTCALL=1` – preserves HostCall path for comparison.
|
||||
- Call conv alignment: x86_64 SysV, aarch64 AAPCS64, Win64.
|
||||
- ABI version checks: `nyrt_abi_version()`, `nyplug_*_abi_version()` hard-fail on mismatch.
|
||||
|
||||
## Risks & Mitigations
|
||||
- ABI drift: minimal headers + version checks.
|
||||
- Linking complexity: start with the smallest set (Array/Print/GC-minimal), expand gradually.
|
||||
- Performance: keep RO-first; benchmark and fall back to HostCall if needed.
|
||||
- Windows linkage: prioritize Linux/macOS, then handle Win specifics in a follow-up task.
|
||||
- JIT coverage: adopt staged lowering (NewBox→birth, Print/Debug no-op) to clear blockers; retain strict skip policy otherwise.
|
||||
|
||||
## References
|
||||
- `c_abi_unified_design.md`
|
||||
- `implementation_steps.md`
|
||||
- `../phase-10.5/` (Python integration)
|
||||
|
||||
---
|
||||
|
||||
Everything is Plugin → unified paths for JIT and AOT.
|
||||
@ -1,29 +0,0 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
# Phase 10.1a - 計画と設計
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
PythonParserBoxの全体計画を理解し、実装の方向性を把握する。
|
||||
|
||||
## 📁 含まれるファイル
|
||||
- **`pythonparser_integrated_plan_summary.txt`** - 統合実装計画(最重要)
|
||||
- **`expert_feedback_gemini_codex.txt`** - Gemini先生とCodex先生の技術評価
|
||||
- **`archive/`** - 初期検討資料
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] 統合計画を読んで理解
|
||||
- [ ] エキスパートフィードバックを確認
|
||||
- [ ] 5つの核心戦略を把握
|
||||
- 関数単位フォールバック
|
||||
- Python 3.11固定
|
||||
- 意味論の正確な実装優先
|
||||
- GIL管理の最小化
|
||||
- テレメトリー重視
|
||||
|
||||
## 📝 重要ポイント
|
||||
- **Differential Testing戦略** - 世界中のPythonコードがテストケースに
|
||||
- **段階的実装** - 完璧を求めず動くものから
|
||||
- **成功の測定基準** - カバレッジ率70%以上、性能向上2-10倍
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1b (環境設定)
|
||||
@ -1,138 +0,0 @@
|
||||
# ChatGPT5の革命的アイデア - 多言語統合とBox化
|
||||
|
||||
## 元の発想
|
||||
|
||||
ChatGPT5さんの発想は「すべての言語をBoxで包んで統一的に扱う」という革命的なアプローチです。
|
||||
これにより、Python、Rust、JavaScript、Java等の既存エコシステムをNyashから自然に利用できるようになります。
|
||||
|
||||
## 核心概念
|
||||
|
||||
### 1. ForeignBox - 外部リソースのBox化
|
||||
```nyash
|
||||
// 外部言語のオブジェクトをBoxとして扱う
|
||||
box ForeignBox<T> {
|
||||
private { handle } // 外部リソースへのハンドル
|
||||
|
||||
fini() {
|
||||
ny_host_finalizer(me.handle) // 適切にリソース解放
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. ProxyBox - スレッドセーフな委譲
|
||||
```nyash
|
||||
// GILやイベントループを持つ言語用
|
||||
box ProxyBox<T> {
|
||||
private { bus, worker_id } // Bus経由で別スレッドに委譲
|
||||
|
||||
call(method, args) {
|
||||
return me.bus.send_and_wait(me.worker_id, method, args)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 言語別統合戦略(ChatGPT5原案)
|
||||
|
||||
### Python統合
|
||||
- **課題**: GIL(Global Interpreter Lock)
|
||||
- **解決**: ProxyBoxでBus経由ワーカー委譲
|
||||
- **実装**: CPython C-APIで`PyObject*`をForeignBoxに入れる
|
||||
|
||||
### JavaScript/Node.js統合
|
||||
- **課題**: イベントループを壊さない
|
||||
- **解決**: ProxyBox(postMessage/uv_queue_work)
|
||||
- **短い同期関数**: ForeignBoxでも可
|
||||
|
||||
### Rust/C統合
|
||||
- **最短パス**: C-ABI直接
|
||||
- **Rust側**: `#[no_mangle] extern "C"`
|
||||
- **所有権**: Nyash↔Rustのどちらかに寄せる(二重所有禁止)
|
||||
|
||||
### JVM/.NET統合
|
||||
- **方式**: JNI/P-Invoke
|
||||
- **要件**: Pinning必要
|
||||
- **GC連携**: SafeHandle/PhantomReferenceでFinalizer橋渡し
|
||||
|
||||
### WASM統合
|
||||
- **方式**: `ny_host_*`をimport
|
||||
- **データ**: リニアメモリへBytes/Strで搬送
|
||||
|
||||
## 統一インターフェース設計
|
||||
|
||||
### NyIDL(Nyash Interface Definition Language)
|
||||
```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
|
||||
}
|
||||
```
|
||||
|
||||
### 自動生成される要素
|
||||
1. Nyash側extern宣言
|
||||
2. C-ABIシム層
|
||||
3. 各言語用スタブ(Rust/Node/Python/JVM)
|
||||
4. ForeignBox/ProxyBoxラッパー
|
||||
|
||||
## 所有権と寿命管理
|
||||
|
||||
### One Strong Owner原則
|
||||
- ForeignBoxは所有者1本(NyashまたはA外部)
|
||||
- 弱参照は`weak/look`で管理
|
||||
- 失効時はnull/false
|
||||
|
||||
### Finalizerの橋渡し
|
||||
1. Nyash `fini` → `ny_host_finalizer`呼び出し
|
||||
2. 外部GC/finalize → `ny_host_finalizer`経由でNyashのweakを失効
|
||||
|
||||
## 効果システムとの統合
|
||||
|
||||
```nyash
|
||||
// 効果注釈でFFI境界の振る舞いを明示
|
||||
extern fn py_numpy_matmul(a: ForeignBox<ndarray>, b: ForeignBox<ndarray>)
|
||||
-> ForeignBox<ndarray> effects mut
|
||||
|
||||
extern fn rust_image_load(path: str)
|
||||
-> ForeignBox<Image> effects io
|
||||
|
||||
extern fn js_fetch(url: str)
|
||||
-> ProxyBox<Promise> effects io
|
||||
```
|
||||
|
||||
## MIRレベルでの統合
|
||||
|
||||
### BoxCall命令の拡張
|
||||
```
|
||||
// 通常のBoxCall
|
||||
BoxCall(%result, %box, "method", [%arg1, %arg2])
|
||||
|
||||
// ForeignBoxのメソッド呼び出し
|
||||
BoxCall(%result, %foreign_box, "py_method", [%arg1])
|
||||
// → 内部でFFI境界を越えて呼び出し
|
||||
|
||||
// ProxyBoxの非同期呼び出し
|
||||
Send(%msg_id, %proxy_box, "method", [%args])
|
||||
Recv(%result, %msg_id)
|
||||
```
|
||||
|
||||
## 革命的な利点
|
||||
|
||||
1. **即座の多言語資産活用**: 既存ライブラリを「箱に詰めて」即Nyashで使える
|
||||
2. **統一的な寿命管理**: 強1+weak/look+finiで外部リソースも確定的に回収
|
||||
3. **配布の柔軟性**: WASM/VM/ネイティブのどれでも同じIDLから出荷
|
||||
4. **MIR最適化の恩恵**: 外部言語呼び出しもMIRレベルで最適化可能
|
||||
5. **段階的移行**: 既存プロジェクトを徐々にNyashに移行
|
||||
|
||||
## 実装優先順位
|
||||
|
||||
1. **Phase 1**: C/Rust統合(最も単純)
|
||||
2. **Phase 2**: Python統合(PythonParserBox)
|
||||
3. **Phase 3**: JavaScript/Node.js統合
|
||||
4. **Phase 4**: JVM/.NET統合
|
||||
5. **Phase 5**: 統一IDLと自動生成ツール
|
||||
|
||||
## まとめ
|
||||
|
||||
「すべてをBoxに閉じ込める」という設計を正式化することで、あらゆる言語→NyashとNyash→あらゆる実行系が綺麗に繋がる。
|
||||
これはまさに「Everything is Box」哲学の究極の実現形態といえる。
|
||||
@ -1,207 +0,0 @@
|
||||
# PythonParserBox設計提案 - CPythonパーサーを使ったPython→Nyash変換
|
||||
|
||||
## 概要
|
||||
CPythonの公式パーサーを活用して、PythonコードをNyashで直接実行可能にする革命的なアプローチ。
|
||||
PythonコードをNyashのAST/MIRに変換し、Nyashの最適化・JITコンパイルの恩恵を受けられるようにする。
|
||||
|
||||
## アーキテクチャ
|
||||
|
||||
### 1. PythonParserBox(ビルトインBox)
|
||||
```nyash
|
||||
// 使用例
|
||||
local py_parser = new PythonParserBox()
|
||||
|
||||
// Pythonコードを直接パース
|
||||
local ast = py_parser.parse("""
|
||||
def calculate(x, y):
|
||||
return x * 2 + y
|
||||
|
||||
result = calculate(10, 5)
|
||||
""")
|
||||
|
||||
// NyashのASTに変換
|
||||
local nyash_ast = py_parser.to_nyash_ast(ast)
|
||||
|
||||
// 直接実行も可能
|
||||
local result = py_parser.run(python_code)
|
||||
```
|
||||
|
||||
### 2. 実装構造
|
||||
```rust
|
||||
pub struct PythonParserBox {
|
||||
base: BoxBase,
|
||||
parser: CPythonParser, // CPythonの公式パーサー使用
|
||||
}
|
||||
|
||||
impl PythonParserBox {
|
||||
// Python → Python AST
|
||||
pub fn parse(&self, code: &str) -> Box<dyn NyashBox> {
|
||||
let py_ast = self.parser.parse_string(code);
|
||||
Box::new(PythonAstBox { ast: py_ast })
|
||||
}
|
||||
|
||||
// Python AST → Nyash AST
|
||||
pub fn to_nyash_ast(&self, py_ast: &PythonAstBox) -> Box<dyn NyashBox> {
|
||||
let converter = AstConverter::new();
|
||||
converter.convert_python_to_nyash(py_ast)
|
||||
}
|
||||
|
||||
// Python AST → MIR(直接変換)
|
||||
pub fn to_mir(&self, py_ast: &PythonAstBox) -> MirModule {
|
||||
let mut builder = MirBuilder::new();
|
||||
for func in py_ast.functions() {
|
||||
self.convert_function_to_mir(&mut builder, func);
|
||||
}
|
||||
builder.build()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## AST変換マッピング
|
||||
|
||||
### Python → Nyash対応表
|
||||
| Python AST | Nyash AST | 説明 |
|
||||
|------------|-----------|------|
|
||||
| FunctionDef | FunctionDecl | 関数定義 |
|
||||
| BinOp | BinaryOp | 二項演算 |
|
||||
| Call | MethodCall | 関数呼び出し |
|
||||
| Assign | Assignment | 代入 |
|
||||
| If | IfStatement | 条件分岐 |
|
||||
| While/For | LoopStatement | ループ |
|
||||
| Return | ReturnStatement | return文 |
|
||||
| Import | NewBox/LoadPlugin | import → Box化 |
|
||||
|
||||
### 型変換戦略
|
||||
```rust
|
||||
// Python動的型 → Nyash Box
|
||||
match py_value {
|
||||
PyInt(n) => IntegerBox::new(n),
|
||||
PyFloat(f) => FloatBox::new(f),
|
||||
PyStr(s) => StringBox::new(s),
|
||||
PyList(items) => ArrayBox::from_iter(items),
|
||||
PyDict(map) => MapBox::from_iter(map),
|
||||
PyObject(obj) => PythonObjectBox::new(obj), // 変換不能な場合
|
||||
}
|
||||
```
|
||||
|
||||
## MIR生成例
|
||||
|
||||
### Pythonコード
|
||||
```python
|
||||
def calculate(x, y):
|
||||
return x * 2 + y
|
||||
```
|
||||
|
||||
### 生成されるMIR
|
||||
```
|
||||
function calculate(%x, %y) {
|
||||
Load(%1, %x)
|
||||
Const(%2, 2)
|
||||
BinOp(%3, Mul, %1, %2)
|
||||
Load(%4, %y)
|
||||
BinOp(%5, Add, %3, %4)
|
||||
Return(%5)
|
||||
}
|
||||
```
|
||||
|
||||
## 利点
|
||||
|
||||
1. **完全な互換性**: CPython公式パーサーで100%正確なパース
|
||||
2. **統一最適化**: PythonコードもNyashのMIR最適化パイプラインを通る
|
||||
3. **JIT/AOTコンパイル**: PythonコードをネイティブコードにJIT/AOTコンパイル可能
|
||||
4. **段階的移行**: 既存Pythonコードを徐々にNyashに移行
|
||||
5. **デバッグ統一**: Nyashのデバッグツールでpythonコードもデバッグ可能
|
||||
|
||||
## 実装フェーズ
|
||||
|
||||
### Phase 1: 基本パーサー統合
|
||||
- CPythonパーサーのFFIバインディング
|
||||
- parse()メソッドでPython ASTを取得
|
||||
- AST可視化(dump_ast)
|
||||
|
||||
### Phase 2: AST変換
|
||||
- Python AST → Nyash AST変換器
|
||||
- 基本的な文法要素のサポート
|
||||
- 型変換システム
|
||||
|
||||
### Phase 3: MIR直接生成
|
||||
- Python AST → MIR変換
|
||||
- Python特有の最適化(動的型推論等)
|
||||
- ベンチマーク
|
||||
|
||||
### Phase 4: エコシステム統合
|
||||
- NumPy等の主要ライブラリサポート
|
||||
- Python例外 → Nyashエラー変換
|
||||
- async/await対応
|
||||
- GIL管理の自動化
|
||||
|
||||
## 技術的課題と解決策
|
||||
|
||||
### 1. GIL(Global Interpreter Lock)
|
||||
- 解決策: PythonコードはGILスコープ内で実行
|
||||
- 将来: MIR変換後はGILフリーで実行可能
|
||||
|
||||
### 2. Python動的型とNyash Box型のマッピング
|
||||
- 解決策: 実行時型情報を保持するPythonObjectBox
|
||||
- 最適化: よく使う型(int, str等)は専用Boxに変換
|
||||
|
||||
### 3. Pythonモジュールシステム
|
||||
- 解決策: importをNyashのプラグインロードにマッピング
|
||||
- pip packages → Nyashプラグインとして扱う
|
||||
|
||||
## 実用例
|
||||
|
||||
### 機械学習コードの実行
|
||||
```nyash
|
||||
local ml_code = """
|
||||
import numpy as np
|
||||
from sklearn.linear_model import LinearRegression
|
||||
|
||||
# データ準備
|
||||
X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
|
||||
y = np.dot(X, np.array([1, 2])) + 3
|
||||
|
||||
# モデル訓練
|
||||
model = LinearRegression()
|
||||
model.fit(X, y)
|
||||
|
||||
# 予測
|
||||
predictions = model.predict(np.array([[3, 5]]))
|
||||
print(f'Prediction: {predictions[0]}')
|
||||
"""
|
||||
|
||||
local py_parser = new PythonParserBox()
|
||||
local result = py_parser.run(ml_code)
|
||||
```
|
||||
|
||||
### Webアプリケーション
|
||||
```nyash
|
||||
local flask_app = """
|
||||
from flask import Flask, jsonify
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/api/hello/<name>')
|
||||
def hello(name):
|
||||
return jsonify({'message': f'Hello, {name}!'})
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(port=5000)
|
||||
"""
|
||||
|
||||
local py_parser = new PythonParserBox()
|
||||
py_parser.run(flask_app) // FlaskアプリがNyash内で起動
|
||||
```
|
||||
|
||||
## 期待される効果
|
||||
|
||||
1. **パフォーマンス向上**: PythonコードがJITコンパイルされ高速化
|
||||
2. **メモリ効率**: NyashのGC/メモリ管理を活用
|
||||
3. **相互運用性**: Python↔Nyash↔Rust↔JS等の自由な組み合わせ
|
||||
4. **開発効率**: 既存Pythonライブラリをそのまま使える
|
||||
5. **将来性**: PythonコードをネイティブAOTコンパイル可能
|
||||
|
||||
## まとめ
|
||||
|
||||
PythonParserBoxは、Pythonの豊富なエコシステムとNyashの高性能実行エンジンを組み合わせる画期的なアプローチ。
|
||||
CPythonパーサーの信頼性とNyashのMIR/JIT最適化により、Pythonコードをより高速に、より効率的に実行できる。
|
||||
@ -1,98 +0,0 @@
|
||||
# 2025-08-27 議論まとめ - PythonParserBoxと言語間統合
|
||||
|
||||
## 本日の議論の流れ
|
||||
|
||||
### 1. ベンチマーク実行と問題発見
|
||||
- インタープリター性能問題(10万回ループで2分以上)
|
||||
- VM変数管理エラー
|
||||
- Box APIの成熟度不足(TimeBox.elapsed()が呼べない)
|
||||
- 問題点をPhase 10ドキュメントに追記
|
||||
|
||||
### 2. Cranelift AOT Backendの追加(Phase 10.9)
|
||||
- JIT実装の基盤を再利用して事前コンパイル可能
|
||||
- 非同期完全サポート(WASMの制限なし)
|
||||
- 実装期間2-3週間で可能(上乗せだけ)
|
||||
|
||||
### 3. PythonParserBox構想の深堀り
|
||||
- ChatGPT5さんの「CPythonをBoxで包みMIRに落とし込む」アイデアを具体化
|
||||
- CPythonの公式パーサーを使ってPythonコード→Nyash AST/MIR変換
|
||||
- ビルトインBoxとして分離実装
|
||||
|
||||
### 4. エキスパートへの相談結果
|
||||
|
||||
#### Gemini先生の分析
|
||||
- pyo3活用で技術的課題は解決可能
|
||||
- 最初は特定ドメインのサブセットから開始すべき
|
||||
- GIL管理のBox隠蔽は現実的
|
||||
- 設計思想は他言語(Ruby/JS)にも応用可能
|
||||
|
||||
#### Codex先生の実装提案
|
||||
- CPython内部APIではなく、安定した`ast`モジュール経由
|
||||
- Python側で`ast.parse()` → JSON → Rust側で処理
|
||||
- 最小実装セット定義(基本構造+演算+制御フロー)
|
||||
- 純Pythonループで2-10倍の高速化が現実的
|
||||
|
||||
### 5. Phase 10.1フォルダの作成と整理
|
||||
以下のドキュメントをPhase 10.1に整理:
|
||||
- python_parser_box_design.txt(基本設計)
|
||||
- python_parser_box_implementation_plan.txt(実装計画)
|
||||
- chatgpt5_original_idea.txt(元のアイデア)
|
||||
- summary_2025_08_27.txt(本まとめ)
|
||||
|
||||
## 技術的な要点
|
||||
|
||||
### 実装アプローチ
|
||||
```rust
|
||||
// pyo3でCPythonを埋め込み
|
||||
pyo3 = { version = "0.22", features = ["auto-initialize"] }
|
||||
|
||||
// Python側でAST→JSON変換
|
||||
def parse_to_json(code):
|
||||
tree = ast.parse(code)
|
||||
return json.dumps(ast_to_dict(tree))
|
||||
|
||||
// Rust側で受け取り
|
||||
let json_ast = py_helper.parse_to_json(python_code);
|
||||
let nyash_ast = convert_json_to_nyash_ast(json_ast);
|
||||
```
|
||||
|
||||
### 最小実装セット(Phase 1-2)
|
||||
- 構造: Module, FunctionDef, Return, Assign
|
||||
- 演算: BinOp, Compare, Call, Name, Constant
|
||||
- 制御: If, While, Br, CondBr
|
||||
- 実行: 最初はCPython exec委譲、段階的にMIR実行へ
|
||||
|
||||
### データ共有戦略
|
||||
- NumPy配列: pyo3-numpyでゼロコピー共有
|
||||
- NdArrayBox: Nyash側でNumPy配列を効率的に扱う
|
||||
- バッファプロトコル: PEP 3118で汎用オブジェクト共有
|
||||
|
||||
### 期待される効果
|
||||
- 純Pythonループ: 2-10倍高速化
|
||||
- NumPy処理: 1.0-1.2倍(既に最適化済み)
|
||||
- 将来的: トレースベース最適化で10-30倍も可能
|
||||
|
||||
## 次のステップ
|
||||
|
||||
1. **Phase 1実装開始**(1-2週間)
|
||||
- pyo3統合とPythonParserBox基本実装
|
||||
- parse_to_jsonヘルパー作成
|
||||
- 最小AST変換動作確認
|
||||
|
||||
2. **小規模ベンチマーク**
|
||||
- 簡単なPython関数で動作確認
|
||||
- 性能測定と改善点洗い出し
|
||||
|
||||
3. **段階的拡張**
|
||||
- MIR変換実装
|
||||
- NumPy統合
|
||||
- より複雑なPython機能対応
|
||||
|
||||
## まとめ
|
||||
|
||||
PythonParserBoxは、Nyashの「Everything is Box」哲学を言語間統合に拡張する革命的なアプローチ。
|
||||
CPythonパーサーの信頼性とNyashのMIR/JIT最適化を組み合わせることで、Pythonエコシステムを
|
||||
Nyashから自然に利用でき、かつ高速化も実現できる。
|
||||
|
||||
ChatGPT5さんの最初のアイデア(ForeignBox/ProxyBox)を基に、具体的な実装計画まで落とし込めた。
|
||||
技術的にも実現可能で、段階的なアプローチにより着実に実装できる見込み。
|
||||
@ -1,197 +0,0 @@
|
||||
# PythonParserBox実装計画 - エキスパートフィードバック
|
||||
日付: 2025-08-27
|
||||
|
||||
## Gemini先生のフィードバック
|
||||
|
||||
### 総評
|
||||
これは非常に野心的で、言語の成熟度を飛躍的に高める可能性を秘めた素晴らしい計画です。Nyashの「Everything is a Box」哲学とPythonエコシステムを融合させるという着眼点に大変興奮しました。
|
||||
|
||||
### 1. 実装計画は技術的に健全か?落とし穴は?
|
||||
|
||||
**技術的健全性:**
|
||||
はい、計画は全体として技術的に非常に健全です。
|
||||
|
||||
* **CPythonパーサーの利用:** `pyo3`経由で`ast.parse()`を利用するのは、Python構文との互換性を100%保証するための最も確実で賢明なアプローチです。
|
||||
* **JSON中間表現(IR):** Python AST (Pythonメモリ空間) と Nyash AST (Rustメモリ空間) の間にJSONを挟むのは、言語間の境界を明確に分離する良い設計です。
|
||||
* **段階的実装とフォールバック:** 未実装機能を`exec()`にフォールバックする戦略は、実用性を保ちながら段階的に実装を進めるための極めて現実的なアプローチです。
|
||||
|
||||
**潜在的な落とし穴:**
|
||||
* **パフォーマンス:** `Python AST → JSON → Nyash AST → Nyash実行`というパイプラインは、特に初期段階では非常に低速になります。
|
||||
* **ASTの複雑性の爆発:** PythonのASTは非常に巨大で、言語バージョンの更新も速いです。
|
||||
* **標準ライブラリの壁:** Pythonの真の力は広範な標準/サードパーティライブラリにあります。`import`文をどう扱うかは最重要課題です。
|
||||
|
||||
### 2. Python AST → Nyash AST変換で注意すべき意味論の違いは?
|
||||
|
||||
* **型システム:** Pythonは動的型付け、Nyashは静的型付けまたはより厳格な型システムを持つと推測
|
||||
* **オブジェクトモデルと可変性:** Pythonのオブジェクトは基本的に可変(mutable)
|
||||
* **スコープとクロージャ:** Pythonの`global`や`nonlocal`の挙動は独特
|
||||
* **特殊メソッド (`__dunder__`):** Pythonの挙動は特殊メソッドで定義される
|
||||
* **組み込み関数:** `len()`, `print()`, `range()`などをどう扱うか
|
||||
|
||||
### 3. Nyashパーサーのバグ検証戦略として効果的か?
|
||||
|
||||
**非常に効果的です。** これは「Differential Testing(差分テスト)」と呼ばれる強力な手法です。
|
||||
* **巨大なテストスイート:** 事実上、世の中にある無数のPythonコードがNyashのテストケースになります。
|
||||
* **微妙なバグの発見:** 手書きの単体テストでは見逃しがちなセマンティクスのバグを発見するのに絶大な効果を発揮します。
|
||||
|
||||
### 4. pyo3統合でのGIL管理のベストプラクティスは?
|
||||
|
||||
* **基本原則:** Pythonオブジェクトに触れるコードは、必ずGILを獲得した状態で実行
|
||||
* **GILの必要期間を最小化する**
|
||||
* **`py.allow_threads`の活用:** 時間がかかり、かつPythonオブジェクトに触れない処理で使用
|
||||
|
||||
### 5. 段階的実装(Phase 1-4)の優先順位は適切か?
|
||||
|
||||
はい、提案されている優先順位は非常に適切です。
|
||||
1. Phase 1: 基本構文 + 変数束縛 + 基本的な式 + プリミティブ型
|
||||
2. Phase 2: list, dict, tuple
|
||||
3. Phase 3: 関数とスコープ
|
||||
4. Phase 4: モジュールとクラス
|
||||
|
||||
**最優先で並行すべきこと:** `exec()`へのフォールバック機構
|
||||
|
||||
### 6. 言語成熟度向上への貢献度をどう評価する?
|
||||
|
||||
**定量的指標:**
|
||||
* ライブラリ互換性カバレッジ
|
||||
* パフォーマンステスト
|
||||
* 発見バグ数
|
||||
|
||||
**定性的指標:**
|
||||
* 表現力の向上
|
||||
* 開発者体験
|
||||
* エコシステムのマイルストーン
|
||||
|
||||
### 結論
|
||||
|
||||
この`PythonParserBox`計画は、単なる機能追加ではなく、**Nyash言語のテスト、デバッグ、そしてエコシステム獲得を同時に加速させる、極めて戦略的な一手**です。
|
||||
|
||||
---
|
||||
|
||||
## Codex先生のフィードバック
|
||||
|
||||
### Overall Verdict
|
||||
- Sound approach: Using CPython's parser via pyo3, lowering via a JSON IR, and gradually replacing exec() with Nyash MIR/JIT is feasible and strategically strong.
|
||||
- Biggest risks: Semantic mismatches at statement/expression boundaries, version skew of Python AST, and boundary-costs between CPython and Nyash during phased rollout.
|
||||
|
||||
### Architectural Pitfalls
|
||||
- **Python version skew:** `ast` schema changes across minors. Pin and encode `py_version` + `ast_format` in the JSON.
|
||||
- **AST stability vs syntax fidelity:** `ast` loses comments and some token distinctions
|
||||
- **Boundary granularity:** Whole-file fallback wastes partial coverage; per-node fallback is unsafe. **The practical unit is per-function.**
|
||||
- **Import system and environment:** Python imports pull arbitrary code
|
||||
- **Error mapping:** Propagate Python exceptions with full traceback
|
||||
- **Performance overhead:** Python AST→JSON→Nyash→MIR is heavy
|
||||
- **Object model mismatch:** Identity (`is`), mutability, truthiness, numeric tower
|
||||
- **Concurrency:** GIL limits parallel parse/exec
|
||||
|
||||
### AST→Nyash Semantics: High-Risk Differences
|
||||
- **Names and scope:**
|
||||
- LEGB resolution; `global`/`nonlocal` behavior; closures and cell variables
|
||||
- Comprehension scopes (separate scope in Python 3)
|
||||
- **Control flow:**
|
||||
- `for` iterates via iterator protocol; `for/else`, `while/else` semantics
|
||||
- Short-circuit truthiness uses Python rules; `__bool__` then `__len__`
|
||||
- **Functions:**
|
||||
- Defaults evaluated at definition time; `*args/**kwargs`
|
||||
- Decorators transform functions at definition time
|
||||
- **Operators and numbers:**
|
||||
- `/` true division; `//` floor division; big integers by default
|
||||
- Operator dispatch via dunder methods; `is` vs `==`
|
||||
|
||||
For Phase 1, the must-haves are: LEGB + locals/freevars, default args timing, iterator-based `for`, `for/else` + `while/else`, Python truthiness and short-circuiting.
|
||||
|
||||
### Fallback Strategy
|
||||
- **Fallback unit: Per-function.** If a function body contains unsupported nodes, compile a "PyThunk" that calls into CPython.
|
||||
- **Boundary types:** Define canonical bridges: `PyAnyBox` in Nyash wrapping `Py<PyAny>`
|
||||
- **Imports and globals:** Execute module top-level in Python; then selectively replace functions
|
||||
|
||||
### pyo3/GIL Best Practices
|
||||
- **Initialization:** Call `pyo3::prepare_freethreaded_python()` once
|
||||
- **GIL usage:**
|
||||
- Use `Python::with_gil(|py| { ... })` for all Python calls
|
||||
- Minimize time under GIL; copy data out promptly
|
||||
- For heavy Rust work, drop GIL: `py.allow_threads(|| { ... })`
|
||||
- **Data transfer:** Prefer building JSON on the Python side
|
||||
- **Versioning:** Pin Python minor version; embed version string in the IR
|
||||
|
||||
### Phasing and Priorities (Refined)
|
||||
- **Phase 1 (Parser + Minimal Semantics):**
|
||||
- Python→JSON exporter with location info
|
||||
- Nyash IR for expressions and basic statements
|
||||
- Semantics fidelity for: iterator protocol, truthiness, scoping
|
||||
- **Fallback per-function for anything else**
|
||||
- **Phase 2-4:** Coverage expansion → Objects/Runtime → MIR/JIT
|
||||
|
||||
### Parser Bug Validation Strategy
|
||||
- **Differential execution:** Curate pairs of semantically equivalent snippets
|
||||
- **Oracle testing:** Run CPython as oracle and compare
|
||||
- **Fuzzing:** Grammar-based fuzzers
|
||||
- **Coverage and gating:** Track node-kind coverage
|
||||
|
||||
### IR/JSON Design Tips
|
||||
- Include: `node_type`, children, `lineno/col_offset`, `py_version`, `ast_format`, `support_level`
|
||||
- Canonicalize: normalize forms, operator names
|
||||
- Determinism: maintain stable field ordering
|
||||
|
||||
### Concrete Recommendations
|
||||
- **Pin to one Python minor (e.g., 3.11 or 3.12)**
|
||||
- **Choose per-function fallback as the core boundary**
|
||||
- **Implement Python truthiness, iterator protocol, and scoping correctly before optimizing**
|
||||
- **Keep the GIL minimal: build the JSON in Python; parse in Rust**
|
||||
- **Telemetry from day one: log unsupported node kinds and fallback counts**
|
||||
- **Start with JSON; plan migration to a compact binary once stable**
|
||||
|
||||
---
|
||||
|
||||
## 統合された重要ポイント
|
||||
|
||||
### 🎯 両エキスパートが一致した最重要事項
|
||||
|
||||
1. **関数単位のフォールバック戦略**
|
||||
- ファイル全体でなく関数レベルでコンパイル/フォールバックを切り替え
|
||||
- 未対応機能を含む関数はCPython exec、対応済み関数はNyash MIR/JIT
|
||||
|
||||
2. **Python バージョン固定**
|
||||
- Python 3.11または3.12に固定
|
||||
- AST安定性の確保とバージョン間の差異回避
|
||||
|
||||
3. **意味論の正確な実装が最優先**
|
||||
- 最適化より先にPython互換性を確保
|
||||
- 特に: イテレータプロトコル、真偽値判定、スコーピング規則
|
||||
|
||||
4. **GIL管理の最小化**
|
||||
- Python側でJSON生成、Rust側で解析
|
||||
- 重い処理はGIL外で実行
|
||||
|
||||
5. **テレメトリーの重要性**
|
||||
- 未対応ノードの記録
|
||||
- フォールバック率の計測
|
||||
- 実行時の統計情報収集
|
||||
|
||||
### 🚨 特に注意すべき意味論の違い
|
||||
|
||||
1. **制御フロー**
|
||||
- for/else, while/else の独特な挙動
|
||||
- forループのイテレータプロトコル
|
||||
|
||||
2. **スコープ規則**
|
||||
- LEGB(Local, Enclosing, Global, Builtins)
|
||||
- global/nonlocal宣言
|
||||
- 内包表記の独立スコープ(Python 3)
|
||||
|
||||
3. **数値演算**
|
||||
- / (true division) vs // (floor division)
|
||||
- デフォルトで大整数
|
||||
- NaN の扱い
|
||||
|
||||
4. **関数定義**
|
||||
- デフォルト引数は定義時に評価
|
||||
- *args/**kwargs の扱い
|
||||
- デコレータの実行順序
|
||||
|
||||
### 📊 成功の測定指標
|
||||
|
||||
1. **カバレッジ**: コンパイル済み vs フォールバック関数の比率
|
||||
2. **性能向上**: 数値計算ベンチマークでの改善率
|
||||
3. **バグ発見数**: Differential Testingで発見されたバグ数
|
||||
4. **エコシステム**: 動作する有名Pythonライブラリの数
|
||||
@ -1,148 +0,0 @@
|
||||
# PythonParserBox統合実装計画 - エキスパート評価後の最終版
|
||||
作成日: 2025-08-27
|
||||
|
||||
## 🎯 革命的な3つの価値
|
||||
|
||||
### 1. Pythonエコシステムの即座活用
|
||||
- 既存のPythonライブラリをNyashから直接利用可能
|
||||
- 段階的な移行パスの提供
|
||||
|
||||
### 2. Nyashパーサーのバグ自動検証(Differential Testing)
|
||||
- **世界中のPythonコードがNyashのテストケースに!**
|
||||
- CPythonをオラクルとして使用、出力・戻り値・例外を自動比較
|
||||
- 微妙なセマンティクスバグを大量に発見可能
|
||||
|
||||
### 3. 言語成熟度の飛躍的向上
|
||||
- 実用的なPythonコードでNyashをストレステスト
|
||||
- 発見されたバグ数が成熟度向上の定量的指標
|
||||
|
||||
## 🏆 エキスパート評価サマリー
|
||||
|
||||
### Gemini先生の評価
|
||||
**「非常に野心的で、言語の成熟度を飛躍的に高める可能性を秘めた素晴らしい計画」**
|
||||
|
||||
- 技術的に健全なアプローチ
|
||||
- pyo3経由のCPythonパーサー利用は最も確実
|
||||
- Differential Testingは極めて強力な手法
|
||||
|
||||
### Codex先生の評価
|
||||
**「Sound approach with strategic strength」**
|
||||
|
||||
- 関数単位フォールバックが実用的かつ効果的
|
||||
- Python 3.11固定でAST安定性確保
|
||||
- テレメトリー重視で継続的改善可能
|
||||
|
||||
## 🔑 統合された5つの核心戦略
|
||||
|
||||
### 1. 関数単位フォールバック(両エキスパート一致)
|
||||
```python
|
||||
def supported_function(): # → Nyash MIR/JIT
|
||||
return x + y
|
||||
|
||||
def unsupported_function(): # → CPython exec
|
||||
yield from generator # Phase 1では未対応
|
||||
```
|
||||
|
||||
### 2. Python 3.11固定
|
||||
- AST安定性確保(3.8 Constant統一、3.10 match/case、3.12位置情報)
|
||||
- `py_version`と`ast_format`をJSON IRに埋め込む
|
||||
|
||||
### 3. 意味論の正確な実装優先
|
||||
Phase 1必須要素(Codex先生強調):
|
||||
- LEGB + locals/freevars(スコーピング)
|
||||
- デフォルト引数の評価タイミング(定義時)
|
||||
- イテレータベースのfor文
|
||||
- for/else + while/else(Python独特)
|
||||
- Python真偽値判定(`__bool__` → `__len__`)
|
||||
- 短絡評価(and/or)
|
||||
|
||||
### 4. GIL管理の最小化
|
||||
```rust
|
||||
// GILは最小限に!
|
||||
let json_ast = Python::with_gil(|py| {
|
||||
py_helper.parse_to_json(py, code) // Python側でJSON生成
|
||||
})?;
|
||||
|
||||
// GIL外でRust処理
|
||||
let nyash_ast = py.allow_threads(|| {
|
||||
convert_json_to_nyash(json_ast)
|
||||
});
|
||||
```
|
||||
|
||||
### 5. テレメトリー基盤
|
||||
```bash
|
||||
[PythonParser] Module: example.py (Python 3.11)
|
||||
Functions: 10 total
|
||||
Compiled: 7 (70%)
|
||||
Fallback: 3 (30%)
|
||||
- async_function: unsupported node 'AsyncFunctionDef' at line 23
|
||||
```
|
||||
|
||||
## 📋 実装フェーズ(詳細版)
|
||||
|
||||
### Phase 0: 準備(1週間)
|
||||
- [ ] Python 3.11.9環境固定
|
||||
- [ ] テレメトリー基盤構築
|
||||
- [ ] Differential Testingフレームワーク
|
||||
- [ ] JSON IR仕様策定
|
||||
|
||||
### Phase 1: Core Subset(2週間)
|
||||
- [ ] pyo3統合(prepare_freethreaded_python)
|
||||
- [ ] 関数単位コンパイル判定器
|
||||
- [ ] 基本構文(def/if/for/while/return)
|
||||
- [ ] 意味論必須要素の実装
|
||||
- [ ] CPythonとの出力比較テスト
|
||||
|
||||
### Phase 2: Data Model(3週間)
|
||||
- [ ] 特殊メソッドマッピング
|
||||
- [ ] list/dict/tuple実装
|
||||
- [ ] 演算子オーバーロード
|
||||
|
||||
### Phase 3: Advanced Features(1ヶ月)
|
||||
- [ ] 例外処理(try/except)
|
||||
- [ ] with文、ジェネレータ
|
||||
- [ ] 内包表記、デコレータ
|
||||
|
||||
## 📊 成功の測定基準
|
||||
|
||||
### 定量的指標
|
||||
| 指標 | 目標 | 測定方法 |
|
||||
|------|------|----------|
|
||||
| カバレッジ率 | 70%以上 | コンパイル済み vs フォールバック関数 |
|
||||
| 性能向上 | 2-10倍 | 純Pythonループのベンチマーク |
|
||||
| バグ発見数 | 10+件/Phase | Differential Testing |
|
||||
| エコシステム | 1以上 | 動作する有名ライブラリ数 |
|
||||
|
||||
### マイルストーン
|
||||
- Phase 1: "Hello from Python in Nyash"が動作
|
||||
- Phase 2: scikit-learnの基本アルゴリズムが動作
|
||||
- Phase 3: FlaskのHello Worldが動作
|
||||
- Phase 4: PyPIトップ100の30%が基本動作
|
||||
|
||||
## 🚨 注意すべき意味論の違い(トップ5)
|
||||
|
||||
1. **制御フロー**: for/else, while/else
|
||||
2. **スコープ規則**: LEGB、global/nonlocal
|
||||
3. **数値演算**: / (true division) vs //
|
||||
4. **関数定義**: デフォルト引数は定義時評価
|
||||
5. **真偽値判定**: Pythonの__bool__/__len__ルール
|
||||
|
||||
## 🎉 期待されるインパクト
|
||||
|
||||
### 技術的成果
|
||||
- Pythonエコシステムの活用
|
||||
- Nyashパーサーの品質向上
|
||||
- 性能最適化の実証
|
||||
|
||||
### 戦略的価値
|
||||
- 言語成熟度の飛躍的向上
|
||||
- 開発者コミュニティの拡大
|
||||
- 実用アプリケーション開発の加速
|
||||
|
||||
## 📝 結論
|
||||
|
||||
PythonParserBoxは、単なる機能追加ではなく、**Nyash言語のテスト、デバッグ、エコシステム獲得を同時に加速させる極めて戦略的なプロジェクト**。
|
||||
|
||||
両エキスパートの技術的評価と具体的な実装指針により、実現可能性が確認され、明確な実装パスが定まった。
|
||||
|
||||
**「Everything is Box」哲学を、言語の壁を超えて実現する革命的な一歩。**
|
||||
@ -1,57 +0,0 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
# Phase 10.1b - 環境設定とセットアップ
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
PythonParserBox実装に必要な開発環境を整える。
|
||||
|
||||
## 📋 セットアップ手順
|
||||
|
||||
### 1. Python 3.11環境の固定
|
||||
```bash
|
||||
# pyenvを使用する場合
|
||||
pyenv install 3.11.9
|
||||
pyenv local 3.11.9
|
||||
|
||||
# または直接指定
|
||||
python3.11 --version # 3.11.9であることを確認
|
||||
```
|
||||
|
||||
### 2. Cargo.tomlへの依存関係追加
|
||||
```toml
|
||||
[dependencies]
|
||||
pyo3 = { version = "0.22", features = ["auto-initialize"] }
|
||||
pyo3-numpy = "0.22" # NumPy連携用(Phase 3で使用)
|
||||
serde_json = "1.0" # JSON中間表現用
|
||||
```
|
||||
|
||||
### 3. 環境変数の設定
|
||||
```bash
|
||||
# テレメトリー用
|
||||
export NYASH_PYTHONPARSER_TELEMETRY=1 # 基本統計
|
||||
export NYASH_PYTHONPARSER_TELEMETRY=2 # 詳細ログ
|
||||
export NYASH_PYTHONPARSER_STRICT=1 # フォールバック時にパニック(CI用)
|
||||
```
|
||||
|
||||
### 4. ディレクトリ構造の準備
|
||||
```
|
||||
src/boxes/python_parser_box/
|
||||
├── mod.rs # メインモジュール
|
||||
├── py_helper.rs # Python側ヘルパー
|
||||
├── converter.rs # AST変換器
|
||||
└── telemetry.rs # テレメトリー実装
|
||||
```
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] Python 3.11.9がインストールされている
|
||||
- [ ] Cargo.tomlに依存関係が追加されている
|
||||
- [ ] 開発ディレクトリ構造が準備されている
|
||||
- [ ] 環境変数の設定方法を理解している
|
||||
|
||||
## 🚨 注意事項
|
||||
- **Python 3.11固定必須** - AST安定性のため
|
||||
- **pyo3::prepare_freethreaded_python()** を一度だけ呼ぶ
|
||||
- GIL管理に注意(Phase 10.1cで詳細)
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1c (パーサー統合実装)
|
||||
@ -1,65 +0,0 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
Note: 本来は「PythonをNyashで動かすフェーズ(パーサー統合)」の位置づけでしたが、現在は順番を変更し、先に 10.5b(MIR→VM→ネイティブビルド基盤)を進めています。
|
||||
|
||||
# Phase 10.1c - パーサー統合実装
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
pyo3を使ってCPythonパーサーをNyashに統合し、Python AST → JSON → Nyash ASTの変換パイプラインを構築する。
|
||||
|
||||
## 📁 実装ドキュメント
|
||||
- **`python_parser_box_implementation_plan.txt`** - 技術的実装計画
|
||||
- **`builtin_box_implementation_flow.txt`** - ビルトインBox実装フロー
|
||||
|
||||
## 🔧 実装タスク
|
||||
|
||||
### 1. PythonParserBoxの基本構造
|
||||
```rust
|
||||
pub struct PythonParserBox {
|
||||
base: BoxBase,
|
||||
py_helper: Arc<Mutex<PyHelper>>,
|
||||
}
|
||||
```
|
||||
|
||||
### 2. GIL管理の実装
|
||||
```rust
|
||||
// ✅ 良い例:GILを最小限に
|
||||
let json_ast = Python::with_gil(|py| {
|
||||
py_helper.parse_to_json(py, code)
|
||||
})?;
|
||||
|
||||
// GIL外でRust処理
|
||||
let nyash_ast = py.allow_threads(|| {
|
||||
convert_json_to_nyash(json_ast)
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Python側ヘルパー実装
|
||||
- `ast.parse()` → JSON変換
|
||||
- 位置情報の保持(lineno, col_offset)
|
||||
- Python 3.11固定チェック
|
||||
|
||||
### 4. 関数単位フォールバック判定
|
||||
```rust
|
||||
pub fn can_compile(&self, func_def: &PythonAst) -> CompileResult {
|
||||
// サポートされているノードかチェック
|
||||
// CompileResult::Compile or CompileResult::Fallback
|
||||
}
|
||||
```
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] PythonParserBoxがビルトインBoxとして登録されている
|
||||
- [ ] `parse_to_json()` メソッドが動作する
|
||||
- [ ] GIL管理が適切に実装されている
|
||||
- [ ] テレメトリー基盤が組み込まれている
|
||||
- [ ] 簡単なPythonコードでJSON ASTが取得できる
|
||||
|
||||
## 🧪 動作確認
|
||||
```nyash
|
||||
local py = new PythonParserBox()
|
||||
local json_ast = py.parse_to_json("def hello(): return 'Hello'")
|
||||
print(json_ast) // JSON ASTが表示される
|
||||
```
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1d (Core実装)
|
||||
@ -1,553 +0,0 @@
|
||||
# PythonParserBox ビルトインBox実装フロー(エキスパート統合版)
|
||||
~CPythonパーサー統合とPhase 1実装の具体的な流れ~
|
||||
更新日: 2025-08-27
|
||||
|
||||
## 🎯 全体の実装フロー
|
||||
|
||||
### Step 0: Python 3.11固定(エキスパート推奨)
|
||||
```
|
||||
- Python 3.11.9を使用(AST安定性確保)
|
||||
- pyenvまたはpython3.11コマンドで固定
|
||||
- py_versionとast_formatをJSON IRに必ず含める
|
||||
```
|
||||
|
||||
### Step 1: ビルトインBoxとしての基盤作成
|
||||
```
|
||||
1. src/boxes/python_parser_box/mod.rs を作成
|
||||
2. BoxBase + BoxCore統一アーキテクチャに準拠
|
||||
3. PythonParserBoxの基本構造を定義
|
||||
4. src/boxes/mod.rs に登録
|
||||
5. テレメトリー基盤を初期から組み込む
|
||||
```
|
||||
|
||||
### Step 2: pyo3統合とCPythonパーサー接続
|
||||
```
|
||||
1. Cargo.tomlに pyo3依存関係追加
|
||||
2. pyo3::prepare_freethreaded_python()で一度だけ初期化
|
||||
3. ast.parse()へのFFIブリッジ実装
|
||||
4. JSON中間表現への変換(Python側でJSON生成)
|
||||
5. GILは最小限に、py.allow_threads()でRust処理
|
||||
```
|
||||
|
||||
### Step 3: Phase 1機能の実装(必須意味論要素)
|
||||
```
|
||||
必須要素(Codex先生強調):
|
||||
- LEGBスコーピング + locals/freevars
|
||||
- デフォルト引数の定義時評価
|
||||
- イテレータプロトコル(for文)
|
||||
- for/else + while/else
|
||||
- Python真偽値判定
|
||||
- 短絡評価(and/or)
|
||||
|
||||
実装手順:
|
||||
1. 関数単位フォールバック戦略の実装
|
||||
2. 基本的なAST変換(def, if, for, while, return)
|
||||
3. 式の変換(算術/比較/論理演算子、関数呼び出し)
|
||||
4. Nyash ASTへの意味論を保ったマッピング
|
||||
5. Differential Testingフレームワーク
|
||||
```
|
||||
|
||||
## 📝 具体的な実装コード
|
||||
|
||||
### 1. ビルトインBox定義(src/boxes/python_parser_box/mod.rs)
|
||||
```rust
|
||||
use crate::core::{BoxBase, BoxCore, NyashBox};
|
||||
use crate::ast;
|
||||
use pyo3::prelude::*;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub struct PythonParserBox {
|
||||
base: BoxBase,
|
||||
py_helper: Arc<Mutex<PyHelper>>, // Python実行環境
|
||||
}
|
||||
|
||||
impl BoxCore for PythonParserBox {
|
||||
fn box_id(&self) -> u64 {
|
||||
self.base.box_id()
|
||||
}
|
||||
|
||||
fn parent_type_id(&self) -> Option<std::any::TypeId> {
|
||||
self.base.parent_type_id()
|
||||
}
|
||||
|
||||
fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "PythonParserBox#{}", self.box_id())
|
||||
}
|
||||
}
|
||||
|
||||
impl NyashBox for PythonParserBox {
|
||||
fn type_name(&self) -> &'static str {
|
||||
"PythonParserBox"
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn NyashBox> {
|
||||
Box::new(PythonParserBox {
|
||||
base: BoxBase::new(),
|
||||
py_helper: self.py_helper.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. メソッド実装(Phase 1対応)
|
||||
```rust
|
||||
// テレメトリー用構造体
|
||||
#[derive(Default)]
|
||||
pub struct CompilationTelemetry {
|
||||
compiled_functions: Vec<String>,
|
||||
fallback_functions: Vec<(String, String, usize)>, // (name, reason, lineno)
|
||||
unsupported_nodes: HashMap<String, usize>, // node_type -> count
|
||||
}
|
||||
|
||||
impl PythonParserBox {
|
||||
// コンストラクタ
|
||||
pub fn new() -> Result<Self, String> {
|
||||
// 一度だけ初期化
|
||||
static INIT: std::sync::Once = std::sync::Once::new();
|
||||
INIT.call_once(|| {
|
||||
pyo3::prepare_freethreaded_python();
|
||||
});
|
||||
|
||||
// Python環境の初期化
|
||||
Python::with_gil(|py| {
|
||||
// Python 3.11確認
|
||||
let version = py.version_info();
|
||||
if version.major != 3 || version.minor != 11 {
|
||||
return Err(format!("Python 3.11 required, got {}.{}",
|
||||
version.major, version.minor));
|
||||
}
|
||||
|
||||
let helper = PyHelper::new(py)?;
|
||||
Ok(PythonParserBox {
|
||||
base: BoxBase::new(),
|
||||
py_helper: Arc::new(Mutex::new(helper)),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Python code → JSON AST
|
||||
pub fn parse_to_json(&self, code: &str) -> Result<String, String> {
|
||||
let helper = self.py_helper.lock().unwrap();
|
||||
Python::with_gil(|py| {
|
||||
helper.parse_to_json(py, code)
|
||||
})
|
||||
}
|
||||
|
||||
// JSON AST → Nyash AST(Phase 1機能のみ)
|
||||
pub fn json_to_nyash_ast(&self, json: &str) -> Result<ast::Program, String> {
|
||||
let py_ast: Phase1PythonAst = serde_json::from_str(json)
|
||||
.map_err(|e| format!("JSON parse error: {}", e))?;
|
||||
|
||||
let converter = Phase1Converter::new();
|
||||
converter.convert(py_ast)
|
||||
}
|
||||
|
||||
// 直接実行(関数単位フォールバック)
|
||||
pub fn run(&self, code: &str) -> Result<Box<dyn NyashBox>, String> {
|
||||
// まずJSON ASTを取得
|
||||
let json_ast = self.parse_to_json(code)?;
|
||||
let py_ast: serde_json::Value = serde_json::from_str(&json_ast)?;
|
||||
|
||||
// モジュール内の各関数をチェック
|
||||
let compiler = FunctionCompiler::new();
|
||||
let module_result = compiler.compile_module(&py_ast)?;
|
||||
|
||||
// テレメトリー出力(環境変数で制御)
|
||||
if std::env::var("NYASH_PYTHONPARSER_TELEMETRY").is_ok() {
|
||||
compiler.print_telemetry();
|
||||
}
|
||||
|
||||
// 実行(コンパイル済み関数はMIR、他はCPython)
|
||||
module_result.execute()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Python側ヘルパー実装
|
||||
```rust
|
||||
// Pythonコードを文字列として埋め込み
|
||||
const PYTHON_HELPER_CODE: &str = r#"
|
||||
import ast
|
||||
import json
|
||||
import sys
|
||||
|
||||
# Python 3.11固定チェック
|
||||
assert sys.version_info[:2] == (3, 11), f"Python 3.11 required, got {sys.version}"
|
||||
|
||||
def ast_to_dict(node):
|
||||
"""Phase 1: 基本的なAST要素のみ変換(エキスパート推奨JSON IR)"""
|
||||
|
||||
result = {
|
||||
"node_type": node.__class__.__name__,
|
||||
"py_version": "3.11",
|
||||
"ast_format": "v1"
|
||||
}
|
||||
|
||||
# 位置情報(エラー診断用)
|
||||
if hasattr(node, 'lineno'):
|
||||
result['lineno'] = node.lineno
|
||||
result['col_offset'] = node.col_offset
|
||||
if hasattr(node, 'end_lineno'):
|
||||
result['end_lineno'] = node.end_lineno
|
||||
result['end_col_offset'] = node.end_col_offset
|
||||
if isinstance(node, ast.Module):
|
||||
return {
|
||||
"type": "Module",
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body]
|
||||
}
|
||||
elif isinstance(node, ast.FunctionDef):
|
||||
# 意味論上重要:デフォルト引数情報を保存
|
||||
args_info = {
|
||||
"args": [arg.arg for arg in node.args.args],
|
||||
"defaults": [ast_to_dict(default) for default in node.args.defaults],
|
||||
"kwonlyargs": [arg.arg for arg in node.args.kwonlyargs],
|
||||
"kw_defaults": [ast_to_dict(d) if d else None for d in node.args.kw_defaults]
|
||||
}
|
||||
result.update({
|
||||
"name": node.name,
|
||||
"args": args_info,
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body],
|
||||
"decorator_list": [], # Phase 1では未対応
|
||||
"support_level": "full" # コンパイル可能
|
||||
})
|
||||
return result
|
||||
elif isinstance(node, ast.Return):
|
||||
return {
|
||||
"type": "Return",
|
||||
"value": ast_to_dict(node.value) if node.value else None
|
||||
}
|
||||
elif isinstance(node, ast.BinOp):
|
||||
return {
|
||||
"type": "BinOp",
|
||||
"op": node.op.__class__.__name__,
|
||||
"left": ast_to_dict(node.left),
|
||||
"right": ast_to_dict(node.right)
|
||||
}
|
||||
elif isinstance(node, ast.Call):
|
||||
return {
|
||||
"type": "Call",
|
||||
"func": ast_to_dict(node.func),
|
||||
"args": [ast_to_dict(arg) for arg in node.args]
|
||||
}
|
||||
elif isinstance(node, ast.Name):
|
||||
return {
|
||||
"type": "Name",
|
||||
"id": node.id
|
||||
}
|
||||
elif isinstance(node, ast.Constant):
|
||||
return {
|
||||
"type": "Constant",
|
||||
"value": node.value
|
||||
}
|
||||
elif isinstance(node, ast.If):
|
||||
return {
|
||||
"type": "If",
|
||||
"test": ast_to_dict(node.test),
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body],
|
||||
"orelse": [ast_to_dict(stmt) for stmt in node.orelse]
|
||||
}
|
||||
elif isinstance(node, ast.For):
|
||||
# 意味論上重要:for/else構文
|
||||
result.update({
|
||||
"target": ast_to_dict(node.target),
|
||||
"iter": ast_to_dict(node.iter),
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body],
|
||||
"orelse": [ast_to_dict(stmt) for stmt in node.orelse], # else節
|
||||
"support_level": "full"
|
||||
})
|
||||
return result
|
||||
|
||||
elif isinstance(node, ast.While):
|
||||
# 意味論上重要:while/else構文
|
||||
result.update({
|
||||
"test": ast_to_dict(node.test),
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body],
|
||||
"orelse": [ast_to_dict(stmt) for stmt in node.orelse], # else節
|
||||
"support_level": "full"
|
||||
})
|
||||
return result
|
||||
|
||||
elif isinstance(node, ast.BoolOp):
|
||||
# 意味論上重要:短絡評価
|
||||
result.update({
|
||||
"op": node.op.__class__.__name__, # And, Or
|
||||
"values": [ast_to_dict(v) for v in node.values],
|
||||
"support_level": "full"
|
||||
})
|
||||
return result
|
||||
else:
|
||||
# Phase 1では未対応(テレメトリー用)
|
||||
return {
|
||||
"node_type": "Unsupported",
|
||||
"original_type": type(node).__name__,
|
||||
"support_level": "fallback",
|
||||
"lineno": getattr(node, 'lineno', -1)
|
||||
}
|
||||
|
||||
def parse_to_json(code):
|
||||
try:
|
||||
tree = ast.parse(code)
|
||||
return json.dumps(ast_to_dict(tree))
|
||||
except Exception as e:
|
||||
return json.dumps({"type": "Error", "message": str(e)})
|
||||
"#;
|
||||
|
||||
struct PyHelper {
|
||||
// Python側のヘルパー関数への参照を保持
|
||||
parse_func: PyObject,
|
||||
}
|
||||
|
||||
impl PyHelper {
|
||||
fn new(py: Python) -> PyResult<Self> {
|
||||
// ヘルパーコードをPythonで実行
|
||||
let helpers = PyModule::from_code(py, PYTHON_HELPER_CODE, "helper.py", "helper")?;
|
||||
let parse_func = helpers.getattr("parse_to_json")?.to_object(py);
|
||||
|
||||
Ok(PyHelper { parse_func })
|
||||
}
|
||||
|
||||
fn parse_to_json(&self, py: Python, code: &str) -> Result<String, String> {
|
||||
match self.parse_func.call1(py, (code,)) {
|
||||
Ok(result) => result.extract::<String>(py)
|
||||
.map_err(|e| format!("Extract error: {}", e)),
|
||||
Err(e) => Err(format!("Parse error: {}", e))
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Phase 1 AST変換器
|
||||
```rust
|
||||
struct Phase1Converter;
|
||||
|
||||
impl Phase1Converter {
|
||||
fn new() -> Self {
|
||||
Phase1Converter
|
||||
}
|
||||
|
||||
fn convert(&self, py_ast: Phase1PythonAst) -> Result<ast::Program, String> {
|
||||
match py_ast {
|
||||
Phase1PythonAst::Module { body } => {
|
||||
let mut items = vec![];
|
||||
for stmt in body {
|
||||
match self.convert_statement(stmt)? {
|
||||
Some(item) => items.push(item),
|
||||
None => {} // 未対応要素はスキップ
|
||||
}
|
||||
}
|
||||
Ok(ast::Program { items })
|
||||
}
|
||||
_ => Err("Expected Module at top level".into())
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_statement(&self, stmt: Phase1PythonAst) -> Result<Option<ast::ProgramItem>, String> {
|
||||
match stmt {
|
||||
Phase1PythonAst::FunctionDef { name, args, body } => {
|
||||
// Python def → Nyash function
|
||||
let params = args.into_iter()
|
||||
.map(|arg| ast::Parameter { name: arg, ty: None })
|
||||
.collect();
|
||||
|
||||
let nyash_body = self.convert_body(body)?;
|
||||
|
||||
Ok(Some(ast::ProgramItem::Function(ast::FunctionDef {
|
||||
name,
|
||||
params,
|
||||
body: nyash_body,
|
||||
return_type: None,
|
||||
})))
|
||||
}
|
||||
Phase1PythonAst::Return { value } => {
|
||||
let expr = value
|
||||
.map(|v| self.convert_expression(v))
|
||||
.transpose()?;
|
||||
|
||||
Ok(Some(ast::ProgramItem::Statement(ast::Statement::Return(expr))))
|
||||
}
|
||||
// 他の文も同様に変換
|
||||
_ => Ok(None) // Phase 1では未対応
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_expression(&self, expr: Phase1PythonAst) -> Result<ast::Expression, String> {
|
||||
match expr {
|
||||
Phase1PythonAst::BinOp { op, left, right } => {
|
||||
let left = Box::new(self.convert_expression(*left)?);
|
||||
let right = Box::new(self.convert_expression(*right)?);
|
||||
|
||||
let op = match op.as_str() {
|
||||
"Add" => ast::BinaryOp::Add,
|
||||
"Sub" => ast::BinaryOp::Sub,
|
||||
"Mul" => ast::BinaryOp::Mul,
|
||||
"Div" => ast::BinaryOp::Div,
|
||||
_ => return Err(format!("Unsupported operator: {}", op))
|
||||
};
|
||||
|
||||
Ok(ast::Expression::BinaryOp { op, left, right })
|
||||
}
|
||||
Phase1PythonAst::Constant { value } => {
|
||||
// Python定数 → Nyashリテラル
|
||||
match value {
|
||||
serde_json::Value::Number(n) => {
|
||||
if let Some(i) = n.as_i64() {
|
||||
Ok(ast::Expression::Integer(i))
|
||||
} else if let Some(f) = n.as_f64() {
|
||||
Ok(ast::Expression::Float(f))
|
||||
} else {
|
||||
Err("Unsupported number type".into())
|
||||
}
|
||||
}
|
||||
serde_json::Value::String(s) => {
|
||||
Ok(ast::Expression::String(s))
|
||||
}
|
||||
serde_json::Value::Bool(b) => {
|
||||
Ok(ast::Expression::Bool(b))
|
||||
}
|
||||
_ => Err("Unsupported constant type".into())
|
||||
}
|
||||
}
|
||||
// 他の式も同様
|
||||
_ => Err("Unsupported expression in Phase 1".into())
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. インタープリター統合(src/interpreter/builtins.rs)
|
||||
```rust
|
||||
// ビルトインBox登録に追加
|
||||
pub fn register_builtin_boxes(env: &mut Environment) {
|
||||
// 既存のBox登録...
|
||||
|
||||
// PythonParserBox追加
|
||||
env.register_builtin_box("PythonParserBox", || {
|
||||
match PythonParserBox::new() {
|
||||
Ok(parser) => Arc::new(parser) as Arc<dyn NyashBox>,
|
||||
Err(e) => panic!("Failed to initialize PythonParserBox: {}", e)
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 6. 使用例とテストケース
|
||||
```nyash
|
||||
// test_python_parser_phase1.hako
|
||||
local py = new PythonParserBox()
|
||||
|
||||
// Phase 1: 基本的な関数定義と演算
|
||||
local code = """
|
||||
def add(x, y):
|
||||
return x + y
|
||||
|
||||
def multiply(x, y):
|
||||
return x * y
|
||||
|
||||
def calculate(a, b):
|
||||
sum_val = add(a, b)
|
||||
prod_val = multiply(a, b)
|
||||
return sum_val + prod_val
|
||||
"""
|
||||
|
||||
// パースしてJSON ASTを確認
|
||||
local json_ast = py.parse_to_json(code)
|
||||
print("JSON AST: " + json_ast)
|
||||
|
||||
// Nyash ASTに変換
|
||||
local nyash_ast = py.json_to_nyash_ast(json_ast)
|
||||
print("Conversion successful!")
|
||||
|
||||
// 実行(最初はCPython経由)
|
||||
local result = py.run(code + "\nprint(calculate(10, 5))")
|
||||
```
|
||||
|
||||
## 📊 段階的な実装計画
|
||||
|
||||
### Week 1: 基盤構築
|
||||
- [ ] PythonParserBoxの基本構造
|
||||
- [ ] pyo3統合とPython環境初期化
|
||||
- [ ] parse_to_json基本実装
|
||||
- [ ] エラーハンドリング
|
||||
|
||||
### Week 2: Phase 1変換器
|
||||
- [ ] Phase1PythonAstの定義
|
||||
- [ ] Phase1Converterの実装
|
||||
- [ ] 基本的な文と式の変換
|
||||
- [ ] テストケース作成
|
||||
|
||||
### Week 3: 統合とテスト
|
||||
- [ ] インタープリター統合
|
||||
- [ ] CPython exec経由の実行
|
||||
- [ ] ベンチマーク準備
|
||||
- [ ] ドキュメント整備
|
||||
|
||||
## 🚀 期待される成果
|
||||
|
||||
### Phase 1完了時点で実現できること:
|
||||
1. **基本的なPythonコードの実行**
|
||||
- 関数定義、算術演算、条件分岐、ループ
|
||||
|
||||
2. **Nyash ASTへの変換**
|
||||
- 将来のMIR/JIT最適化への道筋
|
||||
|
||||
3. **統合開発環境**
|
||||
- PythonコードとNyashコードの混在実行
|
||||
|
||||
4. **性能測定基盤**
|
||||
- CPython実行 vs Nyash実行の比較
|
||||
|
||||
## 📡 テレメトリー出力例
|
||||
|
||||
```bash
|
||||
# 環境変数で制御
|
||||
export NYASH_PYTHONPARSER_TELEMETRY=1 # 基本統計
|
||||
export NYASH_PYTHONPARSER_TELEMETRY=2 # 詳細ログ
|
||||
export NYASH_PYTHONPARSER_STRICT=1 # フォールバック時にパニック
|
||||
|
||||
# 実行例
|
||||
./target/release/nyash test_python_parser.hako
|
||||
|
||||
# 出力
|
||||
[PythonParser] Module: test.py (Python 3.11)
|
||||
Functions: 10 total
|
||||
Compiled: 7 (70%) → Nyash MIR/JIT
|
||||
Fallback: 3 (30%) → CPython exec
|
||||
- async_function: unsupported node 'AsyncFunctionDef' at line 23
|
||||
- generator_func: unsupported node 'Yield' at line 45
|
||||
- decorator_func: unsupported node 'decorator_list' at line 67
|
||||
|
||||
Unsupported Nodes Summary:
|
||||
AsyncFunctionDef: 1
|
||||
Yield: 2
|
||||
ClassDef: 1
|
||||
```
|
||||
|
||||
## 📊 Differential Testingフレームワーク
|
||||
|
||||
```rust
|
||||
// CPythonとNyashの出力比較
|
||||
pub fn differential_test(code: &str) -> TestResult {
|
||||
// CPythonで実行(オラクル)
|
||||
let python_result = Python::with_gil(|py| {
|
||||
capture_python_execution(py, code)
|
||||
})?;
|
||||
|
||||
// Nyashで実行
|
||||
let nyash_result = execute_with_pythonparser(code)?;
|
||||
|
||||
// 結果比較
|
||||
compare_results(python_result, nyash_result)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
作成日: 2025-08-27
|
||||
Phase 1実装の具体的な手順とエキスパートフィードバック統合
|
||||
@ -1,361 +0,0 @@
|
||||
# PythonParserBox実装計画(統合版)
|
||||
更新日: 2025-08-27
|
||||
|
||||
## 🎯 エキスパートからの統合フィードバック
|
||||
|
||||
### 最重要ポイント(両エキスパートが一致)
|
||||
1. **関数単位のフォールバック戦略**
|
||||
- ファイル全体でなく関数レベルでコンパイル/フォールバックを切り替え
|
||||
- 未対応機能を含む関数はCPython exec、対応済み関数はNyash MIR/JIT
|
||||
|
||||
2. **Python 3.11固定**
|
||||
- AST安定性の確保(3.8 Constant統一、3.10 match/case、3.12位置情報)
|
||||
- `py_version`と`ast_format`をJSON IRに埋め込む
|
||||
|
||||
3. **意味論の正確な実装が最優先**
|
||||
- 最適化より先にPython互換性を確保
|
||||
- 特に: イテレータプロトコル、真偽値判定、スコーピング規則(LEGB)
|
||||
|
||||
4. **GIL管理の最小化**
|
||||
- Python側でJSON生成(`ast.NodeVisitor` + `json.dumps`)
|
||||
- Rust側で解析(GIL外で実行)
|
||||
- `py.allow_threads(|| { ... })`で重い処理をGIL外実行
|
||||
|
||||
5. **テレメトリー重視**
|
||||
- 未対応ノードの記録(`support_level`フィールド)
|
||||
- フォールバック率の計測
|
||||
- ソース位置情報の保持(`lineno/col_offset/end_*`)
|
||||
|
||||
### Differential Testing戦略
|
||||
- **世界中のPythonコードがNyashのテストケース**
|
||||
- CPythonを「オラクル」として使用
|
||||
- 出力、戻り値、例外を比較
|
||||
- Grammar-based fuzzing(Hypothesis活用)
|
||||
|
||||
## 技術的実装方針
|
||||
|
||||
### 1. CPythonパーサー統合(pyo3使用)
|
||||
```rust
|
||||
// Cargo.toml
|
||||
[dependencies]
|
||||
pyo3 = { version = "0.22", features = ["auto-initialize"] }
|
||||
pyo3-numpy = "0.22" // NumPy連携用
|
||||
|
||||
// 初期化(一度だけ)
|
||||
pyo3::prepare_freethreaded_python();
|
||||
|
||||
// Python側ヘルパー(embedded)
|
||||
const PYTHON_HELPER: &str = r#"
|
||||
import ast
|
||||
import json
|
||||
import sys
|
||||
|
||||
def parse_to_json(code, filename="<string>", mode="exec"):
|
||||
tree = ast.parse(code, filename, mode)
|
||||
return json.dumps(ast_to_dict(tree))
|
||||
|
||||
def ast_to_dict(node):
|
||||
result = {}
|
||||
|
||||
# 必須フィールド
|
||||
result['node_type'] = node.__class__.__name__
|
||||
result['py_version'] = f"{sys.version_info.major}.{sys.version_info.minor}"
|
||||
|
||||
# 位置情報(エラー診断用)
|
||||
if hasattr(node, 'lineno'):
|
||||
result['lineno'] = node.lineno
|
||||
result['col_offset'] = node.col_offset
|
||||
if hasattr(node, 'end_lineno'): # Python 3.8+
|
||||
result['end_lineno'] = node.end_lineno
|
||||
result['end_col_offset'] = node.end_col_offset
|
||||
|
||||
# サポートレベル(Nyash側で設定)
|
||||
result['support_level'] = 'unknown'
|
||||
|
||||
# ASTフィールド
|
||||
if isinstance(node, ast.AST):
|
||||
for field in node._fields:
|
||||
value = getattr(node, field)
|
||||
result[field] = ast_to_dict(value)
|
||||
elif isinstance(node, list):
|
||||
return [ast_to_dict(x) for x in node]
|
||||
else:
|
||||
return node
|
||||
|
||||
return result
|
||||
"#;
|
||||
```
|
||||
|
||||
### 2. 最小実装セット(Phase 1: Must-Have)
|
||||
```
|
||||
Phase 1 意味論の必須要素(Codex先生強調):
|
||||
- LEGB + locals/freevars(スコーピング)
|
||||
- デフォルト引数の評価タイミング(定義時)
|
||||
- イテレータベースのfor文
|
||||
- for/else + while/else(Python独特)
|
||||
- Python真偽値判定(__bool__ → __len__)
|
||||
- 短絡評価(and/or)
|
||||
|
||||
Phase 1 AST構造:
|
||||
├─ Module (py_version, ast_format)
|
||||
├─ FunctionDef (name, args, body, decorator_list=[])
|
||||
│ └─ arguments (args, defaults, kwonlyargs=[], kw_defaults=[])
|
||||
├─ Return (value)
|
||||
├─ Assign (targets, value)
|
||||
├─ AugAssign (target, op, value) # +=, -=等
|
||||
└─ Expr (value)
|
||||
|
||||
Phase 1 式:
|
||||
├─ BinOp (left, op, right)
|
||||
│ └─ ops: Add, Sub, Mult, Div, FloorDiv, Mod, Pow
|
||||
├─ Compare (left, ops, comparators)
|
||||
│ └─ ops: Eq, NotEq, Lt, LtE, Gt, GtE, Is, IsNot
|
||||
├─ BoolOp (op, values) # and/or
|
||||
├─ UnaryOp (op, operand) # not, -, +
|
||||
├─ Call (func, args, keywords=[])
|
||||
├─ Name (id, ctx=Load/Store/Del)
|
||||
├─ Constant (value) # Python 3.8+統一
|
||||
└─ IfExp (test, body, orelse) # 三項演算子
|
||||
|
||||
Phase 1 制御フロー:
|
||||
├─ If (test, body, orelse)
|
||||
├─ While (test, body, orelse) # else節対応必須
|
||||
├─ For (target, iter, body, orelse) # else節対応必須
|
||||
├─ Break
|
||||
└─ Continue
|
||||
```
|
||||
|
||||
### 3. 関数単位フォールバック戦略
|
||||
```rust
|
||||
// 関数単位のコンパイル判定
|
||||
pub struct FunctionCompiler {
|
||||
supported_nodes: HashSet<&'static str>,
|
||||
telemetry: CompilationTelemetry,
|
||||
}
|
||||
|
||||
impl FunctionCompiler {
|
||||
pub fn can_compile(&self, func_def: &PythonAst) -> CompileResult {
|
||||
let mut visitor = SupportChecker::new(&self.supported_nodes);
|
||||
visitor.visit(func_def);
|
||||
|
||||
if visitor.has_unsupported() {
|
||||
// CPython execへフォールバック
|
||||
CompileResult::Fallback {
|
||||
reason: visitor.unsupported_nodes(),
|
||||
location: func_def.location(),
|
||||
}
|
||||
} else {
|
||||
// Nyash MIR/JITへコンパイル
|
||||
CompileResult::Compile
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile_module(&mut self, module: &PythonAst) -> ModuleUnit {
|
||||
let mut units = vec![];
|
||||
|
||||
// モジュールトップレベルはPythonで実行(globals設定)
|
||||
units.push(ExecutionUnit::PythonExec(module.top_level));
|
||||
|
||||
// 各関数を判定
|
||||
for func in module.functions() {
|
||||
match self.can_compile(func) {
|
||||
CompileResult::Compile => {
|
||||
let mir = self.compile_to_mir(func);
|
||||
units.push(ExecutionUnit::NyashFunction(mir));
|
||||
self.telemetry.record_compiled(func.name);
|
||||
}
|
||||
CompileResult::Fallback { reason, location } => {
|
||||
units.push(ExecutionUnit::PythonThunk(func));
|
||||
self.telemetry.record_fallback(func.name, reason, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModuleUnit { units }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. データ共有戦略
|
||||
```rust
|
||||
// NdArrayBox定義
|
||||
pub struct NdArrayBox {
|
||||
base: BoxBase,
|
||||
py_array: Py<PyArray<f64, Dim<[usize; 2]>>>, // Python側の参照保持
|
||||
// 操作時のみGIL取得してArrayViewを取る
|
||||
}
|
||||
|
||||
impl NdArrayBox {
|
||||
pub fn to_view(&self) -> PyResult<ArrayView2<f64>> {
|
||||
Python::with_gil(|py| {
|
||||
let array = self.py_array.as_ref(py);
|
||||
Ok(array.readonly())
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 実装ロードマップ
|
||||
|
||||
#### Phase 1: パーサー統合(1-2週間)
|
||||
- [ ] pyo3セットアップとPythonParserBox骨格
|
||||
- [ ] Python側parse_to_jsonヘルパー実装
|
||||
- [ ] JSON→Nyash AST最小変換
|
||||
- [ ] run()メソッド(CPython exec委譲)
|
||||
- [ ] 例外変換(PyErr → NyashError)
|
||||
|
||||
#### Phase 2: MIR変換(2-4週間)
|
||||
- [ ] AST→MIR変換器(最小セット)
|
||||
- [ ] 数値演算プリミティブ実装
|
||||
- [ ] スコープ解決(関数ローカル/グローバル)
|
||||
- [ ] 基本的な制御フロー(If/While)
|
||||
|
||||
#### Phase 3: NumPy統合(並行可能)
|
||||
- [ ] pyo3-numpy統合
|
||||
- [ ] NdArrayBox実装
|
||||
- [ ] ゼロコピーベンチマーク
|
||||
- [ ] バッファプロトコル対応
|
||||
|
||||
#### Phase 4: 最適化と拡張
|
||||
- [ ] 型特化とガード最適化
|
||||
- [ ] 例外処理(try/except)
|
||||
- [ ] クラス/メソッド対応
|
||||
- [ ] import統合
|
||||
|
||||
## 性能目標(現実的な見積もり)
|
||||
|
||||
| コードタイプ | 期待される高速化 | 備考 |
|
||||
|------------|----------------|------|
|
||||
| 純Pythonループ | 2-10倍 | 型安定なホットパス |
|
||||
| 関数呼び出し多 | 1.5-3倍 | インライン化効果 |
|
||||
| NumPy処理中心 | 1.0-1.2倍 | 既に最適化済み |
|
||||
| 動的特性多用 | 1.2-3倍 | ガード頻発で限定的 |
|
||||
|
||||
## 実装上の注意点(エキスパート推奨)
|
||||
|
||||
### 意味論の重要な違い(Phase 1で対応必須)
|
||||
|
||||
1. **制御フロー**
|
||||
- `for`文: イテレータプロトコル必須(`__iter__`/`__next__`)
|
||||
- `for/else`, `while/else`: breakしなかった場合のelse実行
|
||||
- 短絡評価: `and`は左がFalseなら右を評価しない
|
||||
|
||||
2. **スコープ規則(LEGB)**
|
||||
```python
|
||||
# Local → Enclosing → Global → Builtins
|
||||
global_var = 1
|
||||
|
||||
def outer():
|
||||
enclosing_var = 2
|
||||
|
||||
def inner():
|
||||
local_var = 3
|
||||
nonlocal enclosing_var # 明示的な宣言
|
||||
global global_var # 明示的な宣言
|
||||
```
|
||||
|
||||
3. **数値演算の違い**
|
||||
- `/`: Python 3では常にfloat(true division)
|
||||
- `//`: floor division(整数除算)
|
||||
- 大整数: デフォルトで無限精度
|
||||
- `is` vs `==`: オブジェクト同一性 vs 値の等価性
|
||||
|
||||
4. **関数定義の罠**
|
||||
```python
|
||||
def f(x, y=[]): # デフォルト引数は定義時に1度だけ評価!
|
||||
y.append(x) # 全呼び出しで同じリストを共有
|
||||
return y
|
||||
```
|
||||
|
||||
### GIL管理のベストプラクティス
|
||||
|
||||
```rust
|
||||
// ❌ 悪い例: GILを長時間保持
|
||||
let result = Python::with_gil(|py| {
|
||||
let ast = parse_python(py, code)?;
|
||||
let json = convert_to_json(py, ast)?; // ここまでGIL必要
|
||||
let nyash_ast = parse_json(&json)?; // GIL不要なのに保持
|
||||
compile_to_mir(nyash_ast)? // GIL不要なのに保持
|
||||
});
|
||||
|
||||
// ✅ 良い例: GILを最小限に
|
||||
let json = Python::with_gil(|py| {
|
||||
let ast = parse_python(py, code)?;
|
||||
convert_to_json(py, ast) // JSON生成まで
|
||||
})?;
|
||||
|
||||
// GIL外で重い処理
|
||||
let nyash_ast = parse_json(&json)?;
|
||||
let mir = compile_to_mir(nyash_ast)?;
|
||||
|
||||
// 必要時のみ再取得
|
||||
Python::with_gil(|py| {
|
||||
py.allow_threads(|| {
|
||||
// 時間のかかるRust処理
|
||||
optimize_mir(mir)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### テレメトリーとデバッグ
|
||||
|
||||
```rust
|
||||
// 環境変数で制御
|
||||
NYASH_PYTHONPARSER_TELEMETRY=1 # 基本統計
|
||||
NYASH_PYTHONPARSER_TELEMETRY=2 # 詳細ログ
|
||||
NYASH_PYTHONPARSER_STRICT=1 # フォールバック時にパニック(CI用)
|
||||
|
||||
// 出力例
|
||||
[PythonParser] Module: example.py
|
||||
Functions: 10 total
|
||||
Compiled: 7 (70%)
|
||||
Fallback: 3 (30%)
|
||||
- async_function: unsupported node 'AsyncFunctionDef' at line 23
|
||||
- generator_func: unsupported node 'Yield' at line 45
|
||||
- class_method: unsupported node 'ClassDef' at line 67
|
||||
```
|
||||
|
||||
## 次のステップ
|
||||
|
||||
### 即座に開始すべきこと
|
||||
|
||||
1. **Python 3.11環境固定**
|
||||
```bash
|
||||
pyenv install 3.11.9
|
||||
pyenv local 3.11.9
|
||||
```
|
||||
|
||||
2. **最小動作確認**
|
||||
```python
|
||||
# test_minimal.py
|
||||
def add(x, y):
|
||||
return x + y
|
||||
|
||||
result = add(10, 5)
|
||||
print(f"Result: {result}") # → Nyashで15が出力されれば成功!
|
||||
```
|
||||
|
||||
3. **テレメトリー基盤構築**
|
||||
- 未対応ノードの記録システム
|
||||
- フォールバック率の可視化
|
||||
- ソース位置情報の保持
|
||||
|
||||
4. **Differential Testingの準備**
|
||||
- CPythonとの出力比較フレームワーク
|
||||
- 標準出力、戻り値、例外のキャプチャ
|
||||
- テストコーパスの選定
|
||||
|
||||
### 成功の測定基準
|
||||
|
||||
| フェーズ | 目標 | 測定指標 |
|
||||
|---------|------|----------|
|
||||
| Phase 1 | 基本動作 | 簡単な数値計算の70%がコンパイル可能 |
|
||||
| Phase 2 | 実用性 | scikit-learnの基本アルゴリズムが動作 |
|
||||
| Phase 3 | 性能 | 純Pythonループで5倍以上の高速化 |
|
||||
| Phase 4 | 成熟度 | PyPIトップ100の30%が基本動作 |
|
||||
|
||||
## まとめ
|
||||
|
||||
このPythonParserBox実装は、単なる機能追加ではなく、Nyash言語の成熟度を飛躍的に高める戦略的プロジェクト。
|
||||
エキスパートの指摘を踏まえ、関数単位のフォールバック、Python 3.11固定、意味論の正確な実装、
|
||||
GIL最小化、テレメトリー重視で着実に実装を進める。
|
||||
@ -1,76 +0,0 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
Note: 本来は「PythonをNyashで動かすフェーズ(Core実装)」の位置づけでしたが、現在は順番を変更し、先に 10.5b(MIR→VM→ネイティブビルド基盤)を進めています。
|
||||
|
||||
# Phase 10.1d - Core実装(Phase 1機能)
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
Python AST → Nyash AST変換のPhase 1機能(基本構文)を実装する。
|
||||
|
||||
## 📁 実装ドキュメント
|
||||
- **`python_implementation_roadmap.txt`** - Phase別実装ロードマップ
|
||||
|
||||
## 🔧 Phase 1必須要素(Codex先生強調)
|
||||
|
||||
### 意味論の必須実装
|
||||
1. **LEGB + locals/freevars** - スコーピング規則
|
||||
2. **デフォルト引数の評価タイミング** - 定義時に一度だけ
|
||||
3. **イテレータベースのfor文** - `__iter__`/`__next__`プロトコル
|
||||
4. **for/else + while/else** - Python独特のelse節
|
||||
5. **Python真偽値判定** - `__bool__` → `__len__`
|
||||
6. **短絡評価** - and/orの正確な挙動
|
||||
|
||||
### サポートする文(Statement)
|
||||
- [x] def - 関数定義
|
||||
- [x] if/elif/else - 条件分岐
|
||||
- [x] for - ループ(else節対応必須)
|
||||
- [x] while - ループ(else節対応必須)
|
||||
- [x] break/continue - ループ制御
|
||||
- [x] return - 戻り値
|
||||
|
||||
### サポートする式(Expression)
|
||||
- [x] 算術演算子(+,-,*,/,//,%)
|
||||
- [x] 比較演算子(==,!=,<,>,<=,>=,is,is not)
|
||||
- [x] 論理演算子(and,or,not)- 短絡評価
|
||||
- [x] 関数呼び出し
|
||||
- [x] 変数参照/代入
|
||||
- [x] リテラル(数値/文字列/bool)
|
||||
|
||||
## 🧪 テストケース
|
||||
```python
|
||||
# Phase 1で動作すべきコード
|
||||
def fibonacci(n):
|
||||
if n <= 1:
|
||||
return n
|
||||
return fibonacci(n-1) + fibonacci(n-2)
|
||||
|
||||
# for/else のテスト
|
||||
for i in range(10):
|
||||
if i == 5:
|
||||
break
|
||||
else:
|
||||
print("No break") # 実行されない
|
||||
|
||||
# デフォルト引数の罠
|
||||
def append_to_list(item, lst=[]): # 定義時に評価!
|
||||
lst.append(item)
|
||||
return lst
|
||||
```
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] 基本的な関数定義が変換できる
|
||||
- [ ] 制御フローが正しく変換される
|
||||
- [ ] 演算子が正しくマッピングされる
|
||||
- [ ] Python意味論が保たれている
|
||||
- [ ] 70%以上の関数がコンパイル可能
|
||||
|
||||
## 📊 テレメトリー確認
|
||||
```bash
|
||||
[PythonParser] Module: test.py (Python 3.11)
|
||||
Functions: 10 total
|
||||
Compiled: 7 (70%) ← 目標達成!
|
||||
Fallback: 3 (30%)
|
||||
```
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1e (トランスパイラー)
|
||||
@ -1,264 +0,0 @@
|
||||
# PythonParserBox 実装ロードマップ(エキスパート統合版)
|
||||
Based on ChatGPT5's Python Language Feature Surface Map + Expert Feedback
|
||||
更新日: 2025-08-27
|
||||
|
||||
## 🎯 実装優先順位の考え方(エキスパート統合)
|
||||
|
||||
### 🏯 核心戦略:関数単位フォールバック
|
||||
**両エキスパートが強調:** ファイル全体ではなく、**関数単位**でコンパイル/フォールバックを判断
|
||||
```python
|
||||
def supported_function(): # → Nyash MIR/JIT
|
||||
return x + y
|
||||
|
||||
def unsupported_function(): # → CPython exec
|
||||
yield from generator # Phase 1では未対応
|
||||
```
|
||||
|
||||
### 🔧 Python 3.11固定
|
||||
- AST安定性確保(3.8 Constant統一、3.10 match/case、3.12位置情報)
|
||||
- `py_version`と`ast_format`をJSON IRに埋め込む
|
||||
|
||||
### 🌟 Differential Testing戦略
|
||||
- **世界中のPythonコードがNyashのテストケースに**
|
||||
- CPythonをオラクルとして使用、出力・戻り値・例外を比較
|
||||
- 微妙なセマンティクスバグを自動発見
|
||||
|
||||
### 📊 テレメトリー重視
|
||||
- 未対応ノードの記録(`support_level`フィールド)
|
||||
- フォールバック率の計測
|
||||
- ソース位置情報保持(`lineno/col_offset/end_*`)
|
||||
|
||||
## 📋 Phase 1: Core Subset(1-2週間)
|
||||
**目標**: 基本的なPythonコードをNyashで実行可能にする
|
||||
|
||||
### ❌ Phase 1での必須意味論要素(Codex先生強調)
|
||||
- **LEGB + locals/freevars**: スコーピング規則
|
||||
- **デフォルト引数の評価タイミング**: 定義時に一度だけ
|
||||
- **イテレータベースのfor文**: `__iter__`/`__next__`プロトコル
|
||||
- **for/else + while/else**: Python独特のelse節
|
||||
- **Python真偽値判定**: `__bool__` → `__len__`
|
||||
- **短絡評価**: and/orの正確な挙動
|
||||
|
||||
### 文(Statement)
|
||||
- [x] def - 関数定義 → Nyash関数/Box
|
||||
- デフォルト引数の定義時評価
|
||||
- argumentsオブジェクトの完全解析
|
||||
- [x] if/elif/else - 条件分岐 → CondBr
|
||||
- [x] for - ループ → Loop + Iterator
|
||||
- **else節対応必須**
|
||||
- [x] while - ループ → Loop
|
||||
- **else節対応必須**
|
||||
- [x] break/continue - ループ制御
|
||||
- [x] return - 戻り値 → Return
|
||||
- [ ] pass - 空文
|
||||
- [ ] import(Phase 3へ延期)
|
||||
|
||||
### 式(Expression)
|
||||
- [x] 関数呼び出し - Call → BoxCall
|
||||
- [x] 算術演算子 - +,-,*,/,//,% → BinOp
|
||||
- `/`: true division(常にfloat)
|
||||
- `//`: floor division
|
||||
- [x] 比較演算子 - ==,!=,<,>,<=,>=,is,is not → Compare
|
||||
- [x] 論理演算子 - and,or,not → BoolOp/UnaryOp
|
||||
- 短絡評価の正確な実装
|
||||
- [x] 変数参照/代入 - Name → Load/Store
|
||||
- [x] リテラル - 数値/文字列/bool → Constant
|
||||
- [x] 三項演算子 - IfExp
|
||||
|
||||
### データ型(最小限)
|
||||
- [x] int → IntegerBox(大整数対応)
|
||||
- [x] float → FloatBox(NaNの扱い注意)
|
||||
- [x] str → StringBox
|
||||
- [x] bool → BoolBox
|
||||
- [x] list(基本) → ArrayBox
|
||||
|
||||
## 📋 Phase 2: Data Model(2-3週間)
|
||||
**目標**: Pythonの特殊メソッドをNyashのBoxメソッドにマッピング
|
||||
|
||||
### 特殊メソッド
|
||||
- [ ] __init__ → constructor/birth
|
||||
- [ ] __len__ → length()
|
||||
- [ ] __getitem__ → get()
|
||||
- [ ] __setitem__ → set()
|
||||
- [ ] __iter__ → iterator()
|
||||
- [ ] __str__ → toString()
|
||||
|
||||
### コレクション拡張
|
||||
- [ ] dict → MapBox
|
||||
- [ ] tuple → ImmutableArrayBox(新規)
|
||||
- [ ] set → SetBox(新規)
|
||||
|
||||
### 演算子オーバーロード
|
||||
- [ ] __add__, __sub__ 等 → operator+, operator-
|
||||
- [ ] __eq__, __lt__ 等 → equals(), compareTo()
|
||||
|
||||
## 📋 Phase 3: Advanced Features(1ヶ月)
|
||||
**目標**: Pythonの生産性の高い機能を実装
|
||||
|
||||
### 制御フロー拡張
|
||||
- [ ] try/except → エラーハンドリング
|
||||
- [ ] with文 → リソース管理
|
||||
- [ ] break/continue → ループ制御
|
||||
|
||||
### 高度な機能
|
||||
- [ ] ジェネレータ(yield) → GeneratorBox
|
||||
- [ ] デコレータ → 関数ラッパー
|
||||
- [ ] 内包表記 → 最適化されたループ
|
||||
- [ ] ラムダ式 → 匿名関数
|
||||
|
||||
### クラスシステム
|
||||
- [ ] class文 → box定義
|
||||
- [ ] 継承 → from構文
|
||||
- [ ] super() → from Parent.method()
|
||||
|
||||
## 📋 Phase 4: Modern Python(将来)
|
||||
**目標**: 最新のPython機能をサポート
|
||||
|
||||
### 非同期
|
||||
- [ ] async/await → 非同期Box(将来のNyash非同期と統合)
|
||||
- [ ] async for/with → 非同期イテレータ
|
||||
|
||||
### パターンマッチ(3.10+)
|
||||
- [ ] match/case → Nyashのパターンマッチ(将来実装時)
|
||||
|
||||
### 型ヒント
|
||||
- [ ] 型アノテーション → MIRの型情報として活用
|
||||
- [ ] typing モジュール → 静的型チェック情報
|
||||
|
||||
## 🚀 実装戦略
|
||||
|
||||
### Step 1: AST変換の基礎(Phase 1開始)
|
||||
```python
|
||||
# Python側でAST→JSON
|
||||
import ast
|
||||
import json
|
||||
|
||||
def parse_to_json(code):
|
||||
tree = ast.parse(code)
|
||||
return json.dumps(ast_to_dict(tree))
|
||||
|
||||
# 最小限のノードから実装
|
||||
def ast_to_dict(node):
|
||||
if isinstance(node, ast.FunctionDef):
|
||||
return {
|
||||
"type": "FunctionDef",
|
||||
"name": node.name,
|
||||
"args": [arg.arg for arg in node.args.args],
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body]
|
||||
}
|
||||
# ... 他のノードタイプを順次追加
|
||||
```
|
||||
|
||||
### Step 2: Nyash AST生成(Rust側)
|
||||
```rust
|
||||
// JSON → Nyash AST
|
||||
fn convert_python_ast(json: &str) -> Result<ast::Program> {
|
||||
let py_ast: PythonAst = serde_json::from_str(json)?;
|
||||
match py_ast {
|
||||
PythonAst::FunctionDef { name, args, body } => {
|
||||
// Python def → Nyash function
|
||||
ast::BoxDef {
|
||||
name,
|
||||
methods: vec![ast::Method {
|
||||
name: name.clone(),
|
||||
params: args,
|
||||
body: convert_statements(body),
|
||||
}],
|
||||
..
|
||||
}
|
||||
}
|
||||
// ... 他のケース
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: 段階的な実行
|
||||
1. 最初はCPython exec()でそのまま実行
|
||||
2. 変換可能な部分からMIR生成
|
||||
3. MIR化された部分はVM/JITで高速実行
|
||||
4. 未対応部分は自動的にCPythonフォールバック
|
||||
|
||||
## 📊 期待される成果
|
||||
|
||||
### Phase 1完了時点
|
||||
- 簡単な数値計算スクリプトが2-5倍高速化
|
||||
- 基本的なループが最適化される
|
||||
- Nyashの既存Box(FileBox等)がPythonから使える
|
||||
|
||||
### Phase 2完了時点
|
||||
- Pythonのリスト/辞書操作が高速化
|
||||
- NyashとPythonのデータ構造が相互運用可能
|
||||
- 特殊メソッドによる自然な統合
|
||||
|
||||
### Phase 3完了時点
|
||||
- Pythonの生産的な機能がNyashで高速実行
|
||||
- 既存Pythonコードの大部分が動作
|
||||
- デコレータやジェネレータも最適化
|
||||
|
||||
## 🎯 最初の一歩(今すぐ開始)
|
||||
|
||||
1. pyo3でPythonParserBoxの骨組み作成
|
||||
2. 最小限のparse_to_json実装(def + return)
|
||||
3. 単純な関数のAST変換テスト
|
||||
4. "Hello from Python in Nyash"を表示
|
||||
|
||||
```python
|
||||
# 最初のテストケース
|
||||
def hello():
|
||||
return "Hello from Python in Nyash"
|
||||
|
||||
# これがNyashで動けば成功!
|
||||
```
|
||||
|
||||
## 📊 成功の測定基準(エキスパート推奨)
|
||||
|
||||
### 定量的指標
|
||||
| 指標 | 目標 | 測定方法 |
|
||||
|------|-------|----------|
|
||||
| カバレッジ率 | 70%以上 | コンパイル済み vs フォールバック関数の比率 |
|
||||
| 性能向上 | 2-10倍 | 純Pythonループのベンチマーク |
|
||||
| バグ発見数 | 10+件/Phase | Differential Testingで発見されたNyashバグ |
|
||||
| エコシステム | 1以上 | 動作する有名Pythonライブラリ |
|
||||
|
||||
### マイルストーン
|
||||
- Phase 1: "Hello from Python in Nyash"が動作
|
||||
- Phase 2: scikit-learnの基本アルゴリズムが動作
|
||||
- Phase 3: FlaskのHello Worldが動作
|
||||
- Phase 4: PyPIトップ100の30%が基本動作
|
||||
|
||||
## 🔧 GIL管理の黄金律
|
||||
|
||||
```rust
|
||||
// GILは最小限に!
|
||||
let json_ast = Python::with_gil(|py| {
|
||||
// Python側でJSON生成(高速)
|
||||
py_helper.parse_to_json(py, code)
|
||||
})?;
|
||||
|
||||
// GIL外でRust処理(並列可能)
|
||||
let nyash_ast = py.allow_threads(|| {
|
||||
convert_json_to_nyash(json_ast)
|
||||
});
|
||||
```
|
||||
|
||||
## 🔍 JSON IR設計(Codex先生推奨)
|
||||
|
||||
```json
|
||||
{
|
||||
"node_type": "FunctionDef",
|
||||
"py_version": "3.11",
|
||||
"ast_format": "v2",
|
||||
"support_level": "full", // "partial", "fallback"
|
||||
"lineno": 1,
|
||||
"col_offset": 0,
|
||||
"end_lineno": 3,
|
||||
"end_col_offset": 15,
|
||||
"name": "hello",
|
||||
"args": {...},
|
||||
"body": [...]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
作成日: 2025-08-27
|
||||
ChatGPT5のサーフェスマップ + Gemini/Codex先生のエキスパートフィードバックを統合
|
||||
@ -1,72 +0,0 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
# Phase 10.1e - Python → Nyashトランスパイラー
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
Python ASTをNyashソースコードとして出力する機能を実装する。
|
||||
|
||||
## 📁 実装ドキュメント
|
||||
- **`python_to_nyash_transpiler.txt`** - トランスパイラー設計
|
||||
|
||||
## 🔧 実装機能
|
||||
|
||||
### 1. AST → Nyashソース生成
|
||||
```rust
|
||||
impl PythonParserBox {
|
||||
pub fn to_nyash_source(&self, python_code: &str) -> Result<String, String> {
|
||||
// Python → JSON AST → Nyash AST → Nyashソース
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 変換例
|
||||
```python
|
||||
# Python入力
|
||||
def add(x, y):
|
||||
return x + y
|
||||
|
||||
result = add(10, 5)
|
||||
```
|
||||
|
||||
```nyash
|
||||
# Nyash出力
|
||||
function add(x, y) {
|
||||
return x + y
|
||||
}
|
||||
|
||||
local result
|
||||
result = add(10, 5)
|
||||
```
|
||||
|
||||
### 3. 出力フォーマッター
|
||||
- インデント管理
|
||||
- 括弧の追加(Nyashは明示的)
|
||||
- コメント保持(可能な範囲で)
|
||||
|
||||
## 🛠️ コマンドラインツール
|
||||
```bash
|
||||
# 基本変換
|
||||
nyash-transpile input.py -o output.hako
|
||||
|
||||
# 変換統計付き
|
||||
nyash-transpile --stats complex.py
|
||||
# Output: Converted 15/17 functions (88%)
|
||||
|
||||
# 部分変換(サポート関数のみ)
|
||||
nyash-transpile --partial script.py
|
||||
```
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] `to_nyash_source()` メソッドが動作する
|
||||
- [ ] 基本的なPythonコードが正しいNyashに変換される
|
||||
- [ ] インデントが正しく管理される
|
||||
- [ ] 変換統計が表示される
|
||||
- [ ] ファイル出力ができる
|
||||
|
||||
## 🌟 期待される利用シーン
|
||||
1. **学習ツール** - PythonユーザーがNyash構文を学ぶ
|
||||
2. **段階的移行** - 既存Pythonコードの移行
|
||||
3. **性能最適化** - ホットパスをNyashネイティブに
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1f (テストとベンチマーク)
|
||||
@ -1,225 +0,0 @@
|
||||
# Python → Nyashトランスパイラー機能
|
||||
~PythonParserBoxの応用による自動変換~
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
PythonParserBoxでPython AST → Nyash ASTの変換ができるなら、それを**Nyashソースコードとして出力**できる!
|
||||
|
||||
## 🚀 実現可能な機能
|
||||
|
||||
### 1. Python → Nyashファイル変換
|
||||
```python
|
||||
# input.py
|
||||
def calculate(x, y):
|
||||
result = x * 2 + y
|
||||
return result
|
||||
|
||||
for i in range(10):
|
||||
print(calculate(i, 5))
|
||||
```
|
||||
|
||||
↓ 変換
|
||||
|
||||
```nyash
|
||||
# output.hako
|
||||
function calculate(x, y) {
|
||||
local result
|
||||
result = x * 2 + y
|
||||
return result
|
||||
}
|
||||
|
||||
local i
|
||||
for i in range(0, 10) {
|
||||
print(calculate(i, 5))
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 実装方法
|
||||
|
||||
```rust
|
||||
impl PythonParserBox {
|
||||
// Python → Nyashファイル出力
|
||||
pub fn transpile_to_file(&self, python_code: &str, output_path: &str) -> Result<(), String> {
|
||||
// 1. Python → JSON AST
|
||||
let json_ast = self.parse_to_json(python_code)?;
|
||||
|
||||
// 2. JSON AST → Nyash AST
|
||||
let nyash_ast = self.json_to_nyash_ast(&json_ast)?;
|
||||
|
||||
// 3. Nyash AST → Nyashソースコード
|
||||
let nyash_code = self.ast_to_nyash_source(&nyash_ast)?;
|
||||
|
||||
// 4. ファイルに出力
|
||||
std::fs::write(output_path, nyash_code)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// AST → Nyashソースコード生成
|
||||
fn ast_to_nyash_source(&self, ast: &NyashAst) -> Result<String, String> {
|
||||
let mut output = String::new();
|
||||
let formatter = NyashFormatter::new();
|
||||
|
||||
for item in &ast.items {
|
||||
formatter.format_item(item, &mut output)?;
|
||||
}
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📋 使用例
|
||||
|
||||
### コマンドライン版
|
||||
```bash
|
||||
# PythonファイルをNyashに変換
|
||||
nyash-transpile input.py -o output.hako
|
||||
|
||||
# 標準出力に出力
|
||||
nyash-transpile script.py
|
||||
|
||||
# 部分変換(サポートされる構文のみ)
|
||||
nyash-transpile --partial complex_script.py
|
||||
```
|
||||
|
||||
### Nyashスクリプト内での使用
|
||||
```nyash
|
||||
local transpiler = new PythonParserBox()
|
||||
|
||||
// Pythonコードを読み込み
|
||||
local python_code = FileBox.read("algorithm.py")
|
||||
|
||||
// Nyashに変換
|
||||
local nyash_code = transpiler.to_nyash_source(python_code)
|
||||
|
||||
// ファイルに保存
|
||||
FileBox.write("algorithm.hako", nyash_code)
|
||||
|
||||
// または直接実行
|
||||
eval(nyash_code)
|
||||
```
|
||||
|
||||
## 🎨 変換マッピング例
|
||||
|
||||
### 基本構文
|
||||
| Python | Nyash |
|
||||
|--------|-------|
|
||||
| `def func():` | `function func() {` |
|
||||
| `if x > 0:` | `if (x > 0) {` |
|
||||
| `for i in range(10):` | `for i in range(0, 10) {` |
|
||||
| `while x < 10:` | `while (x < 10) {` |
|
||||
| `x = 5` | `local x; x = 5` または `x = 5`(スコープによる)|
|
||||
|
||||
### データ型
|
||||
| Python | Nyash |
|
||||
|--------|-------|
|
||||
| `x = 42` | `x = 42` |
|
||||
| `s = "hello"` | `s = "hello"` |
|
||||
| `lst = [1, 2, 3]` | `lst = new ArrayBox([1, 2, 3])` |
|
||||
| `d = {"a": 1}` | `d = new MapBox(); d.set("a", 1)` |
|
||||
|
||||
### 特殊なケース
|
||||
```python
|
||||
# Pythonのfor/else
|
||||
for i in items:
|
||||
if condition:
|
||||
break
|
||||
else:
|
||||
print("No break")
|
||||
```
|
||||
|
||||
```nyash
|
||||
# Nyashでの実装(フラグを使用)
|
||||
local broke = false
|
||||
for i in items {
|
||||
if (condition) {
|
||||
broke = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (not broke) {
|
||||
print("No break")
|
||||
}
|
||||
```
|
||||
|
||||
## 🌟 利点
|
||||
|
||||
### 1. 段階的移行支援
|
||||
- 既存のPythonプロジェクトを段階的にNyashに移行
|
||||
- 変換されたコードを手動で最適化可能
|
||||
|
||||
### 2. 学習ツールとして
|
||||
- PythonユーザーがNyash構文を学ぶ
|
||||
- 両言語の違いを理解
|
||||
|
||||
### 3. コード生成
|
||||
- Pythonで書いたアルゴリズムをNyashネイティブコードに
|
||||
- より高速な実行のための前処理
|
||||
|
||||
### 4. 逆方向変換の可能性
|
||||
- Nyash → Pythonも将来的に可能
|
||||
- 真のバイリンガル環境
|
||||
|
||||
## ⚠️ 制限事項と課題
|
||||
|
||||
### 1. 完全な互換性は不可能
|
||||
- Pythonの動的機能すべては変換できない
|
||||
- 一部の構文は手動調整が必要
|
||||
|
||||
### 2. 意味論の違い
|
||||
```python
|
||||
# Pythonのデフォルト引数(定義時評価)
|
||||
def f(x, lst=[]):
|
||||
lst.append(x)
|
||||
return lst
|
||||
```
|
||||
|
||||
```nyash
|
||||
// Nyashでは毎回新しいリスト(異なる挙動)
|
||||
function f(x, lst) {
|
||||
if (lst == null) {
|
||||
lst = new ArrayBox()
|
||||
}
|
||||
lst.push(x)
|
||||
return lst
|
||||
}
|
||||
```
|
||||
|
||||
### 3. サポートレベルの明示
|
||||
```nyash
|
||||
// 生成されたファイルのヘッダー
|
||||
// Generated from Python by Nyash Transpiler v1.0
|
||||
// Original file: script.py
|
||||
// Conversion rate: 85% (15/17 functions transpiled)
|
||||
// Manual review recommended for: async_func, generator_func
|
||||
```
|
||||
|
||||
## 📊 実装フェーズ
|
||||
|
||||
### Phase 1.5: 基本トランスパイラ(Phase 1と並行)
|
||||
- [ ] NyashFormatter実装(AST → ソースコード)
|
||||
- [ ] 基本構文の出力(def, if, for, while)
|
||||
- [ ] インデント管理
|
||||
- [ ] コメント保持(可能な範囲で)
|
||||
|
||||
### Phase 2.5: 高度な変換
|
||||
- [ ] クラス → Box変換
|
||||
- [ ] 特殊メソッド → Nyashメソッド
|
||||
- [ ] import文の処理
|
||||
|
||||
### Phase 3.5: ツール化
|
||||
- [ ] コマンドラインツール
|
||||
- [ ] VSCode拡張機能
|
||||
- [ ] オンライン変換ツール
|
||||
|
||||
## 🎉 期待される効果
|
||||
|
||||
1. **Pythonエコシステムの資産をNyashネイティブ化**
|
||||
2. **パフォーマンスクリティカルな部分をNyash/MIR/JITで高速化**
|
||||
3. **両言語間のシームレスな相互運用**
|
||||
4. **Nyashの採用障壁を大幅に下げる**
|
||||
|
||||
---
|
||||
|
||||
これは**PythonParserBoxの価値をさらに高める**素晴らしい応用です!
|
||||
@ -1,94 +0,0 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
# Phase 10.1f - テストとベンチマーク
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
Differential Testingでバグを発見し、性能向上を検証する。
|
||||
|
||||
## 🧪 Differential Testing戦略
|
||||
|
||||
### 1. テストフレームワーク
|
||||
```rust
|
||||
pub fn differential_test(code: &str) -> TestResult {
|
||||
// CPythonで実行(オラクル)
|
||||
let python_result = capture_python_execution(code)?;
|
||||
|
||||
// Nyashで実行
|
||||
let nyash_result = execute_with_pythonparser(code)?;
|
||||
|
||||
// 結果比較
|
||||
compare_results(python_result, nyash_result)
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 比較項目
|
||||
- **標準出力** - print文の結果
|
||||
- **戻り値** - 関数の返す値
|
||||
- **例外** - エラーメッセージ(正規化後)
|
||||
- **副作用** - グローバル変数の変更等
|
||||
|
||||
### 3. テストコーパス
|
||||
```
|
||||
test_corpus/
|
||||
├── basic/ # 基本構文テスト
|
||||
├── stdlib/ # 標準ライブラリから抜粋
|
||||
├── pypi_top100/ # 人気ライブラリから抜粋
|
||||
└── edge_cases/ # エッジケース集
|
||||
```
|
||||
|
||||
## 📊 ベンチマーク
|
||||
|
||||
### 1. 性能測定対象
|
||||
```python
|
||||
# 数値計算ベンチマーク
|
||||
def mandelbrot(max_iter=100):
|
||||
# フラクタル計算
|
||||
pass
|
||||
|
||||
# ループベンチマーク
|
||||
def sum_of_primes(n):
|
||||
# 素数の和
|
||||
pass
|
||||
|
||||
# 再帰ベンチマーク
|
||||
def ackermann(m, n):
|
||||
# アッカーマン関数
|
||||
pass
|
||||
```
|
||||
|
||||
### 2. 測定項目
|
||||
- **実行時間** - CPython vs Nyash
|
||||
- **メモリ使用量** - 最大/平均
|
||||
- **コンパイル時間** - AST変換時間
|
||||
- **フォールバック率** - 関数別統計
|
||||
|
||||
## 🐛 バグ発見と報告
|
||||
|
||||
### 発見されたバグの例
|
||||
```
|
||||
[BUG-001] for/else semantics mismatch
|
||||
Python: else executed when no break
|
||||
Nyash: else never executed
|
||||
Fixed in: commit abc123
|
||||
|
||||
[BUG-002] Division operator difference
|
||||
Python: 5/2 = 2.5 (float)
|
||||
Nyash: 5/2 = 2 (integer)
|
||||
Fixed in: commit def456
|
||||
```
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] Differential Testingフレームワークが動作する
|
||||
- [ ] 基本的なテストコーパスが準備されている
|
||||
- [ ] 10個以上のバグを発見・修正
|
||||
- [ ] ベンチマークで2倍以上の高速化を確認
|
||||
- [ ] CI/CDパイプラインに統合されている
|
||||
|
||||
## 📈 成功の測定
|
||||
- **カバレッジ率**: 70%以上の関数がコンパイル
|
||||
- **性能向上**: 純Pythonループで2-10倍
|
||||
- **バグ発見数**: Phase毎に10件以上
|
||||
- **テスト成功率**: 95%以上
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1g (ドキュメント作成)
|
||||
@ -1,102 +0,0 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
# Phase 10.1g - ドキュメントとリリース準備
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
PythonParserBoxの使い方を文書化し、コミュニティに公開する準備をする。
|
||||
|
||||
## 📚 作成するドキュメント
|
||||
|
||||
### 1. ユーザーガイド
|
||||
- **Getting Started** - 最初の一歩
|
||||
- **Python互換性ガイド** - サポートされる構文
|
||||
- **トランスパイラー使用法** - Python→Nyash変換
|
||||
- **トラブルシューティング** - よくある問題と解決法
|
||||
|
||||
### 2. API リファレンス
|
||||
```nyash
|
||||
// PythonParserBox API
|
||||
box PythonParserBox {
|
||||
// Python code → JSON AST
|
||||
parse_to_json(code: String) -> String
|
||||
|
||||
// JSON AST → Nyash AST
|
||||
json_to_nyash_ast(json: String) -> AstBox
|
||||
|
||||
// Python code → Nyash source
|
||||
to_nyash_source(code: String) -> String
|
||||
|
||||
// 直接実行(関数単位フォールバック)
|
||||
run(code: String) -> Box
|
||||
|
||||
// 変換統計
|
||||
get_conversion_stats() -> MapBox
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 移行ガイド
|
||||
- **段階的移行戦略** - Pythonプロジェクトの移行手順
|
||||
- **パフォーマンスチューニング** - ホットパスの最適化
|
||||
- **ベストプラクティス** - 推奨される使い方
|
||||
|
||||
### 4. 内部設計ドキュメント
|
||||
- **アーキテクチャ** - 全体設計
|
||||
- **関数単位フォールバック** - 実装詳細
|
||||
- **GIL管理** - pyo3との統合
|
||||
- **テレメトリー** - 統計収集の仕組み
|
||||
|
||||
## 🎬 デモとチュートリアル
|
||||
|
||||
### 1. 動画チュートリアル
|
||||
- 5分で分かるPythonParserBox
|
||||
- Python→Nyash移行実演
|
||||
- パフォーマンス比較デモ
|
||||
|
||||
### 2. サンプルプロジェクト
|
||||
```
|
||||
examples/
|
||||
├── hello_python/ # 最小限の例
|
||||
├── data_analysis/ # データ分析の移行例
|
||||
├── web_api/ # WebAPIの移行例
|
||||
└── benchmarks/ # ベンチマーク比較
|
||||
```
|
||||
|
||||
## 📣 リリース準備
|
||||
|
||||
### 1. リリースノート作成
|
||||
```markdown
|
||||
# PythonParserBox v1.0 リリース!
|
||||
|
||||
## 🎉 新機能
|
||||
- Python AST → Nyash AST変換
|
||||
- 関数単位フォールバック
|
||||
- Python→Nyashトランスパイラー
|
||||
- Differential Testing
|
||||
|
||||
## 📊 パフォーマンス
|
||||
- 純Pythonループ: 2-10倍高速化
|
||||
- 数値計算: 5倍以上の改善
|
||||
- メモリ効率: 30%削減
|
||||
|
||||
## 🐛 発見されたバグ
|
||||
- Nyashパーサー: 15件修正
|
||||
- セマンティクス: 8件修正
|
||||
```
|
||||
|
||||
### 2. ブログ記事
|
||||
- 「なぜPythonParserBoxを作ったのか」
|
||||
- 「Differential Testingの威力」
|
||||
- 「Everything is Boxの新たな展開」
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] ユーザーガイドが完成している
|
||||
- [ ] APIリファレンスが完成している
|
||||
- [ ] サンプルプロジェクトが動作する
|
||||
- [ ] リリースノートが準備されている
|
||||
- [ ] CI/CDでの自動テストが通る
|
||||
|
||||
## 🎯 Phase 10.1の完了!
|
||||
これでPythonParserBoxの最初のリリースが完成!
|
||||
|
||||
## ⏭️ 次の展開
|
||||
→ Phase 10.2 (Phase 2機能の実装) または Phase 10.x (他言語対応)
|
||||
@ -1,53 +0,0 @@
|
||||
# Phase 10.5a – Python 統合 ABI 設計(Draft)
|
||||
|
||||
目的: Everything is Plugin/AOT の既存基盤上に Python を最小リスクで統合するための ABI と型・メソッド定義を固定する。
|
||||
|
||||
## スコープ(10.5a)
|
||||
- v2 プラグイン ABI 準拠(`nyash_plugin_abi/init/invoke`)の Python プラグイン雛形を作成
|
||||
- 2 Box を定義: `PyRuntimeBox(type_id=40)`, `PyObjectBox(type_id=41)`
|
||||
- メソッド ID の割り当てと TLV 方針を文書化(実装は 10.5b 以降)
|
||||
|
||||
## TLV マッピング(現行運用)
|
||||
- 1 = Bool (1 byte)
|
||||
- 2 = I32 (4 bytes, LE)
|
||||
- 3 = I64 (8 bytes, LE)
|
||||
- 4 = F32 (4 bytes, LE)
|
||||
- 5 = F64 (8 bytes, LE)
|
||||
- 6 = String (UTF-8, n bytes)
|
||||
- 7 = Bytes (opaque, n bytes)
|
||||
- 8 = Handle/BoxRef (`u32 type_id || u32 instance_id`)
|
||||
|
||||
備考: 既存ドキュメントには古い表記の混在があるため、VM_README 準拠で統一。
|
||||
|
||||
## Box とメソッド設計
|
||||
|
||||
### PyRuntimeBox (type_id=40)
|
||||
- birth(0): ランタイムの生成(後続で GIL 初期化などを担当)。戻り値: `instance_id`(非 TLV, u32 LE)
|
||||
- eval(1, code: String): Python コードを評価して `PyObjectBox` を返す。戻り値: `Handle(tag=8)`
|
||||
- import(2, name: String): `__import__(name)` または `importlib.import_module`。戻り値: `Handle(tag=8)`
|
||||
- fini(MAX): ランタイム破棄(GIL 終了・クリーンアップ)
|
||||
|
||||
### PyObjectBox (type_id=41)
|
||||
- birth(0): 予約(通常は runtime 側から生まれる)
|
||||
- getattr(1, name: String): 属性取得 → `Handle(tag=8)`
|
||||
- call(2, args: TLV...): 可変長引数。初期段は I64/String/Bool/Bytes/Handle のサブセットに限定。戻り値: `Handle(tag=8)`
|
||||
- str(3): Python 側で `PyObject_Str` → String へ。戻り値: `String(tag=6)`
|
||||
- fini(MAX): 参照カウント `Py_DECREF` に対応(後続)
|
||||
|
||||
## 参照管理・GIL(概要)
|
||||
- GIL: birth/invoke/fini の入口で確保し、出口で解放(再入を許容)。
|
||||
- 参照: `PyObjectBox` は生成時に `INCREF`、`fini` で `DECREF`。ランタイム終了時に孤立検知の簡易テストを導入。
|
||||
|
||||
## 設定ファイル(nyash.toml)
|
||||
- `libnyash_python_plugin.so` を 2 Box 含む形で登録(path/type_id/method_id を固定)
|
||||
- JIT/VM 側は既存の `plugin_invoke` 経由で呼び出し(AOT は 10.5d で `libnyrt.a` にシム追加)
|
||||
|
||||
## 次フェーズ(10.5b 以降)
|
||||
- 10.5b: `PyRuntimeBox`/`PyObjectBox` 実装(CPython 埋め込み、最小 RO 経路)
|
||||
- 10.5c: Python→Nyash 方向(CPython 拡張 `nyashrt`)
|
||||
- 10.5d: JIT/AOT 連携(`emit_plugin_invoke` 対応・静的リンクシム)
|
||||
- 10.5e: サンプル・テスト・ドキュメント
|
||||
|
||||
---
|
||||
|
||||
補足: 本ドキュメントは「設計の固定」を目的とし、実装は段階的に進める。タグ/ID は既存と衝突しない値を選定した(40/41)。
|
||||
@ -1,37 +0,0 @@
|
||||
# 10.5b – ネイティブビルド基盤の固め(AOT/EXE)
|
||||
|
||||
Python統合を本格化する前に、配布可能なネイティブ実行ファイル(EXE)の足回りを先に完成させる。JITは実行エンジンから外し、EXE生成専用のコンパイラとして運用する。
|
||||
|
||||
## 🎯 目的
|
||||
- VM=実行、JIT=EXE(AOT)の二系統を明確化(フォールバックなし/Fail-Fast)
|
||||
- CLIF→.o→`libnyrt`リンク→EXEのパイプラインを実効化
|
||||
- プラグイン解決をクロスプラットフォームに(.so/.dll/.dylib、自動lib剥がし、検索パス)
|
||||
- Windowsを含む実用的な配布体験を整備
|
||||
|
||||
## 🧩 範囲
|
||||
- JIT分離・Strict運用(Fail-Fast/No-fallback)
|
||||
- AOTパイプライン: `--compile-native` と `tools/build_aot.{sh,ps1}`
|
||||
- プラグインローダの拡張: 拡張子変換/`lib`剥がし、`plugin_paths`+`NYASH_PLUGIN_PATHS`
|
||||
- Windowsリンク: clang優先(`nyrt.lib`/`libnyrt.a`両対応)、bash+cc fallback
|
||||
- 観測/EXE出力の統一: `Result: <val>`、終了コード=<val>
|
||||
|
||||
## ✅ 成果(DoD)
|
||||
- `cargo build --release --features cranelift-jit` の後、
|
||||
- Linux: `./tools/build_aot.sh examples/aot_min_string_len.hako -o app && ./app`
|
||||
- Windows: `powershell -ExecutionPolicy Bypass -File tools\build_aot.ps1 -Input examples\aot_min_string_len.hako -Out app.exe && .\app.exe`
|
||||
- プラグインは `.so` 記述でも各OSで自動解決(.dll/.dylib へ変換、lib剥がし)
|
||||
- `tools/smoke_aot_vs_vm.sh` で VM/EXE の `Result:` 行比較が可能(差異は警告表示)
|
||||
|
||||
## 🔧 実装メモ
|
||||
- `src/runtime/plugin_loader_v2.rs` に `resolve_library_path()` を追加:
|
||||
- OS別拡張子、Windowsの`lib`剥がし、`plugin_paths`探索
|
||||
- `src/config/nyash_toml_v2.rs` に `NYASH_PLUGIN_PATHS` を追加(`;`/`:`区切り)
|
||||
- `AotConfigBox` に `set_plugin_paths()` 追加(env同期)
|
||||
- `crates/nyrt` の EXE出力統一(`Result:`/exit code)
|
||||
- Windows: `tools/build_aot.ps1`(clang→bash fallback)、Linux: `tools/build_aot.sh`
|
||||
|
||||
## 📌 次(10.5c 以降)
|
||||
- PyRuntimeBox/PyObjectBox(RO優先)
|
||||
- Python ABIルータを `libnyrt` に同梱(type_id→invokeディスパッチ)
|
||||
- 配布用パッケージ整備(nyash.toml/プラグイン配置ガイドの最終化)
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
# Phase 10.5c — Handle-First PluginInvoke 設計(最優先計画)
|
||||
|
||||
目的: Python専用の型伝搬を撤廃し、プラグイン呼び出しを「Everything is Handle」で統一。Lowererは箱名や戻り型に依存しない最小知識で `PluginInvoke` を実Emitし、型解決は実行時(TLV/Handle)に委譲する。
|
||||
|
||||
## 背景と問題
|
||||
- 現状のLowererに「import/getattr/call の戻りを PyObjectBox とみなす」暫定コードが混入。これは Python 特化のハードコーディングで、将来のプラグイン拡張(File/Net/DB 等)にブレーキとなる。
|
||||
- すでに ABI/VM は TLV tag=8(Handle)を標準化。戻り値を Handle として受け取り、タイプ情報(type_id)は実行時に判明する。
|
||||
|
||||
## 原則(Handle-First)
|
||||
- すべてのプラグインメソッドの戻りは Handle(TLV: tag=8)またはプリミティブ(i64/f64/bool/string/bytes)。
|
||||
- Lowerer は「戻り型が box かどうか」だけを気にすればよい。個々の箱名(PyObjectBox 等)を前提にしない。
|
||||
- 型の詳細は `type_id` によって実行時に解決される。JIT/AOT は型非依存の汎用コード生成を行う。
|
||||
|
||||
## 設計
|
||||
1) メタデータ駆動
|
||||
- `nyash_box.toml` の `methods.*.returns = { type = "box" | "i64" | "f64" | "string" | "void" | ... }` を単一の参照源に。
|
||||
- `PluginHost.resolve_method` に `returns.type` を含む情報を公開(Lowerer から参照)。
|
||||
|
||||
2) Lowerer の汎用化
|
||||
- `PluginInvoke` を常に `emit_plugin_invoke(type_id, method_id, argc, has_ret)` に落とす。
|
||||
- 「戻りが box のときに特定箱名を記録する」実装を撤去。必要なら「dst は Handle(box)」のヒントのみ保持。
|
||||
- 受け手箱名が未確定の場合に備え、by-name 経路(後述)を用意。
|
||||
|
||||
3) by-name シム(任意→推奨)
|
||||
- `nyrt`/builder に `nyash_plugin_invoke_by_name_{i64,f64}(box_type_name?, method_name, a0, a1, a2)` を追加。
|
||||
- 受け手の箱名が Lowerer 時点で特定できない場合、by-name シムを使用して実行時に `method_id` を解決。
|
||||
|
||||
4) 実行時の統一
|
||||
- 既存の `nyash_plugin_invoke3_{i64,f64}` と同様に、TLVで引数を構築。Handle/プリミティブ変換(StringBox/IntegerBoxの自動プリミティブ化)を継続。
|
||||
- 戻りTLVの tag を見て i64/f64 経由の値化(`NYASH_JIT_NATIVE_F64`)またはハンドル登録を行う。
|
||||
|
||||
## マイルストーン
|
||||
- M1: Lowerer から Python特化の型伝搬を除去(dst=Handle ヒントのみ)。
|
||||
- M2: `PluginHost.resolve_method` 拡張で `returns.type` を取得可能に。
|
||||
- M3: by-name シムの追加と Lowerer 配線(箱名未確定時)。
|
||||
- M4: AOT 最小ケース(import→getattr→call)を Handle-First で Green。
|
||||
- M5: ドキュメントと CURRENT_TASK を刷新。
|
||||
|
||||
## 受け入れ条件(DoD)
|
||||
- VM: `py.import("math"); (math.getattr("sqrt")).call(9)` が Green(autodecode=1 で 3)。
|
||||
- AOT(strict): 上記チェーン最小例で unsupported=0。Console 出力経路は PluginInvoke または extern 経由で表示。
|
||||
- Lowerer に Python 固有の型分岐が存在しない(grepで検出不可)。
|
||||
|
||||
## 運用メモ
|
||||
- 将来的な最適化(箱名が静的に分かる場面での特殊化)は、Handle-First を壊さない範囲で「分岐の1箇所」に限定して導入する。
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
# Phase 10.5 – Index (Active vs Archived)
|
||||
|
||||
このフォルダは Python ネイティブ統合とネイティブビルド基盤のための現行計画(10.5系)と、旧計画(10.1系:アーカイブ)を併置しています。迷った場合は「Active」を参照してください。
|
||||
|
||||
## Active(現行)
|
||||
- 10.5 README(全体像): ./README.md
|
||||
- 10.5a – Python ABI 設計: ./10.5a-ABI-DESIGN.md
|
||||
- 10.5b – ネイティブビルド基盤: ./10.5b-native-build-consolidation.md
|
||||
- 現在フォーカス: MIR→VM→ネイティブビルド(AOT/EXE)を先に堅牢化
|
||||
- 10.5c – Handle-First PluginInvoke / PyRuntimeBox / PyObjectBox(次段)
|
||||
- 10.5d – JIT/AOT 統合(予定)
|
||||
- 10.5e – サンプル / テスト / ドキュメント(予定)
|
||||
|
||||
## Archived(旧10.1系・参照用)
|
||||
- chatgpt5 統合計画(旧称 Phase 10.1): ./chatgpt5_integrated_plan.md
|
||||
- 10.1a_planning ~ 10.1g_documentation 各READMEと資料
|
||||
- 10.1c / 10.1d は「PythonをNyashで動かすフェーズ」の設計・実装メモです(順番変更により後段へ)。
|
||||
|
||||
整理方針:
|
||||
- Active ドキュメントに計画と用語を集約。旧10.1系は背景情報として参照のみ。
|
||||
- 実装の優先は「必要最小の箱(PyRuntimeBox / PyObjectBox)」→ 後から最適化。
|
||||
@ -1,110 +0,0 @@
|
||||
# Phase 10.5 – ネイティブ基盤固め + Python ネイティブ統合
|
||||
*(旧10.1の一部を後段フェーズに再編。まずネイティブ/AOT基盤を固め、その上でPythonを統合する方針に整理)*
|
||||
|
||||
このフォルダの全体像と最新の導線は INDEX を参照してください:
|
||||
- INDEX: ./INDEX.md(Active と Archived の区分とリンク集)
|
||||
|
||||
本フェーズでは方針を明確化する:実行はVMが唯一の基準系、JITは「EXE/AOT生成専用のコンパイラ」として分離運用する。
|
||||
|
||||
アーキテクチャの整理(決定)
|
||||
- 開発/デバッグ: MIR → VM(完全実行)
|
||||
- 本番/配布: MIR → JIT(CLIF)→ OBJ → EXE(完全コンパイル)
|
||||
|
||||
ポイント
|
||||
- フォールバック不要/禁止: JITが未対応ならコンパイルエラー。VMへは落とさない。
|
||||
- 役割分担の明確化: VM=仕様/挙動の唯一の基準、JIT=ネイティブ生成器。
|
||||
- プラグイン整合: VM/EXEとも同一のBID/FFIプラグインを利用(Everything is Plugin)。
|
||||
|
||||
## 📂 サブフェーズ構成(10.5s → 10.5e)
|
||||
|
||||
先行タスク(最優先)
|
||||
- 10.5s JIT Strict/分離の確定(Fail-Fast / ノーフォールバック) [DONE]
|
||||
- 目的: 「VM=実行・JIT=コンパイル」の二系統で混在を排除し、検証を単純化
|
||||
- 仕様:
|
||||
- JITは実行経路から外し、`--compile-native`(AOT)でのみ使用
|
||||
- Lowerer/Engine: unsupported>0 または fallback判定>0 でコンパイル中止(Fail-Fast)
|
||||
- 実行: VMのみ。フォールバックという概念自体を削除
|
||||
- DoD:
|
||||
- CLIに `--compile-native` を追加し、OBJ/EXE生成が一発で通る
|
||||
- VM実行は常にVMのみ(JITディスパッチ既定OFF)。
|
||||
|
||||
### 10.5a(Python)設計・ABI整合(1–2日)
|
||||
- ルート選択:
|
||||
- Embedding: NyashプロセスにCPythonを埋め込み、PyObject*をハンドル管理
|
||||
- Extending: Python拡張モジュール(nyashrt)を提供し、PythonからNyashを呼ぶ
|
||||
- ABI方針:
|
||||
- ハンドル: TLV tag=8(type_id+instance_id)。Pythonオブジェクトは `PyObjectBox` として格納
|
||||
- 変換: Nyash ⇄ Python で Bool/I64/String/Bytes/Handle を相互変換
|
||||
- GIL: birth/invoke/decRef中はGIL確保。AOTでも同等
|
||||
|
||||
### 10.5b ネイティブビルド基盤の固め(AOT/EXE)(2–4日)
|
||||
- 目的: Python統合の前に、AOT/EXE配布体験・クロスプラットフォーム実行の足回りを先に完成させる
|
||||
- 範囲:
|
||||
- VMとJITの分離(JIT=EXE専用)とStrict運用の徹底
|
||||
- AOTパイプラインの実働(CLIF→.o→libnyrtリンク→EXE)
|
||||
- プラグイン解決のクロスプラットフォーム化(.so/.dll/.dylib、自動lib剥がし、検索パス)
|
||||
- Windowsビルド/リンク(clang優先、MSYS2/WSL fallback)
|
||||
- EXE出力の統一(`Result: <val>`)とスモークテスト
|
||||
- DoD:
|
||||
- Linux/Windowsで `--compile-native` が通り、`plugins/` のDLL/so/dylibを自動解決
|
||||
- `tools/build_aot.{sh,ps1}` で配布しやすいEXEが生成される
|
||||
- `tools/smoke_aot_vs_vm.sh` でVM/EXEの出力照合が可能
|
||||
|
||||
### 10.5c PyRuntimeBox / PyObjectBox 実装(3–5日)
|
||||
- `PyRuntimeBox`(シングルトン): `eval(code) -> Handle` / `import(name) -> Handle`
|
||||
- `PyObjectBox`: `getattr(name) -> Handle` / `call(args...) -> Handle` / `str() -> String`
|
||||
- 参照管理: `Py_INCREF`/`Py_DECREF` をBoxライフサイクル(fini)に接続
|
||||
- プラグイン化: `nyash-python-plugin`(cdylib/staticlib)で `nyplug_python_invoke` を提供(将来の静的同梱に対応)
|
||||
|
||||
追加方針(10.5c Handle-First/TLV 統一)
|
||||
- Lowerer は Handle-First を徹底(a0 は常に `nyash.handle.of(receiver)`)。
|
||||
- 引数TLVは String/Integer をプリミティブ化、その他は Handle(tag=8) に統一。
|
||||
- 受け手箱名が未確定な経路には by-name シムを導入(後方安全の回避路)。
|
||||
- 参考: `docs/reference/abi/ffi_calling_convention_min.md`
|
||||
|
||||
### 10.5c 境界の双方向化(3–5日)
|
||||
- Nyash→Python: BoxCall→plugin_invokeでCPython C-APIに橋渡し
|
||||
- Python→Nyash: `nyashrt`(CPython拡張)で `nyash.call(func, args)` を提供
|
||||
- エラーハンドリング: 例外は文字列化(tag=6)でNyashに返却、またはResult化
|
||||
|
||||
### 10.5d JIT/AOT 統合(3–5日)
|
||||
- AOTパイプライン固定: Lower→CLIF→OBJ出力→`ny_main`+`libnyrt.a`リンク→EXE
|
||||
- CLI: `nyash --compile-native file.hako -o app` を追加(失敗は非ゼロ終了)
|
||||
- libnyrt: `nyash.python.*` 等のシムを提供し、未解決シンボル解決
|
||||
- ディスパッチ: type_id→`nyplug_*_invoke` の静的/動的ルート(第一段は動的優先)
|
||||
|
||||
### 10.5e サンプル/テスト/ドキュメント(1週間)
|
||||
- サンプル: `py.eval("'hello' * 3").str()`、`numpy`の軽量ケース(import/shape参照などRO中心)
|
||||
- テスト: GILの再入・参照カウントリーク検知・例外伝搬・多プラットフォーム
|
||||
- ドキュメント: 使用例、制約(GIL/スレッド)、AOT時のリンク・ランタイム要件
|
||||
|
||||
追加済みサンプル(最小チェーン)
|
||||
- VM: `examples/py_min_chain_vm.hako`(import→getattr→call→println)
|
||||
- AOT: `examples/aot_py_min_chain.hako`(import→getattr→call→return)
|
||||
|
||||
## 🎯 DoD(定義)
|
||||
- NyashからPythonコードを評価し、PyObjectをHandleで往復できる
|
||||
- 代表的なプロパティ取得/呼び出し(RO)がJIT/VMで動作
|
||||
- AOTリンク後のEXEで `py.eval()` 代表例が起動できる(動的ロード前提)
|
||||
- 10.5s Strict: VM=仕様/JIT=高速実装の原則に基づき、フォールバック無しで fail-fast が機能
|
||||
|
||||
## ⌛ 目安
|
||||
| サブフェーズ | 目安 |
|
||||
|---|---|
|
||||
| 10.5a 設計 | 1–2日 |
|
||||
| 10.5b 実装 | 3–5日 |
|
||||
| 10.5c 双方向 | 3–5日 |
|
||||
| 10.5d JIT/AOT | 3–5日 |
|
||||
| 10.5e 仕上げ | 1週間 |
|
||||
|
||||
## ⚠️ リスクと対策
|
||||
- GILデッドロック: 入口/出口で厳格に確保/解放。ネスト呼び出しの方針を文書化
|
||||
- 参照カウント漏れ: BoxライフサイクルでDECREFを必ず実施、リークテストを追加
|
||||
- リンク/配布: Linux/macOS優先。WindowsのPythonリンクは後段で対応
|
||||
- 性能: RO先行でJITに寄せ、ミューテーションはポリシー制御
|
||||
|
||||
---
|
||||
|
||||
注: 旧10.1系の資料(10.1a〜g, chatgpt5_integrated_plan.md)は背景情報として残置(Archived)。現行の実装計画と用語は本READMEと 10.5a/b に集約します。
|
||||
|
||||
次は 10.5a(設計・ABI整合)から着手。Everything is Plugin / libnyrt シムの成功パターンをPythonにも適用し、最小リスクで“Pythonネイティブ”を実現する。
|
||||
@ -1,244 +0,0 @@
|
||||
# [Archived] 旧 Phase 10.1 - Python統合計画(ChatGPT5高速開発版)
|
||||
最終更新: 2025-08-27 / 状態: Archived(Phase 10.5 に統合)
|
||||
|
||||
現行の計画は Phase 10.5 のドキュメントに集約しています。最新は以下を参照してください:
|
||||
- Phase 10.5 Index: ./INDEX.md
|
||||
- 10.5a – Python ABI 設計: ./10.5a-ABI-DESIGN.md
|
||||
- 10.5b – ネイティブビルド基盤: ./10.5b-native-build-consolidation.md
|
||||
|
||||
## 🚀 概要:2週間での爆速実装(当時案)
|
||||
|
||||
ChatGPT5の最小Box設計により、元の1ヶ月計画を**2週間**に圧縮。Nyash既存アーキテクチャ(MirBuilder 100%実装済み、HandleRegistry 80%実装済み)を最大活用。
|
||||
|
||||
## 📦 ChatGPT5の6つの必須Box(最小実装)
|
||||
|
||||
### 1. **PythonParserBox** - CPython AST取得(3日)
|
||||
```rust
|
||||
// 既存: pyo3統合済み
|
||||
// 追加: JSON出力とバージョン固定
|
||||
pub struct PythonParserBox {
|
||||
base: BoxBase,
|
||||
py_helper: Arc<Mutex<PyHelper>>,
|
||||
version: String, // "3.11"固定
|
||||
}
|
||||
|
||||
// メソッド(最小限)
|
||||
- parse_to_json(src: String) -> String // ast.parse() → JSON
|
||||
- get_version() -> String // "3.11"
|
||||
```
|
||||
|
||||
### 2. **Py2NyASTBox** - AST変換(3日)
|
||||
```rust
|
||||
// 新規実装
|
||||
pub struct Py2NyASTBox {
|
||||
base: BoxBase,
|
||||
normalizer: AstNormalizer,
|
||||
}
|
||||
|
||||
// メソッド(制御フロー正規化)
|
||||
- convert(json: String) -> NyashAst
|
||||
- normalize_for_else(ast: &mut PyAst) // for/else → if分岐
|
||||
- normalize_comprehensions(ast: &mut PyAst)
|
||||
```
|
||||
|
||||
### 3. **MirBuilderBox** - MIR生成(0日 - 既存活用)
|
||||
```rust
|
||||
// 既存実装100%活用
|
||||
// 追加: Python由来フラグのみ
|
||||
pub struct MirBuilderBox {
|
||||
// 既存フィールド
|
||||
is_python_origin: bool, // 追加
|
||||
}
|
||||
```
|
||||
|
||||
### 4. **BoundaryBox** - 型変換(2日)
|
||||
```rust
|
||||
// Python版のHandleRegistry相当
|
||||
pub struct BoundaryBox {
|
||||
base: BoxBase,
|
||||
handle_registry: Arc<Mutex<HandleRegistry>>, // 既存80%活用
|
||||
}
|
||||
|
||||
// メソッド
|
||||
- py_to_jit(py_val: PyValBox) -> JitValue
|
||||
- jit_to_py(jit_val: JitValue) -> PyValBox
|
||||
- register_handle(obj: Arc<dyn NyashBox>) -> u64
|
||||
```
|
||||
|
||||
### 5. **PyRuntimeBox** - 実行制御(2日)
|
||||
```rust
|
||||
pub struct PyRuntimeBox {
|
||||
base: BoxBase,
|
||||
fallback_stats: FallbackStats,
|
||||
}
|
||||
|
||||
// メソッド(関数単位フォールバック)
|
||||
- execute_function(name: &str, args: Vec<JitValue>) -> JitValue
|
||||
- should_fallback(func_ast: &PyAst) -> bool // Phase1機能判定
|
||||
- fallback_to_cpython(code: &str) -> PyObject
|
||||
```
|
||||
|
||||
### 6. **ObservabilityBox** - 統計収集(1日)
|
||||
```rust
|
||||
// 既存のJIT統計システム(70%実装済み)を拡張
|
||||
pub struct ObservabilityBox {
|
||||
base: BoxBase,
|
||||
stats_collector: StatsCollector,
|
||||
}
|
||||
|
||||
// JSONLフォーマット出力
|
||||
- log_attempt(module: &str, func: &str, compiled: bool, reason: Option<&str>)
|
||||
- output_jsonl() -> String
|
||||
```
|
||||
|
||||
## 🗓️ 実装タイムライン(2週間)
|
||||
|
||||
### Week 1: 基盤実装(7日)
|
||||
- **Day 1-3**: PythonParserBox実装
|
||||
- pyo3統合(既存活用)
|
||||
- Python 3.11固定
|
||||
- JSON出力実装
|
||||
|
||||
- **Day 4-6**: Py2NyASTBox実装
|
||||
- 制御フロー正規化
|
||||
- for/else, while/else変換
|
||||
- Phase1機能のみサポート
|
||||
|
||||
- **Day 7**: ObservabilityBox実装
|
||||
- 既存JIT統計拡張
|
||||
- JSONLフォーマット
|
||||
|
||||
### Week 2: 統合と検証(7日)
|
||||
- **Day 8-9**: BoundaryBox実装
|
||||
- HandleRegistry活用
|
||||
- 型変換ルール確立
|
||||
|
||||
- **Day 10-11**: PyRuntimeBox実装
|
||||
- 関数単位フォールバック
|
||||
- CPython連携
|
||||
|
||||
- **Day 12-13**: 統合テスト
|
||||
- Differential Testing
|
||||
- ベンチマーク実行
|
||||
|
||||
- **Day 14**: ドキュメント・リリース
|
||||
- 使用例作成
|
||||
- パフォーマンス測定
|
||||
|
||||
## 📊 既存アーキテクチャとの整合性
|
||||
|
||||
### 活用率
|
||||
- **MirBuilderBox**: 100%(変更なし)
|
||||
- **HandleRegistry**: 80%(BoundaryBoxで再利用)
|
||||
- **JIT統計**: 70%(ObservabilityBoxで拡張)
|
||||
- **VM/JIT実行**: 100%(そのまま使用)
|
||||
|
||||
### 新規実装
|
||||
- **PythonParserBox**: 30%(pyo3部分は既存)
|
||||
- **Py2NyASTBox**: 100%新規
|
||||
- **PyRuntimeBox**: 100%新規
|
||||
|
||||
## 🎯 Phase 1でサポートする機能(Codex先生推奨)
|
||||
|
||||
### 必須実装
|
||||
1. **LEGB + locals/freevars** - スコーピング規則
|
||||
2. **デフォルト引数の評価タイミング** - 定義時評価
|
||||
3. **イテレータベースのfor文**
|
||||
4. **for/else + while/else**
|
||||
5. **Python真偽値判定**
|
||||
6. **短絡評価**
|
||||
|
||||
### サポートする文
|
||||
- def(関数定義)
|
||||
- if/elif/else
|
||||
- for(else節対応)
|
||||
- while(else節対応)
|
||||
- break/continue
|
||||
- return
|
||||
|
||||
### サポートする式
|
||||
- 算術演算子(+,-,*,/,//,%)
|
||||
- 比較演算子(==,!=,<,>,<=,>=)
|
||||
- 論理演算子(and,or,not)
|
||||
- 関数呼び出し
|
||||
- リテラル(数値/文字列/bool)
|
||||
|
||||
## 📈 成功指標(2週間後)
|
||||
|
||||
### 定量的
|
||||
- **関数コンパイル率**: 70%以上(Phase 1機能)
|
||||
- **実行速度**: 純Pythonループで2倍以上
|
||||
- **メモリ効率**: CPython比50%削減
|
||||
|
||||
### 定性的
|
||||
- **統計可視化**: JSONL形式で全実行を記録
|
||||
- **デバッグ容易性**: 関数単位でフォールバック理由明示
|
||||
- **将来拡張性**: Phase 2-4への明確な道筋
|
||||
|
||||
## 🔧 実装例(最終形)
|
||||
|
||||
```nyash
|
||||
// Nyashから使用
|
||||
local py = new PythonParserBox()
|
||||
local converter = new Py2NyASTBox()
|
||||
local builder = new MirBuilderBox()
|
||||
local runtime = new PyRuntimeBox()
|
||||
local stats = new ObservabilityBox()
|
||||
|
||||
// Pythonコードをコンパイル・実行
|
||||
local code = "def fib(n): return n if n <= 1 else fib(n-1) + fib(n-2)"
|
||||
local json_ast = py.parse_to_json(code)
|
||||
local ny_ast = converter.convert(json_ast)
|
||||
local mir = builder.build(ny_ast)
|
||||
|
||||
// 実行(自動的にJIT/VMで高速化)
|
||||
local result = runtime.execute_function("fib", [10])
|
||||
print(result) // 55
|
||||
|
||||
// 統計出力
|
||||
print(stats.output_jsonl())
|
||||
// {"mod":"test","func":"fib","attempt":1,"jitted":true,"native":true}
|
||||
```
|
||||
|
||||
## 🚨 重要な設計判断
|
||||
|
||||
### 1. 関数単位の境界
|
||||
- ファイル単位ではなく**関数単位**でコンパイル/フォールバック
|
||||
- 未対応機能を含む関数のみCPython実行
|
||||
|
||||
### 2. Python 3.11固定
|
||||
- AST安定性の確保
|
||||
- 将来のバージョンアップは別Phase
|
||||
|
||||
### 3. 箱境界の明確化
|
||||
- 各Boxは単一責任
|
||||
- 相互依存を最小化
|
||||
- テスト可能な粒度
|
||||
|
||||
### 4. 既存資産の最大活用
|
||||
- MirBuilder/VM/JITはそのまま使用
|
||||
- 新規実装は変換層のみ
|
||||
|
||||
## 🎉 期待される成果
|
||||
|
||||
### 即時的効果(2週間後)
|
||||
- Pythonコードの70%がNyashで高速実行
|
||||
- バグ検出力の飛躍的向上(Differential Testing)
|
||||
- 統計による最適化ポイントの可視化
|
||||
|
||||
### 長期的効果
|
||||
- Python→Nyash→Native の世界初パイプライン確立
|
||||
- Nyash言語の成熟度向上
|
||||
- エコシステムの爆発的拡大
|
||||
|
||||
## 📝 次のステップ
|
||||
|
||||
1. **Phase 10.7完了確認** - JIT統計JSONの安定化
|
||||
2. **PythonParserBox実装開始** - pyo3統合から着手
|
||||
3. **テストコーパス準備** - Python標準ライブラリから抜粋
|
||||
|
||||
---
|
||||
|
||||
**作成者**: Claude(Claude Code)
|
||||
**承認者**: ChatGPT5(予定)
|
||||
**開始予定**: Phase 10.7完了直後
|
||||
@ -1,87 +0,0 @@
|
||||
# Phase 10.6 計画(整理版 / txt)
|
||||
|
||||
目的: Thread-Safety(監査→仕込み)と協調スケジューラ(Safepoint連携)を最小構成で通し、次段の並列GC/並列実行に備える。
|
||||
|
||||
====================
|
||||
1) ゴール(DoD)
|
||||
====================
|
||||
- 10.6a: Thread-Safety Audit の完了(一次)
|
||||
- NyashBox/Runtime の共有戦略(Arc+RwLock/Mutex)を棚卸し、未整備箇所はTODO化
|
||||
- Plugin-First 前提(PluginBoxV2 はクロススレッド未サポ運用を明記)
|
||||
- 10.6b: 協調スケジューラの足場
|
||||
- SingleThreadScheduler(queue + delayed + poll)を Safepoint に接続済み
|
||||
- デモ/トレース(NYASH_SCHED_DEMO=1, NYASH_SCHED_TRACE=1, 予算NYASH_SCHED_POLL_BUDGET)で観測可
|
||||
- 10.6c: 並列GC 設計の下準備
|
||||
- Per-thread roots / Safepoint協調 / カードマーキングの設計メモを確定(段階導入方針)
|
||||
|
||||
====================
|
||||
2) スコープ
|
||||
====================
|
||||
- 実装は“最小で通す”に限定(最適化は後続)。
|
||||
- 既存のVM=仕様、JIT=AOT生成専用という原則は維持。
|
||||
- Python/Plugin 経路は Plugin-First/Handle-First/TLV 統一の上に載せる(10.5で固定済)。
|
||||
|
||||
====================
|
||||
3) サブフェーズとタスク
|
||||
====================
|
||||
3.1) 10.6a Thread-Safety Audit(1–2日)
|
||||
- ドキュメント: phase-10/phase_10_6a_thread_safety_audit.md(既存)に一次棚卸しを反映
|
||||
- Grepチェック: Arc/Mutex/RwLock/Send/Sync の確認と未整備箇所の列挙
|
||||
- 確認対象:
|
||||
- ArrayBox/MapBox/BufferBox の共有戦略(Arc<RwLock<...>>)
|
||||
- NyashRuntime メンバのSend+Sync前提(Arcで包む)
|
||||
- Scheduler/GC Hooks のSend+Sync前提
|
||||
- PluginBoxV2: クロススレッド未サポ運用を明記(将来設計のTODO)
|
||||
|
||||
3.2) 10.6b Scheduler Prep(1–2日)
|
||||
- 仕様固定: poll() を MIR Safepoint で呼ぶ(既実装の確認)
|
||||
- 観測: NYASH_SCHED_DEMO=1 / NYASH_SCHED_TRACE=1 / NYASH_SCHED_POLL_BUDGET で動作確認
|
||||
- 最小API: spawn/spawn_after/poll/yield_now(SingleThreadScheduler)
|
||||
- ドキュメント: phase-10/phase_10_6b_scheduler_prep.txt 更新(Trace/観測例追加済)
|
||||
|
||||
3.3) 10.6c Parallel GC Design(2–3日)
|
||||
- 設計メモ: phase-10/phase_10_6c_parallel_gc_design.txt(既存)を最終化
|
||||
- 方針:
|
||||
- Per-thread roots, Safepoint協調、カードマーキングの段階導入
|
||||
- デフォルトは単一スレッド継続(featureで並列ON)
|
||||
- API拡張は後方互換シムを用意(barrier引数拡張など)
|
||||
|
||||
====================
|
||||
4) 成果物(Artifacts)
|
||||
====================
|
||||
- Docs
|
||||
- 10.6a 監査メモ: phase-10/phase_10_6a_thread_safety_audit.md(一次棚卸し完了)
|
||||
- 10.6b スケジューラ: phase-10/phase_10_6b_scheduler_prep.txt(Trace/デモ手順)
|
||||
- 10.6c 並列GC設計: phase-10/phase_10_6c_parallel_gc_design.txt(確定版)
|
||||
- Code
|
||||
- src/runtime/scheduler.rs(SingleThreadScheduler / Send+Sync)
|
||||
- MIR Safepoint → VM Runtime.scheduler.poll()(済)
|
||||
|
||||
====================
|
||||
5) リスクと緩和
|
||||
====================
|
||||
- 共有の粒度: 競合を避けるため、Box内部は最小限のロックで運用(RwLock優先)。
|
||||
- 並列前倒しの誘惑: 10.6では並列化を“設計と足場”に限定、実実装は次フェーズ(feature)
|
||||
- Plugin/FFI: クロススレッド呼出しは明示的に非対応(ドキュメントで制約明記)。
|
||||
|
||||
====================
|
||||
6) タイムライン(目安)
|
||||
====================
|
||||
- 10.6a: 1–2日
|
||||
- 10.6b: 1–2日
|
||||
- 10.6c: 2–3日
|
||||
|
||||
====================
|
||||
7) 依存関係
|
||||
====================
|
||||
- 10.5 完了(AOT/nyrt/Handle-First/TLV統一/Strict運用)を前提
|
||||
- Docsの最新導線: docs/private/roadmap2/phases/phase-10.5/INDEX.md
|
||||
|
||||
====================
|
||||
8) 参照リンク
|
||||
====================
|
||||
- phase-10/phase_10_6_thread_safe_revolution.md(設計準備)
|
||||
- phase-10/phase_10_6a_thread_safety_audit.md(監査)
|
||||
- phase-10/phase_10_6b_scheduler_prep.txt(スケジューラ)
|
||||
- phase-10/phase_10_6c_parallel_gc_design.txt(並列GC)
|
||||
|
||||
@ -1,79 +0,0 @@
|
||||
# Phase 10.6 → Pythonネイティブ接続プラン(整理版 / txt)
|
||||
|
||||
目的: 10.6で整えたThread-Safety/Schedulerの最小足場の上に、Pythonプラグイン(PyRuntimeBox/PyObjectBox)をネイティブEXE(AOT)まで安定接続する。
|
||||
|
||||
====================
|
||||
1) 到達イメージ(DoD)
|
||||
====================
|
||||
- Linux/Windows で以下が安定動作:
|
||||
- AOT: `examples/aot_py_min_chain.hako` → `Result: 4`(math.sqrt(16))
|
||||
- VM: `examples/py_min_chain_vm.hako` → 4.0 表示(NYASH_PY_AUTODECODE=1)
|
||||
- returns_result 系サンプル(importR/getattrR/callR)で Ok/Err が期待通りに表示
|
||||
- AOTビルドの配布体験が明確:
|
||||
- `tools/build_aot.{sh,ps1}` で .o → EXE、`nyash.toml`/plugins 解決、Windowsでは PATH/PYTHONHOME 調整
|
||||
- 配布ガイド(依存コピー/環境変数/動作確認手順)が `docs/guides/build/aot_quickstart.md` に追記済み
|
||||
|
||||
====================
|
||||
2) 方針(変えない原則)
|
||||
====================
|
||||
- Plugin-First / Handle-First / TLV 統一(String/Integerはプリミティブ、Bufferはbytes(tag=7)、他はHandle(tag=8))。
|
||||
- Strict: 実行はVM、JITはAOT生成専用(フォールバック禁止)。
|
||||
- by-name経路: 受け手箱名未確定時は `nyash_plugin_invoke_name_{getattr,call}_i64` で実行時解決。
|
||||
|
||||
====================
|
||||
3) 実装タスク(M1→M5)
|
||||
====================
|
||||
M1: AOT最小ルートの安定(完了確認/微修正)
|
||||
- nyrt シム:BufferBox→bytes(tag=7) 対応、3引数目以降をレガシーVM引数からTLV追補(暫定N引数)
|
||||
- Windows探索:EXE起動時に PATH へ exe/`plugins/` を追加、`PYTHONHOME` が未設定なら `exe\python` を採用(相対はexe基準に正規化)
|
||||
- ドキュメント:AOTクイックスタートにWindows注意点を追記(済)
|
||||
|
||||
M2: TLV/FFIカバレッジ拡大(最小)
|
||||
- kwargs/辞書のパス(callKwR)をbytes(tag=7) or string(tag=6, JSON)で暫定対応(将来 BID-1拡張)
|
||||
- N引数の一般化(invoke3→invokeN 設計、実装は段階導入。先行はレガシー補完で可)
|
||||
- returns_result の統一処理(VM既存→AOTでも同等に扱う)
|
||||
|
||||
M3: Lowerer/Policy の整流
|
||||
- Handle-First統一の確認:Python特化の型伝搬は撤去済み(戻りはHandle or プリミティブのみ参照)
|
||||
- birth引数の一般化(TLVメモに沿い、Integer/Stringはプリミティブ、他はHandle)
|
||||
- by-name の適用範囲と導線(`getattr`/`call` はby-name固定、importはmethod_id直参照)
|
||||
|
||||
M4: 配布導線とサンプル
|
||||
- スクリプト整備:`tools/build_python_aot.sh` の統合(`build_aot.sh` に一本化 or ラッパー)
|
||||
- サンプル最小化:returns_result(Ok/Err)、例外伝搬(Error文字列)、bytes引数、context共有(per-runtime globals)
|
||||
- ガイド整理:`docs/guides/build/aot_quickstart.md` に「Pythonネイティブ」節を追加(動作要件・環境変数)
|
||||
|
||||
M5: 観測/CI(軽量)
|
||||
- スモーク:VMチェーン / AOTチェーンの比較(Result行)を `tools/smoke_aot_vs_vm.sh` に追加(Python系は最小のみ)
|
||||
- ログ:`NYASH_JIT_EVENTS*`/`NYASH_JIT_NATIVE_F64`/`NYASH_PY_AUTODECODE` による差分観測
|
||||
|
||||
====================
|
||||
4) リスク/制約
|
||||
====================
|
||||
- CPython依存の配布:WindowsのDLL探索(PATH/PYTHONHOME)は最小整備。完全同梱(embedded)は後段で検討。
|
||||
- KW/辞書のTLV表現:暫定はbytes/stringでブリッジ。正式BIDタグは将来導入(後方互換のためJSON連携を許容)。
|
||||
- ネイティブN引数:v0はレガシーVM引数からのTLV補完でしのぎ、invokeNは次期導入。
|
||||
|
||||
====================
|
||||
5) タイムライン(目安)
|
||||
====================
|
||||
- M1(安定): 0.5日(確認/微修正)
|
||||
- M2(TLV拡充): 1–2日(kwargsは暫定・bytes/JSON)
|
||||
- M3(Lowerer整流): 0.5–1日
|
||||
- M4(配布/サンプル): 1日
|
||||
- M5(観測/CI): 0.5日
|
||||
|
||||
====================
|
||||
6) 成果物(Artifacts)
|
||||
====================
|
||||
- 例: `examples/aot_py_min_chain.hako`, `examples/py_min_chain_vm.hako`(既存)
|
||||
- ツール: `tools/build_aot.{sh,ps1}`(Python節)、`tools/smoke_aot_vs_vm.sh`(Python最小)
|
||||
- Docs: `docs/guides/build/aot_quickstart.md`(Python節)、`docs/reference/abi/ffi_calling_convention_min.md`(bytes/N引数注記)
|
||||
|
||||
====================
|
||||
7) 参照
|
||||
====================
|
||||
- 10.5c: Handle-First/PluginInvoke 設計(by-name シム)
|
||||
- 10.5d/e: AOT統合/最終仕上げ(nyrt/Windows探索/TLV拡張)
|
||||
- 10.6: Thread-Safety/Scheduler(並列化前の足場)
|
||||
|
||||
@ -1,114 +0,0 @@
|
||||
# Phase 10.7 – Python Native 再スタート計画(合意版 / txt)
|
||||
|
||||
目的: 現行の Plugin-First(PyRuntimeBox/PyObjectBox, Handle-First/TLV)を維持しつつ、トランスパイル路線(Python→Nyash)を“All or Nothing”原則で段階導入。10.6の足場(Thread-Safety/Scheduler)上で、AOT配布体験に直結する最短ラインを構築する。
|
||||
|
||||
====================
|
||||
A) 方針(判断)+ Property System革命統合(2025-09-18追加)
|
||||
====================
|
||||
- 二本立てを明確化:
|
||||
1) 実行系(現行): PyRuntimeBox 経由(VM=仕様、JIT=AOT生成のみ)。配布/運用の実用ライン。
|
||||
2) トランスパイル系(10.7): Python→Nyash→MIR→AOT。コンパイル成功/失敗の二択(フォールバック自動無し)。
|
||||
- 役割分担:未対応Pythonはユーザーが明示的に PyRuntimeBox を使う。トランスパイルはコンパイル成功率を段階的に拡大。
|
||||
- Plugin-Firstは維持(Parser/CompilerもプラグインBox化)。CLI/VMから統一呼び出し。
|
||||
|
||||
====================
|
||||
B) 最小成功像(Phase 1 / DoD)
|
||||
====================
|
||||
- サンプルpy(Phase 1 範囲内)を `pythonc`(仮)で Nyashスクリプトへ生成 → `--compile-native` で EXE 生成 → 実行。
|
||||
- 機能カバレッジ(Phase 1): def/if/for/while/return/bool/算術/比較/関数呼び出し/LEGB/デフォルト引数/for-else。
|
||||
- Differential(限定): Phase 1 サンプル群で CPython と一致(出力/戻り/例外の有無)。
|
||||
|
||||
====================
|
||||
C) サブフェーズとタスク
|
||||
====================
|
||||
C1) Parser Plugin(1週)
|
||||
- `plugins/nyash-python-parser-plugin`: Python→AST(pyo3)。
|
||||
- AST→CorePy IR(JSON): 構文の正規化(with→try/finally などはPhase 2)。
|
||||
- Telemetry: ノード統計/未対応ノードを列挙。
|
||||
|
||||
C2) Compiler Core(2週)
|
||||
- IR→Nyash AST 生成(Box化/クロージャ/LEGB/デフォ引数の再現)。
|
||||
- peephole最小(定数畳み込み)。
|
||||
- 生成NyashのPretty-print + 簡易ソースマップ。
|
||||
|
||||
C3) 配線/CLI/実行(3日)
|
||||
- `nyash --pyc file.py -o out.ny`(Nyash出力)/ `--pyc-native file.py -o app`(EXE直行)を追加(内部で既存 `--compile-native` を利用)。
|
||||
- 生成Nyashは既存コンパイラ経由で MIR→AOT を通す(Strict)。
|
||||
|
||||
C4) テスト/観測(1週並行)
|
||||
- `phase-10.7/testing-plan.md` の Phase 1 部分を小粒に実装。
|
||||
- VM vs AOT の「Result:」比較ラインを流用(既存スモークベース)。
|
||||
|
||||
====================
|
||||
D) インターフェース / 成果物
|
||||
====================
|
||||
- ParserBox: `parse(code: String) -> AstBox/CorePyBox`(内部JSON保持 or to_json)
|
||||
- CompilerBox: `compile(ir: CorePyBox) -> Result<NyashSourceBox, ErrorBox>`
|
||||
- CLI: `--pyc/--pyc-native`(初期は隠しフラグでも可)
|
||||
- Docs: README/implementation/testing-plan を PLAN に沿って更新。
|
||||
|
||||
====================
|
||||
E) リスク/緩和
|
||||
====================
|
||||
- 範囲膨張: Phase 1 の構文/意味論を固定し、Beyondは即Err。PyRuntimeBoxは明示利用。
|
||||
- 例外/with/comp/async: Phase 2/3の対象。IR設計時に将来ノードを予約(後方互換)。
|
||||
- Windows配布: 10.5で整えた PATH/PYTHONHOME 補助はPyRuntime向け。トランスパイル後はCPython依存なし。
|
||||
|
||||
====================
|
||||
F) タイムライン(目安)
|
||||
====================
|
||||
- C1: 1週 / C2: 2週 / C3: 3日 / C4: 1週(並行)。
|
||||
|
||||
====================
|
||||
G) 現行との接続
|
||||
====================
|
||||
- 10.6の足場(Thread-Safety/Scheduler)は維持。トランスパイル系は単一スレッド/VM基準で十分。
|
||||
- 10.5のAOT導線/nyrtシムはそのまま活用(生成Nyashに対して適用)。
|
||||
|
||||
====================
|
||||
H) Property System革命統合(2025-09-18 ブレイクスルー)
|
||||
====================
|
||||
|
||||
### 🌟 Python → Nyash Property マッピング革命
|
||||
|
||||
今日完成したProperty System(stored/computed/once/birth_once)により、Python transpilationが飛躍的に向上:
|
||||
|
||||
**Pythonプロパティの完全対応**:
|
||||
```python
|
||||
# Python側
|
||||
class PyClass:
|
||||
def __init__(self):
|
||||
self._value = 42
|
||||
|
||||
@property
|
||||
def computed_prop(self):
|
||||
return self._value * 2
|
||||
|
||||
@functools.cached_property
|
||||
def expensive_prop(self):
|
||||
return heavy_computation()
|
||||
```
|
||||
|
||||
**自動生成Nyash(革命的シンプル)**:
|
||||
```nyash
|
||||
box PyClass {
|
||||
_value: IntegerBox // stored: 通常フィールド
|
||||
computed_prop: IntegerBox { me._value * 2 } // computed: @property
|
||||
once expensive_prop: ResultBox { heavy_computation() } // once: @cached_property
|
||||
|
||||
birth() { me._value = 42 }
|
||||
}
|
||||
```
|
||||
|
||||
### 🎯 実装戦略更新
|
||||
- **C2フェーズ拡張**: PythonCompilerBoxにProperty System生成機能追加
|
||||
- **descriptor protocol**: Python property/method → Nyash property 4分類自動判定
|
||||
- **poison-on-throw**: cached_property例外時の安全性保証
|
||||
|
||||
### 📊 成功指標追加
|
||||
```
|
||||
Property coverage: @property(100%), @cached_property(100%), descriptors(80%)
|
||||
Performance boost: cached property 10-50x faster (LLVM最適化)
|
||||
Code generation: Python class → 50%短いNyashコード
|
||||
```
|
||||
|
||||
@ -1,286 +0,0 @@
|
||||
# Phase 10.7 - Python→Nyash革命(Phase 16マクロ統合版)
|
||||
|
||||
## 🚀 **Phase 16マクロ革命による劇的変化**
|
||||
|
||||
**Before Phase 16**: 手動transpiler(2-3ヶ月)
|
||||
**After Phase 16**: マクロボックス自動変換(1-2週間)⚡
|
||||
|
||||
### 🎯 新戦略:MacroBox-Driven Python Transpilation
|
||||
|
||||
```
|
||||
Python AST → MacroBox Pattern Match → Nyash AST (自動生成)
|
||||
```
|
||||
|
||||
**革命的変化**:
|
||||
- ❌ **旧**: 手動コード変換地獄(2000行実装)
|
||||
- ✅ **新**: マクロパターンで自動変換(200行実装)
|
||||
|
||||
## 🧠 **核心アイデア:Everything is Box + Macro = 言語統合**
|
||||
|
||||
### **マクロボックス群(新設計)**
|
||||
|
||||
```rust
|
||||
// src/macro/python_transpiler.rs(新規)
|
||||
@macro_box("python_dataclass")
|
||||
@macro_box("python_property")
|
||||
@macro_box("python_listcomp")
|
||||
@macro_box("python_contextmgr")
|
||||
@macro_box("python_decorator")
|
||||
```
|
||||
|
||||
### **実装例:Python @dataclass**
|
||||
|
||||
#### **Before(手動地獄)**:
|
||||
```python
|
||||
@dataclass
|
||||
class User:
|
||||
name: str
|
||||
age: int
|
||||
```
|
||||
→ 手動変換(数時間) → Nyashコード
|
||||
|
||||
#### **After(マクロ天国)**:
|
||||
```nyash
|
||||
// @python_dataclass マクロが自動処理!
|
||||
@python_dataclass
|
||||
box UserBox {
|
||||
name: StringBox
|
||||
age: IntegerBox
|
||||
}
|
||||
// ↓ 自動展開 ↓
|
||||
@derive(Equals, ToString, Clone)
|
||||
box UserBox {
|
||||
name: StringBox
|
||||
age: IntegerBox
|
||||
}
|
||||
```
|
||||
|
||||
### **実装例:Python List Comprehension**
|
||||
|
||||
#### **Python**:
|
||||
```python
|
||||
result = [x * 2 for x in numbers if x > 0]
|
||||
```
|
||||
|
||||
#### **マクロ展開Nyash**:
|
||||
```nyash
|
||||
// @python_listcomp マクロが自動生成
|
||||
local result = numbers
|
||||
.filter(|x| x > 0)
|
||||
.map(|x| x * 2)
|
||||
.toArray()
|
||||
```
|
||||
|
||||
## ⚠️ All or Nothing設計(フォールバックなし)
|
||||
|
||||
**コンパイルできる or できない の2択のみ**
|
||||
|
||||
```nyash
|
||||
compiler = new PythonCompilerBox()
|
||||
result = compiler.compile(ast)
|
||||
|
||||
if result.isOk() {
|
||||
// 100%コンパイル成功 → ネイティブ実行
|
||||
print("Success! Native execution ready.")
|
||||
} else {
|
||||
// 未対応機能あり → 完全拒否
|
||||
print("Cannot compile: " + result.getError())
|
||||
print("Use PyRuntimeBox instead.")
|
||||
}
|
||||
```
|
||||
|
||||
理由:開発時と本番時で挙動が変わるのは最悪の設計
|
||||
|
||||
## 📋 **新実装フェーズ(Phase 16統合版)**
|
||||
|
||||
### **Phase 10.7-A: MacroBox基盤(3日)**
|
||||
```rust
|
||||
// src/macro/python_transpiler.rs 作成
|
||||
pub fn register_python_macros() {
|
||||
register_macro_box("python_dataclass", PythonDataclassTranspiler);
|
||||
register_macro_box("python_property", PythonPropertyTranspiler);
|
||||
register_macro_box("python_listcomp", PythonListCompTranspiler);
|
||||
}
|
||||
```
|
||||
|
||||
### **Phase 10.7-B: コア変換パターン(1週間)**
|
||||
**必須マクロ(Phase 1)**:
|
||||
- `@python_dataclass` → `@derive(Equals,ToString)`
|
||||
- `@python_property` → `computed property`
|
||||
- `@python_listcomp` → `.filter().map()`
|
||||
- `@python_function` → Nyash関数+LEGB
|
||||
|
||||
### **Phase 10.7-C: テスト・検証(3日)**
|
||||
- マクロ展開結果の差分テスト
|
||||
- `nyash --expand` でPython→Nyash変換可視化
|
||||
- エラー時の明確な診断メッセージ
|
||||
|
||||
### **Phase 10.7-D: 高度パターン(1週間)**
|
||||
**拡張マクロ(Phase 2)**:
|
||||
- `@python_contextmgr` → try/finally自動展開
|
||||
- `@python_decorator` → マクロ適用チェーン
|
||||
- `@python_async` → async/await変換
|
||||
|
||||
## 🧪 py_runtime設計
|
||||
|
||||
```nyash
|
||||
// Pythonセマンティクスを忠実に再現
|
||||
box PyRuntime {
|
||||
py_truthy(x) {
|
||||
// Python的真偽値判定
|
||||
if x == null or x == false { return false }
|
||||
if x.hasMethod("__bool__") { return x.__bool__() }
|
||||
if x.hasMethod("__len__") { return x.__len__() != 0 }
|
||||
return true
|
||||
}
|
||||
|
||||
py_getattr(obj, name) {
|
||||
// ディスクリプタプロトコル、MRO探索
|
||||
}
|
||||
|
||||
py_call(f, args, kwargs) {
|
||||
// デフォルト引数、*args/**kwargs処理
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 **新成功指標(マクロ革命版)**
|
||||
|
||||
### **Phase 1完了時(2週間後)**
|
||||
```
|
||||
実装コスト: 2000行 → 200行 (90%削減)
|
||||
開発時間: 2-3ヶ月 → 1-2週間 (85%短縮)
|
||||
マクロパターン: 5個実装完了
|
||||
Python→Nyash変換率: 80%+ (基本構文)
|
||||
```
|
||||
|
||||
### **最終目標(1ヶ月後)**
|
||||
```
|
||||
マクロパターン: 15個+ (全主要Python構文)
|
||||
変換精度: 95%+ (property/dataclass/listcomp)
|
||||
パフォーマンス: 10-50x faster (LLVM最適化)
|
||||
統合性: Property System完全対応
|
||||
```
|
||||
|
||||
## 🚀 **クイックスタート(マクロ版)**
|
||||
|
||||
```bash
|
||||
# Phase 16マクロ基盤活用
|
||||
cd src/macro/
|
||||
touch python_transpiler.rs
|
||||
|
||||
# 最小マクロボックス実装
|
||||
[dependencies]
|
||||
nyash-rust = { path = "../../" }
|
||||
serde_json = "1.0"
|
||||
|
||||
# テスト実行(マクロ展開確認)
|
||||
NYASH_MACRO_ENABLE=1 ./target/release/nyash --expand python_test.ny
|
||||
```
|
||||
|
||||
## 🎯 **Property System統合戦略**
|
||||
|
||||
### **Python @property → Nyash computed**
|
||||
```python
|
||||
class Circle:
|
||||
@property
|
||||
def area(self):
|
||||
return 3.14 * self.radius ** 2
|
||||
```
|
||||
|
||||
**マクロ自動変換**:
|
||||
```nyash
|
||||
@python_property // マクロが自動処理
|
||||
box CircleBox {
|
||||
radius: FloatBox
|
||||
|
||||
// computed property自動生成
|
||||
area: FloatBox { 3.14 * me.radius * me.radius }
|
||||
}
|
||||
```
|
||||
|
||||
### **Python @cached_property → Nyash once**
|
||||
```python
|
||||
@cached_property
|
||||
def expensive_calculation(self):
|
||||
return heavy_computation()
|
||||
```
|
||||
|
||||
**マクロ自動変換**:
|
||||
```nyash
|
||||
// once property自動生成
|
||||
once expensive_calculation: ResultBox {
|
||||
heavyComputation()
|
||||
}
|
||||
```
|
||||
|
||||
## 💡 **創造的可能性(マクロ革命版)**
|
||||
|
||||
### **🎪 ハイブリッドプログラミング**
|
||||
```python
|
||||
@nyash.vectorize # PythonデコレータがNyashマクロ展開!
|
||||
@nyash.config_schema # 環境変数自動読み込み
|
||||
@nyash.api_client("https://api.example.com/swagger.json")
|
||||
class DataProcessor:
|
||||
def process(self, data):
|
||||
return self.api.process_batch(data)
|
||||
```
|
||||
|
||||
**マクロ展開後**:
|
||||
```nyash
|
||||
@vectorize @config_schema @api_client("...")
|
||||
box DataProcessorBox {
|
||||
// 全てマクロで自動生成!
|
||||
api_client: HttpBox { /* 自動生成 */ }
|
||||
config: ConfigBox { /* 環境変数から自動読み込み */ }
|
||||
|
||||
method process(data: ArrayBox) -> ResultBox {
|
||||
me.api.processBatch(data) // SIMD最適化済み
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **🌍 言語統合プラットフォーム**
|
||||
**Phase 16マクロシステムにより実現**:
|
||||
- 🐍 **Python** → 🦀 **Nyash**: 自動変換
|
||||
- ☕ **Java** → 🦀 **Nyash**: `@java_class`マクロで
|
||||
- 🟦 **TypeScript** → 🦀 **Nyash**: `@ts_interface`マクロで
|
||||
- 🔷 **C#** → 🦀 **Nyash**: `@csharp_property`マクロで
|
||||
|
||||
### **🎓 教育革命**
|
||||
**リアルタイム変換Playground**:
|
||||
```
|
||||
┌─ Python Input ─────┐ ┌─ Nyash Output ────┐
|
||||
│ @dataclass │ → │ @derive(...) │
|
||||
│ class User: │ │ box UserBox { │
|
||||
│ name: str │ │ name: StringBox │
|
||||
│ age: int │ │ age: IntegerBox │
|
||||
└────────────────────┘ └────────────────────┘
|
||||
```
|
||||
|
||||
**学習効果**:
|
||||
- プログラミング学習時間: **10分の1**
|
||||
- 言語間移植理解: **瞬時**
|
||||
- 最適化理解: **可視化**
|
||||
|
||||
## 📚 **参考資料(更新版)**
|
||||
|
||||
### **Phase 16統合ドキュメント**
|
||||
- **[Phase 16 Macro Revolution](../phase-16-macro-revolution/README.md)** - マクロシステム全体
|
||||
- **[docs/guides/macro-system.md](../../../../guides/macro-system.md)** - マクロ使用方法
|
||||
- **[Macro Examples](../phase-16-macro-revolution/macro-examples.md)** - 実装例集
|
||||
|
||||
### **従来資料**
|
||||
- **archive/gemini-analysis-transpile-beauty.md** - 創造性分析
|
||||
- **archive/codex-analysis-technical-implementation.md** - 技術分析
|
||||
|
||||
---
|
||||
|
||||
## 🏆 **結論:Phase 10.7の革命的変化**
|
||||
|
||||
**Before Phase 16**: Python実装 = 地獄の手動transpiler
|
||||
**After Phase 16**: Python実装 = 楽しいマクロパターン作成
|
||||
|
||||
**Phase 16マクロシステムにより、Phase 10.7は「Python実装」から「言語統合革命」へと進化した!**
|
||||
|
||||
**実装コスト90%削減、開発時間85%短縮で、10倍の表現力を実現する新時代の到来!** 🚀✨
|
||||
@ -1,252 +0,0 @@
|
||||
# Codex (GPT-5)の技術分析:Python→Nyashトランスパイルの実装詳細
|
||||
|
||||
2025-08-30 - OpenAI Codex v0.25.0による技術的深掘り
|
||||
|
||||
## Big Picture
|
||||
|
||||
- **Purpose**: Generate Nyash source from Python to leverage Nyash's optimizer, keep debugging simple, and "think in Nyash" early without locking into MIR details.
|
||||
- **Core idea**: Normalize Python to a small CorePy IR, then lower to idiomatic Nyash with a thin "Py runtime shim" in Nyash that preserves Python's dynamic semantics where required.
|
||||
|
||||
## AST Conversion
|
||||
|
||||
### Two-stage lowering
|
||||
```
|
||||
Python AST → CorePy IR → Nyash AST
|
||||
```
|
||||
|
||||
CorePy should be expression-friendly, desugared, and semantics-explicit (e.g., with→try/finally, for→iterator loop, boolean ops→if/else).
|
||||
|
||||
### Visitor + environment
|
||||
Implement a node visitor that carries scope info (locals/free/globals), evaluation order, and source spans. Use Python's `symtable` to seed symbol kinds; validate against your own pass.
|
||||
|
||||
### Semantic shims
|
||||
Lower Python ops to Nyash intrinsics that preserve semantics:
|
||||
- `py_truthy(x)`
|
||||
- `py_getattr(o,"a")`
|
||||
- `py_setattr(o,"a",v)`
|
||||
- `py_binop("add", a, b)`
|
||||
- `py_cmp("lt", a, b)`
|
||||
- `py_iter(x)`
|
||||
- `py_call(f, args, kwargs)`
|
||||
- `py_slice(x, i, j, k)`
|
||||
|
||||
### Boxes and cells
|
||||
Model Python variables and closures with Box/Cell objects. Rule of thumb: locals are unboxed unless captured or aliased; promote to Box when needed. Everything-is-Box in Nyash aligns well with Python's mutability/aliasing.
|
||||
|
||||
### Control flow
|
||||
Normalize to a small set: `if`, `block`, `loop`, `break`, `continue`, `try/catch/finally`, `throw`. Lower `and`/`or` with short-circuit temp; turn comprehensions into explicit loops with dedicated inner scope.
|
||||
|
||||
## Transpile Quality
|
||||
|
||||
### Readability vs optimize
|
||||
Offer modes. Default emits idiomatic Nyash constructs and meaningful identifiers, comments with source spans, and simple temporaries. "Optimize" mode switches to `py_*` intrinsics fusion and fewer temps.
|
||||
|
||||
### Idiomatic Nyash
|
||||
Prefer Nyash control constructs over procedural labels. Use native blocks for `if/else`, `match` if Nyash has it; only fall back to runtime calls where semantics demand.
|
||||
|
||||
### Stable pretty-printer
|
||||
Round-trip friendly formatter with consistent whitespace, trailing comma rules, and deterministic temp naming (`_t1`, `_t2…`). Keep def/class emitted in declaration-order.
|
||||
|
||||
### Debug info
|
||||
Attach `span(file, line, col)` to every IR node, carry through to Nyash AST, then emit a sidecar source map. Optionally embed lightweight `#line` directives or inline comments per statement in debug builds.
|
||||
|
||||
## Python Feature Mapping
|
||||
|
||||
### Default args
|
||||
Evaluate at def-time; store tuple/dict on the function object. At call-time, fill missing with stored defaults. Beware mutable defaults: do not clone; reuse exact object.
|
||||
|
||||
### LEGB scoping
|
||||
Build symbol table with flags for `global`/`nonlocal`. Emit closure "cells" (Boxes) for free vars; functions capture a vector of cells. Globals map to the module dict; builtins fallback when name miss in global.
|
||||
|
||||
### for/else, while/else
|
||||
Introduce `broken=false`. On `break`, set and exit; after loop, `if !broken { else_block }`.
|
||||
|
||||
### Comprehensions
|
||||
Create inner function/scope per comprehension (Python 3 semantics). Assignment targets exist only in that scope. Preserve evaluation order and late binding behavior.
|
||||
|
||||
### With statement
|
||||
Desugar to try/finally per Python spec: evaluate context expr, call `__enter__`, bind target, run body, always call `__exit__`, and suppress exception only if `__exit__` returns truthy.
|
||||
|
||||
### Decorators
|
||||
Evaluate bottom-up at def-time: `fn = decoN(...(deco1(fn)))` then assign back. Keep evaluation order of decorator expressions.
|
||||
|
||||
### Generators
|
||||
Lower to a state machine object implementing Nyash's iterator protocol, with saved instruction pointer, stack slots, and exception injection (`throw`, `close`). Support `yield from` by delegation trampoline.
|
||||
|
||||
### Pattern matching (PEP 634)
|
||||
If supported by Nyash, map directly; else lower to nested guards and extractor calls in a `py_match` helper library.
|
||||
|
||||
### Data model
|
||||
Attribute access honors descriptors; method binding creates bound objects; arithmetic and comparisons dispatch to `__op__`/`__rop__` and rich comparisons; truthiness via `__bool__`/`__len__`.
|
||||
|
||||
## Performance Opportunities
|
||||
|
||||
### At transpile-time
|
||||
- Constant fold literals, f-strings (format plan precomputation), simple arithmetic if types are literal.
|
||||
- Invariant hoisting for loop-invariant comprehensions and attribute chains when no side-effects (guarded).
|
||||
- Direct calls to Nyash intrinsics for selected builtins (`len`, `isinstance`, `range`) only if not shadowed (prove via symbol table).
|
||||
- Peephole: collapse nested `py_truthy(py_truthy(x))`, merge adjacent `if` with literal conditions, drop dead temporaries.
|
||||
|
||||
### Defer to Nyash compiler
|
||||
- Inlining across Nyash functions, register allocation, loop unrolling, vectorization, constant propagation at MIR level.
|
||||
- DCE/CSE once `py_*` helpers are inlined or annotated as pure/idempotent where legal.
|
||||
|
||||
### Types as hints
|
||||
- Consume Python annotations/`typing` to emit specialized fast paths: e.g., `int` → direct Nyash integer ops, else fallback to `py_binop`. Plumb types through IR as optional metadata for MIR to exploit.
|
||||
- Profile-guided guards: optional mode emits guards around hot calls to enable Nyash JIT/AOT to speculate and deopt to generic `py_*`.
|
||||
|
||||
## Error Handling & Debug
|
||||
|
||||
### Source maps
|
||||
Emit a compact mapping (e.g., VLQ JSON) from Nyash line/col → Python original; include segment mappings per expression for precise stepping.
|
||||
|
||||
### Exception rewriting
|
||||
Wrap Nyash runtime entrypoints to translate stack frames via the source map, hiding frames from helpers (`py_*`) unless verbose mode is on.
|
||||
|
||||
### Stage diagnostics
|
||||
- CorePy dump: toggle to print normalized IR with spans.
|
||||
- Nyash preview: post-format preview with original Python line hints.
|
||||
- Trace toggles: selective tracing of `py_call`, `py_getattr`, iteration; throttle to avoid noise.
|
||||
|
||||
### Friendly messages
|
||||
On unsupported nodes or ambiguous semantics, show minimal repro, Python snippet, and link to a doc page. Include symbol table excerpt when scoping fails.
|
||||
|
||||
## Architecture & DX
|
||||
|
||||
### Pass pipeline
|
||||
```
|
||||
Parse Python AST → Symbol table → Normalize to CorePy →
|
||||
Scope/closure analysis → Type/meta attach → Lower to Nyash AST →
|
||||
Optimize (peephole/simplify) → Pretty-print + source map
|
||||
```
|
||||
|
||||
### Runtime shim (`nyash/lib/py_runtime.ny`)
|
||||
Core APIs:
|
||||
- `py_call(f, pos, kw, star, dstar)`
|
||||
- `py_truthy(x)`
|
||||
- `py_getattr/py_setattr`
|
||||
- `py_binop(op, a, b)`
|
||||
- `py_cmp(op,a,b)`
|
||||
- `py_iter(x)`
|
||||
- `py_next(it)`
|
||||
- `py_slice(x,i,j,k)`
|
||||
- `py_with(mgr, body_fn)`
|
||||
- `py_raise`
|
||||
- `py_is`
|
||||
- `py_eq`
|
||||
|
||||
Data model support: descriptor get/set, method binding, MRO lookup, exception hierarchy, StopIteration protocol.
|
||||
|
||||
Perf annotations: mark pure or inline candidates; keep stable ABI.
|
||||
|
||||
### CLI/flags
|
||||
Modes:
|
||||
- `--readable`
|
||||
- `--optimized`
|
||||
- `--debug`
|
||||
- `--emit-sourcemap`
|
||||
- `--dump-corepy`
|
||||
- `--strict-builtins`
|
||||
|
||||
Caching: hash of Python AST + flags to cache Nyash output, source map, and diagnostics.
|
||||
|
||||
Watch/incremental: re-transpile changed modules, preserve source map continuity.
|
||||
|
||||
### Tests
|
||||
- Golden tests: Python snippet → Nyash output diff, with normalization.
|
||||
- Differential: run under CPython vs Nyash runtime for functional parity on a corpus (unit/property tests).
|
||||
- Conformance: edge cases (scoping, descriptors, generators, exceptions) and evaluation order tests.
|
||||
|
||||
## Pitfalls & Remedies
|
||||
|
||||
### Evaluation order
|
||||
Python's left-to-right arg eval, starred/unpacking, and kw conflict checks. Enforce by sequencing temps precisely before `py_call`.
|
||||
|
||||
### Shadowing builtins/globals
|
||||
Only specialize when proven not shadowed in any reachable scope. Provide `--strict-builtins` to disable specialization unless guaranteed.
|
||||
|
||||
### Identity vs equality
|
||||
`is` is reference identity; avoid folding or substituting.
|
||||
|
||||
### Integer semantics
|
||||
Python's bigints; ensure Nyash numeric layer matches or route to bigints in `py_*`.
|
||||
|
||||
## Future Extensibility
|
||||
|
||||
### Plugins
|
||||
Pass manager with hooks (`before_lower`, `after_lower`, `on_node_<Type>`). Allow project-local rewrites and macros, with access to symbol/type info.
|
||||
|
||||
### Custom rules
|
||||
DSL for pattern→rewrite with predicates (types, purity), e.g., rewrite `dataclass` patterns to Nyash records.
|
||||
|
||||
### Multi-language
|
||||
Keeping the Nyash script as a stable contract invites other frontends (e.g., a subset of JS/TypeScript or Lua) to target Nyash; keep `py_*` separate from language-agnostic intrinsics to avoid contamination.
|
||||
|
||||
### Gradual migration
|
||||
As Nyash grows Pythonic libraries, progressively replace `py_*` with native Nyash idioms; keep a compatibility layer for mixed projects.
|
||||
|
||||
## Concrete Translation Sketches
|
||||
|
||||
### Attribute
|
||||
```python
|
||||
a.b
|
||||
```
|
||||
→
|
||||
```nyash
|
||||
py_getattr(a, "b")
|
||||
```
|
||||
|
||||
### Call
|
||||
```python
|
||||
f(x, y=1, *as, **kw)
|
||||
```
|
||||
→
|
||||
```nyash
|
||||
py_call(f, [x], {"y":1}, as, kw)
|
||||
```
|
||||
|
||||
### If
|
||||
```python
|
||||
if a and b:
|
||||
```
|
||||
→
|
||||
```nyash
|
||||
let _t=py_truthy(a); if _t { if py_truthy(b) { ... } }
|
||||
```
|
||||
|
||||
### For/else
|
||||
```python
|
||||
for x in xs:
|
||||
if cond:
|
||||
break
|
||||
else:
|
||||
else_block
|
||||
```
|
||||
→
|
||||
```nyash
|
||||
let _it = py_iter(xs);
|
||||
let _broken=false;
|
||||
loop {
|
||||
let _n = py_next(_it) catch StopIteration { break };
|
||||
x = _n;
|
||||
...
|
||||
if cond { _broken=true; break }
|
||||
}
|
||||
if !_broken { else_block }
|
||||
```
|
||||
|
||||
### With
|
||||
Evaluate mgr, call `__enter__`, bind val; try body; on exception, call `__exit__(type,e,tb)` and suppress if returns true; finally call `__exit__(None,None,None)` when no exception.
|
||||
|
||||
### Decorators
|
||||
```nyash
|
||||
let f = <def>;
|
||||
f = decoN(...(deco1(f)));
|
||||
name = f
|
||||
```
|
||||
|
||||
## Why Nyash Script First
|
||||
|
||||
- **Debuggability**: Human-readable Nyash is easier to inspect, diff, and map errors to; source maps stay small and precise.
|
||||
- **Optimization leverage**: Nyash compiler/MIR can keep improving independently; your Python frontend benefits automatically.
|
||||
- **Ecosystem fit**: Generates idiomatic Nyash that other tools (formatters, linters, analyzers) can understand; fosters a consistent DX.
|
||||
@ -1,72 +0,0 @@
|
||||
# Gemini先生の分析:Python→Nyashトランスパイルの「面白さ」と「可能性」
|
||||
|
||||
2025-08-30 - Geminiによる深い洞察
|
||||
|
||||
## 1. 創造的な活用方法 - 「ハイブリッドプログラミング」の新しい形
|
||||
|
||||
このアプローチの最大の面白さは、**PythonとNyashの境界を曖昧にし、両者の長所を自在に組み合わせられる「ハイブリッドプログラミング」環境**が生まれる点にあります。
|
||||
|
||||
### パフォーマンスの「目利き」チューニング
|
||||
開発者はまず、書き慣れたPythonで迅速にプロトタイプを構築します。パフォーマンスが問題になる箇所だけ、トランスパイルされたNyashコードを覗き見ます。「なるほど、このリスト内包表記はこういうループになるのか。ここをNyashの並列処理機能に書き換えれば速くなりそうだ」といった具合に、**生成されたコードを"最適化のためのヒント"として活用**し、手動で高性能なNyashコードに置き換えることができます。これは、Pythonの手軽さとネイティブの速度を、開発者が主体的にコントロールできる、非常に楽しいプロセスです。
|
||||
|
||||
### Nyashを操るためのDSL(ドメイン固有言語)としてPythonを使う
|
||||
Pythonの強力なメタプログラミング能力(デコレータ、AST操作など)を使い、「Nyashコードジェネレータ」をPythonで記述できます。例えば、特定の計算パターンを最適化するNyashコードを生成するPythonデコレータを作るのはどうでしょう。
|
||||
|
||||
```python
|
||||
# このデコレータがNyashのSIMD命令を使うコードを生成する
|
||||
@nyash.vectorize
|
||||
def python_function(a, b):
|
||||
return a + b
|
||||
```
|
||||
|
||||
このように、Pythonの簡潔な記述から、裏では非常に複雑で高性能なNyashコードが生成される。これはまさに、**Pythonを「Nyashのための高級マクロ言語」として使う**創造的なハックです。
|
||||
|
||||
### 動的なコード生成と実行
|
||||
実行時にPythonコード文字列を生成し、それをNyashにトランスパイルして即座にネイティブ実行する、といった芸当も可能です。これにより、設定ファイルやユーザー入力に基づいて動的に高性能な処理ロジックを組み立てるような、柔軟なアプリケーションが実現できます。
|
||||
|
||||
## 2. 言語進化への影響 - 共進化するエコシステム
|
||||
|
||||
この方式は、一方的な変換ではなく、両言語が互いに影響を与え合う「共進化」の触媒となります。
|
||||
|
||||
### Nyashへのフィードバック
|
||||
Pythonの標準的なイディオム(例: `with`文、ジェネレータ、リスト内包表記)をNyashに変換する際、「どうもしっくりくる表現がNyashにない」「もっとエレガントに書ける構文が欲しい」という課題が必ず見つかります。これは、**Pythonという巨大なユースケースからNyashが学ぶ絶好の機会**です。このフィードバックループが、Nyashをより表現力豊かで実用的な言語へと進化させます。
|
||||
|
||||
### Pythonコミュニティへの影響
|
||||
「この書き方をすれば、Nyashで速くなる」という知見が広まると、Pythonプログラマーの中に**「Nyash-aware」なコーディングスタイル**が生まれる可能性があります。これは、Pythonのサブセットや方言のようなもので、パフォーマンスを意識した新しいPythonの書き方として定着するかもしれません。Pythonのコードが、静的解析や型ヒントだけでなく、「ネイティブ変換効率」という新しい評価軸を持つようになります。
|
||||
|
||||
## 3. 実装の優雅さ - 「AST to AST」という美しい設計
|
||||
|
||||
トランスパイラの内部実装そのものにも、開発者を楽しませるエレガントなパターンが存在します。
|
||||
|
||||
### AST(抽象構文木)レベルでの変換
|
||||
最もクリーンな実装は、Pythonの`ast`モジュールでソースコードをASTに変換し、そのASTの各ノードを再帰的に辿りながら、対応するNyashのASTノードを構築していく方法です。これは、文字列置換のような場当たり的な方法とは異なり、非常に構造的で堅牢です。Pythonの`for`ループのASTノードが、Nyashの`for`ループのASTノードに1対1で対応付けられる様は、パズルを解くような知的な面白さがあります。
|
||||
|
||||
### 変換パターンの分離と合成
|
||||
Pythonの各構文要素(関数定義、if文、クラスなど)に対応する変換ロジックを、それぞれ独立した小さな関数やクラスとして実装します。これにより、トランスパイラ全体の見通しが良くなり、テストも容易になります。新しい構文への対応も、新しい変換パターンを追加するだけで済みます。このモジュール性は、大規模なソフトウェアを設計する上での美しさそのものです。
|
||||
|
||||
## 4. 教育的インパクト - 生きた「コンパイラ入門」
|
||||
|
||||
このツールは、プログラミング学習者にとって最高の教材となり得ます。
|
||||
|
||||
### 概念の可視化
|
||||
「高級言語の裏側では、実際にはもっと低レベルな処理が行われている」というコンピュータサイエンスの基本概念を、これ以上なく明確に示せます。Pythonのたった1行が、Nyashの数行のコードに展開されるのを見ることで、抽象化のコストとメリットを直感的に理解できます。
|
||||
|
||||
### 言語間の「ロゼッタストーン」
|
||||
PythonとNyashという2つの言語の思考様式の違いを学ぶための、動的な「ロゼッタストーン」になります。「Pythonの辞書は、Nyashではハッシュマップとしてこう表現されるのか」「Pythonの動的型付けは、Nyashの型推論によってこう解決されるのか」といった発見は、学習者にとって大きな喜びとなるでしょう。
|
||||
|
||||
### インタラクティブな学習環境
|
||||
Web上で、左にPython、右にリアルタイムで変換されたNyashコードが表示されるような「Nyash Playground」を作れば、非常に人気の出る学習ツールになるはずです。
|
||||
|
||||
## 5. 長期的な展望 - 5年後、10年後の可能性
|
||||
|
||||
このアプローチは、短期的な実装の容易さだけでなく、長期的に大きな可能性を秘めています。
|
||||
|
||||
### 5年後: Pythonエコシステムのシームレスな高速化
|
||||
トランスパイラの完成度が高まり、主要なPythonライブラリ(NumPy, Pandasの一部など)をNyashに変換できるようになっているかもしれません。`pip install`するだけで、内部的にNyashへ変換・コンパイルされ、ユーザーは意識することなくPythonコードのままネイティブの速度を手に入れる、という未来が考えられます。Pythonの型ヒントが、単なる静的解析のためだけでなく、**Nyashへの最適化コンパイルのための重要なヒント**として活用されているでしょう。
|
||||
|
||||
### 10年後: 「ハイブリッド言語」としての地位確立
|
||||
PythonとNyashの関係は、TypeScriptとJavaScriptの関係に似たものになっているかもしれません。開発者は、プロジェクトの大部分をPythonで書き、パフォーマンスクリティカルな部分はNyashで書く、あるいはPythonで書いたものをトランスパイルして微調整する、という開発スタイルが当たり前になっている可能性があります。Nyashは「Pythonをネイティブ速度で動かすための最高のパートナー言語」としての地位を確立し、両言語は互いに補完し合う強力なエコシステムを形成しているでしょう。最終的には、**Pythonの書きやすさと、ネイティブコードの実行性能を両立させた、究極のスクリプト環境**が実現しているかもしれません。
|
||||
|
||||
## まとめ
|
||||
|
||||
B案(トランスパイル方式)は、単に技術的に堅実なだけでなく、開発者の知的好奇心を刺激し、言語コミュニティ全体を巻き込んで成長していく「面白さ」と「可能性」に満ちた選択です。生成されたNyashコードが「ブラックボックス」ではなく「ホワイトボックス」であることが、デバッグ、最適化、学習、そして未来の創造的なハックへと繋がる鍵となります。この選択は、Nyashプロジェクトの成功に大きく貢献する戦略的な一手だと確信します。
|
||||
@ -1,274 +0,0 @@
|
||||
# PythonCompilerBox Property System活用実装
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
Property System革命(stored/computed/once/birth_once)をPythonCompilerBoxで活用し、Python→Nyash transpilationを実現する技術実装設計。
|
||||
|
||||
## 🏗️ アーキテクチャ設計
|
||||
|
||||
### コアコンポーネント
|
||||
```nyash
|
||||
box PythonCompilerBox {
|
||||
// Property System を活用したコンパイラ実装
|
||||
classifier: PropertyClassifierBox
|
||||
generator: NyashCodeGeneratorBox
|
||||
validator: SemanticValidatorBox
|
||||
|
||||
// コンパイル結果のキャッシュ(once使用)
|
||||
once compilation_cache: MapBox { new MapBox() }
|
||||
|
||||
// 動的に計算される統計情報(computed使用)
|
||||
success_rate: FloatBox { me.get_success_statistics() }
|
||||
total_files_processed: IntegerBox { me.compilation_cache.size() }
|
||||
|
||||
birth() {
|
||||
me.classifier = new PropertyClassifierBox()
|
||||
me.generator = new NyashCodeGeneratorBox()
|
||||
me.validator = new SemanticValidatorBox()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧠 PropertyClassifierBox実装
|
||||
|
||||
```nyash
|
||||
box PropertyClassifierBox {
|
||||
// 分類ルールのキャッシュ(once)
|
||||
once classification_rules: RuleSetBox { load_classification_rules() }
|
||||
|
||||
// 統計情報(computed)
|
||||
classified_count: IntegerBox { me.get_classification_stats().count }
|
||||
accuracy_rate: FloatBox { me.get_classification_stats().accuracy }
|
||||
|
||||
classify_python_property(ast_node) {
|
||||
// Python AST → Property type 分類
|
||||
if me.has_decorator(ast_node, "@property") {
|
||||
if me.is_simple_computation(ast_node) {
|
||||
return "computed" // 単純計算 → computed
|
||||
} else {
|
||||
return "once" // 複雑処理 → キャッシュ推奨
|
||||
}
|
||||
}
|
||||
|
||||
if me.has_decorator(ast_node, "@functools.cached_property") {
|
||||
return "once" // 明示的キャッシュ
|
||||
}
|
||||
|
||||
if me.is_init_assignment(ast_node) {
|
||||
return "stored" // 通常フィールド
|
||||
}
|
||||
|
||||
if me.is_birth_once_candidate(ast_node) {
|
||||
return "birth_once" // 初期化時のみ評価
|
||||
}
|
||||
|
||||
return "unsupported" // Phase 2以降
|
||||
}
|
||||
|
||||
// ヒューリスティック判定
|
||||
is_simple_computation(node) {
|
||||
// 副作用なし+計算量小 → computed適合性判定
|
||||
return me.has_no_side_effects(node) and me.is_lightweight(node)
|
||||
}
|
||||
|
||||
is_birth_once_candidate(node) {
|
||||
// 初期化時のみ必要な重い処理を検出
|
||||
return me.called_in_init_only(node) and me.is_expensive(node)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🏭 NyashCodeGeneratorBox実装
|
||||
|
||||
```nyash
|
||||
box NyashCodeGeneratorBox {
|
||||
// テンプレートエンジン(once)
|
||||
once property_templates: TemplateEngineBox {
|
||||
load_property_templates()
|
||||
}
|
||||
|
||||
// 生成コード統計(computed)
|
||||
generated_lines: IntegerBox { me.count_generated_code_lines() }
|
||||
compression_ratio: FloatBox { me.calculate_compression_ratio() }
|
||||
|
||||
generate_property_declaration(property_info) {
|
||||
local template = me.property_templates.get(property_info.type)
|
||||
|
||||
// Property typeごとの生成
|
||||
peek property_info.type {
|
||||
"stored" => me.generate_stored_property(property_info),
|
||||
"computed" => me.generate_computed_property(property_info),
|
||||
"once" => me.generate_once_property(property_info),
|
||||
"birth_once" => me.generate_birth_once_property(property_info),
|
||||
else => throw UnsupportedPropertyError(property_info.type)
|
||||
}
|
||||
}
|
||||
|
||||
generate_computed_property(info) {
|
||||
// computed property テンプレート
|
||||
return info.name + ": " + info.type + " { " + info.expression + " }"
|
||||
}
|
||||
|
||||
generate_once_property(info) {
|
||||
// once property テンプレート(キャッシュ+例外安全)
|
||||
local code = "once " + info.name + ": " + info.type + " { " + info.expression + " }"
|
||||
|
||||
if info.has_exception_risk {
|
||||
code = code + " catch(ex) { poison(me." + info.name + ", ex); throw ex }"
|
||||
}
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
generate_birth_once_property(info) {
|
||||
// birth_once property テンプレート
|
||||
return "birth_once " + info.name + ": " + info.type + " { " + info.expression + " }"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔍 SemanticValidatorBox実装
|
||||
|
||||
```nyash
|
||||
box SemanticValidatorBox {
|
||||
// 検証ルール(once)
|
||||
once validation_rules: ValidationRuleSetBox {
|
||||
load_semantic_validation_rules()
|
||||
}
|
||||
|
||||
// 検証結果統計(computed)
|
||||
validation_success_rate: FloatBox { me.get_validation_stats().success_rate }
|
||||
error_categories: ArrayBox { me.get_validation_stats().error_types }
|
||||
|
||||
validate_property_semantics(python_ast, nyash_code) {
|
||||
local errors = new ArrayBox()
|
||||
|
||||
// 1. Property type一致性検証
|
||||
me.validate_property_type_consistency(python_ast, nyash_code, errors)
|
||||
|
||||
// 2. 例外安全性検証
|
||||
me.validate_exception_safety(python_ast, nyash_code, errors)
|
||||
|
||||
// 3. 性能特性検証
|
||||
me.validate_performance_characteristics(python_ast, nyash_code, errors)
|
||||
|
||||
return ValidationResult.new(errors)
|
||||
}
|
||||
|
||||
validate_property_type_consistency(python_ast, nyash_code, errors) {
|
||||
// Pythonの@propertyとNyashのcomputedが対応しているかチェック
|
||||
local python_properties = me.extract_python_properties(python_ast)
|
||||
local nyash_properties = me.extract_nyash_properties(nyash_code)
|
||||
|
||||
loop(python_properties.iter()) property {
|
||||
local expected_type = me.infer_nyash_property_type(property)
|
||||
local actual_type = nyash_properties.get(property.name).type
|
||||
|
||||
if expected_type != actual_type {
|
||||
errors.add(PropertyTypeMismatchError.new(property.name, expected_type, actual_type))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 統合ワークフロー
|
||||
|
||||
```nyash
|
||||
box PythonTranspilationWorkflow {
|
||||
compiler: PythonCompilerBox
|
||||
|
||||
birth() {
|
||||
me.compiler = new PythonCompilerBox()
|
||||
}
|
||||
|
||||
transpile_python_file(file_path) {
|
||||
// 1. Pythonファイル解析
|
||||
local python_ast = me.parse_python_file(file_path)
|
||||
|
||||
// 2. Property分類
|
||||
local classified_properties = me.compiler.classifier.classify_all_properties(python_ast)
|
||||
|
||||
// 3. Nyashコード生成
|
||||
local nyash_code = me.compiler.generator.generate_nyash_code(classified_properties)
|
||||
|
||||
// 4. セマンティック検証
|
||||
local validation_result = me.compiler.validator.validate_property_semantics(python_ast, nyash_code)
|
||||
|
||||
if validation_result.has_errors() {
|
||||
throw TranspilationError.new(validation_result.errors)
|
||||
}
|
||||
|
||||
// 5. コンパイル結果キャッシュ(once活用)
|
||||
me.compiler.compilation_cache.set(file_path, nyash_code)
|
||||
|
||||
return nyash_code
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 テスト実装例
|
||||
|
||||
```nyash
|
||||
box PropertySystemTranspilationTest {
|
||||
test_computed_property_generation() {
|
||||
local python_code = '''
|
||||
class TestClass:
|
||||
@property
|
||||
def doubled_value(self):
|
||||
return self.value * 2
|
||||
'''
|
||||
|
||||
local compiler = new PythonCompilerBox()
|
||||
local result = compiler.transpile(python_code)
|
||||
|
||||
assert result.contains("doubled_value: IntegerBox { me.value * 2 }")
|
||||
}
|
||||
|
||||
test_once_property_generation() {
|
||||
local python_code = '''
|
||||
class TestClass:
|
||||
@functools.cached_property
|
||||
def expensive_calc(self):
|
||||
return heavy_computation()
|
||||
'''
|
||||
|
||||
local compiler = new PythonCompilerBox()
|
||||
local result = compiler.transpile(python_code)
|
||||
|
||||
assert result.contains("once expensive_calc: ResultBox { heavy_computation() }")
|
||||
}
|
||||
|
||||
test_poison_on_throw_integration() {
|
||||
local python_code = '''
|
||||
class TestClass:
|
||||
@functools.cached_property
|
||||
def risky_operation(self):
|
||||
if random.random() < 0.1:
|
||||
raise ValueError("Failed")
|
||||
return success_result()
|
||||
'''
|
||||
|
||||
local compiler = new PythonCompilerBox()
|
||||
local result = compiler.transpile(python_code)
|
||||
|
||||
assert result.contains("catch(ex) { poison(me.risky_operation, ex); throw ex }")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 期待される効果
|
||||
|
||||
### 1. 実装効率の向上
|
||||
- Property System活用により、コンパイラ自体の実装がクリーン
|
||||
- once活用でコンパイルキャッシュ、computed活用で統計計算
|
||||
|
||||
### 2. 生成コードの高品質化
|
||||
- Python property → Nyash property の自然な1:1マッピング
|
||||
- poison-on-throw統合による例外安全性
|
||||
|
||||
### 3. 保守性の向上
|
||||
- Box化されたコンポーネント設計
|
||||
- 明確な責任分離(分類・生成・検証)
|
||||
|
||||
この設計により、Property System革命を最大限活用したPython transpilation実装が実現できます!
|
||||
@ -1,295 +0,0 @@
|
||||
# Python Native実装例
|
||||
|
||||
## 🎯 実装イメージ
|
||||
|
||||
### 使用例1: 基本的な関数のネイティブ化
|
||||
|
||||
```nyash
|
||||
// example1_basic.hako
|
||||
// Pythonコードをネイティブコンパイル
|
||||
|
||||
// Step 1: Pythonコードを用意
|
||||
code = """
|
||||
def fibonacci(n):
|
||||
if n <= 1:
|
||||
return n
|
||||
return fibonacci(n-1) + fibonacci(n-2)
|
||||
|
||||
def factorial(n):
|
||||
if n == 0:
|
||||
return 1
|
||||
return n * factorial(n-1)
|
||||
"""
|
||||
|
||||
// Step 2: パース
|
||||
parser = new PythonParserBox()
|
||||
ast = parser.parse(code)
|
||||
print("Parsed functions: " + parser.getStats().get("functions"))
|
||||
|
||||
// Step 3: コンパイル
|
||||
compiler = new PythonCompilerBox()
|
||||
mir_module = compiler.compile(ast)
|
||||
|
||||
// Step 4: 実行
|
||||
if mir_module.isOk() {
|
||||
// ネイティブ実行!
|
||||
module = mir_module.get()
|
||||
|
||||
// 関数を取得して実行
|
||||
fib = module.getFunction("fibonacci")
|
||||
result = fib.call(10)
|
||||
print("fibonacci(10) = " + result) // 55
|
||||
|
||||
fact = module.getFunction("factorial")
|
||||
result = fact.call(5)
|
||||
print("factorial(5) = " + result) // 120
|
||||
} else {
|
||||
print("Compilation failed: " + mir_module.getError())
|
||||
}
|
||||
```
|
||||
|
||||
### 使用例2: コンパイル可否の明確な判定
|
||||
|
||||
```nyash
|
||||
// example2_clear_separation.hako
|
||||
// コンパイルできるかどうか事前に判定
|
||||
|
||||
// Phase 1対応のコード
|
||||
code_phase1 = """
|
||||
def compute_sum(n):
|
||||
total = 0
|
||||
for i in range(n):
|
||||
total += i * i
|
||||
return total
|
||||
|
||||
def factorial(n):
|
||||
if n == 0:
|
||||
return 1
|
||||
return n * factorial(n-1)
|
||||
"""
|
||||
|
||||
// Phase 1未対応のコード
|
||||
code_unsupported = """
|
||||
def fibonacci_generator(n):
|
||||
a, b = 0, 1
|
||||
for _ in range(n):
|
||||
yield a
|
||||
a, b = b, a + b
|
||||
"""
|
||||
|
||||
// コンパイラーで判定
|
||||
parser = new PythonParserBox()
|
||||
compiler = new PythonCompilerBox()
|
||||
|
||||
// Phase 1対応コードのチェック
|
||||
ast1 = parser.parse(code_phase1)
|
||||
result1 = compiler.compile(ast1)
|
||||
if result1.isOk() {
|
||||
print("✅ Phase 1 code compiled successfully!")
|
||||
module = result1.get()
|
||||
print("compute_sum(100) = " + module.call("compute_sum", 100))
|
||||
} else {
|
||||
print("❌ Compilation failed: " + result1.getError())
|
||||
}
|
||||
|
||||
// 未対応コードのチェック
|
||||
ast2 = parser.parse(code_unsupported)
|
||||
result2 = compiler.compile(ast2)
|
||||
if result2.isOk() {
|
||||
print("✅ Compiled successfully!")
|
||||
} else {
|
||||
print("❌ Cannot compile: " + result2.getError())
|
||||
print(" Reason: yield expression not supported in Phase 1")
|
||||
print(" Please use PyRuntimeBox instead")
|
||||
}
|
||||
```
|
||||
|
||||
### 使用例3: プログレッシブ最適化
|
||||
|
||||
```nyash
|
||||
// example3_progressive.hako
|
||||
// 実行しながら徐々に最適化
|
||||
|
||||
// 型推論付きコンパイラー
|
||||
compiler = new PythonCompilerBox()
|
||||
compiler.enableTypeInference(true)
|
||||
compiler.enableProfiling(true)
|
||||
|
||||
// 初回実行(型情報収集)
|
||||
code = """
|
||||
def matrix_multiply(A, B):
|
||||
# 最初は型が不明
|
||||
result = []
|
||||
for i in range(len(A)):
|
||||
row = []
|
||||
for j in range(len(B[0])):
|
||||
sum = 0
|
||||
for k in range(len(B)):
|
||||
sum += A[i][k] * B[k][j]
|
||||
row.append(sum)
|
||||
result.append(row)
|
||||
return result
|
||||
"""
|
||||
|
||||
// プロファイル付き実行
|
||||
for i in range(5) {
|
||||
mir = compiler.compile(parser.parse(code))
|
||||
|
||||
// 実行してプロファイル収集
|
||||
module = mir.get()
|
||||
A = [[1, 2], [3, 4]]
|
||||
B = [[5, 6], [7, 8]]
|
||||
result = module.call("matrix_multiply", A, B)
|
||||
|
||||
// 型情報が蓄積される
|
||||
print("Iteration " + i + ": ")
|
||||
print(" Type confidence: " + compiler.getTypeConfidence())
|
||||
print(" Optimization level: " + compiler.getOptimizationLevel())
|
||||
}
|
||||
|
||||
// 5回実行後、完全に最適化されたコードが生成される
|
||||
```
|
||||
|
||||
### 使用例4: 言語間相互運用
|
||||
|
||||
```nyash
|
||||
// example4_interop.hako
|
||||
// PythonコードとNyashコードのシームレスな連携
|
||||
|
||||
// Pythonで数値計算関数を定義
|
||||
python_math = """
|
||||
import math
|
||||
|
||||
def distance(x1, y1, x2, y2):
|
||||
return math.sqrt((x2-x1)**2 + (y2-y1)**2)
|
||||
|
||||
def normalize(vector):
|
||||
magnitude = math.sqrt(sum(x**2 for x in vector))
|
||||
return [x/magnitude for x in vector]
|
||||
"""
|
||||
|
||||
// コンパイルしてNyashから使用
|
||||
module = compile_python(python_math)
|
||||
|
||||
// Nyash側のゲームロジック
|
||||
box GameObject {
|
||||
init { x, y, vx, vy }
|
||||
|
||||
update(dt) {
|
||||
// Python関数をネイティブ速度で呼び出し
|
||||
me.x = me.x + me.vx * dt
|
||||
me.y = me.y + me.vy * dt
|
||||
|
||||
// 正規化(Pythonの関数を使用)
|
||||
local normalized = module.normalize([me.vx, me.vy])
|
||||
me.vx = normalized[0]
|
||||
me.vy = normalized[1]
|
||||
}
|
||||
|
||||
distanceTo(other) {
|
||||
// Pythonの距離計算関数を使用
|
||||
return module.distance(me.x, me.y, other.x, other.y)
|
||||
}
|
||||
}
|
||||
|
||||
// 完全にネイティブコードとして実行される!
|
||||
```
|
||||
|
||||
### 使用例5: デバッグとプロファイリング
|
||||
|
||||
```nyash
|
||||
// example5_debug.hako
|
||||
// 開発時のデバッグ支援
|
||||
|
||||
// デバッグモード有効
|
||||
parser = new PythonParserBox()
|
||||
parser.enableDebug(true)
|
||||
|
||||
compiler = new PythonCompilerBox()
|
||||
compiler.enableDebug(true)
|
||||
compiler.enableSourceMap(true) // 元のPythonコードへのマッピング
|
||||
|
||||
problematic_code = """
|
||||
def buggy_function(items):
|
||||
total = 0
|
||||
for item in items:
|
||||
# バグ: itemが文字列の場合エラー
|
||||
total += item * 2
|
||||
return total / len(items)
|
||||
"""
|
||||
|
||||
// コンパイル試行
|
||||
result = compiler.compile(parser.parse(problematic_code))
|
||||
|
||||
if result.isErr() {
|
||||
// 詳細なエラー情報
|
||||
diag = compiler.getDiagnostics()
|
||||
print("Compilation failed at line " + diag.line)
|
||||
print("Issue: " + diag.message)
|
||||
print("Suggestion: " + diag.suggestion)
|
||||
|
||||
// フォールバックで実行してランタイムエラーを確認
|
||||
runtime = new PythonRuntimeBox()
|
||||
try {
|
||||
runtime.exec(problematic_code)
|
||||
runtime.call("buggy_function", ["a", "b", "c"])
|
||||
} catch (e) {
|
||||
print("Runtime error: " + e.message)
|
||||
print("This would have been caught at compile time!")
|
||||
}
|
||||
}
|
||||
|
||||
// プロファイリング情報
|
||||
profiler = new PythonProfiler()
|
||||
profiler.attach(module)
|
||||
profiler.run()
|
||||
|
||||
print("Hot spots:")
|
||||
print(profiler.getHotSpots())
|
||||
print("Type instability:")
|
||||
print(profiler.getTypeInstability())
|
||||
```
|
||||
|
||||
## 🎯 実装の進化
|
||||
|
||||
### Phase 1(現在)
|
||||
```python
|
||||
# これらがネイティブ化可能
|
||||
def add(x, y): return x + y
|
||||
def factorial(n): ...
|
||||
def fibonacci(n): ...
|
||||
```
|
||||
|
||||
### Phase 2(予定)
|
||||
```python
|
||||
# 特殊メソッド対応
|
||||
class Vector:
|
||||
def __add__(self, other): ...
|
||||
def __len__(self): ...
|
||||
|
||||
# 内包表記
|
||||
squares = [x**2 for x in range(10)]
|
||||
```
|
||||
|
||||
### Phase 3(将来)
|
||||
```python
|
||||
# 完全な言語機能
|
||||
async def fetch_data(): ...
|
||||
@decorator
|
||||
def enhanced_function(): ...
|
||||
yield from generator
|
||||
```
|
||||
|
||||
## 🚀 パフォーマンス期待値
|
||||
|
||||
```
|
||||
Benchmark: Fibonacci(30)
|
||||
CPython: 1.234s
|
||||
PyPy: 0.123s
|
||||
Nyash Native: 0.012s (100x faster!)
|
||||
|
||||
Benchmark: Matrix Multiplication (100x100)
|
||||
CPython: 5.678s
|
||||
NumPy: 0.234s
|
||||
Nyash Native: 0.198s (NumPyに匹敵!)
|
||||
```
|
||||
@ -1,249 +0,0 @@
|
||||
# Phase 10.7 実装詳細
|
||||
|
||||
## 🛠️ 技術アーキテクチャ
|
||||
|
||||
### 2段階変換パイプライン
|
||||
|
||||
```
|
||||
Python AST → CorePy IR → Nyash AST → Nyashスクリプト
|
||||
```
|
||||
|
||||
**CorePy IR**の役割:
|
||||
- Pythonの複雑な構文を正規化
|
||||
- セマンティクスを明示的に(with→try/finally等)
|
||||
- 最適化しやすい中間表現
|
||||
|
||||
### 実装構造
|
||||
|
||||
```rust
|
||||
// plugins/nyash-python-parser-plugin/src/lib.rs
|
||||
#[plugin_box]
|
||||
pub struct PythonParserBox {
|
||||
base: BoxBase,
|
||||
}
|
||||
|
||||
#[plugin_methods]
|
||||
impl PythonParserBox {
|
||||
pub fn parse(&self, code: &str) -> Result<Box<dyn NyashBox>> {
|
||||
Python::with_gil(|py| {
|
||||
let ast_mod = py.import("ast")?;
|
||||
let tree = ast_mod.call_method1("parse", (code,))?;
|
||||
Ok(self.convert_ast(tree)?)
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📐 Python固有機能の実装戦略
|
||||
|
||||
### 1. デフォルト引数の罠
|
||||
|
||||
```python
|
||||
# Python: 定義時に一度だけ評価
|
||||
def bad_default(lst=[]):
|
||||
lst.append(1)
|
||||
return lst
|
||||
```
|
||||
|
||||
```nyash
|
||||
// 生成されるNyash
|
||||
box GeneratedModule {
|
||||
init { _default_lst }
|
||||
|
||||
constructor() {
|
||||
me._default_lst = new ArrayBox() // 定義時に一度だけ
|
||||
}
|
||||
|
||||
bad_default(lst) {
|
||||
if lst == null {
|
||||
lst = me._default_lst // 同じインスタンスを再利用!
|
||||
}
|
||||
lst.append(1)
|
||||
return lst
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. LEGB スコーピング
|
||||
|
||||
```python
|
||||
# Local → Enclosing → Global → Builtin
|
||||
global_var = 1
|
||||
def outer():
|
||||
enclosing_var = 2
|
||||
def inner():
|
||||
local_var = 3
|
||||
```
|
||||
|
||||
実装:
|
||||
- シンボルテーブルでスコープ管理
|
||||
- クロージャはBox/Cellで実装
|
||||
- global/nonlocalフラグを追跡
|
||||
|
||||
### 3. for/else, while/else
|
||||
|
||||
```python
|
||||
for i in range(10):
|
||||
if i == 5:
|
||||
break
|
||||
else:
|
||||
print("No break")
|
||||
```
|
||||
|
||||
```nyash
|
||||
// 生成されるNyash
|
||||
local _broken = false
|
||||
local _iter = py_iter(range(10))
|
||||
loop(true) {
|
||||
local _next = py_next(_iter)
|
||||
if _next.isStopIteration() { break }
|
||||
local i = _next.value
|
||||
|
||||
if i == 5 {
|
||||
_broken = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if not _broken {
|
||||
print("No break")
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 パスパイプライン
|
||||
|
||||
```
|
||||
Parse Python AST
|
||||
↓
|
||||
Symbol table analysis
|
||||
↓
|
||||
Normalize to CorePy IR
|
||||
↓
|
||||
Scope/closure analysis
|
||||
↓
|
||||
Type metadata attachment
|
||||
↓
|
||||
Lower to Nyash AST
|
||||
↓
|
||||
Peephole optimization
|
||||
↓
|
||||
Pretty-print + source map
|
||||
```
|
||||
|
||||
## 📊 最適化戦略
|
||||
|
||||
### トランスパイル時の最適化
|
||||
- 定数畳み込み
|
||||
- ループ不変式の巻き上げ
|
||||
- ビルトイン関数の直接呼び出し(シャドウイングなし時)
|
||||
- 冗長な`py_truthy()`の除去
|
||||
|
||||
### Nyashコンパイラに委ねる最適化
|
||||
- インライン展開
|
||||
- レジスタ割り当て
|
||||
- ループアンローリング
|
||||
- ベクトル化
|
||||
|
||||
### 型情報の活用
|
||||
```python
|
||||
def add(x: int, y: int) -> int:
|
||||
return x + y
|
||||
```
|
||||
→ 型ヒントがあれば`py_binop`ではなく直接整数演算
|
||||
|
||||
## 🐛 エラー処理とデバッグ
|
||||
|
||||
### ソースマップ
|
||||
```json
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["example.py"],
|
||||
"mappings": "AAAA,IAAM,CAAC,GAAG...",
|
||||
"names": ["add", "x", "y"]
|
||||
}
|
||||
```
|
||||
|
||||
### デバッグモード
|
||||
```bash
|
||||
nyash-transpile --debug example.py
|
||||
# 出力:
|
||||
# - CorePy IRダンプ
|
||||
# - Nyashプレビュー(元のPython行ヒント付き)
|
||||
# - 変換トレース
|
||||
```
|
||||
|
||||
### エラーメッセージ
|
||||
```
|
||||
ERROR: Cannot compile function 'async_func' at line 10
|
||||
Reason: async/await not supported in Phase 1
|
||||
AST Node: AsyncFunctionDef
|
||||
Suggestion: Use PyRuntimeBox or wait for Phase 3
|
||||
```
|
||||
|
||||
## ⚡ パフォーマンス最適化
|
||||
|
||||
### ホットパス識別
|
||||
```nyash
|
||||
// プロファイル情報を活用
|
||||
if compiler.isHotPath(func) {
|
||||
// 積極的な最適化
|
||||
result = compiler.optimizeAggressive(func)
|
||||
} else {
|
||||
// 標準的な変換
|
||||
result = compiler.compile(func)
|
||||
}
|
||||
```
|
||||
|
||||
### JIT連携
|
||||
```nyash
|
||||
// 型特化コード生成
|
||||
@jit_specialize(int, int)
|
||||
def add(x, y):
|
||||
return x + y
|
||||
```
|
||||
|
||||
## 🔌 プラグインAPI
|
||||
|
||||
### 変換フック
|
||||
```rust
|
||||
trait TransformHook {
|
||||
fn before_lower(&mut self, node: &CorePyNode);
|
||||
fn after_lower(&mut self, node: &NyashNode);
|
||||
fn on_function(&mut self, func: &FunctionDef);
|
||||
}
|
||||
```
|
||||
|
||||
### カスタムルール
|
||||
```yaml
|
||||
# custom_rules.yaml
|
||||
rules:
|
||||
- pattern: "dataclass"
|
||||
action: "convert_to_nyash_box"
|
||||
- pattern: "numpy.array"
|
||||
action: "use_native_array"
|
||||
```
|
||||
|
||||
## 📋 実装チェックリスト
|
||||
|
||||
### Phase 1(必須)
|
||||
- [ ] 関数定義(def)
|
||||
- [ ] 条件分岐(if/elif/else)
|
||||
- [ ] ループ(for/while with else)
|
||||
- [ ] 基本演算子
|
||||
- [ ] 関数呼び出し
|
||||
- [ ] return/break/continue
|
||||
- [ ] LEGB スコーピング
|
||||
- [ ] デフォルト引数
|
||||
|
||||
### Phase 2(拡張)
|
||||
- [ ] 例外処理(try/except/finally)
|
||||
- [ ] with文
|
||||
- [ ] list/dict/set comprehensions
|
||||
- [ ] lambda式
|
||||
- [ ] *args, **kwargs
|
||||
|
||||
### Phase 3(高度)
|
||||
- [ ] async/await
|
||||
- [ ] yield/yield from
|
||||
- [ ] デコレータ
|
||||
- [ ] クラス定義(基本)
|
||||
- [ ] import文
|
||||
@ -1,194 +0,0 @@
|
||||
# Python Descriptor Protocol → Nyash Property System マッピング
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
2025-09-18のProperty System革命により、Python transpilationが飛躍的に向上。Pythonのdescriptor protocolを完全にNyashのProperty System(stored/computed/once/birth_once)にマッピングする設計。
|
||||
|
||||
## 🧬 Pythonプロパティ分類とNyashマッピング
|
||||
|
||||
### 1. 通常フィールド → stored
|
||||
```python
|
||||
class PyClass:
|
||||
def __init__(self):
|
||||
self.name = "example" # 通常の属性
|
||||
```
|
||||
```nyash
|
||||
box PyClass {
|
||||
name: StringBox // stored: 通常のフィールドストレージ
|
||||
|
||||
birth() {
|
||||
me.name = "example"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. @property → computed
|
||||
```python
|
||||
class PyClass:
|
||||
@property
|
||||
def full_name(self):
|
||||
return f"{self.first} {self.last}"
|
||||
```
|
||||
```nyash
|
||||
box PyClass {
|
||||
first: StringBox
|
||||
last: StringBox
|
||||
full_name: StringBox { me.first + " " + me.last } // computed: 毎回計算
|
||||
}
|
||||
```
|
||||
|
||||
### 3. @functools.cached_property → once
|
||||
```python
|
||||
import functools
|
||||
|
||||
class PyClass:
|
||||
@functools.cached_property
|
||||
def expensive_data(self):
|
||||
return expensive_computation()
|
||||
```
|
||||
```nyash
|
||||
box PyClass {
|
||||
once expensive_data: DataBox { expensive_computation() } // once: 遅延評価+キャッシュ
|
||||
}
|
||||
```
|
||||
|
||||
### 4. カスタムdescriptor → 判定ロジック
|
||||
```python
|
||||
class CustomDescriptor:
|
||||
def __get__(self, obj, objtype=None):
|
||||
# カスタムロジック
|
||||
pass
|
||||
|
||||
def __set__(self, obj, value):
|
||||
# セットロジック
|
||||
pass
|
||||
|
||||
class PyClass:
|
||||
custom_prop = CustomDescriptor()
|
||||
```
|
||||
|
||||
**判定ロジック(PythonCompilerBox内)**:
|
||||
```nyash
|
||||
box DescriptorAnalyzer {
|
||||
analyze_descriptor(descriptor_ast) {
|
||||
if descriptor_ast.has_get_only() {
|
||||
if descriptor_ast.is_pure_computation() {
|
||||
return "computed" // 副作用なし計算
|
||||
} else {
|
||||
return "once" // 副作用あり=キャッシュ推奨
|
||||
}
|
||||
}
|
||||
|
||||
if descriptor_ast.has_get_and_set() {
|
||||
return "stored" // getterとsetterあり=通常フィールド
|
||||
}
|
||||
|
||||
return "unsupported" // 複雑すぎ→Phase 2以降
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 自動判定アルゴリズム
|
||||
|
||||
### Phase 1: 基本パターン認識
|
||||
```python
|
||||
def classify_python_property(ast_node):
|
||||
# 1. デコレータ解析
|
||||
if has_decorator(ast_node, "@property"):
|
||||
if is_simple_computation(ast_node.body):
|
||||
return "computed"
|
||||
else:
|
||||
return "once" # 複雑→キャッシュ推奨
|
||||
|
||||
# 2. cached_property検出
|
||||
if has_decorator(ast_node, "@functools.cached_property"):
|
||||
return "once"
|
||||
|
||||
# 3. 通常の__init__内代入
|
||||
if is_init_assignment(ast_node):
|
||||
return "stored"
|
||||
|
||||
# 4. descriptor検出(Phase 2以降)
|
||||
if has_custom_descriptor(ast_node):
|
||||
return analyze_descriptor_complexity(ast_node)
|
||||
```
|
||||
|
||||
### Phase 2: 高度な判定(将来)
|
||||
- **副作用解析**: I/O、外部状態変更の検出
|
||||
- **コスト解析**: 計算量推定による once vs computed 判定
|
||||
- **依存解析**: 他のプロパティとの依存関係
|
||||
|
||||
## 🌟 poison-on-throw統合
|
||||
|
||||
### Python例外 → Nyash例外処理
|
||||
```python
|
||||
class PyClass:
|
||||
@functools.cached_property
|
||||
def risky_operation(self):
|
||||
if random.random() < 0.1:
|
||||
raise ValueError("Failed!")
|
||||
return expensive_result()
|
||||
```
|
||||
|
||||
```nyash
|
||||
box PyClass {
|
||||
once risky_operation: ResultBox {
|
||||
if random_float() < 0.1 {
|
||||
throw ValueError("Failed!")
|
||||
}
|
||||
return expensive_result()
|
||||
} catch(ex) {
|
||||
poison(me.risky_operation, ex) // poison-on-throw適用
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 実装フェーズ
|
||||
|
||||
### Phase 10.7a: 基本認識(1週間)
|
||||
- @property, @cached_property, 通常フィールドの自動分類
|
||||
- 単純なcomputedプロパティ生成
|
||||
|
||||
### Phase 10.7b: 拡張判定(2週間)
|
||||
- カスタムdescriptor解析
|
||||
- 副作用検出ロジック
|
||||
- poison-on-throw統合
|
||||
|
||||
### Phase 10.7c: 最適化(1週間)
|
||||
- 依存解析による once vs computed 最適選択
|
||||
- LLVM最適化との連携
|
||||
|
||||
## 🧪 テストケース
|
||||
|
||||
### 成功パターン
|
||||
```python
|
||||
# シンプルcomputed
|
||||
@property
|
||||
def area(self): return self.width * self.height # → computed
|
||||
|
||||
# キャッシュ必要
|
||||
@functools.cached_property
|
||||
def heavy_calc(self): return sum(range(1000000)) # → once
|
||||
|
||||
# 通常フィールド
|
||||
def __init__(self): self.name = "test" # → stored
|
||||
```
|
||||
|
||||
### 限界ケース(Phase 2以降)
|
||||
```python
|
||||
# 複雑なdescriptor(未対応)
|
||||
class ComplexDescriptor:
|
||||
def __get__(self, obj, objtype=None):
|
||||
# 複雑な条件分岐、外部API呼び出し等
|
||||
pass
|
||||
```
|
||||
|
||||
## 🚀 期待される効果
|
||||
|
||||
1. **開発体験**: PythonプロパティがNyashで自然に表現
|
||||
2. **性能向上**: LLVMによるproperty最適化(10-50x高速化)
|
||||
3. **型安全性**: NyashのBox型システムによる実行時安全性
|
||||
4. **保守性**: 生成されたNyashコードの可読性・編集可能性
|
||||
|
||||
このマッピング設計により、PythonからNyashへの自然で高性能なtranspilationが実現できます!
|
||||
@ -1,152 +0,0 @@
|
||||
# Phase 10.7 × Property System 革命 - 今すぐ始めるクイックスタート
|
||||
|
||||
## 🎯 Property System革命により実現可能になったPython→Nyash実行
|
||||
|
||||
2025-09-18のProperty System革命により、Python transpilationが飛躍的に実現可能に!
|
||||
|
||||
## 🚀 最短実装ルート(3週間で実用レベル)
|
||||
|
||||
### Week 1: 基本プロパティ認識
|
||||
```bash
|
||||
# プラグイン作成
|
||||
cd plugins/
|
||||
cargo new nyash-python-parser-plugin --lib
|
||||
|
||||
# 最小依存関係
|
||||
echo '[dependencies]
|
||||
pyo3 = { version = "0.22", features = ["auto-initialize"] }
|
||||
nyash-plugin-sdk = { path = "../../crates/plugin-sdk" }' >> Cargo.toml
|
||||
```
|
||||
|
||||
### Week 2-3: Property System活用コンパイラ
|
||||
```rust
|
||||
// src/lib.rs - 最小実装例
|
||||
use pyo3::prelude::*;
|
||||
|
||||
#[pyclass]
|
||||
pub struct PythonCompilerBox {
|
||||
property_classifier: PropertyClassifier,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl PythonCompilerBox {
|
||||
#[new]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
property_classifier: PropertyClassifier::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile_simple(&self, python_code: &str) -> PyResult<String> {
|
||||
let ast = self.parse_python(python_code)?;
|
||||
let classified = self.property_classifier.classify(ast);
|
||||
let nyash_code = self.generate_nyash_with_properties(classified);
|
||||
Ok(nyash_code)
|
||||
}
|
||||
}
|
||||
|
||||
struct PropertyClassifier;
|
||||
|
||||
impl PropertyClassifier {
|
||||
fn new() -> Self { Self }
|
||||
|
||||
fn classify(&self, ast: PythonAst) -> ClassifiedAst {
|
||||
// Phase 1: 基本パターンのみ
|
||||
// @property → computed
|
||||
// @cached_property → once
|
||||
// __init__代入 → stored
|
||||
todo!("実装")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 MVP テストケース
|
||||
|
||||
### 入力Python
|
||||
```python
|
||||
# test_simple.py
|
||||
class Counter:
|
||||
def __init__(self):
|
||||
self.value = 0
|
||||
|
||||
@property
|
||||
def doubled(self):
|
||||
return self.value * 2
|
||||
|
||||
@functools.cached_property
|
||||
def expensive_result(self):
|
||||
return sum(range(1000))
|
||||
```
|
||||
|
||||
### 期待されるNyash出力
|
||||
```nyash
|
||||
box Counter {
|
||||
value: IntegerBox // stored
|
||||
doubled: IntegerBox { me.value * 2 } // computed
|
||||
once expensive_result: IntegerBox { sum_range(1000) } // once
|
||||
|
||||
birth() {
|
||||
me.value = 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 実行テスト
|
||||
```bash
|
||||
# transpilation
|
||||
nyash --pyc test_simple.py -o test_simple.ny
|
||||
|
||||
# ネイティブコンパイル
|
||||
nyash --compile-native test_simple.ny -o test_app
|
||||
|
||||
# 実行(CPython依存なし!)
|
||||
./test_app
|
||||
```
|
||||
|
||||
## 📊 段階的成功指標
|
||||
|
||||
### Phase 1 (1週間後)
|
||||
- ✅ @property, @cached_property認識
|
||||
- ✅ 基本クラス → box変換
|
||||
- ✅ 1つのサンプルPythonファイルが動作
|
||||
|
||||
### Phase 2 (2週間後)
|
||||
- ✅ 継承、メソッド呼び出し対応
|
||||
- ✅ 10個のサンプルファイル成功
|
||||
- ✅ 性能測定(CPythonとの比較)
|
||||
|
||||
### Phase 3 (3週間後)
|
||||
- ✅ エラーハンドリング、例外処理
|
||||
- ✅ 実用的なPythonライブラリ部分対応
|
||||
- ✅ AOT配布可能なサンプルアプリ
|
||||
|
||||
## 🌟 創造的可能性
|
||||
|
||||
### ハイブリッド開発
|
||||
```python
|
||||
# Python側で開発・デバッグ
|
||||
@nyash.optimize # デコレータで高速化指定
|
||||
def heavy_computation(data):
|
||||
return complex_algorithm(data)
|
||||
|
||||
# 本番はNyash AOTで配布
|
||||
```
|
||||
|
||||
### リアルタイムtranspilation IDE
|
||||
- 左: Pythonコード編集
|
||||
- 右: リアルタイムNyash生成表示
|
||||
- 下: 性能比較グラフ
|
||||
|
||||
### 教育効果
|
||||
- Pythonユーザーが自然にNyashを学習
|
||||
- Property Systemの概念理解促進
|
||||
|
||||
## 🎯 今日から始められるアクション
|
||||
|
||||
1. **プラグイン skelton作成** (30分)
|
||||
2. **pyo3でPython AST取得** (2時間)
|
||||
3. **@property検出ロジック** (半日)
|
||||
4. **最初のbox変換** (1日)
|
||||
5. **テスト実行** (30分)
|
||||
|
||||
Property System革命により、この夢が現実になりました!🚀
|
||||
@ -1,285 +0,0 @@
|
||||
# Python Native Testing Plan
|
||||
|
||||
## 🎯 テスト戦略の全体像
|
||||
|
||||
「世界中のPythonコードがNyashのテストケース」という思想のもと、CPythonをオラクルとして使用する包括的なテスト戦略。
|
||||
|
||||
## 🧪 テストレベル
|
||||
|
||||
### 1. プラグインレベルテスト
|
||||
|
||||
#### PythonParserBox Tests
|
||||
```rust
|
||||
// plugins/nyash-python-parser-plugin/tests/parser_tests.rs
|
||||
#[test]
|
||||
fn test_parse_simple_function() {
|
||||
let parser = create_parser_box();
|
||||
let code = "def add(x, y): return x + y";
|
||||
let ast = parser.parse(create_string_box(code));
|
||||
|
||||
assert_eq!(ast.get_type().to_string(), "Module");
|
||||
let functions = ast.get_children();
|
||||
assert_eq!(functions.length(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_with_telemetry() {
|
||||
let parser = create_parser_box();
|
||||
parser.enable_telemetry(true);
|
||||
|
||||
let code = r#"
|
||||
def supported(): return 1
|
||||
async def unsupported(): await foo()
|
||||
"#;
|
||||
|
||||
parser.parse(create_string_box(code));
|
||||
let stats = parser.get_stats();
|
||||
|
||||
assert_eq!(stats.get("total_functions"), 2);
|
||||
assert_eq!(stats.get("supported_functions"), 1);
|
||||
}
|
||||
```
|
||||
|
||||
#### PythonCompilerBox Tests
|
||||
```rust
|
||||
#[test]
|
||||
fn test_compile_arithmetic() {
|
||||
let compiler = create_compiler_box();
|
||||
let ast = /* ... */;
|
||||
|
||||
let mir = compiler.compile(ast);
|
||||
assert!(mir.is_ok());
|
||||
|
||||
// MIR検証
|
||||
let module = mir.unwrap();
|
||||
assert!(module.has_function("add"));
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Differential Testing Framework
|
||||
|
||||
```nyash
|
||||
// tests/differential/framework.hako
|
||||
box DifferentialTester {
|
||||
init { oracle, implementation, results }
|
||||
|
||||
constructor() {
|
||||
me.oracle = new PythonRuntimeBox() // CPython
|
||||
me.implementation = new NativeEngine()
|
||||
me.results = new ArrayBox()
|
||||
}
|
||||
|
||||
test(code) {
|
||||
local oracle_result, impl_result
|
||||
|
||||
// CPythonで実行
|
||||
oracle_result = me.oracle.eval(code)
|
||||
|
||||
// Native実装で実行
|
||||
impl_result = me.implementation.exec(code)
|
||||
|
||||
// 結果比較
|
||||
return me.compare(oracle_result, impl_result)
|
||||
}
|
||||
|
||||
compare(expected, actual) {
|
||||
// 出力、戻り値、例外を比較
|
||||
local match = new MapBox()
|
||||
match.set("output", expected.output == actual.output)
|
||||
match.set("return", expected.return == actual.return)
|
||||
match.set("exception", expected.exception == actual.exception)
|
||||
return match
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. テストケース生成
|
||||
|
||||
#### 基本テストスイート
|
||||
```python
|
||||
# tests/suites/phase1_tests.py
|
||||
|
||||
# 算術演算
|
||||
def test_arithmetic():
|
||||
assert add(2, 3) == 5
|
||||
assert multiply(4, 5) == 20
|
||||
assert divide(10, 2) == 5.0 # true division
|
||||
|
||||
# 制御フロー
|
||||
def test_control_flow():
|
||||
# if/else
|
||||
result = conditional_logic(True, 10, 20)
|
||||
assert result == 10
|
||||
|
||||
# for/else
|
||||
found = search_with_else([1, 2, 3], 5)
|
||||
assert found == "not found" # else節実行
|
||||
|
||||
# デフォルト引数の罠
|
||||
def test_default_args():
|
||||
list1 = append_to_default(1)
|
||||
list2 = append_to_default(2)
|
||||
assert list1 is list2 # 同じリスト!
|
||||
```
|
||||
|
||||
#### Fuzzing with Hypothesis
|
||||
```python
|
||||
# tests/fuzzing/property_tests.py
|
||||
from hypothesis import given, strategies as st
|
||||
|
||||
@given(st.integers(), st.integers())
|
||||
def test_arithmetic_properties(x, y):
|
||||
"""算術演算の性質をテスト"""
|
||||
# Commutativity
|
||||
assert add(x, y) == add(y, x)
|
||||
|
||||
# Identity
|
||||
assert add(x, 0) == x
|
||||
|
||||
# Differential testing
|
||||
native_result = native_add(x, y)
|
||||
cpython_result = x + y
|
||||
assert native_result == cpython_result
|
||||
```
|
||||
|
||||
### 4. ベンチマークスイート
|
||||
|
||||
```nyash
|
||||
// benchmarks/numeric_suite.hako
|
||||
box NumericBenchmark {
|
||||
run() {
|
||||
local suite = new BenchmarkSuite()
|
||||
|
||||
// Fibonacci
|
||||
suite.add("fibonacci", {
|
||||
"cpython": { return me.runCPython("fib.py") },
|
||||
"native": { return me.runNative("fib.py") }
|
||||
})
|
||||
|
||||
// Matrix multiplication
|
||||
suite.add("matrix_mult", {
|
||||
"cpython": { return me.runCPython("matrix.py") },
|
||||
"native": { return me.runNative("matrix.py") }
|
||||
})
|
||||
|
||||
return suite.execute()
|
||||
}
|
||||
}
|
||||
|
||||
// 実行結果例
|
||||
// fibonacci:
|
||||
// CPython: 1.234s
|
||||
// Native: 0.123s (10.0x faster)
|
||||
// matrix_mult:
|
||||
// CPython: 5.678s
|
||||
// Native: 0.456s (12.4x faster)
|
||||
```
|
||||
|
||||
### 5. 回帰テスト
|
||||
|
||||
```yaml
|
||||
# .github/workflows/python-native-tests.yml
|
||||
name: Python Native Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Differential Tests
|
||||
run: |
|
||||
cargo test --package nyash-python-parser-plugin
|
||||
cargo test --package nyash-python-compiler-plugin
|
||||
|
||||
- name: Coverage Report
|
||||
run: |
|
||||
./tools/measure_compilation_coverage.sh
|
||||
# Expected output:
|
||||
# Phase 1 compatible files: 15%
|
||||
# Phase 2 functions: 40% compilable
|
||||
# Phase 3 functions: 10% compilable
|
||||
```
|
||||
|
||||
## 📊 メトリクス収集
|
||||
|
||||
### コンパイル成功率
|
||||
```nyash
|
||||
// 自動計測ツール
|
||||
box CoverageAnalyzer {
|
||||
analyze(directory) {
|
||||
local parser = new PythonParserBox()
|
||||
local compiler = new PythonCompilerBox()
|
||||
local stats = new MapBox()
|
||||
|
||||
for file in directory.glob("*.py") {
|
||||
local ast = parser.parseFile(file)
|
||||
local result = compiler.compile(ast)
|
||||
|
||||
stats.increment("total")
|
||||
if result.isOk() {
|
||||
stats.increment("success")
|
||||
} else {
|
||||
stats.increment("not_compilable")
|
||||
stats.record("unsupported", result.getError())
|
||||
}
|
||||
}
|
||||
|
||||
return stats
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### パフォーマンス追跡
|
||||
```sql
|
||||
-- メトリクスDB
|
||||
CREATE TABLE benchmark_results (
|
||||
id SERIAL PRIMARY KEY,
|
||||
test_name VARCHAR(255),
|
||||
implementation VARCHAR(50), -- 'cpython' or 'native'
|
||||
execution_time FLOAT,
|
||||
memory_usage BIGINT,
|
||||
timestamp TIMESTAMP,
|
||||
git_hash VARCHAR(40)
|
||||
);
|
||||
```
|
||||
|
||||
## 🚨 失敗時の診断
|
||||
|
||||
### デバッグ情報収集
|
||||
```nyash
|
||||
// コンパイル失敗時の詳細情報
|
||||
compiler.enableDebug(true)
|
||||
result = compiler.compile(ast)
|
||||
|
||||
if result.isErr() {
|
||||
local diag = compiler.getDiagnostics()
|
||||
print("Failed at: " + diag.get("location"))
|
||||
print("Reason: " + diag.get("reason"))
|
||||
print("AST node: " + diag.get("node_type"))
|
||||
print("Suggestion: " + diag.get("suggestion"))
|
||||
}
|
||||
```
|
||||
|
||||
### トレース機能
|
||||
```
|
||||
NYASH_PYTHON_TRACE=1 ./target/release/nyash test.py
|
||||
[Parser] Parsing function 'compute' at line 5
|
||||
[Compiler] Compiling BinOp: Add at line 7
|
||||
[Compiler] Unsupported: YieldFrom at line 15
|
||||
[Error] Cannot compile function 'generator_func' - yield not supported
|
||||
```
|
||||
|
||||
## ✅ 受け入れ基準
|
||||
|
||||
### Phase 1完了
|
||||
- [ ] 基本テストスイート100%パス
|
||||
- [ ] Differential testing 100%一致
|
||||
- [ ] Phase 1対応コードの100%コンパイル成功
|
||||
- [ ] 10x性能向上(数値計算ベンチマーク)
|
||||
|
||||
### 各PR必須
|
||||
- [ ] 新機能の単体テスト
|
||||
- [ ] Differential testケース追加
|
||||
- [ ] ベンチマーク結果(該当する場合)
|
||||
- [ ] カバレッジ低下なし
|
||||
@ -1,13 +0,0 @@
|
||||
# DECISIONS (Phase 10.7)
|
||||
|
||||
## 2025-08-30 — 二本立て運用(決定)
|
||||
- 決定: 現行の実行系(PyRuntimeBox, Plugin-First)は維持し、トランスパイル系(Python→Nyash)は All-or-Nothing で併走。
|
||||
- 代替案: トランスパイルの部分フォールバック(実行時にPyRuntimeへ落とす)。
|
||||
- 理由: 実行時の不一致/隠れ分岐を避ける。デプロイ時の挙動を単純に保つ。
|
||||
- 影響: 生成Nyashの品質責任はトランスパイラ側。利用者は明示的に系を選択。
|
||||
|
||||
## 2025-08-30 — Parser/CompilerもプラグインBox(決定)
|
||||
- 決定: PythonParserBox/PythonCompilerBox としてプラグイン化し、CLIから呼び出す。
|
||||
- 代替案: コア組込み。
|
||||
- 理由: Plugin-First原則、配布容易性、差し替え性、隔離テスト。
|
||||
- 影響: plugins/ 以下に新規プラグインを追加。SDKの最小拡張が必要になる場合あり。
|
||||
@ -1,39 +0,0 @@
|
||||
# CorePy IR 最小スキーマ(C2草案)
|
||||
|
||||
目的: Phase 1 の End-to-End を最短で通すための暫定IR。将来は構造化・拡張(with/try/comp/async等)。
|
||||
|
||||
## JSON 形式(暫定)
|
||||
```json
|
||||
{
|
||||
"module": {
|
||||
"functions": [
|
||||
{
|
||||
"name": "main", // 省略可(既定: "main")
|
||||
"return_value": 0, // 省略可(bodyと排他)
|
||||
"body": [ // 省略可(return_valueと排他)
|
||||
{ "Return": { "value": 0 } }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
ショートカット(デバッグ/ブリッジ用)
|
||||
```json
|
||||
{ "nyash_source": "static box Generated { main() { return 0 } }" }
|
||||
```
|
||||
|
||||
## 変換規則(最小)
|
||||
- module.functions[0] だけを見る(複数関数は将来対応)
|
||||
- name があれば `static box Generated { <name>() { ... } }`
|
||||
- return_value が数値/文字列なら `return <value>` を生成
|
||||
- body があれば先頭の Return.value を探し、`return <value>` を生成
|
||||
- 上記が無ければ `return 0`
|
||||
|
||||
## 将来(予約)
|
||||
- statements: If/While/For/Assign/Expr などの節を追加
|
||||
- expressions: BinOp/Call/Name/Constant などを構造化
|
||||
- functions配列の複数対応、クロージャは別Box化の方針を検討
|
||||
|
||||
注意: All-or-Nothing 原則のもと、未対応ノードはCompiler側で明示的にエラーにする(現段階では未実装のため、return 0にフォールバックするが、C2終盤でStrict化する)。
|
||||
@ -1,21 +0,0 @@
|
||||
# Phase 10.7 Workbench
|
||||
|
||||
このフォルダは Python Native(トランスパイル路線, All-or-Nothing)専用の作業台です。仕様・決定・スパイク・タスクをここに集約し、雑多にならないようにします。
|
||||
|
||||
構成
|
||||
- TODO.md: 直近の作業キュー(小粒で管理)
|
||||
- DECISIONS.md: 決定事項(理由/代替案/影響)
|
||||
- SPIKES/: 検証スパイクの成果(小さなPoCやプロト)
|
||||
- notes-YYYYMMDD.md: 打合せ/検討メモ(必要に応じて)
|
||||
|
||||
関連
|
||||
- 計画: ../PLAN.txt
|
||||
- 実装: ../implementation.md
|
||||
- テスト: ../testing-plan.md
|
||||
- 背景: ../README.md
|
||||
|
||||
運用ルール(最小)
|
||||
- 一度に大きくしない(5〜30分単位の成果で刻む)
|
||||
- 決定は DECISIONS.md に残す(誰でも後から辿れる)
|
||||
- スパイクは SPIKES に隔離(本流に混ぜない)
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
# TODO (Phase 10.7 Workbench)
|
||||
|
||||
短期(C1〜C3に向けた小粒タスク)
|
||||
- [ ] C1: Parser plugin 雛形スケルトンを作る(pyo3, parse(code)->AstBox/to_json)
|
||||
- [ ] C1: Telemetry最小(node種別カウント, 未対応ノード列挙)
|
||||
- [ ] C2: CorePy IR最小スキーマ(JSON)を commit(with/async系は予約)
|
||||
- [ ] C2: IR→Nyash ASTの最小変換(def/if/for/while/return/算術/比較/呼出し)
|
||||
- [ ] C3: CLI隠しフラグ prototyping(--pyc/--pyc-native)
|
||||
- [ ] Docs: PLANとimplementationの差分同期(週次)
|
||||
|
||||
メモ
|
||||
- All-or-Nothing原則:未対応は即Err(自動フォールバックなし)
|
||||
- 生成Nyashは現行AOT導線で配布可能(Strict)
|
||||
@ -1,61 +0,0 @@
|
||||
# Phase 10: JIT実装とセルフホスティング
|
||||
|
||||
## 🎯 Phase 10の全体像
|
||||
|
||||
Phase 10は、Nyashの実行性能を大幅に向上させるJIT実装と、言語の成熟度を示すセルフホスティングを実現します。
|
||||
|
||||
## 📊 実装優先順位
|
||||
|
||||
### 1️⃣ **メイン実装: Cranelift JIT**
|
||||
→ [phase_10_cranelift_jit_backend.md](phase_10_cranelift_jit_backend.md)
|
||||
- VMとのハイブリッド実行(ホットパス検出→JIT化)
|
||||
- 実装期間: 2-3ヶ月
|
||||
- 目標: ホットパスで2倍以上の高速化
|
||||
|
||||
### 🌟 **革新的機能: GC切り替え可能ランタイム**
|
||||
→ [phase_10_4_gc_switchable_runtime.md](phase_10_4_gc_switchable_runtime.md)
|
||||
- 世界初:実行時にGCモード切り替え可能
|
||||
- 開発時はGCオンで快適、本番はGCオフで高速
|
||||
- 実装期間: 2-3ヶ月(Cranelift JIT後)
|
||||
- 技術的にCodex GPT-5が実現可能性を確認済み
|
||||
|
||||
### 2️⃣ **並行プロジェクト: セルフホスティング**
|
||||
→ [phase_10_5_core_std_nyash_impl.md](phase_10_5_core_std_nyash_impl.md)
|
||||
- String/Array/MapをNyash自身で実装
|
||||
- Rust依存の段階的削減
|
||||
- 実装期間: 1-2ヶ月
|
||||
|
||||
### 3️⃣ **実戦テスト: アプリケーション移植**
|
||||
→ [phase_10_app_migration.md](phase_10_app_migration.md)
|
||||
- Tinyproxy: ゼロコピー判定機能の検証
|
||||
- Chip-8エミュレータ: fini伝播とweak参照の実戦テスト
|
||||
- kiloエディタ: メモリ効率の「うっかり全体コピー」検出
|
||||
|
||||
### 🚫 **延期プロジェクト**
|
||||
→ [Phase 11: LLVM AOT Backend](../phase-11/) - 将来の研究開発として分離
|
||||
|
||||
## 🛤️ 実装ロードマップ
|
||||
|
||||
```
|
||||
Phase 9.79b (現在)
|
||||
↓
|
||||
Phase 10.0: Cranelift JIT基盤構築
|
||||
├→ Phase 10.1-10.3: JIT実装・最適化
|
||||
├→ Phase 10.4: GC切り替え可能ランタイム ← NEW!
|
||||
└→ Phase 10.5: セルフホスティング(並行)
|
||||
↓
|
||||
Phase 10.9: アプリケーション移植で実戦検証
|
||||
↓
|
||||
Phase 11: LLVM AOT研究(将来)
|
||||
```
|
||||
|
||||
## 📈 期待される成果
|
||||
|
||||
1. **実行性能**: インタープリタ比100倍、VM比2-3倍の高速化
|
||||
2. **言語成熟度**: 基本コンテナのセルフホスティング達成
|
||||
3. **実用性検証**: 実アプリケーションの移植による実戦テスト
|
||||
|
||||
## 🔗 関連ドキュメント
|
||||
- [00_MASTER_ROADMAP.md](../00_MASTER_ROADMAP.md) - 全体計画
|
||||
- [Phase 9.79b](../phase-9/) - 統一Box設計(前提)
|
||||
- [MIR仕様](../../../../reference/mir/) - 中間表現
|
||||
@ -1,94 +0,0 @@
|
||||
# Phase 10.10 – Python→Nyash→MIR→VM/Native ラインの実用化整備(Box-First 継続)
|
||||
|
||||
目的: Nyash→MIR→VM/Native の実行ラインを日常運用レベルに引き上げ、GC/デバッグ/HostCallの柱を整備する。
|
||||
|
||||
## ゴール(DoD)
|
||||
- エンドツーエンド実行ライン(Parser→AST→MIR→VM→JIT)がビルトインBoxで安定(RO/一部WO)
|
||||
- GC切替(Null/Counting)をCLI/Boxから操作可能、root領域APIが一箇所化
|
||||
- デバッグ/可視化の旗振り(DebugConfig/Box)でJIT/VM/イベント/DOTを一本化
|
||||
- HostCall: 読み取り系はparam受けでJIT直実行(allow)。書き込み系はポリシー/whitelistでopt-in可能
|
||||
- 最小ベンチと回帰(サンプル)でラインの劣化を検知
|
||||
|
||||
## 事前整備(現状)
|
||||
- HostCall基盤: Registry/Policy/Events/Boundary(10.9-β/δ完了)
|
||||
- JITイベント: `NYASH_JIT_EVENTS=1` 時に `threshold=1` 自動適用でLower確実実行
|
||||
- 戻り境界: CallBoundaryBox で JitValue→VMValue を一元化(ハンドル復元含む)
|
||||
|
||||
## ワークストリーム
|
||||
1) GC Switchable Runtime(phase_10_4_gc_switchable_runtime.md)
|
||||
- 目標: NullGc/CountingGc の切替、root領域/バリアAPIの一本化
|
||||
- タスク:
|
||||
- NyashRuntimeBuilder: GC選択をCLI/Box反映(NYASH_GC=none|counting など)
|
||||
- ScopeTracker/enter_root_region()/pin_roots() の公開インターフェース確認
|
||||
- CountingGcの統計出力(roots/reads/writes/safepoints)
|
||||
- 書き込み系HostCallにバリアサイトのフック(Map/Array set/push)
|
||||
- 受入: GC切替コマンドで統計差分が取れる/HostCall書き込みでバリアサイトが加算される
|
||||
|
||||
2) Unified Debug System(phase_10_8_unified_debug_system.md)
|
||||
- 目標: デバッグ/観測フラグを DebugConfig/Box に統合(CLI/env/Boxの単一路)
|
||||
- タスク:
|
||||
- DebugConfig(Rust側): dump/events/stats/dot/phi_min 等を集約
|
||||
- DebugConfigBox: Boxから get/set/apply/toJson/fromJson
|
||||
- Runner: CLI→DebugConfig→env/Box の一本化(env直読み排除)
|
||||
- イベント出力先: stdout/file 切替の設定(NYASH_JIT_EVENTS_PATH のBox反映)
|
||||
- 受入: Boxから apply 後、JIT/VM/DOTの挙動が即時反映/JSONLが指定先に出力
|
||||
|
||||
3) E2Eラインの実用化(builtin→pluginの足場)
|
||||
- 目標: ビルトインBoxで日常運用レベル、プラグインBoxはTLV HostCallの足場を準備
|
||||
- タスク:
|
||||
- Lowerカバレッジの整理(BoxCall/RO/WO・param/非paramの分岐ダンプ)
|
||||
- 署名管理: レジストリのオーバーロード運用方針(canonical idと派生idの整理)
|
||||
- 返り型推論: MIR Builderのreturn_type推定を確認(main/補助関数とも)
|
||||
- Plugin PoC: TLV/handle経由のread-onlyメソッド1つをHostCall経由で通す(allowログまで)
|
||||
- 受入: 代表サンプル(math/map/array/string)でallow/fallbackが意図通り、plugin PoCでallowイベントが出る
|
||||
|
||||
4) ドキュメントと例の整理
|
||||
- 目標: 例の最小集合化(param/非param/RO/WO/HH/Hの代表)、手順の簡潔化
|
||||
- タスク:
|
||||
- examples/: 重複の削減、README(実行コマンド付き)
|
||||
- phase_10_9/10_10 のガイドをCURRENT_TASKと相互参照
|
||||
- 受入: 主要ケースが examples/README からそのまま実行可
|
||||
|
||||
5) ベンチと回帰(最小)
|
||||
- 目標: ラインの性能/退行の早期検知
|
||||
- タスク:
|
||||
- ny_bench.hako のケース整理(関数呼出/Map set-get/branch)
|
||||
- compare: VM vs JIT(ウォームアップ付き)
|
||||
- 受入: ベンチ出力に JIT/VM の比較が出る(改善/退行が見える)
|
||||
|
||||
## リスクと対策
|
||||
- param/非param 分岐の混乱: イベントに reason を必ず出す/docsにベストプラクティス(受け手をparam化)
|
||||
- mutatingの誤許可: JitPolicyBox の whitelist/プリセットのみで許可、既定はread_only
|
||||
- 署名の散逸: canonical id(例: nyash.map.get_h)と派生(_hh)の方針を明示
|
||||
|
||||
## 受け入れ基準(サマリ)
|
||||
- DebugConfig/Box/CLIの一貫挙動(apply後の即時反映)
|
||||
- GC切替とバリアサイト観測が可能
|
||||
- HostCall(RO/一部WO)が param でallow、非paramでfallback(イベントで確認可)
|
||||
- 代表サンプルが examples/README の手順で成功
|
||||
|
||||
## すぐ試せるコマンド(抜粋)
|
||||
```bash
|
||||
# math.min(関数スタイル)
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_NATIVE_F64=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_math_function_style_min_float.hako
|
||||
|
||||
# Map.get HH直実行
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_map_get_param_hh.hako
|
||||
|
||||
# Mutating opt-in(Array.push)
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_policy_optin_mutating.hako
|
||||
|
||||
## 例とスモーク(開発者向けクイック)
|
||||
- 例一覧: `examples/README.md`(HH直実行・mutating opt-in・GCデモ)
|
||||
- スモーク: `bash tools/smoke_phase_10_10.sh`
|
||||
- JITイベント最小スキーマ: `docs/reference/jit/jit_events_json_v0_1.md`
|
||||
|
||||
### Quick Note(運用の勘所)
|
||||
- phase分離: compile→`phase:"lower"`(opt-in), runtime→`phase:"execute"`(既定ON可)
|
||||
- しきい値: 観測ONかつ未指定なら `NYASH_JIT_THRESHOLD=1`(Runner/DebugConfigが補助)
|
||||
- HostCall: 実例では `NYASH_JIT_HOSTCALL=1` を明示(HH直実行/ANYヘルパ)
|
||||
- ANYヘルパ: `nyash.any.length_h / is_empty_h` でROは十分カバー(追加不要)
|
||||
```
|
||||
@ -1,19 +0,0 @@
|
||||
# Phase 10.4 — GC Switchable Runtime (Scaffold)
|
||||
|
||||
Status: scaffolded (hooks only)
|
||||
|
||||
Goals
|
||||
- Decouple execution engines from a concrete GC.
|
||||
- Provide minimal `GcHooks` with `safepoint()` and `barrier(kind)` used by MIR `Safepoint`/`Barrier*`.
|
||||
- Make runtime supply a pluggable GC via `NyashRuntimeBuilder::with_gc_hooks`.
|
||||
|
||||
What’s done (in this repo)
|
||||
- Added `src/runtime/gc.rs` with `GcHooks` trait, `BarrierKind`, and `NullGc` (no-op).
|
||||
- `NyashRuntime` now holds `gc: Arc<dyn GcHooks>`; defaults to `NullGc`.
|
||||
- VM dispatch calls hooks on `Safepoint` and `Barrier(Read|Write|unified)`.
|
||||
|
||||
Next
|
||||
- Thread-local root set API design (`enter_scope/leave_scope`, root pinning) for precise collectors.
|
||||
- Card marking/write barrier integration for object field writes (`RefSet` sites).
|
||||
- Preemption policy at safepoints (cooperative scheduling integration).
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
Phase 10.4d — Barrier Strict Mode (CI/Local)
|
||||
|
||||
Goal
|
||||
- Catch missing Write-Barrier quickly in development and CI.
|
||||
|
||||
How-To (Local)
|
||||
1) Build with default features:
|
||||
cargo build --release -j32
|
||||
2) Run with CountingGc + Strict Barrier + Trace:
|
||||
(in code) build runtime via NyashRuntimeBuilder::with_counting_gc()
|
||||
(env)
|
||||
set NYASH_GC_BARRIER_STRICT=1
|
||||
set NYASH_GC_TRACE=1
|
||||
nyash <program.hako>
|
||||
|
||||
Expected
|
||||
- Barrier sites log to stderr.
|
||||
- On any mutating site without barrier increment, process panics with site name.
|
||||
|
||||
CI Suggestion
|
||||
- Add a job that runs selected examples/tests with CountingGc enabled and
|
||||
NYASH_GC_BARRIER_STRICT=1. Fail build on panic.
|
||||
|
||||
Notes
|
||||
- Strict mode requires CountingGc; otherwise the helper panics to avoid false negatives.
|
||||
- Use NYASH_GC_TRACE=2 for detailed roots breakdown at end-of-run when investigating.
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
# 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 ABI(fat 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
|
||||
@ -1,20 +0,0 @@
|
||||
# Phase 10.6 — Thread-Safe Revolution (Design Prep)
|
||||
|
||||
Status: preparation
|
||||
|
||||
Principles
|
||||
- Opt-in concurrency: default runtime remains single-threaded for simplicity.
|
||||
- All extension points intended for cross-thread use must be `Send + Sync`.
|
||||
|
||||
What’s prepared
|
||||
- `GcHooks: Send + Sync` to allow multi-threaded collectors later.
|
||||
- `NyashRuntime` holds `Arc<dyn GcHooks>` for safe sharing across threads.
|
||||
|
||||
Planned tasks
|
||||
- Audit `NyashBox` implementations for `Send + Sync` (introduce marker traits or wrappers).
|
||||
- Introduce scheduler abstraction for futures/actors (no global state).
|
||||
- Introduce interior mutability strategy `RwLock` on shared mutable state, with minimal contention.
|
||||
|
||||
Notes
|
||||
- Until the audit, VM enforces single-threaded access; sharing across threads is unsupported by default.
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
# Phase 10.6a — Thread-Safety Audit (Checklist)
|
||||
|
||||
目的: NyashBox/ランタイムのスレッド安全性を棚卸しし、将来の並列化(10.6b/c以降)に備える。
|
||||
|
||||
## 方針
|
||||
- 既定は単一スレッド実行(VM/Interpreter)。並列化は opt-in。
|
||||
- 共有状態は `Arc<...>` と `RwLock/Mutex` により内的可変を確保。
|
||||
- クロススレッド境界に出る型は `Send + Sync` を満たす(必要に応じてラッパで担保)。
|
||||
|
||||
## チェックリスト
|
||||
- Box実装(src/boxes/*)
|
||||
- [ ] 共有内部状態を持つ型は `Arc<RwLock<_>>` のようにラップされているか
|
||||
- [ ] `to_string_box()` が重い処理やグローバル可変に依存しないか
|
||||
- [ ] FFI/プラグイン橋渡し時に非同期イベント/コールバックを保持しないか(保持する場合は送受戦略を文書化)
|
||||
- ランタイム(src/runtime/*)
|
||||
- [ ] `NyashRuntime` のメンバは `Send + Sync` 要件を満たす(`Arc<...>`)
|
||||
- [ ] `GcHooks` 実装は `Send + Sync`(CountingGc/NullGc はOK)
|
||||
- [ ] Scheduler 実装は `Send + Sync`(SingleThreadSchedulerはOK)
|
||||
- VM/Interpreter
|
||||
- [ ] MIR `Safepoint` で `runtime.scheduler.poll()` を呼ぶ(協調スケジューラの結合点)
|
||||
- [ ] Grep: `rg -n "Safepoint" src` で配置確認
|
||||
|
||||
## Grep支援
|
||||
```bash
|
||||
rg -n "Arc<|Mutex<|RwLock<|Send|Sync" src/boxes src/runtime
|
||||
```
|
||||
|
||||
## 既知の注意点
|
||||
- Python/外部DLLとの橋渡しはGIL/PATH管理で単一スレッド優先(AOT時はPATH/PYTHONHOME調整済)。
|
||||
- BufferBox は共有化のために `Arc<RwLock<Vec<u8>>>` を採用済み。
|
||||
|
||||
## クイック監査(第一次)
|
||||
- ArrayBox: `Arc<RwLock<Vec<Box<dyn NyashBox>>>>` → OK(共有+内的可変)
|
||||
- MapBox: `Arc<RwLock<HashMap<String, Box<dyn NyashBox>>>>` → OK
|
||||
- BufferBox: `Arc<RwLock<Vec<u8>>>` → OK
|
||||
- NyashRuntime: `box_registry: Arc<Mutex<_>>`, `box_declarations: Arc<RwLock<_>>`, `gc: Arc<dyn GcHooks>`, `scheduler: Option<Arc<dyn Scheduler>>` → OK
|
||||
- Scheduler: `SingleThreadScheduler` 内部に `Arc<Mutex<VecDeque<...>>>` → OK
|
||||
- GC Hooks: `NullGc/CountingGc` は `Send+Sync` 実装方針 → OK
|
||||
|
||||
未確認/注意:
|
||||
- プラグインBox(PluginBoxV2)の内部FFIハンドルはVM/EXE側で共有参照のみ(実体はFFI側)。クロススレッド呼出しは未サポート運用(明記要)。
|
||||
- 一部のBoxで外部資源(ファイル/ネット)を扱う場合、スレッド越境のI/O同期設計は別途(Phase 10.6d+)。
|
||||
|
||||
## 次の一手(提案)
|
||||
- マーカーTraits(例: `ThreadSafeBox`)の導入は保留(破壊的)。現時点は監査+ドキュメントで運用。
|
||||
- 並列スケジューラ(M:N)の実装は `feature` フラグで段階導入。
|
||||
@ -1,64 +0,0 @@
|
||||
Phase 10.6a — Thread-Safety Audit (TXT)
|
||||
|
||||
Scope
|
||||
- Audit Send/Sync policy for core runtime + Box families.
|
||||
- Classify: Allowed (Send+Sync), Not-Send (single-threaded), Needs-Wrapper (guarded by RwLock/mpsc/etc.).
|
||||
- Output concrete action items for hardening.
|
||||
|
||||
Legend
|
||||
- ALLOW: Safe to share/send across threads as-is.
|
||||
- NO-SEND: Must remain thread-confined; do not share.
|
||||
- WRAP: Provide wrapper/adapter to safely share (interior mutability / channels / handles).
|
||||
|
||||
Runtime Components
|
||||
- NyashRuntime: WRAP — shared via Arc; subcomponents must be audited (registry/decls RwLock OK).
|
||||
- GcHooks: ALLOW — trait requires Send+Sync; CountingGc is Send+Sync by design.
|
||||
- TypeMeta/CacheVersions: WRAP — global tables; protect via atomic/versioning (already present) + RwLock where needed.
|
||||
- Scheduler (planned): WRAP — explicit abstraction (cooperative); no global mutable state.
|
||||
|
||||
VM Values / Execution
|
||||
- VMValue: ALLOW (data) / WRAP (BoxRef) — primitives OK; BoxRef must only be shared via immutable Box API.
|
||||
- ScopeTracker: NO-SEND — per-VM; not shared. Access confined to single thread.
|
||||
- JIT Manager: WRAP — read-mostly maps; guard with RwLock if shared, or keep per-VM.
|
||||
|
||||
Builtin Boxes (initial pass)
|
||||
- IntegerBox/BoolBox/StringBox: ALLOW (immutable data semantics).
|
||||
- FloatBox (math): ALLOW (stateless ops; string-ification only).
|
||||
- ArrayBox/MapBox: WRAP — interior mutability required (RwLock); Write-Barrier remains required.
|
||||
- Buffer/IO/Net/Time/Audio/etc.: WRAP — external handles; use Arc + internal locks; expose async/channel for ops.
|
||||
- FutureBox: WRAP — already uses RwLock pattern; verify methods are non-blocking and Send+Sync where applicable.
|
||||
- ChannelBox: WRAP — backed by mpsc/crossbeam; ensure senders/receivers are Send.
|
||||
|
||||
Plugin Boxes
|
||||
- PluginBoxV2: WRAP — FFI handle; calls marshalled via TLV; all access through thread-safe host layer.
|
||||
|
||||
Interpreter/Runner Layers
|
||||
- Parser/Tokenizer/AST: ALLOW (not shared at runtime).
|
||||
- Runner (VM backend): NO-SEND — execution confined to the owning thread.
|
||||
|
||||
Policies and Enforcement
|
||||
1) Marker traits (for docs only):
|
||||
- ThreadSafeBox (Doc): Box types that are Send+Sync-safe as value semantics.
|
||||
- HandleBox (Doc): wraps external/native handles; must be behind RwLock/Mutex and non-blocking APIs.
|
||||
2) Constructor guidance:
|
||||
- For WRAP boxes, store state under RwLock/Mutex; prefer RwLock (read-mostly).
|
||||
- Avoid blocking in methods; prefer async/task dispatch via scheduler abstraction.
|
||||
3) Sharing rules:
|
||||
- VMValue::BoxRef must not be mutated without Write-Barrier when GC is active.
|
||||
- Cross-thread sharing limited to BoxRef with immutable APIs or actor-like message passing.
|
||||
4) Testing:
|
||||
- Add feature-gated thread-smoke tests (spawn two threads, share ALLOW boxes, ensure no UB).
|
||||
- Add Mutex/RwLock poisoning handling policies (map to Nyash exceptions if needed).
|
||||
|
||||
Immediate Action Items
|
||||
- [A1] Document per-Box classification in code headers (short note + rationale).
|
||||
- [A2] Ensure ArrayBox/MapBox internals use RwLock and respect Write-Barrier (already partially in place; verify set/push paths).
|
||||
- [A3] PluginBoxV2 calls remain serialized through host; confirm Send on host dispatch closures.
|
||||
- [A4] Introduce lightweight scheduler trait (single-threaded impl first); route blocking ops via scheduler.
|
||||
- [A5] Add CI job to run with NYASH_GC_BARRIER_STRICT=1 and CountingGc for barrier regression.
|
||||
|
||||
Future (10_6b/10_6c tie-ins)
|
||||
- Scheduler + cooperative safepoint policy across threads.
|
||||
- Per-thread root regions; ensure root pin/unpin remains thread-local.
|
||||
- Card marking/write barrier strategy for shared objects modified across threads (design doc first).
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
Phase 10.6b — Scheduler Prep (Single-Thread Queue)
|
||||
|
||||
What’s added
|
||||
- `src/runtime/scheduler.rs` with `Scheduler` trait and `SingleThreadScheduler`.
|
||||
- Queue + delayed tasks (spawn/spawn_after) and `poll()` to run work.
|
||||
- VM calls `scheduler.poll()` at MIR `Safepoint` to integrate cooperative scheduling.
|
||||
- Poll budget via env `NYASH_SCHED_POLL_BUDGET` (default: 1)
|
||||
- Trace via `NYASH_SCHED_TRACE=1` (diagnostic)
|
||||
|
||||
How to use (dev)
|
||||
- Build runtime with default SingleThreadScheduler (already default via builder), or inject custom via:
|
||||
`NyashRuntimeBuilder::new().with_single_thread_scheduler().build()`
|
||||
- Schedule tasks from boxes/host code via `runtime.scheduler.spawn(...)`.
|
||||
- At safepoints, queued tasks run (1 per safepoint) and due delayed tasks are enqueued.
|
||||
|
||||
How to validate quickly
|
||||
- Run any Nyash program that contains loops or function entries (safepoints exist by default).
|
||||
- Optionally enable the demo hook: set `NYASH_SCHED_DEMO=1` and run the VM backend
|
||||
to observe scheduler tasks firing at safepoints.
|
||||
- Control throughput by `NYASH_SCHED_POLL_BUDGET` (e.g., 3 runs up to 3 tasks/safepoint).
|
||||
- GC trace pairs well: set `NYASH_GC_COUNTING=1 NYASH_GC_TRACE=1` to see safepoints.
|
||||
|
||||
Next (10.6c+)
|
||||
- Expose scheduling APIs to script level (Box API).
|
||||
- Optional multi-thread scheduler implementation behind feature flag.
|
||||
@ -1,37 +0,0 @@
|
||||
Phase 10.6c — Parallel GC Design (Notes)
|
||||
|
||||
Objectives
|
||||
- Keep GC hooks and MIR sites stable while enabling parallel/stop-the-world options.
|
||||
- Introduce per-thread root regions, card marking, and coordinated safepoints.
|
||||
|
||||
Design Sketch
|
||||
1) Per-thread roots
|
||||
- Root API remains the same but live under thread-local trackers.
|
||||
- VM/engines expose `enter_root_region/pin/leave_root_region` that operate on TLS.
|
||||
- Global snapshot for diagnostics merges per-thread views (debug only).
|
||||
|
||||
2) Safepoint coordination
|
||||
- Central GC controller requests a safepoint; worker threads acknowledge at next MIR `Safepoint`.
|
||||
- Timeout/poll policy configurable; in single-threaded mode this is no-op.
|
||||
|
||||
3) Card marking / write barriers
|
||||
- Extend `BarrierKind::Write` to accept optional object metadata (future API): object id/card index.
|
||||
- For now, keep symbolic barrier only; when parallel GC is enabled, maintain a global dirty set.
|
||||
|
||||
4) Scheduler interplay
|
||||
- GC controller can schedule minor/major cycles using the Scheduler abstraction.
|
||||
- In single-threaded mode, cycles are chunked via `poll()` to avoid long pauses.
|
||||
|
||||
API Diffs (future)
|
||||
- `GcHooks::barrier(kind)` → `barrier(kind, obj: Option<ObjectId>)` (compat shim keeps old signature).
|
||||
- `GcHooks::safepoint()` may return a hint (`Proceed`, `Yield`) for engines to cooperate.
|
||||
|
||||
Migration Plan
|
||||
- Keep current single-threaded path as default.
|
||||
- Add feature flag `gc-parallel` that swaps in an implementation honoring the extended API.
|
||||
- Incrementally add: dirty set, per-thread roots, coordinated safepoint prototype.
|
||||
|
||||
Testing Strategy
|
||||
- Deterministic unit tests using SingleThreadScheduler.
|
||||
- Stress tests with STRICT barrier and TRACE=2 to validate barrier coverage and root progression.
|
||||
|
||||
@ -1,85 +0,0 @@
|
||||
Phase 10.7 — JIT Branch Wiring + Minimal ABI Extensions
|
||||
|
||||
Overview
|
||||
- Purpose: Enable real control-flow in the JIT path by wiring MIR Branch/Jump/Return to Cranelift blocks, and extend the minimal ABI to support multi-arg i64 and basic bool/f64.
|
||||
- Outcome: If/loop constructs execute natively in JIT for straight-line + branched code paths, with safe VM fallback preserved. HostCall PoC remains opt-in.
|
||||
|
||||
Goals (Must)
|
||||
- Wire MIR basic blocks to Cranelift blocks; emit `brif` and `jump` for Branch/Jump.
|
||||
- Keep Compare result usable as a branch condition (b1); where necessary, convert i64 to b1 via `icmp_imm != 0`.
|
||||
- Preserve Return behavior (already in place) and allow branching to return in both sides (no PHI required for first pass).
|
||||
- Minimal ABI: multi-argument i64 stable, bool constants lowered to 0/1, f64 constants passed through (no arithmetic yet required).
|
||||
- Safety: On JIT panic or unsupported instruction at runtime, VM fallback with logs.
|
||||
|
||||
Stretch (Nice-to-have)
|
||||
- PHI at merge points via block parameters for simple patterns (two-predecessor if-else returning a value).
|
||||
- Bench: Add a small control-flow benchmark to CLI/`examples`.
|
||||
|
||||
Non-Goals (10.7)
|
||||
- Full PHI generalization across arbitrary CFG.
|
||||
- Type-specialized calling conventions beyond i64/f64/bool minimal path.
|
||||
- Deoptimization or on-stack replacement.
|
||||
|
||||
Deliverables
|
||||
- Code: CraneliftBuilder block management + branch/jump emission.
|
||||
- Lowering updates: Branch/Jump hook uses real block IDs; Compare emits b1-friendly shape.
|
||||
- Env flags: Reuse `NYASH_JIT_EXEC/THRESHOLD/STATS/DUMP`; guard hostcalls by `NYASH_JIT_HOSTCALL`.
|
||||
- Docs: Update execution-backends.md with “JIT control-flow coverage (10.7)”.
|
||||
- Examples: `examples/jit_branch_demo.hako` (if/loop minimal).
|
||||
|
||||
Design Sketch
|
||||
1) Block Mapping
|
||||
- Build `bb_map: MirBB -> Cranelift Block` in `begin_function` based on MIR function blocks.
|
||||
- Switch to entry block, `seal_block(entry)`.
|
||||
|
||||
2) Conditions
|
||||
- Compare emits Cranelift `icmp` returning b1; avoid converting to i64 unless explicitly needed.
|
||||
- If the condition arrives as i64 (const/param), lower `icmp_imm != 0` to get b1 for `brif`.
|
||||
|
||||
3) Branch / Jump
|
||||
- `emit_branch(cond, then_bb, else_bb)` → `brif(cond_b1, then_block, []); jump(else_block, []); seal both`.
|
||||
- `emit_jump(target_bb)` → `jump(target_block, [])`.
|
||||
|
||||
4) Return
|
||||
- Keep current return emission; when branches end in return, no PHI needed.
|
||||
|
||||
5) PHI (limited)
|
||||
- For a simple diamond where both arms jump to a single merge, add one block param at merge.
|
||||
- Pass the value via `jump(merge, [val])`; read via `block-arg(merge, 0)`; return it.
|
||||
|
||||
6) ABI
|
||||
- Keep signature `(i64 x argc) -> i64?` baseline.
|
||||
- Support f64/bool consts materialization; booleans as 0/1 integers for now unless used as branch cond (then b1).
|
||||
|
||||
Implementation Plan (Tasks)
|
||||
- T1: Extend IRBuilder API (only behind `cranelift-jit`): create_block(), br_if(), jump(), seal_block(), block_param(), append_block_params_for_function_params().
|
||||
- T2: CraneliftBuilder: implement block map allocation in begin_function; store in builder state.
|
||||
- T3: LowerCore:
|
||||
- Track current MIR bb while iterating.
|
||||
- For Branch/Jump, call builder with mapped blocks and condition value hint.
|
||||
- Compare: emit b1 icmp; when Compare is used as value elsewhere, allow i64 extend as needed.
|
||||
- T4: Minimal PHI support for a single merge (optional; guarded by env `NYASH_JIT_PHI_MIN=1`).
|
||||
- T5: Add `examples/jit_branch_demo.hako` with: `if (a < b) { return 1 } else { return 2 }` and a small loop with early `return`.
|
||||
- T6: Docs update: execution-backends.md “JIT coverage 10.7” + env flags.
|
||||
- T7: Bench (optional): integrate into `--benchmark` with JIT warmup when `NYASH_JIT_EXEC=1`.
|
||||
|
||||
Validation
|
||||
- Build matrix: with/without `cranelift-jit` feature.
|
||||
- Smoke tests: run `jit_branch_demo.hako` with `NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1`.
|
||||
- Fallback verification: force a path with unsupported op to confirm VM fallback.
|
||||
- GC/scheduler: ensure safepoint path still works (unchanged).
|
||||
|
||||
Risk & Mitigation
|
||||
- Mismatch of block sealing/order → start with straight-line + simple diamond; add asserts; prefer FunctionBuilder patterns.
|
||||
- Condition type confusion (i64 vs b1) → centralize cond normalization helper.
|
||||
- PHI complexity → keep optional, limited to single value diamond.
|
||||
|
||||
Rollout
|
||||
- Phase gate by envs: `NYASH_JIT_EXEC` for enable, `NYASH_JIT_PHI_MIN` for PHI.
|
||||
- Keep `NYASH_JIT_HOSTCALL` opt-in.
|
||||
|
||||
Success Criteria
|
||||
- If/else returning constants runs fully via JIT (Cranelift) without VM fallback.
|
||||
- Simple counting loop with early exit returns correct result via JIT.
|
||||
- All tests pass with and without feature flag; VM fallback works on traps.
|
||||
|
||||
@ -1,135 +0,0 @@
|
||||
Phase 10.7 — JIT CFG/PHI/ABI Hardening (Master Plan)
|
||||
|
||||
Intent
|
||||
- Deliver a practical, observable JIT path for control flow and minimal data flow while keeping VM as the safe fallback.
|
||||
- Decompose into small, shippable sub-phases with flags and examples, minimizing blast radius.
|
||||
|
||||
Related docs
|
||||
- 10.7a details: phase_10_7a_jit_phi_cfg_and_abi_min.txt
|
||||
- Current work log: docs/development/current/CURRENT_TASK.md
|
||||
- Cranelift JIT backend notes: phase_10_cranelift_jit_backend.md
|
||||
|
||||
Flags and CLI (common across 10.7)
|
||||
- Env: NYASH_JIT_EXEC, NYASH_JIT_STATS, NYASH_JIT_STATS_JSON, NYASH_JIT_DUMP, NYASH_JIT_THRESHOLD, NYASH_JIT_PHI_MIN, NYASH_JIT_HOSTCALL
|
||||
- CLI: --jit-exec --jit-stats --jit-stats-json --jit-dump --jit-threshold N --jit-phi-min --jit-hostcall
|
||||
|
||||
Examples to validate
|
||||
- examples/jit_branch_demo.hako
|
||||
- examples/jit_loop_early_return.hako
|
||||
- examples/jit_phi_demo.hako
|
||||
- examples/jit_array_param_call.hako, jit_map_param_call.hako (when hostcall is enabled)
|
||||
|
||||
Sub-phases (10.7a → 10.7h)
|
||||
|
||||
10.7a — Minimal branch/PHI/ABI (Done or in-flight)
|
||||
- Branch wiring with b1 and i64!=0 normalization
|
||||
- Minimal PHI: single-value diamond via block param
|
||||
- Independent ABI (JitValue) with integer-first calling
|
||||
- Panic-safe dispatch (catch_unwind) and VM fallback
|
||||
- Minimal hostcall bridge (Array/Map) behind NYASH_JIT_HOSTCALL
|
||||
- Observability: unified JIT summary/JSON, lower summary (argc/phi_min), CFG edge dump (phi_min)
|
||||
|
||||
Acceptance: see 10.7a doc
|
||||
|
||||
10.7b — PHI generalization and block-parameterization
|
||||
- Support multiple PHIs in a merge block; pass N values via block params
|
||||
- LowerCore: gather PHI inputs per successor, produce explicit arg lists; handle straight merges and simple loops
|
||||
- IRBuilder API formalization:
|
||||
- ensure_block_params_i64(index, count)
|
||||
- br_if_with_args(then_idx, else_idx, then_n, else_n)
|
||||
- jump_with_args(target_idx, n)
|
||||
- CraneliftBuilder: append N I64 params per block, materialize current block params onto stack when requested
|
||||
- Validation: multi-PHI diamonds, if-else chains, early returns; keep loops as simple as possible in 10.7b
|
||||
|
||||
10.7c — Independent host-handle registry (JIT↔Host decoupling)
|
||||
- Introduce JitHandleRegistry: u64 ↔ Arc<dyn NyashBox>
|
||||
- JIT hostcalls accept/return only handles and PODs; VMValue↔JitValue boundary converts BoxRef <-> Handle via registry
|
||||
- Rooting policy: enter/pin roots for handles crossing the boundary; leave on return
|
||||
- Flags: NYASH_JIT_HOSTCALL=1 (still gated); add NYASH_JIT_HANDLE_DEBUG for dumps
|
||||
- Deliverables: array/map operations via handles, no direct VMValue access on JIT side
|
||||
|
||||
10.7d — Side-effect boundary and hostcall coverage expansion
|
||||
- Keep side-effecting ops (print/IO) on VM for now; document deopt path
|
||||
- Expand safe hostcalls (read-only or confined):
|
||||
- String.len / slice basics (POD returns)
|
||||
- Map.size; Map.get with integer and string keys (key boxing handled at boundary)
|
||||
- Record effect categories on lowered calls for future optimizer (metadata only)
|
||||
|
||||
10.7e — CFG diagnostics and visualization
|
||||
- Add DOT export for CLIF CFG with block params and PHI bindings
|
||||
- Env: NYASH_JIT_DOT=path.dot (produces per-function graph)
|
||||
- Optional: ASCII CFG summary for CI logs
|
||||
- Cross-check with VM-side MIR printer for block and PHI consistency
|
||||
|
||||
10.7f — JitConfigBox (configuration as a Box)
|
||||
- Encapsulate all JIT toggles into a runtime-managed box (JitConfigBox)
|
||||
- Harmonize env/CLI with programmatic overrides for tests
|
||||
- Feed config into JIT engine and lowerers (no direct env reads inside hot paths)
|
||||
- Serialization: dump/load config JSON for reproducible runs
|
||||
|
||||
10.7g — Stability, tests, and benchmarks
|
||||
- Golden tests: ensure JIT/VM outputs match on curated programs
|
||||
- Fallback ratio regression guard: alert when fallback_rate spikes beyond threshold
|
||||
- JSON schema stability for stats; include version field
|
||||
- Microbenchmarks: branch-heavy, phi-heavy, and hostcall-heavy cases; gated perf checks
|
||||
|
||||
10.7h — Type widening for native ABI
|
||||
- Add native F64 and Bool parameter/return paths in CLIF
|
||||
- Condition handling: keep b1 where possible; map Bool to b1 cleanly
|
||||
- Conversions: explicit i64<->f64 ops in lowerer where needed (no silent truncation)
|
||||
- Update adapter and closure trampoline to select proper function signatures (arity×type shapes)
|
||||
|
||||
Out of scope for 10.7 (shift to 10.8/10.9)
|
||||
- Global register allocation strategies or codegen-level optimizations
|
||||
- Deoptimization machinery beyond simple VM fallback
|
||||
- Advanced exception propagation across JIT/VM boundary
|
||||
|
||||
Risks and mitigation
|
||||
- PHI N-arity correctness: introduce targeted unit tests over synthetic MIR
|
||||
- Handle registry leaks: counting diagnostics, strict mode; tie roots to scope regions
|
||||
- CLIF block-param misuse: deterministic block order + seal discipline + assertions in builder
|
||||
|
||||
Verification checklist (roll-up)
|
||||
- cargo check (± --features cranelift-jit)
|
||||
- Run examples with JIT flags; diff with pure VM runs
|
||||
- Inspect: unified JIT summary/JSON, lower logs, CFG dumps/DOT
|
||||
- Leak/roots checks when NYASH_GC_TRACE=1/2/3 and strict barrier mode is on
|
||||
|
||||
Suggested timeline (tentative)
|
||||
- 10.7a: Minimal branch/PHI/ABI (done / in-flight)
|
||||
- 10.7b: PHI generalization + builder API formalization (1–2 days)
|
||||
- 10.7c: Host-handle registry PoC (1–2 days)
|
||||
- 10.7d/e: Hostcall coverage + CFG DOT (2–3 days)
|
||||
- 10.7f: JitConfigBox + integration (1 day)
|
||||
- 10.7g/h: QA + type widening for f64/bool (2–4 days)
|
||||
|
||||
10.7z — Follow-ups and Open Items (post-10.7)
|
||||
- b1 PHI tagging robustness
|
||||
- Problem: Provenance can be obscured by Load/Store and multi-step copies; (b1) tag may be missed in dumps.
|
||||
- Action:
|
||||
- Add a lightweight boolean-lattice analysis over MIR to classify boolean-producing values independent of path shape.
|
||||
- Extend dump to include phi_summary JSON or structured rows when NYASH_JIT_STATS_JSON is on.
|
||||
- Placement: 10.7g (stability/tests) — does not block 10.7 close.
|
||||
|
||||
- VM f64 arithmetic/compare parity
|
||||
- Problem: VM backend currently errors on f64 BinOp/Compare; JIT (Cranelift) supports f64 when enabled.
|
||||
- Action: Implement f64 ops in VM or add consistent auto-promotion; add golden tests.
|
||||
- Placement: 10.8 (VM parity/perf) — out-of-scope for 10.7.
|
||||
|
||||
- Native b1 ABI in function signatures
|
||||
- Problem: Toolchain capability for b1 return/params is currently disabled.
|
||||
- Action: Keep centralized switch; add CI probe to flip automatically when supported; wire return path fully.
|
||||
- Placement: 10.7h or later (gated by toolchain).
|
||||
|
||||
- Stats/diagnostics polish
|
||||
- Action: Version the unified JIT JSON schema; expose phi(b1) slot counts in JSON; enrich JitStatsBox with summary/topN (partially done).
|
||||
- Placement: 10.7g.
|
||||
|
||||
- Build warnings (unexpected cfg: llvm)
|
||||
- Problem: Warning noise from unused/unknown cfg.
|
||||
- Action: Declare feature flags in Cargo.toml or gate code behind existing features; optionally silence for non-supported builds.
|
||||
- Placement: 10.7g (cleanup) — non-blocking.
|
||||
|
||||
- Documentation sync
|
||||
- Action: Add a "JIT quick flags" section with common env/CLI combos; ensure CURRENT_TASK and examples remain aligned.
|
||||
- Placement: 10.7e (docs) — non-blocking.
|
||||
@ -1,92 +0,0 @@
|
||||
Phase 10.7a — JIT Branch/PHI/Independent ABI: Minimal Path Hardening (Plan)
|
||||
|
||||
Purpose
|
||||
- Solidify the first functional slice of the JIT control-flow path:
|
||||
- Branch wiring (b1 and i64!=0 normalization)
|
||||
- Minimal PHI via block parameters (single-value diamond)
|
||||
- Independent ABI (JitValue) and safe dispatch + fallback
|
||||
- Observable, toggleable, and easy to verify via flags + examples
|
||||
|
||||
Scope (10.7a only)
|
||||
1) Minimal PHI handoff
|
||||
- LowerCore: detect single-PHI merge; pass i64 value via block param
|
||||
- CraneliftBuilder: ensure block param (I64), push/pop on branch/jump with args
|
||||
- Flag gate: NYASH_JIT_PHI_MIN=1
|
||||
|
||||
2) Branch wiring and condition normalization
|
||||
- Keep compare result on stack as b1 when possible
|
||||
- If top-of-stack is I64, normalize by icmp_imm != 0
|
||||
- Implement br_if/jump to pre-created blocks (deterministic order)
|
||||
|
||||
3) Independent ABI (minimum viable)
|
||||
- JitValue(I64/F64/Bool/Handle) in/out; normalize non-i64 args to i64 for now
|
||||
- TLS split: legacy VM args (for hostcalls) and JIT args
|
||||
- Engine.execute_handle uses catch_unwind; panic → VM fallback with stats
|
||||
|
||||
4) Minimal hostcall bridge (safe; off by default)
|
||||
- Symbols: nyash.array.{len,get,set,push}, nyash.map.{size}
|
||||
- Gate: NYASH_JIT_HOSTCALL=1
|
||||
- Only integer indices/values (PoC); other types map to handles later
|
||||
|
||||
5) Observability and ergonomics
|
||||
- Flags: NYASH_JIT_EXEC, NYASH_JIT_STATS, NYASH_JIT_STATS_JSON, NYASH_JIT_DUMP, NYASH_JIT_THRESHOLD, NYASH_JIT_PHI_MIN, NYASH_JIT_HOSTCALL
|
||||
- CLI: --jit-exec --jit-stats --jit-stats-json --jit-dump --jit-threshold N --jit-phi-min --jit-hostcall
|
||||
- Unified JIT summary on VM exit (sites/compiled/hits/exec_ok/trap/fallback_rate)
|
||||
- Lower log includes argc/phi_min + CFG light dump (phi edges) when NYASH_JIT_DUMP=1
|
||||
|
||||
Non-Goals (later 10.7b+)
|
||||
- Full PHI generalization (multiple values, loops, complex CFG forms)
|
||||
- Non-i64 native path (true F64/Bool return/params in CLIF)
|
||||
- Side-effect instruction lowering (print, IO) — keep in VM path
|
||||
- Host handle registry for real object bridging (u64↔Arc<dyn NyashBox>)
|
||||
|
||||
Deliverables
|
||||
- Working minimal PHI + branch JIT execution on curated examples:
|
||||
- examples/jit_branch_demo.hako
|
||||
- examples/jit_loop_early_return.hako
|
||||
- examples/jit_phi_demo.hako (single-PHI diamond)
|
||||
- Fallback correctness: traps/panic → VM path; results match VM
|
||||
- Configurable via CLI flags; metrics visible via JIT summary/JSON
|
||||
|
||||
Acceptance Criteria
|
||||
- With: --backend vm --jit-exec --jit-stats --jit-threshold 1
|
||||
- For branch/phi examples, JIT executes without panic
|
||||
- VM fallback occurs only for unsupported ops (logged)
|
||||
- JIT summary shows exec_ok > 0 and reasonable fallback_rate
|
||||
- With: --jit-phi-min
|
||||
- CFG dump lists phi_min edges and blocks count
|
||||
- Results match the same program without JIT enabled
|
||||
|
||||
Risk & Mitigation
|
||||
- Mismatch between VMValue and JitValue adapters
|
||||
- Mitigation: normalize non-i64 to i64 defensively; expand tests on adapters
|
||||
- Cranelift block parameter misuse
|
||||
- Mitigation: deterministic block order and explicit ensure_block_param_i64()
|
||||
- Panic in hostcall stubs (unexpected Box types)
|
||||
- Mitigation: gated by NYASH_JIT_HOSTCALL=1; default off; fallback to VM on panic
|
||||
|
||||
Verification Checklist
|
||||
- cargo check (w/ and w/o --features cranelift-jit)
|
||||
- Run examples with JIT flags; compare outputs with pure VM
|
||||
- Inspect logs: lower summary + CFG dump + unified summary/JSON
|
||||
|
||||
Timeline (10.7a)
|
||||
Day 1:
|
||||
- Finalize ABI normalization and branch wiring; add unified stats (done)
|
||||
- Wire CLI flags and JSON stats (done)
|
||||
Day 2:
|
||||
- Harden minimal PHI path and CFG dump (done)
|
||||
- Curate examples and sanity-run on flags
|
||||
Day 3:
|
||||
- Stabilize logging format, trim rough edges, doc polish
|
||||
→ Then roll into 10.7b (multi-PHI, multi-arg block params, real handle registry)
|
||||
|
||||
Follow-ups (10.7b/10.7c seeds)
|
||||
- Host handle registry (u64↔Arc) and type-safe bridging
|
||||
- True F64/Bool native ABI, multi-arg params/returns
|
||||
- CFG visualization improvements (dot export) and JitConfigBox
|
||||
|
||||
Refs
|
||||
- docs/development/current/CURRENT_TASK.md (10_7 items)
|
||||
- src/jit/{lower,engine,manager,abi,rt}/
|
||||
- examples: jit_* demos
|
||||
@ -1,45 +0,0 @@
|
||||
# Phase 10.7h — Native ABI Types (F64/Bool)
|
||||
|
||||
Goal
|
||||
- Extend the minimal i64-only JIT ABI to support f64 and bool as native parameter/return types in CLIF.
|
||||
|
||||
Principles
|
||||
- Keep JIT independent from VM internals (use JitValue + adapters at boundary)
|
||||
- Avoid silent truncation; perform explicit conversions in the lowerer
|
||||
- Maintain safety-first fallback to VM for unsupported ops
|
||||
|
||||
Plan
|
||||
1) JitValue widening
|
||||
- JitValue already has I64/F64/Bool/Handle — keep this as the ABI surface
|
||||
- Adapter: refine to/from VMValue mappings (no lossy coercion by default)
|
||||
|
||||
2) CLIF signature selection
|
||||
- Augment CraneliftBuilder to build signatures based on (arity × type shape)
|
||||
- Start with small shapes: (I64|F64|Bool)* → I64|F64|Bool
|
||||
- Closure trampoline: transmute to matching extern "C" fn type; dispatch by shape id
|
||||
|
||||
3) Condition handling
|
||||
- Bool: prefer b1 in IR; allow i64!=0 normalization when comparing integers
|
||||
- Comparisons yield b1; lower branch consumes b1 directly
|
||||
|
||||
4) Conversions in lowerer (explicit only)
|
||||
- add_const_f64, add_convert_{i64_to_f64, f64_to_i64}
|
||||
- prohibit implicit int<->float coercion in arithmetic; gate conversions via explicit MIR ops or intrinsics
|
||||
|
||||
5) Observability and flags
|
||||
- NYASH_JIT_NATIVE_F64=1 / NYASH_JIT_NATIVE_BOOL=1 to enable paths
|
||||
- Dump: show chosen signature shape and conversions when NYASH_JIT_DUMP=1
|
||||
|
||||
6) Rollout
|
||||
- Phase A: const/binop/ret for f64; comparisons yield b1
|
||||
- Phase B: mixed-type ops via explicit converts
|
||||
- Phase C: HostCall bridging for f64/bool PODs (read-only first)
|
||||
|
||||
Risks / Mitigation
|
||||
- Signature explosion: start with a few common shapes; fallback to i64 path
|
||||
- Platform ABI mismatches: rely on Cranelift default call conv; e2e-perf and correctness first
|
||||
|
||||
Acceptance
|
||||
- Examples with pure f64 pipelines run under JIT with matching results vs VM
|
||||
- No silent lossy conversions; conversions visible in MIR/Lower logs
|
||||
|
||||
@ -1,172 +0,0 @@
|
||||
# Phase 10.8: 統一デバッグシステム - DeepInspectorBoxとグローバルデバッグ整理
|
||||
|
||||
作成日: 2025-08-27
|
||||
発見者: ニャー
|
||||
参照元: docs/ideas/other/2025-08-25-unified-box-design-deep-analysis.md
|
||||
|
||||
## 🚨 現在の問題
|
||||
|
||||
### 1. デバッグ環境変数の乱立
|
||||
現在20個以上の環境変数が散在:
|
||||
- `NYASH_VM_STATS=1`
|
||||
- `NYASH_VM_DEBUG_BOXCALL=1`
|
||||
- `NYASH_DEBUG_PLUGIN=1`
|
||||
- `NYASH_NET_LOG=1`
|
||||
- `NYASH_JIT_THRESHOLD=1`
|
||||
- ... など多数
|
||||
|
||||
### 2. 統一されていないデバッグ体験
|
||||
- VM、プラグイン、JIT、ネットワークなど各コンポーネントが独自のデバッグフラグ
|
||||
- 複数の環境変数を組み合わせる必要がある
|
||||
- 何をONにすればいいか分かりにくい
|
||||
|
||||
## 🌟 提案: 統一デバッグシステム
|
||||
|
||||
### 1. 環境変数の整理統合
|
||||
|
||||
```bash
|
||||
# Before (現在)
|
||||
NYASH_VM_STATS=1 NYASH_VM_DEBUG_BOXCALL=1 NYASH_NET_LOG=1 ./nyash
|
||||
|
||||
# After (提案)
|
||||
NYASH_DEBUG=vm,boxcall,net ./nyash
|
||||
```
|
||||
|
||||
### 2. デバッグレベル制御
|
||||
|
||||
```bash
|
||||
# シンプルなレベル制御
|
||||
NYASH_DEBUG_LEVEL=0 # OFF
|
||||
NYASH_DEBUG_LEVEL=1 # 基本情報のみ
|
||||
NYASH_DEBUG_LEVEL=2 # 詳細情報
|
||||
NYASH_DEBUG_LEVEL=3 # すべて
|
||||
|
||||
# カテゴリ別レベル
|
||||
NYASH_DEBUG=vm:2,net:1,jit:3
|
||||
```
|
||||
|
||||
### 3. プリセット(よく使う組み合わせ)
|
||||
|
||||
```bash
|
||||
# プリセット
|
||||
NYASH_DEBUG_PRESET=basic # 基本的なデバッグ情報
|
||||
NYASH_DEBUG_PRESET=perf # パフォーマンス分析用
|
||||
NYASH_DEBUG_PRESET=network # ネットワーク問題調査用
|
||||
NYASH_DEBUG_PRESET=memory # メモリリーク調査用
|
||||
NYASH_DEBUG_PRESET=all # すべて有効
|
||||
```
|
||||
|
||||
## 🔍 DeepInspectorBox - Everything is Debugの実現
|
||||
|
||||
### グローバルシングルトンデバッガー
|
||||
|
||||
```nyash
|
||||
// グローバルに1つだけ存在する統一デバッガー
|
||||
static box DeepInspectorBox {
|
||||
public { enabled }
|
||||
private {
|
||||
boxCreations, methodCalls, fieldAccess,
|
||||
memorySnapshots, referenceGraph, performanceMetrics
|
||||
}
|
||||
|
||||
// === 簡単な有効化 ===
|
||||
enable(categories) {
|
||||
// "vm,net,memory" のようなカテゴリ文字列を解析
|
||||
me.parseAndEnableCategories(categories)
|
||||
}
|
||||
|
||||
// === プリセット対応 ===
|
||||
usePreset(presetName) {
|
||||
match presetName {
|
||||
"basic" => me.enable("vm,error")
|
||||
"perf" => me.enable("vm,boxcall,stats")
|
||||
"network" => me.enable("net,plugin,tlv")
|
||||
"memory" => me.enable("alloc,gc,leak")
|
||||
"all" => me.enable("*")
|
||||
}
|
||||
}
|
||||
|
||||
// === 統合ログ出力 ===
|
||||
log(category, level, message) {
|
||||
if me.shouldLog(category, level) {
|
||||
local formatted = me.formatLog(category, level, message)
|
||||
me.output(formatted)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### MIRレベルでの統一実装
|
||||
|
||||
```rust
|
||||
// MIR生成時にデバッグフックを埋め込み
|
||||
impl MirBuilder {
|
||||
fn build_new_box(&mut self, type_id: TypeId) -> ValueId {
|
||||
let result = self.push(NewBox { type_id });
|
||||
|
||||
// デバッグモード時のみ
|
||||
if self.debug_enabled {
|
||||
self.push(DebugHook {
|
||||
event: DebugEvent::BoxCreated,
|
||||
type_id,
|
||||
value: result,
|
||||
});
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 実装計画
|
||||
|
||||
### Phase 10.8a: 環境変数統合(3日)
|
||||
- [ ] 統一パーサー実装(`NYASH_DEBUG`解析)
|
||||
- [ ] レベル制御システム
|
||||
- [ ] プリセット定義
|
||||
- [ ] 既存環境変数との互換性層
|
||||
|
||||
### Phase 10.8b: DeepInspectorBox基礎(1週間)
|
||||
- [ ] グローバルシングルトン実装
|
||||
- [ ] カテゴリ管理システム
|
||||
- [ ] 基本的なログ収集
|
||||
- [ ] 出力フォーマッター
|
||||
|
||||
### Phase 10.8c: MIR統合(1週間)
|
||||
- [ ] DebugHook命令追加
|
||||
- [ ] MirBuilderへのフック埋め込み
|
||||
- [ ] VMでのDebugHook実行
|
||||
- [ ] JITでのデバッグ情報保持
|
||||
|
||||
### Phase 10.8d: 高度な機能(2週間)
|
||||
- [ ] メモリリーク検出
|
||||
- [ ] 参照グラフ構築
|
||||
- [ ] P2P非同期フロー追跡
|
||||
- [ ] パフォーマンスプロファイリング
|
||||
|
||||
## 🎯 期待される効果
|
||||
|
||||
### 1. 使いやすさ向上
|
||||
- 1つの環境変数で制御
|
||||
- 分かりやすいプリセット
|
||||
- 統一されたログフォーマット
|
||||
|
||||
### 2. デバッグ効率向上
|
||||
- 必要な情報だけを表示
|
||||
- カテゴリ別フィルタリング
|
||||
- レベル別詳細度制御
|
||||
|
||||
### 3. 保守性向上
|
||||
- 新しいデバッグ機能の追加が容易
|
||||
- 統一されたインターフェース
|
||||
- MIRレベルでの一元管理
|
||||
|
||||
## ✅ 成功基準
|
||||
|
||||
1. **環境変数の数**: 20個以上 → 3個以下
|
||||
2. **デバッグ有効化**: 複雑なコマンド → `NYASH_DEBUG=basic`
|
||||
3. **統一体験**: すべてのコンポーネントで同じデバッグインターフェース
|
||||
|
||||
---
|
||||
|
||||
*Everything is Box, Everything is Debug - 統一されたデバッグ体験へ*
|
||||
@ -1,85 +0,0 @@
|
||||
# Phase 10.7: fromキーワード一貫性修正
|
||||
|
||||
作成日: 2025-08-27
|
||||
発見者: ニャー
|
||||
|
||||
## 🚨 現在の問題
|
||||
|
||||
### 言語仕様と実装の不一致
|
||||
- **言語仕様**: `from Parent.method()` (2025-08-11完全明示デリゲーション革命で決定)
|
||||
- **実装の一部**: まだ`super`という用語が残っている可能性
|
||||
|
||||
### 影響範囲
|
||||
主にRustの`use super::*`(モジュールインポート)なので言語仕様への影響は限定的だが、以下の確認が必要:
|
||||
1. エラーメッセージ内の文言
|
||||
2. ドキュメントやコメント内の記述
|
||||
3. 内部変数名・関数名での使用
|
||||
|
||||
## 🔧 修正内容
|
||||
|
||||
### 1. エラーメッセージの確認
|
||||
```rust
|
||||
// 例: エラーメッセージで"super"を使っていないか確認
|
||||
"Cannot find super class" → "Cannot find parent box for delegation"
|
||||
```
|
||||
|
||||
### 2. ドキュメント・コメントの統一
|
||||
```rust
|
||||
// Before
|
||||
// Call super method
|
||||
|
||||
// After
|
||||
// Call parent method via from delegation
|
||||
```
|
||||
|
||||
### 3. 内部実装での用語統一(必要に応じて)
|
||||
```rust
|
||||
// 変数名や内部メソッド名での統一
|
||||
super_call() → from_call()
|
||||
SuperMethodCall → FromMethodCall
|
||||
```
|
||||
|
||||
## 📊 優先度評価
|
||||
|
||||
- **重要度**: 中(言語仕様の一貫性)
|
||||
- **緊急度**: 低(機能的には問題ない)
|
||||
- **実装難度**: 低(主に文言修正)
|
||||
|
||||
## 🎯 実装計画
|
||||
|
||||
### Phase 10.7a: 調査フェーズ(1日)
|
||||
- [ ] エラーメッセージ内の"super"使用箇所を特定
|
||||
- [ ] ドキュメント内の不整合を洗い出し
|
||||
- [ ] テストケース内の文言確認
|
||||
|
||||
### Phase 10.7b: 修正フェーズ(1日)
|
||||
- [ ] エラーメッセージの文言修正
|
||||
- [ ] ドキュメント更新
|
||||
- [ ] 必要に応じて内部変数名の統一
|
||||
|
||||
### Phase 10.7c: 検証フェーズ(半日)
|
||||
- [ ] 修正後の動作確認
|
||||
- [ ] エラーメッセージの表示確認
|
||||
- [ ] ドキュメントの整合性チェック
|
||||
|
||||
## 📝 Nyashの哲学との整合性
|
||||
|
||||
### fromキーワードの意義
|
||||
- **明示性**: どの親のどのメソッドかを完全に明示
|
||||
- **統一性**: 宣言(`box Child from Parent`)と呼び出し(`from Parent.method()`)で同じキーワード
|
||||
- **初学者フレンドリー**: 「〜から」という直感的な表現
|
||||
|
||||
### superを使わない理由
|
||||
- 多重デリゲーション時に曖昧
|
||||
- 他言語の概念を引きずらない
|
||||
- Nyash独自の哲学を貫く
|
||||
|
||||
## ✅ 期待される効果
|
||||
|
||||
1. **一貫性**: 言語仕様と実装の完全な一致
|
||||
2. **学習性**: 初学者が混乱しない統一された用語
|
||||
3. **独自性**: Nyashらしい設計思想の徹底
|
||||
|
||||
---
|
||||
|
||||
*「from」こそがNyashの明示的デリゲーションの象徴*
|
||||
@ -1,155 +0,0 @@
|
||||
# Phase 10.9 – Builtin-Box JIT Support(Box-First Plan)
|
||||
|
||||
目的: Nyashスクリプト → VM(基準)→ JIT(段階導入)。
|
||||
まずは「読み取り系」をJITで安全に通し、箱で問題点を包んで順に拡張する。
|
||||
|
||||
## 🎯 ゴール(DoD)
|
||||
- 機能: String/Array/Map の読み取りAPIが JIT 経路で VM と一致
|
||||
- length/isEmpty/charCodeAt, Array.get, Map.size/has
|
||||
- 境界: 署名不一致・未対応は VM フォールバック(理由はイベントJSONに記録)
|
||||
- 箱: Policy/Events/Registry を 1 箇所参照(切替点の一本化)
|
||||
- 観測: JSONL イベントが最小1件以上出力(オプトイン)
|
||||
|
||||
## 🧱 先に積む箱(最小)
|
||||
- JitConfigBox(設定)
|
||||
- exec/stats/dump/phi_min/hostcall/native_f64/native_bool/threshold を `apply()` でenv反映
|
||||
- `toJson()/fromJson()/summary()` で可視化
|
||||
- JitPolicyBox(ポリシー)
|
||||
- read_only/hostcall_whitelist。書込系は既定で拒否(jit-direct等の安全弁)
|
||||
- JitEventsBox(観測)
|
||||
- compile/execute/fallback/trap を 1行JSON(標準出力 or ファイル)で記録
|
||||
- HostcallRegistryBox(レジストリ)
|
||||
- 許可HostCallと args/ret 署名(唯一の切替点)。不一致は `sig_mismatch`
|
||||
- FrameSlotsBox(スロット)
|
||||
- ptr→slot の割付と型注釈(v0は i64 のみ)
|
||||
- CallBoundaryBox(境界)
|
||||
- JIT↔VM の薄い呼出し点(型変換の一本化)。将来多関数へ拡張
|
||||
|
||||
最小原則: 箱を先に置く(no-op/ログでもOK)→ 切替点を1箇所に固定 → その箱の内部を順に強化。
|
||||
|
||||
## 🛣️ 実行経路の設計(概要)
|
||||
1) Runner: CLI/env→`JitConfig`→TLSへ反映(env直読を排除)
|
||||
2) LowerCore: `jit::config::current()` を参照し、BoxCall/Load/Store/Branch/PHIを最小下ろし
|
||||
3) HostCall: Handle経由で read-only を通す(mutating は Policy で拒否)
|
||||
4) Fallback: 未対応/署名不一致/ポリシー違反は VM 実行へ委譲
|
||||
5) Events: `JitEventsBox` 経由で allow/fallback/trap を JSONL 出力
|
||||
|
||||
## 🔢 対象API(v0)
|
||||
- ArrayBox: `length`, `get`, `isEmpty`, `push/set`(mutatingは拒否)
|
||||
- MapBox: `size`, `has`, `get`, `set`(mutatingは拒否)
|
||||
- StringBox: `length`, `isEmpty`, `charCodeAt`
|
||||
- Math(薄接続): `sin/cos/abs/min/max`(署名一致のみ allow を記録、実体はVMへ)
|
||||
|
||||
## 🗺️ マイルストーン
|
||||
### 10.9-α(足場)
|
||||
- JitPolicyBox v0: read-only/whitelist を箱へ移動
|
||||
- JitEventsBox v0: compile/execute の JSONL イベント(オプトイン)
|
||||
- ドキュメント: 再起動チェック/箱の役割を追記
|
||||
|
||||
### 10.9-β(読み取りカバレッジ)
|
||||
- HostcallRegistryBox v0: String/Array/Map 読み取り API の登録・署名検査
|
||||
- LowerCore: BoxCall read-only 経路を Registry/Policy 参照に切替
|
||||
- E2E: `length/isEmpty/charCodeAt/get/size/has` の一致(jit-direct + VM)
|
||||
|
||||
### 10.9-γ(生成の足場)
|
||||
- CallBoundaryBox v0: JIT→VMで `new` 等を委譲(薄い箱)
|
||||
- `new StringBox/IntegerBox/ArrayBox` の最小経路(方針次第で jit-direct は拒否)
|
||||
|
||||
### 10.9-δ(書き込みの導線のみ)
|
||||
- JitPolicyBox: 書込許可スイッチ(既定OFF)
|
||||
- LowerCore: 書込命令は Policy 参照で拒否/委譲/許可(1箇所で判断)
|
||||
|
||||
## ✅ すぐ使えるチェック
|
||||
- ビルド
|
||||
- `cargo build --release --features cranelift-jit`
|
||||
- 主要フラグ
|
||||
- `NYASH_JIT_EXEC=1` `NYASH_JIT_THRESHOLD=1`
|
||||
- `NYASH_JIT_EVENTS=1`(標準出力へJSON)
|
||||
- 任意: `NYASH_JIT_EVENTS_PATH=target/nyash/jit-events.jsonl`
|
||||
- 代表サンプル(VM経由でJITパス通過)
|
||||
- 成功: `./target/release/nyash --backend vm examples/jit_hostcall_len_string.hako`
|
||||
- 失敗: `NYASH_JIT_EVENTS=1 ./target/release/nyash --backend vm examples/jit_hostcall_array_append.hako`
|
||||
- 境界: `NYASH_JIT_EVENTS=1 ./target/release/nyash --backend vm examples/jit_hostcall_math_sin_mismatch.hako`
|
||||
- 署名一致(allow観測): `NYASH_JIT_EVENTS=1 ./target/release/nyash --backend vm examples/jit_hostcall_math_sin_allow_float.hako`
|
||||
- 関数スタイル(math.*): `NYASH_JIT_NATIVE_F64=1 NYASH_JIT_EVENTS=1 ./target/release/nyash --backend vm examples/jit_math_function_style_sin_float.hako`
|
||||
- `cos/abs/min/max` も同様のサンプルあり
|
||||
- 詰まったら
|
||||
- `--features cranelift-jit` が付いているか
|
||||
- イベントJSONに `fallback/trap` の理由が出ているか
|
||||
- `cargo clean -p nyash-rust` → 再ビルド
|
||||
|
||||
## 🧪 検証と観測
|
||||
- 統合JIT統計(テキスト/JSON): sites/compiled/hits/exec_ok/trap/fallback_rate/handles
|
||||
- `JitStatsBox.perFunction()` で関数単位の統計(JSON配列)
|
||||
- CFG/PHIダンプ: `NYASH_JIT_DUMP=1`、`NYASH_JIT_DOT=path.dot`(最小)
|
||||
- b1正規化カウンタ: `b1_norm_count`(分岐条件/PHI)
|
||||
- HostCallイベント: `argc`/`arg_types`/`reason`でデバッグ容易化(mutatingは `policy_denied_mutating`)
|
||||
|
||||
### 🔎 HostCallイベントの基準(10.9-β)
|
||||
- 受け手が関数パラメータ(param)の場合は JIT直実行(allow/sig_ok)を基本にイベント出力
|
||||
- Map.get(Handle, I64): `id: nyash.map.get_h`, `arg_types: ["Handle","I64"]`
|
||||
- Map.get(Handle, Handle): `id: nyash.map.get_hh`, `arg_types: ["Handle","Handle"]`
|
||||
- length/isEmpty/charCodeAt/size 等も `*_h`(Handle受け)でallow
|
||||
- 受け手がparamでない場合は VMへフォールバック(fallback/receiver_not_param)をイベントで記録(読み取り系の可視化を保証)
|
||||
- 例: `id: nyash.any.length_h`, `decision: fallback`, `reason: receiver_not_param`
|
||||
- 数値緩和: `NYASH_JIT_HOSTCALL_RELAX_NUMERIC=1` または `NYASH_JIT_NATIVE_F64=1` で `I64→F64` コアーションを許容(sig_okに影響)
|
||||
|
||||
### 🧪 代表サンプル(E2E)
|
||||
```bash
|
||||
# math.*(関数スタイル): 署名一致でallow、戻りFloat表示
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_NATIVE_F64=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_math_function_style_min_float.hako
|
||||
|
||||
# Map.get(パラメータ受け+Handleキー → HH直実行)
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_map_get_param_hh.hako
|
||||
|
||||
# Map.get(非パラメータ受け → fallback記録)
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_hostcall_map_get_handle.hako
|
||||
```
|
||||
|
||||
### ⚙️ Quick flags(イベント観測を確実に)
|
||||
- `NYASH_JIT_EVENTS=1` のとき Runner が `NYASH_JIT_THRESHOLD=1` を自動適用(未指定の場合)
|
||||
- 1回目からLowerが走り、allow/fallbackのイベントが必ず出る
|
||||
- 明示的に `NYASH_JIT_THRESHOLD` を指定した場合はそちらを優先
|
||||
|
||||
## ⚠️ リスクとその箱での緩和
|
||||
- 署名不一致(args/ret)
|
||||
- HostcallRegistryBox で一元検査。不一致は `sig_mismatch` でイベント記録→VMへ
|
||||
- mutatingの混入
|
||||
- JitPolicyBox.read_only で抑止。Registryの Mutating 分類と併用
|
||||
- 型崩れ/ABIの揺れ
|
||||
- `JitValue`(I64/F64/Bool/Handle)へ統一、変換は境界1箇所
|
||||
- 観測不足
|
||||
- JitEventsBox の粒度を最小から用意(必要に応じ拡張)
|
||||
|
||||
## 🔧 実装ノート(現状)
|
||||
- Config: Rust側 `jit::config::JitConfig` に集約。Nyash側は JitConfigBox で操作
|
||||
- LowerCore: BoxCallの read-only は Registry/Policyに委譲。math.* は署名一致なら allow を記録(実行はVM)
|
||||
- Handle: `rt::handles` による u64→Arc<Box>。JIT↔ホストをVM型非参照で独立
|
||||
- 数値緩和: `NYASH_JIT_HOSTCALL_RELAX_NUMERIC=1` で i64→f64 コアーションを許容(既定は `native_f64=1` 時に有効)。`JitConfigBox.set_flag("relax_numeric", true)` でも切替可能
|
||||
|
||||
## 📌 次の拡張(10.9の後)
|
||||
- f64ネイティブ最小経路(`NYASH_JIT_NATIVE_F64=1`)の拡充
|
||||
- Boolネイティブ(b1)署名サポート(ツールチェーンcapに連動)
|
||||
- HostCallブリッジの拡大(Map.getの多型キー、String操作の追加)
|
||||
- CallBoundaryBox経由の `new`/副作用命令の段階的JIT化
|
||||
|
||||
## ✳️ 10.9-δ 書き込みの導線(運用)
|
||||
- 既定ポリシー: read_only(`NYASH_JIT_READ_ONLY=1`)で mutating はフォールバック(`reason: policy_denied_mutating`)。
|
||||
- JitPolicyBox でopt-in:
|
||||
```nyash
|
||||
P = new JitPolicyBox()
|
||||
P.set("read_only", true)
|
||||
P.addWhitelist("nyash.array.push_h") // 個別に許可
|
||||
// またはプリセット:
|
||||
P.enablePreset("mutating_minimal") // Array.push_h を許可
|
||||
```
|
||||
- イベント方針:
|
||||
- 受け手=param: allow/sig_ok(whitelist/オフ時はfallback/policy_denied_mutating)
|
||||
- 受け手≠param: fallback/receiver_not_param(可視化を保証)
|
||||
|
||||
---
|
||||
|
||||
最短ルート: 箱(Policy/Events/Registry/Boundary)を先に置き、読み取り系でJITを安全に通す→観測を増やす→署名とポリシーの一本化で切替点を固定→必要最小限のネイティブ型(f64/b1)を段階導入。
|
||||
@ -1,220 +0,0 @@
|
||||
# Phase 10: Classic C Applications Migration to Nyash
|
||||
|
||||
## 🎯 概要
|
||||
3つの著名なCアプリケーションをNyashに移植し、新実装された高度なメモリ管理機能を実戦テストする。
|
||||
|
||||
## 📦 移植対象アプリケーション(優先順位順)
|
||||
|
||||
### 1. 🌐 **Tinyproxy** - ゼロコピー判定機能の実証
|
||||
**元実装**: https://github.com/tinyproxy/tinyproxy
|
||||
**サイズ**: ~5000行C、軽量HTTPプロキシサーバー
|
||||
**Nyash移植目標**: `apps/tinyproxy_nyash/`
|
||||
|
||||
#### 🔍 **ゼロコピー判定テストケース**
|
||||
```nyash
|
||||
// HTTPリクエスト転送でのメモリ効率検証
|
||||
static box ProxyServer {
|
||||
init { upstream_buffer, downstream_buffer }
|
||||
|
||||
relay_data(client_data) {
|
||||
// ⭐ ゼロコピー判定:バッファーが共有されているかチェック
|
||||
if (me.upstream_buffer.is_shared_with(client_data)) {
|
||||
console.log("✅ Zero-copy achieved!")
|
||||
} else {
|
||||
console.log("❌ Unnecessary copy detected")
|
||||
}
|
||||
|
||||
// 大量データ転送での最適化確認
|
||||
return me.upstream_buffer.share_reference(client_data)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 📋 **実装要件**
|
||||
- HTTPプロキシの基本機能(GET/POST転送)
|
||||
- `SocketBox`でのクライアント・サーバー接続
|
||||
- `BufferBox`での効率的なデータ転送
|
||||
- **ゼロコピー判定API**の実装・テスト
|
||||
|
||||
---
|
||||
|
||||
### 2. 🎮 **Chip-8エミュレーター** - fini伝播とweak生存チェック
|
||||
**元実装**: https://github.com/mattmikolay/chip-8 (参考)
|
||||
**サイズ**: ~1000行C、8ビットゲーム機エミュレーター
|
||||
**Nyash移植目標**: `apps/chip8_nyash/`
|
||||
|
||||
#### 🔍 **メモリ管理テストケース**
|
||||
```nyash
|
||||
// CPU・メモリ・グラフィックスの相互参照関係でのfini伝播テスト
|
||||
static box Chip8CPU {
|
||||
init { memory, graphics, sound }
|
||||
|
||||
fini() {
|
||||
// ⭐ fini伝播:依存オブジェクトの自動クリーンアップ
|
||||
console.log("🔄 CPU cleanup triggered")
|
||||
me.memory.cleanup() // メモリバンクの解放
|
||||
me.graphics.cleanup() // VRAM解放
|
||||
}
|
||||
}
|
||||
|
||||
static box Chip8Memory {
|
||||
init { ram, weak_cpu_ref } // CPUへの弱参照
|
||||
|
||||
read_byte(address) {
|
||||
// ⭐ weak生存チェック:CPUがまだ生きているか確認
|
||||
if (me.weak_cpu_ref.is_alive()) {
|
||||
return me.ram.get(address)
|
||||
} else {
|
||||
console.log("⚠️ CPU destroyed, memory access blocked")
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 📋 **実装要件**
|
||||
- Chip-8命令セット実装(35命令)
|
||||
- 64x32ピクセルグラフィックス(`WebCanvasBox`使用)
|
||||
- サウンド出力(`SoundBox`使用)
|
||||
- **fini伝播システム**と**weak参照**の実戦テスト
|
||||
|
||||
---
|
||||
|
||||
### 3. ✏️ **kilo テキストエディター** - 「うっかり全体コピー」検出
|
||||
**元実装**: https://github.com/antirez/kilo
|
||||
**サイズ**: ~1000行C、軽量ターミナルエディター
|
||||
**Nyash移植目標**: `apps/kilo_nyash/`
|
||||
|
||||
#### 🔍 **メモリ効率テストケース**
|
||||
```nyash
|
||||
// 大きなテキストファイル編集での不必要なコピー検出
|
||||
static box TextBuffer {
|
||||
init { lines, undo_stack }
|
||||
|
||||
insert_char(row, col, char) {
|
||||
local old_lines_size = me.lines.memory_footprint()
|
||||
|
||||
// 文字挿入操作
|
||||
me.lines.get(row).insert_at(col, char)
|
||||
|
||||
local new_lines_size = me.lines.memory_footprint()
|
||||
local size_diff = new_lines_size - old_lines_size
|
||||
|
||||
// ⭐ 「うっかり全体コピー」検出
|
||||
if (size_diff > 1000) { // 1文字挿入で1KB以上増加
|
||||
console.log("🚨 INEFFICIENT COPY DETECTED!")
|
||||
console.log("Expected: 1 byte, Actual: " + size_diff + " bytes")
|
||||
me.log_memory_leak_warning()
|
||||
}
|
||||
}
|
||||
|
||||
// 大規模な検索・置換での効率性チェック
|
||||
search_and_replace(pattern, replacement) {
|
||||
local initial_memory = me.lines.memory_footprint()
|
||||
|
||||
// 検索・置換実行
|
||||
me.lines.replace_all(pattern, replacement)
|
||||
|
||||
local final_memory = me.lines.memory_footprint()
|
||||
// メモリ使用量が2倍を超えた場合は問題
|
||||
if (final_memory > initial_memory * 2) {
|
||||
console.log("⚠️ Memory usage doubled during replace operation")
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 📋 **実装要件**
|
||||
- ターミナル操作(`ConsoleBox`での入出力)
|
||||
- ファイル読み書き(`FileBox`使用)
|
||||
- 基本的な編集機能(カーソル移動、挿入、削除)
|
||||
- **メモリ効率監視**と**コピー検出システム**
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ **技術的実装指針**
|
||||
|
||||
### 共通アーキテクチャ
|
||||
```nyash
|
||||
// 各アプリケーション共通の構造
|
||||
static box AppName {
|
||||
init { core_components }
|
||||
|
||||
main() {
|
||||
me.initialize_components()
|
||||
me.run_main_loop()
|
||||
me.cleanup_resources()
|
||||
}
|
||||
|
||||
// メモリ効率レポート(全アプリ共通)
|
||||
memory_report() {
|
||||
return new MapBox()
|
||||
.set("zero_copy_count", me.zero_copy_operations)
|
||||
.set("unnecessary_copies", me.detected_copies)
|
||||
.set("memory_leaks", me.fini_failures)
|
||||
.set("weak_ref_cleanups", me.weak_cleanup_count)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 新API要件
|
||||
1. **ゼロコピー判定API**
|
||||
- `BufferBox.is_shared_with(other)` → BoolBox
|
||||
- `BufferBox.share_reference(data)` → 参照共有
|
||||
|
||||
2. **fini伝播システム**
|
||||
- 自動的な依存オブジェクトクリーンアップ
|
||||
- クリーンアップチェーンの可視化
|
||||
|
||||
3. **weak参照システム**
|
||||
- `WeakBox.is_alive()` → BoolBox
|
||||
- 循環参照の自動検出・回避
|
||||
|
||||
4. **メモリ効率監視**
|
||||
- `Box.memory_footprint()` → IntegerBox
|
||||
- コピー発生の検出・警告
|
||||
|
||||
---
|
||||
|
||||
## 🎯 **期待される成果**
|
||||
|
||||
### パフォーマンス目標
|
||||
- **Tinyproxy**: HTTP転送でのゼロコピー率 90%以上
|
||||
- **Chip-8**: 60FPSエミュレーション + fini伝播の完全動作
|
||||
- **kilo**: 1MB+ファイル編集でのメモリ効率 95%以上
|
||||
|
||||
### 学習効果
|
||||
- **Copilot**: 大規模Nyashアプリケーション開発経験
|
||||
- **開発者**: 新メモリ管理機能の実用性確認
|
||||
- **コミュニティ**: Nyashでの実用アプリケーション事例
|
||||
|
||||
---
|
||||
|
||||
## 📅 **実装計画**
|
||||
|
||||
### Phase 10.1: Tinyproxy実装 (1週間)
|
||||
- HTTPプロキシ基本機能
|
||||
- ゼロコピー判定API実装・テスト
|
||||
|
||||
### Phase 10.2: Chip-8実装 (1週間)
|
||||
- エミュレーター基本機能
|
||||
- fini伝播・weak参照の実戦テスト
|
||||
|
||||
### Phase 10.3: kilo実装 (1週間)
|
||||
- テキストエディター基本機能
|
||||
- メモリ効率監視システム
|
||||
|
||||
### Phase 10.4: 統合テスト・最適化 (1週間)
|
||||
- 3アプリケーション同時実行テスト
|
||||
- パフォーマンス分析・改善
|
||||
|
||||
---
|
||||
|
||||
## 🚀 **この移植プロジェクトの意義**
|
||||
|
||||
1. **実用性の実証**: Nyashで実際のアプリケーションが作れることを証明
|
||||
2. **新機能の検証**: ゼロコピー・fini・weakの実戦テスト
|
||||
3. **開発体験の向上**: Copilotとの協調開発での生産性検証
|
||||
4. **エコシステム拡充**: Nyashアプリケーションの具体例提供
|
||||
|
||||
**この移植が成功すれば、Nyashは「実用的なプログラミング言語」として確立されます!** 🎉
|
||||
@ -1,267 +0,0 @@
|
||||
# Phase 10: Cranelift JIT Backend(MIR→VM→Cranelift)
|
||||
|
||||
Status: Planned (Primary path for native speed)
|
||||
Last Updated: 2025-08-25
|
||||
|
||||
## 🎯 ゴール
|
||||
- 実行系の主経路を「MIR→VM」を維持しつつ、ホットパスをCraneliftでJIT化して高速化する。
|
||||
- LLVM AOTは後段(Phase 11以降)の研究対象へ繰り延べ。
|
||||
|
||||
## 🔗 位置づけ
|
||||
- これまでの案(MIR→LLVM AOT)を改め、現実的な開発速度と安定性を優先してCranelift JITを先行。
|
||||
- VMとのハイブリッド実行(OSR/ホットカウントに基づくJIT)を採用。
|
||||
|
||||
## 📐 アーキテクチャ
|
||||
```
|
||||
AST → MIR → Optimizer → VM Dispatcher
|
||||
└─(Hot)→ Cranelift JIT (fn単位)
|
||||
```
|
||||
- VMが命令カウント・プロファイルを集計し、しきい値超過関数をJITコンパイル。
|
||||
- JIT済み関数は関数テーブルから直接呼び出し、VMはフォールバック先として維持。
|
||||
|
||||
## 📋 スコープ
|
||||
1) 基盤
|
||||
- JITマネージャ(関数プロファイル・コンパイルキャッシュ)
|
||||
- Craneliftコード生成(MIR→CLIF Lower)
|
||||
- 呼出しABI(Nyash VMスタック/レジスタとのブリッジ)
|
||||
|
||||
2) 命令カバレッジ(段階導入)
|
||||
- Phase A: Const/Copy/BinOp/Compare/Jump/Branch/Return(純関数相当)
|
||||
- Phase B: Call/BoxCall/ArrayGet/ArraySet(ホットパス対応)
|
||||
- Phase C: TypeOp/Ref*/Weak*/Barrier(必要最小)
|
||||
|
||||
3) ランタイム連携
|
||||
- Boxの所有・参照モデルを維持(共有/クローンの意味論を破らない)
|
||||
- 例外・TypeErrorはVMの例外パスへエスケープ
|
||||
|
||||
## ✅ 受け入れ基準(Milestone)
|
||||
- M1: 算術/比較/分岐/returnの関数がJIT化され、VMより高速に実行
|
||||
- M2: Array/Mapの代表操作(get/set/push/size)がJITで安定動作
|
||||
- M3: BoxCallホットパス(特にArray/Map)で有意な高速化(2×目標)
|
||||
- M4: 回帰防止のベンチと`--vm-stats`連携(JITカウント/時間)
|
||||
|
||||
## 🪜 実装ステップ
|
||||
1. JITマネージャ/関数プロファイルの導入(VM統計と統合)
|
||||
2. MIR→CLIF Lower骨子(基本型/算術/比較/制御)
|
||||
3. 呼出しABIブリッジ(引数/戻り値/BoxRefの表現)
|
||||
4. JIT関数テーブル + VMディスパッチ切替
|
||||
5. Array/Map/BoxCallのホットパス最適化
|
||||
6. TypeOp/Ref/Weak/Barrierの必要最小を実装
|
||||
7. ベンチ/スナップショット整備・回帰検出
|
||||
|
||||
## ⚠️ 依存・前提
|
||||
- MIR26整合(TypeOp/WeakRef/Barrierの統合前提)
|
||||
- P2PBox再設計(Phase 9.x)を先に安定化しておく(VM/プラグインE2E維持)
|
||||
|
||||
## 📚 参考
|
||||
- Cranelift: Peepmatic/CLIF、simple_jitの最小例
|
||||
- JIT/VMハイブリッド: LuaJIT/HotSpotのOSR設計
|
||||
|
||||
---
|
||||
備考: LLVM AOTはPhase 11以降の研究路線に移行(設計ドキュメントは維持)。
|
||||
|
||||
## 🔬 Sub-Phases (10_a .. 10_h)
|
||||
|
||||
各サブフェーズは「小さく立ち上げ→検証→次へ」。既存のVM/Thunk/PICを活用し、JITは同じ経路に自然合流させる。
|
||||
|
||||
### 10_a: JITブートストラップ(基盤+プロファイラ)
|
||||
- 目的: Cranelift JITの骨組みとホット関数検出の導線を用意。
|
||||
- 具体:
|
||||
- `JitManager`(関数プロファイル、しきい値、キャッシュ)
|
||||
- CLIF環境初期化(`Module`, `Context`, `ISA`)
|
||||
- VM統合: 関数入口でホット度チェック→JITコンパイル/呼び出し
|
||||
- 診断: `NYASH_JIT_STATS=1`(JIT件数/時間/キャッシュヒット)
|
||||
- 受入: ダミー関数をJIT登録してVMから呼出可能、ログが出る
|
||||
|
||||
### 10_b: Lower(Core-1) – Const/Move/BinOp/Cmp/Branch/Ret
|
||||
- 目的: ループや条件分岐を含む純粋関数をJIT実行可能に。
|
||||
- 具体:
|
||||
- MIR値/型→CLIF型(i64/f64/i1/void)
|
||||
- Const/Copy/算術/比較/ジャンプ/分岐/return のLower
|
||||
- フレームレイアウト(VMValue最小表現)
|
||||
- 受入: 算術/比較/分岐のみの関数がJITでVMより速い(小ベンチ)
|
||||
|
||||
### 10_c: ABI/呼出し – 関数呼び出しとフォールバック
|
||||
- 目的: JIT化関数から他関数を呼ぶ/VMへ戻る道を用意。
|
||||
- 具体:
|
||||
- 同一モジュール関数呼び出し(JIT→JIT/JIT→VM)
|
||||
- 引数/戻り値の受け渡し(整数/浮動/void)
|
||||
- 例外/TypeErrorはVMへバイアウト(trap→VM)
|
||||
- 受入: 再帰/多段呼び出しが安定動作
|
||||
|
||||
### 10_d: コレクション基礎 – Array/Map ホット操作(外部呼び出し)
|
||||
- 目的: 実用的ホットパス(length/get/set/push/pop)をJIT側から呼べるように。
|
||||
- 具体:
|
||||
- ホスト関数テーブル(外部シンボル)で既存Rust実装を呼ぶ
|
||||
- 境界チェック/エラーはRust側に委譲、JITは薄い橋渡し
|
||||
- 受入: Array操作がVM経由より高速(目安1.5–2.0×)
|
||||
|
||||
Status(2025-08-27)
|
||||
- Param経路でのE2Eを実装(`NYASH_JIT_HOSTCALL=1`ゲート)
|
||||
- 実装済みシンボル(PoC, C-ABI in Rust):
|
||||
- `nyash.array.{len,push,get,set}` / `nyash.map.size`
|
||||
- 使い方(例):
|
||||
```bash
|
||||
cargo build --features cranelift-jit --release
|
||||
NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EXEC=1 \
|
||||
./target/release/nyash --backend vm examples/jit_array_param_call.hako
|
||||
NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EXEC=1 \
|
||||
./target/release/nyash --backend vm examples/jit_map_param_call.hako
|
||||
```
|
||||
Notes
|
||||
- 関数パラメータに渡した配列/MapのみHostCall経由でアクセス(thread-local引数参照)
|
||||
- ローカルnew値は10_eへ移管(ハンドル表PoC: u64→Arc<Box>)
|
||||
|
||||
### 10_e: BoxCall高速化 – Thunk/PICの直結
|
||||
- 目的: Phase 9.79bの `TypeMeta{slot->thunk}` と Poly-PIC をJITにインライン。
|
||||
- 具体:
|
||||
- `slot -> thunk -> target` 解決をJITで再現(ユニバーサル0..3含む)
|
||||
- `(type_id, version)` チェック(Poly-PIC 2–4件)→ヒット直呼び、ミスVM
|
||||
- バージョンミスマッチで安全にフォールバック
|
||||
- 受入: BoxCallホットサイトで2×以上の高速化+正しい無効化挙動
|
||||
|
||||
### 10_f: TypeOp/Ref/Weak/Barrier(最小)
|
||||
- 目的: 実アプリで必要な最小限のタイプ/参照操作を埋める。
|
||||
- 具体:
|
||||
- `as_bool()` 等の基本型変換
|
||||
- 参照/弱参照/バリアの最小パス(重い経路はVMへ)
|
||||
- 受入: 代表的コードパスでJIT有効のままE2E成功
|
||||
|
||||
### 10_g: 診断/ベンチ/回帰
|
||||
- 目的: 可視化と安定化。
|
||||
- 具体:
|
||||
- `--vm-stats` にJIT統計統合(compile/ms, sites, cache率)
|
||||
- ベンチ更新(JIT有/無比較)とスナップショット
|
||||
- 受入: CIで回帰検知可能/ドキュメント更新
|
||||
|
||||
### 10_h: 硬化・パフォーマンス調整
|
||||
- 目的: ホットスポットの最適化とノイズ除去。
|
||||
- 具体:
|
||||
- ガード配置最適化(分岐予測/ICヒット優先)
|
||||
- 不要コピー削減、ホスト呼出回数の削減
|
||||
- 受入: 代表ベンチで安定して目標達成(2×以上)
|
||||
|
||||
## 📦 成果物(各サブフェーズ)
|
||||
- 10_a: `jit/manager.rs` スケルトン、VM連携、統計ログ
|
||||
- 10_b: `jit/lower/core.rs`(Const/BinOp/Cmp/Branch/Ret)+単体テスト
|
||||
- 10_c: `jit/abi.rs`(call/ret/fallback)+再帰テスト
|
||||
- 10_d: `jit/extern/collections.rs`(Array/Mapブリッジ)+マイクロベンチ
|
||||
- 10_e: `jit/inline_cache.rs`(PIC/VT連携)+無効化テスト
|
||||
- 10_f: `jit/lower/typeop_ref.rs`(最小)
|
||||
- 10_g: ベンチ/統計/README更新
|
||||
- 10_h: 最適化コミットと測定レポート
|
||||
|
||||
## 🧩 既存資産との連携(重要)
|
||||
- Thunk: Phase 9.79b.3の `TypeMeta{thunks}` をJIT直呼びターゲットとして使用
|
||||
- Poly-PIC: VMの構造をJITに投影(同じキー `(label, version)` を使用)
|
||||
- Versioning: `cache_versions` のイベントに同期してIC無効化
|
||||
|
||||
## 🎯 マイルストーン再定義
|
||||
- M1: 10_a + 10_b 合格(Core関数のJIT実行)
|
||||
- M2: 10_c + 10_d 合格(関数呼出/Arrayホット操作)
|
||||
- M3: 10_e 合格(BoxCallホットパス2×)
|
||||
- M4: 10_g + 10_h 合格(ベンチ/統計/硬化)
|
||||
|
||||
## ⚠️ リスクと緩和
|
||||
- ABI複雑化: まず整数/浮動/voidに限定し、BoxRefはホスト関数へブリッジ
|
||||
- 最適化過剰: 常にVMフォールバックを保持、ガード失敗で安全に戻す
|
||||
- デバッグ困難: CLIFダンプ/CFG表示/`NYASH_JIT_STATS`で観測
|
||||
|
||||
## 🐛 発見した問題点(2025-08-27 ベンチマーク実行時)
|
||||
|
||||
### 1. インタープリター性能問題
|
||||
- **問題**: 10万回のループで2分以上かかりタイムアウト
|
||||
- **原因**: `unwrap_instance`のデバッグログが大量出力(毎回の演算でInstanceBoxチェック)
|
||||
- **目標**: 10万回ループを数秒で完了
|
||||
- **対策**:
|
||||
- デバッグログの条件付き出力化
|
||||
- 基本演算の高速化(IntegerBoxの直接操作最適化)
|
||||
|
||||
### 2. VMの変数管理エラー
|
||||
- **問題**: `Invalid value: Value %47 not set` - simple_add_loop内の変数zが正しく管理されていない
|
||||
- **原因**: MIR生成時の変数スコープ管理の不具合
|
||||
- **対策**: MirBuilderの変数トラッキング改善
|
||||
|
||||
### 3. Box APIの成熟度
|
||||
- **問題**: TimeBoxにelapsed()/reset()メソッドがインタープリターから呼べない
|
||||
- **原因**: Boxメソッドの登録システム未完成
|
||||
- **対策**:
|
||||
- Boxメソッドの統一的登録システム実装
|
||||
- インタープリターとVMのメソッド解決統一
|
||||
|
||||
### 4. ベンチマーク基盤
|
||||
- **問題**: Nyashスクリプトでの正確な時間計測が困難
|
||||
- **根本原因**: TimeBoxのelapsed()/reset()メソッドがインタープリターから呼べない(Box API問題と同じ)
|
||||
- **対策**: Box APIの成熟度問題(問題3)が解決すれば自動的に解決
|
||||
|
||||
### 改善優先度
|
||||
1. **高**: インタープリター性能問題(基本機能の使い物にならない)
|
||||
2. **中**: VM変数管理(JIT最適化の前提)
|
||||
3. **中**: Box APIの成熟度(ベンチマーク基盤も同時解決)
|
||||
|
||||
## 🚀 Phase 10.9: Cranelift AOT Backend(追加計画)
|
||||
|
||||
Status: Future (JIT実装の上乗せで実現可能)
|
||||
|
||||
### 概要
|
||||
JIT実装(10_a~10_h)で構築したMIR→CLIF変換基盤をそのまま活用し、事前コンパイル(AOT)によるスタンドアロン実行ファイル生成を実現する。
|
||||
|
||||
### 利点
|
||||
- **コード再利用**: JITと同じLowerCore実装を使用(追加実装最小)
|
||||
- **非同期完全サポート**: WASMの制限なし、ネイティブ非同期可能
|
||||
- **最高性能**: ネイティブコード直接実行(起動時コンパイル不要)
|
||||
- **デバッグ容易**: gdb/lldb等のネイティブデバッガ使用可能
|
||||
|
||||
### 実装ステップ案
|
||||
```
|
||||
10.9a: ObjectModule統合
|
||||
├── cranelift-objectモジュール導入
|
||||
├── CLIF→オブジェクトファイル生成
|
||||
└── 既存のLowerCore再利用
|
||||
|
||||
10.9b: ランタイムライブラリ
|
||||
├── Nyash標準Box群の静的リンク版作成
|
||||
├── プラグインの静的埋め込み対応
|
||||
└── 最小ランタイム(GC hooks等)分離
|
||||
|
||||
10.9c: リンカー統合
|
||||
├── cc/ldによる実行ファイル生成
|
||||
├── プラットフォーム別設定
|
||||
└── デバッグシンボル生成
|
||||
|
||||
10.9d: クロスコンパイル
|
||||
├── 複数ターゲット(x86_64/aarch64/wasm32)
|
||||
├── ターゲット別最適化
|
||||
└── CI/CDでのマルチプラットフォームビルド
|
||||
```
|
||||
|
||||
### 使用イメージ
|
||||
```bash
|
||||
# ネイティブ実行ファイル生成
|
||||
./target/release/nyash --compile-native program.hako -o program
|
||||
./program # スタンドアロン実行!
|
||||
|
||||
# クロスコンパイル
|
||||
./target/release/nyash --compile-native --target x86_64-pc-windows-msvc program.hako -o program.exe
|
||||
./target/release/nyash --compile-native --target aarch64-apple-darwin program.hako -o program.mac
|
||||
```
|
||||
|
||||
### 技術的詳細
|
||||
- **共通基盤**: `LowerCore`のemit処理はJIT/AOT両対応
|
||||
- **差分実装**: JITは`JITModule`、AOTは`ObjectModule`を使用
|
||||
- **リンク方式**: 静的リンク優先(配布容易性重視)
|
||||
- **サイズ最適化**: LTO/strip対応で実行ファイルサイズ削減
|
||||
|
||||
### WASM AOTとの比較
|
||||
| 特性 | Cranelift AOT | WASM AOT |
|
||||
|------|--------------|----------|
|
||||
| 非同期 | ✅ 完全対応 | ❌ 制限あり |
|
||||
| 実行速度 | 最速 | 速い |
|
||||
| ファイルサイズ | 大(MB級) | 小(KB級) |
|
||||
| ポータビリティ | プラットフォーム別 | 高い |
|
||||
| デバッグ | ネイティブツール | 限定的 |
|
||||
|
||||
### 想定スケジュール
|
||||
- Phase 10(JIT)安定化後に着手
|
||||
- 実装期間: 2-3週間(JIT基盤の再利用により短期実現可能)
|
||||
- 初期ターゲット: Linux x86_64、その後Windows/macOS対応
|
||||
@ -1,72 +0,0 @@
|
||||
# Phase 10: Function Declaration MIR サポート課題
|
||||
|
||||
作成日: 2025-08-27
|
||||
発見者: Claude & ChatGPT5 & ニャー
|
||||
|
||||
## 🚨 現在の問題
|
||||
|
||||
### 症状
|
||||
```bash
|
||||
❌ MIR compilation error: Unsupported AST node type: FunctionDeclaration
|
||||
```
|
||||
|
||||
### 影響範囲
|
||||
- 通常の`function`定義がMIRでコンパイルできない
|
||||
- JITテストで関数を使った配列操作ができない
|
||||
- Static Boxメソッドは動作するが、通常関数が使えない
|
||||
|
||||
### 具体例
|
||||
```nyash
|
||||
// ❌ 動作しない - FunctionDeclarationがMIR未対応
|
||||
function len_of(arr) {
|
||||
return arr.length()
|
||||
}
|
||||
|
||||
// ✅ 動作する - Static Boxメソッド
|
||||
static box Utils {
|
||||
len_of(arr) {
|
||||
return arr.length()
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ 動作する - 直接呼び出し
|
||||
local arr = new ArrayBox()
|
||||
local len = arr.length()
|
||||
```
|
||||
|
||||
## 🔧 解決案
|
||||
|
||||
### Option 1: MIRビルダーにFunctionDeclaration対応追加
|
||||
```rust
|
||||
// mir/builder.rs に追加
|
||||
AstNode::FunctionDeclaration { name, params, body, .. } => {
|
||||
// 関数をMirFunctionとして登録
|
||||
let mir_func = self.build_function(name, params, body)?;
|
||||
self.functions.insert(name.clone(), mir_func);
|
||||
}
|
||||
```
|
||||
|
||||
### Option 2: ASTレベルでStatic Boxに変換
|
||||
- FunctionDeclarationを内部的にStatic Boxメソッドに変換
|
||||
- 互換性を保ちつつ既存の仕組みを活用
|
||||
|
||||
### Option 3: 当面の回避策を公式化
|
||||
- ドキュメントで「VMモードではStatic Boxメソッドを推奨」と明記
|
||||
- 将来のサポートとして計画に含める
|
||||
|
||||
## 📊 優先度評価
|
||||
|
||||
- **重要度**: 中(基本的な言語機能だが回避策あり)
|
||||
- **緊急度**: 低(Static Boxで代替可能)
|
||||
- **実装難度**: 中(MIRビルダーの拡張が必要)
|
||||
|
||||
## 🎯 推奨アクション
|
||||
|
||||
1. **短期**: Static Boxメソッドを使った回避策をドキュメント化
|
||||
2. **中期**: Phase 10.1でFunctionDeclaration対応を実装
|
||||
3. **長期**: 関数定義の最適化(インライン化等)も検討
|
||||
|
||||
## 📝 関連イシュー
|
||||
- JIT配列操作テスト
|
||||
- MIRビルダー拡張
|
||||
- 言語仕様の完全性
|
||||
@ -1,35 +0,0 @@
|
||||
Phase 10 — GC/Thread Roadmap Order (txt)
|
||||
|
||||
Recommended order:
|
||||
10_4a → 10_4b → 10_6a → 10_4c → 10_4d → 10_6b → 10_6c
|
||||
|
||||
10_4a: GC hook scaffolding
|
||||
- Add GcHooks { safepoint(), barrier(kind) } and BarrierKind.
|
||||
- NyashRuntime holds Arc<dyn GcHooks>; builder supports with_gc_hooks.
|
||||
- VM calls hooks at MIR Safepoint/Barrier*.
|
||||
|
||||
10_4b: Roots + minimal barriers
|
||||
- ScopeTracker root API: enter_root_region/leave_root_region/pin_root.
|
||||
- Write-Barrier at RefSet/ArraySet/BoxCall(Array/Map: set/push).
|
||||
- Tracing flags: NYASH_GC_TRACE=1 for barrier/safepoint and roots.
|
||||
|
||||
10_6a: Thread-safety audit (prep)
|
||||
- Audit Builtin/User/Plugin boxes for Send/Sync policy.
|
||||
- Strategy for shared state (RwLock) and non-thread-safe wrappers.
|
||||
|
||||
10_4c: GC PoC (STW, single-thread)
|
||||
- Implement simple collector behind GcHooks (e.g., mark-sweep or RC hybrid).
|
||||
- Manage roots via ScopeTracker; traverse VMValue graph/object_fields.
|
||||
|
||||
10_4d: Barrier hardening + regression
|
||||
- Ensure coverage for all mutating write sites (Array/Map/Ref/Plugin paths).
|
||||
- Strict checks flag for development; add stress/regression tests.
|
||||
|
||||
10_6b: Thread runtime scaffolding
|
||||
- Scheduler abstraction (cooperative preemption), Future/Channel compliance.
|
||||
- Confirm GcHooks is Send+Sync and shareable.
|
||||
|
||||
10_6c: Parallel GC design notes
|
||||
- Per-thread root regions, card marking/write barriers, safepoint coordination.
|
||||
- Document design and API diffs for later implementation.
|
||||
|
||||
@ -1,200 +0,0 @@
|
||||
# Phase 11.5a: Write Barrier除去によるGC最適化
|
||||
|
||||
## 🎯 目標
|
||||
JITコンパイル時にescape analysisを行い、不要なwrite barrierを除去してGC性能を大幅に向上させる。
|
||||
|
||||
## 📊 現状の問題
|
||||
|
||||
### 現在のVM実装
|
||||
```rust
|
||||
// すべてのrefset操作でbarrierが呼ばれる
|
||||
pub fn execute_ref_set(&mut self, reference: ValueId, field: &str, value: ValueId)
|
||||
-> Result<ControlFlow, VMError> {
|
||||
// ... 値の設定 ...
|
||||
|
||||
// 常にwrite barrierが実行される
|
||||
gc_write_barrier_site(&self.runtime, "RefSet");
|
||||
Ok(ControlFlow::Continue)
|
||||
}
|
||||
```
|
||||
|
||||
### オーバーヘッド
|
||||
- 単純な代入でも毎回barrier呼び出し
|
||||
- Stack上のローカル変数でも不要にbarrier
|
||||
- ループ内での大量のbarrier呼び出し
|
||||
|
||||
## 🚀 実装計画
|
||||
|
||||
### Step 1: Escape Analysis基盤
|
||||
```rust
|
||||
// mir/escape_analysis.rs
|
||||
pub struct EscapeAnalysis {
|
||||
// allocation site追跡
|
||||
allocations: HashMap<ValueId, AllocInfo>,
|
||||
// escape状態
|
||||
escapes: HashSet<ValueId>,
|
||||
// 解析結果キャッシュ
|
||||
cache: HashMap<FunctionId, EscapeInfo>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AllocInfo {
|
||||
location: BasicBlockId,
|
||||
kind: AllocKind,
|
||||
size: Option<usize>,
|
||||
}
|
||||
|
||||
enum AllocKind {
|
||||
NewBox, // new StringBox()
|
||||
ArrayNew, // []
|
||||
RefNew, // ユーザー定義Box
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: MIR解析
|
||||
```rust
|
||||
impl EscapeAnalysis {
|
||||
/// 関数内でのescape解析
|
||||
pub fn analyze_function(&mut self, func: &MirFunction) -> EscapeInfo {
|
||||
// 1. allocation site収集
|
||||
for (bb_id, bb) in &func.basic_blocks {
|
||||
for inst in &bb.instructions {
|
||||
match inst {
|
||||
MirInstruction::NewBox { dst, .. } |
|
||||
MirInstruction::ArrayNew { dst, .. } |
|
||||
MirInstruction::RefNew { dst, .. } => {
|
||||
self.allocations.insert(*dst, AllocInfo {
|
||||
location: bb_id,
|
||||
kind: self.classify_alloc(inst),
|
||||
size: self.estimate_size(inst),
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. escape point検出
|
||||
self.find_escape_points(func);
|
||||
|
||||
// 3. 結果集計
|
||||
EscapeInfo {
|
||||
non_escaping: self.collect_non_escaping(),
|
||||
barrier_sites: self.collect_barrier_sites(),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_escape_points(&mut self, func: &MirFunction) {
|
||||
// return文でのescape
|
||||
// 関数引数としてのescape
|
||||
// グローバル変数へのescape
|
||||
// プラグイン呼び出しでのescape
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: JIT統合
|
||||
```rust
|
||||
// jit/lower/builder.rs
|
||||
impl<'a> LoweringBuilder<'a> {
|
||||
fn emit_ref_set(&mut self, reference: Value, field: &str, value: Value) {
|
||||
// escape解析結果を確認
|
||||
let needs_barrier = self.escape_info
|
||||
.map(|info| info.needs_barrier(reference))
|
||||
.unwrap_or(true); // 解析なしなら保守的にbarrier
|
||||
|
||||
if needs_barrier {
|
||||
// barrierあり
|
||||
self.emit_gc_barrier(BarrierKind::Write);
|
||||
} else {
|
||||
// barrier除去!
|
||||
if self.config.trace_opt {
|
||||
eprintln!("[JIT] barrier removed at {:?}", self.current_location());
|
||||
}
|
||||
}
|
||||
|
||||
// 実際のstore操作
|
||||
self.emit_store(reference, field, value);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: 最適化レベル設定
|
||||
```rust
|
||||
// 環境変数で制御
|
||||
NYASH_JIT_ESCAPE_ANALYSIS=1 # escape analysis有効化
|
||||
NYASH_JIT_BARRIER_OPT=1 # barrier最適化有効化
|
||||
NYASH_JIT_BARRIER_STATS=1 # 統計出力
|
||||
```
|
||||
|
||||
## 📈 期待される効果
|
||||
|
||||
### ベンチマーク例
|
||||
```nyash
|
||||
// 大量のローカル変数操作
|
||||
function processData(n) {
|
||||
local sum = 0
|
||||
local temp = new MapBox()
|
||||
|
||||
loop(i < n) {
|
||||
temp.set(i, i * 2) // escape analysisでbarrier除去
|
||||
sum = sum + temp.get(i)
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
return sum
|
||||
}
|
||||
```
|
||||
|
||||
### 性能改善予測
|
||||
- ローカル変数操作: 90%以上のbarrier除去
|
||||
- ループ内操作: 80%以上の高速化
|
||||
- 全体的なGCオーバーヘッド: 50%削減
|
||||
|
||||
## 🔍 検証方法
|
||||
|
||||
### 1. Barrier統計
|
||||
```json
|
||||
{
|
||||
"total_barriers": 10000,
|
||||
"removed_barriers": 8500,
|
||||
"removal_rate": 0.85,
|
||||
"sites": {
|
||||
"RefSet": { "total": 5000, "removed": 4800 },
|
||||
"ArraySet": { "total": 3000, "removed": 2500 },
|
||||
"MapSet": { "total": 2000, "removed": 1200 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 性能測定
|
||||
```bash
|
||||
# barrier最適化なし
|
||||
NYASH_JIT_ESCAPE_ANALYSIS=0 ./target/release/nyash --benchmark
|
||||
|
||||
# barrier最適化あり
|
||||
NYASH_JIT_ESCAPE_ANALYSIS=1 ./target/release/nyash --benchmark
|
||||
```
|
||||
|
||||
## 🚧 実装上の注意点
|
||||
|
||||
1. **保守的な解析**
|
||||
- 不明な場合は必ずbarrierを残す
|
||||
- プラグイン境界では常にbarrier
|
||||
|
||||
2. **デバッグ性**
|
||||
- 除去したbarrierサイトを記録
|
||||
- GCエラー時の診断情報
|
||||
|
||||
3. **段階的実装**
|
||||
- まずローカル変数のみ
|
||||
- 次にループ不変式
|
||||
- 最後に関数間解析
|
||||
|
||||
## 🎉 完了基準
|
||||
|
||||
- [ ] Escape analysis基本実装
|
||||
- [ ] MIR解析パス追加
|
||||
- [ ] JIT統合
|
||||
- [ ] ベンチマーク50%改善
|
||||
- [ ] ドキュメント更新
|
||||
@ -1,240 +0,0 @@
|
||||
# Phase 11.5b: Atomic操作最適化によるsync処理高速化
|
||||
|
||||
## 🎯 目標
|
||||
Arc<Mutex>の重いロック操作を、可能な限り軽量なatomic操作に置き換えて性能を向上させる。
|
||||
|
||||
## 📊 現状の問題
|
||||
|
||||
### 現在の実装
|
||||
```rust
|
||||
// すべてのBox操作でMutexロック
|
||||
pub fn get_field(&self, name: &str) -> Option<Box<dyn NyashBox>> {
|
||||
let fields = self.fields.lock().unwrap(); // 重い!
|
||||
fields.get(name).cloned()
|
||||
}
|
||||
|
||||
// Read-onlyでも同じコスト
|
||||
pub fn to_string(&self) -> String {
|
||||
let value = self.value.lock().unwrap(); // 不要なロック!
|
||||
value.clone()
|
||||
}
|
||||
```
|
||||
|
||||
### パフォーマンス問題
|
||||
- Read操作でも排他ロックのオーバーヘッド
|
||||
- 複数スレッドでのcontention
|
||||
- Cache line bouncing
|
||||
|
||||
## 🚀 実装計画
|
||||
|
||||
### Step 1: Read-only path分析
|
||||
```rust
|
||||
// mir/readonly_analysis.rs
|
||||
pub struct ReadOnlyAnalysis {
|
||||
// メソッドのread-only性
|
||||
readonly_methods: HashMap<(TypeId, String), bool>,
|
||||
// フィールドのimmutability
|
||||
immutable_fields: HashMap<(TypeId, String), bool>,
|
||||
}
|
||||
|
||||
impl ReadOnlyAnalysis {
|
||||
pub fn analyze_box_types(&mut self, registry: &BoxRegistry) {
|
||||
// StringBox.length() -> read-only
|
||||
self.mark_readonly("StringBox", "length");
|
||||
self.mark_readonly("StringBox", "isEmpty");
|
||||
|
||||
// IntegerBox.value() -> read-only
|
||||
self.mark_readonly("IntegerBox", "value");
|
||||
|
||||
// プラグインメソッドも解析
|
||||
self.analyze_plugin_methods();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Atomic wrapper実装
|
||||
```rust
|
||||
// runtime/atomic_box.rs
|
||||
pub struct AtomicBox<T: NyashBox> {
|
||||
// Read-optimized RwLock
|
||||
inner: Arc<RwLock<T>>,
|
||||
// Atomic cache for immutable data
|
||||
cached_string: AtomicPtr<String>,
|
||||
cached_int: AtomicI64,
|
||||
}
|
||||
|
||||
impl<T: NyashBox> AtomicBox<T> {
|
||||
/// Lock-free read for cached values
|
||||
pub fn read_cached(&self) -> Option<Box<dyn NyashBox>> {
|
||||
// Atomic loadでキャッシュチェック
|
||||
let ptr = self.cached_string.load(Ordering::Acquire);
|
||||
if !ptr.is_null() {
|
||||
unsafe {
|
||||
let s = &*ptr;
|
||||
return Some(Box::new(StringBox::new(s.clone())));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Optimized read path
|
||||
pub fn read_optimized<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&T) -> R
|
||||
{
|
||||
// Try read lock first (non-blocking)
|
||||
if let Ok(guard) = self.inner.try_read() {
|
||||
return f(&*guard);
|
||||
}
|
||||
|
||||
// Fallback to regular read
|
||||
let guard = self.inner.read().unwrap();
|
||||
f(&*guard)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: JIT最適化
|
||||
```rust
|
||||
// jit/lower/atomic_opt.rs
|
||||
impl<'a> LoweringBuilder<'a> {
|
||||
fn emit_box_method_call(&mut self,
|
||||
box_val: Value,
|
||||
method: &str,
|
||||
args: &[Value]
|
||||
) -> Value {
|
||||
// Read-only解析結果確認
|
||||
if self.readonly_info.is_readonly_method(box_val, method) {
|
||||
// Atomic fast path
|
||||
self.emit_atomic_read_path(box_val, method, args)
|
||||
} else {
|
||||
// 通常のMutexパス
|
||||
self.emit_mutex_path(box_val, method, args)
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_atomic_read_path(&mut self,
|
||||
box_val: Value,
|
||||
method: &str,
|
||||
args: &[Value]
|
||||
) -> Value {
|
||||
// 1. Atomic loadでcacheチェック
|
||||
let cache_ptr = self.emit_atomic_load(box_val, "cache");
|
||||
|
||||
// 2. Cache hit判定
|
||||
let is_valid = self.emit_null_check(cache_ptr);
|
||||
|
||||
// 3. 条件分岐
|
||||
let then_block = self.create_block();
|
||||
let else_block = self.create_block();
|
||||
self.emit_branch(is_valid, then_block, else_block);
|
||||
|
||||
// Cache hit: lock-free return
|
||||
self.switch_to_block(then_block);
|
||||
let cached = self.emit_load(cache_ptr);
|
||||
self.emit_jump(merge_block);
|
||||
|
||||
// Cache miss: RwLock読み取り
|
||||
self.switch_to_block(else_block);
|
||||
let value = self.emit_rwlock_read(box_val, method);
|
||||
self.emit_jump(merge_block);
|
||||
|
||||
// Merge
|
||||
self.switch_to_block(merge_block);
|
||||
self.emit_phi(vec![(cached, then_block), (value, else_block)])
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Memory ordering最適化
|
||||
```rust
|
||||
// プラットフォーム別最適化
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn emit_memory_fence(&mut self, ordering: Ordering) {
|
||||
match ordering {
|
||||
Ordering::Relaxed => {}, // x86は強いメモリモデル
|
||||
Ordering::Acquire => self.emit_lfence(),
|
||||
Ordering::Release => self.emit_sfence(),
|
||||
Ordering::SeqCst => self.emit_mfence(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn emit_memory_fence(&mut self, ordering: Ordering) {
|
||||
// ARMは弱いメモリモデル
|
||||
match ordering {
|
||||
Ordering::Relaxed => {},
|
||||
Ordering::Acquire => self.emit_dmb_ld(),
|
||||
Ordering::Release => self.emit_dmb_st(),
|
||||
Ordering::SeqCst => self.emit_dmb(),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📈 期待される効果
|
||||
|
||||
### ベンチマーク
|
||||
```nyash
|
||||
// Read-heavy workload
|
||||
function sumStringLengths(strings) {
|
||||
local total = 0
|
||||
loop(s in strings) {
|
||||
total = total + s.length() // Atomic最適化
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
// 性能改善
|
||||
// Before: 1000ms (Mutex contention)
|
||||
// After: 100ms (Lock-free reads)
|
||||
```
|
||||
|
||||
### 改善予測
|
||||
- Read操作: 90%高速化
|
||||
- Read/Write混在: 50%高速化
|
||||
- マルチスレッド: スケーラビリティ大幅向上
|
||||
|
||||
## 🔍 検証方法
|
||||
|
||||
### 1. Lock統計
|
||||
```json
|
||||
{
|
||||
"total_operations": 100000,
|
||||
"mutex_locks": 10000,
|
||||
"atomic_reads": 90000,
|
||||
"lock_reduction": 0.9,
|
||||
"contention_events": 50
|
||||
}
|
||||
```
|
||||
|
||||
### 2. プロファイリング
|
||||
```bash
|
||||
# Mutexプロファイル
|
||||
NYASH_PROFILE_LOCKS=1 ./target/release/nyash bench.hako
|
||||
|
||||
# Atomic最適化後
|
||||
NYASH_ATOMIC_OPT=1 ./target/release/nyash bench.hako
|
||||
```
|
||||
|
||||
## 🚧 実装上の注意点
|
||||
|
||||
1. **正確性**
|
||||
- Memory orderingの正しさ
|
||||
- ABA問題の回避
|
||||
- Weak pointer対応
|
||||
|
||||
2. **互換性**
|
||||
- 既存APIの維持
|
||||
- プラグインとの相互運用
|
||||
|
||||
3. **デバッグ性**
|
||||
- Race condition検出
|
||||
- Lock順序の追跡
|
||||
|
||||
## 🎉 完了基準
|
||||
|
||||
- [ ] Read-only分析実装
|
||||
- [ ] AtomicBox wrapper実装
|
||||
- [ ] JIT統合
|
||||
- [ ] マルチスレッドベンチマーク
|
||||
- [ ] プラットフォーム別最適化
|
||||
@ -1,295 +0,0 @@
|
||||
# Phase 11.5c: Coroutine実装による非同期処理の完成
|
||||
|
||||
## 🎯 目標
|
||||
async/await構文を追加し、JITレベルでcoroutineをstate machineに変換して高性能な非同期処理を実現する。
|
||||
|
||||
## 📊 現状と目標
|
||||
|
||||
### 現在の非同期処理
|
||||
```nyash
|
||||
// nowait文(スレッドベース)
|
||||
nowait result = heavyComputation()
|
||||
// ...
|
||||
local value = wait result // FutureBoxから取得
|
||||
```
|
||||
|
||||
### 目標の構文
|
||||
```nyash
|
||||
// async/await(coroutineベース)
|
||||
async function fetchData(url) {
|
||||
local response = await httpGet(url)
|
||||
local json = await response.json()
|
||||
return json.data
|
||||
}
|
||||
|
||||
// 複数の非同期処理
|
||||
async function fetchAll(urls) {
|
||||
local promises = []
|
||||
loop(url in urls) {
|
||||
promises.push(fetchData(url))
|
||||
}
|
||||
return await Promise.all(promises)
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 実装計画
|
||||
|
||||
### Step 1: AST拡張
|
||||
```rust
|
||||
// ast.rs
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ASTNode {
|
||||
// 既存
|
||||
Function { name: String, params: Vec<String>, body: Box<ASTNode> },
|
||||
|
||||
// 新規追加
|
||||
AsyncFunction {
|
||||
name: String,
|
||||
params: Vec<String>,
|
||||
body: Box<ASTNode>
|
||||
},
|
||||
AwaitExpression {
|
||||
expression: Box<ASTNode>
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: MIR Coroutine命令
|
||||
```rust
|
||||
// mir/instruction.rs
|
||||
pub enum MirInstruction {
|
||||
// 既存命令...
|
||||
|
||||
// Coroutine関連
|
||||
/// Coroutine生成
|
||||
CoroutineCreate {
|
||||
dst: ValueId,
|
||||
func: FunctionId,
|
||||
captures: Vec<ValueId>,
|
||||
},
|
||||
|
||||
/// Yield point(await)
|
||||
CoroutineYield {
|
||||
value: ValueId,
|
||||
resume_label: BasicBlockId,
|
||||
},
|
||||
|
||||
/// Coroutine再開
|
||||
CoroutineResume {
|
||||
dst: Option<ValueId>,
|
||||
coroutine: ValueId,
|
||||
value: Option<ValueId>,
|
||||
},
|
||||
|
||||
/// Promise結合
|
||||
PromiseAll {
|
||||
dst: ValueId,
|
||||
promises: Vec<ValueId>,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: State Machine変換
|
||||
```rust
|
||||
// mir/coroutine_transform.rs
|
||||
pub struct CoroutineTransform {
|
||||
state_enum: HashMap<FunctionId, StateEnum>,
|
||||
}
|
||||
|
||||
/// async関数をstate machineに変換
|
||||
impl CoroutineTransform {
|
||||
pub fn transform_async_function(&mut self,
|
||||
func: &MirFunction
|
||||
) -> MirFunction {
|
||||
// 1. await pointsを収集
|
||||
let await_points = self.collect_await_points(func);
|
||||
|
||||
// 2. State enum生成
|
||||
let states = self.generate_states(await_points);
|
||||
|
||||
// 3. State machine関数生成
|
||||
let state_machine = self.build_state_machine(func, states);
|
||||
|
||||
// 4. Coroutine wrapper生成
|
||||
self.wrap_as_coroutine(state_machine)
|
||||
}
|
||||
|
||||
fn build_state_machine(&self,
|
||||
func: &MirFunction,
|
||||
states: Vec<State>
|
||||
) -> MirFunction {
|
||||
// switch(state) {
|
||||
// case State0: ... goto await1 or return
|
||||
// case State1: ... goto await2 or return
|
||||
// ...
|
||||
// }
|
||||
|
||||
let mut builder = MirBuilder::new();
|
||||
|
||||
// Coroutine state
|
||||
let state_var = builder.emit_local("state");
|
||||
let locals = builder.emit_local("locals");
|
||||
|
||||
// Main dispatch loop
|
||||
let loop_bb = builder.create_block();
|
||||
builder.emit_jump(loop_bb);
|
||||
|
||||
builder.switch_to_block(loop_bb);
|
||||
let state = builder.emit_load(state_var);
|
||||
|
||||
// State dispatch
|
||||
for (i, state) in states.iter().enumerate() {
|
||||
let state_bb = builder.create_block();
|
||||
builder.emit_case(state.id, state_bb);
|
||||
|
||||
builder.switch_to_block(state_bb);
|
||||
self.emit_state_code(&mut builder, state);
|
||||
}
|
||||
|
||||
builder.build()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: JIT Coroutine最適化
|
||||
```rust
|
||||
// jit/lower/coroutine.rs
|
||||
impl<'a> LoweringBuilder<'a> {
|
||||
/// Coroutineのstack switching最適化
|
||||
fn emit_coroutine_switch(&mut self,
|
||||
from: Value,
|
||||
to: Value
|
||||
) {
|
||||
if self.config.use_fast_switch {
|
||||
// レジスタのみ保存(最適化)
|
||||
self.emit_save_registers();
|
||||
self.emit_switch_stack(to);
|
||||
self.emit_restore_registers();
|
||||
} else {
|
||||
// フルコンテキスト保存
|
||||
self.emit_full_context_save(from);
|
||||
self.emit_full_context_restore(to);
|
||||
}
|
||||
}
|
||||
|
||||
/// Inline可能なawaitの検出
|
||||
fn try_inline_await(&mut self,
|
||||
await_expr: &MirInstruction
|
||||
) -> Option<Value> {
|
||||
// Promise.resolvedなら即値返却
|
||||
if self.is_resolved_promise(await_expr) {
|
||||
return Some(self.emit_immediate_value());
|
||||
}
|
||||
|
||||
// 小さなasync関数ならインライン化
|
||||
if self.is_small_async(await_expr) {
|
||||
return Some(self.inline_async_call(await_expr));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: ランタイムサポート
|
||||
```rust
|
||||
// boxes/promise_box.rs
|
||||
pub struct PromiseBox {
|
||||
state: Arc<Mutex<PromiseState>>,
|
||||
base: BoxBase,
|
||||
}
|
||||
|
||||
enum PromiseState {
|
||||
Pending(Vec<Box<dyn FnOnce(Box<dyn NyashBox>)>>),
|
||||
Resolved(Box<dyn NyashBox>),
|
||||
Rejected(String),
|
||||
}
|
||||
|
||||
impl PromiseBox {
|
||||
pub fn all(promises: Vec<Box<PromiseBox>>) -> Box<PromiseBox> {
|
||||
// 全Promise完了待ち
|
||||
let result = PromiseBox::new();
|
||||
let remaining = Arc::new(AtomicUsize::new(promises.len()));
|
||||
|
||||
for (i, promise) in promises.iter().enumerate() {
|
||||
promise.then(move |value| {
|
||||
// 結果収集
|
||||
if remaining.fetch_sub(1, Ordering::SeqCst) == 1 {
|
||||
result.resolve(collected_values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Box::new(result)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📈 期待される効果
|
||||
|
||||
### パフォーマンス比較
|
||||
```nyash
|
||||
// Before: Thread-based
|
||||
nowait results = []
|
||||
loop(url in urls) {
|
||||
nowait r = httpGet(url) // 新スレッド生成
|
||||
results.push(r)
|
||||
}
|
||||
|
||||
// After: Coroutine-based
|
||||
async function fetchAll(urls) {
|
||||
return await Promise.all(
|
||||
urls.map(url => httpGet(url)) // Stack switching only
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 改善予測
|
||||
- メモリ使用量: 1/100(スレッドstack vs coroutine state)
|
||||
- コンテキストスイッチ: 1000倍高速
|
||||
- 同時接続数: 10,000+対応可能
|
||||
|
||||
## 🔍 検証方法
|
||||
|
||||
### 1. Coroutine統計
|
||||
```json
|
||||
{
|
||||
"total_coroutines": 10000,
|
||||
"active_coroutines": 500,
|
||||
"yield_count": 50000,
|
||||
"average_yield_ns": 100,
|
||||
"stack_memory_mb": 10
|
||||
}
|
||||
```
|
||||
|
||||
### 2. ベンチマーク
|
||||
```bash
|
||||
# 10000並行リクエスト
|
||||
./target/release/nyash bench/async_stress.hako
|
||||
|
||||
# メモリプロファイル
|
||||
NYASH_COROUTINE_STATS=1 ./target/release/nyash bench/async_memory.hako
|
||||
```
|
||||
|
||||
## 🚧 実装上の注意点
|
||||
|
||||
1. **Stack管理**
|
||||
- Segmented stack対応
|
||||
- Stack overflow検出
|
||||
- GC root scanning
|
||||
|
||||
2. **エラー伝播**
|
||||
- async境界でのエラー
|
||||
- Promise rejection chain
|
||||
|
||||
3. **デバッグ対応**
|
||||
- async stack trace
|
||||
- Coroutine状態可視化
|
||||
|
||||
## 🎉 完了基準
|
||||
|
||||
- [ ] async/await構文実装
|
||||
- [ ] MIR coroutine変換
|
||||
- [ ] JIT最適化
|
||||
- [ ] Promise/PromiseBox実装
|
||||
- [ ] 10000並行処理ベンチマーク達成
|
||||
@ -1,80 +0,0 @@
|
||||
# Box-SSA Core-15 最終決定
|
||||
|
||||
Date: 2025-08-31
|
||||
Status: **固定仕様** (Frozen Specification)
|
||||
Summary: MIR命令セットを真の15個に統一
|
||||
|
||||
## 📊 問題と解決
|
||||
|
||||
### 混乱していた2案
|
||||
1. **Gemini版15**: RefNew/RefGet/RefSet含む(15個だがBox哲学に反する)
|
||||
2. **文書版Core-15**: 実は17個(Box哲学に近いが数が合わない)
|
||||
|
||||
### ChatGPT5の第三案で決着
|
||||
```
|
||||
{ Const, UnaryOp, BinOp, Compare, TypeOp,
|
||||
Load, Store,
|
||||
Jump, Branch, Return, Phi,
|
||||
Call, NewBox, BoxCall, ExternCall }
|
||||
```
|
||||
|
||||
## 🌟 革命的統一:BoxCall
|
||||
|
||||
すべてのBox操作を**BoxCall**一本に統一:
|
||||
|
||||
| 旧命令 | 新BoxCall表現 |
|
||||
|--------|---------------|
|
||||
| RefGet(obj, field) | BoxCall(obj, "getField", field) |
|
||||
| RefSet(obj, field, val) | BoxCall(obj, "setField", field, val) |
|
||||
| ArrayGet(arr, idx) | BoxCall(arr, "get", idx) |
|
||||
| ArraySet(arr, idx, val) | BoxCall(arr, "set", idx, val) |
|
||||
| PluginInvoke(p, m, args) | BoxCall(p, m, args) |
|
||||
|
||||
## 💡 技術的インパクト
|
||||
|
||||
### 実装の簡素化
|
||||
- **Verifier**: BoxCallのチェックのみ
|
||||
- **最適化**: PIC/インライン化がBoxCallに集中
|
||||
- **GCバリア**: BoxCallのLoweringで統一処理
|
||||
- **削減効果**: 26→15命令(42%削減)
|
||||
|
||||
### LLVM変換戦略(AI会議の合意)
|
||||
1. **BoxCall最適化**: メソッドID + PIC(Polymorphic Inline Cache)
|
||||
2. **脱箱化**: 2表現SSA(プリミティブ計算→必要時のみBox化)
|
||||
3. **GCバリア**: 世代別GCで若→若は省略
|
||||
4. **注釈→属性**: 保守的マッピング(安全性優先)
|
||||
|
||||
## 🚀 実装への影響
|
||||
|
||||
### JIT→LLVM直行の決断
|
||||
- Cranelift = 実はAOTだった(JIT幻想)
|
||||
- 15命令なら機械的変換で十分
|
||||
- Phase 9-10スキップ → Phase 11(LLVM)直行
|
||||
|
||||
### ChatGPT5の反応
|
||||
```
|
||||
Box-SSA Core-15を聞く
|
||||
↓
|
||||
完璧と判断
|
||||
↓
|
||||
無言でコーディング開始(議論の余地なし)
|
||||
```
|
||||
|
||||
## 📝 今後の課題
|
||||
|
||||
1. **MIR注釈システム**: 命令数を増やさずに最適化ヒント付与(設計案のみ)
|
||||
2. **LLVM実装**: inkwellセットアップから開始
|
||||
3. **既存コード移行**: 26→15命令への段階的移行
|
||||
|
||||
## 🎉 結論
|
||||
|
||||
**Box-SSA Core-15**により「Everything is Box」哲学が完全開花:
|
||||
- 真の15命令達成
|
||||
- 実装の劇的簡素化
|
||||
- 最適化の統一的適用
|
||||
|
||||
これが「あほみたいに簡単」で「恐ろしく速い」Nyashの最終形態!
|
||||
|
||||
---
|
||||
|
||||
詳細なAI会議記録は [archives/](archives/) フォルダに保存
|
||||
@ -1,60 +0,0 @@
|
||||
# Phase 11.5 Current Status
|
||||
|
||||
Date: 2025-08-31
|
||||
Status: Active Development → LLVM Implementation
|
||||
|
||||
## 🎯 本日の大革命:Box-SSA Core-15
|
||||
|
||||
### MIR命令セットの固定
|
||||
- 26命令 → **真の15命令**に統一
|
||||
- すべてのBox操作を**BoxCall**に集約
|
||||
- Everything is Box哲学の完全実現
|
||||
|
||||
詳細: [BOX_SSA_CORE_15_FINAL_DECISION.md](BOX_SSA_CORE_15_FINAL_DECISION.md)
|
||||
|
||||
## 📊 Phase 11.5 タスク状況
|
||||
|
||||
### ✅ 完了
|
||||
1. **Write Barrier Removal** (11.5a)
|
||||
- Escape Analysis基礎実装
|
||||
- RefSet最適化
|
||||
|
||||
2. **Atomic Operations** (11.5b)
|
||||
- 同期プリミティブ実装
|
||||
- Memory ordering保証
|
||||
|
||||
3. **Coroutine/Async** (11.5c)
|
||||
- Future/Await基本実装
|
||||
- 非同期ランタイム統合
|
||||
|
||||
4. **Box-SSA Core-15仕様固定** (NEW!)
|
||||
- MIR 15命令に統一
|
||||
- BoxCall万能化
|
||||
|
||||
### 🚀 次のステップ
|
||||
|
||||
**Phase 11(LLVM)直行決定**:
|
||||
- Phase 9-10(JIT)スキップ
|
||||
- Cranelift削除 → inkwell導入
|
||||
- 15命令の機械的LLVM変換
|
||||
|
||||
## 📁 ドキュメント構成
|
||||
|
||||
### メインドキュメント
|
||||
- `BOX_SSA_CORE_15_FINAL_DECISION.md` - 本日の革命的決定
|
||||
- `11.5a/b/c-*.md` - 各サブフェーズの実装ガイド
|
||||
- `IMPLEMENTATION-GUIDE.md` - 全体実装指針
|
||||
- `FIRST-FIVE-APPS.md` - アプリケーション例
|
||||
|
||||
### アーカイブ
|
||||
- `archives/` - 詳細なAI会議記録
|
||||
- 個別相談記録(Gemini, Codex, ChatGPT5)
|
||||
- 詳細技術議論
|
||||
|
||||
## 🎉 成果
|
||||
|
||||
1. **MIR簡素化**: 26→15命令(42%削減)
|
||||
2. **実装統一**: BoxCallに全Box操作を集約
|
||||
3. **戦略転換**: JIT幻想から解放→LLVM直行
|
||||
|
||||
これでPhase 11.5は概念的に完了し、LLVM実装(Phase 11)へ移行準備完了!
|
||||
@ -1,307 +0,0 @@
|
||||
# 🚀 First Five Apps - Nyashの実力を証明する最初の5本
|
||||
|
||||
## 🎯 概要
|
||||
Phase 11.5完了を待たずに、**今すぐ作れる**実用アプリ5本で、Nyashの産業レベルの完成度を世に示します。
|
||||
すべて「Everything is Box/PluginInvoke」で統一実装し、VM/JIT/AOT/WASMの全バックエンドで動作確認します。
|
||||
|
||||
## 📋 アプリケーション一覧
|
||||
|
||||
### 1. ny-echo(最小CLI)- 基本I/O検証
|
||||
**目的**: I/O・StringBoxの道通し確認
|
||||
|
||||
```nyash
|
||||
// apps/ny-echo/main.hako
|
||||
static box Main {
|
||||
main(args) {
|
||||
local console = new ConsoleBox()
|
||||
local options = parseArgs(args)
|
||||
|
||||
loop(true) {
|
||||
local input = console.readLine()
|
||||
if input == null { break }
|
||||
|
||||
local output = input
|
||||
if options.get("upper") {
|
||||
output = input.toUpperCase()
|
||||
} else if options.get("lower") {
|
||||
output = input.toLowerCase()
|
||||
}
|
||||
|
||||
console.log(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**受入基準**:
|
||||
- [ ] VM/JIT/AOT/GCオン・オフすべてでtrace_hash一致
|
||||
- [ ] 100万行処理で性能劣化なし
|
||||
- [ ] メモリリークなし(GCカウンター確認)
|
||||
|
||||
### 2. ny-jsonlint(Python連携デモ)- プラグイン統合
|
||||
**目的**: PyRuntimeBox/PyObjectBox経由のPluginInvoke検証
|
||||
|
||||
```nyash
|
||||
// apps/ny-jsonlint/main.hako
|
||||
static box Main {
|
||||
init { py, console }
|
||||
|
||||
main(args) {
|
||||
me.py = new PyRuntimeBox()
|
||||
me.console = new ConsoleBox()
|
||||
|
||||
local filename = args.get(1)
|
||||
if filename == null {
|
||||
me.console.error("Usage: ny-jsonlint <file.json>")
|
||||
return 1
|
||||
}
|
||||
|
||||
local file = new FileBox()
|
||||
file.open(filename, "r")
|
||||
local content = file.read()
|
||||
file.close()
|
||||
|
||||
local result = me.py.eval("
|
||||
import json
|
||||
try:
|
||||
json.loads(content)
|
||||
'OK'
|
||||
except Exception as e:
|
||||
f'NG: {str(e)}'
|
||||
", new MapBox().set("content", content))
|
||||
|
||||
me.console.log(result)
|
||||
return result.startsWith("OK") ? 0 : 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**受入基準**:
|
||||
- [ ] OS差なく実行(Windows/Linux/macOS)
|
||||
- [ ] --sealedモードで完全再現可能
|
||||
- [ ] 大規模JSON(10MB)でも安定動作
|
||||
|
||||
### 3. ny-array-bench(性能デモ)- ベンチマーク基準
|
||||
**目的**: ArrayBox map/reduce、StatsBox導入、性能可視化
|
||||
|
||||
```nyash
|
||||
// apps/ny-array-bench/main.hako
|
||||
static box Main {
|
||||
init { stats }
|
||||
|
||||
main(args) {
|
||||
me.stats = new StatsBox()
|
||||
local sizes = [1000, 10000, 100000]
|
||||
|
||||
loop(size in sizes) {
|
||||
me.benchArrayOps(size)
|
||||
}
|
||||
|
||||
// 結果をJSON出力(CI集計用)
|
||||
local result = me.stats.toJSON()
|
||||
print(result)
|
||||
}
|
||||
|
||||
benchArrayOps(size) {
|
||||
local array = new ArrayBox()
|
||||
|
||||
// 1. 配列生成
|
||||
me.stats.startTimer("create_" + size)
|
||||
loop(i < size) {
|
||||
array.push(i)
|
||||
}
|
||||
me.stats.endTimer("create_" + size)
|
||||
|
||||
// 2. map操作
|
||||
me.stats.startTimer("map_" + size)
|
||||
local doubled = array.map(|x| x * 2)
|
||||
me.stats.endTimer("map_" + size)
|
||||
|
||||
// 3. reduce操作
|
||||
me.stats.startTimer("reduce_" + size)
|
||||
local sum = doubled.reduce(|a, b| a + b, 0)
|
||||
me.stats.endTimer("reduce_" + size)
|
||||
|
||||
// VM基準の相対性能を記録
|
||||
me.stats.recordRelative("vm", 1.0)
|
||||
if IS_JIT { me.stats.recordRelative("jit", SPEEDUP) }
|
||||
if IS_AOT { me.stats.recordRelative("aot", SPEEDUP) }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**受入基準**:
|
||||
- [ ] VM=1.0x基準でJIT/AOTの倍率表示
|
||||
- [ ] fallbacks=0(完全最適化)
|
||||
- [ ] 結果JSON自動出力(CI集計可能)
|
||||
|
||||
### 4. ny-filegrep(実用ミニ)- ファイルI/O実用例
|
||||
**目的**: BytesBox/FileBox(プラグイン)I/O、実用的なツール
|
||||
|
||||
```nyash
|
||||
// apps/ny-filegrep/main.hako
|
||||
static box Main {
|
||||
init { pattern, recursive, results }
|
||||
|
||||
main(args) {
|
||||
me.parseArgs(args)
|
||||
me.results = new ArrayBox()
|
||||
|
||||
local path = args.getLast() || "."
|
||||
me.searchPath(path)
|
||||
|
||||
// 結果表示
|
||||
loop(result in me.results) {
|
||||
print(result)
|
||||
}
|
||||
|
||||
return me.results.length() > 0 ? 0 : 1
|
||||
}
|
||||
|
||||
searchPath(path) {
|
||||
local file = new FileBox()
|
||||
|
||||
if file.isDirectory(path) {
|
||||
if me.recursive {
|
||||
local entries = file.listDir(path)
|
||||
loop(entry in entries) {
|
||||
me.searchPath(path + "/" + entry)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
me.searchFile(path)
|
||||
}
|
||||
}
|
||||
|
||||
searchFile(filepath) {
|
||||
local file = new FileBox()
|
||||
file.open(filepath, "r")
|
||||
|
||||
local lineNum = 0
|
||||
loop(true) {
|
||||
local line = file.readLine()
|
||||
if line == null { break }
|
||||
|
||||
lineNum = lineNum + 1
|
||||
if line.contains(me.pattern) {
|
||||
me.results.push(filepath + ":" + lineNum + ":" + line)
|
||||
}
|
||||
}
|
||||
|
||||
file.close()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**受入基準**:
|
||||
- [ ] Windows/Linux/macOSで同一結果
|
||||
- [ ] 大規模ディレクトリ(1万ファイル)対応
|
||||
- [ ] メモリ効率的(ストリーム処理)
|
||||
|
||||
### 5. ny-http-hello(WASM/ネイティブ両対応)- Web実用例
|
||||
**目的**: NetBox(プラグイン)とイベントループ、FutureBox活用
|
||||
|
||||
```nyash
|
||||
// apps/ny-http-hello/main.hako
|
||||
static box Main {
|
||||
init { server, running }
|
||||
|
||||
main(args) {
|
||||
local port = args.get(1) || "8080"
|
||||
me.server = new HttpServerBox()
|
||||
me.running = true
|
||||
|
||||
// シグナルハンドラー設定
|
||||
registerSignal("SIGINT", || me.stop())
|
||||
|
||||
// サーバー起動
|
||||
me.server.start(port.toInteger())
|
||||
print("Server listening on http://localhost:" + port)
|
||||
|
||||
// リクエストループ
|
||||
loop(me.running) {
|
||||
nowait request = me.server.accept()
|
||||
me.handleRequest(wait request)
|
||||
}
|
||||
|
||||
me.server.stop()
|
||||
return 0
|
||||
}
|
||||
|
||||
handleRequest(request) {
|
||||
local response = new HttpResponseBox()
|
||||
|
||||
if request.path() == "/" {
|
||||
response.setStatus(200)
|
||||
response.setHeader("Content-Type", "text/plain")
|
||||
response.write("Hello from Nyash!")
|
||||
} else {
|
||||
response.setStatus(404)
|
||||
response.write("Not Found")
|
||||
}
|
||||
|
||||
request.respond(response)
|
||||
}
|
||||
|
||||
stop() {
|
||||
print("Shutting down...")
|
||||
me.running = false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**受入基準**:
|
||||
- [ ] 100req/s程度のスモーク通過
|
||||
- [ ] 停止シグナルでクリーンfini
|
||||
- [ ] WASMビルドでも動作(制限付き)
|
||||
|
||||
## 🎯 実装優先順位
|
||||
|
||||
1. **ny-echo** - 最小実装、CI基盤確立
|
||||
2. **ny-array-bench** - 性能基準確立
|
||||
3. **ny-jsonlint** - プラグイン統合実証
|
||||
4. **ny-filegrep** - 実用性実証
|
||||
5. **ny-http-hello** - Web対応実証
|
||||
|
||||
## 📊 成功指標
|
||||
|
||||
### 全体指標
|
||||
- [ ] 5アプリすべてがVM/JIT/AOTで動作
|
||||
- [ ] CIでの自動テスト確立
|
||||
- [ ] ドキュメント・サンプル完備
|
||||
|
||||
### 性能指標
|
||||
- [ ] JIT: VMの5倍以上高速
|
||||
- [ ] AOT: VMの10倍以上高速
|
||||
- [ ] メモリ使用量: 同等機能のPython比50%以下
|
||||
|
||||
### 品質指標
|
||||
- [ ] ゼロクラッシュ(1000回実行)
|
||||
- [ ] メモリリークなし(長時間実行)
|
||||
- [ ] プラットフォーム差異なし
|
||||
|
||||
## 🚀 配布戦略
|
||||
|
||||
### リリース形式
|
||||
```
|
||||
nyash-apps-v1.0/
|
||||
├── bin/
|
||||
│ ├── ny-echo[.exe]
|
||||
│ ├── ny-jsonlint[.exe]
|
||||
│ ├── ny-array-bench[.exe]
|
||||
│ ├── ny-filegrep[.exe]
|
||||
│ └── ny-http-hello[.exe]
|
||||
├── examples/
|
||||
│ └── *.hako (ソースコード)
|
||||
├── benchmarks/
|
||||
│ └── results.json
|
||||
└── README.md
|
||||
```
|
||||
|
||||
### 展開先
|
||||
- GitHub Releases
|
||||
- Homebrew (macOS)
|
||||
- Scoop (Windows)
|
||||
- Docker Hub (コンテナ版)
|
||||
|
||||
これで「30日で作った言語」の実力を世界に示せます!🎉
|
||||
@ -1,191 +0,0 @@
|
||||
# Phase 11.5 実装ガイド - ChatGPT5向け
|
||||
|
||||
## 🎯 実装の全体像
|
||||
|
||||
Phase 11.5は、Nyashの性能を産業レベルに引き上げる最終段階です。3つの主要な最適化を行います:
|
||||
|
||||
1. **Write Barrier除去** - GCオーバーヘッドを90%削減
|
||||
2. **Atomic最適化** - sync処理を10倍高速化
|
||||
3. **Coroutine実装** - 真の非同期処理を実現
|
||||
|
||||
## 📋 実装順序と依存関係
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[11.5a: Write Barrier除去] --> D[統合テスト]
|
||||
B[11.5b: Atomic最適化] --> D
|
||||
C[11.5c: Coroutine実装] --> D
|
||||
D --> E[Phase 11.5完了]
|
||||
```
|
||||
|
||||
各タスクは独立して実装可能ですが、統合テストで相互作用を検証します。
|
||||
|
||||
## 🔧 技術的な実装詳細
|
||||
|
||||
### 1. Write Barrier除去の実装手順
|
||||
|
||||
#### Step 1: MIR拡張
|
||||
```rust
|
||||
// src/mir/escape_analysis.rs (新規作成)
|
||||
use crate::mir::{MirFunction, MirInstruction, ValueId};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub struct EscapeAnalysis {
|
||||
allocations: HashMap<ValueId, AllocSite>,
|
||||
escapes: HashSet<ValueId>,
|
||||
}
|
||||
|
||||
impl EscapeAnalysis {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
allocations: HashMap::new(),
|
||||
escapes: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn analyze(&mut self, func: &MirFunction) -> EscapeInfo {
|
||||
// 実装のポイント:
|
||||
// 1. NewBox, RefNew命令を追跡
|
||||
// 2. Return, Call命令でescape判定
|
||||
// 3. ループ不変式も考慮
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Step 2: VM統合
|
||||
```rust
|
||||
// src/backend/vm_instructions.rs の修正
|
||||
pub fn execute_ref_set(&mut self, reference: ValueId, field: &str, value: ValueId)
|
||||
-> Result<ControlFlow, VMError> {
|
||||
// 既存のコード...
|
||||
|
||||
// Escape analysisの結果を確認
|
||||
if let Some(escape_info) = &self.escape_info {
|
||||
if !escape_info.escapes(reference) {
|
||||
// Barrierスキップ!
|
||||
return Ok(ControlFlow::Continue);
|
||||
}
|
||||
}
|
||||
|
||||
// 通常のbarrier処理
|
||||
gc_write_barrier_site(&self.runtime, "RefSet");
|
||||
Ok(ControlFlow::Continue)
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Atomic最適化の実装手順
|
||||
|
||||
#### Step 1: BoxCore拡張
|
||||
```rust
|
||||
// src/box_trait.rs の修正
|
||||
pub trait BoxCore: Send + Sync {
|
||||
// 既存のメソッド...
|
||||
|
||||
/// Read-onlyメソッドかどうか
|
||||
fn is_readonly_method(&self, method: &str) -> bool {
|
||||
// デフォルトはfalse(保守的)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// 各Boxで実装
|
||||
impl BoxCore for StringBox {
|
||||
fn is_readonly_method(&self, method: &str) -> bool {
|
||||
matches!(method, "length" | "isEmpty" | "charAt")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Step 2: Atomic wrapper
|
||||
```rust
|
||||
// src/runtime/atomic_box.rs (新規作成)
|
||||
use std::sync::atomic::{AtomicPtr, Ordering};
|
||||
use std::sync::Arc;
|
||||
use parking_lot::RwLock; // より高速なRwLock
|
||||
|
||||
pub struct AtomicBox<T> {
|
||||
inner: Arc<RwLock<T>>,
|
||||
cache: AtomicPtr<CachedValue>,
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Coroutine実装の実装手順
|
||||
|
||||
#### Step 1: Parser拡張
|
||||
```rust
|
||||
// src/parser/keywords.rs の修正
|
||||
pub const RESERVED_WORDS: &[&str] = &[
|
||||
// 既存のキーワード...
|
||||
"async",
|
||||
"await",
|
||||
];
|
||||
|
||||
// src/parser/expressions.rs の修正
|
||||
fn parse_function_declaration(&mut self) -> Result<ASTNode, ParseError> {
|
||||
let is_async = self.consume_keyword("async");
|
||||
// 既存のパース処理...
|
||||
}
|
||||
```
|
||||
|
||||
#### Step 2: MIR Coroutine変換
|
||||
```rust
|
||||
// src/mir/coroutine_transform.rs (新規作成)
|
||||
pub fn transform_async_function(func: &MirFunction) -> MirFunction {
|
||||
// State machine変換のアルゴリズム:
|
||||
// 1. await箇所でstateを分割
|
||||
// 2. ローカル変数をstate構造体に移動
|
||||
// 3. switch文で状態遷移を実装
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 ChatGPT5への実装指示
|
||||
|
||||
### Phase 11.5a(最優先)
|
||||
1. `src/mir/escape_analysis.rs`を作成
|
||||
2. 基本的なallocation追跡を実装
|
||||
3. VM統合でbarrier除去をテスト
|
||||
4. ベンチマークで効果測定
|
||||
|
||||
### Phase 11.5b(次優先)
|
||||
1. `BoxCore::is_readonly_method`を追加
|
||||
2. 主要Boxで実装(StringBox, IntegerBox)
|
||||
3. RwLock移行を段階的に実施
|
||||
|
||||
### Phase 11.5c(最後)
|
||||
1. Parser拡張(async/await)
|
||||
2. 基本的なPromiseBox実装
|
||||
3. 簡単なasync関数の動作確認
|
||||
|
||||
## 📊 成功指標
|
||||
|
||||
各フェーズの完了基準:
|
||||
|
||||
### 11.5a: Write Barrier除去
|
||||
- [ ] escape_analysis.rsが動作
|
||||
- [ ] 簡単なループでbarrier除去確認
|
||||
- [ ] ベンチマークで30%以上改善
|
||||
|
||||
### 11.5b: Atomic最適化
|
||||
- [ ] Read-onlyメソッドの識別
|
||||
- [ ] RwLock使用でread性能向上
|
||||
- [ ] マルチスレッドベンチマーク改善
|
||||
|
||||
### 11.5c: Coroutine実装
|
||||
- [ ] async/awaitがパース可能
|
||||
- [ ] 簡単なasync関数が実行可能
|
||||
- [ ] Promiseチェーンが動作
|
||||
|
||||
## 🚀 実装開始コマンド
|
||||
|
||||
```bash
|
||||
# ブランチ作成
|
||||
git checkout -b phase-11.5-jit-integration
|
||||
|
||||
# テスト駆動開発
|
||||
cargo test escape_analysis
|
||||
|
||||
# ベンチマーク実行
|
||||
./target/release/nyash --benchmark --iterations 1000
|
||||
```
|
||||
|
||||
頑張ってください、ChatGPT5!これが完成すれば、Nyashは本当に世界クラスの言語になります!
|
||||
@ -1,169 +0,0 @@
|
||||
# Phase 11.5: JIT完全統合 - sync/GC/非同期の最終実装
|
||||
|
||||
## 🎯 概要
|
||||
Phase 11.5は、Nyashの全実行レイヤー(インタープリター/MIR/VM/JIT)でsync処理、GC処理、非同期処理を完全に統合する最終フェーズです。
|
||||
|
||||
## 📊 現状分析(2025-08-30)
|
||||
|
||||
### ✅ 完了済み
|
||||
1. **基本アーキテクチャ**
|
||||
- Everything is Box哲学の完全実装
|
||||
- インタープリター → MIR → VM → JIT パイプライン
|
||||
- プラグインシステム(C ABI/TLVハンドル)
|
||||
|
||||
2. **sync処理**
|
||||
- Arc<Mutex>/Arc<RwLock>による完全スレッドセーフ設計
|
||||
- 全レイヤーでの一貫した同期化
|
||||
|
||||
3. **GC基礎**
|
||||
- カウンティングGC実装(NYASH_GC_COUNTING=1)
|
||||
- Read/Writeバリア実装
|
||||
- VMセーフポイント
|
||||
|
||||
4. **非同期基礎**
|
||||
- FutureBox/TimerBox実装
|
||||
- SingleThreadScheduler
|
||||
- nowait/wait文
|
||||
|
||||
## 🚀 Phase 11.5 タスク一覧
|
||||
|
||||
### 1. JIT sync処理統合
|
||||
- [ ] **1.1 Atomic操作の最適化**
|
||||
- Arc<Mutex>アクセスのJIT最適化
|
||||
- Lock elision(不要なロック除去)
|
||||
- Read-only pathでのロック回避
|
||||
|
||||
- [ ] **1.2 Memory ordering最適化**
|
||||
- Relaxed/Acquire/Release semanticsの活用
|
||||
- プラットフォーム別最適化(x86/ARM)
|
||||
|
||||
### 2. JIT GC統合
|
||||
- [ ] **2.1 Write barrier除去**
|
||||
- Escape analysisによる不要バリア検出
|
||||
- Stack allocation最適化
|
||||
- Generational hypothesis活用
|
||||
|
||||
- [ ] **2.2 Safepoint最適化**
|
||||
- Loop safepoint挿入
|
||||
- Call site safepoint
|
||||
- Polling overhead削減
|
||||
|
||||
- [ ] **2.3 GC情報の伝播**
|
||||
- Stack map生成
|
||||
- Root set tracking
|
||||
- Precise GC対応
|
||||
|
||||
### 3. JIT 非同期処理統合
|
||||
- [ ] **3.1 Coroutine変換**
|
||||
- async/await → state machine変換
|
||||
- Stack switching最適化
|
||||
- Continuation passing
|
||||
|
||||
- [ ] **3.2 スケジューラー統合**
|
||||
- Work stealing queue
|
||||
- CPU affinity最適化
|
||||
- Yield point最適化
|
||||
|
||||
### 4. 統合テスト・ベンチマーク
|
||||
- [ ] **4.1 性能測定**
|
||||
- sync処理のオーバーヘッド測定
|
||||
- GC pause time測定
|
||||
- 非同期処理のレイテンシ測定
|
||||
|
||||
- [ ] **4.2 正確性検証**
|
||||
- Race condition検出
|
||||
- Memory leak検出
|
||||
- Deadlock検出
|
||||
|
||||
## 📋 実装優先順位
|
||||
|
||||
### Phase 11.5a: Write barrier除去(最重要)
|
||||
```rust
|
||||
// 現在: すべてのBox操作でbarrier
|
||||
vm.execute_ref_set() -> gc.barrier(Write)
|
||||
|
||||
// 目標: JITでescape analysisして除去
|
||||
if !escapes_to_heap(value) {
|
||||
// barrierスキップ
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 11.5b: Atomic最適化
|
||||
```rust
|
||||
// 現在: Arc<Mutex>の重いロック
|
||||
let value = box.lock().unwrap().clone();
|
||||
|
||||
// 目標: Read-onlyならatomic load
|
||||
if is_read_only(box) {
|
||||
atomic_load_relaxed(box)
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 11.5c: Coroutine実装
|
||||
```nyash
|
||||
// 将来構文
|
||||
async function fetchData() {
|
||||
local result = await httpGet("...")
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 成功基準
|
||||
|
||||
1. **性能向上**
|
||||
- sync処理: 50%以上のロックオーバーヘッド削減
|
||||
- GC: 90%以上のwrite barrier除去
|
||||
- 非同期: ネイティブthread並みの性能
|
||||
|
||||
2. **互換性維持**
|
||||
- 既存のNyashコードがそのまま動作
|
||||
- プラグインシステムとの完全互換
|
||||
|
||||
3. **デバッグ性**
|
||||
- JIT最適化の可視化(NYASH_JIT_OPT_TRACE)
|
||||
- GC統計の詳細化
|
||||
- 非同期処理のトレース
|
||||
|
||||
## 📅 実装スケジュール(推定)
|
||||
|
||||
- **Week 1-2**: Write barrier除去とescape analysis
|
||||
- **Week 3**: Atomic操作最適化
|
||||
- **Week 4**: Coroutine基礎実装
|
||||
- **Week 5**: 統合テストとベンチマーク
|
||||
- **Week 6**: ドキュメント化と最適化
|
||||
|
||||
## 🔧 技術的詳細
|
||||
|
||||
### Escape Analysis実装案
|
||||
```rust
|
||||
// MIR解析でallocサイトを特定
|
||||
struct EscapeAnalysis {
|
||||
allocations: HashMap<ValueId, AllocSite>,
|
||||
escapes: HashSet<ValueId>,
|
||||
}
|
||||
|
||||
impl EscapeAnalysis {
|
||||
fn analyze(&mut self, func: &MirFunction) {
|
||||
// 1. allocation site収集
|
||||
// 2. data flow解析
|
||||
// 3. escape判定
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### JIT統合ポイント
|
||||
```rust
|
||||
// cranelift-jitでのbarrier除去
|
||||
if !self.escape_info.escapes(value) {
|
||||
// emit_call(gc_write_barrier) をスキップ
|
||||
}
|
||||
```
|
||||
|
||||
## 🎉 期待される成果
|
||||
|
||||
Phase 11.5完了により、Nyashは:
|
||||
- **産業レベルの性能**: GC pauseがマイクロ秒単位
|
||||
- **真の並行性**: lock-free data structures対応
|
||||
- **モダンな非同期**: async/await完全サポート
|
||||
|
||||
これにより、**30日で作られたとは思えない**世界クラスの言語が完成します!
|
||||
@ -1,162 +0,0 @@
|
||||
# WASM実装の問題と改善計画
|
||||
|
||||
## 🚨 現状の問題
|
||||
|
||||
### 1. **2つのWASM実装が存在**
|
||||
- **Rust→WASM**: `wasm-pack build`でNyashインタープリター全体をWASMに(動作する)
|
||||
- **MIR→WASM**: `--compile-wasm`でNyashコードをWASMに変換(ほぼ動かない)
|
||||
|
||||
### 2. **MIR→WASM実装の問題点**
|
||||
```rust
|
||||
// src/backend/wasm/codegen.rs より
|
||||
pub fn generate_module(...) -> Result<WasmModule, WasmError> {
|
||||
// 基本的な命令しか実装されていない
|
||||
// - 算術演算
|
||||
// - 制御フロー
|
||||
// - print文(ホスト関数呼び出し)
|
||||
|
||||
// 未実装:
|
||||
// - Box操作(NewBox, BoxCall, PluginInvoke)
|
||||
// - 配列操作
|
||||
// - プラグインシステム
|
||||
// - GC/メモリ管理
|
||||
}
|
||||
```
|
||||
|
||||
### 3. **根本的な設計問題**
|
||||
- **Box抽象の表現困難**: Everything is BoxをWASMの型システムで表現できない
|
||||
- **動的ディスパッチ**: BoxCallやPluginInvokeの実装が困難
|
||||
- **GCの不在**: WASMにはGCがない(WasmGC提案はまだ実験的)
|
||||
- **プラグインFFI**: C ABIをWASM環境で実現できない
|
||||
|
||||
## 📊 現状の実装状況
|
||||
|
||||
### 実装済み(動作するもの)
|
||||
```nyash
|
||||
// 基本的な算術
|
||||
function add(a, b) {
|
||||
return a + b
|
||||
}
|
||||
|
||||
// 単純な制御フロー
|
||||
function factorial(n) {
|
||||
if n <= 1 { return 1 }
|
||||
return n * factorial(n - 1)
|
||||
}
|
||||
|
||||
// print文(ホスト関数経由)
|
||||
print("Hello WASM")
|
||||
```
|
||||
|
||||
### 未実装(動作しないもの)
|
||||
```nyash
|
||||
// Box操作
|
||||
local str = new StringBox("hello") // ❌ NewBox未実装
|
||||
str.toUpperCase() // ❌ BoxCall未実装
|
||||
|
||||
// 配列
|
||||
local arr = [1, 2, 3] // ❌ 配列リテラル未実装
|
||||
arr.push(4) // ❌ ArrayBox未実装
|
||||
|
||||
// プラグイン
|
||||
local file = new FileBox() // ❌ PluginInvoke未実装
|
||||
```
|
||||
|
||||
## 🤔 なぜRust→WASMは動くのか
|
||||
|
||||
```toml
|
||||
# Cargo.toml
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
```
|
||||
|
||||
- **すべてのBox実装がそのままWASMに**: Arc<Mutex>も含めて
|
||||
- **wasm-bindgenの魔法**: JavaScript↔Rust境界を自動生成
|
||||
- **制限事項**: 一部のBox(TimerBox、FileBox等)は除外
|
||||
|
||||
## 🚀 改善案
|
||||
|
||||
### Option 1: MIR→WASM実装の完成(困難)
|
||||
```wat
|
||||
;; BoxをWASMテーブルで管理
|
||||
(table $boxes 1000 externref)
|
||||
(global $next_box_id (mut i32) (i32.const 0))
|
||||
|
||||
;; NewBox実装
|
||||
(func $new_string_box (param $str i32) (result i32)
|
||||
;; 新しいBox IDを割り当て
|
||||
(local $box_id i32)
|
||||
(local.set $box_id (global.get $next_box_id))
|
||||
|
||||
;; JavaScriptでStringBoxを作成
|
||||
(table.set $boxes
|
||||
(local.get $box_id)
|
||||
(call $js_create_string_box (local.get $str)))
|
||||
|
||||
;; IDを返す
|
||||
(local.get $box_id)
|
||||
)
|
||||
```
|
||||
|
||||
**問題点**:
|
||||
- JavaScript側にBox実装が必要
|
||||
- 性能オーバーヘッドが大きい
|
||||
- プラグインシステムとの統合困難
|
||||
|
||||
### Option 2: Rust→WASMの活用(現実的)
|
||||
```rust
|
||||
// NyashコードをRustに変換してからWASMに
|
||||
nyash_code → rust_code → wasm
|
||||
|
||||
// 例:
|
||||
// Nyash: local s = new StringBox("hello")
|
||||
// Rust: let s = Box::new(StringBox::new("hello".to_string()));
|
||||
// WASM: (自動生成)
|
||||
```
|
||||
|
||||
### Option 3: WASMランタイムの埋め込み(革新的)
|
||||
```wat
|
||||
;; 最小VMをWASMに埋め込む
|
||||
(module
|
||||
;; MIRバイトコードを格納
|
||||
(data (i32.const 0) "\01\02\03...")
|
||||
|
||||
;; VMインタープリター
|
||||
(func $vm_execute
|
||||
;; MIR命令をデコード・実行
|
||||
)
|
||||
|
||||
;; エントリーポイント
|
||||
(func (export "main")
|
||||
(call $vm_execute)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
## 🎯 推奨アプローチ
|
||||
|
||||
### Phase 1: 現状維持
|
||||
- **Rust→WASM**: ブラウザでNyashを動かす用途で活用
|
||||
- **MIR→WASM**: 実験的機能として残す
|
||||
|
||||
### Phase 2: Nyash→Rust変換
|
||||
- NyashコードをRustに変換する仕組みを作る
|
||||
- 生成されたRustコードをwasm-packでビルド
|
||||
|
||||
### Phase 3: WasmGC待ち
|
||||
- WasmGC仕様が安定したら本格実装
|
||||
- Box型システムをWasmGCで表現
|
||||
|
||||
## 📝 結論
|
||||
|
||||
現在のMIR→WASM実装は**実験的**なもので、実用レベルには達していません。一方、Rust→WASMは**すでに動作**しており、ブラウザでNyashを体験してもらうには十分です。
|
||||
|
||||
**当面は**:
|
||||
1. Rust→WASMでプレイグラウンド提供
|
||||
2. ネイティブ実行(VM/JIT/AOT)に注力
|
||||
3. WasmGCの成熟を待つ
|
||||
|
||||
これが現実的な戦略です!
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user