use crate::{Edge, Node, compile::ModuleError, node};
use petgraph::visit::{Data, IntoEdgesDirected, IntoNodeReferences, NodeIndexable, Visitable};
use steel::{SteelVal, parser::ast::ExprKind, steel_vm::engine::Engine};
#[derive(Debug, thiserror::Error)]
pub enum CompileError {
#[error("module generation failed: {0}")]
Module(#[from] ModuleError),
#[error("expression evaluation failed: {0}")]
Eval(String),
}
pub fn init<'a, G>(
get_node: node::GetNode<'a>,
graph: G,
) -> Result<(Engine, Vec<ExprKind>), CompileError>
where
G: Data<EdgeWeight = Edge>
+ IntoEdgesDirected
+ IntoNodeReferences
+ NodeIndexable
+ Visitable
+ Copy,
G::NodeWeight: Node,
{
let mut vm = Engine::new_base();
vm.register_value(crate::ROOT_STATE, SteelVal::empty_hashmap());
crate::graph::register(get_node, graph, &[], &mut vm);
let module = compile(get_node, graph, &mut vm)?;
Ok((vm, module))
}
pub fn compile<'a, G>(
get_node: node::GetNode<'a>,
graph: G,
vm: &mut Engine,
) -> Result<Vec<ExprKind>, CompileError>
where
G: Data<EdgeWeight = Edge>
+ IntoEdgesDirected
+ IntoNodeReferences
+ NodeIndexable
+ Visitable
+ Copy,
G::NodeWeight: Node,
{
let module = crate::compile::module(get_node, graph)?;
for expr in &module {
vm.run(expr.to_pretty(80))
.map_err(|e| CompileError::Eval(e.to_string()))?;
}
Ok(module)
}
pub fn fmt_module(module: &[ExprKind]) -> String {
module
.iter()
.map(|expr| expr.to_pretty(80))
.collect::<Vec<String>>()
.join("\n\n")
}