use crate::internal_representation::{InteractionInternalRepresentation,InteractionOperatorRepresentation,CommonIoInteractionInterface};
pub trait FromInteractionTermToInternalRepresentation<CioII : CommonIoInteractionInterface> : Sized + Clone {
fn get_operator_at_root(&self) -> Option<CioII::InteractionOperatorType>;
fn get_subinteractions(&self) -> Vec<&Self>;
fn identify_pattern_at_interaction_leaf(&self) -> Option<CioII::InteractionLeafPatternType>;
fn merge_patterns_under_operator_if_possible(
parent_op : &CioII::InteractionOperatorType,
p1 : &CioII::InteractionLeafPatternType,
p2 : &CioII::InteractionLeafPatternType
) -> Option<CioII::InteractionLeafPatternType>;
fn get_associative_operands_recursively<'a>(
&'a self,
considered_associative_operator : &CioII::InteractionOperatorType
) -> Vec<&'a Self> {
let consider_sub_interactions = match self.get_operator_at_root() {
None => {
false
},
Some(got_at_root) => {
&got_at_root == considered_associative_operator
}
};
let mut operands : Vec<&Self> = Vec::new();
if consider_sub_interactions {
for sub_int in self.get_subinteractions() {
operands.extend(
sub_int.get_associative_operands_recursively(considered_associative_operator)
);
}
} else {
operands.push(self);
}
operands
}
fn to_io_repr(
&self,
merge_patterns : bool,
flatten_operands_under_associative_operators : bool
) -> InteractionInternalRepresentation<CioII> {
match self.identify_pattern_at_interaction_leaf() {
Some(pattern) => {
InteractionInternalRepresentation::LeafPattern(pattern)
},
None => {
let op_at_root = self.get_operator_at_root().unwrap();
let raw_operands = if flatten_operands_under_associative_operators && op_at_root.is_associative() {
self.get_associative_operands_recursively(&op_at_root)
} else {
self.get_subinteractions()
};
let mut operands = vec![];
let mut last_pattern : Option<<CioII as CommonIoInteractionInterface>::InteractionLeafPatternType> = None;
for raw_op in raw_operands {
let operand_io_repr = raw_op.to_io_repr(
merge_patterns,
flatten_operands_under_associative_operators
);
match operand_io_repr {
InteractionInternalRepresentation::LeafPattern(pt) => {
match last_pattern {
Some(prev_pt) => {
if merge_patterns {
match Self::merge_patterns_under_operator_if_possible(
&op_at_root,
&prev_pt,
&pt
) {
None => {
operands.push(
InteractionInternalRepresentation::LeafPattern(prev_pt)
);
last_pattern = Some(pt);
},
Some(merged_pt) => {
last_pattern = Some(merged_pt);
}
}
} else {
operands.push(
InteractionInternalRepresentation::LeafPattern(prev_pt)
);
last_pattern = Some(pt);
}
},
None => {
last_pattern = Some(pt);
}
}
},
_ => {
if let Some(prev_pt) = last_pattern {
operands.push(
InteractionInternalRepresentation::LeafPattern(prev_pt)
);
last_pattern = None;
}
operands.push(operand_io_repr);
}
}
}
if let Some(pt) = last_pattern {
operands.push(
InteractionInternalRepresentation::LeafPattern(pt)
);
}
debug_assert!(!operands.is_empty());
if operands.len() == 1 && op_at_root.arity() >= 2 {
operands.pop().unwrap()
} else {
InteractionInternalRepresentation::Operator(op_at_root, operands)
}
}
}
}
}