chore: Phase 25.1 完了 - LoopForm v2/Stage1 CLI/環境変数削減 + Phase 26-D からの変更
Phase 25.1 完了成果: - ✅ LoopForm v2 テスト・ドキュメント・コメント完備 - 4ケース(A/B/C/D)完全テストカバレッジ - 最小再現ケース作成(SSAバグ調査用) - SSOT文書作成(loopform_ssot.md) - 全ソースに [LoopForm] コメントタグ追加 - ✅ Stage-1 CLI デバッグ環境構築 - stage1_cli.hako 実装 - stage1_bridge.rs ブリッジ実装 - デバッグツール作成(stage1_debug.sh/stage1_minimal.sh) - アーキテクチャ改善提案文書 - ✅ 環境変数削減計画策定 - 25変数の完全調査・分類 - 6段階削減ロードマップ(25→5、80%削減) - 即時削除可能変数特定(NYASH_CONFIG/NYASH_DEBUG) Phase 26-D からの累積変更: - PHI実装改善(ExitPhiBuilder/HeaderPhiBuilder等) - MIRビルダーリファクタリング - 型伝播・最適化パス改善 - その他約300ファイルの累積変更 🎯 技術的成果: - SSAバグ根本原因特定(条件分岐内loop変数変更) - Region+next_iパターン適用完了(UsingCollectorBox等) - LoopFormパターン文書化・テスト化完了 - セルフホスティング基盤強化 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: ChatGPT <noreply@openai.com> Co-Authored-By: Task Assistant <task@anthropic.com>
This commit is contained in:
@ -1,9 +1,9 @@
|
||||
use super::mir_json::common as mirjson_common;
|
||||
use crate::mir::{
|
||||
function::{FunctionSignature, MirFunction, MirModule},
|
||||
BasicBlock, BasicBlockId, ConstValue, EffectMask, MirInstruction, MirType, ValueId,
|
||||
};
|
||||
use serde_json::Value;
|
||||
use super::mir_json::common as mirjson_common;
|
||||
|
||||
fn parse_effects_from(node: &Value) -> EffectMask {
|
||||
if let Some(arr) = node.get("effects").and_then(Value::as_array) {
|
||||
@ -11,10 +11,18 @@ fn parse_effects_from(node: &Value) -> EffectMask {
|
||||
for e in arr {
|
||||
if let Some(s) = e.as_str() {
|
||||
match s {
|
||||
"write" | "mut" | "WriteHeap" => { m = m.union(EffectMask::WRITE); }
|
||||
"read" | "ReadHeap" => { m = m.union(EffectMask::READ); }
|
||||
"io" | "IO" | "ffi" | "FFI" | "debug" => { m = m.union(EffectMask::IO); }
|
||||
"control" | "Control" => { m = m.union(EffectMask::CONTROL); }
|
||||
"write" | "mut" | "WriteHeap" => {
|
||||
m = m.union(EffectMask::WRITE);
|
||||
}
|
||||
"read" | "ReadHeap" => {
|
||||
m = m.union(EffectMask::READ);
|
||||
}
|
||||
"io" | "IO" | "ffi" | "FFI" | "debug" => {
|
||||
m = m.union(EffectMask::IO);
|
||||
}
|
||||
"control" | "Control" => {
|
||||
m = m.union(EffectMask::CONTROL);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -39,12 +47,7 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
|
||||
let schema = match value.get("schema_version") {
|
||||
Some(Value::String(s)) => s.clone(),
|
||||
Some(other) => {
|
||||
return Err(format!(
|
||||
"expected schema_version string, found {}",
|
||||
other
|
||||
))
|
||||
}
|
||||
Some(other) => return Err(format!("expected schema_version string, found {}", other)),
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
@ -98,7 +101,8 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
let block_id = block
|
||||
.get("id")
|
||||
.and_then(|id| id.as_u64())
|
||||
.ok_or_else(|| format!("function '{}' block missing id", func_name))? as u32;
|
||||
.ok_or_else(|| format!("function '{}' block missing id", func_name))?
|
||||
as u32;
|
||||
let bb_id = BasicBlockId::new(block_id);
|
||||
if mir_fn.get_block(bb_id).is_none() {
|
||||
mir_fn.add_block(BasicBlock::new(bb_id));
|
||||
@ -118,34 +122,23 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
})?;
|
||||
|
||||
for inst in instructions {
|
||||
let op = inst
|
||||
.get("op")
|
||||
.and_then(|o| o.as_str())
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"function '{}' block {} missing op field",
|
||||
func_name, block_id
|
||||
)
|
||||
})?;
|
||||
let op = inst.get("op").and_then(|o| o.as_str()).ok_or_else(|| {
|
||||
format!(
|
||||
"function '{}' block {} missing op field",
|
||||
func_name, block_id
|
||||
)
|
||||
})?;
|
||||
match op {
|
||||
"const" => {
|
||||
let dst = inst
|
||||
.get("dst")
|
||||
.and_then(|d| d.as_u64())
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"const instruction missing dst in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})? as u32;
|
||||
let value_obj = inst
|
||||
.get("value")
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"const instruction missing value in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})?;
|
||||
let dst = inst.get("dst").and_then(|d| d.as_u64()).ok_or_else(|| {
|
||||
format!("const instruction missing dst in function '{}'", func_name)
|
||||
})? as u32;
|
||||
let value_obj = inst.get("value").ok_or_else(|| {
|
||||
format!(
|
||||
"const instruction missing value in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})?;
|
||||
let const_val = mirjson_common::parse_const_value_generic(value_obj)?;
|
||||
block_ref.add_instruction(MirInstruction::Const {
|
||||
dst: ValueId::new(dst),
|
||||
@ -156,24 +149,12 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
}
|
||||
}
|
||||
"copy" => {
|
||||
let dst = inst
|
||||
.get("dst")
|
||||
.and_then(|d| d.as_u64())
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"copy instruction missing dst in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})? as u32;
|
||||
let src = inst
|
||||
.get("src")
|
||||
.and_then(|d| d.as_u64())
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"copy instruction missing src in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})? as u32;
|
||||
let dst = inst.get("dst").and_then(|d| d.as_u64()).ok_or_else(|| {
|
||||
format!("copy instruction missing dst in function '{}'", func_name)
|
||||
})? as u32;
|
||||
let src = inst.get("src").and_then(|d| d.as_u64()).ok_or_else(|| {
|
||||
format!("copy instruction missing src in function '{}'", func_name)
|
||||
})? as u32;
|
||||
block_ref.add_instruction(MirInstruction::Copy {
|
||||
dst: ValueId::new(dst),
|
||||
src: ValueId::new(src),
|
||||
@ -186,10 +167,12 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
let dst = require_u64(inst, "dst", "binop dst")? as u32;
|
||||
let lhs = require_u64(inst, "lhs", "binop lhs")? as u32;
|
||||
let rhs = require_u64(inst, "rhs", "binop rhs")? as u32;
|
||||
let operation = inst
|
||||
.get("operation")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or_else(|| format!("binop operation missing in function '{}'", func_name))?;
|
||||
let operation =
|
||||
inst.get("operation")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or_else(|| {
|
||||
format!("binop operation missing in function '{}'", func_name)
|
||||
})?;
|
||||
let bop = parse_binop(operation)?;
|
||||
block_ref.add_instruction(MirInstruction::BinOp {
|
||||
dst: ValueId::new(dst),
|
||||
@ -206,7 +189,10 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
// Accept both JSON shapes:
|
||||
// - operation: symbolic string ("<", ">=", "==", ...)
|
||||
// - cmp: spelled enum name ("Lt", "Le", "Gt", "Ge", "Eq", "Ne")
|
||||
let op_sym_opt = inst.get("operation").and_then(Value::as_str).map(|s| s.to_string());
|
||||
let op_sym_opt = inst
|
||||
.get("operation")
|
||||
.and_then(Value::as_str)
|
||||
.map(|s| s.to_string());
|
||||
let op_sym = if let Some(sym) = op_sym_opt {
|
||||
sym
|
||||
} else if let Some(name) = inst.get("cmp").and_then(Value::as_str) {
|
||||
@ -257,25 +243,31 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
}
|
||||
"phi" => {
|
||||
let dst = require_u64(inst, "dst", "phi dst")? as u32;
|
||||
let incoming = inst
|
||||
.get("incoming")
|
||||
.and_then(Value::as_array)
|
||||
.ok_or_else(|| format!("phi incoming missing in function '{}'", func_name))?;
|
||||
let incoming =
|
||||
inst.get("incoming")
|
||||
.and_then(Value::as_array)
|
||||
.ok_or_else(|| {
|
||||
format!("phi incoming missing in function '{}'", func_name)
|
||||
})?;
|
||||
let mut pairs = Vec::with_capacity(incoming.len());
|
||||
for entry in incoming {
|
||||
let pair = entry
|
||||
.as_array()
|
||||
.ok_or_else(|| format!("phi incoming entry must be array in function '{}'", func_name))?;
|
||||
let pair = entry.as_array().ok_or_else(|| {
|
||||
format!(
|
||||
"phi incoming entry must be array in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})?;
|
||||
if pair.len() != 2 {
|
||||
return Err("phi incoming entry must have 2 elements".into());
|
||||
}
|
||||
// JSON shape: [pred_block_id, value_id]
|
||||
let pred_bb = pair[0]
|
||||
.as_u64()
|
||||
.ok_or_else(|| "phi incoming predecessor block must be integer".to_string())? as u32;
|
||||
let pred_bb = pair[0].as_u64().ok_or_else(|| {
|
||||
"phi incoming predecessor block must be integer".to_string()
|
||||
})? as u32;
|
||||
let val = pair[1]
|
||||
.as_u64()
|
||||
.ok_or_else(|| "phi incoming value must be integer".to_string())? as u32;
|
||||
.ok_or_else(|| "phi incoming value must be integer".to_string())?
|
||||
as u32;
|
||||
pairs.push((BasicBlockId::new(pred_bb), ValueId::new(val)));
|
||||
}
|
||||
block_ref.add_instruction(MirInstruction::Phi {
|
||||
@ -303,20 +295,30 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
// - flat: { op:"mir_call", callee:{...}, args:[...], effects:[] }
|
||||
// - nested: { op:"mir_call", mir_call:{ callee:{...}, args:[...], effects:[] } }
|
||||
// dst remains at the instruction root level in both forms.
|
||||
let dst_opt = inst.get("dst").and_then(|d| d.as_u64()).map(|v| ValueId::new(v as u32));
|
||||
let effects = if let Some(sub) = inst.get("mir_call") { parse_effects_from(sub) } else { parse_effects_from(inst) };
|
||||
let dst_opt = inst
|
||||
.get("dst")
|
||||
.and_then(|d| d.as_u64())
|
||||
.map(|v| ValueId::new(v as u32));
|
||||
let effects = if let Some(sub) = inst.get("mir_call") {
|
||||
parse_effects_from(sub)
|
||||
} else {
|
||||
parse_effects_from(inst)
|
||||
};
|
||||
// args: support both flat/nested placement
|
||||
let mut argv: Vec<ValueId> = Vec::new();
|
||||
if let Some(arr) = inst
|
||||
.get("args")
|
||||
.and_then(|a| a.as_array())
|
||||
.or_else(|| inst.get("mir_call").and_then(|m| m.get("args").and_then(|a| a.as_array())))
|
||||
if let Some(arr) =
|
||||
inst.get("args").and_then(|a| a.as_array()).or_else(|| {
|
||||
inst.get("mir_call")
|
||||
.and_then(|m| m.get("args").and_then(|a| a.as_array()))
|
||||
})
|
||||
{
|
||||
for a in arr {
|
||||
let id = a.as_u64().ok_or_else(|| format!(
|
||||
"mir_call arg must be integer value id in function '{}'",
|
||||
func_name
|
||||
))? as u32;
|
||||
let id = a.as_u64().ok_or_else(|| {
|
||||
format!(
|
||||
"mir_call arg must be integer value id in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})? as u32;
|
||||
argv.push(ValueId::new(id));
|
||||
}
|
||||
}
|
||||
@ -325,30 +327,37 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
.get("callee")
|
||||
.or_else(|| inst.get("mir_call").and_then(|m| m.get("callee")))
|
||||
.ok_or_else(|| {
|
||||
format!("mir_call missing callee in function '{}'", func_name)
|
||||
})?;
|
||||
let ctype = callee_obj
|
||||
.get("type")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or_else(|| format!("mir_call callee.type missing in function '{}'", func_name))?;
|
||||
format!("mir_call missing callee in function '{}'", func_name)
|
||||
})?;
|
||||
let ctype =
|
||||
callee_obj
|
||||
.get("type")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"mir_call callee.type missing in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})?;
|
||||
match ctype {
|
||||
"Global" => {
|
||||
let raw_name = callee_obj
|
||||
.get("name")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or_else(|| format!(
|
||||
"mir_call callee Global missing name in function '{}'",
|
||||
func_name
|
||||
))?;
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"mir_call callee Global missing name in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})?;
|
||||
// Map known console aliases to interpreter-accepted names
|
||||
let mapped = match raw_name {
|
||||
"print" => "print".to_string(),
|
||||
"nyash.builtin.print" => "nyash.builtin.print".to_string(),
|
||||
"nyash.console.log" => "nyash.console.log".to_string(),
|
||||
// Accept env.console.* as nyash.console.log (numeric only)
|
||||
"env.console.log" | "env.console.warn" | "env.console.error" => {
|
||||
"nyash.console.log".to_string()
|
||||
}
|
||||
"env.console.log" | "env.console.warn"
|
||||
| "env.console.error" => "nyash.console.log".to_string(),
|
||||
other => {
|
||||
return Err(format!(
|
||||
"unsupported Global callee '{}' in mir_call (Gate-C v1 bridge)",
|
||||
@ -363,7 +372,9 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
args: argv,
|
||||
effects,
|
||||
});
|
||||
if let Some(d) = dst_opt { max_value_id = max_value_id.max(d.as_u32() + 1); }
|
||||
if let Some(d) = dst_opt {
|
||||
max_value_id = max_value_id.max(d.as_u32() + 1);
|
||||
}
|
||||
}
|
||||
"Constructor" => {
|
||||
// new box instance: box_type required
|
||||
@ -375,10 +386,12 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
func_name
|
||||
))?;
|
||||
// dst required for Constructor
|
||||
let dst = dst_opt.ok_or_else(|| format!(
|
||||
"mir_call Constructor requires dst in function '{}'",
|
||||
func_name
|
||||
))?;
|
||||
let dst = dst_opt.ok_or_else(|| {
|
||||
format!(
|
||||
"mir_call Constructor requires dst in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})?;
|
||||
block_ref.add_instruction(MirInstruction::NewBox {
|
||||
dst,
|
||||
box_type: bt.to_string(),
|
||||
@ -391,18 +404,22 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
let method = callee_obj
|
||||
.get("method")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or_else(|| format!(
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"mir_call callee Method missing method in function '{}'",
|
||||
func_name
|
||||
))?
|
||||
)
|
||||
})?
|
||||
.to_string();
|
||||
let recv_id = callee_obj
|
||||
.get("receiver")
|
||||
.and_then(Value::as_u64)
|
||||
.ok_or_else(|| format!(
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"mir_call callee Method missing receiver in function '{}'",
|
||||
func_name
|
||||
))? as u32;
|
||||
)
|
||||
})? as u32;
|
||||
let box_name = callee_obj
|
||||
.get("box_name")
|
||||
.and_then(Value::as_str)
|
||||
@ -422,7 +439,9 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
args: argv,
|
||||
effects,
|
||||
});
|
||||
if let Some(d) = dst_opt { max_value_id = max_value_id.max(d.as_u32() + 1); }
|
||||
if let Some(d) = dst_opt {
|
||||
max_value_id = max_value_id.max(d.as_u32() + 1);
|
||||
}
|
||||
}
|
||||
"Closure" => {
|
||||
// Two shapes are seen in the wild:
|
||||
@ -433,13 +452,17 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
|| callee_obj.get("me_capture").is_some();
|
||||
if has_new_fields {
|
||||
// Closure creation (NewClosure equivalent)
|
||||
let dst = dst_opt.ok_or_else(|| format!(
|
||||
"mir_call Closure requires dst in function '{}'",
|
||||
func_name
|
||||
))?;
|
||||
let dst = dst_opt.ok_or_else(|| {
|
||||
format!(
|
||||
"mir_call Closure requires dst in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})?;
|
||||
// params: array of strings (optional)
|
||||
let mut params: Vec<String> = Vec::new();
|
||||
if let Some(arr) = callee_obj.get("params").and_then(Value::as_array) {
|
||||
if let Some(arr) =
|
||||
callee_obj.get("params").and_then(Value::as_array)
|
||||
{
|
||||
for p in arr {
|
||||
let s = p.as_str().ok_or_else(|| format!(
|
||||
"mir_call Closure params must be strings in function '{}'",
|
||||
@ -450,7 +473,9 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
}
|
||||
// captures: array of [name, id]
|
||||
let mut captures: Vec<(String, ValueId)> = Vec::new();
|
||||
if let Some(arr) = callee_obj.get("captures").and_then(Value::as_array) {
|
||||
if let Some(arr) =
|
||||
callee_obj.get("captures").and_then(Value::as_array)
|
||||
{
|
||||
for e in arr {
|
||||
let pair = e.as_array().ok_or_else(|| format!(
|
||||
"mir_call Closure capture entry must be array in function '{}'",
|
||||
@ -460,11 +485,14 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
return Err("mir_call Closure capture entry must have 2 elements".into());
|
||||
}
|
||||
let name = pair[0].as_str().ok_or_else(|| {
|
||||
"mir_call Closure capture[0] must be string".to_string()
|
||||
"mir_call Closure capture[0] must be string"
|
||||
.to_string()
|
||||
})?;
|
||||
let id = pair[1].as_u64().ok_or_else(|| {
|
||||
"mir_call Closure capture[1] must be integer".to_string()
|
||||
})? as u32;
|
||||
"mir_call Closure capture[1] must be integer"
|
||||
.to_string()
|
||||
})?
|
||||
as u32;
|
||||
captures.push((name.to_string(), ValueId::new(id)));
|
||||
}
|
||||
}
|
||||
@ -487,12 +515,16 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
let fid = callee_obj
|
||||
.get("func")
|
||||
.and_then(Value::as_u64)
|
||||
.ok_or_else(|| format!(
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"mir_call callee Closure missing func in function '{}'",
|
||||
func_name
|
||||
))? as u32;
|
||||
)
|
||||
})? as u32;
|
||||
// Captures array (if present) are appended to argv for minimal parity
|
||||
if let Some(caps) = callee_obj.get("captures").and_then(Value::as_array) {
|
||||
if let Some(caps) =
|
||||
callee_obj.get("captures").and_then(Value::as_array)
|
||||
{
|
||||
for c in caps {
|
||||
let id = c.as_u64().ok_or_else(|| format!(
|
||||
"mir_call Closure capture must be integer in function '{}'",
|
||||
@ -504,21 +536,27 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
block_ref.add_instruction(MirInstruction::Call {
|
||||
dst: dst_opt,
|
||||
func: ValueId::new(0),
|
||||
callee: Some(crate::mir::definitions::Callee::Value(ValueId::new(fid))),
|
||||
callee: Some(crate::mir::definitions::Callee::Value(
|
||||
ValueId::new(fid),
|
||||
)),
|
||||
args: argv,
|
||||
effects,
|
||||
});
|
||||
if let Some(d) = dst_opt { max_value_id = max_value_id.max(d.as_u32() + 1); }
|
||||
if let Some(d) = dst_opt {
|
||||
max_value_id = max_value_id.max(d.as_u32() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
"Extern" => {
|
||||
let name = callee_obj
|
||||
.get("name")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or_else(|| format!(
|
||||
"mir_call callee Extern missing name in function '{}'",
|
||||
func_name
|
||||
))?
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"mir_call callee Extern missing name in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})?
|
||||
.to_string();
|
||||
block_ref.add_instruction(MirInstruction::Call {
|
||||
dst: dst_opt,
|
||||
@ -527,25 +565,33 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
||||
args: argv,
|
||||
effects: EffectMask::IO,
|
||||
});
|
||||
if let Some(d) = dst_opt { max_value_id = max_value_id.max(d.as_u32() + 1); }
|
||||
if let Some(d) = dst_opt {
|
||||
max_value_id = max_value_id.max(d.as_u32() + 1);
|
||||
}
|
||||
}
|
||||
"Value" => {
|
||||
// dynamic function value id: field 'func' (u64)
|
||||
let fid = callee_obj
|
||||
.get("func")
|
||||
.and_then(Value::as_u64)
|
||||
.ok_or_else(|| format!(
|
||||
"mir_call callee Value missing func in function '{}'",
|
||||
func_name
|
||||
))? as u32;
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"mir_call callee Value missing func in function '{}'",
|
||||
func_name
|
||||
)
|
||||
})? as u32;
|
||||
block_ref.add_instruction(MirInstruction::Call {
|
||||
dst: dst_opt,
|
||||
func: ValueId::new(0),
|
||||
callee: Some(crate::mir::definitions::Callee::Value(ValueId::new(fid))),
|
||||
callee: Some(crate::mir::definitions::Callee::Value(
|
||||
ValueId::new(fid),
|
||||
)),
|
||||
args: argv,
|
||||
effects,
|
||||
});
|
||||
if let Some(d) = dst_opt { max_value_id = max_value_id.max(d.as_u32() + 1); }
|
||||
if let Some(d) = dst_opt {
|
||||
max_value_id = max_value_id.max(d.as_u32() + 1);
|
||||
}
|
||||
}
|
||||
// (no duplicate Closure arm; handled above)
|
||||
other => {
|
||||
@ -646,9 +692,9 @@ fn parse_const_value(value_obj: &Value) -> Result<ConstValue, String> {
|
||||
match box_type.as_str() {
|
||||
// StringBox handle is serialized with raw string payload
|
||||
"StringBox" => {
|
||||
let s = raw_val
|
||||
.as_str()
|
||||
.ok_or_else(|| "StringBox const expects string value".to_string())?;
|
||||
let s = raw_val.as_str().ok_or_else(|| {
|
||||
"StringBox const expects string value".to_string()
|
||||
})?;
|
||||
return Ok(ConstValue::String(s.to_string()));
|
||||
}
|
||||
// Other handle kinds are not yet supported in the bridge
|
||||
@ -667,7 +713,9 @@ fn parse_const_value(value_obj: &Value) -> Result<ConstValue, String> {
|
||||
|
||||
// No explicit type: heuristics
|
||||
match raw_val {
|
||||
Value::Number(n) => Ok(ConstValue::Integer(n.as_i64().ok_or_else(|| "integer expected".to_string())?)),
|
||||
Value::Number(n) => Ok(ConstValue::Integer(
|
||||
n.as_i64().ok_or_else(|| "integer expected".to_string())?,
|
||||
)),
|
||||
Value::Bool(b) => Ok(ConstValue::Bool(b)),
|
||||
Value::String(s) => Ok(ConstValue::String(s)),
|
||||
_ => Err("const value has unsupported type descriptor".to_string()),
|
||||
|
||||
Reference in New Issue
Block a user