Compiles a 'for' statement that use an 'iterator' as expression.

@param array              $exprRaw
@param CompilationContext $compilationContext

@return bool
541679
public function compileIterator(array $exprRaw, CompilationContext $compilationContext)
    {
        $iteratorVariable = $compilationContext->symbolTable->getTempVariableForWrite('zend_object_iterator', $compilationContext);

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

        $codePrinter = $compilationContext->codePrinter;

        /**
         * Resolve first parameter of iterator(p).
         */
        $expr = new Expression($exprRaw['parameters'][0]['parameter']);
        $expr->setReadOnly(false);
        $expression = $expr->compile($compilationContext);

        if ('variable' != $expression->getType()) {
            throw new CompilerException('Unknown type: '.$expression->getType(), $exprRaw);
        }

        $exprVariable = $compilationContext->symbolTable->getVariableForRead($expression->getCode(), $compilationContext, $this->statement['expr']);
        switch ($exprVariable->getType()) {
            case 'variable':
                break;
        }

        /*
         * Initialize 'key' variable
         */
        if (isset($this->statement['key'])) {
            if ('_' != $this->statement['key']) {
                $keyVariable = $compilationContext->symbolTable->getVariableForWrite($this->statement['key'], $compilationContext, $this->statement['expr']);
                if ('variable' != $keyVariable->getType()) {
                    throw new CompilerException('Cannot use variable: '.$this->statement['key'].' type: '.$keyVariable->getType().' as key in hash traversal', $this->statement['expr']);
                }
            } else {
                /**
                 * Anonymous key variable.
                 */
                $keyVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                $keyVariable->increaseUses();
            }

            $keyVariable->setMustInitNull(true);
            $keyVariable->setIsInitialized(true, $compilationContext);
            $keyVariable->setDynamicTypes('undefined');
        }

        /*
         * Initialize 'value' variable
         */
        if (isset($this->statement['value'])) {
            if ('_' != $this->statement['value']) {
                $variable = $compilationContext->symbolTable->getVariableForWrite($this->statement['value'], $compilationContext, $this->statement['expr']);
                if ('variable' != $variable->getType()) {
                    throw new CompilerException('Cannot use variable: '.$this->statement['value'].' type: '.$variable->getType().' as value in hash traversal', $this->statement['expr']);
                }
            } else {
                /**
                 * Anonymous value variable.
                 */
                $variable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                $variable->increaseUses();
            }

            $variable->setMustInitNull(true);
            $variable->setIsInitialized(true, $compilationContext);
            $variable->setDynamicTypes('undefined');
        }

        /*
         * Variables are initialized in a different way inside cycle
         */
        ++$compilationContext->insideCycle;

        $codePrinter->output($iteratorVariable->getName().' = zephir_get_iterator('.$compilationContext->backend->getVariableCode($exprVariable).' TSRMLS_CC);');

        $codePrinter->output($iteratorVariable->getName().'->funcs->rewind('.$iteratorVariable->getName().' TSRMLS_CC);');
        $codePrinter->output('for (;'.$iteratorVariable->getName().'->funcs->valid('.$iteratorVariable->getName().' TSRMLS_CC) == SUCCESS && !EG(exception); '.$iteratorVariable->getName().'->funcs->move_forward('.$iteratorVariable->getName().' TSRMLS_CC)) {');

        if (isset($this->statement['key'])) {
            $compilationContext->symbolTable->mustGrownStack(true);
            $codePrinter->output("\t".'ZEPHIR_GET_IMKEY('.$this->statement['key'].', '.$iteratorVariable->getName().');');
        }

        if (isset($this->statement['value'])) {
            $compilationContext->symbolTable->mustGrownStack(true);
            $codePrinter->increaseLevel();
            $codePrinter->output('{');
            $codePrinter->increaseLevel();
            $compilationContext->backend->forStatementIterator($iteratorVariable, $variable, $compilationContext);
            $codePrinter->decreaseLevel();
            $codePrinter->output('}');
            $codePrinter->decreaseLevel();
        }

        /*
         * Compile statements in the 'for' block
         */
        if (isset($this->statement['statements'])) {
            $st = new StatementsBlock($this->statement['statements']);
            $st->isLoop(true);
            if (isset($this->statement['key'])) {
                $st->getMutateGatherer()->increaseMutations($this->statement['key']);
            }
            $st->getMutateGatherer()->increaseMutations($this->statement['value']);
            $st->compile($compilationContext);
        }

        /*
         * Restore the cycle counter
         */
        --$compilationContext->insideCycle;

        $codePrinter->output('}');

        $compilationContext->backend->destroyIterator($iteratorVariable, $compilationContext);
    }
145169
public function compile($expression, CompilationContext $compilationContext)
    {
        if (!isset($expression['left'])) {
            throw new CompilerException("Invalid 'left' operand for 'typeof' expression", $expression['left']);
        }

        $functionCall = BuilderFactory::getInstance()->statements()->functionCall('gettype', [$expression['left']]);
        $expression = new Expression($functionCall->build());

        return $expression->compile($compilationContext);
    }
134678
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() && 'array' != $symbolVariable->getType()) {
                    throw new CompilerException('Cannot use variable type: '.$symbolVariable->getType().' as an array', $expression);
                }
            } else {
                $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('array', $compilationContext, $expression);
            }
        } else {
            $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('array', $compilationContext, $expression);
        }

        if (!isset($expression['left'])) {
            if ($this->expectingVariable) {
                $symbolVariable->initVariant($compilationContext);
            }
            /*+
             * Mark the variable as an array
             */
            $symbolVariable->setDynamicTypes('array');

            return new CompiledExpression('array', $symbolVariable->getRealName(), $expression);
        }

        $codePrinter = $compilationContext->codePrinter;

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

        /**
         * This calculates a prime number bigger than the current array size to possibly
         * reduce hash collisions when adding new members to the array.
         */
        $arrayLength = \count($expression['left']);
        if ($arrayLength >= 33 && \function_exists('gmp_nextprime')) {
            $arrayLength = gmp_strval(gmp_nextprime($arrayLength - 1));
        }
        $oldSymbolVariable = $symbolVariable;
        if ($this->expectingVariable && $symbolVariable->geVariantInits() >= 1) {
            $symbolVariable = $compilationContext->symbolTable->addTemp('variable', $compilationContext);
            $symbolVariable->initVariant($compilationContext);
            $compilationContext->backend->initArray($symbolVariable, $compilationContext, $arrayLength > 0 ? $arrayLength : null);
            $symbolVariable->setDynamicTypes('array');
        } else {
            if ($this->expectingVariable) {
                $symbolVariable->initVariant($compilationContext);
            }
            /*+
             * Mark the variable as an array
             */
            $symbolVariable->setDynamicTypes('array');
            $compilationContext->backend->initArray($symbolVariable, $compilationContext, $arrayLength > 0 ? $arrayLength : null);
        }
        foreach ($expression['left'] as $item) {
            if (isset($item['key'])) {
                $key = null;
                $exprKey = new Expression($item['key']);
                $resolvedExprKey = $exprKey->compile($compilationContext);

                switch ($resolvedExprKey->getType()) {
                    case 'string':
                        $expr = new Expression($item['value']);
                        $resolvedExpr = $expr->compile($compilationContext);
                        switch ($resolvedExpr->getType()) {
                            case 'int':
                            case 'uint':
                            case 'long':
                            case 'ulong':
                            case 'double':
                                $compilationContext->backend->addArrayEntry($symbolVariable, $resolvedExprKey, $resolvedExpr, $compilationContext);
                                break;

                            case 'bool':
                                $compilationContext->headersManager->add('kernel/array');
                                if ('true' == $resolvedExpr->getCode()) {
                                    $compilationContext->backend->updateArray($symbolVariable, $resolvedExprKey, 'true', $compilationContext, 'PH_COPY | PH_SEPARATE');
                                } else {
                                    $compilationContext->backend->updateArray($symbolVariable, $resolvedExprKey, 'false', $compilationContext, 'PH_COPY | PH_SEPARATE');
                                }
                                break;

                            case 'string':
                                $compilationContext->backend->addArrayEntry($symbolVariable, $resolvedExprKey, $resolvedExpr, $compilationContext);
                                break;

                            case 'null':
                                $compilationContext->backend->updateArray($symbolVariable, $resolvedExprKey, 'null', $compilationContext, 'PH_COPY | PH_SEPARATE');
                                break;

                            case 'array':
                            case 'variable':
                                $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                                $compilationContext->backend->updateArray($symbolVariable, $resolvedExprKey, $valueVariable, $compilationContext, 'PH_COPY | PH_SEPARATE');
                                if ($valueVariable->isTemporal()) {
                                    $valueVariable->setIdle(true);
                                }
                                break;

                            default:
                                throw new CompilerException('Invalid value type: '.$resolvedExpr->getType(), $item['value']);
                        }
                        break;

                    case 'int':
                    case 'uint':
                    case 'long':
                    case 'ulong':
                        $expr = new Expression($item['value']);
                        $resolvedExpr = $expr->compile($compilationContext);
                        switch ($resolvedExpr->getType()) {
                            case 'int':
                            case 'uint':
                            case 'long':
                            case 'ulong':
                            case 'double':
                            case 'string':
                                $compilationContext->backend->addArrayEntry($symbolVariable, $resolvedExprKey, $resolvedExpr, $compilationContext);
                                break;

                            case 'bool':
                                if ('true' == $resolvedExpr->getCode()) {
                                    $compilationContext->backend->updateArray($symbolVariable, $resolvedExprKey, 'true', $compilationContext, 'PH_COPY');
                                } else {
                                    $compilationContext->backend->updateArray($symbolVariable, $resolvedExprKey, 'false', $compilationContext, 'PH_COPY');
                                }
                                break;

                            case 'null':
                                $compilationContext->backend->updateArray($symbolVariable, $resolvedExprKey, 'null', $compilationContext, 'PH_COPY');
                                break;

                            case 'array':
                            case 'variable':
                                $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                                $compilationContext->backend->updateArray($symbolVariable, $resolvedExprKey, $valueVariable, $compilationContext, 'PH_COPY');
                                if ($valueVariable->isTemporal()) {
                                    $valueVariable->setIdle(true);
                                }
                                break;

                            default:
                                throw new CompilerException('Invalid value type: '.$item['value']['type'], $item['value']);
                        }
                        break;

                    case 'variable':
                        $variableVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExprKey->getCode(), $compilationContext, $item['key']);
                        switch ($variableVariable->getType()) {
                            case 'int':
                            case 'uint':
                            case 'long':
                            case 'ulong':
                                $expr = new Expression($item['value']);
                                $resolvedExpr = $expr->compile($compilationContext);
                                switch ($resolvedExpr->getType()) {
                                    case 'int':
                                    case 'uint':
                                    case 'long':
                                    case 'ulong':
                                    case 'bool':
                                    case 'double':
                                    case 'null':
                                    case 'string':
                                        $compilationContext->backend->addArrayEntry($symbolVariable, $resolvedExprKey, $resolvedExpr, $compilationContext);
                                        break;

                                    case 'variable':
                                        $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                                        $compilationContext->backend->updateArray($symbolVariable, $resolvedExprKey, $valueVariable, $compilationContext, 'PH_COPY');
                                        if ($valueVariable->isTemporal()) {
                                            $valueVariable->setIdle(true);
                                        }
                                        break;

                                    default:
                                        throw new CompilerException('Invalid value type: '.$item['value']['type'], $item['value']);
                                }
                                break;

                            case 'string':
                                $expr = new Expression($item['value']);
                                $resolvedExpr = $expr->compile($compilationContext);
                                switch ($resolvedExpr->getType()) {
                                    case 'int':
                                    case 'uint':
                                    case 'long':
                                    case 'ulong':
                                        $codePrinter->output('add_assoc_long_ex('.$symbolVariable->getName().', Z_STRVAL_P('.$resolvedExprKey->getCode().'), Z_STRLEN_P('.$item['key']['value'].'), '.$resolvedExpr->getCode().');');
                                        break;

                                    case 'double':
                                        $codePrinter->output('add_assoc_double_ex('.$symbolVariable->getName().', Z_STRVAL_P('.$resolvedExprKey->getCode().'), Z_STRLEN_P('.$item['key']['value'].'), '.$resolvedExpr->getCode().');');
                                        break;

                                    case 'bool':
                                        $codePrinter->output('add_assoc_bool_ex('.$symbolVariable->getName().', Z_STRVAL_P('.$resolvedExprKey->getCode().'), Z_STRLEN_P('.$item['key']['value'].'), '.$resolvedExpr->getBooleanCode().');');
                                        break;

                                    case 'string':
                                        $compilationContext->backend->addArrayEntry($symbolVariable, $resolvedExprKey, $resolvedExpr, $compilationContext);
                                        break;

                                    case 'null':
                                        $codePrinter->output('add_assoc_null_ex('.$symbolVariable->getName().', Z_STRVAL_P('.$resolvedExprKey->getCode().'), Z_STRLEN_P('.$item['key']['value'].') + 1);');
                                        break;

                                    case 'variable':
                                        $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                                        $compilationContext->backend->updateArray($symbolVariable, $resolvedExprKey, $resolvedExpr, $compilationContext);
                                        if ($valueVariable->isTemporal()) {
                                            $valueVariable->setIdle(true);
                                        }
                                        break;

                                    default:
                                        throw new CompilerException('Invalid value type: '.$resolvedExpr->getType(), $item['value']);
                                }
                                break;

                            case 'variable':
                                $expr = new Expression($item['value']);
                                $resolvedExpr = $expr->compile($compilationContext);
                                switch ($resolvedExpr->getType()) {
                                    case 'null':
                                    case 'bool':
                                        $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                                        $compilationContext->backend->updateArray($symbolVariable, $variableVariable, $valueVariable, $compilationContext);

                                        if ($valueVariable->isTemporal()) {
                                            $valueVariable->setIdle(true);
                                        }
                                        break;

                                    case 'variable':
                                        $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                                        $compilationContext->backend->updateArray($symbolVariable, $variableVariable, $valueVariable, $compilationContext);

                                        if ($valueVariable->isTemporal()) {
                                            $valueVariable->setIdle(true);
                                        }
                                        break;

                                    default:
                                        throw new CompilerException('Invalid value type: '.$item['value']['type'], $item['value']);
                                }
                                break;

                            default:
                                throw new CompilerException('Cannot use variable type: '.$variableVariable->getType().' as array index', $item['key']);
                        }
                        break;

                    default:
                        throw new CompilerException('Invalid key type: '.$resolvedExprKey->getType(), $item['key']);
                }
            } else {
                $expr = new Expression($item['value']);
                $resolvedExpr = $expr->compile($compilationContext);
                $itemVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                $symbol = $compilationContext->backend->getVariableCode($symbolVariable);
                $item = $compilationContext->backend->resolveValue($itemVariable, $compilationContext);
                $codePrinter->output('zephir_array_fast_append('.$symbol.', '.$item.');');
                if ($itemVariable->isTemporal()) {
                    $itemVariable->setIdle(true);
                }
            }
        }

        return new CompiledExpression('array', $symbolVariable->getRealName(), $expression);
    }
216318
public function compileHashTraverse($expression, CompilationContext $compilationContext, Variable $exprVariable)
    {
        /*
         * Initialize 'key' variable
         */
        if (isset($this->statement['key'])) {
            if ('_' != $this->statement['key']) {
                $keyVariable = $compilationContext->symbolTable->getVariableForWrite($this->statement['key'], $compilationContext, $this->statement['expr']);
                if ('variable' != $keyVariable->getType()) {
                    throw new CompilerException('Cannot use variable: '.$this->statement['key'].' type: '.$keyVariable->getType().' as key in hash traversal', $this->statement['expr']);
                }
            } else {
                $keyVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
            }

            $keyVariable->setMustInitNull(true);
            $keyVariable->setIsInitialized(true, $compilationContext);
            $keyVariable->setDynamicTypes('undefined');
        }

        /*
         * Initialize 'value' variable
         */
        if (isset($this->statement['value'])) {
            if ('_' != $this->statement['value']) {
                $variable = $compilationContext->symbolTable->getVariableForWrite($this->statement['value'], $compilationContext, $this->statement['expr']);
                if ('variable' != $variable->getType()) {
                    throw new CompilerException('Cannot use variable: '.$this->statement['value'].' type: '.$variable->getType().' as value in hash traversal', $this->statement['expr']);
                }
            } else {
                $variable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
            }

            $variable->setMustInitNull(true);
            $variable->setIsInitialized(true, $compilationContext);
            $variable->increaseVariantIfNull();
            $variable->setDynamicTypes('undefined');
        }

        /*
         * Variables are initialized in a different way inside cycle
         */
        ++$compilationContext->insideCycle;

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

        $duplicateHash = '0';
        $duplicateKey = true;

        /**
         * We have to check if hashes are modified within the for's block.
         */
        $st = null;
        if (isset($this->statement['statements'])) {
            /**
             * Create the statements block here to obtain the last use line.
             */
            $st = new StatementsBlock($this->statement['statements']);

            $detector = new ForValueUseDetector();
            if ($detector->detect($exprVariable->getName(), $this->statement['statements'])) {
                $duplicateHash = '1';
            }

            /*
             * Detect if the key is modified or passed to an external scope
             */
            if (isset($this->statement['key'])) {
                if (!$keyVariable->isTemporal()) {
                    $detector->setDetectionFlags(ForValueUseDetector::DETECT_ALL);
                    if ($detector->detect($keyVariable->getName(), $this->statement['statements'])) {
                        $duplicateKey = true;
                    }
                }
            }
        }

        $compilationContext->backend->forStatement(
            $exprVariable,
            isset($this->statement['key']) ? $keyVariable : null,
            isset($this->statement['value']) ? $variable : null,
            $duplicateKey,
            $duplicateHash,
            $this->statement,
            $st,
            $compilationContext
        );

        /*
         * Restore the cycle counter
         */
        --$compilationContext->insideCycle;
    }
701828
public function compile(CompilationContext $compilationContext)
    {
        $this->compiler = $compilationContext->compiler;

        /*
         * Sets the current object as global class definition
         */
        $compilationContext->classDefinition = $this;

        /*
         * Get the global codePrinter.
         */
        $codePrinter = $compilationContext->codePrinter;

        /*
         * The ZEPHIR_INIT_CLASS defines properties and constants exported by the class.
         */
        $initClassName = $this->getCNamespace().'_'.$this->getName();
        $codePrinter->output('ZEPHIR_INIT_CLASS('.$initClassName.') {');
        $codePrinter->outputBlankLine();

        $codePrinter->increaseLevel();

        /*
         * Method entry.
         */
        $methods = &$this->methods;
        $initMethod = $this->getLocalOrParentInitMethod();

        if (\count($methods) || $initMethod) {
            $methodEntry = strtolower($this->getCNamespace()).'_'.strtolower($this->getName()).'_method_entry';
        } else {
            $methodEntry = 'NULL';
        }

        foreach ($methods as $method) {
            $method->setupOptimized($compilationContext);
        }

        $namespace = str_replace('\\', '_', $compilationContext->config->get('namespace'));

        $flags = '0';
        if ($this->isAbstract()) {
            $flags = 'ZEND_ACC_EXPLICIT_ABSTRACT_CLASS';
        }
        if ($this->isFinal()) {
            if ('0' == $flags) {
                $flags = 'ZEND_ACC_FINAL_CLASS';
            } else {
                $flags .= '|ZEND_ACC_FINAL_CLASS';
            }
        }

        /*
         * Register the class with extends + interfaces.
         */
        $classExtendsDefinition = null;
        if ($this->extendsClass) {
            $classExtendsDefinition = $this->extendsClassDefinition;
            if ($classExtendsDefinition instanceof self && !$classExtendsDefinition->isBundled()) {
                $classEntry = $classExtendsDefinition->getClassEntry($compilationContext);
            } else {
                $classEntry = $this->getClassEntryByClassName($classExtendsDefinition->getName(), $compilationContext);
            }

            if ('class' == $this->getType()) {
                $codePrinter->output('ZEPHIR_REGISTER_CLASS_EX('.$this->getNCNamespace().', '.$this->getName().', '.$namespace.', '.strtolower($this->getSCName($namespace)).', '.$classEntry.', '.$methodEntry.', '.$flags.');');
                $codePrinter->outputBlankLine();
            } else {
                $codePrinter->output('ZEPHIR_REGISTER_INTERFACE_EX('.$this->getNCNamespace().', '.$this->getName().', '.$namespace.', '.strtolower($this->getSCName($namespace)).', '.$classEntry.', '.$methodEntry.');');
                $codePrinter->outputBlankLine();
            }
        } else {
            if ('class' == $this->getType()) {
                $codePrinter->output('ZEPHIR_REGISTER_CLASS('.$this->getNCNamespace().', '.$this->getName().', '.$namespace.', '.strtolower($this->getSCName($namespace)).', '.$methodEntry.', '.$flags.');');
            } else {
                $codePrinter->output('ZEPHIR_REGISTER_INTERFACE('.$this->getNCNamespace().', '.$this->getName().', '.$namespace.', '.strtolower($this->getSCName($namespace)).', '.$methodEntry.');');
            }
            $codePrinter->outputBlankLine();
        }

        /*
         * Compile properties.
         */
        foreach ($this->getProperties() as $property) {
            $docBlock = $property->getDocBlock();
            if ($docBlock) {
                $codePrinter->outputDocBlock($docBlock, true);
            }

            $property->compile($compilationContext);
            $codePrinter->outputBlankLine();
        }

        $initMethod = $this->getInitMethod();
        if ($initMethod) {
            $codePrinter->output($namespace.'_'.strtolower($this->getSCName($namespace)).'_ce->create_object = '.$initMethod->getName().';');
        }

        /*
         * Compile constants.
         */
        foreach ($this->getConstants() as $constant) {
            $docBlock = $constant->getDocBlock();
            if ($docBlock) {
                $codePrinter->outputDocBlock($docBlock, true);
            }

            $constant->compile($compilationContext);
            $codePrinter->outputBlankLine();
        }

        /**
         * Implemented interfaces.
         */
        $interfaces = $this->interfaces;
        $compiler = $compilationContext->compiler;

        if (\is_array($interfaces)) {
            $codePrinter->outputBlankLine(true);

            foreach ($interfaces as $interface) {
                /**
                 * Try to find the interface.
                 */
                $classEntry = false;

                if ($compiler->isInterface($interface)) {
                    $classInterfaceDefinition = $compiler->getClassDefinition($interface);
                    $classEntry = $classInterfaceDefinition->getClassEntry($compilationContext);
                } else {
                    if ($compiler->isBundledInterface($interface)) {
                        $classInterfaceDefinition = $compiler->getInternalClassDefinition($interface);
                        $classEntry = $this->getClassEntryByClassName($classInterfaceDefinition->getName(), $compilationContext);
                    }
                }

                if (!$classEntry) {
                    if ($compiler->isClass($interface)) {
                        throw new CompilerException(
                            sprintf(
                                'Cannot locate interface %s when implementing interfaces on %s. '.
                                '%s is currently a class',
                                $interface,
                                $this->getCompleteName(),
                                $interface
                            ),
                            $this->originalNode
                        );
                    } else {
                        throw new CompilerException(
                            sprintf(
                                'Cannot locate interface %s when implementing interfaces on %s',
                                $interface,
                                $this->getCompleteName()
                            ),
                            $this->originalNode
                        );
                    }
                }

                /*
                 * We don't check if abstract classes implement the methods in their interfaces
                 */
                if (!$this->isAbstract() && !$this->isInterface()) {
                    $this->checkInterfaceImplements($this, $classInterfaceDefinition);
                }

                $codePrinter->output('zend_class_implements('.$this->getClassEntry().' TSRMLS_CC, 1, '.$classEntry.');');
            }
        }

        if (!$this->isAbstract() && !$this->isInterface()) {
            /*
             * Interfaces in extended classes may have
             */
            if ($classExtendsDefinition) {
                if ($classExtendsDefinition instanceof self && !$classExtendsDefinition->isBundled()) {
                    $interfaces = $classExtendsDefinition->getImplementedInterfaces();
                    if (\is_array($interfaces)) {
                        foreach ($interfaces as $interface) {
                            $classInterfaceDefinition = null;
                            if ($compiler->isInterface($interface)) {
                                $classInterfaceDefinition = $compiler->getClassDefinition($interface);
                            } else {
                                if ($compiler->isBundledInterface($interface)) {
                                    $classInterfaceDefinition = $compiler->getInternalClassDefinition($interface);
                                }
                            }

                            if ($classInterfaceDefinition) {
                                $this->checkInterfaceImplements($this, $classInterfaceDefinition);
                            }
                        }
                    }
                }
            }
        }

        $codePrinter->output('return SUCCESS;');

        $codePrinter->outputBlankLine();
        $codePrinter->decreaseLevel();

        $codePrinter->output('}');
        $codePrinter->outputBlankLine();

        /*
         * Compile methods
         */
        foreach ($methods as $method) {
            $docBlock = $method->getDocBlock();
            if ($docBlock) {
                $codePrinter->outputDocBlock($docBlock);
            }

            if ('class' == $this->getType()) {
                if (!$method->isInternal()) {
                    $codePrinter->output('PHP_METHOD('.$this->getCNamespace().'_'.$this->getName().', '.$method->getName().') {');
                } else {
                    $codePrinter->output($compilationContext->backend->getInternalSignature($method, $compilationContext).' {');
                }
                $codePrinter->outputBlankLine();

                if (!$method->isAbstract()) {
                    $method->compile($compilationContext);
                }

                $codePrinter->output('}');
                $codePrinter->outputBlankLine();
            } else {
                $codePrinter->output('ZEPHIR_DOC_METHOD('.$this->getCNamespace().'_'.$this->getName().', '.$method->getName().');');
                $codePrinter->outputBlankLine();
            }
        }

        /**
         * Check whether classes must be exported.
         */
        $exportClasses = $compilationContext->config->get('export-classes', 'extra');
        if ($exportClasses) {
            $exportAPI = 'extern ZEPHIR_API';
        } else {
            $exportAPI = 'extern';
        }

        /**
         * Create a code printer for the header file.
         */
        $codePrinter = new CodePrinter();

        $codePrinter->outputBlankLine();
        $codePrinter->output($exportAPI.' zend_class_entry *'.$this->getClassEntry().';');
        $codePrinter->outputBlankLine();

        $codePrinter->output('ZEPHIR_INIT_CLASS('.$this->getCNamespace().'_'.$this->getName().');');
        $codePrinter->outputBlankLine();

        if ('class' == $this->getType()) {
            if (\count($methods)) {
                foreach ($methods as $method) {
                    if (!$method->isInternal()) {
                        $codePrinter->output('PHP_METHOD('.$this->getCNamespace().'_'.$this->getName().', '.$method->getName().');');
                    } else {
                        $internalSignature = $compilationContext->backend->getInternalSignature($method, $compilationContext);
                        $codePrinter->output($internalSignature.';');
                    }
                }
                $codePrinter->outputBlankLine();
            }
        }

        /*
         * Specifying Argument Information
         */
        foreach ($methods as $method) {
            $argInfo = new ArgInfoDefinition(
                $method->getArgInfoName($this),
                $method,
                $codePrinter,
                $compilationContext
            );

            $argInfo->setBooleanDefinition($this->compiler->backend->isZE3() ? '_IS_BOOL' : 'IS_BOOL');
            $argInfo->setRichFormat($this->compiler->backend->isZE3());

            $argInfo->render();
        }

        if (\count($methods)) {
            $codePrinter->output(
                sprintf(
                    'ZEPHIR_INIT_FUNCS(%s_%s_method_entry) {',
                    strtolower($this->getCNamespace()),
                    strtolower($this->getName())
                )
            );

            foreach ($methods as $method) {
                if ('class' == $this->getType()) {
                    if (!$method->isInternal()) {
                        $richFormat = $this->compiler->backend->isZE3() &&
                            $method->isReturnTypesHintDetermined() &&
                            $method->areReturnTypesCompatible();

                        if ($richFormat || $method->hasParameters()) {
                            $codePrinter->output(
                                sprintf(
                                    "\tPHP_ME(%s_%s, %s, %s, %s)",
                                    $this->getCNamespace(),
                                    $this->getName(),
                                    $method->getName(),
                                    $method->getArgInfoName($this),
                                    $method->getModifiers()
                                )
                            );
                        } else {
                            $codePrinter->output(
                                sprintf(
                                    "\tPHP_ME(%s_%s, %s, NULL, %s)",
                                    $this->getCNamespace(),
                                    $this->getName(),
                                    $method->getName(),
                                    $method->getModifiers()
                                )
                            );
                        }
                    }
                } else {
                    $richFormat = $this->compiler->backend->isZE3() &&
                            $method->isReturnTypesHintDetermined() &&
                            $method->areReturnTypesCompatible();

                    if ($method->isStatic()) {
                        if ($richFormat || $method->hasParameters()) {
                            $codePrinter->output(
                                sprintf(
                                    "\tZEND_FENTRY(%s, NULL, %s, ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_PUBLIC)",
                                    $method->getName(),
                                    $method->getArgInfoName($this)
                                )
                            );
                        } else {
                            $codePrinter->output(
                                sprintf(
                                    "\tZEND_FENTRY(%s, NULL, NULL, ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_PUBLIC)",
                                    $method->getName()
                                )
                            );
                        }
                    } else {
                        if ($richFormat || $method->hasParameters()) {
                            $codePrinter->output(
                                sprintf(
                                    "\tPHP_ABSTRACT_ME(%s_%s, %s, %s)",
                                    $this->getCNamespace(),
                                    $this->getName(),
                                    $method->getName(),
                                    $method->getArgInfoName($this)
                                )
                            );
                        } else {
                            $codePrinter->output(
                                sprintf(
                                    "\tPHP_ABSTRACT_ME(%s_%s, %s, NULL)",
                                    $this->getCNamespace(),
                                    $this->getName(),
                                    $method->getName()
                                )
                            );
                        }
                    }
                }
            }
            $codePrinter->output("\t".'PHP_FE_END');
            $codePrinter->output('};'); // ZEPHIR_INIT_FUNCS
        }

        $compilationContext->headerPrinter = $codePrinter;
    }
1212204
private function resolveOffsetExprs($offsetExprs, CompilationContext $compilationContext)
    {
        $keys = '';
        $offsetItems = [];
        $numberParams = 0;

        foreach ($offsetExprs as $offsetExpr) {
            if ('a' == $offsetExpr) {
                $keys .= 'a';
                ++$numberParams;
                continue;
            }
            switch ($offsetExpr->getType()) {
                case 'int':
                case 'uint':
                case 'long':
                case 'ulong':
                    $keys .= 'l';
                    $offsetItems[] = $offsetExpr->getCode();
                    ++$numberParams;
                    break;

                case 'string':
                    $keys .= 's';
                    $offsetItems[] = 'SL("'.$offsetExpr->getCode().'")';
                    $numberParams += 2;
                    break;

                case 'variable':
                    $variableIndex = $compilationContext->symbolTable->getVariableForRead(
                        $offsetExpr->getCode(),
                        $compilationContext,
                        null
                    );

                    switch ($variableIndex->getType()) {
                        case 'int':
                        case 'uint':
                        case 'long':
                        case 'ulong':
                            $keys .= 'l';
                            $offsetItems[] = $this->getVariableCode($variableIndex);
                            ++$numberParams;
                            break;
                        case 'string':
                        case 'variable':
                            $keys .= 'z';
                            $offsetItems[] = $this->getVariableCode($variableIndex);
                            ++$numberParams;
                            break;
                        default:
                            throw new CompilerException(
                                sprintf('Variable: %s cannot be used as array index', $variableIndex->getType()),
                                $offsetExpr->getOriginal()
                            );
                    }
                    break;

                default:
                    throw new CompilerException(
                        sprintf('Value: %s cannot be used as array index', $offsetExpr->getType()),
                        $offsetExpr->getOriginal()
                    );
            }
        }

        return [$keys, $offsetItems, $numberParams];
    }
253775
public function processValue(CompilationContext $compilationContext)
    {
        if ('constant' == $this->value['type']) {
            $constant = new Constants();
            $compiledExpression = $constant->compile($this->value, $compilationContext);

            $this->value = [
                'type' => $compiledExpression->getType(),
                'value' => $compiledExpression->getCode(),
            ];

            return;
        }

        if ('static-constant-access' == $this->value['type']) {
            $staticConstantAccess = new StaticConstantAccess();
            $compiledExpression = $staticConstantAccess->compile($this->value, $compilationContext);

            $this->value = [
                'type' => $compiledExpression->getType(),
                'value' => $compiledExpression->getCode(),
            ];

            return;
        }
    }
1042582
public function compile(CompilationContext $compilationContext)
    {
        $statement = $this->statement;

        $codePrinter = $compilationContext->codePrinter;

        if (isset($statement['expr'])) {
            $currentMethod = $compilationContext->currentMethod;

            if ($currentMethod->isConstructor()) {
                throw new CompilerException('Constructors cannot return values', $statement['expr']);
            }

            if ($currentMethod->isVoid()) {
                throw new CompilerException(
                    "Method is marked as 'void' and it must not return any value",
                    $statement['expr']
                );
            }

            /*
             * Use return member for properties on this
             */
            if ('property-access' == $statement['expr']['type']) {
                if ('variable' == $statement['expr']['left']['type']) {
                    if ('this' == $statement['expr']['left']['value']) {
                        if ('variable' == $statement['expr']['right']['type']) {
                            /*
                             * If the property is accessed on 'this', we check if the property does exist.
                             */
                            $property = $statement['expr']['right']['value'];
                            $classDefinition = $compilationContext->classDefinition;
                            if (!$classDefinition->hasProperty($property)) {
                                throw new CompilerException(
                                    sprintf(
                                        "Class '%s' does not have a property called: '%s'",
                                        $classDefinition->getCompleteName(),
                                        $property
                                    ),
                                    $statement['expr']['right']
                                );
                            }

                            $compilationContext->headersManager->add('kernel/object');
                            $codePrinter->output('RETURN_MM_MEMBER(getThis(), "'.$property.'");');

                            return;
                        }
                    }
                }
            }

            /*
             * Fetches return_value and tries to return the value directly there.
             */
            $variable = $compilationContext->symbolTable->getVariable('return_value');

            $expr = new Expression($statement['expr']);
            $expr->setExpectReturn(true, $variable);
            $expr->setReadOnly(true);
            $resolvedExpr = $expr->compile($compilationContext);

            /*
             * Here we check if the variable returns a compatible type according to its type hints
             */
            if ($currentMethod->hasReturnTypes()) {
                switch ($resolvedExpr->getType()) {
                    case Types::T_NULL:
                        if (false == $currentMethod->areReturnTypesNullCompatible()) {
                            throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
                        }
                        break;

                    case Types::T_INT:
                    case Types::T_UINT:
                    case Types::T_LONG:
                    case Types::T_ULONG:
                    case Types::T_CHAR:
                    case Types::T_UCHAR:
                        if (false == $currentMethod->areReturnTypesIntCompatible()) {
                            throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
                        }
                        break;

                    case Types::T_BOOL:
                        if (false == $currentMethod->areReturnTypesBoolCompatible()) {
                            throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
                        }
                        break;

                    case Types::T_DOUBLE:
                        if (false == $currentMethod->areReturnTypesDoubleCompatible()) {
                            throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
                        }
                        break;

                    case Types::T_STRING:
                    case Types::T_ISTRING:
                        if (false == $currentMethod->areReturnTypesStringCompatible()) {
                            throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
                        }
                        break;

                    case Types::T_VARIABLE:
                        $symbolVariable = $compilationContext->symbolTable->getVariableForRead(
                            $resolvedExpr->getCode(),
                            $compilationContext,
                            $statement['expr']
                        );

                        switch ($symbolVariable->getType()) {
                            case Types::T_INT:
                            case Types::T_UINT:
                            case Types::T_LONG:
                            case Types::T_ULONG:
                            case Types::T_CHAR:
                            case Types::T_UCHAR:
                                if (false == $currentMethod->areReturnTypesIntCompatible()) {
                                    throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
                                }
                                break;

                            case Types::T_DOUBLE:
                                if (false == $currentMethod->areReturnTypesDoubleCompatible()) {
                                    throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
                                }
                                break;

                            case Types::T_STRING:
                            case Types::T_ISTRING:
                                if (false == $currentMethod->areReturnTypesStringCompatible()) {
                                    throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
                                }
                                break;

                            case Types::T_BOOL:
                                if (false == $currentMethod->areReturnTypesBoolCompatible()) {
                                    throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
                                }
                                break;

                            case Types::T_VARIABLE:
                                break;
                        }
                        break;
                }
            }

            switch ($resolvedExpr->getType()) {
                case Types::T_NULL:
                    $codePrinter->output('RETURN_MM_NULL();');
                    break;

                case Types::T_INT:
                case Types::T_UINT:
                case Types::T_LONG:
                case Types::T_ULONG:
                case Types::T_CHAR:
                case Types::T_UCHAR:
                    $codePrinter->output('RETURN_MM_LONG('.$resolvedExpr->getCode().');');
                    break;

                case Types::T_BOOL:
                    $codePrinter->output('RETURN_MM_BOOL('.$resolvedExpr->getBooleanCode().');');
                    break;

                case Types::T_DOUBLE:
                    $codePrinter->output('RETURN_MM_DOUBLE('.$resolvedExpr->getCode().');');
                    break;

                case Types::T_STRING:
                case Types::T_ISTRING:
                    $compilationContext->backend->returnString(
                        add_slashes($resolvedExpr->getCode()),
                        $compilationContext
                    );
                    break;

                case Types::T_ARRAY:
                    if ('return_value' != $resolvedExpr->getCode()) {
                        $codePrinter->output('RETURN_CTOR('.$resolvedExpr->getCode().');');
                    } else {
                        $codePrinter->output('RETURN_MM();');
                    }
                    break;

                case Types::T_VARIABLE:
                    if (!isset($symbolVariable)) {
                        $symbolVariable = $compilationContext->symbolTable->getVariableForRead(
                            $resolvedExpr->getCode(),
                            $compilationContext,
                            $statement['expr']
                        );
                    }

                    switch ($symbolVariable->getType()) {
                        case Types::T_INT:
                        case Types::T_UINT:
                        case Types::T_LONG:
                        case Types::T_ULONG:
                        case Types::T_CHAR:
                        case Types::T_UCHAR:
                            $codePrinter->output('RETURN_MM_LONG('.$symbolVariable->getName().');');
                            break;

                        case Types::T_DOUBLE:
                            $codePrinter->output('RETURN_MM_DOUBLE('.$symbolVariable->getName().');');
                            break;

                        case Types::T_STRING:
                        case Types::T_ISTRING:
                        case Types::T_ARRAY:
                            $codePrinter->output(
                                'RETURN_CTOR('.$compilationContext->backend->getVariableCode($symbolVariable).');'
                            );
                            break;

                        case Types::T_BOOL:
                            $codePrinter->output('RETURN_MM_BOOL('.$symbolVariable->getName().');');
                            break;

                        case Types::T_VARIABLE:
                            if ('this_ptr' == $symbolVariable->getName()) {
                                $codePrinter->output('RETURN_THIS();');
                            } else {
                                if ('return_value' != $symbolVariable->getName()) {
                                    if (!$symbolVariable->isExternal()) {
                                        if ($symbolVariable->isLocalOnly()) {
                                            $codePrinter->output(
                                                sprintf(
                                                    'RETURN_LCTOR(%s);',
                                                    $compilationContext->backend->getVariableCode($symbolVariable)
                                                )
                                            );
                                        } else {
                                            if (!$symbolVariable->isMemoryTracked()) {
                                                $codePrinter->output(
                                                    sprintf(
                                                        'RETURN_CTOR(%s);',
                                                        $compilationContext->backend->getVariableCode($symbolVariable)
                                                    )
                                                );
                                            } else {
                                                $codePrinter->output(
                                                    sprintf(
                                                        'RETURN_CCTOR(%s);',
                                                        $compilationContext->backend->getVariableCode($symbolVariable)
                                                    )
                                                );
                                            }
                                        }
                                    } else {
                                        $codePrinter->output(
                                            sprintf(
                                                'RETVAL_ZVAL(%s, 1, 0);',
                                                $compilationContext->backend->getVariableCode($symbolVariable)
                                            )
                                        );
                                        $codePrinter->output('RETURN_MM();');
                                    }
                                } else {
                                    $codePrinter->output('RETURN_MM();');
                                }
                            }
                            if ($symbolVariable->isTemporal()) {
                                $symbolVariable->setIdle(true);
                            }
                            break;

                        default:
                            throw new CompilerException(
                                sprintf("Cannot return variable '%s'", $symbolVariable->getType()),
                                $statement['expr']
                            );
                    }
                    break;

                default:
                    throw new CompilerException("Cannot return '".$resolvedExpr->getType()."'", $statement['expr']);
            }

            return;
        }

        /*
         * Return without an expression
         */
        $codePrinter->output('RETURN_MM_NULL();');
    }
754241
public function useExpr($expr, $tags = array())
    {
        foreach ($tags as $key => $value) {
            if ($key[0] == ':') {
                $this->extra_params[$key] = $value;
                continue;
            }

            $this->args['custom'][$key] = $value;
        }

        $this->template = $expr;
        if (!empty($tags)) {
            $this->setCustom($tags);
        }
        $this->output_mode = 'render';

        return $this;
    }
1317923
public function compile($expression, CompilationContext $compilationContext)
    {
        $propertyAccess = $expression;

        $expr = new Expression($propertyAccess['left']);
        $exprVariable = $expr->compile($compilationContext);

        switch ($exprVariable->getType()) {
            case 'variable':
                $variableVariable = $compilationContext->symbolTable->getVariableForRead($exprVariable->getCode(), $compilationContext, $expression);
                switch ($variableVariable->getType()) {
                    case 'variable':
                        break;
                    default:
                        throw new CompilerException('Variable type: '.$variableVariable->getType().' cannot be used as object', $propertyAccess['left']);
                }
                break;
            default:
                throw new CompilerException('Cannot use expression: '.$exprVariable->getType().' as an object', $propertyAccess['left']);
        }

        switch ($propertyAccess['right']['type']) {
            case 'variable':
                $propertyVariable = $compilationContext->symbolTable->getVariableForRead($propertyAccess['right']['value'], $compilationContext, $expression);
                break;
            case 'string':
                $propertyVariable = null;
                break;
            default:
                throw new CompilerException('Variable type: '.$propertyAccess['right']['type'].' cannot be used as object', $propertyAccess['left']);
        }

        /*
         * Resolves the symbol that expects the value
         */
        if ($this->expecting) {
            if ($this->expectingVariable) {
                $symbolVariable = $this->expectingVariable;
                if ('return_value' != $symbolVariable->getName()) {
                    $symbolVariable->observeVariant($compilationContext);
                } else {
                    $symbolVariable = $compilationContext->symbolTable->getTempVariableForObserve('variable', $compilationContext, $expression);
                }
            } else {
                $symbolVariable = $compilationContext->symbolTable->getTempVariableForObserve('variable', $compilationContext, $expression);
            }
        }

        /*
         * Variable that receives a property value must be polymorphic
         */
        if ($symbolVariable && !$symbolVariable->isVariable()) {
            throw new CompilerException('Cannot use variable: '.$symbolVariable->getType().' to assign property value', $expression);
        }

        /*
         * At this point, we don't know the exact dynamic type fetched from the property
         */
        $symbolVariable->setDynamicTypes('undefined');

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

        $property = $propertyVariable ? $propertyVariable : add_slashes($expression['right']['value']);
        $compilationContext->backend->fetchProperty($symbolVariable, $variableVariable, $property, false, $compilationContext, false);

        return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
    }
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);
    }
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;
        }
    }
865941
public function process(ExprBuilder $builder, $field, $expression, $value)
    {
        if (!Expr::isValidExpression($expression)) {
            throw new ParserException(sprintf(
                'The expression "%s" is not allowed or not exists.',
                $expression
            ));
        }

        switch ($expression) {
            case 'between':
                set_error_handler(function () use ($value) {
                    throw new ParserException(sprintf(
                        'The value of "between" expression "%s" is not valid.',
                        $value
                    ));
                });

                list($from, $to) = explode('-', $value);

                restore_error_handler();

                return $builder->between($field, $from, $to);
            case 'paginate':
                set_error_handler(function () use ($value) {
                    throw new ParserException(sprintf(
                        'The value of "paginate" expression "%s" is not valid.',
                        $value
                    ));
                });

                list($currentPageNumber, $maxResultsPerPage) = explode('-', $value);

                restore_error_handler();

                return $builder->paginate($currentPageNumber, $maxResultsPerPage);
            case 'or':
                return $builder->orx($value);
            default:
                return $builder->{$expression}($field, $value);
        }
    }
756438
public function walkCompositeExpression(CompositeExpression $expr)
    {
        foreach ($expr->getExpressionList() as $child) {
            $this->dispatch($child);
        }
    }
195053
public function hasVariable($name, CompilationContext $compilationContext = null)
    {
        return false !== $this->getVariable($name, $compilationContext ?: $this->compilationContext);
    }
588368
public function compile(CompilationContext $compilationContext)
    {
        $statement = $this->statement;

        if (!isset($statement['data-type'])) {
            throw new CompilerException('Data type is required', $this->statement);
        }

        $typeInference = $compilationContext->typeInference;
        $symbolTable = $compilationContext->symbolTable;

        foreach ($statement['variables'] as $variable) {
            $varName = $variable['variable'];
            if ($symbolTable->hasVariableInBranch($varName, $compilationContext->branchManager->getCurrentBranch())) {
                throw new CompilerException("Variable '".$varName."' is already defined", $variable);
            }

            $currentType = $statement['data-type'];

            /*
             * Replace original data type by the pre-processed infered type
             */
            if ($typeInference) {
                if ('variable' == $currentType) {
                    $type = $typeInference->getInferedType($varName);
                    if (\is_string($type)) {
                        $currentType = $type;
                    }
                }
            }

            switch ($currentType) {
                case 'variable':
                case 'array-access':
                case 'property-access':
                case 'static-property-access':
                case 'fcall':
                case 'mcall':
                case 'scall':
                    $currentType = 'variable';
                    break;
            }

            /**
             * Variables are added to the symbol table.
             */
            $symbolVariable = $symbolTable->addVariable($currentType, $varName, $compilationContext);
            $varName = $symbolVariable->getName();

            /*
             * Set the node where the variable is declared
             */
            $symbolVariable->setOriginal($variable);

            $symbolVariable->setIsInitialized(true, $compilationContext);
            //$symbolVariable->increaseMutates();

            if ('variable' == $currentType) {
                $symbolVariable->setMustInitNull(true);
                $symbolVariable->setLocalOnly(false);
            }
            //$symbolVariable->increaseVariantIfNull();

            if (isset($variable['expr'])) {
                $builder = BuilderFactory::getInstance();
                $letBuilder = $builder->statements()->let([
                    $builder->operators()
                        ->assignVariable($varName, $builder->raw($variable['expr'])),
                ]);

                $letStatement = new LetStatement($letBuilder->build());
                $letStatement->compile($compilationContext);
            } else {
                $symbolVariable->enableDefaultAutoInitValue();
            }
        }
    }
1215433
public function compile($expression, CompilationContext $compilationContext)
    {
        if (!isset($expression['left'])) {
            throw new CompilerException('Missing left part of the expression', $expression);
        }

        if (!isset($expression['right'])) {
            throw new CompilerException('Missing right part of the expression', $expression);
        }

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

        /**
         * Try to optimize the concatenation.
         */
        $optimized = $this->_getOptimizedConcat($expression, $compilationContext, $isFullString);
        if (\is_array($optimized)) {
            if (!$isFullString) {
                $expected = $this->getExpectedComplexLiteral($compilationContext, $expression);
            } else {
                $expected = $this->getExpectedComplexLiteral($compilationContext, $expression, 'string');
            }

            $expected->setDynamicTypes('string');
            $expectedCode = $compilationContext->backend->getVariableCode($expected);
            $compilationContext->codePrinter->output('ZEPHIR_CONCAT_'.strtoupper($optimized[0]).'('.$expectedCode.', '.$optimized[1].');');

            return new CompiledExpression('variable', $expected->getName(), $expression);
        }

        /**
         * If the expression cannot be optimized, fall back to the standard compilation.
         */
        $leftExpr = new Expression($expression['left']);
        switch ($expression['left']['type']) {
            case 'array-access':
            case 'property-access':
                $leftExpr->setReadOnly(true);
                break;

            default:
                $leftExpr->setReadOnly($this->readOnly);
                break;
        }
        $left = $leftExpr->compile($compilationContext);

        if ('variable' == $left->getType()) {
            $variableLeft = $compilationContext->symbolTable->getVariableForRead($left->getCode(), $compilationContext, $expression['right']);
            $variableLeft = $compilationContext->backend->getVariableCode($variableLeft);
        }

        $rightExpr = new Expression($expression['right']);
        switch ($expression['left']['type']) {
            case 'array-access':
            case 'property-access':
                $rightExpr->setReadOnly(true);
                break;

            default:
                $rightExpr->setReadOnly($this->readOnly);
                break;
        }
        $right = $rightExpr->compile($compilationContext);

        if ('variable' == $right->getType()) {
            $variableRight = $compilationContext->symbolTable->getVariableForRead($right->getCode(), $compilationContext, $expression['right']);
            $variableRight = $compilationContext->backend->getVariableCode($variableRight);
        }

        $expected = $this->getExpectedComplexLiteral($compilationContext, $expression);
        $expectedCode = $compilationContext->backend->getVariableCode($expected);

        if ('string' == $left->getType() && 'variable' == $right->getType()) {
            $compilationContext->codePrinter->output('ZEPHIR_CONCAT_SV('.$expectedCode.', "'.$left->getCode().'", '.$variableRight.');');
        }

        if ('variable' == $left->getType() && 'string' == $right->getType()) {
            $compilationContext->codePrinter->output('ZEPHIR_CONCAT_VS('.$expectedCode.', '.$variableLeft.', "'.$right->getCode().'");');
        }

        if ('variable' == $left->getType() && 'variable' == $right->getType()) {
            $compilationContext->codePrinter->output('zephir_concat_function('.$expectedCode.', '.$variableLeft.', '.$variableRight.');');
        }

        $expected->setDynamicTypes('string');

        return new CompiledExpression('variable', $expected->getName(), $expression);
    }