mod codegen;
mod collector;
mod error;
pub mod fol_model;
pub mod verilog;
pub use codegen::{emit_property_check, emit_value, primitive_rust_type};
pub use collector::{is_extractable, is_logical_type};
pub use error::ExtractError;
use logicaffeine_kernel::Context;
use codegen::CodeGen;
use collector::collect_dependencies;
use std::collections::HashSet;
pub fn extract_program(ctx: &Context, entry: &str) -> Result<String, ExtractError> {
extract_programs(ctx, &[entry])
}
pub fn extract_programs(ctx: &Context, entries: &[&str]) -> Result<String, ExtractError> {
let mut all_deps: HashSet<String> = HashSet::new();
for entry in entries {
if !ctx.is_inductive(entry) && !ctx.is_definition(entry) && !ctx.is_constructor(entry) {
return Err(ExtractError::NotFound((*entry).to_string()));
}
all_deps.extend(collect_dependencies(ctx, entry));
}
let sorted = topological_sort(ctx, &all_deps);
let mut codegen = CodeGen::new(ctx);
for name in &sorted {
if ctx.is_inductive(name) {
if !ctx.get_constructors(name).is_empty() {
codegen.emit_inductive(name)?;
}
} else if ctx.is_definition(name) {
codegen.emit_definition(name)?;
}
}
Ok(codegen.finish())
}
fn topological_sort(ctx: &Context, deps: &HashSet<String>) -> Vec<String> {
let mut inductives = Vec::new();
let mut definitions = Vec::new();
for name in deps {
if ctx.is_inductive(name) {
inductives.push(name.clone());
} else if ctx.is_definition(name) {
definitions.push(name.clone());
}
}
inductives.sort();
definitions.sort();
inductives.extend(definitions);
inductives
}