Files
hakorune/src/tests/identical_exec_instance.rs

176 lines
5.8 KiB
Rust
Raw Normal View History

#[cfg(all(test, not(feature = "jit-direct-only")))]
mod tests {
use std::collections::HashMap;
use crate::box_factory::RuntimeError;
use crate::box_trait::NyashBox;
use crate::mir::{
BasicBlockId, ConstValue, EffectMask, FunctionSignature, MirFunction, MirInstruction,
MirModule, MirType,
};
// Minimal Person factory: creates InstanceBox with fields [name, age]
struct PersonFactory;
impl crate::box_factory::BoxFactory for PersonFactory {
fn create_box(
&self,
name: &str,
_args: &[Box<dyn NyashBox>],
) -> Result<Box<dyn NyashBox>, RuntimeError> {
if name != "Person" {
return Err(RuntimeError::InvalidOperation {
message: format!("Unknown Box type: {}", name),
});
}
let fields = vec!["name".to_string(), "age".to_string()];
let methods: HashMap<String, crate::ast::ASTNode> = HashMap::new();
let inst = crate::instance_v2::InstanceBox::from_declaration(
"Person".to_string(),
fields,
methods,
);
Ok(Box::new(inst))
}
fn box_types(&self) -> Vec<&str> {
vec!["Person"]
}
fn is_builtin_factory(&self) -> bool {
true
}
}
fn build_person_module() -> MirModule {
let mut module = MirModule::new("identical_person".to_string());
let sig = FunctionSignature {
name: "main".into(),
params: vec![],
return_type: MirType::String,
effects: EffectMask::PURE,
};
let mut f = MirFunction::new(sig, BasicBlockId::new(0));
let bb = f.entry_block;
let person = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::NewBox {
dst: person,
box_type: "Person".into(),
args: vec![],
});
// person.setField("name", "Alice")
let k_name = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: k_name,
value: ConstValue::String("name".into()),
});
let v_alice = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: v_alice,
value: ConstValue::String("Alice".into()),
});
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BoxCall {
dst: None,
box_val: person,
method: "setField".into(),
args: vec![k_name, v_alice],
method_id: None,
effects: EffectMask::PURE,
});
// person.setField("age", 25)
let k_age = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: k_age,
value: ConstValue::String("age".into()),
});
let v_25 = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: v_25,
value: ConstValue::Integer(25),
});
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BoxCall {
dst: None,
box_val: person,
method: "setField".into(),
args: vec![k_age, v_25],
method_id: None,
effects: EffectMask::PURE,
});
// name = person.getField("name"); return name
let k_name2 = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: k_name2,
value: ConstValue::String("name".into()),
});
let out_name = f.next_value_id();
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::BoxCall {
dst: Some(out_name),
box_val: person,
method: "getField".into(),
args: vec![k_name2],
method_id: None,
effects: EffectMask::PURE,
});
f.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Return {
value: Some(out_name),
});
module.add_function(f);
module
}
#[cfg(feature = "cranelift-jit")]
#[test]
#[ignore = "ABI_STRICT vtable path diverges; JIT host-bridge parity pending"]
fn identical_vm_and_jit_person_get_set_slots() {
// Build runtime with Person factory
let mut rt_builder = crate::runtime::NyashRuntimeBuilder::new();
rt_builder = rt_builder.with_factory(Arc::new(PersonFactory));
let runtime = rt_builder.build();
// Also register factory globally for JIT path (host-bridge creates via global registry)
crate::runtime::register_user_defined_factory(Arc::new(PersonFactory));
// Build module
let module = build_person_module();
// VM (VTABLE on)
std::env::set_var("NYASH_ABI_VTABLE", "1");
feat(mir/builder): implement BoxCompilationContext for structural metadata isolation 箱理論の完璧な実装!各static boxコンパイルを独立したコンテキストで実行。 設計: - BoxCompilationContext: variable_map, value_origin_newbox, value_types を箱化 - MirBuilder: compilation_context: Option<BoxCompilationContext> フィールド追加 - context swap: lower_static_method_as_function 開始/終了時に std::mem::swap - 自動クリーンアップ: スコープ終了でコンテキスト破棄 実装: 1. src/mir/builder/context.rs: BoxCompilationContext構造体定義(テスト付き) 2. src/mir/builder.rs: compilation_contextフィールド追加、既存フィールドにコメント追加 3. src/mir/builder/lifecycle.rs: 各static boxでコンテキスト作成・破棄 4. src/mir/builder/builder_calls.rs: lower_static_method_as_functionでcontext swap 5. src/mir/builder/decls.rs, exprs.rs: 古いmanual clear()削除 効果: ✅ グローバル状態汚染を構造的に不可能化 ✅ 各static boxが完全に独立したコンテキストでコンパイル ✅ 既存コード変更なし(swap技法で完全後方互換性) ✅ StageBArgsBox ValueId(21)エラー完全解決 箱理論的評価: 🟢 95点 - 明示的な境界: 各boxのコンテキストが物理的に分離 - 汚染不可能: 前の箱の状態が構造的に残らない - 戻せる: コンテキスト差し替えで簡単ロールバック - 美しい設計: スコープベースのリソース管理 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 11:28:18 +09:00
let mut vm = VM::new();
let vm_out = vm.execute_module(&module).expect("VM exec");
let vm_s = vm_out.to_string_box().value;
// JIThost-bridge on
std::env::set_var("NYASH_JIT_HOST_BRIDGE", "1");
let jit_out = crate::backend::cranelift_compile_and_execute(&module, "identical_person")
.expect("JIT exec");
let jit_s = jit_out.to_string_box().value;
assert_eq!(vm_s, jit_s);
assert_eq!(vm_s, "Alice");
}
}