Files
hakorune/docs/private/roadmap/phases/phase-20-python-integration/design/enhanced-architecture-v2.md

11 KiB
Raw Blame History

Python-Hakorune統合 強化版アーキテクチャ v2

作成: 2025-10-02 ソース: ChatGPT Pro UltraThink Mode ステータス: 設計提案


📋 概要

Phase 10.5の「Active」設計を踏まえつつ、強化版HakoruneEffect/Capability/Contract/Policy・PHI検証・BlockVMap等の上に載せる、安全で境界に問題を閉じ込めたPythonブリッジの設計書です。


🎯 ねらいPhase 10.5の「Active」意図との整合

  • 最小コアで "箱Boxに閉じ込めたPython実行環境" を提供
  • VM/LLVM/AOTラインから同じ呼び出し規約で扱える
  • 当面はVMハーネスllvmlite側を使って決定実行とスモークの安定性を優先、AOT/EXEは段階導入

🏗️ 1. Box階層木構造の基本セット

PyRuntimeBoxルート・単一 or 少数)

役割:

  • PythonランタイムCPython埋め込み
  • import 解決
  • GIL管理
  • モジュールキャッシュ

ライフサイクル:

  • init: インタプリタ起動
  • fini: 停止
  • Capabilityで"import可能モジュールFS/NET/ENV"を限定

実装指針:

  • まずは既存 Plugin-FirstC ABI・TLVでブリッジ
  • 後段で Hakorune ABIvtable に段階移行
  • HAKO_ABI_VTABLE 等のgateを活用
box PyRuntimeBox {
    // 初期化・終了
    init()
    fini()

    // モジュール
    import(name: StringBox) -> PyModuleBox
    reflect(module_name: StringBox) -> PyModuleBox

    // 実行
    eval(code: StringBox) -> PyObjectBox
    exec(code: StringBox)
}

PyModuleBox

役割:

  • import "pkg.mod" の結果をBoxとして公開
  • 属性 = フィールド
  • 関数 = MethodBox

ライフサイクル:

  • PyRuntimeBox が所有
  • fini で参照解除refcnt を減らす)
box PyModuleBox {
    // 属性アクセス
    get(name: StringBox) -> PyObjectBox
    set(name: StringBox, value: PyObjectBox)

    // 列挙
    list_attributes() -> ArrayBox
}

PyTypeBox / PyInstanceBox

役割:

  • Pythonのクラス定義とインスタンスをBox化
  • get/setFieldcall_method を統一導線に

所有権タグ:

  • sharedCPython RC前提
  • unique が必要な場合は"借用トークン"で一時的に排他操作を許可
box PyTypeBox {
    // クラス情報
    get_name() -> StringBox
    get_bases() -> ArrayBox
    get_methods() -> ArrayBox

    // インスタンス化
    new_instance(args: ArrayBox) -> PyInstanceBox
}

box PyInstanceBox {
    // フィールドアクセス
    get_field(name: StringBox) -> PyObjectBox
    set_field(name: StringBox, value: PyObjectBox)

    // メソッド呼び出し
    call_method(name: StringBox, args: ArrayBox) -> PyObjectBox
}

PyFunctionBox / PyCallableBox

役割:

  • 呼出しを exec(args)->resultPulse的に落として最小ライフサイクルで扱える
box PyFunctionBox {
    // Pulse: 完全な一発実行
    exec(args: ArrayBox) -> PyObjectBox

    // メタ情報
    get_name() -> StringBox
    get_signature() -> StringBox
}

PyIteratorBox / PyGeneratorBox必要に応じて

役割:

  • __iter__/__next__ をBox化
  • flow実行と相性を取る
box PyIteratorBox {
    next() -> PyObjectBox
    has_next() -> BoolBox
}

box PyGeneratorBox {
    send(value: PyObjectBox) -> PyObjectBox
    throw(error: ErrorBox)
}

Phase 10.5の設計メモと整合"最小の箱から着手 → 後から拡張"


🔄 2. ライフサイクル対応Hakorune流

init/fini

PyRuntimeBox.init():

fn init() {
    Py_Initialize();
    // import policyのロード
    // キャッシュ構築
}

PyRuntimeBox.fini():

fn fini() {
    // weakref.finalize併用で安全解放循環対策
    Py_Finalize();
}

Pulse

PyFunctionBox.exec は完全Pulseinit/fini不要:

  • 作用範囲はmetaのCapabilityに閉じ込め
  • 副作用は明示的にEffect宣言

所有権タグ

  • 既定: sharedRC準拠
  • unique が必要な経路: BorrowMutToken を発行して単発処理中のみ排他

これらは 管理棟のトグルとも親和性が高いdev: 緩める / prod: 厳格)


🎭 3. Effect / Capability / Contract の外付けmeta

Effect論理的効果名

[box.PyRuntimeBox.effects]
available = [
    "py.import",
    "py.fs",
    "py.net",
    "py.env",
    "py.time",
    "py.random",
    "py.subprocess"
]

Capability許可リスト

[box.PyRuntimeBox.capabilities]
allow = [
    "py.import:math",
    "py.import:json",
    "py.time:monotonic"
]
deny = [
    "py.subprocess",
    "py.net"
]
enforce = true  # devではfalse→観測のみ

Contract

Pre条件:

[contracts.PyFunctionBox.exec]
pre = [
    "args.len <= 8",
    "bytes_total <= 1_000_000"
]

Post条件:

[contracts.PyFunctionBox.exec]
post = [
    "result.size <= 1_000_000",
    "no_exception",
    "allow_none = true"
]

監査トグル

# Dev/CI
HAKO_PLUGIN_CAPS_ENFORCE=1
HAKO_CHECK_CONTRACTS=1

# Prod
HAKO_PLUGIN_CAPS_ENFORCE=1
HAKO_CHECK_CONTRACTS=0  # 警告のみ

🔁 4. Deterministic / Repro の扱い

Deterministic モード

問題:

  • random, time, os.urandom 等は非決定的

解決策:

  • Capability トークン経由で提供するshimsを使用

実装例:

# py.random shim
class DeterministicRandom:
    def __init__(self, seed):
        self._rng = random.Random(seed)

    def random(self):
        return self._rng.random()

# py.time shim
class LogicalClock:
    def __init__(self):
        self._tick = 0

    def monotonic(self):
        self._tick += 1
        return float(self._tick)

トグル:

# Deterministic モード有効化
HAKO_DETERMINISTIC=1
HAKO_TRACE_EFFECTS=1  # 効果ログ収集

メリット:

  • flow Main.main 実行のスナップショット再現が可能
  • デバッグ容易性向上
  • テストの再現性保証

🌳 5. 木構造への「落とし方」(反射 → Box化

ビルダー(反射)

PyRuntimeBox.reflect(module_name: String) -> PyModuleBox:

  1. dir(module)inspect属性ツリーを走査
  2. Boxを生成
  3. 規約:
    • 公開対象は __all__ 優先
    • ない場合は _ 先頭を除外
    • @hako_export デコレータがあれば優先で FunctionBox

実装擬似コード:

# Python側リフレクションヘルパー
def reflect_module(module_name):
    mod = importlib.import_module(module_name)

    # 属性リスト取得
    if hasattr(mod, '__all__'):
        attrs = mod.__all__
    else:
        attrs = [a for a in dir(mod) if not a.startswith('_')]

    # Box化
    boxes = {}
    for attr_name in attrs:
        attr = getattr(mod, attr_name)

        if callable(attr):
            boxes[attr_name] = create_function_box(attr)
        elif inspect.isclass(attr):
            boxes[attr_name] = create_type_box(attr)
        else:
            boxes[attr_name] = create_object_box(attr)

    return boxes

使用例

using "python"

box Main {
    flow main() {
        // init: CPython起動
        let py = PyRuntimeBox();

        // PyModuleBox
        let m = py.reflect("math");

        // PyFunctionBox
        let sqrt = m.get("sqrt");

        // 実行
        let r = sqrt.exec([2.0]);
        print(r);  // -> 1.4142...

        // 正常停止
        py.fini();
    }
}

反射で"木"を作り、Box統一APIget/set/callで走る — Phase 10.5の「Activeは最小の箱から導入」を踏襲


⚠️ 6. 例外とエラー境界

Python例外 → ErrorBox

box ErrorBox {
    type: StringBox       // "ZeroDivisionError"
    message: StringBox    // "division by zero"
    traceback: StringBox  // フルトレースバック
}

変換例:

# Python側
try:
    result = some_function()
except Exception as e:
    return ErrorBox(
        type=type(e).__name__,
        message=str(e),
        traceback=traceback.format_exc()
    )

Contract違反

Strict モード:

HAKO_EXTERN_STRICT=1  # fail-fast

通常モード:

HAKO_EXTERN_STRICT=0  # 警告 + ErrorBox返却

🎛️ 7. 実行ポリシーとトグル(管理棟)

ハーネス

# 既定でPythonハーネス使用
HAKO_LLVM_USE_HARNESS=1  # デフォルトON

PHIオプション

ブリッジ互換PHI-off:

HAKO_VERIFY_ALLOW_NO_PHI=1  # 互換用途のみ

統一PHI-on:

HAKO_VERIFY_ALLOW_NO_PHI=0  # 推奨
# Verifierを**PHI直後に常時実行**

モード設定:

  • Dev: fail-fast
  • Prod: 警告

ABI

初期C ABI - TLV:

HAKO_ABI_VTABLE=0  # C ABI使用

段階移行Hakorune ABI - vtable:

HAKO_ABI_VTABLE=1
HAKO_ABI_STRICT=1  # フォールバック禁止

Plugin観測

# CI/Dev
HAKO_TRACE_EFFECTS=1
HAKO_PLUGIN_META=1
HAKO_PLUGIN_CAPS_ENFORCE=1

🚀 強化版Hakoruneでの設計図アップデート

1. 境界検証を"必須フェーズ"に

実装:

  • finalize_phis() の直後で SSA/支配関係/到達性を検証
  • Dev: 例外
  • Prod: 警告+トレース保全

効果:

  • Pythonブリッジ有無に関わらず毎回回る
  • IR品質を境界に閉じ込める

2. BlockVMap型でvmap/_current_vmapを統合

実装:

  • 参照は必ず BlockVMap::at(block) 経由
  • 呼び出し側からどの視点が"真"かを隠蔽

効果:

  • Python連携でもブロック境界で値がぶれない
  • 事故防止

3. InstructionContextを必須引数化

実装:

  • すべての lower_* に統一コンテキストを渡す
  • ログ/例外に命令位置・BB名を強制添付

効果:

  • 原因追跡が一気に楽に

4. flow Main.main を"仕様"として固定

実装:

  • Phase 10.5のActive方針と揃えて flow優先
  • staticを覚える必要なし

効果:

  • 入口の一意化
  • セルフホストの再現ビルド検証にも効く

5. 開発→本番の昇格パスを明確化

Dev:

HAKO_*_ENFORCE=0
HAKO_TRACE=1
# fail-fast ON

Prod:

HAKO_*_ENFORCE=1
HAKO_TRACE=0
# fail-fast OFFErrorBox警告

効果:

  • 管理棟envにすでに集約されている設計
  • 運用で迷わない

🔗 関連ドキュメント


最終更新: 2025-10-02 作成者: ChatGPT Pro (UltraThink Mode) レビュー: 未実施 ステータス: 設計提案・Phase 15完了後に実装予定