heron_rebuild_workflow/
task.rs1use anyhow::Result;
2
3use intern::InternStr;
4use syntax::ast;
5use util::IdVec;
6
7use crate::{AbstractValueId, Error, IdentId, LiteralId, ModuleId, Value, WorkflowStrings};
8
9const DEFAULT_VARS_LEN: usize = 8;
10
11#[derive(Debug, Default, Clone)]
14pub struct TaskVars<T> {
15 pub inputs: Vec<T>,
16 pub outputs: Vec<T>,
17 pub params: Vec<T>,
18}
19
20impl<T> TaskVars<T> {
21 pub fn new_with_sizes<U>(other: &TaskVars<U>) -> Self {
24 Self {
25 inputs: Vec::with_capacity(other.inputs.len()),
26 outputs: Vec::with_capacity(other.outputs.len()),
27 params: Vec::with_capacity(other.params.len()),
28 }
29 }
30
31 pub fn with_default_capacity(cap: usize) -> Self {
33 Self {
34 inputs: Vec::with_capacity(cap),
35 outputs: Vec::with_capacity(cap),
36 params: Vec::with_capacity(cap),
37 }
38 }
39}
40
41#[derive(Debug, Default, Clone)]
43pub struct Task {
44 pub vars: TaskVars<(IdentId, AbstractValueId)>,
46 pub code: LiteralId,
48 pub referenced_vars: Vec<IdentId>,
50 pub module: Option<ModuleId>,
52 pub exists: bool,
54}
55
56impl Task {
57 pub fn create(
59 block: ast::TasklikeBlock,
60 strings: &mut WorkflowStrings,
61 values: &mut IdVec<AbstractValueId, Value>,
62 ) -> Result<Self> {
63 let default_len = block.specs.len().min(DEFAULT_VARS_LEN);
65 let mut vars = TaskVars::with_default_capacity(default_len);
66 let mut module = None;
67
68 use ast::BlockSpec::*;
69 for spec in block.specs {
70 match spec {
71 Input { lhs, rhs } => vars.inputs.push(add_spec(lhs, rhs, strings, values)?),
72 Output { lhs, rhs } => vars.outputs.push(add_spec(lhs, rhs, strings, values)?),
73 Param { lhs, rhs, dot } => {
74 if dot {
75 return Err(Error::DotParamsUnsupported.into());
76 } else {
77 vars.params.push(add_spec(lhs, rhs, strings, values)?);
78 }
79 }
80 Module { name } => {
81 if module.is_none() {
82 module = Some(strings.modules.intern(name)?);
83 } else {
84 return Err(Error::MultipleModulesDefined.into());
85 }
86 }
87 }
88 }
89
90 let code = strings.literals.intern(block.code.text)?;
91 let referenced_vars = block
92 .code
93 .vars
94 .iter()
95 .map(|id| strings.idents.intern(id))
96 .collect::<Result<_, _>>()?;
97
98 Ok(Self {
99 vars,
100 code,
101 referenced_vars,
102 module,
103 exists: true,
104 })
105 }
106}
107
108fn add_spec(
109 lhs: ast::Ident,
110 rhs: ast::Rhs,
111 strings: &mut WorkflowStrings,
112 values: &mut IdVec<AbstractValueId, Value>,
113) -> Result<(IdentId, AbstractValueId)> {
114 let name = strings.idents.intern(lhs)?;
115 let val = strings.create_value(lhs, rhs)?;
116 let val_id = values.push(val);
117 Ok((name, val_id))
118}