diff --git a/cli/src/commands/doc.rs b/cli/src/commands/doc.rs index 699b52ec..cc745036 100644 --- a/cli/src/commands/doc.rs +++ b/cli/src/commands/doc.rs @@ -4,6 +4,7 @@ use crate::artifacts::ArtifactManager; use crate::exit_code::ExitCode; +use std::fmt::Write; use std::path::{Path, PathBuf}; use techscript_package_manager::DocExtractor; @@ -55,14 +56,15 @@ pub fn execute(path_str: Option<&str>) -> ExitCode { // Build structured output let mut md_content = String::new(); - md_content.push_str(&format!( + let _ = write!( + md_content, "# API Documentation — {}\n\n", path.file_name().unwrap_or_default().to_string_lossy() - )); + ); for item in &doc_items { - md_content.push_str(&format!("## {}\n\n", item.name)); - md_content.push_str(&format!("{}\n\n", item.doc)); + let _ = write!(md_content, "## {}\n\n", item.name); + let _ = write!(md_content, "{}\n\n", item.doc); md_content.push_str("---\n\n"); } diff --git a/cli/src/commands/migrate.rs b/cli/src/commands/migrate.rs index 292592b6..39348147 100644 --- a/cli/src/commands/migrate.rs +++ b/cli/src/commands/migrate.rs @@ -3,6 +3,7 @@ //! Automatically migrates legacy TechScript 1.0.8 code to TechScript 2.0 canonical syntax. use crate::exit_code::ExitCode; +use std::fmt::Write; use std::path::PathBuf; pub fn execute(path_str: Option<&str>) -> ExitCode { @@ -263,7 +264,7 @@ fn replace_call(source: &str, prefix: &str, keyword: &str) -> String { remaining = &remaining[pos + full.len()..]; if let Some(close) = remaining.find(')') { let args = &remaining[..close]; - result.push_str(&format!("{keyword} {args}")); + let _ = write!(result, "{keyword} {args}"); remaining = &remaining[close + 1..]; } else { result.push_str(remaining); diff --git a/cli/src/crash.rs b/cli/src/crash.rs index d62a71a2..6aabc953 100644 --- a/cli/src/crash.rs +++ b/cli/src/crash.rs @@ -4,6 +4,7 @@ //! and write structured crash reports. use crate::exit_code::ExitCode; +use std::fmt::Write; use std::panic; use std::path::{Path, PathBuf}; use std::time::SystemTime; @@ -33,12 +34,12 @@ impl CrashReport { out.push_str( "================================================================================\n", ); - out.push_str(&format!("Compiler Version: {}\n", self.compiler_version)); - out.push_str(&format!("CLI Command: {}\n", self.command)); - out.push_str(&format!("Timestamp: {}\n", self.timestamp)); - out.push_str(&format!("OS Info: {}\n", self.os_info)); + let _ = write!(out, "Compiler Version: {}\n", self.compiler_version); + let _ = write!(out, "CLI Command: {}\n", self.command); + let _ = write!(out, "Timestamp: {}\n", self.timestamp); + let _ = write!(out, "OS Info: {}\n", self.os_info); if let Some(file) = &self.source_file { - out.push_str(&format!("Active File: {}\n", file)); + let _ = write!(out, "Active File: {}\n", file); } out.push_str( "--------------------------------------------------------------------------------\n", diff --git a/cli/src/diagnostics.rs b/cli/src/diagnostics.rs index 0a5c0b36..a199fcef 100644 --- a/cli/src/diagnostics.rs +++ b/cli/src/diagnostics.rs @@ -5,6 +5,7 @@ //! and accumulates post-compilation statistics. use colored::Colorize; +use std::fmt::Write; use std::sync::Arc; use std::time::Duration; @@ -229,29 +230,32 @@ impl<'a> DiagnosticRenderer<'a> { if self.output == DiagnosticOutput::Colored { if header.is_empty() { - out.push_str(&format!( + let _ = write!( + out, "{}: {}\n", diag.severity.colored_label(), diag.message.bold() - )); + ); } else { - out.push_str(&format!( + let _ = write!( + out, "{}[{}]: {}\n", diag.severity.colored_label(), header.white(), diag.message.bold() - )); + ); } } else { if header.is_empty() { - out.push_str(&format!("{}: {}\n", diag.severity.label(), diag.message)); + let _ = write!(out, "{}: {}\n", diag.severity.label(), diag.message); } else { - out.push_str(&format!( + let _ = write!( + out, "{}[{}]: {}\n", diag.severity.label(), header, diag.message - )); + ); } } @@ -262,9 +266,9 @@ impl<'a> DiagnosticRenderer<'a> { let file_ref = format!(" --> {}:{}:{}", file.path().display(), line, col); if self.output == DiagnosticOutput::Colored { - out.push_str(&format!("{}\n", file_ref.cyan())); + let _ = write!(out, "{}\n", file_ref.cyan()); } else { - out.push_str(&format!("{}\n", file_ref)); + let _ = write!(out, "{}\n", file_ref); } // Source line @@ -272,16 +276,11 @@ impl<'a> DiagnosticRenderer<'a> { let line_num = format!("{:>4}", line); let bar = "|"; if self.output == DiagnosticOutput::Colored { - out.push_str(&format!("{} {}\n", line_num.cyan(), bar.cyan())); - out.push_str(&format!( - "{} {} {}\n", - line_num.cyan(), - bar.cyan(), - line_text - )); + let _ = write!(out, "{} {}\n", line_num.cyan(), bar.cyan()); + let _ = write!(out, "{} {} {}\n", line_num.cyan(), bar.cyan(), line_text); } else { - out.push_str(&format!("{} {}\n", line_num, bar)); - out.push_str(&format!("{} {} {}\n", line_num, bar, line_text)); + let _ = write!(out, "{} {}\n", line_num, bar); + let _ = write!(out, "{} {} {}\n", line_num, bar, line_text); } // Caret underline — Unicode-safe (count chars, not bytes) @@ -298,13 +297,9 @@ impl<'a> DiagnosticRenderer<'a> { format!("{}{}", spaces, carets) }; if self.output == DiagnosticOutput::Colored { - out.push_str(&format!( - " {} {}\n", - bar.cyan(), - caret_line.red().bold() - )); + let _ = write!(out, " {} {}\n", bar.cyan(), caret_line.red().bold()); } else { - out.push_str(&format!(" {} {}\n", bar, caret_line)); + let _ = write!(out, " {} {}\n", bar, caret_line); } } } @@ -313,41 +308,41 @@ impl<'a> DiagnosticRenderer<'a> { // Related diagnostics (help, notes) for related in &diag.related { if self.output == DiagnosticOutput::Colored { - out.push_str(&format!( + let _ = write!( + out, " {}: {}\n", related.severity.colored_label(), related.message - )); + ); } else { - out.push_str(&format!( - " {}: {}\n", - related.severity.label(), - related.message - )); + let _ = write!(out, " {}: {}\n", related.severity.label(), related.message); } } // Fix suggestions for suggestion in &diag.suggestions { if self.output == DiagnosticOutput::Colored { - out.push_str(&format!( + let _ = write!( + out, " {}: {} → `{}`\n", "suggestion".green().bold(), suggestion.message, suggestion.replacement.green() - )); + ); } else { - out.push_str(&format!( + let _ = write!( + out, " suggestion: {} → `{}`\n", suggestion.message, suggestion.replacement - )); + ); } } // Documentation link if code is present if let Some(code) = diag.code { if self.output == DiagnosticOutput::Colored { - out.push_str(&format!( + let _ = write!( + out, " {}: For more details see: {}\n", "note".cyan().bold(), format!( @@ -355,12 +350,12 @@ impl<'a> DiagnosticRenderer<'a> { code ) .underline() - )); + ); } else { - out.push_str(&format!( + let _ = write!(out, " note: For more details see: https://github.com/Tcode-Motion/techscript/blob/main/docs/errors.md#{:?}\n", code - )); + ); } } diff --git a/cli/src/profiler.rs b/cli/src/profiler.rs index 9ed94e13..3420bd31 100644 --- a/cli/src/profiler.rs +++ b/cli/src/profiler.rs @@ -4,6 +4,7 @@ //! The `TimingProfiler` is an `EventListener` so it receives events //! automatically from the compilation pipeline. +use std::fmt::Write; use std::time::{Duration, Instant}; use colored::Colorize; @@ -97,75 +98,81 @@ impl TimingProfiler { let total: Duration = self.stages.iter().map(|s| s.duration).sum(); let mut out = String::new(); - out.push_str(&format!( + let _ = write!( + out, "{}\n", "─── Compilation Timings ────────────────────────────────".dimmed() - )); - out.push_str(&format!( + ); + let _ = write!( + out, "{:<24} {:>10} {}\n", "Stage".bold(), "Duration".bold(), "Items".bold() - )); - out.push_str(&format!("{}\n", "─".repeat(50).dimmed())); + ); + let _ = write!(out, "{}\n", "─".repeat(50).dimmed()); for s in &self.stages { - out.push_str(&format!( + let _ = write!( + out, "{:<24} {:>10} {} {}\n", s.stage, format_duration(s.duration).cyan().to_string(), s.item_count, s.item_label.dimmed() - )); + ); } - out.push_str(&format!("{}\n", "─".repeat(50).dimmed())); - out.push_str(&format!( + let _ = write!(out, "{}\n", "─".repeat(50).dimmed()); + let _ = write!( + out, "{:<24} {:>10}\n\n", "Total".bold(), format_duration(total).green().bold().to_string() - )); + ); // Memory section let mem = &self.memory; if mem.peak_memory_bytes > 0 || mem.ast_node_count > 0 { - out.push_str(&format!( + let _ = write!( + out, "{}\n", "─── Memory Statistics ──────────────────────────────────".dimmed() - )); - out.push_str(&format!( + ); + let _ = write!( + out, "{:<24} {:>10}\n", "Peak memory", format_bytes(mem.peak_memory_bytes).cyan().to_string() - )); + ); if mem.ir_size_bytes > 0 { - out.push_str(&format!( + let _ = write!( + out, "{:<24} {:>10}\n", "IR module", format_bytes(mem.ir_size_bytes).cyan().to_string() - )); + ); } if mem.bytecode_size_bytes > 0 { - out.push_str(&format!( + let _ = write!( + out, "{:<24} {:>10}\n", "Bytecode", format_bytes(mem.bytecode_size_bytes).cyan().to_string() - )); + ); } if mem.ast_node_count > 0 { - out.push_str(&format!("{:<24} {:>10}\n", "AST nodes", mem.ast_node_count)); + let _ = write!(out, "{:<24} {:>10}\n", "AST nodes", mem.ast_node_count); } if mem.function_count > 0 { - out.push_str(&format!( - "{:<24} {:>10}\n", - "IR functions", mem.function_count - )); + let _ = write!(out, "{:<24} {:>10}\n", "IR functions", mem.function_count); } if mem.basic_block_count > 0 { - out.push_str(&format!( + let _ = write!( + out, "{:<24} {:>10}\n", "Basic blocks", mem.basic_block_count - )); + ); } } diff --git a/compiler/bytecode/src/disassembler.rs b/compiler/bytecode/src/disassembler.rs index 75004ee7..2fa5a497 100644 --- a/compiler/bytecode/src/disassembler.rs +++ b/compiler/bytecode/src/disassembler.rs @@ -1,6 +1,7 @@ use crate::function::BytecodeFunction; use crate::module::BytecodeModule; use crate::operand::Operand; +use std::fmt::Write; /// Disassembler rendering human-readable bytecode instructions. pub struct BytecodeDisassembler; @@ -9,7 +10,7 @@ impl BytecodeDisassembler { /// Renders a whole module to a formatted string. pub fn disassemble_module(module: &BytecodeModule) -> String { let mut output = String::new(); - output.push_str(&format!("Module: {}\n\n", module.name)); + let _ = write!(output, "Module: {}\n\n", module.name); for func in &module.functions { output.push_str(&Self::disassemble_function(func)); @@ -21,10 +22,11 @@ impl BytecodeDisassembler { /// Renders a single function's chunk to formatted string. pub fn disassemble_function(func: &BytecodeFunction) -> String { let mut output = String::new(); - output.push_str(&format!( + let _ = write!( + output, "Function: {} (params: {}, locals: {}, max_stack: {})\n", func.name, func.param_count, func.local_count, func.max_stack_size - )); + ); for (idx, inst) in func.chunk.instructions.iter().enumerate() { let op_str = format!("{:?}", inst.op); @@ -34,33 +36,33 @@ impl BytecodeDisassembler { match op { Operand::ConstantIndex(c_idx) => { if let Some(lit) = func.chunk.constants.get(*c_idx) { - line.push_str(&format!(" #{:<3} ({:?})", c_idx, lit)); + let _ = write!(line, " #{:<3} ({:?})", c_idx, lit); } else { - line.push_str(&format!(" #{:<3} (invalid)", c_idx)); + let _ = write!(line, " #{:<3} (invalid)", c_idx); } } Operand::LocalIndex(l_idx) => { if let Some(name) = func.debug_symbols.local_names.get(l_idx) { - line.push_str(&format!(" local_{:<2} ({})", l_idx, name)); + let _ = write!(line, " local_{:<2} ({})", l_idx, name); } else { - line.push_str(&format!(" local_{}", l_idx)); + let _ = write!(line, " local_{}", l_idx); } } Operand::JumpOffset(offset) => { let target = (idx as i32) + offset; - line.push_str(&format!(" offset_{:<3} (target: {:04})", offset, target)); + let _ = write!(line, " offset_{:<3} (target: {:04})", offset, target); } Operand::Count(n) => { - line.push_str(&format!(" count_{}", n)); + let _ = write!(line, " count_{}", n); } Operand::GlobalIndex(g_idx) => { - line.push_str(&format!(" global_{}", g_idx)); + let _ = write!(line, " global_{}", g_idx); } Operand::Register(r_idx) => { - line.push_str(&format!(" reg_{}", r_idx)); + let _ = write!(line, " reg_{}", r_idx); } Operand::FunctionIndex(f_idx) => { - line.push_str(&format!(" func_{}", f_idx)); + let _ = write!(line, " func_{}", f_idx); } } } diff --git a/fix3.py b/fix3.py new file mode 100644 index 00000000..3da49598 --- /dev/null +++ b/fix3.py @@ -0,0 +1,7 @@ +with open("runtime/vm/src/debugger.rs", "r") as f: + content = f.read() + +content = content.replace("operands_str\n .push_str(&format!(", "let _ = write!(operands_str, ") + +with open("runtime/vm/src/debugger.rs", "w") as f: + f.write(content) diff --git a/runtime/builtins/src/lib.rs b/runtime/builtins/src/lib.rs index da3fd2b7..08e947d7 100644 --- a/runtime/builtins/src/lib.rs +++ b/runtime/builtins/src/lib.rs @@ -4,6 +4,7 @@ //! Interfaces native Rust operations with interpreter scopes. use std::collections::HashMap; +use std::fmt::Write; use techscript_interpreter::{RuntimeError, Value}; /// Type definition for native built-in functions. @@ -62,7 +63,7 @@ impl BuiltinRegistry { self.register("fstring_concat", |args| { let mut res = String::new(); for arg in args { - res.push_str(&format!("{}", arg)); + let _ = write!(res, "{}", arg); } Ok(Value::Str(res)) }); diff --git a/runtime/vm/src/debugger.rs b/runtime/vm/src/debugger.rs index c15a9a80..3817852f 100644 --- a/runtime/vm/src/debugger.rs +++ b/runtime/vm/src/debugger.rs @@ -1,4 +1,5 @@ use std::collections::HashSet; +use std::fmt::Write; use techscript_bytecode::{BytecodeFunction, Operand}; /// VM debugger supporting breakpoint registries and opcode single-step tracing. @@ -61,28 +62,31 @@ impl VMDebugger { match op { Operand::ConstantIndex(c_idx) => { if let Some(lit) = func.chunk.constants.get(*c_idx) { - operands_str.push_str(&format!(" #{:<3} ({:?})", c_idx, lit)); + let _ = write!(operands_str, " #{:<3} ({:?})", c_idx, lit); } else { - operands_str.push_str(&format!(" #{:<3} (invalid)", c_idx)); + let _ = write!(operands_str, " #{:<3} (invalid)", c_idx); } } Operand::LocalIndex(l_idx) => { if let Some(name) = func.debug_symbols.local_names.get(l_idx) { - operands_str.push_str(&format!(" local_{:<2} ({})", l_idx, name)); + let _ = write!(operands_str, " local_{:<2} ({})", l_idx, name); } else { - operands_str.push_str(&format!(" local_{}", l_idx)); + let _ = write!(operands_str, " local_{}", l_idx); } } Operand::JumpOffset(offset) => { let target = (ip as i32) + offset; - operands_str - .push_str(&format!(" offset_{:<3} (target: {:04})", offset, target)); + let _ = write!( + operands_str, + " offset_{:<3} (target: {:04})", + offset, target + ); } Operand::Count(n) => { - operands_str.push_str(&format!(" count_{}", n)); + let _ = write!(operands_str, " count_{}", n); } Operand::GlobalIndex(g_idx) => { - operands_str.push_str(&format!(" global_{}", g_idx)); + let _ = write!(operands_str, " global_{}", g_idx); } _ => {} }