//! # Compiler Orchestration //! //! This module provides the high-level API for triggering the compilation process. //! It handles the transition between different compiler phases: Frontend -> IR -> Backend. use crate::backend; use crate::common::files::FileManager; use crate::common::symbols::Symbol; use crate::frontends::ts::TypescriptFrontend; use crate::frontends::Frontend; use crate::ir; use anyhow::Result; use std::path::Path; /// The result of a successful compilation process. /// It contains the final binary and the metadata needed for debugging. pub struct CompilationUnit { /// The raw binary data formatted as Prometeu ByteCode (PBC). /// This is what gets written to a `.pbc` file. pub rom: Vec, /// The list of debug symbols discovered during compilation. /// These are used to map bytecode offsets back to source code locations. pub symbols: Vec, } impl CompilationUnit { /// Writes the compilation results (PBC binary, disassembly, and symbols) to the disk. /// /// # Arguments /// * `out` - The base path for the output `.pbc` file. /// * `emit_disasm` - If true, a `.disasm` file will be created next to the output. /// * `emit_symbols` - If true, a `.json` symbols file will be created next to the output. pub fn export(&self, out: &Path, emit_disasm: bool, emit_symbols: bool) -> Result<()> { let artifacts = backend::artifacts::Artifacts::new(self.rom.clone(), self.symbols.clone()); artifacts.export(out, emit_disasm, emit_symbols) } } /// Orchestrates the compilation of a Prometeu project starting from an entry file. /// /// This function executes the full compiler pipeline: /// 1. **Frontend**: Loads and parses the entry file (and its dependencies). /// Currently, it uses the `TypescriptFrontend`. /// 2. **IR Generation**: The frontend produces a high-level Intermediate Representation (IR). /// 3. **Validation**: Checks the IR for consistency and VM compatibility. /// 4. **Backend**: Lowers the IR into final Prometeu ByteCode. /// /// # Errors /// Returns an error if parsing fails, validation finds issues, or code generation fails. /// /// # Example /// ```no_run /// use std::path::Path; /// let entry = Path::new("src/main.ts"); /// let unit = prometeu_compiler::compiler::compile(entry).expect("Failed to compile"); /// unit.export(Path::new("build/program.pbc"), true, true).unwrap(); /// ``` pub fn compile(entry: &Path) -> Result { let mut file_manager = FileManager::new(); // 1. Select Frontend (Currently only TS is supported) // The frontend is responsible for parsing source code and producing the IR. let frontend = TypescriptFrontend; // 2. Compile to IR (Intermediate Representation) // This step abstracts away source-specific syntax (like TypeScript) into a // generic set of instructions that the backend can understand. let ir_module = frontend.compile_to_ir(entry, &mut file_manager) .map_err(|bundle| anyhow::anyhow!("Compilation failed with {} errors", bundle.diagnostics.len()))?; // 3. IR Validation // Ensures the generated IR is sound and doesn't violate any VM constraints // before we spend time generating bytecode. ir::validate::validate_module(&ir_module) .map_err(|bundle| anyhow::anyhow!("IR Validation failed: {:?}", bundle))?; // 4. Emit Bytecode // The backend takes the validated IR and produces the final binary executable. let result = backend::emit_module(&ir_module, &file_manager)?; Ok(CompilationUnit { rom: result.rom, symbols: result.symbols, }) }