📚 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:
@ -0,0 +1,142 @@
|
||||
# 埋め込みVMでの箱引数サポート
|
||||
|
||||
## 🎯 結論:完全にサポート可能
|
||||
|
||||
現在のMIR/VM/JIT/プラグインすべてで**箱は箱を引数にできる**仕組みが確立されており、埋め込みVMでも同じパターンで実装可能です。
|
||||
|
||||
## 📊 各層での箱引数の扱い
|
||||
|
||||
### 1. Nyashスクリプトレベル
|
||||
```nyash
|
||||
// 箱を引数に取るメソッド
|
||||
box Processor {
|
||||
process(inputBox, configBox) {
|
||||
// inputBoxもconfigBoxも箱インスタンス
|
||||
local data = inputBox.getData()
|
||||
local settings = configBox.getSettings()
|
||||
return me.transform(data, settings)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. MIRレベル
|
||||
```
|
||||
; box1.process(box2, box3)
|
||||
%4 = BoxCall %1.process(%2, %3)
|
||||
```
|
||||
|
||||
### 3. 埋め込みVMでの実装
|
||||
|
||||
#### バイトコード表現
|
||||
```c
|
||||
// BoxCall命令: [op][dst][recv][method_id:2][argc][args...]
|
||||
// 例: box1.process(box2, box3)
|
||||
0x20 // OP_BOXCALL
|
||||
0x04 // dst: %4
|
||||
0x01 // recv: %1 (box1)
|
||||
0x00 0x10 // method_id: 16 (process)
|
||||
0x02 // argc: 2
|
||||
0x02 // arg[0]: %2 (box2)
|
||||
0x03 // arg[1]: %3 (box3)
|
||||
```
|
||||
|
||||
#### 実行時処理
|
||||
```c
|
||||
// 埋め込みVMでの箱引数処理
|
||||
int nyvm_execute_boxcall(NyashEmbeddedVM* vm, ...) {
|
||||
// レシーバー取得
|
||||
NyVMValue* recv = &vm->values[recv_idx];
|
||||
|
||||
// 引数をTLVエンコード
|
||||
for (int i = 0; i < argc; i++) {
|
||||
NyVMValue* arg = &vm->values[args[i]];
|
||||
|
||||
if (arg->type == NYVM_TYPE_HANDLE) {
|
||||
// 箱引数はハンドルとしてエンコード
|
||||
uint32_t type_id = get_type_id_from_handle(arg->value.h);
|
||||
uint32_t inst_id = get_instance_id_from_handle(arg->value.h);
|
||||
encode_handle(&tlv, type_id, inst_id);
|
||||
} else {
|
||||
// プリミティブ値
|
||||
encode_primitive(&tlv, arg);
|
||||
}
|
||||
}
|
||||
|
||||
// C ABIプラグイン呼び出し
|
||||
return nyash_plugin_invoke(...);
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 ハンドル管理の詳細
|
||||
|
||||
### 1. ハンドルレジストリ
|
||||
```c
|
||||
// グローバルハンドルテーブル
|
||||
typedef struct {
|
||||
uint32_t type_id; // Box型ID
|
||||
uint32_t instance_id; // インスタンスID
|
||||
uint8_t flags; // GC/所有権フラグ
|
||||
} HandleEntry;
|
||||
|
||||
static HandleEntry g_handles[MAX_HANDLES];
|
||||
|
||||
// 新しい箱インスタンスの登録
|
||||
uint64_t register_box_handle(uint32_t type_id, uint32_t instance_id) {
|
||||
uint64_t handle = allocate_handle();
|
||||
g_handles[handle] = (HandleEntry){
|
||||
.type_id = type_id,
|
||||
.instance_id = instance_id,
|
||||
.flags = HANDLE_OWNED
|
||||
};
|
||||
return handle;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. プラグイン間の箱共有
|
||||
```c
|
||||
// プラグインAが箱を返す
|
||||
int plugin_a_create_box(uint8_t* result, size_t* result_len) {
|
||||
// 新しい箱を作成
|
||||
uint32_t type_id = 100; // CustomBox
|
||||
uint32_t inst_id = create_instance();
|
||||
|
||||
// TLVエンコード
|
||||
encode_handle(result, type_id, inst_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// プラグインBが箱を受け取る
|
||||
int plugin_b_process(const uint8_t* args, size_t args_len) {
|
||||
// TLVデコード
|
||||
uint32_t type_id, inst_id;
|
||||
decode_handle(args, &type_id, &inst_id);
|
||||
|
||||
// 箱を使用
|
||||
process_box(type_id, inst_id);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 💡 重要なポイント
|
||||
|
||||
### 1. 型安全性
|
||||
- ハンドルには型情報(type_id)が含まれる
|
||||
- 実行時の型チェックが可能
|
||||
|
||||
### 2. 所有権管理
|
||||
- ハンドルは参照カウント or GC管理
|
||||
- プラグイン間で安全に共有
|
||||
|
||||
### 3. 相互運用性
|
||||
- ネイティブBox ↔ スクリプトBox間で透過的
|
||||
- 同じハンドル機構を使用
|
||||
|
||||
## 🎯 結論
|
||||
|
||||
埋め込みVMでも:
|
||||
1. **箱は箱を引数に取れる**(ハンドル経由)
|
||||
2. **型情報を保持**(type_id)
|
||||
3. **プラグイン間で共有可能**(instance_id)
|
||||
4. **C ABIと完全互換**(TLVエンコード)
|
||||
|
||||
これにより、Nyashスクリプトで書いた高度なBoxコンポジションも、C ABIプラグインとして動作します!
|
||||
106
docs/development/roadmap/phases/phase-12/CRITICAL-ISSUE.md
Normal file
106
docs/development/roadmap/phases/phase-12/CRITICAL-ISSUE.md
Normal file
@ -0,0 +1,106 @@
|
||||
# 🚨 重大な設計問題:スクリプトプラグインとMIR/EXEの非互換性
|
||||
|
||||
## 問題の本質
|
||||
|
||||
**MIR/JIT/AOT(EXE)は、C ABIの関数しか呼び出せない。**
|
||||
|
||||
```
|
||||
現実のフロー:
|
||||
MIR → JIT → C関数呼び出し(固定アドレス)→ ネイティブコード実行
|
||||
MIR → AOT → EXE内のC関数(静的リンク)→ ネイティブコード実行
|
||||
|
||||
不可能なフロー:
|
||||
MIR → ??? → Nyashスクリプト実行(インタープリター必要)
|
||||
```
|
||||
|
||||
## なぜスクリプトプラグインは動作しないのか
|
||||
|
||||
### 1. インタープリター依存
|
||||
```nyash
|
||||
// スクリプトプラグイン
|
||||
export box CustomMath {
|
||||
sin(x) { return me._math.sin(x) }
|
||||
}
|
||||
```
|
||||
↓
|
||||
**実行にはNyash VMが必要** → EXEに埋め込めない
|
||||
|
||||
### 2. 動的型システム
|
||||
- C ABI: 静的型(i32, i64, double等)
|
||||
- Nyashスクリプト: 動的型(Box)
|
||||
- 型変換にはランタイムが必要
|
||||
|
||||
### 3. メモリ管理
|
||||
- C ABI: 手動管理またはシンプルなGC
|
||||
- Nyashスクリプト: Arc<Mutex<dyn NyashBox>>
|
||||
- GC/参照カウント管理にランタイムが必要
|
||||
|
||||
## 実例:なぜFileBoxはC ABIなのか
|
||||
|
||||
```rust
|
||||
// FileBoxプラグイン(ネイティブ)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyash_plugin_invoke(...) -> i32 {
|
||||
// 直接システムコール可能
|
||||
// VMなしで動作
|
||||
// EXEに静的リンク可能
|
||||
}
|
||||
```
|
||||
|
||||
対して、Nyashスクリプトは:
|
||||
- VM必須
|
||||
- 動的評価
|
||||
- EXEに埋め込み不可
|
||||
|
||||
## 結論:Phase 12の方向転換が必要
|
||||
|
||||
### ❌ 不可能なこと
|
||||
- スクリプトプラグインをJIT/AOTから直接呼び出し
|
||||
- スクリプトプラグインをEXEに埋め込み
|
||||
- ネイティブプラグインと完全に透過的な利用
|
||||
|
||||
### ✅ 可能なこと
|
||||
1. **インタープリターモード限定**
|
||||
- スクリプトプラグインはインタープリター実行時のみ
|
||||
- 開発/プロトタイピング用途
|
||||
|
||||
2. **トランスパイル方式**
|
||||
- Nyashスクリプト → C/Rust → ネイティブプラグイン
|
||||
- ビルドステップが必要
|
||||
|
||||
3. **ハイブリッド実行**
|
||||
- 開発時: スクリプトプラグイン(高速イテレーション)
|
||||
- 本番時: ネイティブプラグイン(高性能)
|
||||
|
||||
## 修正された価値提案
|
||||
|
||||
### 開発フローの改善
|
||||
```
|
||||
1. アイデア → Nyashスクリプトでプロトタイプ
|
||||
2. 動作確認 → インタープリターでテスト
|
||||
3. 性能要求 → Rust/Cで再実装
|
||||
4. 配布 → ネイティブプラグインとして
|
||||
```
|
||||
|
||||
### 制限事項の明確化
|
||||
- **JIT/AOT**: ネイティブプラグインのみ
|
||||
- **インタープリター**: スクリプトプラグインも可
|
||||
- **EXE生成**: ネイティブプラグインのみ含む
|
||||
|
||||
## 推奨アクション
|
||||
|
||||
1. **Phase 12の再定義**
|
||||
- 「開発支援ツール」として位置づけ
|
||||
- JIT/AOT統合は諦める
|
||||
|
||||
2. **ドキュメント修正**
|
||||
- 制限事項を明確に記載
|
||||
- 誤解を招く「透過的利用」を削除
|
||||
|
||||
3. **代替案の検討**
|
||||
- Nyash→Rustトランスパイラー
|
||||
- プラグインテンプレート生成ツール
|
||||
|
||||
---
|
||||
|
||||
**重要な教訓:C ABIの制約は、システムプログラミングの本質的な制約である。**
|
||||
@ -0,0 +1,207 @@
|
||||
# 埋め込みVMでのBox処理設計
|
||||
|
||||
## 🎯 核心:MIRレベルでのBox処理を再現
|
||||
|
||||
### 現在のMIR/VMでのBox処理フロー
|
||||
|
||||
```
|
||||
1. MIR: BoxCall/PluginInvoke命令
|
||||
↓
|
||||
2. VM: ValueId → VMValue変換
|
||||
↓
|
||||
3. VMValue → Box<dyn NyashBox> or TLVエンコード
|
||||
↓
|
||||
4. メソッド実行
|
||||
↓
|
||||
5. 結果をVMValueに戻す
|
||||
```
|
||||
|
||||
## 📊 埋め込みVMの設計
|
||||
|
||||
### 1. 軽量VMValue定義
|
||||
|
||||
```c
|
||||
// 埋め込みVM用の値表現
|
||||
typedef enum {
|
||||
NYVM_TYPE_INT,
|
||||
NYVM_TYPE_FLOAT,
|
||||
NYVM_TYPE_BOOL,
|
||||
NYVM_TYPE_STRING,
|
||||
NYVM_TYPE_HANDLE, // Box参照(ハンドル)
|
||||
NYVM_TYPE_VOID
|
||||
} NyVMType;
|
||||
|
||||
typedef struct {
|
||||
NyVMType type;
|
||||
union {
|
||||
int64_t i;
|
||||
double f;
|
||||
uint8_t b;
|
||||
struct { const char* data; size_t len; } s;
|
||||
uint64_t h; // ハンドル(Box参照)
|
||||
} value;
|
||||
} NyVMValue;
|
||||
```
|
||||
|
||||
### 2. MIRバイトコード形式
|
||||
|
||||
```c
|
||||
// BoxCall命令のエンコード
|
||||
enum {
|
||||
OP_BOXCALL = 0x20,
|
||||
OP_PLUGIN_INVOKE = 0x21,
|
||||
// ...
|
||||
};
|
||||
|
||||
// BoxCall: [op:1] [dst:1] [box_val:1] [method_id:2] [argc:1] [args...]
|
||||
// 例: BoxCall %2 = %1.toString()
|
||||
// → 0x20 0x02 0x01 0x00 0x00 0x00
|
||||
```
|
||||
|
||||
### 3. 埋め込みVMでのBoxCall実行
|
||||
|
||||
```c
|
||||
int nyvm_execute_boxcall(
|
||||
NyashEmbeddedVM* vm,
|
||||
uint8_t dst,
|
||||
uint8_t box_val,
|
||||
uint16_t method_id,
|
||||
uint8_t argc,
|
||||
uint8_t* args
|
||||
) {
|
||||
// 1. レシーバー取得
|
||||
NyVMValue* recv = &vm->values[box_val];
|
||||
|
||||
// 2. プリミティブ型の場合
|
||||
if (recv->type != NYVM_TYPE_HANDLE) {
|
||||
// プリミティブ→TLV変換
|
||||
uint8_t tlv_buf[256];
|
||||
size_t tlv_len = encode_primitive_to_tlv(recv, tlv_buf);
|
||||
|
||||
// 組み込み実装を呼び出し
|
||||
return call_builtin_method(recv->type, method_id, tlv_buf, tlv_len);
|
||||
}
|
||||
|
||||
// 3. Box(ハンドル)の場合
|
||||
uint64_t handle = recv->value.h;
|
||||
|
||||
// 引数をTLVエンコード
|
||||
uint8_t args_tlv[1024];
|
||||
size_t args_len = 0;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
NyVMValue* arg = &vm->values[args[i]];
|
||||
args_len += encode_value_to_tlv(arg, &args_tlv[args_len]);
|
||||
}
|
||||
|
||||
// 4. プラグイン呼び出し(C ABI)
|
||||
uint8_t result[4096];
|
||||
size_t result_len = sizeof(result);
|
||||
|
||||
int rc = nyash_plugin_invoke(
|
||||
get_type_id_from_handle(handle),
|
||||
method_id,
|
||||
get_instance_id_from_handle(handle),
|
||||
args_tlv, args_len,
|
||||
result, &result_len
|
||||
);
|
||||
|
||||
// 5. 結果をVMValueに変換
|
||||
if (rc == 0) {
|
||||
decode_tlv_to_value(result, result_len, &vm->values[dst]);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 Box引数の処理
|
||||
|
||||
### 現在のVM(Rust)
|
||||
```rust
|
||||
// VMValue → Box<dyn NyashBox>変換
|
||||
let val = self.get_value(*arg)?;
|
||||
Ok(val.to_nyash_box())
|
||||
```
|
||||
|
||||
### 埋め込みVM(C)
|
||||
```c
|
||||
// NyVMValue → TLVエンコード
|
||||
switch (value->type) {
|
||||
case NYVM_TYPE_INT:
|
||||
encode_i64(tlv, value->value.i);
|
||||
break;
|
||||
case NYVM_TYPE_HANDLE:
|
||||
encode_handle(tlv,
|
||||
get_type_id_from_handle(value->value.h),
|
||||
get_instance_id_from_handle(value->value.h)
|
||||
);
|
||||
break;
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 💡 実装のポイント
|
||||
|
||||
### 1. ハンドル管理
|
||||
```c
|
||||
// グローバルハンドルテーブル
|
||||
typedef struct {
|
||||
uint32_t type_id;
|
||||
uint32_t instance_id;
|
||||
void* native_ptr; // 実際のBoxポインタ(必要な場合)
|
||||
} HandleEntry;
|
||||
|
||||
static HandleEntry g_handles[MAX_HANDLES];
|
||||
static uint64_t g_next_handle = 1;
|
||||
|
||||
uint64_t register_handle(uint32_t type_id, uint32_t instance_id) {
|
||||
uint64_t h = g_next_handle++;
|
||||
g_handles[h].type_id = type_id;
|
||||
g_handles[h].instance_id = instance_id;
|
||||
return h;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 組み込みメソッド
|
||||
```c
|
||||
// 頻出メソッドは埋め込みVMに直接実装
|
||||
int call_builtin_method(NyVMType type, uint16_t method_id, ...) {
|
||||
switch (type) {
|
||||
case NYVM_TYPE_INT:
|
||||
if (method_id == 0) { // toString
|
||||
// 整数→文字列変換
|
||||
}
|
||||
break;
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. プラグインとの統合
|
||||
```c
|
||||
// 生成されるCコード
|
||||
extern "C" int32_t nyplug_mybox_invoke(...) {
|
||||
// MIRバイトコード実行
|
||||
NyashEmbeddedVM vm;
|
||||
nyvm_init(&vm, BYTECODE, sizeof(BYTECODE));
|
||||
|
||||
// 引数をVMスタックに設定
|
||||
nyvm_decode_args(&vm, args, args_len);
|
||||
|
||||
// メソッド実行
|
||||
nyvm_execute_method(&vm, method_id);
|
||||
|
||||
// 結果をTLVエンコード
|
||||
return nyvm_encode_result(&vm, result, result_len);
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 結論
|
||||
|
||||
埋め込みVMは:
|
||||
1. **MIRのBoxCall/PluginInvoke命令を忠実に実装**
|
||||
2. **TLVエンコード/デコードでC ABIと通信**
|
||||
3. **ハンドルでBox参照を管理**
|
||||
4. **頻出処理は最適化実装**
|
||||
|
||||
これにより、Nyashスクリプトで書いたプラグインも、ネイティブプラグインと同じC ABIで動作します!
|
||||
@ -0,0 +1,195 @@
|
||||
# 埋め込みVM実装ロードマップ
|
||||
|
||||
## 🎯 目標:スクリプトプラグインのC ABI化
|
||||
|
||||
**Nyashスクリプト → C ABIプラグイン変換の完全自動化**
|
||||
|
||||
## 📊 技術スタック
|
||||
|
||||
```
|
||||
[Nyashスクリプト]
|
||||
↓ パース・型チェック
|
||||
[MIR (中間表現)]
|
||||
↓ 最適化・定数畳み込み
|
||||
[MIRバイトコード]
|
||||
↓ 埋め込み
|
||||
[Cソースコード] ← nyash-to-c ツール
|
||||
↓ コンパイル (cc/clang/gcc)
|
||||
[.so/.dll/.a] ← 通常のプラグイン!
|
||||
```
|
||||
|
||||
## 🚀 実装フェーズ
|
||||
|
||||
### Phase 12.1: 最小埋め込みVM(2-3週間)
|
||||
|
||||
#### 1. MIRバイトコード設計
|
||||
```rust
|
||||
// mir_bytecode.rs
|
||||
pub enum CompactInstruction {
|
||||
// 1バイト命令(頻出)
|
||||
LoadLocal(u8), // 0x00-0x7F
|
||||
StoreLocal(u8), // 0x80-0xFF
|
||||
|
||||
// 2バイト命令
|
||||
LoadConst(u8), // 0x01 XX
|
||||
Call(u8), // 0x02 XX
|
||||
|
||||
// 可変長
|
||||
LoadString, // 0x03 [len:u16] [data]
|
||||
Jump, // 0x04 [offset:i16]
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 埋め込みVMコア
|
||||
```c
|
||||
// nyash_embedded_vm.h
|
||||
typedef struct {
|
||||
const uint8_t* bytecode;
|
||||
size_t bytecode_len;
|
||||
|
||||
// 実行時状態(最小)
|
||||
void* stack[256];
|
||||
int sp;
|
||||
void* locals[16];
|
||||
} NyashEmbeddedVM;
|
||||
|
||||
int32_t nyash_embedded_execute(
|
||||
const uint8_t* bytecode,
|
||||
size_t bytecode_len,
|
||||
uint32_t method_id,
|
||||
const uint8_t* args,
|
||||
size_t args_len,
|
||||
uint8_t* result,
|
||||
size_t* result_len
|
||||
);
|
||||
```
|
||||
|
||||
### Phase 12.2: Nyash→Cトランスパイラー(3-4週間)
|
||||
|
||||
#### 1. 基本変換
|
||||
```bash
|
||||
$ nyash-to-c math_plugin.ny -o math_plugin.c
|
||||
Generating C plugin from Nyash script...
|
||||
- Parsing... OK
|
||||
- Type checking... OK
|
||||
- MIR generation... OK
|
||||
- Bytecode emission... OK
|
||||
- C code generation... OK
|
||||
Output: math_plugin.c (2.3KB)
|
||||
```
|
||||
|
||||
#### 2. 生成コード例
|
||||
```c
|
||||
// Generated from: math_plugin.ny
|
||||
#include <nyash_embedded.h>
|
||||
|
||||
// MIRバイトコード(最適化済み)
|
||||
static const uint8_t BYTECODE[] = {
|
||||
0x01, 0x00, // Version 1.0
|
||||
0x01, 0x00, // 1 function
|
||||
|
||||
// Function: cached_sin
|
||||
0x00, 0x08, // Function header
|
||||
0x80, 0x00, // StoreLocal 0 (x)
|
||||
0x02, 0x10, // Call sin
|
||||
0x90, // Return
|
||||
};
|
||||
|
||||
// プラグインエントリポイント
|
||||
extern "C" int32_t nyplug_math_plugin_invoke(
|
||||
uint32_t type_id,
|
||||
uint32_t method_id,
|
||||
uint32_t instance_id,
|
||||
const uint8_t* args,
|
||||
size_t args_len,
|
||||
uint8_t* result,
|
||||
size_t* result_len
|
||||
) {
|
||||
return nyash_embedded_execute(
|
||||
BYTECODE, sizeof(BYTECODE),
|
||||
method_id,
|
||||
args, args_len,
|
||||
result, result_len
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 12.3: 最適化とツールチェーン(4-6週間)
|
||||
|
||||
#### 1. ビルドシステム統合
|
||||
```toml
|
||||
# nyash.toml
|
||||
[[plugins]]
|
||||
name = "math_plugin"
|
||||
source = "plugins/math_plugin.ny" # Nyashソース
|
||||
type = "script" # 自動的にC変換
|
||||
|
||||
[[plugins]]
|
||||
name = "file_plugin"
|
||||
source = "plugins/file_plugin/Cargo.toml"
|
||||
type = "native" # 従来のRustプラグイン
|
||||
```
|
||||
|
||||
#### 2. 自動ビルドパイプライン
|
||||
```bash
|
||||
$ nyash build --plugins
|
||||
Building plugins...
|
||||
[1/2] math_plugin (script)
|
||||
- Transpiling to C... OK
|
||||
- Compiling... OK
|
||||
- Output: target/plugins/libmath_plugin.so
|
||||
[2/2] file_plugin (native)
|
||||
- Building with cargo... OK
|
||||
- Output: target/plugins/libfile_plugin.so
|
||||
Done!
|
||||
```
|
||||
|
||||
## 📈 パフォーマンス目標
|
||||
|
||||
| 操作 | ネイティブ | 埋め込みVM | 目標比率 |
|
||||
|------|-----------|------------|----------|
|
||||
| 単純計算 | 10ns | 50ns | 5x |
|
||||
| メソッド呼び出し | 20ns | 100ns | 5x |
|
||||
| 文字列操作 | 100ns | 200ns | 2x |
|
||||
| I/O操作 | 10μs | 10.1μs | 1.01x |
|
||||
|
||||
## 🔧 開発ツール
|
||||
|
||||
### 1. デバッガ
|
||||
```bash
|
||||
$ nyash-debug math_plugin.ny --method cached_sin --args "[3.14]"
|
||||
Executing cached_sin(3.14)...
|
||||
[PC:0000] LoadLocal 0 ; x = 3.14
|
||||
[PC:0002] Call sin ; sin(3.14)
|
||||
[PC:0004] Return ; 0.0015926...
|
||||
Result: 0.0015926
|
||||
```
|
||||
|
||||
### 2. プロファイラ
|
||||
```bash
|
||||
$ nyash-profile math_plugin.so
|
||||
Method statistics:
|
||||
- cached_sin: 1000 calls, avg 120ns
|
||||
- cached_cos: 500 calls, avg 115ns
|
||||
Bottlenecks: None detected
|
||||
```
|
||||
|
||||
## 🎉 最終形
|
||||
|
||||
```bash
|
||||
# 開発者の体験
|
||||
$ cat my_plugin.ny
|
||||
export box MyPlugin {
|
||||
init { cache = new MapBox() }
|
||||
process(x) { return x * 2 }
|
||||
}
|
||||
|
||||
$ nyash build my_plugin.ny
|
||||
✓ Generated: my_plugin.so
|
||||
|
||||
$ nyash run --plugin my_plugin.so test.ny
|
||||
✓ Plugin loaded (C ABI)
|
||||
✓ Result: 42
|
||||
```
|
||||
|
||||
**Nyashで書いて、どこでも動く!**
|
||||
115
docs/development/roadmap/phases/phase-12/README.md
Normal file
115
docs/development/roadmap/phases/phase-12/README.md
Normal file
@ -0,0 +1,115 @@
|
||||
# Phase 12: Nyashスクリプトプラグインシステム革命
|
||||
|
||||
## 🚀 概要
|
||||
|
||||
Nyashスクリプト自体でプラグインを作成できる革命的発見!ビルド不要で、既存のネイティブプラグインを組み合わせて新機能を作成可能。
|
||||
|
||||
## 💡 発見の経緯
|
||||
|
||||
include/export仕様の検討中に、以下の重要な気づきが:
|
||||
|
||||
```nyash
|
||||
# custom_math_plugin.ny
|
||||
export box CustomMathPlugin {
|
||||
init {
|
||||
_math = new MathBox() # 既存プラグイン活用
|
||||
_cache = new MapBox() # 結果キャッシュ
|
||||
}
|
||||
|
||||
// カスタム拡張
|
||||
cached_sin(x) {
|
||||
local key = x.toString()
|
||||
if me._cache.has(key) {
|
||||
return me._cache.get(key)
|
||||
}
|
||||
local result = me._math.sin(x)
|
||||
me._cache.set(key, result)
|
||||
return result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
これにより、Rust/C++のビルドなしでプラグイン開発が可能に!
|
||||
|
||||
## 🎯 統一Box ABI設計
|
||||
|
||||
### 基本インターフェース
|
||||
|
||||
```rust
|
||||
// Rust側の統一インターフェース
|
||||
trait BoxInterface {
|
||||
fn invoke(&self, method_id: u32, args: NyashValue) -> NyashValue;
|
||||
fn get_methods(&self) -> Vec<MethodInfo>;
|
||||
fn init(&mut self, ctx: Context);
|
||||
fn drop(&mut self);
|
||||
}
|
||||
```
|
||||
|
||||
### Nyashスクリプトプラグインの要件
|
||||
|
||||
```nyash
|
||||
export box MyPlugin {
|
||||
// 必須:初期化
|
||||
init { ... }
|
||||
|
||||
// 推奨:FFI互換インターフェース
|
||||
invoke(method_id, args) {
|
||||
// method_idに基づいてディスパッチ
|
||||
}
|
||||
|
||||
// オプション:メソッド情報
|
||||
get_methods() {
|
||||
return [
|
||||
{ name: "method1", id: 1 },
|
||||
{ name: "method2", id: 2 }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 エコシステムへの影響
|
||||
|
||||
### 開発の民主化
|
||||
- **参入障壁の劇的低下**: Rust/C++環境不要
|
||||
- **即座の開発**: ビルド待ち時間ゼロ
|
||||
- **コミュニティ拡大**: より多くの開発者が参加可能
|
||||
|
||||
### 新しい開発パターン
|
||||
1. **プラグインの合成**: 複数のネイティブプラグインを組み合わせ
|
||||
2. **ラピッドプロトタイピング**: アイデアを即座に実装
|
||||
3. **ホットリロード**: 実行中の更新が可能
|
||||
|
||||
## 🛣️ 実装ロードマップ
|
||||
|
||||
### Phase 12.1: 基盤構築
|
||||
- [ ] Box ABI仕様の最終決定
|
||||
- [ ] export box構文のパーサー実装
|
||||
- [ ] 基本的なPluginRegistry実装
|
||||
|
||||
### Phase 12.2: 統一インターフェース
|
||||
- [ ] FFIプラグインのBoxInterface対応
|
||||
- [ ] NyashスクリプトのBoxInterface実装
|
||||
- [ ] 相互運用テスト
|
||||
|
||||
### Phase 12.3: 動的機能
|
||||
- [ ] 動的ロード/アンロード機能
|
||||
- [ ] ホットリロード対応
|
||||
- [ ] プラグイン間依存関係管理
|
||||
|
||||
### Phase 12.4: セキュリティと最適化
|
||||
- [ ] サンドボックス実装
|
||||
- [ ] ケイパビリティベース権限
|
||||
- [ ] パフォーマンス最適化
|
||||
|
||||
## 📚 関連ドキュメント
|
||||
- [Gemini先生の分析](./gemini-analysis-script-plugins.md)
|
||||
- [Codex先生の技術提案](./codex-technical-proposal.md)
|
||||
- [統合分析まとめ](./synthesis-script-plugin-revolution.md)
|
||||
|
||||
## 🎯 次のアクション
|
||||
1. Box ABI仕様書の作成
|
||||
2. export box構文の実装開始
|
||||
3. 既存FFIプラグイン1つを統一インターフェースに移行
|
||||
|
||||
---
|
||||
*Everything is Box - そしてプラグインもBoxになる!*
|
||||
147
docs/development/roadmap/phases/phase-12/REVISED-PROPOSAL.md
Normal file
147
docs/development/roadmap/phases/phase-12/REVISED-PROPOSAL.md
Normal file
@ -0,0 +1,147 @@
|
||||
# Phase 12(改訂版):Nyashスクリプトプラグイン - 開発支援ツールとして
|
||||
|
||||
## 🎯 現実的な位置づけ
|
||||
|
||||
**スクリプトプラグインは、JIT/AOT/EXEとは独立した開発支援機能として実装する。**
|
||||
|
||||
## 📊 制約と可能性の整理
|
||||
|
||||
### ❌ できないこと(技術的制約)
|
||||
- MIR/VM/JIT/AOTからのスクリプトプラグイン呼び出し
|
||||
- スクリプトプラグインのEXE埋め込み
|
||||
- ネイティブプラグインとの完全な相互運用性
|
||||
|
||||
### ✅ できること(現実的な価値)
|
||||
- インタープリターモードでの高速プロトタイピング
|
||||
- 既存プラグインの組み合わせによる新機能開発
|
||||
- ビルド不要な機能拡張(開発時のみ)
|
||||
|
||||
## 🔄 修正された開発フロー
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ アイデア/要件 │
|
||||
└────────┬────────┘
|
||||
↓
|
||||
┌─────────────────┐
|
||||
│ Nyashスクリプト │ ← 高速イテレーション
|
||||
│ プラグイン作成 │ ビルド不要
|
||||
└────────┬────────┘
|
||||
↓
|
||||
┌─────────────────┐
|
||||
│ インタープリター│
|
||||
│ でテスト/検証 │
|
||||
└────────┬────────┘
|
||||
↓
|
||||
性能要求?
|
||||
↙ ↘
|
||||
No Yes
|
||||
↓ ↓
|
||||
そのまま Rust/Cで
|
||||
使用 再実装
|
||||
↓
|
||||
ネイティブ
|
||||
プラグイン
|
||||
↓
|
||||
JIT/AOT/EXE
|
||||
```
|
||||
|
||||
## 📝 実装方針
|
||||
|
||||
### 1. インタープリター専用機能として実装
|
||||
|
||||
```nyash
|
||||
// script_plugin.ny
|
||||
export box CustomLogic {
|
||||
init {
|
||||
_math = new MathBox() // ネイティブプラグイン利用
|
||||
_cache = new MapBox()
|
||||
}
|
||||
|
||||
process(data) {
|
||||
// 複雑なビジネスロジック
|
||||
// インタープリターでのみ実行
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 明確な使用場面の区別
|
||||
|
||||
```nyash
|
||||
// development.ny(開発時)
|
||||
local plugin = include("custom_logic.ny") // ✅ OK
|
||||
|
||||
// production.ny(本番時)
|
||||
local plugin = new CustomLogicBox() // ネイティブ版を使用
|
||||
```
|
||||
|
||||
### 3. トランスパイル支援ツール(将来)
|
||||
|
||||
```bash
|
||||
# Nyashスクリプト → Rustテンプレート生成
|
||||
nyash-to-rust custom_logic.ny > custom_logic_plugin/src/lib.rs
|
||||
```
|
||||
|
||||
## 🎯 価値提案(修正版)
|
||||
|
||||
### 開発者にとっての価値
|
||||
1. **探索的プログラミング** - アイデアを即座に試せる
|
||||
2. **プロトタイピング** - ビルドなしで機能検証
|
||||
3. **学習曲線の緩和** - Rust/C知識不要で拡張開発
|
||||
|
||||
### エコシステムへの貢献
|
||||
1. **アイデアの具現化** - スクリプトで検証→ネイティブで実装
|
||||
2. **コミュニティ参加** - より多くの開発者が貢献可能
|
||||
3. **ベストプラクティス** - 成功パターンの蓄積
|
||||
|
||||
## 🚀 実装計画(現実的版)
|
||||
|
||||
### Phase 12.1: 基盤構築(2週間)
|
||||
- [ ] export box構文(インタープリター専用)
|
||||
- [ ] include()関数の拡張
|
||||
- [ ] 基本的なプラグインレジストリ
|
||||
|
||||
### Phase 12.2: 開発体験向上(3週間)
|
||||
- [ ] ホットリロード(開発モード)
|
||||
- [ ] エラーメッセージ改善
|
||||
- [ ] デバッグ支援機能
|
||||
|
||||
### Phase 12.3: 移行支援(4週間)
|
||||
- [ ] パフォーマンス分析ツール
|
||||
- [ ] Rust変換テンプレート
|
||||
- [ ] 移行ガイドライン
|
||||
|
||||
## 📚 ドキュメント戦略
|
||||
|
||||
### 明確な制約の説明
|
||||
```markdown
|
||||
# Nyashスクリプトプラグイン
|
||||
|
||||
⚠️ **重要な制約**
|
||||
- インタープリターモードでのみ動作
|
||||
- JIT/AOT/EXEでは使用不可
|
||||
- 本番環境ではネイティブプラグインへの移行推奨
|
||||
```
|
||||
|
||||
### 使用例の充実
|
||||
- プロトタイピング例
|
||||
- ネイティブ移行例
|
||||
- パフォーマンス比較
|
||||
|
||||
## 🎉 期待される成果(現実的版)
|
||||
|
||||
### 短期(3ヶ月)
|
||||
- 開発効率の向上(プロトタイピング時間80%削減)
|
||||
- 新規開発者の参入(Rust不要)
|
||||
- アイデア検証の高速化
|
||||
|
||||
### 中期(1年)
|
||||
- 成功パターンの確立
|
||||
- ネイティブプラグインの品質向上
|
||||
- コミュニティ主導の機能提案増加
|
||||
|
||||
## 結論
|
||||
|
||||
**スクリプトプラグインは、C ABIの制約を認識した上で、開発支援ツールとして大きな価値を提供できる。**
|
||||
|
||||
「Everything is Box」の哲学は、実行時の制約はあれど、開発時の自由度として実現される。
|
||||
164
docs/development/roadmap/phases/phase-12/SOLUTION-EMBEDDED-VM.md
Normal file
164
docs/development/roadmap/phases/phase-12/SOLUTION-EMBEDDED-VM.md
Normal file
@ -0,0 +1,164 @@
|
||||
# 解決策:埋め込みVMによるスクリプトプラグイン実現
|
||||
|
||||
## 💡 発想の転換
|
||||
|
||||
**制約は「リンク時にC ABIが必要」だけ。つまり、C ABI関数の中でVMを動かせばいい!**
|
||||
|
||||
## 🎯 アーキテクチャ
|
||||
|
||||
```c
|
||||
// C ABI関数(静的リンク可能)
|
||||
extern "C" int32_t nyplug_custom_math_invoke(
|
||||
uint32_t method_id,
|
||||
const uint8_t* args,
|
||||
size_t args_len,
|
||||
uint8_t* result,
|
||||
size_t* result_len
|
||||
) {
|
||||
// 埋め込みVM起動
|
||||
static NyashVM* embedded_vm = NULL;
|
||||
if (!embedded_vm) {
|
||||
embedded_vm = nyash_vm_create_minimal();
|
||||
nyash_vm_load_script(embedded_vm, EMBEDDED_SCRIPT);
|
||||
}
|
||||
|
||||
// スクリプト実行
|
||||
return nyash_vm_invoke(embedded_vm, method_id, args, args_len, result, result_len);
|
||||
}
|
||||
|
||||
// スクリプトは文字列リテラルとして埋め込み
|
||||
static const char* EMBEDDED_SCRIPT = R"(
|
||||
export box CustomMath {
|
||||
cached_sin(x) {
|
||||
// Nyashコード
|
||||
}
|
||||
}
|
||||
)";
|
||||
```
|
||||
|
||||
## 🔄 実現方法
|
||||
|
||||
### 1. Nyash→C トランスパイラー
|
||||
|
||||
```bash
|
||||
# Nyashスクリプト → C関数
|
||||
nyash-to-c custom_math.ny > custom_math_plugin.c
|
||||
|
||||
# 生成されるC
|
||||
// custom_math_plugin.c
|
||||
#include "nyash_embedded_vm.h"
|
||||
|
||||
static const char* SCRIPT = "..."; // Nyashコード埋め込み
|
||||
|
||||
extern "C" int32_t nyplug_custom_math_invoke(...) {
|
||||
return nyash_embedded_invoke(SCRIPT, method_id, ...);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 最小VM実装
|
||||
|
||||
```rust
|
||||
// crates/nyash-embedded-vm
|
||||
pub struct EmbeddedVM {
|
||||
// 最小限の実行環境
|
||||
values: Vec<VMValue>,
|
||||
// スクリプトはプリコンパイル済みMIR
|
||||
mir: MirModule,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyash_embedded_invoke(
|
||||
script: *const c_char,
|
||||
method_id: u32,
|
||||
// ... TLV args/result
|
||||
) -> i32 {
|
||||
// MIR実行(インタープリター)
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 利点と制約
|
||||
|
||||
### ✅ 可能になること
|
||||
- **スクリプトプラグインがEXEに埋め込み可能**
|
||||
- **JIT/AOTから呼び出し可能**(C ABI経由)
|
||||
- **既存のプラグインシステムと完全互換**
|
||||
|
||||
### ⚠️ 制約
|
||||
- **パフォーマンス**: 埋め込みVMのオーバーヘッド
|
||||
- **サイズ**: 最小VMランタイムが必要(~500KB?)
|
||||
- **機能制限**: フルVMの一部機能のみ
|
||||
|
||||
## 🚀 段階的実装
|
||||
|
||||
### Phase 1: 最小埋め込みVM
|
||||
```rust
|
||||
// 必要最小限の機能
|
||||
- MIR実行(インタープリター)
|
||||
- 基本型(Integer, String, Bool)
|
||||
- メソッド呼び出し
|
||||
- TLVエンコード/デコード
|
||||
```
|
||||
|
||||
### Phase 2: Nyash→Cトランスパイラー
|
||||
```nyash
|
||||
// input: custom_math.ny
|
||||
export box CustomMath {
|
||||
sin(x) { ... }
|
||||
}
|
||||
|
||||
// output: custom_math_plugin.c
|
||||
extern "C" int32_t nyplug_custom_math_invoke(...) {
|
||||
static const uint8_t MIR_BYTECODE[] = { ... };
|
||||
return nyash_embedded_execute(MIR_BYTECODE, ...);
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: 最適化
|
||||
- MIRプリコンパイル
|
||||
- 頻出パスのネイティブ化
|
||||
- 選択的JITコンパイル
|
||||
|
||||
## 💡 実装例
|
||||
|
||||
```c
|
||||
// 生成されたプラグイン
|
||||
#include <nyash_embedded.h>
|
||||
|
||||
// MIRバイトコード(事前コンパイル)
|
||||
static const uint8_t CUSTOM_MATH_MIR[] = {
|
||||
0x01, 0x00, // version
|
||||
0x10, 0x00, // function count
|
||||
// ... MIR instructions
|
||||
};
|
||||
|
||||
extern "C" int32_t nyplug_custom_math_abi_version() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" int32_t nyplug_custom_math_invoke(
|
||||
uint32_t method_id,
|
||||
const uint8_t* args,
|
||||
size_t args_len,
|
||||
uint8_t* result,
|
||||
size_t* result_len
|
||||
) {
|
||||
// 埋め込みVM実行
|
||||
return nyash_mir_execute(
|
||||
CUSTOM_MATH_MIR,
|
||||
sizeof(CUSTOM_MATH_MIR),
|
||||
method_id,
|
||||
args, args_len,
|
||||
result, result_len
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 結論
|
||||
|
||||
**「リンク時にC ABI」という制約は、埋め込みVMで解決可能!**
|
||||
|
||||
- Nyashスクリプト → MIR → Cコード → ネイティブプラグイン
|
||||
- 開発の容易さ(Nyash)と配布の利便性(C ABI)を両立
|
||||
- 既存のプラグインエコシステムと完全互換
|
||||
|
||||
これで「Everything is Box」が真に実現する!
|
||||
175
docs/development/roadmap/phases/phase-12/c-abi-compatibility.md
Normal file
175
docs/development/roadmap/phases/phase-12/c-abi-compatibility.md
Normal file
@ -0,0 +1,175 @@
|
||||
# C ABIとの整合性:Phase 12スクリプトプラグインシステム
|
||||
|
||||
## 🚨 重要な発見
|
||||
|
||||
Phase 10.1で既に**C ABI v0**が定義されており、これとPhase 12の提案を整合させる必要があります。
|
||||
|
||||
## 📊 現状のC ABI(Phase 10.1)
|
||||
|
||||
### 既存のBID-FFI(プラグイン用)
|
||||
```c
|
||||
// 現在のプラグインFFI(TLVベース)
|
||||
extern "C" fn nyash_plugin_invoke(
|
||||
type_id: u32,
|
||||
method_id: u32,
|
||||
instance_id: u32,
|
||||
args: *const u8, // TLVエンコード
|
||||
args_len: usize,
|
||||
result: *mut u8, // TLVエンコード
|
||||
result_len: *mut usize,
|
||||
) -> i32
|
||||
```
|
||||
|
||||
### 新しいNyRT C ABI v0
|
||||
```c
|
||||
// コア関数
|
||||
int32_t nyrt_abi_version(void);
|
||||
NyBox nyrt_box_new(uint64_t typeid, uint64_t size);
|
||||
void nyrt_box_free(NyBox b);
|
||||
|
||||
// プラグイン関数(例:Array)
|
||||
int32_t nyplug_array_abi_version(void);
|
||||
NyBox nyplug_array_new(void);
|
||||
int32_t nyplug_array_get(NyBox arr, uint64_t i, NyBox* out);
|
||||
```
|
||||
|
||||
## 🎯 Phase 12の修正案
|
||||
|
||||
### 問題点
|
||||
- Gemini/Codexの提案した`BoxInterface`トレイトは**Rust専用**
|
||||
- C ABIとの相互運用性が考慮されていない
|
||||
- TLVエンコーディングとの整合性が不明
|
||||
|
||||
### 解決策:C ABIラッパー戦略
|
||||
|
||||
```rust
|
||||
// ❌ 元の提案(Rust専用)
|
||||
trait BoxInterface {
|
||||
fn invoke(&self, method_id: u32, args: NyashValue) -> NyashValue;
|
||||
}
|
||||
|
||||
// ✅ 修正案(C ABI互換)
|
||||
pub struct ScriptPluginWrapper {
|
||||
// Nyashスクリプトインスタンス
|
||||
script_box: NyashValue,
|
||||
|
||||
// C ABI互換性のためのFFI関数
|
||||
ffi_invoke: extern "C" fn(
|
||||
type_id: u32,
|
||||
method_id: u32,
|
||||
instance_id: u32,
|
||||
args: *const u8,
|
||||
args_len: usize,
|
||||
result: *mut u8,
|
||||
result_len: *mut usize,
|
||||
) -> i32,
|
||||
}
|
||||
|
||||
impl ScriptPluginWrapper {
|
||||
// 既存のBID-FFIと完全互換
|
||||
pub extern "C" fn invoke_ffi(
|
||||
&self,
|
||||
type_id: u32,
|
||||
method_id: u32,
|
||||
instance_id: u32,
|
||||
args: *const u8,
|
||||
args_len: usize,
|
||||
result: *mut u8,
|
||||
result_len: *mut usize,
|
||||
) -> i32 {
|
||||
// 1. TLVデコード
|
||||
let nyash_args = decode_tlv(args, args_len);
|
||||
|
||||
// 2. Nyashスクリプト呼び出し
|
||||
let result_value = self.script_box.invoke(method_id, nyash_args);
|
||||
|
||||
// 3. TLVエンコード
|
||||
encode_tlv(result_value, result, result_len)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 統合アーキテクチャ
|
||||
|
||||
```
|
||||
[JIT/AOT] ---> C ABI (nyrt_*/nyplug_*) --+--> [ネイティブプラグイン]
|
||||
|
|
||||
+--> [ScriptPluginWrapper] --> [Nyashスクリプト]
|
||||
```
|
||||
|
||||
### 利点
|
||||
1. **完全な後方互換性** - 既存のプラグインがそのまま動作
|
||||
2. **統一されたFFI** - JIT/AOT/プラグインすべて同じC ABI
|
||||
3. **透過的な利用** - 呼び出し側はネイティブ/スクリプトを区別しない
|
||||
|
||||
## 📝 実装修正案
|
||||
|
||||
### Phase 12.1(修正版)
|
||||
1. **ScriptPluginWrapperの実装**
|
||||
- BID-FFI互換のC関数エクスポート
|
||||
- TLVエンコード/デコード処理
|
||||
- Nyashスクリプトへの橋渡し
|
||||
|
||||
2. **プラグインレジストリ拡張**
|
||||
```rust
|
||||
pub struct PluginRegistry {
|
||||
// 既存のネイティブプラグイン(C ABI)
|
||||
native_plugins: HashMap<u32, PluginHandle>,
|
||||
|
||||
// スクリプトプラグイン(C ABIラッパー経由)
|
||||
script_plugins: HashMap<u32, ScriptPluginWrapper>,
|
||||
}
|
||||
```
|
||||
|
||||
3. **export box構文の実装**
|
||||
```nyash
|
||||
export box CustomMathPlugin {
|
||||
// BID-FFI互換のためのメタ情報
|
||||
__type_id__ = 100 // 動的割り当てor設定ファイル
|
||||
__methods__ = {
|
||||
"cached_sin": 1,
|
||||
"cached_cos": 2
|
||||
}
|
||||
|
||||
// 通常のNyashコード
|
||||
init { ... }
|
||||
cached_sin(x) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 移行パス
|
||||
|
||||
### 段階1:既存プラグインの動作確認
|
||||
- FileBox、NetBox等がC ABI経由で正常動作
|
||||
- パフォーマンステスト
|
||||
|
||||
### 段階2:簡単なスクリプトプラグイン
|
||||
- MathBoxの一部機能をNyashで再実装
|
||||
- C ABIラッパー経由での動作確認
|
||||
|
||||
### 段階3:高度な統合
|
||||
- ネイティブとスクリプトの混在
|
||||
- 動的ロード/アンロード
|
||||
|
||||
## ⚡ パフォーマンス影響
|
||||
|
||||
```
|
||||
呼び出しチェーン:
|
||||
1. JIT → C ABI関数呼び出し(既存)
|
||||
2. C ABI → ScriptPluginWrapper(追加)
|
||||
3. Wrapper → TLVデコード(追加)
|
||||
4. Wrapper → Nyashスクリプト実行(追加)
|
||||
5. Wrapper → TLVエンコード(追加)
|
||||
|
||||
予想オーバーヘッド: 100-500ns/呼び出し
|
||||
```
|
||||
|
||||
## 🎯 結論
|
||||
|
||||
Phase 12のスクリプトプラグインシステムは、**C ABIを尊重**しつつ実装可能です。
|
||||
|
||||
- BoxInterfaceトレイトは内部実装詳細に留める
|
||||
- 外部インターフェースは既存のC ABI(BID-FFI)を維持
|
||||
- ScriptPluginWrapperがブリッジとして機能
|
||||
|
||||
これにより、**「Everything is Plugin」**の哲学を保ちながら、スクリプトプラグインを実現できます。
|
||||
@ -0,0 +1,334 @@
|
||||
# Codex先生の技術提案:Nyashスクリプトプラグインシステム実装
|
||||
|
||||
## エグゼクティブサマリー
|
||||
|
||||
Nyashスクリプトをプラグインとして使用する提案は、技術的に極めて実現可能であり、Nyashエコシステムに革命的な価値をもたらします。「Everything is Box」哲学の究極の実現として、実装言語に依存しない統一インターフェースを提供することで、開発の民主化とエコシステムの爆発的成長が期待できます。
|
||||
|
||||
## 技術アーキテクチャ提案
|
||||
|
||||
### 1. 統一Box ABIの詳細設計
|
||||
|
||||
```rust
|
||||
// コアインターフェース定義
|
||||
pub trait UnifiedBoxInterface: Send + Sync {
|
||||
// 基本メソッド
|
||||
fn invoke(&self, ctx: &mut Context, method_id: u32, args: &[NyashValue]) -> Result<NyashValue, BoxError>;
|
||||
fn get_metadata(&self) -> BoxMetadata;
|
||||
|
||||
// ライフサイクル管理
|
||||
fn initialize(&mut self, config: &BoxConfig) -> Result<(), BoxError>;
|
||||
fn shutdown(&mut self) -> Result<(), BoxError>;
|
||||
|
||||
// 動的機能(オプション)
|
||||
fn hot_reload(&mut self, new_code: &str) -> Result<(), BoxError> {
|
||||
Err(BoxError::NotSupported)
|
||||
}
|
||||
}
|
||||
|
||||
// メタデータ構造
|
||||
pub struct BoxMetadata {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub methods: Vec<MethodInfo>,
|
||||
pub capabilities: Vec<Capability>,
|
||||
pub dependencies: Vec<Dependency>,
|
||||
}
|
||||
```
|
||||
|
||||
### 2. プラグインレジストリアーキテクチャ
|
||||
|
||||
```rust
|
||||
pub struct PluginRegistry {
|
||||
// ネイティブプラグイン
|
||||
native_plugins: HashMap<u32, Arc<dyn UnifiedBoxInterface>>,
|
||||
|
||||
// スクリプトプラグイン
|
||||
script_plugins: HashMap<u32, ScriptPlugin>,
|
||||
|
||||
// 動的ID管理
|
||||
id_allocator: IdAllocator,
|
||||
|
||||
// 依存関係グラフ
|
||||
dependency_graph: DependencyGraph,
|
||||
}
|
||||
|
||||
impl PluginRegistry {
|
||||
pub fn register_native(&mut self, plugin: impl UnifiedBoxInterface + 'static) -> u32 {
|
||||
let id = self.id_allocator.allocate();
|
||||
self.native_plugins.insert(id, Arc::new(plugin));
|
||||
id
|
||||
}
|
||||
|
||||
pub fn register_script(&mut self, source: &str) -> Result<u32, RegistryError> {
|
||||
let plugin = ScriptPlugin::compile(source)?;
|
||||
let id = self.id_allocator.allocate();
|
||||
self.script_plugins.insert(id, plugin);
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. スクリプトプラグインラッパー実装
|
||||
|
||||
```rust
|
||||
pub struct ScriptPlugin {
|
||||
vm: NyashVM,
|
||||
box_instance: NyashValue,
|
||||
method_cache: HashMap<u32, MethodHandle>,
|
||||
}
|
||||
|
||||
impl UnifiedBoxInterface for ScriptPlugin {
|
||||
fn invoke(&self, ctx: &mut Context, method_id: u32, args: &[NyashValue]) -> Result<NyashValue, BoxError> {
|
||||
// メソッドキャッシュから高速検索
|
||||
if let Some(handle) = self.method_cache.get(&method_id) {
|
||||
return self.vm.call_cached(handle, args);
|
||||
}
|
||||
|
||||
// 動的メソッド解決
|
||||
let method = self.resolve_method(method_id)?;
|
||||
self.vm.call_method(&self.box_instance, &method, args)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 実装戦略
|
||||
|
||||
### Phase 1: MVP実装(2-3週間)
|
||||
|
||||
1. **基本インターフェース実装**
|
||||
- UnifiedBoxInterfaceトレイトの実装
|
||||
- 既存FFIプラグイン1つを移行(MathBox推奨)
|
||||
- ScriptPluginラッパーの基本実装
|
||||
|
||||
2. **export box構文の実装**
|
||||
```nyash
|
||||
export box MyPlugin {
|
||||
init { _version = "1.0.0" }
|
||||
|
||||
// 必須:プラグインメタデータ
|
||||
get_metadata() {
|
||||
return {
|
||||
name: "MyPlugin",
|
||||
version: me._version,
|
||||
methods: ["process", "transform"]
|
||||
}
|
||||
}
|
||||
|
||||
// ビジネスロジック
|
||||
process(data) { ... }
|
||||
transform(input) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
3. **基本的なレジストリ**
|
||||
- 静的登録のみ
|
||||
- 依存関係解決なし
|
||||
|
||||
### Phase 2: 動的機能(3-4週間)
|
||||
|
||||
1. **動的ロード/アンロード**
|
||||
```nyash
|
||||
local registry = new PluginRegistry()
|
||||
local id = registry.load_script("path/to/plugin.ny")
|
||||
registry.unload(id)
|
||||
```
|
||||
|
||||
2. **ホットリロード**
|
||||
```nyash
|
||||
registry.enable_hot_reload("path/to/plugin.ny")
|
||||
// ファイル変更時に自動リロード
|
||||
```
|
||||
|
||||
3. **依存関係管理**
|
||||
- 循環依存検出
|
||||
- バージョン互換性チェック
|
||||
|
||||
### Phase 3: 最適化とセキュリティ(4-6週間)
|
||||
|
||||
1. **パフォーマンス最適化**
|
||||
- メソッドキャッシング
|
||||
- JITコンパイル統合
|
||||
- プリコンパイルオプション
|
||||
|
||||
2. **セキュリティサンドボックス**
|
||||
```rust
|
||||
pub struct Sandbox {
|
||||
memory_limit: usize,
|
||||
cpu_quota: Duration,
|
||||
allowed_capabilities: HashSet<Capability>,
|
||||
}
|
||||
```
|
||||
|
||||
3. **ケイパビリティベースセキュリティ**
|
||||
- ファイルアクセス制限
|
||||
- ネットワーク制限
|
||||
- システムコール制限
|
||||
|
||||
## パフォーマンス考察
|
||||
|
||||
### ベンチマーク予測
|
||||
|
||||
```
|
||||
操作 | ネイティブ | スクリプト | 比率
|
||||
--------------------|-----------|-----------|-----
|
||||
単純メソッド呼び出し | 10ns | 100ns | 10x
|
||||
複雑な計算(1000ops) | 1μs | 5μs | 5x
|
||||
I/O操作 | 100μs | 102μs | 1.02x
|
||||
```
|
||||
|
||||
### 最適化戦略
|
||||
|
||||
1. **ホットパスの識別**
|
||||
- 頻繁に呼ばれるメソッドを自動検出
|
||||
- JITコンパイル優先度付け
|
||||
|
||||
2. **ハイブリッドアプローチ**
|
||||
- コア機能:ネイティブ実装
|
||||
- カスタマイズ層:スクリプト実装
|
||||
|
||||
## エコシステムへの影響
|
||||
|
||||
### 開発者体験の革新
|
||||
|
||||
1. **即座のフィードバックループ**
|
||||
```bash
|
||||
# 編集
|
||||
vim my_plugin.ny
|
||||
|
||||
# 即座にテスト(ビルド不要)
|
||||
nyash test_plugin.ny
|
||||
```
|
||||
|
||||
2. **プラグインマーケットプレイス**
|
||||
- GitHubから直接インストール
|
||||
- バージョン管理統合
|
||||
- 自動更新機能
|
||||
|
||||
### コミュニティ成長予測
|
||||
|
||||
- **現在**: 10-20人のコアコントリビューター(Rust必須)
|
||||
- **1年後**: 100-500人のプラグイン開発者(Nyashのみ)
|
||||
- **3年後**: 1000+のプラグインエコシステム
|
||||
|
||||
## リスクと緩和策
|
||||
|
||||
### 技術的リスク
|
||||
|
||||
1. **パフォーマンス劣化**
|
||||
- 緩和策:重要部分のネイティブ実装維持
|
||||
- プロファイリングツール提供
|
||||
|
||||
2. **セキュリティ脆弱性**
|
||||
- 緩和策:デフォルトサンドボックス
|
||||
- 署名付きプラグイン
|
||||
|
||||
### エコシステムリスク
|
||||
|
||||
1. **品質のばらつき**
|
||||
- 緩和策:公式プラグインガイドライン
|
||||
- 自動品質チェックツール
|
||||
|
||||
2. **互換性問題**
|
||||
- 緩和策:セマンティックバージョニング強制
|
||||
- 自動互換性テスト
|
||||
|
||||
## 結論と推奨事項
|
||||
|
||||
### 即時実行すべきアクション
|
||||
|
||||
1. **Box ABI仕様書の作成**(1週間)
|
||||
2. **export box構文の実装**(2週間)
|
||||
3. **MathBoxの統一インターフェース移行**(1週間)
|
||||
|
||||
### 長期ビジョン
|
||||
|
||||
Nyashスクリプトプラグインシステムは、単なる機能追加ではなく、Nyashを**プログラミング言語**から**拡張可能なプラットフォーム**へと進化させる革命的な一歩です。
|
||||
|
||||
「Everything is Box」の哲学が、実装言語の壁を超えて真に実現される時、Nyashは次世代のプログラミングエコシステムのモデルケースとなるでしょう。
|
||||
|
||||
## 付録:実装例
|
||||
|
||||
### A. 完全なスクリプトプラグイン例
|
||||
|
||||
```nyash
|
||||
# advanced_math_plugin.ny
|
||||
export box AdvancedMathPlugin {
|
||||
init {
|
||||
_math = new MathBox()
|
||||
_cache = new MapBox()
|
||||
_stats = new MapBox()
|
||||
}
|
||||
|
||||
// プラグインメタデータ(必須)
|
||||
get_metadata() {
|
||||
return {
|
||||
name: "AdvancedMathPlugin",
|
||||
version: "1.0.0",
|
||||
methods: ["cached_sin", "cached_cos", "fibonacci", "factorial"],
|
||||
capabilities: ["compute"],
|
||||
dependencies: [{
|
||||
name: "MathBox",
|
||||
version: ">=1.0.0"
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
// キャッシュ付き三角関数
|
||||
cached_sin(x) {
|
||||
local key = "sin:" + x.toString()
|
||||
if me._cache.has(key) {
|
||||
me._update_stats("cache_hit")
|
||||
return me._cache.get(key)
|
||||
}
|
||||
|
||||
local result = me._math.sin(x)
|
||||
me._cache.set(key, result)
|
||||
me._update_stats("cache_miss")
|
||||
return result
|
||||
}
|
||||
|
||||
// 再帰的フィボナッチ(メモ化)
|
||||
fibonacci(n) {
|
||||
if n <= 1 { return n }
|
||||
|
||||
local key = "fib:" + n.toString()
|
||||
if me._cache.has(key) {
|
||||
return me._cache.get(key)
|
||||
}
|
||||
|
||||
local result = me.fibonacci(n-1) + me.fibonacci(n-2)
|
||||
me._cache.set(key, result)
|
||||
return result
|
||||
}
|
||||
|
||||
// 統計情報
|
||||
get_stats() {
|
||||
return me._stats
|
||||
}
|
||||
|
||||
// プライベートメソッド
|
||||
_update_stats(event) {
|
||||
local count = me._stats.get(event) or 0
|
||||
me._stats.set(event, count + 1)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### B. ネイティブとスクリプトの透過的利用
|
||||
|
||||
```nyash
|
||||
// 使用側のコード(プラグインの実装言語を意識しない)
|
||||
local math1 = new MathBox() // ネイティブプラグイン
|
||||
local math2 = include("advanced_math_plugin.ny") // スクリプトプラグイン
|
||||
|
||||
// 同じインターフェースで利用
|
||||
print(math1.sin(3.14)) // ネイティブ実装
|
||||
print(math2.cached_sin(3.14)) // スクリプト実装
|
||||
|
||||
// 動的に切り替え可能
|
||||
local math = get_config("use_cached") ? math2 : math1
|
||||
print(math.sin(1.57))
|
||||
```
|
||||
|
||||
---
|
||||
*"Write plugins in Nyash, for Nyash, by Nyash!"*
|
||||
@ -0,0 +1,90 @@
|
||||
# Gemini先生の分析:Nyashスクリプトプラグインシステム
|
||||
|
||||
## 技術的妥当性評価
|
||||
|
||||
### 結論:極めて実現可能性は高く、技術的にも非常に妥当
|
||||
|
||||
このアプローチは、多くのモダンな言語やエンジン(Lua, JavaScript/Node.js, Pythonなど)で採用されている「ネイティブコアとスクリプト拡張」という実績あるモデルを踏襲しています。
|
||||
|
||||
### 「Everything is Box」哲学との整合性
|
||||
|
||||
このアプローチは、Boxを「外部から観測可能なインターフェースを持つオブジェクト」と定義するならば、その実装がネイティブ(Rust/C++)であろうとスクリプト(Nyash)であろうと区別しない、という哲学の究極的な現れです。
|
||||
|
||||
## 統一インターフェース設計
|
||||
|
||||
### BoxInterface Traitの提案
|
||||
|
||||
```rust
|
||||
// Rust側に、すべてのプラグインが実装すべきtraitを定義
|
||||
trait BoxInterface {
|
||||
fn invoke(&self, method_id: u32, args: NyashValue) -> NyashValue;
|
||||
// その他、初期化やメタデータ取得などの共通メソッド
|
||||
}
|
||||
```
|
||||
|
||||
### アーキテクチャ
|
||||
|
||||
```
|
||||
[Nyashコード] -> [BoxInterface Trait] --+--> [FFIラッパー] -> [ネイティブコード]
|
||||
|
|
||||
+--> [Nyashスクリプトラッパー] -> [Nyash VM実行]
|
||||
```
|
||||
|
||||
これにより、Nyashのコードからプラグインを利用する側は、相手がネイティブかスクリプトかを一切意識する必要がなくなります。
|
||||
|
||||
## エコシステムへの影響
|
||||
|
||||
### 開発の民主化
|
||||
|
||||
- **参入障壁の劇的な低下**: Rust/C++の環境構築やビルドプロセスが不要
|
||||
- **迅速なプロトタイピング**: アイデアをすぐにNyashスクリプトで形にし、テスト可能
|
||||
|
||||
### 新しいプラグインの形態
|
||||
|
||||
- **プラグインの合成**: 複数の既存プラグインを組み合わせて新しい機能を持つ「メタプラグイン」
|
||||
- **アプリケーションの「設定」としてのプラグイン**: ユーザーが自身のアプリケーションの動作をカスタマイズ
|
||||
|
||||
### 動的性の向上
|
||||
|
||||
アプリケーションの実行中に、Nyashスクリプトプラグインをリロードしたり、新しいものを追加したりすることが容易になります。
|
||||
|
||||
## 実装ロードマップ
|
||||
|
||||
### フェーズ1:コアランタイムの実現(MVP)
|
||||
1. `BoxInterface` Traitの設計と実装(Rust側)
|
||||
2. 既存FFIの`BoxInterface`への対応
|
||||
3. Nyashオブジェクトの`BoxInterface`対応
|
||||
4. `import` / `export` の実装
|
||||
|
||||
### フェーズ2:動的機能と管理
|
||||
1. プラグインレジストリの実装
|
||||
2. 動的ロード/アンロードAPIの提供
|
||||
3. ID管理の洗練
|
||||
|
||||
### フェーズ3:セキュリティと堅牢性
|
||||
1. サンドボックスの導入
|
||||
2. パフォーマンス分析ツールの提供
|
||||
|
||||
### フェーズ4:開発者体験(DX)の向上
|
||||
1. ドキュメントの整備
|
||||
2. LSP/静的解析の対応
|
||||
|
||||
## 他言語からの学び
|
||||
|
||||
### Lua
|
||||
- C APIが非常にクリーンで、Cの関数をLuaから、Luaの関数をCから呼び出すのが容易
|
||||
- **学ぶべき点**: ネイティブとスクリプト間の境界(API)をいかにシンプルで強力に保つか
|
||||
|
||||
### Node.js (JavaScript)
|
||||
- `require()`システムが、C++で書かれたネイティブアドオンも、JavaScriptで書かれたモジュールも、全く同じように読み込む
|
||||
- **学ぶべき点**: 統一されたモジュール解決システムとインターフェースの重要性
|
||||
|
||||
### Python
|
||||
- Cで書かれた拡張モジュールと、Pure Pythonで書かれたモジュールが共存
|
||||
- **学ぶべき点**: パフォーマンスが重要な部分はCで、それ以外は柔軟なPythonで書くという、実用的な使い分け
|
||||
|
||||
## 総括
|
||||
|
||||
この発見はNyashの方向性を決定づける重要なマイルストーンです。パフォーマンスが最重要視されるコアな機能はRust/C++のFFIプラグインで、それ以外の大部分の機能、ビジネスロジック、UI、ユーザーカスタマイズなどはNyashスクリプトプラグインで開発する、という美しい棲み分けが実現します。
|
||||
|
||||
これはNyashを単なるプログラミング言語から、**拡張可能なプラットフォーム**へと昇華させる可能性を秘めています。
|
||||
@ -0,0 +1,172 @@
|
||||
# Nyashスクリプトプラグイン革命:統合分析まとめ
|
||||
|
||||
## 🚀 革命的発見の本質
|
||||
|
||||
Nyashスクリプト自体でプラグインを作成できるという発見は、単なる機能追加ではなく、**Nyashの本質的な進化**を意味します。
|
||||
|
||||
### Everything is Boxの究極形
|
||||
|
||||
```
|
||||
従来: Box = Rust/C++実装のオブジェクト
|
||||
革命: Box = 実装言語を問わないインターフェース
|
||||
```
|
||||
|
||||
この発見により、「Everything is Box」哲学が実装レイヤーの制約から解放され、真の意味で実現されます。
|
||||
|
||||
## 🎯 両先生の分析の統合
|
||||
|
||||
### 共通の評価ポイント
|
||||
|
||||
1. **技術的妥当性**: 極めて高い実現可能性
|
||||
2. **エコシステムへの影響**: 開発者数の爆発的増加が期待
|
||||
3. **実装アプローチ**: 統一インターフェースによる透過的利用
|
||||
|
||||
### 相補的な視点
|
||||
|
||||
| 観点 | Gemini先生 | Codex先生 |
|
||||
|------|-----------|-----------|
|
||||
| 焦点 | 哲学的整合性・他言語事例 | 具体的実装・パフォーマンス |
|
||||
| 強み | エコシステム影響分析 | 技術アーキテクチャ設計 |
|
||||
| 提案 | 段階的ロードマップ | 詳細な実装戦略 |
|
||||
|
||||
## 📊 統合実装計画
|
||||
|
||||
### 即時着手(1-2週間)
|
||||
|
||||
1. **Box ABI仕様策定**
|
||||
- Gemini案のBoxInterfaceトレイト
|
||||
- Codex案のUnifiedBoxInterface
|
||||
- 両案を統合した最終仕様
|
||||
|
||||
2. **export box構文実装**
|
||||
```nyash
|
||||
export box PluginName {
|
||||
// 必須:メタデータ提供
|
||||
get_metadata() { ... }
|
||||
|
||||
// ビジネスロジック
|
||||
method1() { ... }
|
||||
method2() { ... }
|
||||
}
|
||||
```
|
||||
|
||||
3. **プロトタイプ実装**
|
||||
- MathBoxを統一インターフェースに移行
|
||||
- 簡単なNyashスクリプトプラグイン作成
|
||||
|
||||
### 中期目標(1-2ヶ月)
|
||||
|
||||
1. **動的プラグインシステム**
|
||||
- ホットリロード機能
|
||||
- 依存関係管理
|
||||
- バージョン互換性
|
||||
|
||||
2. **開発ツール整備**
|
||||
- プラグインテンプレート
|
||||
- デバッグツール
|
||||
- パフォーマンスプロファイラ
|
||||
|
||||
3. **セキュリティ基盤**
|
||||
- サンドボックス実装
|
||||
- ケイパビリティベース権限
|
||||
|
||||
### 長期ビジョン(6ヶ月-1年)
|
||||
|
||||
1. **プラグインエコシステム**
|
||||
- マーケットプレイス構築
|
||||
- 自動品質チェック
|
||||
- コミュニティガイドライン
|
||||
|
||||
2. **高度な最適化**
|
||||
- JIT統合
|
||||
- プリコンパイル機能
|
||||
- ネイティブ/スクリプトハイブリッド
|
||||
|
||||
## 🔑 成功の鍵
|
||||
|
||||
### 技術的成功要因
|
||||
|
||||
1. **シンプルな統一インターフェース**
|
||||
- 学習コストを最小化
|
||||
- 既存プラグインの移行を容易に
|
||||
|
||||
2. **段階的移行パス**
|
||||
- 既存のFFIプラグインと共存
|
||||
- 破壊的変更を避ける
|
||||
|
||||
3. **パフォーマンス配慮**
|
||||
- ホットパスはネイティブ維持
|
||||
- I/O boundタスクから適用
|
||||
|
||||
### エコシステム成功要因
|
||||
|
||||
1. **開発体験の劇的改善**
|
||||
- ビルド不要
|
||||
- 即座のフィードバック
|
||||
- 豊富なサンプル
|
||||
|
||||
2. **コミュニティ形成**
|
||||
- 初心者に優しいドキュメント
|
||||
- アクティブなサポート
|
||||
- 貢献への明確なパス
|
||||
|
||||
## 🎊 期待される成果
|
||||
|
||||
### 短期(3-6ヶ月)
|
||||
- プラグイン開発者: 10→100人
|
||||
- プラグイン数: 20→200個
|
||||
- 開発速度: 10倍向上
|
||||
|
||||
### 中期(1年)
|
||||
- 主要機能の8割がプラグイン化
|
||||
- サードパーティエコシステム確立
|
||||
- 企業採用事例の出現
|
||||
|
||||
### 長期(3年)
|
||||
- デファクトスタンダード化
|
||||
- 1000+のプラグイン
|
||||
- 自立的エコシステム
|
||||
|
||||
## 🏁 結論
|
||||
|
||||
Nyashスクリプトプラグインシステムは、**技術的に実現可能**であり、**戦略的に必須**の進化です。
|
||||
|
||||
「Everything is Box」哲学の真の実現により、Nyashは単なるプログラミング言語から、**次世代の拡張可能プラットフォーム**へと進化します。
|
||||
|
||||
### 合言葉
|
||||
|
||||
> **"Write plugins in Nyash, for Nyash, by Nyash!"**
|
||||
|
||||
この革命により、Nyashコミュニティは爆発的な成長を遂げ、真に民主的なプログラミングエコシステムが誕生するでしょう。
|
||||
|
||||
---
|
||||
|
||||
## 📎 付録:クイックスタートガイド
|
||||
|
||||
### 最初のスクリプトプラグイン(5分で作成)
|
||||
|
||||
```nyash
|
||||
# my_first_plugin.ny
|
||||
export box MyFirstPlugin {
|
||||
init {
|
||||
_name = "My First Plugin"
|
||||
_count = 0
|
||||
}
|
||||
|
||||
greet(name) {
|
||||
me._count = me._count + 1
|
||||
return "Hello, " + name + "! (call #" + me._count.toString() + ")"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 使用例
|
||||
|
||||
```nyash
|
||||
# main.ny
|
||||
local plugin = include("my_first_plugin.ny")
|
||||
print(plugin.greet("World")) // "Hello, World! (call #1)"
|
||||
print(plugin.greet("Nyash")) // "Hello, Nyash! (call #2)"
|
||||
```
|
||||
|
||||
**ビルド不要、即実行!** これがNyashスクリプトプラグインの力です。
|
||||
Reference in New Issue
Block a user