fix(stage-b): Add sh_core using + Stage-1 JSON support

## Fixed Issues

1. compiler_stageb.hako: Added 'using sh_core as StringHelpers'
   - Resolved: call unresolved ParserStringUtilsBox.skip_ws/2
   - Root cause: using chain resolution not implemented
   - Workaround: explicit using in parent file

2. stageb_helpers.sh: Accept Stage-1 JSON format
   - Modified awk pattern to accept both formats:
     - MIR JSON v0: "version":0, "kind":"Program"
     - Stage-1 JSON: "type":"Program"

## Remaining Issues

ParserBox VM crash: Invalid value: use of undefined value ValueId(5839)
- Cause: Complex nested loops in parse_program2()
- Workaround: Minimal Stage-B (without ParserBox) works
- Fallback: Rust compiler path available

## Verification

 Minimal Stage-B outputs JSON correctly
 ParserBox execution crashes VM (SSA bug)

Co-Authored-By: Task先生 (AI Agent)
This commit is contained in:
nyash-codex
2025-11-02 08:23:43 +09:00
parent 91f3d82deb
commit 3aa0c3c875
15 changed files with 326 additions and 119 deletions

View File

@ -254,7 +254,7 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
}
}
"mir_call" => {
// Minimal v1 mir_call support (Global only; print-family)
// Minimal v1 mir_call support (Global/Method/Constructor/Extern/Value + Closure creation)
// dst: optional
let dst_opt = inst.get("dst").and_then(|d| d.as_u64()).map(|v| ValueId::new(v as u32));
// args: array of value ids
@ -310,6 +310,153 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
});
if let Some(d) = dst_opt { max_value_id = max_value_id.max(d.as_u32() + 1); }
}
"Method" => {
// receiver: required u64, method: string, box_name: optional
let method = callee_obj
.get("method")
.and_then(Value::as_str)
.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!(
"mir_call callee Method missing receiver in function '{}'",
func_name
))? as u32;
let box_name = callee_obj
.get("box_name")
.and_then(Value::as_str)
.unwrap_or("")
.to_string();
block_ref.add_instruction(MirInstruction::Call {
dst: dst_opt,
func: ValueId::new(0),
callee: Some(crate::mir::definitions::Callee::Method {
box_name,
method,
receiver: Some(ValueId::new(recv_id)),
certainty: crate::mir::definitions::call_unified::TypeCertainty::Known,
}),
args: argv,
effects: EffectMask::PURE,
});
if let Some(d) = dst_opt { max_value_id = max_value_id.max(d.as_u32() + 1); }
}
"Closure" => {
// Closure creation (NewClosure equivalent)
// Requires dst; accepts optional params[], captures[[name, id]...], me_capture
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) {
for p in arr {
let s = p.as_str().ok_or_else(|| format!(
"mir_call Closure params must be strings in function '{}'",
func_name
))?;
params.push(s.to_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) {
for e in arr {
let pair = e.as_array().ok_or_else(|| format!(
"mir_call Closure capture entry must be array in function '{}'",
func_name
))?;
if pair.len() != 2 {
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()
})?;
let id = pair[1].as_u64().ok_or_else(|| {
"mir_call Closure capture[1] must be integer".to_string()
})? as u32;
captures.push((name.to_string(), ValueId::new(id)));
}
}
// me_capture: optional u64
let me_capture = callee_obj
.get("me_capture")
.and_then(Value::as_u64)
.map(|v| ValueId::new(v as u32));
// Body is not carried in v1; create empty body vector as placeholder
block_ref.add_instruction(MirInstruction::NewClosure {
dst,
params,
body: Vec::new(),
captures,
me: me_capture,
});
max_value_id = max_value_id.max(dst.as_u32() + 1);
}
"Constructor" => {
// box_type: string, dst: required
let dst = dst_opt.ok_or_else(|| format!(
"mir_call Constructor requires dst in function '{}'",
func_name
))?;
let bt = callee_obj
.get("box_type")
.and_then(Value::as_str)
.ok_or_else(|| format!(
"mir_call Constructor missing box_type in function '{}'",
func_name
))?
.to_string();
block_ref.add_instruction(MirInstruction::NewBox {
dst,
box_type: bt,
args: argv.clone(),
});
max_value_id = max_value_id.max(dst.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
))?
.to_string();
block_ref.add_instruction(MirInstruction::Call {
dst: dst_opt,
func: ValueId::new(0),
callee: Some(crate::mir::definitions::Callee::Extern(name)),
args: argv,
effects: EffectMask::IO,
});
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;
block_ref.add_instruction(MirInstruction::Call {
dst: dst_opt,
func: ValueId::new(0),
callee: Some(crate::mir::definitions::Callee::Value(ValueId::new(fid))),
args: argv,
effects: EffectMask::PURE,
});
if let Some(d) = dst_opt { max_value_id = max_value_id.max(d.as_u32() + 1); }
}
other => {
return Err(format!(
"unsupported callee type '{}' in mir_call (Gate-C v1 bridge)",