Fix MIR builder me-call recursion and add compile tracing
This commit is contained in:
@ -15,7 +15,7 @@ impl MirInterpreter {
|
||||
) -> Result<VMValue, VMError> {
|
||||
// Safety valve: cap nested exec_function_inner depth to avoid Rust stack overflow
|
||||
// on accidental infinite recursion in MIR (e.g., self-recursive call chains).
|
||||
const MAX_CALL_DEPTH: usize = 1024;
|
||||
const MAX_CALL_DEPTH: usize = 128;
|
||||
self.call_depth = self.call_depth.saturating_add(1);
|
||||
if self.call_depth > MAX_CALL_DEPTH {
|
||||
eprintln!(
|
||||
|
||||
12
src/main.rs
12
src/main.rs
@ -9,6 +9,18 @@ use nyash_rust::runner::NyashRunner;
|
||||
|
||||
/// Thin entry point - delegates to CLI parsing and runner execution
|
||||
fn main() {
|
||||
// Optional: enable backtrace on stack overflow for deep debug runs.
|
||||
// Guarded by env to keep default behavior unchanged.
|
||||
if std::env::var("NYASH_DEBUG_STACK_OVERFLOW")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1")
|
||||
{
|
||||
unsafe {
|
||||
let _ = backtrace_on_stack_overflow::enable();
|
||||
}
|
||||
}
|
||||
|
||||
// hv1 direct (primary): earliest possible check before any bootstrap/log init
|
||||
// If NYASH_VERIFY_JSON is present and route is requested, execute and exit.
|
||||
// This avoids plugin host/registry initialization and keeps output minimal.
|
||||
|
||||
@ -314,6 +314,24 @@ impl MirBuilder {
|
||||
self.debug_scope_stack.last().cloned()
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// Compile trace helpers (dev only; env-gated)
|
||||
// ----------------------
|
||||
#[inline]
|
||||
pub(super) fn compile_trace_enabled() -> bool {
|
||||
std::env::var("NYASH_MIR_COMPILE_TRACE")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn trace_compile<S: AsRef<str>>(&self, msg: S) {
|
||||
if Self::compile_trace_enabled() {
|
||||
eprintln!("[mir-compile] {}", msg.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// Method tail index (performance helper)
|
||||
// ----------------------
|
||||
|
||||
@ -400,12 +400,7 @@ impl MirBuilder {
|
||||
method: &str,
|
||||
arguments: &[ASTNode],
|
||||
) -> Result<Option<ValueId>, String> {
|
||||
// 3-a) Static box fast path
|
||||
if let Some(res) = self.handle_me_method_call(method, arguments)? {
|
||||
return Ok(Some(res));
|
||||
}
|
||||
|
||||
// 3-b) Instance box: prefer enclosing box method
|
||||
// Instance box: prefer enclosing box method
|
||||
let enclosing_cls: Option<String> = self
|
||||
.current_function
|
||||
.as_ref()
|
||||
|
||||
@ -87,6 +87,8 @@ impl super::MirBuilder {
|
||||
if name == "Main" {
|
||||
main_static = Some((name.clone(), methods.clone()));
|
||||
} else {
|
||||
// Dev: trace which static box is being lowered (env-gated)
|
||||
self.trace_compile(format!("lower static box {}", name));
|
||||
// 🎯 箱理論: 各static boxに専用のコンパイルコンテキストを作成
|
||||
// これにより、using文や前のboxからのメタデータ汚染を構造的に防止
|
||||
// スコープを抜けると自動的にコンテキストが破棄される
|
||||
@ -99,17 +101,17 @@ impl super::MirBuilder {
|
||||
if let N::FunctionDeclaration { params, body, .. } = mast {
|
||||
let func_name = format!("{}.{}{}", name, mname, format!("/{}", params.len()));
|
||||
self.lower_static_method_as_function(func_name, params.clone(), body.clone())?;
|
||||
self.static_method_index
|
||||
.entry(mname.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push((name.clone(), params.len()));
|
||||
self.static_method_index
|
||||
.entry(mname.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push((name.clone(), params.len()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 🎯 箱理論: コンテキストをクリア(スコープ終了で自動破棄)
|
||||
// これにより、次のstatic boxは汚染されていない状態から開始される
|
||||
self.compilation_context = None;
|
||||
}
|
||||
// 🎯 箱理論: コンテキストをクリア(スコープ終了で自動破棄)
|
||||
// これにより、次のstatic boxは汚染されていない状態から開始される
|
||||
self.compilation_context = None;
|
||||
}
|
||||
} else {
|
||||
// Instance box: register type and lower instance methods/ctors as functions
|
||||
|
||||
Reference in New Issue
Block a user