heron_rebuild_workflow/
value.rs1use anyhow::Result;
2
3use intern::InternStr;
4use syntax::ast;
5
6use crate::{AbstractTaskId, BranchSpec, IdentId, LiteralId, WorkflowStrings};
7
8#[derive(Debug)]
10pub enum BaseValue {
11 Literal(LiteralId),
13 Config(IdentId),
15 Task(AbstractTaskId, IdentId),
17 Interp(LiteralId, Vec<IdentId>),
19}
20
21#[derive(Debug)]
23pub enum DirectValue {
24 Simple(BaseValue),
26 Graft(BaseValue, BranchSpec),
28}
29
30#[derive(Debug)]
32pub enum Value {
33 Direct(DirectValue),
35 Branched(Vec<(BranchSpec, DirectValue)>),
37}
38
39pub fn create_value(
41 strings: &mut WorkflowStrings,
42 lhs: ast::Ident,
43 rhs: ast::Rhs,
44) -> Result<Value> {
45 use ast::Rhs::*;
46 match rhs {
47 Branchpoint { branchpoint, vals } => {
48 let outer_k = strings.branchpoints.intern(branchpoint)?;
49 let mut flattened_vals = Vec::with_capacity(vals.len());
50 for (branch_lhs, val) in vals {
51 let outer_v = strings.idents.intern(branch_lhs)?;
52 strings.baselines.add(outer_k, outer_v);
53 match create_value(strings, branch_lhs, val)? {
54 Value::Branched(nested_vals) => {
55 for (mut nested_branch, nested_val) in nested_vals {
56 nested_branch.insert(outer_k, outer_v);
57 flattened_vals.push((nested_branch, nested_val));
58 }
59 }
60 Value::Direct(val) => {
61 let branch = BranchSpec::simple(outer_k, outer_v);
62 flattened_vals.push((branch, val));
63 }
64 }
65 }
66 Ok(Value::Branched(flattened_vals))
67 }
68 direct_rhs => Ok(Value::Direct(create_direct(strings, lhs, direct_rhs)?)),
69 }
70}
71
72fn create_direct(
73 strings: &mut WorkflowStrings,
74 lhs: ast::Ident,
75 rhs: ast::Rhs,
76) -> Result<DirectValue> {
77 use ast::Rhs::*;
78 match rhs {
79 GraftedVariable { name, branch } => {
80 let name = strings.idents.intern(name)?;
81 let value = BaseValue::Config(name);
82 let branch = create_branch(strings, branch)?;
83 Ok(DirectValue::Graft(value, branch))
84 }
85 GraftedTaskOutput {
86 task,
87 output,
88 branch,
89 } => {
90 let task = strings.tasks.intern(task)?;
91 let output = strings.idents.intern(output)?;
92 let value = BaseValue::Task(task, output);
93 let branch = create_branch(strings, branch)?;
94 Ok(DirectValue::Graft(value, branch))
95 }
96 ShorthandGraftedTaskOutput { task, branch } => {
97 let task = strings.tasks.intern(task)?;
98 let output = strings.idents.intern(lhs)?;
99 let value = BaseValue::Task(task, output);
100 let branch = create_branch(strings, branch)?;
101 Ok(DirectValue::Graft(value, branch))
102 }
103 _ => Ok(DirectValue::Simple(create_base(strings, lhs, rhs)?)),
104 }
105}
106
107#[rustfmt::skip]
108fn create_base(strings: &mut WorkflowStrings, lhs: ast::Ident, rhs: ast::Rhs) -> Result<BaseValue> {
109 use ast::Rhs::*;
110 match rhs {
111 Unbound => strings.literals.intern(lhs).map(BaseValue::Literal),
112 Literal { val } => strings.literals.intern(val).map(BaseValue::Literal),
113 Variable { name } => strings.idents.intern(name).map(BaseValue::Config),
114 ShorthandVariable => strings.idents.intern(lhs).map(BaseValue::Config),
115 TaskOutput { task, output } => {
116 let task = strings.tasks.intern(task)?;
117 let output = strings.idents.intern(output)?;
118 Ok(BaseValue::Task(task, output))
119 }
120 ShorthandTaskOutput { task } => {
121 let task = strings.tasks.intern(task)?;
122 let output = strings.idents.intern(lhs)?;
123 Ok(BaseValue::Task(task, output))
124 }
125 Interp { text, vars } => {
126 let val = strings.literals.intern(text)?;
127 let mut vars: Vec<IdentId> = vars
128 .into_iter()
129 .map(|var| strings.idents.intern(var))
130 .collect::<Result<_, _>>()?;
131 vars.reverse();
134 Ok(BaseValue::Interp(val, vars))
135 }
136 _ => {
137 unreachable!("Should not be handling grafted or branched values here")
138 }
139 }
140}
141
142fn create_branch(strings: &mut WorkflowStrings, branch: ast::Branch) -> Result<BranchSpec> {
143 let mut spec = BranchSpec::default();
144 for (k, v) in branch {
145 let k = strings.branchpoints.intern(k)?;
146 let v = strings.idents.intern(v)?;
147 spec.insert(k, v);
148 }
149 Ok(spec)
150}