feat(phase285): Complete weak reference implementation (VM + LLVM harness)
Phase 285LLVM-1.1 to 1.4 + weak reference infrastructure: **LLVM Harness** (Phase 285LLVM-1.x): - 285LLVM-1.1: User Box registration & debug output - 285LLVM-1.2: WeakRef basic operations (identity deferred) - 285LLVM-1.3: InstanceBox field access (getField/setField) - 285LLVM-1.4: print Handle resolution (type tag propagation) **VM Runtime** (nyash_kernel): - FFI functions: nyrt_weak_new, nyrt_weak_to_strong, nyrt_weak_drop (crates/nyash_kernel/src/lib.rs: +209 lines) - WeakRef plugin invoke support (crates/nyash_kernel/src/plugin/invoke.rs: +250 lines) - weak_handles.rs: WeakRef handle registry (NEW) **LLVM Python Backend**: - WeakRef instruction lowering (weak.py: NEW) - Entry point integration (entry.py: +93 lines) - Instruction lowering (instruction_lower.py: +13 lines) - LLVM harness runner script (tools/run_llvm_harness.sh: NEW) **MIR & Runtime**: - WeakRef emission & validation - MIR JSON export for weak instructions - Environment variable support (NYASH_WEAK_*, HAKO_WEAK_*) **Documentation**: - CLAUDE.md: Phase 285 completion notes - LANGUAGE_REFERENCE_2025.md: Weak reference syntax - 10-Now.md & 30-Backlog.md: Phase 285 status updates Total: +864 lines, 24 files changed SSOT: docs/reference/language/lifecycle.md Related: Phase 285W-Syntax-0, Phase 285W-Syntax-0.1
This commit is contained in:
@ -238,6 +238,218 @@ fn nyash_plugin_invoke_name_common_i64(method: &str, argc: i64, a0: i64, a1: i64
|
||||
0
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// Phase 285LLVM-1.3: InstanceBox Field Access Helpers
|
||||
// ========================================================================
|
||||
|
||||
/// Helper: handle → String デコード
|
||||
///
|
||||
/// Phase 285LLVM-1.3: Fail-Fast error logging
|
||||
fn decode_handle_to_string(handle: i64) -> Result<String, String> {
|
||||
if handle <= 0 {
|
||||
return Err(format!("Invalid handle: {}", handle));
|
||||
}
|
||||
|
||||
let obj = nyash_rust::runtime::host_handles::get(handle as u64)
|
||||
.ok_or_else(|| format!("Handle {} not found", handle))?;
|
||||
|
||||
let sb = obj
|
||||
.as_any()
|
||||
.downcast_ref::<nyash_rust::box_trait::StringBox>()
|
||||
.ok_or_else(|| format!("Handle {} is not a StringBox", handle))?;
|
||||
|
||||
Ok(sb.value.clone())
|
||||
}
|
||||
|
||||
/// Helper: handle → NyashValue デコード(対応型のみ)
|
||||
///
|
||||
/// Phase 285LLVM-1.3: Integer/String/Bool のみ対応、未対応型は明示エラー
|
||||
fn decode_handle_to_nyash_value(handle: i64) -> Result<nyash_rust::value::NyashValue, String> {
|
||||
use nyash_rust::box_trait::{BoolBox, IntegerBox, StringBox};
|
||||
use nyash_rust::value::NyashValue;
|
||||
|
||||
if handle <= 0 {
|
||||
return Err(format!("Invalid handle: {}", handle));
|
||||
}
|
||||
|
||||
let obj = nyash_rust::runtime::host_handles::get(handle as u64)
|
||||
.ok_or_else(|| format!("Handle {} not found", handle))?;
|
||||
|
||||
// Integer
|
||||
if let Some(ib) = obj.as_any().downcast_ref::<IntegerBox>() {
|
||||
return Ok(NyashValue::Integer(ib.value));
|
||||
}
|
||||
|
||||
// String
|
||||
if let Some(sb) = obj.as_any().downcast_ref::<StringBox>() {
|
||||
return Ok(NyashValue::String(sb.value.clone()));
|
||||
}
|
||||
|
||||
// Bool
|
||||
if let Some(bb) = obj.as_any().downcast_ref::<BoolBox>() {
|
||||
return Ok(NyashValue::Bool(bb.value));
|
||||
}
|
||||
|
||||
// 未対応型: 明示的エラー(次フェーズで対応)
|
||||
Err(format!(
|
||||
"Unsupported Box type for handle {}: Phase 285LLVM-1.3 supports Integer/String/Bool only",
|
||||
handle
|
||||
))
|
||||
}
|
||||
|
||||
/// InstanceBox.getField(field_name) → i64 handle
|
||||
///
|
||||
/// Fail-Fast: エラーは明示的にログ出力して0返却
|
||||
fn handle_instance_get_field(inst: &nyash_rust::instance_v2::InstanceBox, field_handle: i64) -> i64 {
|
||||
use nyash_rust::box_trait::{BoolBox, IntegerBox, StringBox};
|
||||
use nyash_rust::value::NyashValue;
|
||||
use std::sync::Arc;
|
||||
|
||||
// 1. field_name デコード (既存ユーティリティ活用)
|
||||
let field_name = match decode_handle_to_string(field_handle) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
eprintln!(
|
||||
"[llvm/invoke/getField] Failed to decode field_name handle {}: {}",
|
||||
field_handle, e
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// 2. fields_ng から値を取得 (SSOT: get_field_ng のみ使用)
|
||||
let nv = match inst.get_field_ng(&field_name) {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
eprintln!(
|
||||
"[llvm/invoke/getField] Field '{}' not found in InstanceBox",
|
||||
field_name
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// 3. NyashValue → i64 handle 変換
|
||||
match nv {
|
||||
NyashValue::Integer(i) => {
|
||||
let arc: Arc<dyn nyash_rust::box_trait::NyashBox> = Arc::new(IntegerBox::new(i));
|
||||
let handle = nyash_rust::runtime::host_handles::to_handle_arc(arc) as i64;
|
||||
eprintln!("[llvm/invoke/getField] Returning Integer({}) as handle {}", i, handle);
|
||||
// Verify handle can be resolved back
|
||||
if let Some(obj) = nyash_rust::runtime::host_handles::get(handle as u64) {
|
||||
if let Some(ib) = obj.as_any().downcast_ref::<nyash_rust::box_trait::IntegerBox>() {
|
||||
eprintln!("[llvm/invoke/getField] ✅ Verified: handle {} resolves to IntegerBox({})", handle, ib.value);
|
||||
} else {
|
||||
eprintln!("[llvm/invoke/getField] ❌ ERROR: handle {} does not resolve to IntegerBox!", handle);
|
||||
}
|
||||
} else {
|
||||
eprintln!("[llvm/invoke/getField] ❌ ERROR: handle {} cannot be resolved!", handle);
|
||||
}
|
||||
handle
|
||||
}
|
||||
NyashValue::String(s) => {
|
||||
let arc: Arc<dyn nyash_rust::box_trait::NyashBox> = Arc::new(StringBox::new(s));
|
||||
nyash_rust::runtime::host_handles::to_handle_arc(arc) as i64
|
||||
}
|
||||
NyashValue::Bool(b) => {
|
||||
let arc: Arc<dyn nyash_rust::box_trait::NyashBox> = Arc::new(BoolBox::new(b));
|
||||
nyash_rust::runtime::host_handles::to_handle_arc(arc) as i64
|
||||
}
|
||||
NyashValue::Null | NyashValue::Void => 0,
|
||||
|
||||
// 未対応型: 明示的エラー(次フェーズで対応)
|
||||
NyashValue::Float(_) => {
|
||||
eprintln!(
|
||||
"[llvm/invoke/getField] Unsupported type: Float (field: {})",
|
||||
field_name
|
||||
);
|
||||
0
|
||||
}
|
||||
NyashValue::Array(_) => {
|
||||
eprintln!(
|
||||
"[llvm/invoke/getField] Unsupported type: Array (field: {})",
|
||||
field_name
|
||||
);
|
||||
0
|
||||
}
|
||||
NyashValue::Map(_) => {
|
||||
eprintln!(
|
||||
"[llvm/invoke/getField] Unsupported type: Map (field: {})",
|
||||
field_name
|
||||
);
|
||||
0
|
||||
}
|
||||
NyashValue::Box(_) => {
|
||||
eprintln!(
|
||||
"[llvm/invoke/getField] Unsupported type: Box (field: {})",
|
||||
field_name
|
||||
);
|
||||
0
|
||||
}
|
||||
NyashValue::WeakBox(_) => {
|
||||
eprintln!(
|
||||
"[llvm/invoke/getField] Unsupported type: WeakBox (field: {})",
|
||||
field_name
|
||||
);
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// InstanceBox.setField(field_name, value) → 1 (success) or 0 (failure)
|
||||
///
|
||||
/// Fail-Fast: エラーは明示的にログ出力して0返却
|
||||
fn handle_instance_set_field(
|
||||
inst: &nyash_rust::instance_v2::InstanceBox,
|
||||
field_handle: i64,
|
||||
value_handle: i64,
|
||||
) -> i64 {
|
||||
use nyash_rust::value::NyashValue;
|
||||
|
||||
// 1. field_name デコード (既存ユーティリティ活用)
|
||||
let field_name = match decode_handle_to_string(field_handle) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
eprintln!(
|
||||
"[llvm/invoke/setField] Failed to decode field_name handle {}: {}",
|
||||
field_handle, e
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// 2. value handle → NyashValue 変換
|
||||
// LLVM backend では i64 値がそのまま渡される場合がある(handle ではなく生の値)
|
||||
let nv = if value_handle == 0 {
|
||||
NyashValue::Null
|
||||
} else {
|
||||
// まず handle として解決を試みる
|
||||
match decode_handle_to_nyash_value(value_handle) {
|
||||
Ok(v) => v,
|
||||
Err(_) => {
|
||||
// handle でない場合は、i64 値として直接扱う(LLVM backend の挙動)
|
||||
eprintln!(
|
||||
"[llvm/invoke/setField] Handle {} not found for field '{}', treating as raw i64 value",
|
||||
value_handle, field_name
|
||||
);
|
||||
NyashValue::Integer(value_handle)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 3. fields_ng に設定 (SSOT: set_field_ng のみ使用)
|
||||
match inst.set_field_ng(field_name.clone(), nv) {
|
||||
Ok(_) => 1, // 成功
|
||||
Err(e) => {
|
||||
eprintln!(
|
||||
"[llvm/invoke/setField] Failed to set field '{}': {}",
|
||||
field_name, e
|
||||
);
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// General by-name invoke: (recv_handle, method_cstr, argc, a1, a2) -> i64
|
||||
// Export name: nyash.plugin.invoke_by_name_i64
|
||||
#[export_name = "nyash.plugin.invoke_by_name_i64"]
|
||||
@ -255,7 +467,12 @@ pub extern "C" fn nyash_plugin_invoke_by_name_i64(
|
||||
let Ok(method_str) = mname.to_str() else {
|
||||
return 0;
|
||||
};
|
||||
|
||||
// 🔍 DEBUG: Trace function entry
|
||||
eprintln!("[llvm/invoke/DEBUG] Called with recv_handle={}, method={}, argc={}", recv_handle, method_str, argc);
|
||||
|
||||
use nyash_rust::runtime::plugin_loader_v2::PluginBoxV2;
|
||||
use nyash_rust::instance_v2::InstanceBox;
|
||||
let mut instance_id: u32 = 0;
|
||||
let mut type_id: u32 = 0;
|
||||
let mut box_type: Option<String> = None;
|
||||
@ -264,13 +481,46 @@ pub extern "C" fn nyash_plugin_invoke_by_name_i64(
|
||||
> = None;
|
||||
if recv_handle > 0 {
|
||||
if let Some(obj) = nyash_rust::runtime::host_handles::get(recv_handle as u64) {
|
||||
eprintln!("[llvm/invoke/DEBUG] Handle {} resolved successfully", recv_handle);
|
||||
|
||||
// 🔥 Phase 285LLVM-1.3: InstanceBox 専用処理(優先)
|
||||
if let Some(inst) = obj.as_any().downcast_ref::<InstanceBox>() {
|
||||
eprintln!("[llvm/invoke/DEBUG] ✅ InstanceBox downcast SUCCESS, method={}", method_str);
|
||||
match method_str {
|
||||
"getField" => {
|
||||
return handle_instance_get_field(inst, a1);
|
||||
}
|
||||
"setField" => {
|
||||
return handle_instance_set_field(inst, a1, a2);
|
||||
}
|
||||
_ => {
|
||||
// getField/setField 以外はエラー
|
||||
eprintln!(
|
||||
"[llvm/invoke] Unsupported InstanceBox method: {}",
|
||||
method_str
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eprintln!("[llvm/invoke/DEBUG] ❌ InstanceBox downcast FAILED, trying PluginBoxV2...");
|
||||
}
|
||||
|
||||
// 既存の PluginBoxV2 処理(変更なし)
|
||||
if let Some(p) = obj.as_any().downcast_ref::<PluginBoxV2>() {
|
||||
eprintln!("[llvm/invoke/DEBUG] ✅ PluginBoxV2 downcast SUCCESS");
|
||||
instance_id = p.instance_id();
|
||||
type_id = p.inner.type_id;
|
||||
box_type = Some(p.box_type.clone());
|
||||
invoke = Some(p.inner.invoke_fn);
|
||||
} else {
|
||||
eprintln!("[llvm/invoke/DEBUG] ❌ PluginBoxV2 downcast FAILED");
|
||||
}
|
||||
} else {
|
||||
eprintln!("[llvm/invoke/DEBUG] ❌ Handle {} NOT found in host_handles", recv_handle);
|
||||
}
|
||||
} else {
|
||||
eprintln!("[llvm/invoke/DEBUG] ❌ recv_handle <= 0");
|
||||
}
|
||||
if invoke.is_none() {
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user