Files
hakorune/src/interpreter/expressions/access.rs
Moe Charm da96bcb906 📚 Phase 12.5 最適化戦略 & Phase 15 セルフホスティング計画
Phase 12.5: MIR15最適化戦略 - コンパイラ丸投げ作戦
- optimization-strategy.txt: 詳細戦略(MIR側は軽量、コンパイラに丸投げ)
- implementation-examples.md: 具体的な実装例
- debug-safety-comparison.md: 現在のDebugBox vs ChatGPT5提案の比較分析

Phase 15: Nyashセルフホスティング - 究極の目標
- self-hosting-plan.txt: 内蔵Craneliftによる実現計画
- technical-details.md: CompilerBox設計とブートストラップ手順
- README.md: セルフホスティングのビジョン

重要な知見:
- LLVM統合完了済み(Phase 11)だが依存が重すぎる
- Craneliftが現実的な選択肢(3-5MB vs LLVM 50-100MB)
- 「コンパイラもBox、すべてがBox」の夢へ

MASTERロードマップ更新済み
2025-09-02 05:11:10 +09:00

180 lines
8.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
* Field access operations
*/
// Removed super::* import - specific imports below
use crate::ast::ASTNode;
use crate::box_trait::{NyashBox, SharedNyashBox};
use crate::boxes::FutureBox;
use crate::instance_v2::InstanceBox;
use crate::interpreter::{NyashInterpreter, RuntimeError};
use std::sync::Arc;
// Conditional debug macro - only outputs if NYASH_DEBUG=1 environment variable is set
macro_rules! debug_trace {
($($arg:tt)*) => {
if std::env::var("NYASH_DEBUG").unwrap_or_default() == "1" {
eprintln!($($arg)*);
}
};
}
impl NyashInterpreter {
/// フィールドアクセスを実行 - Field access processing with weak reference support
pub(super) fn execute_field_access(&mut self, object: &ASTNode, field: &str)
-> Result<SharedNyashBox, RuntimeError> {
// 🔥 Static Boxアクセスチェック
if let ASTNode::Variable { name, .. } = object {
// Static boxの可能性をチェック
if self.is_static_box(name) {
let static_result = self.execute_static_field_access(name, field)?;
return Ok(Arc::from(static_result));
}
}
// 外からのフィールドアクセスかme/this以外を判定
let is_internal_access = match object {
ASTNode::This { .. } | ASTNode::Me { .. } => true,
ASTNode::Variable { name, .. } if name == "me" => true,
_ => false,
};
// オブジェクトを評価(通常のフィールドアクセス)
let obj_value = self.execute_expression(object);
let obj_value = obj_value?;
// InstanceBoxにキャスト
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
// 可視性チェック(互換性: public/privateのどちらかが定義されていれば強制
if !is_internal_access {
let box_decls = self.shared.box_declarations.read().unwrap();
if let Some(box_decl) = box_decls.get(&instance.class_name) {
let has_visibility = !box_decl.public_fields.is_empty() || !box_decl.private_fields.is_empty();
if has_visibility {
if !box_decl.public_fields.contains(&field.to_string()) {
return Err(RuntimeError::InvalidOperation {
message: format!("Field '{}' is private in {}", field, instance.class_name),
});
}
}
}
}
// 🔥 finiは何回呼ばれてもエラーにしないユーザー要求
// is_finalized()チェックを削除
// フィールドの値を取得
let field_value = instance.get_field(field)
.ok_or(RuntimeError::InvalidOperation {
message: format!("Field '{}' not found in {}", field, instance.class_name),
})?;
// 🔗 Weak Reference Check: Use unified accessor for weak fields
let box_decls = self.shared.box_declarations.read().unwrap();
if let Some(box_decl) = box_decls.get(&instance.class_name) {
if box_decl.weak_fields.contains(&field.to_string()) {
// 🎯 PHASE 2: Use unified accessor for auto-nil weak reference handling
if let Some(weak_value) = instance.get_weak_field(field, self) { // Pass self
match &weak_value {
crate::value::NyashValue::Null => {
debug_trace!("🔗 DEBUG: Weak field '{}' is null (reference dropped)", field);
// Return null box for compatibility
return Ok(Arc::new(crate::boxes::null_box::NullBox::new()));
}
_ => {
debug_trace!("🔗 DEBUG: Weak field '{}' still has valid reference", field);
// Convert back to Box<dyn NyashBox> for now
if let Ok(box_value) = weak_value.to_box() {
if let Ok(inner_box) = box_value.try_lock() {
return Ok(Arc::from(inner_box.clone_or_share()));
}
}
}
}
}
// If weak field access failed, fall through to normal access
}
}
// Return the shared Arc reference directly
Ok(field_value)
} else {
Err(RuntimeError::TypeError {
message: format!("Cannot access field '{}' on non-instance type. Type: {}", field, obj_value.type_name()),
})
}
}
/// 🔥 Static Box名前空間のフィールドアクセス
fn execute_static_field_access(&mut self, static_box_name: &str, field: &str)
-> Result<Box<dyn NyashBox>, RuntimeError> {
// 1. Static Boxの初期化を確実に実行
self.ensure_static_box_initialized(static_box_name)?;
// 2. GlobalBox.statics.{static_box_name} からインスタンスを取得
let global_box = self.shared.global_box.lock()
.map_err(|_| RuntimeError::RuntimeFailure {
message: "Failed to acquire global box lock".to_string()
})?;
let statics_box = global_box.get_field("statics")
.ok_or(RuntimeError::RuntimeFailure {
message: "statics namespace not found in GlobalBox".to_string()
})?;
let statics_instance = statics_box.as_any()
.downcast_ref::<InstanceBox>()
.ok_or(RuntimeError::TypeError {
message: "statics field is not an InstanceBox".to_string()
})?;
let static_box_instance = statics_instance.get_field(static_box_name)
.ok_or(RuntimeError::RuntimeFailure {
message: format!("Static box '{}' instance not found in statics namespace", static_box_name)
})?;
let instance = static_box_instance.as_any()
.downcast_ref::<InstanceBox>()
.ok_or(RuntimeError::TypeError {
message: format!("Static box '{}' is not an InstanceBox", static_box_name)
})?;
// 3. フィールドアクセス
let shared_field = instance.get_field(field)
.ok_or(RuntimeError::InvalidOperation {
message: format!("Field '{}' not found in static box '{}'", field, static_box_name),
})?;
// Convert Arc to Box for compatibility
Ok((*shared_field).clone_or_share())
}
/// await式を実行 - Execute await expression (Result.Ok/Err統一)
pub(super) fn execute_await(&mut self, expression: &ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
let value = self.execute_expression(expression)?;
if let Some(future) = value.as_any().downcast_ref::<FutureBox>() {
let max_ms: u64 = std::env::var("NYASH_AWAIT_MAX_MS").ok().and_then(|s| s.parse().ok()).unwrap_or(5000);
let start = std::time::Instant::now();
let mut spins = 0usize;
while !future.ready() {
crate::runtime::global_hooks::safepoint_and_poll();
std::thread::yield_now();
spins += 1;
if spins % 1024 == 0 { std::thread::sleep(std::time::Duration::from_millis(1)); }
if start.elapsed() >= std::time::Duration::from_millis(max_ms) {
let err = Box::new(crate::box_trait::StringBox::new("Timeout"));
return Ok(Box::new(crate::boxes::result::NyashResultBox::new_err(err)));
}
}
let v = future.get();
Ok(Box::new(crate::boxes::result::NyashResultBox::new_ok(v)))
} else {
Ok(Box::new(crate::boxes::result::NyashResultBox::new_ok(value)))
}
}
}