heron_rebuild_workflow/
plan.rs1use anyhow::Result;
2
3use intern::InternStr;
4use syntax::ast;
5
6use crate::{AbstractTaskId, BranchSpec, Error, WorkflowStrings};
7
8#[derive(Debug, Clone)]
10pub struct Plan {
11 pub subplans: Vec<Subplan>,
12}
13
14impl Plan {
15 pub fn create(
17 strings: &mut WorkflowStrings,
18 cross_products: Vec<ast::CrossProduct>,
19 ) -> Result<Self> {
20 debug_assert!(!cross_products.is_empty());
21 let mut subplans = Vec::with_capacity(cross_products.len());
22 for cross_product in cross_products {
23 subplans.push(Subplan::create(strings, cross_product)?);
24 }
25 Ok(Self { subplans })
26 }
27
28 pub fn create_anonymous(
30 strings: &mut WorkflowStrings,
31 tasks: &[String],
32 branch: BranchSpec,
33 ) -> Result<Self> {
34 let goals = tasks.iter().map(|t| strings.tasks.intern(t)).collect::<Result<_, _>>()?;
35
36 Ok(Self {
37 subplans: vec![Subplan {
38 goals,
39 branches: vec![branch],
40 }],
41 })
42 }
43}
44
45#[derive(Debug, Clone)]
47pub struct Subplan {
48 pub goals: Vec<AbstractTaskId>,
50 pub branches: Vec<BranchSpec>,
52}
53
54impl Subplan {
55 pub fn create(strings: &mut WorkflowStrings, cross_product: ast::CrossProduct) -> Result<Self> {
56 debug_assert!(!cross_product.goals.is_empty());
57 let mut goals = Vec::with_capacity(cross_product.goals.len());
58 for goal in &cross_product.goals {
59 let id = strings.tasks.intern(goal)?;
60 goals.push(id);
61 }
62
63 let mut branches = vec![BranchSpec::default()];
64 for (k, vs) in &cross_product.branches {
65 let k = strings.add_branchpoint(k)?; let vs = match vs {
67 ast::Branches::Specified(vec) => vec,
68 _ => {
69 return Err(Error::Unsupported(
70 "plans with branch glob specifications".to_owned(),
71 )
72 .into())
73 }
74 };
75
76 match vs.len() {
77 0 => unreachable!(
78 "Plan branch specifications should have at least one branch, \
79 but the parser should catch this."
80 ),
81 1 => {
82 let v = strings.add_branch(k, vs[0])?;
84 for branch in &mut branches {
85 branch.insert(k, v);
86 }
87 }
88 len => {
89 branches.reserve(branches.len() * len);
90 let v0 = strings.add_branch(k, vs[0])?;
92 for branch in &mut branches {
93 branch.insert(k, v0);
94 }
95 let mut new_branches = Vec::with_capacity(branches.len() * len);
97 for v in vs.iter().skip(1) {
98 let v = strings.add_branch(k, v)?;
99 for branch in &branches {
100 let mut new_branch = branch.clone();
101 new_branch.insert(k, v);
102 new_branches.push(new_branch);
103 }
104 }
105 branches.append(&mut new_branches);
107 }
108 }
109 }
110
111 Ok(Self { goals, branches })
112 }
113}