use std::path::{Path, PathBuf};
use std::process::ExitCode;
use qala_compiler::diagnostics::Diagnostic;
use qala_compiler::vm::Vm;
use crate::Target;
use crate::diagnostics::{render_errors, render_warnings};
use crate::pipeline;
pub fn run(file: &Path) -> ExitCode {
let src = match std::fs::read_to_string(file) {
Ok(s) => s,
Err(e) => {
eprintln!("error: cannot read '{}': {e}", file.display());
return ExitCode::from(1);
}
};
let compiled = match pipeline::compile_source(&src) {
Ok(c) => c,
Err(errors) => {
eprint!("{}", render_errors(&errors, &src));
return ExitCode::from(1);
}
};
if !compiled.warnings.is_empty() {
eprint!("{}", render_warnings(&compiled.warnings, &src));
}
let mut vm = Vm::new(compiled.program, src.clone());
match vm.run() {
Ok(()) => {
for line in vm.get_state().console {
println!("{line}");
}
ExitCode::SUCCESS
}
Err(err) => {
eprint!("{}", Diagnostic::from(err).render(&src));
ExitCode::from(1)
}
}
}
pub fn check(file: &Path) -> ExitCode {
let src = match std::fs::read_to_string(file) {
Ok(s) => s,
Err(e) => {
eprintln!("error: cannot read '{}': {e}", file.display());
return ExitCode::from(1);
}
};
let (errors, warnings) = pipeline::check_source(&src);
if !errors.is_empty() {
eprint!("{}", render_errors(&errors, &src));
}
if !warnings.is_empty() {
eprint!("{}", render_warnings(&warnings, &src));
}
if errors.is_empty() {
ExitCode::SUCCESS
} else {
ExitCode::from(1)
}
}
pub fn build(file: &Path, target: Target, output: Option<PathBuf>) -> ExitCode {
if target == Target::Arm64 {
let src = match std::fs::read_to_string(file) {
Ok(s) => s,
Err(e) => {
eprintln!("error: cannot read '{}': {e}", file.display());
return ExitCode::from(1);
}
};
let typed = match pipeline::typecheck_source(&src) {
Ok(t) => t,
Err(errors) => {
eprint!("{}", render_errors(&errors, &src));
return ExitCode::from(1);
}
};
let assembly = match qala_compiler::arm64::compile_arm64(&typed, &src) {
Ok(asm) => asm,
Err(errors) => {
eprint!("{}", render_errors(&errors, &src));
return ExitCode::from(1);
}
};
let out_path = match output {
Some(p) => p,
None => file.with_extension("s"),
};
if let Err(e) = std::fs::write(&out_path, assembly) {
eprintln!("error: cannot write '{}': {e}", out_path.display());
return ExitCode::from(1);
}
println!("wrote {}", out_path.display());
return ExitCode::SUCCESS;
}
let src = match std::fs::read_to_string(file) {
Ok(s) => s,
Err(e) => {
eprintln!("error: cannot read '{}': {e}", file.display());
return ExitCode::from(1);
}
};
let compiled = match pipeline::compile_source(&src) {
Ok(c) => c,
Err(errors) => {
eprint!("{}", render_errors(&errors, &src));
return ExitCode::from(1);
}
};
let out_path = match output {
Some(p) => p,
None => file.with_extension("qbc"),
};
let listing = compiled.program.disassemble();
if let Err(e) = std::fs::write(&out_path, listing) {
eprintln!("error: cannot write '{}': {e}", out_path.display());
return ExitCode::from(1);
}
println!("wrote {}", out_path.display());
ExitCode::SUCCESS
}