Factor JSON v0 bridge globals/throw into small helpers
This commit is contained in:
@ -7,3 +7,26 @@
|
||||
3. break / continue / exit の snapshot を `LoopSnapshotMergeBox` に渡して canonical continue_merge/backedge を構築する。
|
||||
|
||||
LoopForm/PHI の意味論を変更したい場合は、`loopform_builder.rs` / `loop_snapshot_merge.rs` を更新すること。`loop_.rs` 内での ad-hoc な PHI 実装は禁止。
|
||||
|
||||
### Rust パーサー経路との関係
|
||||
|
||||
- 共通 SSOT:
|
||||
- 制御フロー: `src/mir/ssot/cf_common.rs`(branch/jump/compare/phi 挿入)
|
||||
- 算術・比較: `src/mir/ssot/binop_lower.rs`(二項演算 lowering)
|
||||
- ループ形: `src/mir/ssot/loop_common.rs` + `LoopFormBuilder`
|
||||
- フロントエンド(入口):
|
||||
- Rust パーサー経路: `parser/*` + `mir/builder/*` が AST から MIR を構築する。
|
||||
- JSON v0 経路: このディレクトリの lowering 群が `ProgramV0` から MIR を構築する。
|
||||
- どちらも「PHI/LoopForm/CF の意味論」は mir/ssot 側に委譲し、入口側では構造準備のみに留める。
|
||||
|
||||
### Bridge 固有ロジックの箱化方針
|
||||
|
||||
- JSON v0 → MIR の際に必要な「ブリッジ固有」の処理は、入口ファイルにベタ書きしない:
|
||||
- `hostbridge` / `env` / `me` ダミーなどの特別な変数解決
|
||||
- Stage‑1/Stage‑B の try-result モードに合わせた throw ルーティング
|
||||
- これらは `lowering/globals.rs` / `lowering/throw_ctx.rs` などの小さなモジュールに閉じ込め、
|
||||
- JSON v0 経路
|
||||
- 将来の Rust パーサー self‑host 経路
|
||||
から同じ箱を使い回せるようにする。
|
||||
|
||||
このディレクトリでは「JSON → MIR 変換」と「最低限のブリッジ設定」だけを行い、その先の最適化や意味論変更は `mir/*`(optimizer/pass, LoopForm, VM/LLVM)側に任せる。
|
||||
|
||||
@ -13,11 +13,13 @@ mod merge;
|
||||
use merge::{merge_var_maps, new_block};
|
||||
// Feature splits (gradual extraction)
|
||||
pub(super) mod expr;
|
||||
pub(super) mod globals;
|
||||
pub(super) mod if_else;
|
||||
pub(super) mod loop_;
|
||||
pub(super) mod match_expr; // placeholder (not wired)
|
||||
pub(super) mod ternary; // placeholder (not wired)
|
||||
pub(super) mod throw_ctx;
|
||||
pub(super) mod throw_lower;
|
||||
pub(super) mod try_catch; // thread-local ctx for Result-mode throw routing
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
use super::match_expr;
|
||||
use super::merge::new_block;
|
||||
use super::globals::resolve_bridge_global;
|
||||
use super::ternary;
|
||||
use super::BridgeEnv;
|
||||
use super::throw_lower::lower_throw;
|
||||
use crate::mir::{BasicBlockId, ConstValue, EffectMask, MirFunction, MirInstruction, ValueId};
|
||||
use crate::ast::Span;
|
||||
use std::collections::BTreeMap;
|
||||
@ -50,101 +52,15 @@ impl<'a> VarScope for MapVars<'a> {
|
||||
if let Some(&vid) = self.vars.get(name) {
|
||||
return Ok(Some(vid));
|
||||
}
|
||||
// Phase 21.8: Check using-imported modules/boxes
|
||||
if let Some(box_type) = env.imports.get(name) {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
// Treat as static box reference - create a const string representing the box type
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst,
|
||||
value: ConstValue::String(box_type.clone()),
|
||||
});
|
||||
}
|
||||
// Cache the resolution for subsequent uses
|
||||
self.vars.insert(name.to_string(), dst);
|
||||
return Ok(Some(dst));
|
||||
}
|
||||
// Phase 25.1a: Treat `hostbridge` as a well-known global for bridge lowering.
|
||||
// The actual extern dispatch is handled at runtime; here we only need a stable
|
||||
// placeholder value so that Program(JSON) containing hostbridge.extern_invoke(...)
|
||||
// can be lowered without "undefined variable" errors.
|
||||
if name == "hostbridge" {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst,
|
||||
value: ConstValue::String("hostbridge".into()),
|
||||
});
|
||||
}
|
||||
self.vars.insert(name.to_string(), dst);
|
||||
return Ok(Some(dst));
|
||||
}
|
||||
// Phase 25.1b: Treat `env` as a well-known global for env.box_introspect.* etc.
|
||||
// Similar to hostbridge, we need a placeholder value for the nested method pattern.
|
||||
if name == "env" {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst,
|
||||
value: ConstValue::String("env".into()),
|
||||
});
|
||||
}
|
||||
self.vars.insert(name.to_string(), dst);
|
||||
return Ok(Some(dst));
|
||||
}
|
||||
if name == "me" {
|
||||
if env.allow_me_dummy {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::NewBox {
|
||||
dst,
|
||||
box_type: env.me_class.clone(),
|
||||
args: vec![],
|
||||
});
|
||||
}
|
||||
self.vars.insert(name.to_string(), dst);
|
||||
Ok(Some(dst))
|
||||
} else {
|
||||
Err("undefined 'me' outside box context (set NYASH_BRIDGE_ME_DUMMY=1 to inject placeholder)".into())
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_throw(
|
||||
env: &BridgeEnv,
|
||||
f: &mut MirFunction,
|
||||
cur_bb: BasicBlockId,
|
||||
exception_value: ValueId,
|
||||
) -> (ValueId, BasicBlockId) {
|
||||
// Result-mode try context active: route to current catch via Jump and record incoming
|
||||
if env.try_result_mode && super::throw_ctx::is_active() {
|
||||
if crate::config::env::cli_verbose() {
|
||||
eprintln!("[Bridge] lower_throw: routing to catch (Result-mode)");
|
||||
// Bridge 固有のグローバル解決(imports/hostbridge/env/me dummy)は専用モジュールに委譲
|
||||
if let Some(vid) =
|
||||
resolve_bridge_global(name, env, f, cur_bb, self.vars)?
|
||||
{
|
||||
return Ok(Some(vid));
|
||||
}
|
||||
let _ = super::throw_ctx::record_throw(f, cur_bb, exception_value);
|
||||
return (exception_value, cur_bb);
|
||||
}
|
||||
// Legacy path: emit MIR Throw (if enabled) or degrade to const 0
|
||||
if env.throw_enabled {
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.set_terminator(MirInstruction::Throw {
|
||||
exception: exception_value,
|
||||
effects: EffectMask::PANIC,
|
||||
});
|
||||
}
|
||||
(exception_value, cur_bb)
|
||||
} else {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst,
|
||||
value: ConstValue::Integer(0),
|
||||
});
|
||||
}
|
||||
(dst, cur_bb)
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
77
src/runner/json_v0_bridge/lowering/globals.rs
Normal file
77
src/runner/json_v0_bridge/lowering/globals.rs
Normal file
@ -0,0 +1,77 @@
|
||||
use super::BridgeEnv;
|
||||
use crate::mir::{BasicBlockId, ConstValue, MirFunction, MirInstruction, ValueId};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
/// Resolve Bridge-specific globals (imports/hostbridge/env/me dummy).
|
||||
///
|
||||
/// - `vars`: current local/global value map (updated when a new value is synthesized)
|
||||
/// - returns Some(ValueId) when the name is handled here, or Ok(None) to let callers
|
||||
/// fallback to "undefined variable" handling.
|
||||
pub(super) fn resolve_bridge_global(
|
||||
name: &str,
|
||||
env: &BridgeEnv,
|
||||
f: &mut MirFunction,
|
||||
cur_bb: BasicBlockId,
|
||||
vars: &mut BTreeMap<String, ValueId>,
|
||||
) -> Result<Option<ValueId>, String> {
|
||||
// Phase 21.8: using-imported modules/boxes
|
||||
if let Some(box_type) = env.imports.get(name) {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst,
|
||||
value: ConstValue::String(box_type.clone()),
|
||||
});
|
||||
}
|
||||
vars.insert(name.to_string(), dst);
|
||||
return Ok(Some(dst));
|
||||
}
|
||||
|
||||
// Phase 25.1a: well-known bridge globals
|
||||
if name == "hostbridge" {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst,
|
||||
value: ConstValue::String("hostbridge".into()),
|
||||
});
|
||||
}
|
||||
vars.insert(name.to_string(), dst);
|
||||
return Ok(Some(dst));
|
||||
}
|
||||
|
||||
if name == "env" {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst,
|
||||
value: ConstValue::String("env".into()),
|
||||
});
|
||||
}
|
||||
vars.insert(name.to_string(), dst);
|
||||
return Ok(Some(dst));
|
||||
}
|
||||
|
||||
if name == "me" {
|
||||
if env.allow_me_dummy {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::NewBox {
|
||||
dst,
|
||||
box_type: env.me_class.clone(),
|
||||
args: vec![],
|
||||
});
|
||||
}
|
||||
vars.insert(name.to_string(), dst);
|
||||
Ok(Some(dst))
|
||||
} else {
|
||||
Err(
|
||||
"undefined 'me' outside box context (set NYASH_BRIDGE_ME_DUMMY=1 to inject placeholder)"
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
45
src/runner/json_v0_bridge/lowering/throw_lower.rs
Normal file
45
src/runner/json_v0_bridge/lowering/throw_lower.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use super::BridgeEnv;
|
||||
use crate::mir::{BasicBlockId, ConstValue, EffectMask, MirFunction, MirInstruction, ValueId};
|
||||
|
||||
/// Lower a throw expression/value according to BridgeEnv and throw_ctx.
|
||||
///
|
||||
/// - Result-mode try contextが有効なら、catch ブロックへ jump しつつ incoming に記録する。
|
||||
/// - それ以外では:
|
||||
/// - throw_enabled=1 のとき MIR Throw を発行
|
||||
/// - そうでなければ `const 0` にフォールバック
|
||||
pub(super) fn lower_throw(
|
||||
env: &BridgeEnv,
|
||||
f: &mut MirFunction,
|
||||
cur_bb: BasicBlockId,
|
||||
exception_value: ValueId,
|
||||
) -> (ValueId, BasicBlockId) {
|
||||
// Result-mode try context active: route to current catch via Jump and record incoming
|
||||
if env.try_result_mode && super::throw_ctx::is_active() {
|
||||
if crate::config::env::cli_verbose() {
|
||||
eprintln!("[Bridge] lower_throw: routing to catch (Result-mode)");
|
||||
}
|
||||
let _ = super::throw_ctx::record_throw(f, cur_bb, exception_value);
|
||||
return (exception_value, cur_bb);
|
||||
}
|
||||
|
||||
// Legacy path: emit MIR Throw (if enabled) or degrade to const 0
|
||||
if env.throw_enabled {
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.set_terminator(MirInstruction::Throw {
|
||||
exception: exception_value,
|
||||
effects: EffectMask::PANIC,
|
||||
});
|
||||
}
|
||||
(exception_value, cur_bb)
|
||||
} else {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst,
|
||||
value: ConstValue::Integer(0),
|
||||
});
|
||||
}
|
||||
(dst, cur_bb)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user