private function caseGettypeFunctionCall(\PHPParser_Node $node, PhpType $type, $value, $resultEqualsValue, LinkedFlowScope $blindScope) { $restrictedType = $this->getRestrictedByGettypeResult($type, $value, $resultEqualsValue); // cannot narrow the scope if (null === $restrictedType) { return $blindScope; } $informed = $blindScope->createChildFlowScope(); $this->declareNameInScope($informed, $node, $restrictedType); return $informed; }
private function traverseShortCircuitingBinOp(\PHPParser_Node $node, LinkedFlowScope $scope, $condition) { $left = $node->left; $right = $node->right; // Type the left node. $leftLiterals = $this->traverseWithinShortCircuitingBinOp($left, $scope->createChildFlowScope()); $leftType = $left->getAttribute('type'); // As these operations are short circuiting, we can reverse interpreter the left node as we know the // outcome to its evaluation if we are ever going to reach the right node. $rightScope = $this->reverseInterpreter->getPreciserScopeKnowingConditionOutcome($left, $leftLiterals->getOutcomeFlowScope($left, $condition), $condition); // Now, type the right node in the updated scope. $rightLiterals = $this->traverseWithinShortCircuitingBinOp($right, $rightScope->createChildFlowScope()); $rightType = $right->getAttribute('type'); if (null === $leftType || null === $rightType) { return new BooleanOutcomePair($this, array(true, false), array(true, false), $leftLiterals->getJoinedFlowScope(), $rightLiterals->getJoinedFlowScope()); } // In PHP, binary operations are always of boolean type. $node->setAttribute('type', $this->typeRegistry->getNativeType('boolean')); if ($leftLiterals->toBooleanOutcomes === array(!$condition)) { // Use the restricted left type, since the right side never gets evaluated. return $leftLiterals; } // Use the join of the restricted left type knowing the outcome of the // ToBoolean predicate of the right type. return BooleanOutcomePair::fromPairs($this, $leftLiterals, $rightLiterals, $condition); }