📚 Phase 12: Nyashスクリプトプラグインシステム設計と埋め込みVM構想
## 主な成果 - Nyashスクリプトでプラグイン作成可能という革命的発見 - C ABI制約の分析と埋め込みVMによる解決策 - MIR/VM/JIT層での箱引数サポートの詳細分析 ## ドキュメント作成 - Phase 12基本構想(README.md) - Gemini/Codex先生の技術分析 - C ABIとの整合性問題と解決策 - 埋め込みVM実装ロードマップ - 箱引数サポートの技術詳細 ## 重要な洞察 - 制約は「リンク時にC ABI必要」のみ - 埋め込みVMでMIRバイトコード実行により解決可能 - Nyashスクリプト→C ABIプラグイン変換が実現可能 Everything is Box → Everything is Plugin → Everything is Possible!
This commit is contained in:
67
docs/development/roadmap/phases/phase-10.7/PLAN.txt
Normal file
67
docs/development/roadmap/phases/phase-10.7/PLAN.txt
Normal file
@ -0,0 +1,67 @@
|
||||
# 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) 方針(判断)
|
||||
====================
|
||||
- 二本立てを明確化:
|
||||
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に対して適用)。
|
||||
|
||||
148
docs/development/roadmap/phases/phase-10.7/README.md
Normal file
148
docs/development/roadmap/phases/phase-10.7/README.md
Normal file
@ -0,0 +1,148 @@
|
||||
# Phase 10.7 - True Python Native via Plugin Boxes
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
PythonコードをNyashで**本当にネイティブ実行**する。CPythonへの依存なしに、Pythonコードが完全にNyash MIR/JIT経由で機械語として実行される。
|
||||
|
||||
### 現状 vs 理想
|
||||
|
||||
**現状(Phase 10.6)**: PyRuntimeBox → libpython呼び出し
|
||||
**理想(Phase 10.7)**: Python → Nyashスクリプト → MIR → ネイティブ
|
||||
|
||||
## 🏗️ アーキテクチャ:トランスパイル方式
|
||||
|
||||
```
|
||||
Python AST → CorePy IR → Nyash AST → Nyashスクリプト
|
||||
```
|
||||
|
||||
### なぜトランスパイル?
|
||||
|
||||
1. **透明性**: 生成コードが見える・デバッグできる・手を加えられる
|
||||
2. **既存資産活用**: Nyashコンパイラの最適化を自動享受
|
||||
3. **教育的価値**: PythonとNyashの対応が学習価値を持つ
|
||||
4. **段階的改善**: 生成コードの品質を徐々に向上
|
||||
|
||||
### プラグインBox群
|
||||
|
||||
- **PythonParserBox**: Python → AST変換
|
||||
- **PythonCompilerBox**: AST → Nyashスクリプト生成
|
||||
- **py_runtime.ny**: Pythonセマンティクス保持ライブラリ
|
||||
|
||||
## ⚠️ 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 10.7a - Parser Plugin(1週間)
|
||||
- PythonParserBoxの実装
|
||||
- Python AST → ASTBox変換
|
||||
- テレメトリー基盤
|
||||
|
||||
### Phase 10.7b - Compiler Core(2週間)
|
||||
**Phase 1機能(必須)**
|
||||
- 関数定義、条件分岐、ループ
|
||||
- 演算子、関数呼び出し
|
||||
- Python固有:LEGB、デフォルト引数、for/else
|
||||
|
||||
### Phase 10.7c - Validation & Testing(1週間)
|
||||
- コンパイル可能性の事前検証
|
||||
- Differential testing(CPythonと比較)
|
||||
- 明確なエラーメッセージ
|
||||
|
||||
### Phase 10.7d - Coverage拡大(3-4週間)
|
||||
**Phase 2**: 例外処理、with文、comprehensions
|
||||
**Phase 3**: 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完了時
|
||||
```
|
||||
Compilable files: 15/100 (15%)
|
||||
Performance (numeric): 10x faster than CPython
|
||||
Correctness: 100% (differential testing)
|
||||
```
|
||||
|
||||
### 最終目標(Phase 3)
|
||||
```
|
||||
Coverage: 95%+ of common patterns
|
||||
Performance: 5-20x faster
|
||||
Distribution: Single binary, no CPython
|
||||
```
|
||||
|
||||
## 🚀 クイックスタート
|
||||
|
||||
```bash
|
||||
# プラグイン作成
|
||||
cd plugins/
|
||||
cargo new nyash-python-parser-plugin --lib
|
||||
|
||||
# 最小実装
|
||||
[dependencies]
|
||||
pyo3 = { version = "0.22", features = ["auto-initialize"] }
|
||||
nyash-plugin-sdk = { path = "../../crates/plugin-sdk" }
|
||||
|
||||
# テスト実行
|
||||
cargo build --release
|
||||
../../target/release/nyash test_parser.nyash
|
||||
```
|
||||
|
||||
## 💡 創造的可能性
|
||||
|
||||
### ハイブリッドプログラミング
|
||||
```python
|
||||
@nyash.vectorize # PythonデコレータがNyashのSIMD生成!
|
||||
def matrix_multiply(a, b):
|
||||
return a @ b
|
||||
```
|
||||
|
||||
### 言語の共進化
|
||||
- Nyashが「Pythonで最も使われるイディオム」から学習
|
||||
- Pythonに「Nyash-aware」コーディングスタイル誕生
|
||||
|
||||
### 教育的インパクト
|
||||
左にPython、右にリアルタイムNyash変換のPlayground
|
||||
|
||||
## 📚 参考資料
|
||||
|
||||
- **archive/gemini-analysis-transpile-beauty.md** - 創造性分析
|
||||
- **archive/codex-analysis-technical-implementation.md** - 技術分析
|
||||
@ -0,0 +1,252 @@
|
||||
# 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.
|
||||
@ -0,0 +1,72 @@
|
||||
# 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プロジェクトの成功に大きく貢献する戦略的な一手だと確信します。
|
||||
295
docs/development/roadmap/phases/phase-10.7/examples.md
Normal file
295
docs/development/roadmap/phases/phase-10.7/examples.md
Normal file
@ -0,0 +1,295 @@
|
||||
# Python Native実装例
|
||||
|
||||
## 🎯 実装イメージ
|
||||
|
||||
### 使用例1: 基本的な関数のネイティブ化
|
||||
|
||||
```nyash
|
||||
// example1_basic.nyash
|
||||
// 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.nyash
|
||||
// コンパイルできるかどうか事前に判定
|
||||
|
||||
// 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.nyash
|
||||
// 実行しながら徐々に最適化
|
||||
|
||||
// 型推論付きコンパイラー
|
||||
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.nyash
|
||||
// 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.nyash
|
||||
// 開発時のデバッグ支援
|
||||
|
||||
// デバッグモード有効
|
||||
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に匹敵!)
|
||||
```
|
||||
249
docs/development/roadmap/phases/phase-10.7/implementation.md
Normal file
249
docs/development/roadmap/phases/phase-10.7/implementation.md
Normal file
@ -0,0 +1,249 @@
|
||||
# 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文
|
||||
285
docs/development/roadmap/phases/phase-10.7/testing-plan.md
Normal file
285
docs/development/roadmap/phases/phase-10.7/testing-plan.md
Normal file
@ -0,0 +1,285 @@
|
||||
# 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.nyash
|
||||
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.nyash
|
||||
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ケース追加
|
||||
- [ ] ベンチマーク結果(該当する場合)
|
||||
- [ ] カバレッジ低下なし
|
||||
@ -0,0 +1,13 @@
|
||||
# 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の最小拡張が必要になる場合あり。
|
||||
@ -0,0 +1,39 @@
|
||||
# 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化する)。
|
||||
@ -0,0 +1,21 @@
|
||||
# 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 に隔離(本流に混ぜない)
|
||||
|
||||
13
docs/development/roadmap/phases/phase-10.7/workbench/TODO.md
Normal file
13
docs/development/roadmap/phases/phase-10.7/workbench/TODO.md
Normal file
@ -0,0 +1,13 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user