use std::collections::HashSet;
use brane_ast::ast;
use brane_exe::pc::ProgramCounter;
use crate::{Dataset, Elem, ElemBranch, ElemCommit, ElemLoop, ElemParallel, ElemTask};
#[inline]
pub fn get_edge(wir: &ast::Workflow, pc: ProgramCounter) -> Option<&ast::Edge> {
if pc.func_id.is_main() { wir.graph.get(pc.edge_idx) } else { wir.funcs.get(&pc.func_id.id()).and_then(|edges| edges.get(pc.edge_idx)) }
}
pub trait WorkflowVisitor {
fn visit_task(&mut self, _task: &ElemTask) {}
fn visit_commit(&mut self, _commit: &ElemCommit) {}
fn visit_branch(&mut self, _branch: &ElemBranch) {}
fn visit_parallel(&mut self, _parallel: &ElemParallel) {}
fn visit_loop(&mut self, _loop: &ElemLoop) {}
fn visit_next(&mut self) {}
fn visit_stop(&mut self, _stop: &HashSet<Dataset>) {}
}
pub fn walk_workflow_preorder(elem: &Elem, visitor: &mut impl WorkflowVisitor) {
match elem {
Elem::Task(task) => {
visitor.visit_task(task);
walk_workflow_preorder(&task.next, visitor);
},
Elem::Commit(commit) => {
visitor.visit_commit(commit);
walk_workflow_preorder(&commit.next, visitor);
},
Elem::Branch(branch) => {
visitor.visit_branch(branch);
for elem in &branch.branches {
walk_workflow_preorder(elem, visitor);
}
walk_workflow_preorder(&branch.next, visitor);
},
Elem::Parallel(parallel) => {
visitor.visit_parallel(parallel);
for elem in ¶llel.branches {
walk_workflow_preorder(elem, visitor);
}
walk_workflow_preorder(¶llel.next, visitor);
},
Elem::Loop(r#loop) => {
visitor.visit_loop(r#loop);
walk_workflow_preorder(&r#loop.body, visitor);
walk_workflow_preorder(&r#loop.next, visitor);
},
Elem::Next => {
visitor.visit_next();
},
Elem::Stop(stop) => {
visitor.visit_stop(stop);
},
}
}