Adds a variable to the symbol table.

@param int                $type
@param string             $name
@param CompilationContext $compilationContext

@return Variable
5250
public function addVariable($type, $name, CompilationContext $compilationContext)
    {
        $currentBranch = $compilationContext->branchManager->getCurrentBranch();
        $branchId = $currentBranch->getUniqueId();
        if ($this->globalsManager->isSuperGlobal($name) || 'zephir_fcall_cache_entry' == $type) {
            $branchId = 1;
        }

        $varName = $name;
        if ($branchId > 1 && Branch::TYPE_ROOT != $currentBranch->getType()) {
            $varName = $name.Variable::BRANCH_MAGIC.$branchId;
        }

        $variable = new Variable($type, $varName, $currentBranch);

        /*
         * Checks whether a variable can be optimized to be static or not
         */
        if ('variable' == $type && $this->localContext && $this->localContext->shouldBeLocal($name)) {
            $variable->setLocalOnly(true);
        }

        if (!isset($this->branchVariables[$branchId])) {
            $this->branchVariables[$branchId] = [];
        }

        $this->branchVariables[$branchId][$name] = $variable;

        return $variable;
    }
823811
public function compile(CompilationContext $compilationContext)
    {
        $readDetector = new ReadDetector();

        $statement = $this->statement;
        foreach ($statement['assignments'] as $assignment) {
            $variable = $assignment['variable'];

            /*
             * Get the symbol from the symbol table if necessary
             */
            switch ($assignment['assign-type']) {
                case 'static-property':
                case 'static-property-append':
                case 'static-property-array-index':
                case 'static-property-array-index-append':
                case 'dynamic-variable-string':
                    $symbolVariable = null;
                    break;

                case 'array-index':
                case 'variable-append':
                case 'object-property':
                case 'array-index-append':
                case 'string-dynamic-object-property':
                case 'variable-dynamic-object-property':
                    $symbolVariable = $compilationContext->symbolTable->getVariableForUpdate($variable, $compilationContext, $assignment);
                    break;

                default:
                    $symbolVariable = $compilationContext->symbolTable->getVariableForWrite($variable, $compilationContext, $assignment);
                    break;
            }

            /*
             * Incr/Decr assignments don't require an expression
             */
            if (isset($assignment['expr'])) {
                $expr = new Expression($assignment['expr']);

                switch ($assignment['assign-type']) {
                    case 'variable':
                        if (!$readDetector->detect($variable, $assignment['expr'])) {
                            if (isset($assignment['operator'])) {
                                if ('assign' == $assignment['operator']) {
                                    $expr->setExpectReturn(true, $symbolVariable);
                                }
                            } else {
                                $expr->setExpectReturn(true, $symbolVariable);
                            }
                        } else {
                            if (isset($assignment['operator'])) {
                                if ('assign' == $assignment['operator']) {
                                    $expr->setExpectReturn(true);
                                }
                            } else {
                                $expr->setExpectReturn(true);
                            }
                        }
                        break;
                }

                switch ($assignment['expr']['type']) {
                    case 'property-access':
                    case 'array-access':
                    case 'type-hint':
                        $expr->setReadOnly(true);
                        break;
                }

                $resolvedExpr = $expr->compile($compilationContext);

                /*
                 * Bad implemented operators could return values different than objects
                 */
                if (!\is_object($resolvedExpr)) {
                    throw new CompilerException('Resolved expression is not valid', $assignment['expr']);
                }
            }

            if ($symbolVariable) {
                $variable = $symbolVariable->getName();
            }

            /*
             * There are four types of assignments
             */
            switch ($assignment['assign-type']) {
                case 'variable':
                    $let = new LetVariable();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $readDetector, $compilationContext, $assignment);
                    break;

                case 'variable-append':
                    $let = new LetVariableAppend();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'object-property':
                    $let = new LetObjectProperty();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'variable-dynamic-object-property':
                    $let = new LetObjectDynamicProperty();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'string-dynamic-object-property':
                    $let = new LetObjectDynamicStringProperty();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'static-property':
                    $let = new LetStaticProperty();
                    $let->assignStatic($variable, $assignment['property'], $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'static-property-append':
                    $let = new LetStaticPropertyAppend();
                    $let->assignStatic($variable, $assignment['property'], $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'static-property-array-index':
                    $let = new LetStaticPropertyArrayIndex();
                    $let->assignStatic($variable, $assignment['property'], $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'static-property-array-index-append':
                    $let = new LetStaticPropertyArrayIndexAppend();
                    $let->assignStatic($variable, $assignment['property'], $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'array-index':
                    $let = new LetArrayIndex();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'array-index-append':
                    $let = new LetArrayIndexAppend();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'object-property-append':
                    $let = new LetObjectPropertyAppend();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'object-property-array-index':
                    $let = new LetObjectPropertyArrayIndex();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'object-property-array-index-append':
                    $let = new LetObjectPropertyArrayIndexAppend();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'incr':
                    $let = new LetIncr();
                    $let->assign($variable, $symbolVariable, $compilationContext, $assignment);
                    break;

                case 'decr':
                    $let = new LetDecr();
                    $let->assign($variable, $symbolVariable, $compilationContext, $assignment);
                    break;

                case 'object-property-incr':
                    $let = new LetObjectPropertyIncr();
                    $let->assign($variable, $assignment['property'], $symbolVariable, $compilationContext, $assignment);
                    break;

                case 'object-property-decr':
                    $let = new LetObjectPropertyDecr();
                    $let->assign($variable, $assignment['property'], $symbolVariable, $compilationContext, $assignment);
                    break;

                case 'dynamic-variable':
                    $let = new LetExportSymbol();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                    break;

                case 'dynamic-variable-string':
                    $let = new LetExportSymbolString();
                    $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                    break;

                default:
                    throw new CompilerException('Unknown assignment: '.$assignment['assign-type'], $assignment);
            }
        }
    }
96601
public function createConstant($name, $type = NULL, $default = self::UNDEFINED, $modifiers = GConstant::MODIFIER_PROTECTED) {
    $gConstant = GConstant::create($name, $type, $default, $modifiers);
    
    $this->addConstant($gConstant);
    return $gConstant;
  }
1019420
public function compile(CompilationContext $compilationContext)
    {
        $this->processValue($compilationContext);

        $constanValue = isset($this->value['value']) ? $this->value['value'] : null;

        $compilationContext->backend->declareConstant(
            $this->value['type'],
            $this->getName(),
            $constanValue,
            $compilationContext
        );
    }
1286102
public function compile($expression, CompilationContext $compilationContext)
    {
        /*
         * Resolves the symbol that expects the value
         */
        if ($this->expecting) {
            if ($this->expectingVariable) {
                $symbolVariable = $this->expectingVariable;
                if ('variable' != $symbolVariable->getType()) {
                    throw new CompilerException('Cannot use variable type: '.$symbolVariable->getType().' to store a reference', $expression);
                }
            } else {
                $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression);
            }
        } else {
            $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression);
        }

        $leftExpr = new Expression($expression['left']);
        $leftExpr->setReadOnly($this->readOnly);
        $left = $leftExpr->compile($compilationContext);

        switch ($left->getType()) {
            case 'variable':
            case 'string':
            case 'object':
            case 'array':
            case 'callable':
                break;
            default:
                throw new CompilerException('Cannot obtain a reference from type: '.$left->getType(), $expression);
        }

        $leftVariable = $compilationContext->symbolTable->getVariableForRead($left->getCode(), $compilationContext, $expression);
        switch ($leftVariable->getType()) {
            case 'variable':
            case 'string':
            case 'object':
            case 'array':
            case 'callable':
                break;
            default:
                throw new CompilerException('Cannot obtain reference from variable type: '.$leftVariable->getType(), $expression);
        }

        $symbolVariable->setMustInitNull(true);
        $compilationContext->symbolTable->mustGrownStack(true);

        $symbolVariable->increaseVariantIfNull();
        $compilationContext->codePrinter->output('ZEPHIR_MAKE_REFERENCE('.$symbolVariable->getName().', '.$leftVariable->getName().');');

        return new CompiledExpression('reference', $symbolVariable->getRealName(), $expression);
    }
794930
public static function setter($name, $type)
  {
    $setter = self::method(
      'set' . ucfirst($name),
      [
        new ParameterGenerator($name, $type)
      ]
    );

    $setter->getDocBlock()->setTag(new GenericTag('return', 'static'));

    $body = "\$this->{$name} = \${$name};" . PHP_EOL
    . "return \$this;" . PHP_EOL;

    $setter->setBody($body);

    return $setter;
  }
1099999
protected function registerTempVariable($type, $location, Variable $variable, CompilationContext $compilationContext = null)
    {
        $compilationContext = $compilationContext ?: $this->compilationContext;
        $branchId = $compilationContext->branchManager->getCurrentBranchId();

        if (!isset($this->branchTempVariables[$branchId][$location][$type])) {
            $this->branchTempVariables[$branchId][$location][$type] = [];
        }
        $this->branchTempVariables[$branchId][$location][$type][] = $variable;
    }
549597
public function getVariable($name, $compilationContext = null)
    {
        /* Check if the variable already is referencing a branch */
        $pos = strpos($name, Variable::BRANCH_MAGIC);
        if ($pos > -1) {
            $branchId = (int) (substr($name, $pos + \strlen(Variable::BRANCH_MAGIC)));
            $name = substr($name, 0, $pos);
        } else {
            $branch = $this->resolveVariableToBranch($name, $compilationContext ?: $this->compilationContext);
            if (!$branch) {
                return false;
            }
            $branchId = $branch->getUniqueId();
        }
        if (!isset($this->branchVariables[$branchId]) || !isset($this->branchVariables[$branchId][$name])) {
            return false;
        }

        return $this->branchVariables[$branchId][$name];
    }
105890
public function addColumn($name, $type, $length = null)
    {
        $column = new MDatabaseTableColumn($name, $type, $length);
        array_push($this->columns, $column);
    }
1039632
protected function declareProperty(CompilationContext $compilationContext, $type, $value)
    {
        $codePrinter = $compilationContext->codePrinter;

        if (\is_object($value)) {
            return;
        }

        $classEntry = $compilationContext->classDefinition->getClassEntry();

        switch ($type) {
            case 'long':
            case 'int':
                $codePrinter->output('zend_declare_property_long('.$classEntry.', SL("'.$this->getName().'"), '.$value.', '.$this->getVisibilityAccessor().' TSRMLS_CC);');
                break;

            case 'double':
                $codePrinter->output('zend_declare_property_double('.$classEntry.', SL("'.$this->getName().'"), '.$value.', '.$this->getVisibilityAccessor().' TSRMLS_CC);');
                break;

            case 'bool':
                $codePrinter->output('zend_declare_property_bool('.$classEntry.', SL("'.$this->getName().'"), '.$this->getBooleanCode($value).', '.$this->getVisibilityAccessor().' TSRMLS_CC);');
                break;

            case Types::T_CHAR:
            case Types::T_STRING:
                $codePrinter->output(
                    sprintf(
                        'zend_declare_property_string(%s, SL("%s"), "%s", %s TSRMLS_CC);',
                        $classEntry,
                        $this->getName(),
                        add_slashes($value),
                        $this->getVisibilityAccessor()
                    )
                );
                break;

            case 'array':
            case 'empty-array':
            case 'null':
                $codePrinter->output('zend_declare_property_null('.$classEntry.', SL("'.$this->getName().'"), '.$this->getVisibilityAccessor().' TSRMLS_CC);');
                break;

            default:
                throw new CompilerException('Unknown default type: '.$type, $this->original);
        }
    }
1139371
public LocalVariableInfo addLocalVariable(String typeQualifiedName, String name) {
    return contextLayers.getFirst().addLocalVariable(typeQualifiedName, name);
  }
1351007
public function assign($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, $statement)
    {
        if (!$symbolVariable->isInitialized()) {
            throw new CompilerException("Cannot mutate variable '".$variable."' because it is not initialized", $statement);
        }

        if (!$symbolVariable->isVariable()) {
            throw new CompilerException("Variable type '".$symbolVariable->getType()."' cannot be used as object", $statement);
        }

        $propertyName = $statement['property'];
        $className = $compilationContext->classDefinition->getCompleteName();

        if (!$symbolVariable->isInitialized()) {
            throw new CompilerException("Cannot mutate static property '".$className.'::'.$propertyName."' because it is not initialized", $statement);
        }

        if (!$symbolVariable->isVariable()) {
            throw new CompilerException('Cannot use variable type: '.$symbolVariable->getType().' as an object', $statement);
        }

        if ($symbolVariable->hasAnyDynamicType('unknown')) {
            throw new CompilerException('Cannot use non-initialized variable as an object', $statement);
        }

        /*
         * Trying to use a non-object dynamic variable as object
         */
        if ($symbolVariable->hasDifferentDynamicType(['undefined', 'object'])) {
            $compilationContext->logger->warning(
                'Possible attempt to update property on non-object dynamic property',
                ['non-valid-objectupdate', $statement]
            );
        }

        /*
         * Try to check if property is implemented on related object
         */
        if ('this' == $variable) {
            if (!$compilationContext->classDefinition->hasProperty($propertyName)) {
                throw new CompilerException("Property '".$propertyName."' is not defined on class '".$className."'", $statement);
            }
        }

        $codePrinter = $compilationContext->codePrinter;

        $compilationContext->headersManager->add('kernel/object');

        switch ($resolvedExpr->getType()) {
            case 'null':
                $compilationContext->backend->updateProperty($symbolVariable, $propertyName, 'null', $compilationContext);
                break;

            case 'int':
            case 'long':
            case 'uint':
                $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
                switch ($statement['operator']) {
                    case 'mul-assign':
                    case 'sub-assign':
                    case 'add-assign':
                        switch ($statement['operator']) {
                            case 'mul-assign':
                                $functionName = 'ZEPHIR_MUL_ASSIGN';
                                break;
                            case 'sub-assign':
                                $functionName = 'ZEPHIR_SUB_ASSIGN';
                                break;
                            case 'add-assign':
                                $functionName = 'ZEPHIR_ADD_ASSIGN';
                                break;
                        }

                        $resolvedVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                        $compilationContext->backend->assignLong($resolvedVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
                        $compilationContext->backend->fetchProperty($tempVariable, $symbolVariable, $propertyName, false, $compilationContext);
                        $codePrinter->output($functionName.'('.$compilationContext->backend->getVariableCode($tempVariable).', '.$compilationContext->backend->getVariableCode($resolvedVariable).')');
                        break;

                    case 'assign':
                        $tempVariable->initNonReferenced($compilationContext);
                        $compilationContext->backend->assignLong($tempVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
                        break;

                    default:
                        throw new CompilerException("Operator '".$statement['operator']."' is not supported for object property: ".$tempVariable->getType(), $statement);
                }

                $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
                $tempVariable->setIdle(true);
                break;

            case 'char':
                $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
                switch ($statement['operator']) {
                    case 'assign':
                        $tempVariable->initNonReferenced($compilationContext);
                        $compilationContext->backend->assignLong($tempVariable, '\''.$resolvedExpr->getBooleanCode().'\'', $compilationContext);
                        break;

                    default:
                        throw new CompilerException("Operator '".$statement['operator']."' is not supported for object property: ".$tempVariable->getType(), $statement);
                }

                $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
                $tempVariable->setIdle(true);
                break;

            case 'double':
                $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
                switch ($statement['operator']) {
                    case 'mul-assign':
                    case 'sub-assign':
                    case 'add-assign':
                        switch ($statement['operator']) {
                            case 'mul-assign':
                                $functionName = 'ZEPHIR_MUL_ASSIGN';
                                break;
                            case 'sub-assign':
                                $functionName = 'ZEPHIR_SUB_ASSIGN';
                                break;
                            case 'add-assign':
                                $functionName = 'ZEPHIR_ADD_ASSIGN';
                                break;
                        }

                        $resolvedVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                        $compilationContext->backend->assignDouble($resolvedVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
                        $compilationContext->backend->fetchProperty($tempVariable, $symbolVariable, $propertyName, false, $compilationContext);
                        $codePrinter->output($functionName.'('.$compilationContext->backend->getVariableCode($tempVariable).', '.$compilationContext->backend->getVariableCode($resolvedVariable).')');
                        break;

                    case 'assign':
                        $tempVariable->initNonReferenced($compilationContext);
                        $compilationContext->backend->assignDouble($tempVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
                        break;

                    default:
                        throw new CompilerException("Operator '".$statement['operator']."' is not supported for object property: ".$tempVariable->getType(), $statement);
                }

                $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
                $tempVariable->setIdle(true);
                break;

            case 'string':
                if ('ZendEngine2' == $compilationContext->backend->getName()) {
                    $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
                } else {
                    $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, false);
                }

                switch ($statement['operator']) {
                    case 'concat-assign':
                        $codePrinter->output('zephir_concat_self_str(&'.$tempVariable->getName().', "'.$resolvedExpr->getCode().'", sizeof("'.$resolvedExpr->getCode().'")-1 TSRMLS_CC);');
                        break;
                    case 'assign':
                        /* We only can use nonReferenced variables for not refcounted stuff in ZE3 */
                        if ('ZendEngine2' == $compilationContext->backend->getName()) {
                            $tempVariable->initNonReferenced($compilationContext);
                        } else {
                            $tempVariable->initVariant($compilationContext);
                        }
                        $compilationContext->backend->assignString($tempVariable, $resolvedExpr->getCode(), $compilationContext);
                        break;
                }

                $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
                $tempVariable->setIdle(true);
                break;

            case 'array':
                $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $resolvedExpr, $compilationContext);
                break;

            case 'bool':
                $codePrinter->output('if ('.$resolvedExpr->getBooleanCode().') {');
                $codePrinter->increaseLevel();
                $compilationContext->backend->updateProperty($symbolVariable, $propertyName, 'true', $compilationContext);
                $codePrinter->decreaseLevel();
                $codePrinter->output('} else {');
                $codePrinter->increaseLevel();
                $compilationContext->backend->updateProperty($symbolVariable, $propertyName, 'false', $compilationContext);
                $codePrinter->decreaseLevel();
                $codePrinter->output('}');
                break;

            /* unreachable code */
            case 'empty-array':
                $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);

                $compilationContext->backend->initArray($tempVariable, $compilationContext);
                $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $resolvedExpr->getCode(), $compilationContext);
                $tempVariable->setIdle(true);
                break;

            case 'variable':
                $variableVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
                switch ($variableVariable->getType()) {
                    case 'int':
                    case 'uint':
                    case 'long':
                    case 'ulong':
                    case 'char':
                    case 'uchar':
                        $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                        $compilationContext->backend->assignLong($tempVariable, $variableVariable, $compilationContext);
                        $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
                        $tempVariable->setIdle(true);
                        break;

                    case 'double':
                        $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                        $compilationContext->backend->assignDouble($tempVariable, $variableVariable, $compilationContext);
                        $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
                        $tempVariable->setIdle(true);
                        break;

                    case 'bool':
                        $codePrinter->output('if ('.$variableVariable->getName().') {');
                        $codePrinter->increaseLevel();
                        $compilationContext->backend->updateProperty($symbolVariable, $propertyName, 'true', $compilationContext);
                        $codePrinter->decreaseLevel();
                        $codePrinter->output('} else {');
                        $codePrinter->increaseLevel();
                        $compilationContext->backend->updateProperty($symbolVariable, $propertyName, 'false', $compilationContext);
                        $codePrinter->decreaseLevel();
                        $codePrinter->output('}');
                        break;

                    case 'array':
                    case 'string':
                    case 'variable':
                        $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $variableVariable, $compilationContext);
                        if ($symbolVariable->isTemporal()) {
                            $symbolVariable->setIdle(true);
                        }
                        break;

                    default:
                        throw new CompilerException('Unknown type '.$variableVariable->getType(), $statement);
                }
                break;

            default:
                throw new CompilerException('Unknown type '.$resolvedExpr->getType(), $statement);
        }
    }
1284298
private function sourceDeclaration(string $name, string $type, string $model): SourceDeclaration
    {
        return new SourceDeclaration(
            $this->getConfig()->className('source', $name),
            $type,
            $model
        );
    }
103434
private function provideProductAttribute($type, $name, $code = null)
    {
        $code = $code ?: StringInflector::nameToCode($name);

        /** @var ProductAttributeInterface $productAttribute */
        $productAttribute = $this->productAttributeRepository->findOneBy(['code' => $code]);
        if (null !== $productAttribute) {
            return $productAttribute;
        }

        $productAttribute = $this->createProductAttribute($type, $name, $code);
        $this->saveProductAttribute($productAttribute);

        return $productAttribute;
    }
511614
public function initVariant(CompilationContext $compilationContext)
    {
        if ($this->numberSkips) {
            --$this->numberSkips;

            return;
        }

        /*
         * Variables are allocated for the first time using ZEPHIR_INIT_VAR
         * the second, third, etc times are allocated using ZEPHIR_INIT_NVAR
         * Variables initialized for the first time in a cycle are always initialized using ZEPHIR_INIT_NVAR
         */
        if ('this_ptr' != $this->getName() && 'return_value' != $this->getName()) {
            if (false === $this->initBranch) {
                $this->initBranch = $compilationContext->currentBranch;
            }

            $compilationContext->headersManager->add('kernel/memory');

            if (!$this->isLocalOnly()) {
                $compilationContext->symbolTable->mustGrownStack(true);
                if ($compilationContext->insideCycle) {
                    $this->mustInitNull = true;
                    $compilationContext->backend->initVar($this, $compilationContext, true, true);
                } else {
                    if ($this->variantInits > 0) {
                        if (0 === $this->initBranch) {
                            $compilationContext->codePrinter->output('ZEPHIR_INIT_BNVAR('.$this->getName().');');
                        } else {
                            $this->mustInitNull = true;
                            $compilationContext->backend->initVar($this, $compilationContext, true, true);
                        }
                    } else {
                        $compilationContext->backend->initVar($this, $compilationContext);
                    }
                }
            } else {
                if ($this->variantInits > 0 || $compilationContext->insideCycle) {
                    $this->mustInitNull = true;
                    $compilationContext->codePrinter->output('ZEPHIR_SINIT_NVAR('.$this->getName().');');
                } else {
                    $compilationContext->codePrinter->output('ZEPHIR_SINIT_VAR('.$this->getName().');');
                }
            }

            ++$this->variantInits;
            $this->associatedClass = null;
        }
    }
933050
public function getVariableForRead($name, CompilationContext $compilationContext = null, array $statement = null)
    {
        /*
         * Validate that 'this' cannot be used in a static function
         */
        if ('this' == $name || 'this_ptr' == $name) {
            if ($compilationContext->staticContext) {
                throw new CompilerException("Cannot use variable 'this' in static context", $statement);
            }
        }

        /*
         * Create superglobals just in time
         */
        if ($this->globalsManager->isSuperGlobal($name)) {
            if (!$this->hasVariable($name)) {
                /**
                 * @TODO, injecting globals, initialize to null and check first?
                 */
                $variable = new Variable('variable', $name, $compilationContext->branchManager->getCurrentBranch());
                $variable->setIsInitialized(true, $compilationContext);
                $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 ('return_value' != $name && 'this' != $name) {
                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);
                                }
                                break;
                        }
                    }

                    $initBranches = $variable->getInitBranches();

                    $currentBranch = $compilationContext->branchManager->getCurrentBranch();
                    /** @var Branch[] $branches */
                    $branches = array_reverse($initBranches);

                    if (1 == \count($branches)) {
                        if (Branch::TYPE_CONDITIONAL_TRUE == $branches[0]->getType()) {
                            if (true === $branches[0]->isUnreachable()) {
                                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 (false === $branches[0]->isUnreachable()) {
                                    throw new CompilerException('Initialization of variable "'.$name.'" depends on unreachable branch, consider initialize at its declaration', $statement);
                                }
                            }
                        }

                        $tempBranch = $branches[0]->getParentBranch();
                        while ($tempBranch) {
                            if (Branch::TYPE_CONDITIONAL_TRUE == $tempBranch->getType()) {
                                if (true === $tempBranch->isUnreachable()) {
                                    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::TYPE_ROOT == $branch->getType() || Branch::TYPE_EXTERNAL == $branch->getType()) {
                            $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 (Branch::TYPE_CONDITIONAL_TRUE == $branches[0]->getType()) {
                                    $evalExpression = $branches[0]->getRelatedStatement()->getEvalExpression();

                                    if (true === $evalExpression->isUnreachable()) {
                                        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 (Branch::TYPE_CONDITIONAL_FALSE == $branches[0]->getType()) {
                                        $evalExpression = $branches[0]->getRelatedStatement()->getEvalExpression();

                                        if (true === $evalExpression->isUnreachableElse()) {
                                            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;
    }
1079273
public function compile(CompilationContext $compilationContext)
    {
        $compilationContext->headersManager->add('kernel/array');
        $expression = $this->statement['expr'];

        $flags = 'PH_SEPARATE';

        if ('list' == $expression['type']) {
            $expression = $expression['left'];
        }

        switch ($expression['type']) {
            case 'array-access':
                $expr = new Expression($expression['left']);
                $expr->setReadOnly(true);
                $exprVar = $expr->compile($compilationContext);
                $variable = $compilationContext->symbolTable->getVariableForWrite($exprVar->getCode(), $compilationContext, $this->statement);

                $expr = new Expression($expression['right']);
                $expr->setReadOnly(true);
                $exprIndex = $expr->compile($compilationContext);
                break;

            case 'property-access':
                $expr = new Expression($expression['left']);
                $expr->setReadOnly(true);
                $exprVar = $expr->compile($compilationContext);
                $variable = $compilationContext->symbolTable->getVariableForWrite($exprVar->getCode(), $compilationContext, $this->statement);
                $variableCode = $compilationContext->backend->getVariableCode($variable);

                $compilationContext->headersManager->add('kernel/object');
                $compilationContext->codePrinter->output('zephir_unset_property('.$variableCode.', "'.$expression['right']['value'].'" TSRMLS_CC);');

                return true;

            case 'property-dynamic-access':
                //@todo fix it

            default:
                throw new CompilerException('Cannot use expression type: '.$expression['type'].' in "unset"', $expression);
        }

        if (!\in_array($variable->getType(), ['variable', 'array'])) {
            throw new CompilerException('Cannot use variable type: '.$variable->gettype().' in "unset"', $expression['left']);
        }

        if ($variable->hasDifferentDynamicType(['undefined', 'array', 'object', 'null'])) {
            $compilationContext->logger->warning(
                'Possible attempt to use non array/object in unset operator',
                ['non-valid-unset', $expression['left']]
            );
        }

        $compilationContext->backend->arrayUnset($variable, $exprIndex, $flags, $compilationContext);
    }