Phase 10.10: GC Switchable Runtime & Unified Debug System 実装完了

Phase 10.10の主要実装:
- GcConfigBox: GC設定の実行時制御(counting/trace/barrier_strict)
- DebugConfigBox: デバッグ設定の統一管理(JIT events/stats/dump/dot)
- メソッドディスパッチ: system_methods.rsで両Boxのメソッド実装
- CountingGC動作確認: write_barriers正常カウント(VM実行時)

技術的詳細:
- BoxCore/BoxBase統一アーキテクチャを活用
- setFlag/getFlag/apply/summaryメソッドで統一API提供
- 環境変数経由でVM/JITランタイムと連携
- GcConfigBox.apply()は次回実行から有効(ランタイム作成前に環境変数参照)

テスト済み:
- examples/gc_counting_demo.nyash: CountingGCの動作確認
- write_barriers=3でArray.push/set, Map.setを正しくカウント
- NYASH_GC_TRACE=1でGC統計出力確認

Box-First哲学の体現: 設定も制御も観測もすべてBox!

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-28 22:31:51 +09:00
parent 4e1b595796
commit d67f27f4b8
27 changed files with 1341 additions and 63 deletions

View File

@ -0,0 +1,171 @@
/*!
* System Methods Module
*
* Contains system-level Box type method implementations:
* - GcConfigBox: Garbage collector configuration
* - DebugConfigBox: Debug and observability configuration
*/
use crate::ast::ASTNode;
use crate::box_trait::{NyashBox, VoidBox, StringBox, BoolBox};
use crate::boxes::gc_config_box::GcConfigBox;
use crate::boxes::debug_config_box::DebugConfigBox;
use crate::interpreter::{NyashInterpreter, RuntimeError};
impl NyashInterpreter {
/// Execute GcConfigBox methods
pub(crate) fn execute_gc_config_method(
&mut self,
gc_box: &GcConfigBox,
method: &str,
arguments: &[ASTNode],
) -> Result<Box<dyn NyashBox>, RuntimeError> {
match method {
"setFlag" => {
if arguments.len() != 2 {
return Err(RuntimeError::InvalidOperation {
message: format!("GcConfigBox.setFlag expects 2 arguments, got {}", arguments.len()),
});
}
let name = self.execute_expression(&arguments[0])?;
let on = self.execute_expression(&arguments[1])?;
let name_str = name.to_string_box().value;
let on_bool = if let Some(b) = on.as_any().downcast_ref::<BoolBox>() {
b.value
} else {
on.to_string_box().value.to_lowercase() == "true"
};
let mut gc_clone = gc_box.clone();
gc_clone.set_flag(&name_str, on_bool);
Ok(Box::new(gc_clone))
}
"getFlag" => {
if arguments.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("GcConfigBox.getFlag expects 1 argument, got {}", arguments.len()),
});
}
let name = self.execute_expression(&arguments[0])?;
let name_str = name.to_string_box().value;
Ok(gc_box.get_flag(&name_str))
}
"apply" => {
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("GcConfigBox.apply expects 0 arguments, got {}", arguments.len()),
});
}
Ok(gc_box.apply())
}
"summary" => {
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("GcConfigBox.summary expects 0 arguments, got {}", arguments.len()),
});
}
Ok(gc_box.summary())
}
_ => Err(RuntimeError::InvalidOperation {
message: format!("GcConfigBox has no method '{}'", method),
}),
}
}
/// Execute DebugConfigBox methods
pub(crate) fn execute_debug_config_method(
&mut self,
debug_box: &DebugConfigBox,
method: &str,
arguments: &[ASTNode],
) -> Result<Box<dyn NyashBox>, RuntimeError> {
match method {
"setFlag" => {
if arguments.len() != 2 {
return Err(RuntimeError::InvalidOperation {
message: format!("DebugConfigBox.setFlag expects 2 arguments, got {}", arguments.len()),
});
}
let name = self.execute_expression(&arguments[0])?;
let on = self.execute_expression(&arguments[1])?;
let name_str = name.to_string_box().value;
let on_bool = if let Some(b) = on.as_any().downcast_ref::<BoolBox>() {
b.value
} else {
on.to_string_box().value.to_lowercase() == "true"
};
let mut debug_clone = debug_box.clone();
debug_clone.set_flag(&name_str, on_bool);
Ok(Box::new(debug_clone))
}
"setPath" => {
if arguments.len() != 2 {
return Err(RuntimeError::InvalidOperation {
message: format!("DebugConfigBox.setPath expects 2 arguments, got {}", arguments.len()),
});
}
let name = self.execute_expression(&arguments[0])?;
let path = self.execute_expression(&arguments[1])?;
let name_str = name.to_string_box().value;
let path_str = path.to_string_box().value;
let mut debug_clone = debug_box.clone();
debug_clone.set_path(&name_str, &path_str);
Ok(Box::new(debug_clone))
}
"getFlag" => {
if arguments.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("DebugConfigBox.getFlag expects 1 argument, got {}", arguments.len()),
});
}
let name = self.execute_expression(&arguments[0])?;
let name_str = name.to_string_box().value;
Ok(debug_box.get_flag(&name_str))
}
"getPath" => {
if arguments.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("DebugConfigBox.getPath expects 1 argument, got {}", arguments.len()),
});
}
let name = self.execute_expression(&arguments[0])?;
let name_str = name.to_string_box().value;
Ok(debug_box.get_path(&name_str))
}
"apply" => {
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("DebugConfigBox.apply expects 0 arguments, got {}", arguments.len()),
});
}
Ok(debug_box.apply())
}
"summary" => {
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("DebugConfigBox.summary expects 0 arguments, got {}", arguments.len()),
});
}
Ok(debug_box.summary())
}
_ => Err(RuntimeError::InvalidOperation {
message: format!("DebugConfigBox has no method '{}'", method),
}),
}
}
}