in amzn-smt-string-transformer/src/callgraph.rs [436:504]
fn propagate_used_with(
&mut self,
var: NodeId,
cliques: &HashMap<NodeId, NodeSetData>,
) -> Result<(NodeSetData, AffectOk), AffectErr> {
let nodes = self.forest.nodes().clone();
let cur_node = match nodes.get(&var) {
Some(n) => n,
None => {
// if the node is not in the callgraph, error out
return Err(AffectErr::InvalidNode);
}
};
// if already done, bail early
if let Some(contrib) = &cur_node.data.used_with {
return Ok((contrib.clone(), AffectOk::AlreadyDone));
}
// if it's in a partition we've already formed, just collect this
if let Some(contrib) = self.get_contribs_for_var(var) {
self.update_node_with_contribs(
var,
contrib.clone(),
cur_node.data.clone(),
GraphTraversalDir::UsedWith,
)?;
return Ok((contrib, AffectOk::AlreadyDone));
}
// now, we're tracking the literals, vars, and string functions that the current var are used WITH
// these are all the nodes that are in cliques with the current var
let mut contrib_vars = BTreeSet::<NodeId>::new();
contrib_vars.insert(var);
let mut contrib_string_fcts = HashSet::<(StringFct, StringFctArgs)>::new();
contrib_string_fcts.insert(cur_node.data.get_string_fct_arg_pair());
let mut contrib_string_lits: BTreeSet<String> =
cur_node.data.string_lits_built_from.clone();
// iterate over the cliques and collect the info from those who contain the current var
let mut cids: Vec<&NodeId> = cliques.keys().collect::<Vec<_>>();
cids.sort();
for cid in cids {
let clique = &cliques[cid];
if clique.vars.contains(&var) {
contrib_vars.extend(clique.vars.iter().cloned());
contrib_string_fcts.extend(clique.string_fcts.iter().cloned());
contrib_string_lits.extend(clique.string_lits.iter().cloned());
}
}
// finally, once the data has all been collected, update the current node with the contribs
let new_node_data = cur_node.data.clone();
let new_nodeset_data = NodeSetData {
vars: contrib_vars,
string_fcts: contrib_string_fcts,
string_lits: contrib_string_lits,
};
self.update_node_with_contribs(
var,
new_nodeset_data.clone(),
new_node_data,
GraphTraversalDir::UsedWith,
)?;
self.partitions.push(new_nodeset_data.clone());
Ok((new_nodeset_data, AffectOk::Done))
}