protected function joinInputs(GraphNode $node)
 {
     if ($this->cfg->getEntryPoint() === $node) {
         $node->setAttribute(self::ATTR_FLOW_STATE_IN, $this->createEntryLattice());
         return;
     }
     $predNodes = $this->cfg->getDirectedPredNodes($node);
     if (!$predNodes) {
         return;
     }
     $values = array();
     foreach ($predNodes as $predNode) {
         $succNodes = $this->cfg->getDirectedSuccNodes($predNode);
         $index = array_search($node, $succNodes, true);
         $outStates = $predNode->getAttribute(self::ATTR_FLOW_STATE_OUT);
         $values[] = $outStates[$index];
     }
     if (!$values) {
         return;
     }
     $newInState = call_user_func($this->joinOp, $values);
     $node->setAttribute(self::ATTR_FLOW_STATE_IN, $newInState);
 }
 protected function flow(GraphNode $node)
 {
     if ($this->isForward()) {
         $outBefore = $node->getAttribute(self::ATTR_FLOW_STATE_OUT);
         $outAfter = $this->flowThrough($node->getAstNode(), $node->getAttribute(self::ATTR_FLOW_STATE_IN));
         $node->setAttribute(self::ATTR_FLOW_STATE_OUT, $outAfter);
         return false === $outBefore->equals($outAfter);
     }
     $inBefore = $node->getAttribute(self::ATTR_FLOW_STATE_IN);
     $inAfter = $this->flowThrough($node->getAstNode(), $node->getAttribute(self::ATTR_FLOW_STATE_OUT));
     $node->setAttribute(self::ATTR_FLOW_STATE_IN, $inAfter);
     return false === $inBefore->equals($inAfter);
 }