2025-11-21 06:25:17 +09:00
|
|
|
|
use super::match_expr;
|
2025-09-17 11:45:57 +09:00
|
|
|
|
use super::merge::new_block;
|
2025-11-24 15:21:49 +09:00
|
|
|
|
use super::globals::resolve_bridge_global;
|
2025-09-17 11:45:57 +09:00
|
|
|
|
use super::ternary;
|
2025-11-21 06:25:17 +09:00
|
|
|
|
use super::BridgeEnv;
|
2025-11-24 15:21:49 +09:00
|
|
|
|
use super::throw_lower::lower_throw;
|
2025-11-21 06:25:17 +09:00
|
|
|
|
use crate::mir::{BasicBlockId, ConstValue, EffectMask, MirFunction, MirInstruction, ValueId};
|
2025-11-24 15:02:51 +09:00
|
|
|
|
use crate::ast::Span;
|
2025-11-22 05:33:40 +09:00
|
|
|
|
use std::collections::BTreeMap;
|
2025-09-17 11:45:57 +09:00
|
|
|
|
|
|
|
|
|
|
use super::super::ast::ExprV0;
|
|
|
|
|
|
|
|
|
|
|
|
pub(super) trait VarScope {
|
|
|
|
|
|
fn resolve(
|
|
|
|
|
|
&mut self,
|
|
|
|
|
|
env: &BridgeEnv,
|
|
|
|
|
|
f: &mut MirFunction,
|
|
|
|
|
|
cur_bb: BasicBlockId,
|
|
|
|
|
|
name: &str,
|
|
|
|
|
|
) -> Result<Option<ValueId>, String>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(super) struct NoVars;
|
|
|
|
|
|
impl VarScope for NoVars {
|
|
|
|
|
|
fn resolve(
|
|
|
|
|
|
&mut self,
|
|
|
|
|
|
_env: &BridgeEnv,
|
|
|
|
|
|
_f: &mut MirFunction,
|
|
|
|
|
|
_cur_bb: BasicBlockId,
|
|
|
|
|
|
name: &str,
|
|
|
|
|
|
) -> Result<Option<ValueId>, String> {
|
|
|
|
|
|
Err(format!("undefined variable in this context: {}", name))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(super) struct MapVars<'a> {
|
2025-11-22 05:33:40 +09:00
|
|
|
|
vars: &'a mut BTreeMap<String, ValueId>,
|
2025-09-17 11:45:57 +09:00
|
|
|
|
}
|
|
|
|
|
|
impl<'a> MapVars<'a> {
|
2025-11-22 05:33:40 +09:00
|
|
|
|
fn new(vars: &'a mut BTreeMap<String, ValueId>) -> Self {
|
2025-09-17 11:45:57 +09:00
|
|
|
|
Self { vars }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
impl<'a> VarScope for MapVars<'a> {
|
|
|
|
|
|
fn resolve(
|
|
|
|
|
|
&mut self,
|
|
|
|
|
|
env: &BridgeEnv,
|
|
|
|
|
|
f: &mut MirFunction,
|
|
|
|
|
|
cur_bb: BasicBlockId,
|
|
|
|
|
|
name: &str,
|
|
|
|
|
|
) -> Result<Option<ValueId>, String> {
|
|
|
|
|
|
if let Some(&vid) = self.vars.get(name) {
|
|
|
|
|
|
return Ok(Some(vid));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 15:21:49 +09:00
|
|
|
|
// Bridge 固有のグローバル解決(imports/hostbridge/env/me dummy)は専用モジュールに委譲
|
|
|
|
|
|
if let Some(vid) =
|
|
|
|
|
|
resolve_bridge_global(name, env, f, cur_bb, self.vars)?
|
|
|
|
|
|
{
|
|
|
|
|
|
return Ok(Some(vid));
|
2025-09-17 11:45:57 +09:00
|
|
|
|
}
|
2025-11-24 15:21:49 +09:00
|
|
|
|
|
|
|
|
|
|
Ok(None)
|
2025-09-17 11:45:57 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(super) fn lower_expr_with_scope<S: VarScope>(
|
|
|
|
|
|
env: &BridgeEnv,
|
|
|
|
|
|
f: &mut MirFunction,
|
|
|
|
|
|
cur_bb: BasicBlockId,
|
|
|
|
|
|
e: &ExprV0,
|
|
|
|
|
|
vars: &mut S,
|
|
|
|
|
|
) -> Result<(ValueId, BasicBlockId), String> {
|
|
|
|
|
|
match e {
|
|
|
|
|
|
ExprV0::Int { value } => {
|
|
|
|
|
|
let ival: i64 = if let Some(n) = value.as_i64() {
|
|
|
|
|
|
n
|
|
|
|
|
|
} else if let Some(s) = value.as_str() {
|
|
|
|
|
|
s.parse().map_err(|_| "invalid int literal")?
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return Err("invalid int literal".into());
|
|
|
|
|
|
};
|
|
|
|
|
|
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(ival),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok((dst, cur_bb))
|
|
|
|
|
|
}
|
|
|
|
|
|
ExprV0::Str { value } => {
|
|
|
|
|
|
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(value.clone()),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok((dst, cur_bb))
|
|
|
|
|
|
}
|
|
|
|
|
|
ExprV0::Bool { value } => {
|
|
|
|
|
|
let dst = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur_bb) {
|
|
|
|
|
|
bb.add_instruction(MirInstruction::Const {
|
|
|
|
|
|
dst,
|
|
|
|
|
|
value: ConstValue::Bool(*value),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok((dst, cur_bb))
|
|
|
|
|
|
}
|
2025-11-15 22:32:13 +09:00
|
|
|
|
ExprV0::Null => {
|
|
|
|
|
|
let dst = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur_bb) {
|
|
|
|
|
|
bb.add_instruction(MirInstruction::Const {
|
|
|
|
|
|
dst,
|
|
|
|
|
|
value: ConstValue::Null,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok((dst, cur_bb))
|
|
|
|
|
|
}
|
2025-09-17 11:45:57 +09:00
|
|
|
|
ExprV0::Binary { op, lhs, rhs } => {
|
|
|
|
|
|
let (l, cur_after_l) = lower_expr_with_scope(env, f, cur_bb, lhs, vars)?;
|
|
|
|
|
|
let (r, cur_after_r) = lower_expr_with_scope(env, f, cur_after_l, rhs, vars)?;
|
2025-11-04 20:46:43 +09:00
|
|
|
|
let bop = match crate::mir::ssot::binop_lower::parse_binop_str(op) {
|
|
|
|
|
|
Some(b) => b,
|
|
|
|
|
|
None => return Err("unsupported op".into()),
|
2025-09-17 11:45:57 +09:00
|
|
|
|
};
|
2025-11-04 20:46:43 +09:00
|
|
|
|
let dst = crate::mir::ssot::binop_lower::emit_binop_func(f, cur_after_r, bop, l, r);
|
2025-09-17 11:45:57 +09:00
|
|
|
|
Ok((dst, cur_after_r))
|
|
|
|
|
|
}
|
|
|
|
|
|
ExprV0::Extern {
|
|
|
|
|
|
iface,
|
|
|
|
|
|
method,
|
|
|
|
|
|
args,
|
|
|
|
|
|
} => {
|
|
|
|
|
|
let (arg_ids, cur2) = lower_args_with_scope(env, f, cur_bb, args, vars)?;
|
|
|
|
|
|
let dst = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur2) {
|
|
|
|
|
|
bb.add_instruction(MirInstruction::ExternCall {
|
|
|
|
|
|
dst: Some(dst),
|
|
|
|
|
|
iface_name: iface.clone(),
|
|
|
|
|
|
method_name: method.clone(),
|
|
|
|
|
|
args: arg_ids,
|
|
|
|
|
|
effects: EffectMask::IO,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok((dst, cur2))
|
|
|
|
|
|
}
|
|
|
|
|
|
ExprV0::Compare { op, lhs, rhs } => {
|
|
|
|
|
|
let (l, cur_after_l) = lower_expr_with_scope(env, f, cur_bb, lhs, vars)?;
|
|
|
|
|
|
let (r, cur_after_r) = lower_expr_with_scope(env, f, cur_after_l, rhs, vars)?;
|
|
|
|
|
|
let cop = match op.as_str() {
|
|
|
|
|
|
"==" => crate::mir::CompareOp::Eq,
|
|
|
|
|
|
"!=" => crate::mir::CompareOp::Ne,
|
|
|
|
|
|
"<" => crate::mir::CompareOp::Lt,
|
|
|
|
|
|
"<=" => crate::mir::CompareOp::Le,
|
|
|
|
|
|
">" => crate::mir::CompareOp::Gt,
|
|
|
|
|
|
">=" => crate::mir::CompareOp::Ge,
|
|
|
|
|
|
_ => return Err("unsupported compare op".into()),
|
|
|
|
|
|
};
|
|
|
|
|
|
let dst = f.next_value_id();
|
2025-11-04 21:33:09 +09:00
|
|
|
|
crate::mir::ssot::cf_common::emit_compare_func(f, cur_after_r, dst, cop, l, r);
|
2025-09-17 11:45:57 +09:00
|
|
|
|
Ok((dst, cur_after_r))
|
|
|
|
|
|
}
|
|
|
|
|
|
ExprV0::Logical { op, lhs, rhs } => {
|
|
|
|
|
|
let (l, cur_after_l) = lower_expr_with_scope(env, f, cur_bb, lhs, vars)?;
|
|
|
|
|
|
let rhs_bb = new_block(f);
|
|
|
|
|
|
let fall_bb = new_block(f);
|
|
|
|
|
|
let merge_bb = new_block(f);
|
|
|
|
|
|
let is_and = matches!(op.as_str(), "&&" | "and");
|
2025-11-04 21:33:09 +09:00
|
|
|
|
if is_and {
|
|
|
|
|
|
crate::mir::ssot::cf_common::set_branch(f, cur_after_l, l, rhs_bb, fall_bb);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
crate::mir::ssot::cf_common::set_branch(f, cur_after_l, l, fall_bb, rhs_bb);
|
2025-09-17 11:45:57 +09:00
|
|
|
|
}
|
2025-09-23 02:26:33 +09:00
|
|
|
|
// ARCHIVED: JIT events moved to archive/jit-cranelift/ during Phase 15
|
|
|
|
|
|
// crate::jit::events::emit_lower(
|
|
|
|
|
|
// serde_json::json!({ "id":"shortcircuit","op": if is_and {"and"} else {"or"},"rhs_bb":rhs_bb.0,"fall_bb":fall_bb.0,"merge_bb":merge_bb.0 }),
|
|
|
|
|
|
// "shortcircuit",
|
|
|
|
|
|
// "<json_v0>",
|
|
|
|
|
|
// );
|
2025-09-17 11:45:57 +09:00
|
|
|
|
let cdst = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(fall_bb) {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
let cval = if is_and {
|
|
|
|
|
|
ConstValue::Bool(false)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
ConstValue::Bool(true)
|
|
|
|
|
|
};
|
|
|
|
|
|
bb.add_instruction(MirInstruction::Const {
|
|
|
|
|
|
dst: cdst,
|
|
|
|
|
|
value: cval,
|
|
|
|
|
|
});
|
2025-09-17 11:45:57 +09:00
|
|
|
|
}
|
2025-11-04 21:33:09 +09:00
|
|
|
|
crate::mir::ssot::cf_common::set_jump(f, fall_bb, merge_bb);
|
2025-09-17 11:45:57 +09:00
|
|
|
|
let (rval, rhs_end) = lower_expr_with_scope(env, f, rhs_bb, rhs, vars)?;
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(rhs_end) {
|
|
|
|
|
|
if !bb.is_terminated() {
|
2025-11-04 21:33:09 +09:00
|
|
|
|
crate::mir::ssot::cf_common::set_jump(f, rhs_end, merge_bb);
|
2025-09-17 11:45:57 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
let out = f.next_value_id();
|
2025-09-23 07:41:08 +09:00
|
|
|
|
// フェーズM.2: PHI統一処理(no_phi分岐削除)
|
2025-11-04 21:33:09 +09:00
|
|
|
|
let mut inputs: Vec<(BasicBlockId, ValueId)> = vec![(fall_bb, cdst)];
|
2025-11-21 06:25:17 +09:00
|
|
|
|
if rhs_end != fall_bb {
|
|
|
|
|
|
inputs.push((rhs_end, rval));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
inputs.push((fall_bb, rval));
|
|
|
|
|
|
}
|
2025-11-24 15:02:51 +09:00
|
|
|
|
crate::mir::ssot::cf_common::insert_phi_at_head_spanned(
|
|
|
|
|
|
f,
|
|
|
|
|
|
merge_bb,
|
|
|
|
|
|
out,
|
|
|
|
|
|
inputs,
|
|
|
|
|
|
Span::unknown(),
|
|
|
|
|
|
);
|
2025-09-17 11:45:57 +09:00
|
|
|
|
Ok((out, merge_bb))
|
|
|
|
|
|
}
|
|
|
|
|
|
ExprV0::Call { name, args } => {
|
|
|
|
|
|
if name == "array.of" {
|
|
|
|
|
|
let arr = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur_bb) {
|
|
|
|
|
|
bb.add_instruction(MirInstruction::NewBox {
|
|
|
|
|
|
dst: arr,
|
|
|
|
|
|
box_type: "ArrayBox".into(),
|
|
|
|
|
|
args: vec![],
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
let mut cur = cur_bb;
|
|
|
|
|
|
for e in args {
|
|
|
|
|
|
let (v, c) = lower_expr_with_scope(env, f, cur, e, vars)?;
|
|
|
|
|
|
cur = c;
|
|
|
|
|
|
let tmp = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur) {
|
|
|
|
|
|
bb.add_instruction(MirInstruction::BoxCall {
|
|
|
|
|
|
dst: Some(tmp),
|
|
|
|
|
|
box_val: arr,
|
|
|
|
|
|
method: "push".into(),
|
|
|
|
|
|
method_id: None,
|
|
|
|
|
|
args: vec![v],
|
|
|
|
|
|
effects: EffectMask::READ,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return Ok((arr, cur));
|
|
|
|
|
|
}
|
|
|
|
|
|
if name == "map.of" {
|
|
|
|
|
|
let mapv = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur_bb) {
|
|
|
|
|
|
bb.add_instruction(MirInstruction::NewBox {
|
|
|
|
|
|
dst: mapv,
|
|
|
|
|
|
box_type: "MapBox".into(),
|
|
|
|
|
|
args: vec![],
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
let mut cur = cur_bb;
|
|
|
|
|
|
let mut it = args.iter();
|
|
|
|
|
|
while let Some(k) = it.next() {
|
|
|
|
|
|
if let Some(v) = it.next() {
|
|
|
|
|
|
let (kv, cur2) = lower_expr_with_scope(env, f, cur, k, vars)?;
|
|
|
|
|
|
cur = cur2;
|
|
|
|
|
|
let (vv, cur3) = lower_expr_with_scope(env, f, cur, v, vars)?;
|
|
|
|
|
|
cur = cur3;
|
|
|
|
|
|
let tmp = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur) {
|
|
|
|
|
|
bb.add_instruction(MirInstruction::BoxCall {
|
|
|
|
|
|
dst: Some(tmp),
|
|
|
|
|
|
box_val: mapv,
|
|
|
|
|
|
method: "set".into(),
|
|
|
|
|
|
method_id: None,
|
|
|
|
|
|
args: vec![kv, vv],
|
|
|
|
|
|
effects: EffectMask::READ,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return Ok((mapv, cur));
|
|
|
|
|
|
}
|
|
|
|
|
|
let (arg_ids, cur) = lower_args_with_scope(env, f, cur_bb, args, vars)?;
|
|
|
|
|
|
let fun_val = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur) {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
bb.add_instruction(MirInstruction::Const {
|
|
|
|
|
|
dst: fun_val,
|
|
|
|
|
|
value: ConstValue::String(name.clone()),
|
|
|
|
|
|
});
|
2025-09-17 11:45:57 +09:00
|
|
|
|
}
|
|
|
|
|
|
let dst = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur) {
|
|
|
|
|
|
bb.add_instruction(MirInstruction::Call {
|
|
|
|
|
|
dst: Some(dst),
|
|
|
|
|
|
func: fun_val,
|
2025-09-24 01:05:44 +09:00
|
|
|
|
callee: None, // JSON bridge - use legacy resolution
|
2025-09-17 11:45:57 +09:00
|
|
|
|
args: arg_ids,
|
|
|
|
|
|
effects: EffectMask::READ,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok((dst, cur))
|
|
|
|
|
|
}
|
|
|
|
|
|
ExprV0::Method { recv, method, args } => {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
let recv_is_console_new =
|
|
|
|
|
|
matches!(&**recv, ExprV0::New { class, .. } if class == "ConsoleBox");
|
|
|
|
|
|
if recv_is_console_new && (method == "println" || method == "print" || method == "log")
|
|
|
|
|
|
{
|
2025-09-17 11:45:57 +09:00
|
|
|
|
let (arg_ids, cur2) = lower_args_with_scope(env, f, cur_bb, args, vars)?;
|
|
|
|
|
|
let dst = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur2) {
|
|
|
|
|
|
bb.add_instruction(MirInstruction::ExternCall {
|
|
|
|
|
|
dst: Some(dst),
|
|
|
|
|
|
iface_name: "env.console".into(),
|
|
|
|
|
|
method_name: "log".into(),
|
|
|
|
|
|
args: arg_ids,
|
|
|
|
|
|
effects: EffectMask::READ,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
return Ok((dst, cur2));
|
|
|
|
|
|
}
|
2025-11-16 17:19:56 +09:00
|
|
|
|
// Phase 25.1b: Handle env.box_introspect.kind(value) pattern
|
|
|
|
|
|
// Pattern: Method { recv: Method { recv: Var("env"), method: "box_introspect" }, method: "kind", args }
|
2025-11-21 06:25:17 +09:00
|
|
|
|
if let ExprV0::Method {
|
|
|
|
|
|
recv: inner_recv,
|
|
|
|
|
|
method: inner_method,
|
|
|
|
|
|
args: inner_args,
|
|
|
|
|
|
} = &**recv
|
|
|
|
|
|
{
|
2025-11-16 17:19:56 +09:00
|
|
|
|
if matches!(&**inner_recv, ExprV0::Var { name } if name == "env")
|
|
|
|
|
|
&& inner_method == "box_introspect"
|
2025-11-21 06:25:17 +09:00
|
|
|
|
&& inner_args.is_empty()
|
|
|
|
|
|
{
|
2025-11-16 17:19:56 +09:00
|
|
|
|
// Lower args for the final method call
|
|
|
|
|
|
let (arg_ids, cur2) = lower_args_with_scope(env, f, cur_bb, args, vars)?;
|
|
|
|
|
|
let dst = f.next_value_id();
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur2) {
|
|
|
|
|
|
bb.add_instruction(MirInstruction::ExternCall {
|
|
|
|
|
|
dst: Some(dst),
|
|
|
|
|
|
iface_name: "env.box_introspect".into(),
|
|
|
|
|
|
method_name: method.clone(),
|
|
|
|
|
|
args: arg_ids,
|
|
|
|
|
|
effects: EffectMask::READ,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
return Ok((dst, cur2));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-17 11:45:57 +09:00
|
|
|
|
let (recv_v, cur) = lower_expr_with_scope(env, f, cur_bb, recv, vars)?;
|
|
|
|
|
|
let (arg_ids, cur2) = lower_args_with_scope(env, f, cur, args, vars)?;
|
|
|
|
|
|
let dst = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur2) {
|
|
|
|
|
|
bb.add_instruction(MirInstruction::BoxCall {
|
|
|
|
|
|
dst: Some(dst),
|
|
|
|
|
|
box_val: recv_v,
|
|
|
|
|
|
method: method.clone(),
|
|
|
|
|
|
method_id: None,
|
|
|
|
|
|
args: arg_ids,
|
|
|
|
|
|
effects: EffectMask::READ,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok((dst, cur2))
|
|
|
|
|
|
}
|
|
|
|
|
|
ExprV0::New { class, args } => {
|
|
|
|
|
|
let (arg_ids, cur) = lower_args_with_scope(env, f, cur_bb, args, vars)?;
|
|
|
|
|
|
let dst = f.next_value_id();
|
|
|
|
|
|
if let Some(bb) = f.get_block_mut(cur) {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
bb.add_instruction(MirInstruction::NewBox {
|
|
|
|
|
|
dst,
|
|
|
|
|
|
box_type: class.clone(),
|
|
|
|
|
|
args: arg_ids,
|
|
|
|
|
|
});
|
2025-09-17 11:45:57 +09:00
|
|
|
|
}
|
|
|
|
|
|
Ok((dst, cur))
|
|
|
|
|
|
}
|
|
|
|
|
|
ExprV0::Var { name } => match vars.resolve(env, f, cur_bb, name)? {
|
|
|
|
|
|
Some(v) => Ok((v, cur_bb)),
|
|
|
|
|
|
None => Err(format!("undefined variable: {}", name)),
|
|
|
|
|
|
},
|
|
|
|
|
|
ExprV0::Throw { expr } => {
|
|
|
|
|
|
let (exc, cur) = lower_expr_with_scope(env, f, cur_bb, expr, vars)?;
|
|
|
|
|
|
Ok(lower_throw(env, f, cur, exc))
|
|
|
|
|
|
}
|
2025-11-21 06:25:17 +09:00
|
|
|
|
ExprV0::Ternary { cond, then, r#else } => {
|
|
|
|
|
|
ternary::lower_ternary_expr_with_scope(env, f, cur_bb, cond, then, r#else, vars)
|
|
|
|
|
|
}
|
|
|
|
|
|
ExprV0::Match {
|
|
|
|
|
|
scrutinee,
|
|
|
|
|
|
arms,
|
|
|
|
|
|
r#else,
|
|
|
|
|
|
} => match_expr::lower_match_expr_with_scope(env, f, cur_bb, scrutinee, arms, r#else, vars),
|
2025-09-17 11:45:57 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn lower_args_with_scope<S: VarScope>(
|
|
|
|
|
|
env: &BridgeEnv,
|
|
|
|
|
|
f: &mut MirFunction,
|
|
|
|
|
|
cur_bb: BasicBlockId,
|
|
|
|
|
|
args: &[ExprV0],
|
|
|
|
|
|
scope: &mut S,
|
|
|
|
|
|
) -> Result<(Vec<ValueId>, BasicBlockId), String> {
|
|
|
|
|
|
let mut out = Vec::with_capacity(args.len());
|
|
|
|
|
|
let mut cur = cur_bb;
|
|
|
|
|
|
for a in args {
|
|
|
|
|
|
let (v, c) = lower_expr_with_scope(env, f, cur, a, scope)?;
|
|
|
|
|
|
out.push(v);
|
|
|
|
|
|
cur = c;
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok((out, cur))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
|
fn lower_expr(
|
|
|
|
|
|
env: &BridgeEnv,
|
|
|
|
|
|
f: &mut MirFunction,
|
|
|
|
|
|
cur_bb: BasicBlockId,
|
|
|
|
|
|
e: &ExprV0,
|
|
|
|
|
|
) -> Result<(ValueId, BasicBlockId), String> {
|
|
|
|
|
|
let mut scope = NoVars;
|
|
|
|
|
|
lower_expr_with_scope(env, f, cur_bb, e, &mut scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(super) fn lower_expr_with_vars(
|
|
|
|
|
|
env: &BridgeEnv,
|
|
|
|
|
|
f: &mut MirFunction,
|
|
|
|
|
|
cur_bb: BasicBlockId,
|
|
|
|
|
|
e: &ExprV0,
|
2025-11-22 05:33:40 +09:00
|
|
|
|
vars: &mut BTreeMap<String, ValueId>,
|
2025-09-17 11:45:57 +09:00
|
|
|
|
) -> Result<(ValueId, BasicBlockId), String> {
|
|
|
|
|
|
let mut scope = MapVars::new(vars);
|
|
|
|
|
|
lower_expr_with_scope(env, f, cur_bb, e, &mut scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
|
fn lower_args(
|
|
|
|
|
|
env: &BridgeEnv,
|
|
|
|
|
|
f: &mut MirFunction,
|
|
|
|
|
|
cur_bb: BasicBlockId,
|
|
|
|
|
|
args: &[ExprV0],
|
|
|
|
|
|
) -> Result<(Vec<ValueId>, BasicBlockId), String> {
|
|
|
|
|
|
let mut scope = NoVars;
|
|
|
|
|
|
lower_args_with_scope(env, f, cur_bb, args, &mut scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(super) fn lower_args_with_vars(
|
|
|
|
|
|
env: &BridgeEnv,
|
|
|
|
|
|
f: &mut MirFunction,
|
|
|
|
|
|
cur_bb: BasicBlockId,
|
|
|
|
|
|
args: &[ExprV0],
|
2025-11-22 05:33:40 +09:00
|
|
|
|
vars: &mut BTreeMap<String, ValueId>,
|
2025-09-17 11:45:57 +09:00
|
|
|
|
) -> Result<(Vec<ValueId>, BasicBlockId), String> {
|
|
|
|
|
|
let mut scope = MapVars::new(vars);
|
|
|
|
|
|
lower_args_with_scope(env, f, cur_bb, args, &mut scope)
|
|
|
|
|
|
}
|