diff --git a/src/bin/ast.rs b/src/bin/ast.rs index 2786a16..7c7d0b6 100644 --- a/src/bin/ast.rs +++ b/src/bin/ast.rs @@ -26,11 +26,15 @@ struct Cli { /// Dump the compiled AST #[arg(short, long)] dump: bool, + + /// Run with TracingObserver enabled + #[arg(short, long)] + trace: bool, } fn main() { let cli = Cli::parse(); - let env = Environment::new(); + let mut env = Environment::new(); if cli.bench || cli.update_bench { if cfg!(debug_assertions) { @@ -54,6 +58,8 @@ fn main() { Ok(dump) => println!("{}", dump), Err(e) => eprintln!("Error dumping AST: {}", e), } + } else if cli.trace { + execute_trace(&mut env, &script_str); } else { execute(&env, &script_str); } @@ -65,6 +71,8 @@ fn main() { Ok(dump) => println!("{}", dump), Err(e) => eprintln!("Error dumping AST: {}", e), } + } else if cli.trace { + execute_trace(&mut env, &content); } else { execute(&env, &content); } @@ -88,3 +96,32 @@ fn execute(env: &Environment, source: &str) { } } } + +fn execute_trace(env: &mut Environment, source: &str) { + match env.compile(source) { + Ok(compiled) => { + let linked = env.link(compiled); + let mut vm = myc::ast::vm::VM::new(env.global_values.clone()); + let mut observer = myc::ast::vm::TracingObserver::new(); + match vm.run_with_observer(&mut observer, &linked) { + Ok(result) => { + for line in observer.logs { + println!("{}", line); + } + println!("Result: {}", result); + } + Err(e) => { + for line in observer.logs { + println!("{}", line); + } + eprintln!("Runtime Error: {}", e); + std::process::exit(1); + } + } + } + Err(e) => { + eprintln!("Compilation Error: {}", e); + std::process::exit(1); + } + } +} diff --git a/src/main.rs b/src/main.rs index 66c519d..520fc7c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -96,29 +96,19 @@ impl CompilerApp { // Reset environment for a fresh run self.env = Environment::new(); - let res = (|| -> Result<(myc::ast::types::Value, std::time::Duration, std::time::Duration, std::time::Duration), String> { - let start_compile = std::time::Instant::now(); - let compiled = self.env.compile(&self.source_code)?; - let duration_compile = start_compile.elapsed(); - - let start_link = std::time::Instant::now(); - let linked = self.env.link(compiled); - let duration_link = start_link.elapsed(); - + let res = (|| -> Result<(myc::ast::types::Value, std::time::Duration), String> { let start_run = std::time::Instant::now(); let result = if self.debug_enabled { - let mut vm = myc::ast::vm::VM::new(self.env.global_values.clone()); - let mut observer = myc::ast::vm::TracingObserver::new(); - let res = vm.run_with_observer(&mut observer, &linked); - - // Batch-truncate logs for GUI performance (once after execution) - let mut logs = observer.logs; - if logs.len() > 1000 { - logs.truncate(1000); - logs.push("... [Trace truncated to 1,000 entries] ...".to_string()); + let (res, logs) = self.env.run_debug(&self.source_code)?; + + // Batch-truncate logs for GUI performance + let mut display_logs = logs; + if display_logs.len() > 1000 { + display_logs.truncate(1000); + display_logs.push("... [Trace truncated to 1,000 entries] ...".to_string()); } - for line in &mut logs { + for line in &mut display_logs { if line.len() > 255 && let Some((idx, _)) = line.char_indices().nth(255) { line.truncate(idx); @@ -126,25 +116,32 @@ impl CompilerApp { } } - self.trace_logs = logs; + self.trace_logs = display_logs; self.active_tab = AppTab::Trace; res? } else { - self.env.run(&linked)? + self.env.run_script(&self.source_code)? }; let duration_run = start_run.elapsed(); - Ok((result, duration_compile, duration_link, duration_run)) + Ok((result, duration_run)) })(); match res { - Ok((val, d_compile, d_link, d_run)) => { + Ok((val, d_run)) => { let d_total = start_total.elapsed(); let now = chrono::Local::now().format("%H:%M:%S").to_string(); - self.output_log = format!( - "Execution Successful.\nResult: {}\n\nPhases:\n - Compile: {:?}\n - Link: {:?}\n - Run: {:?}\n\nTotal Duration: {:?}\nFinished at: {}", - val, d_compile, d_link, d_run, d_total, now, + + let mut stats = format!( + "Execution Successful.\nResult: {}\n\nTotal Duration: {:?}\nFinished at: {}", + val, d_total, now, ); + + if !self.debug_enabled { + stats.push_str(&format!("\nRun Phase: {:?}", d_run)); + } + + self.output_log = stats; if !self.debug_enabled { self.active_tab = AppTab::Output; }