Zephir\SymbolTable::getVariableForRead PHP Method

getVariableForRead() public method

Return a variable in the symbol table, it will be used for a read operation
public getVariableForRead ( string $name, zephir\CompilationContext $compilationContext = null, array $statement = null ) : Variable
$name string
$compilationContext zephir\CompilationContext
$statement array
return Variable
    public function getVariableForRead($name, CompilationContext $compilationContext = null, array $statement = null)
    {
        /**
         * Validate that 'this' cannot be used in a static function
         */
        if ($name == 'this' || $name == 'this_ptr') {
            if ($compilationContext->staticContext) {
                throw new CompilerException("Cannot use variable 'this' in static context", $statement);
            }
        }
        /**
         * Create superglobals just in time
         */
        if ($this->isSuperGlobal($name)) {
            if (!$this->hasVariable($name)) {
                /**
                 * @TODO, injecting globals, initialize to null and check first?
                 */
                $variable = new Variable('variable', $name, $compilationContext->currentBranch);
                $variable->setIsInitialized(true, $compilationContext, $statement);
                $variable->setDynamicTypes('array');
                $variable->setIsExternal(true);
                $this->addRawVariable($variable);
            } else {
                $variable = $this->getVariable($name);
            }
            $variable->increaseUses();
            return $variable;
        }
        if (!$this->hasVariable($name)) {
            throw new CompilerException("Cannot read variable '" . $name . "' because it wasn't declared", $statement);
        }
        $variable = $this->getVariable($name);
        if (!$variable->isInitialized()) {
            /* DON'T REMOVE THIS!! */
            throw new CompilerException("Variable '" . $name . "' cannot be read because it's not initialized", $statement);
        }
        $variable->increaseUses();
        /**
         * Analise branches to detect possible initialization of variables in conditional branches
         */
        if (!$variable->isTemporal() && !$variable->getSkipVariant()) {
            if ($name != 'return_value' && $name != 'this') {
                if (is_object($compilationContext) && is_object($compilationContext->branchManager)) {
                    if ($compilationContext->config->get('check-invalid-reads', 'optimizations')) {
                        switch ($variable->getType()) {
                            case 'variable':
                            case 'string':
                            case 'array':
                                if (!$variable->isLocalOnly()) {
                                    $variable->setMustInitNull(true);
                                    $compilationContext->codePrinter->output('ZEPHIR_CHECK_POINTER(' . $variable->getName() . ');');
                                }
                                break;
                        }
                    }
                    $initBranches = $variable->getInitBranches();
                    $currentBranch = $compilationContext->branchManager->getCurrentBranch();
                    $branches = array_reverse($initBranches);
                    if (count($branches) == 1) {
                        if (Branch::TYPE_CONDITIONAL_TRUE == $branches[0]->getType()) {
                            if ($branches[0]->isUnreachable() === true) {
                                throw new CompilerException('Initialization of variable "' . $name . '" depends on unreachable branch, consider initialize it at its declaration', $statement);
                            }
                        } else {
                            if (Branch::TYPE_CONDITIONAL_FALSE == $branches[0]->getType()) {
                                if ($branches[0]->isUnreachable() === false) {
                                    throw new CompilerException('Initialization of variable "' . $name . '" depends on unreachable branch, consider initialize at its declaration', $statement);
                                }
                            }
                        }
                        $tempBranch = $branches[0]->getParentBranch();
                        while ($tempBranch) {
                            if ($tempBranch->getType() == Branch::TYPE_CONDITIONAL_TRUE) {
                                if ($tempBranch->isUnreachable() === true) {
                                    throw new CompilerException('Initialization of variable "' . $name . '" depends on unreachable branch, consider initialize it at its declaration', $statement);
                                }
                            }
                            $tempBranch = $tempBranch->getParentBranch();
                        }
                    }
                    $found = false;
                    foreach ($branches as $branch) {
                        /*+
                         * Variable was initialized in the same current branch
                         */
                        if ($branch == $currentBranch) {
                            $found = true;
                            break;
                        }
                        /**
                         * 'root' and 'external' branches are safe branches
                         */
                        if ($branch->getType() == Branch::TYPE_ROOT || $branch->getType() == Branch::TYPE_EXTERNAL) {
                            $found = true;
                            break;
                        }
                    }
                    if (!$found) {
                        /**
                         * Check if last assignment
                         * Variable was initialized in a sub-branch and it's being used in a parent branch
                         */
                        $possibleBadAssignment = false;
                        if ($currentBranch->getLevel() < $branches[0]->getLevel()) {
                            $possibleBadAssignment = true;
                        }
                        if ($possibleBadAssignment) {
                            if (count($branches) > 1) {
                                $graph = new BranchGraph();
                                foreach ($branches as $branch) {
                                    $graph->addLeaf($branch);
                                }
                                //echo $graph->getRoot()->show();
                            } else {
                                /**
                                 * Variable is assigned just once and it's assigned in a conditional branch
                                 */
                                if ($branches[0]->getType() == Branch::TYPE_CONDITIONAL_TRUE) {
                                    $evalExpression = $branches[0]->getRelatedStatement()->getEvalExpression();
                                    if ($evalExpression->isUnreachable() === true) {
                                        throw new CompilerException("Variable '" . $name . "' was assigned for the first time in conditional branch, consider initialize it at its declaration", $statement);
                                    } else {
                                        $variable->enableDefaultAutoInitValue();
                                        $compilationContext->logger->warning("Variable '" . $name . "' was assigned for the first time in conditional branch, consider initialize it at its declaration", 'conditional-initialization', $statement);
                                    }
                                } else {
                                    if ($branches[0]->getType() == Branch::TYPE_CONDITIONAL_FALSE) {
                                        $evalExpression = $branches[0]->getRelatedStatement()->getEvalExpression();
                                        if ($evalExpression->isUnreachableElse() === true) {
                                            throw new CompilerException("Variable '" . $name . "' was assigned for the first time in conditional branch, consider initialize it at its declaration", $statement);
                                        } else {
                                            $variable->enableDefaultAutoInitValue();
                                            $compilationContext->logger->warning("Variable '" . $name . "' was assigned for the first time in conditional branch, consider initialize it at its declaration", 'conditional-initialization', $statement);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        /**
         * Saves the latest place where the variable was used
         */
        $variable->setUsed(true, $statement);
        return $variable;
    }