use std::path::{Path, PathBuf};
use super::backend::{self, BackendKind};
use super::metadata::{ArtifactKind, ComponentMetadata, ComponentSpec, OptimizationLevel};
use super::pipeline::Compiler;
#[must_use]
pub fn lower_unified_module(module: &crate::core_ir::UnifiedModule, module_id: &str) -> String {
crate::lower_core::lower_to_textual_sil(module, module_id)
}
pub fn compile_in_file(
source_path: &Path,
spec: &ComponentSpec,
emit_metadata: bool,
) -> Result<(PathBuf, Option<PathBuf>), String> {
let source = std::fs::read_to_string(source_path).map_err(|e| format!("read source: {e}"))?;
let source_name = source_path
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("module");
let mut compiler = Compiler::new(spec.clone()).map_err(|e| format!("compiler setup: {e}"))?;
let result = compiler
.compile(&source)
.map_err(|e| format!("compilation: {e}"))?;
let ext = result.output.extension;
let output_path = source_path.with_extension(ext);
std::fs::write(&output_path, &result.output.data).map_err(|e| format!("write output: {e}"))?;
println!(
" Compiled `{}` → {} ({} bytes, target: {})",
source_name,
output_path.display(),
result.output.data.len(),
spec.target,
);
let metadata_path = if emit_metadata {
let md_path = output_path.with_extension("component.json");
let json = serde_json::to_string_pretty(&result.metadata)
.map_err(|e| format!("serialize metadata: {e}"))?;
let code_bytes: u64 = result.metadata.code_sections.iter().map(|s| s.size).sum();
std::fs::write(&md_path, &json).map_err(|e| format!("write metadata: {e}"))?;
println!(
" Metadata → {} ({}b code, {} imports, {} exports, {}+{} capabilities)",
md_path.display(),
code_bytes,
result.metadata.imports.len(),
result.metadata.exports.len(),
result.metadata.capabilities_required.len(),
result.metadata.capabilities_exported.len(),
);
Some(md_path)
} else {
None
};
Ok((output_path, metadata_path))
}
pub fn emit_component_metadata(
source_path: &Path,
spec: &ComponentSpec,
) -> Result<PathBuf, String> {
let source = std::fs::read_to_string(source_path).map_err(|e| format!("read source: {e}"))?;
let mut compiler = Compiler::new(spec.clone()).map_err(|e| format!("compiler setup: {e}"))?;
let module = compiler
.parse_source(&source)
.map_err(|e| format!("parse: {e}"))?;
let empty_output = super::backend::BackendOutput {
data: Vec::new(),
extension: "",
entry_offset: None,
symbol_table: vec![],
};
let metadata = ComponentMetadata::build(spec, &module, &empty_output, &source);
let md_path = source_path.with_extension("component.json");
let json =
serde_json::to_string_pretty(&metadata).map_err(|e| format!("serialize metadata: {e}"))?;
std::fs::write(&md_path, &json).map_err(|e| format!("write metadata: {e}"))?;
println!(
" Metadata `{}` → {}",
source_path.display(),
md_path.display()
);
Ok(md_path)
}
pub fn spec_from_cli(
name: &str,
target: &str,
kind: ArtifactKind,
entry: &str,
opt: u8,
deterministic: bool,
freestanding: bool,
) -> ComponentSpec {
let target = if freestanding {
if target.contains("aarch64") {
"aarch64-unknown-none".to_string()
} else {
"x86_64-unknown-none".to_string()
}
} else {
target.to_string()
};
let opt_level = match opt {
0 => OptimizationLevel::None,
1 => OptimizationLevel::Less,
2 => OptimizationLevel::Default,
_ => OptimizationLevel::Aggressive,
};
ComponentSpec {
name: name.to_string(),
target,
artifact_kind: kind,
deterministic,
checkpoint: String::new(),
optimization_level: opt_level,
debug_info: false,
entry_point: Some(entry.to_string()),
imports: vec![],
exports: vec![],
capabilities: vec![],
capabilities_exported: vec![],
}
}
pub fn print_backends() {
println!("Available codegen backends (replacing LLVM):");
println!();
for kind in BackendKind::ALL {
let triple = match kind {
BackendKind::AArch64MachO => "aarch64-apple-darwin",
BackendKind::AArch64Elf => "aarch64-unknown-linux-gnu",
BackendKind::X86_64Elf => "x86_64-unknown-linux-gnu",
BackendKind::Arm32Elf => "armv7-unknown-linux-gnueabihf",
BackendKind::X86_64Coff => "x86_64-pc-windows-msvc",
BackendKind::AArch64Coff => "aarch64-pc-windows-msvc",
BackendKind::Wasm32 => "wasm32-unknown-unknown",
BackendKind::RawBinary => "raw",
};
let caps = backend::backend_capabilities(triple);
let status = if caps.implemented {
"implemented"
} else {
"contract"
};
println!(" {triple:40} {status:15} format={}", caps.object_format);
}
}