Files
hakorune/docs/phases/phase-12/archive/03_spec_box_arguments.md

3.9 KiB
Raw Blame History

埋め込みVMでの箱引数サポート

🎯 結論:完全にサポート可能

現在のMIR/VM/JIT/プラグインすべてで箱は箱を引数にできる仕組みが確立されており、埋め込みVMでも同じパターンで実装可能です。

📊 各層での箱引数の扱い

1. 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での実装

バイトコード表現

// 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)

実行時処理

// 埋め込み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. ハンドルレジストリ

// グローバルハンドルテーブル
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. プラグイン間の箱共有

// プラグイン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プラグインとして動作します