use super::super::error::{ErrorSpan, ParseError};
use super::super::types::{ChoiceBranch, Statement};
use std::collections::HashMap;
#[allow(clippy::too_many_lines)]
pub(crate) fn inline_calls(
statements: &[Statement],
protocol_defs: &HashMap<String, Vec<Statement>>,
input: &str,
) -> std::result::Result<Vec<Statement>, ParseError> {
let mut result = Vec::new();
for statement in statements {
match statement {
Statement::Call { name } => {
let key = name.to_string();
let called =
protocol_defs
.get(&key)
.ok_or_else(|| ParseError::UndefinedProtocol {
protocol: key.clone(),
span: ErrorSpan::from_line_col(1, 1, input),
})?;
result.extend(inline_calls(called, protocol_defs, input)?);
}
Statement::Choice { role, branches, .. } => {
let mut new_branches = Vec::new();
for b in branches {
new_branches.push(ChoiceBranch {
label: b.label.clone(),
guard: b.guard.clone(),
statements: inline_calls(&b.statements, protocol_defs, input)?,
});
}
result.push(Statement::Choice {
role: role.clone(),
branches: new_branches,
annotations: HashMap::new(),
});
}
Statement::Loop { condition, body } => {
result.push(Statement::Loop {
condition: condition.clone(),
body: inline_calls(body, protocol_defs, input)?,
});
}
Statement::Parallel { branches } => {
let mut new_branches = Vec::new();
for b in branches {
new_branches.push(inline_calls(b, protocol_defs, input)?);
}
result.push(Statement::Parallel {
branches: new_branches,
});
}
Statement::Rec { label, body } => {
result.push(Statement::Rec {
label: label.clone(),
body: inline_calls(body, protocol_defs, input)?,
});
}
_ => {
result.push(statement.clone());
}
}
}
Ok(result)
}