1mod config;
3mod error;
4mod result;
5
6pub use config::{CompilerConfig, OptimizationLevel};
7pub use error::LingError;
8pub use result::LingResult;
9
10use crate::mir;
11use ling_codegen::CodegenBackend;
12use std::path::Path;
13
14pub struct LingCompiler {
15 config: CompilerConfig,
16}
17
18impl LingCompiler {
19 pub fn new(config: CompilerConfig) -> Self {
20 Self { config }
21 }
22
23 pub fn compile<P: AsRef<Path>>(&self, input: P, output: P) -> LingResult<()> {
24 let source =
25 std::fs::read_to_string(input.as_ref()).map_err(|e| LingError::Io(e.to_string()))?;
26 let mir = mir::compile_and_optimize(&source, self.config.optimization)?;
27 println!(
28 "compiled {} functions, optimized at {:?}",
29 mir.functions.len(),
30 self.config.optimization
31 );
32
33 let mir_prog = ling_codegen::MirProgram::new(mir, input.as_ref().to_string_lossy());
34 let mut backend = ling_codegen::BytecodeBackend;
35 backend
36 .emit(&mir_prog, output.as_ref())
37 .map_err(|e| LingError::Codegen(e.to_string()))?;
38 println!("bytecode emitted to {}", output.as_ref().display());
39 Ok(())
40 }
41
42 pub fn compile_and_run<P: AsRef<Path>>(&self, input: P) -> LingResult<()> {
43 let source =
44 std::fs::read_to_string(input.as_ref()).map_err(|e| LingError::Io(e.to_string()))?;
45 let mir = mir::compile_and_optimize(&source, self.config.optimization)?;
46 println!(
47 "compiled {} functions, optimized at {:?}",
48 mir.functions.len(),
49 self.config.optimization
50 );
51
52 let vm_prog = ling_codegen::compile_mir_program(&mir);
53 let mut vm = ling_codegen::Vm::new();
54 vm.load(vm_prog);
55 vm.run_main()
56 .map_err(|e| LingError::Codegen(e.to_string()))?;
57 Ok(())
58 }
59
60 pub fn dump_mir<P: AsRef<Path>>(&self, input: P) -> LingResult<()> {
61 let source =
62 std::fs::read_to_string(input.as_ref()).map_err(|e| LingError::Io(e.to_string()))?;
63 let mir = mir::compile_and_optimize(&source, self.config.optimization)?;
64 for func in &mir.functions {
65 println!("=== function: {} ===", func.name);
66 println!(" args: {}, locals: {}", func.arg_count, func.locals.len());
67 for (i, decl) in func.locals.iter().enumerate() {
68 let name = decl.name.as_deref().unwrap_or("_");
69 println!(
70 " local {}: {} {:?} mut={} owning={}",
71 i, name, decl.ty, decl.is_mut, decl.is_owning
72 );
73 }
74 for (bi, bb) in func.basic_blocks.iter().enumerate() {
75 println!(" bb{}:", bi);
76 for stmt in &bb.statements {
77 println!(" {:?}", stmt.kind);
78 }
79 if let Some(term) = &bb.terminator {
80 println!(" term: {:?}", term.kind);
81 }
82 }
83 }
84 Ok(())
85 }
86}