Fix VM: string handler no longer hijacks length() on non-strings; ArrayBox.length returns correct values (fixes json_lint loop). Add string-literal reader init guard earlier
This commit is contained in:
@ -293,6 +293,11 @@ box JsonScanner {
|
||||
// 文字列リテラルを読み取り(クォート含む)
|
||||
read_string_literal() {
|
||||
local start_pos = me.position
|
||||
// Save starting position to _tmp_pos so that substring/range checks
|
||||
// do not depend on a previous reader’s value (PHI-safe, loop-safe).
|
||||
// Other high-level readers (read_number/read_identifier) already
|
||||
// initialize _tmp_pos; string literal must do the same.
|
||||
me._tmp_pos = me.position
|
||||
|
||||
// 開始クォート
|
||||
if me.current() != "\"" {
|
||||
|
||||
@ -12,13 +12,21 @@ pub(super) fn try_handle_string_box(
|
||||
eprintln!("[vm-trace] try_handle_string_box(method={})", method);
|
||||
}
|
||||
let recv = this.reg_load(box_val)?;
|
||||
// Normalize receiver to trait-level StringBox to bridge old/new StringBox implementations
|
||||
let sb_norm: crate::box_trait::StringBox = match recv.clone() {
|
||||
VMValue::String(s) => crate::box_trait::StringBox::new(s),
|
||||
VMValue::BoxRef(b) => b.to_string_box(),
|
||||
other => other.to_nyash_box().to_string_box(),
|
||||
// Handle ONLY when the receiver is actually a string.
|
||||
// Do NOT coerce arbitrary boxes to StringBox (e.g., ArrayBox.length()).
|
||||
let sb_norm_opt: Option<crate::box_trait::StringBox> = match recv.clone() {
|
||||
VMValue::String(s) => Some(crate::box_trait::StringBox::new(s)),
|
||||
VMValue::BoxRef(b) => {
|
||||
if b.as_any().downcast_ref::<crate::box_trait::StringBox>().is_some() {
|
||||
Some(b.to_string_box())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
// Only handle known string methods here
|
||||
let Some(sb_norm) = sb_norm_opt else { return Ok(false) };
|
||||
// Only handle known string methods here (receiver is confirmed string)
|
||||
match method {
|
||||
"length" => {
|
||||
let ret = sb_norm.length();
|
||||
|
||||
@ -120,7 +120,17 @@ pub fn seal_incomplete_phis_with<O: LoopPhiOps>(
|
||||
let value_after = ops
|
||||
.get_variable_at_block(&phi.var_name, latch_id)
|
||||
.ok_or_else(|| format!("Variable {} not found at latch block", phi.var_name))?;
|
||||
phi.known_inputs.push((latch_id, value_after));
|
||||
|
||||
// 🔧 ループ不変変数の自己参照PHI問題を修正
|
||||
// value_afterがPHI自身の場合(ループ内で変更されていない変数)は、
|
||||
// preheaderの値を使用する
|
||||
let latch_value = if value_after == phi.phi_id {
|
||||
// ループ不変変数:preheaderの値を使用
|
||||
phi.known_inputs[0].1 // preheaderからの初期値
|
||||
} else {
|
||||
value_after
|
||||
};
|
||||
phi.known_inputs.push((latch_id, latch_value));
|
||||
|
||||
ops.debug_verify_phi_inputs(block_id, &phi.known_inputs);
|
||||
ops.emit_phi_at_block_start(block_id, phi.phi_id, phi.known_inputs)?;
|
||||
|
||||
Reference in New Issue
Block a user