use super::constraint_ops::parse_expression;
use super::engine::AstEngine;
use super::error::OperationError;
use super::result::ApplyResult;
use super::types::SumBoundDef;
use crate::constraint::{Constraint, Expression};
use crate::structure::{Ident, NodeKind, Reference};
impl AstEngine {
pub(crate) fn introduce_multi_test_case(
&mut self,
count_var_name: &str,
sum_bound: Option<&SumBoundDef>,
) -> Result<ApplyResult, OperationError> {
for node in self.structure.iter() {
if matches!(node.kind(), NodeKind::Repeat { .. }) {
return Err(OperationError::InvalidOperation {
action: "IntroduceMultiTestCase".to_owned(),
reason: "Multi-test-case wrapper already exists".to_owned(),
});
}
}
let count_scalar_id = self.structure.add_node(NodeKind::Scalar {
name: Ident::new(count_var_name),
});
let current_root = self.structure.root();
let current_children = if let Some(root_node) = self.structure.get(current_root) {
if let NodeKind::Sequence { children } = root_node.kind() {
children.clone()
} else {
vec![current_root]
}
} else {
vec![]
};
let repeat_id = self.structure.add_node(NodeKind::Repeat {
count: Expression::Var(Reference::VariableRef(count_scalar_id)),
index_var: None,
body: current_children,
});
if let Some(root_node) = self.structure.get_mut(current_root) {
root_node.set_kind(NodeKind::Sequence {
children: vec![count_scalar_id, repeat_id],
});
}
let created_nodes = vec![count_scalar_id, repeat_id];
let mut created_constraints = vec![];
if let Some(sum_bound_def) = sum_bound {
let constraint = Constraint::SumBound {
variable: Reference::Unresolved(Ident::new(&sum_bound_def.bound_var)),
upper: parse_expression(&sum_bound_def.upper),
};
let cid = self.constraints.add(None, constraint);
created_constraints.push(cid);
}
Ok(ApplyResult {
created_nodes,
removed_nodes: vec![],
created_constraints,
affected_constraints: vec![],
})
}
}