Pre-compiles the method making compilation pass data (static inference, local-context-pass) available to other methods.

@param CompilationContext $compilationContext

@throws CompilerException
420924
public function preCompile(CompilationContext $compilationContext)
    {
        $localContext = null;
        $typeInference = null;
        $callGathererPass = null;

        if (\is_object($this->statements)) {
            $compilationContext->currentMethod = $this;

            /*
             * This pass checks for zval variables than can be potentially
             * used without allocating memory and track it
             * these variables are stored in the stack
             */
            if ($compilationContext->config->get('local-context-pass', 'optimizations')) {
                $localContext = new LocalContextPass();
                $localContext->pass($this->statements);
            }

            /*
             * This pass tries to infer types for dynamic variables
             * replacing them by low level variables
             */
            if ($compilationContext->config->get('static-type-inference', 'optimizations')) {
                $typeInference = new StaticTypeInference();
                $typeInference->pass($this->statements);
                if ($compilationContext->config->get('static-type-inference-second-pass', 'optimizations')) {
                    $typeInference->reduce();
                    $typeInference->pass($this->statements);
                }
            }

            /*
             * This pass counts how many times a specific
             */
            if ($compilationContext->config->get('call-gatherer-pass', 'optimizations')) {
                $callGathererPass = new CallGathererPass($compilationContext);
                $callGathererPass->pass($this->statements);
            }
        }

        $this->localContext = $localContext;
        $this->typeInference = $typeInference;
        $this->callGathererPass = $callGathererPass;
    }
492008
public function initializeContext(Context $context)
    {
        if (!$context instanceof CollectionAwareContextInterface) {
            return;
        }
        $context->setTerminalCollection($this->collection);
        $context->setTerminalDefaultAlias($this->defaultAlias);
    }
300585
public void setContext(Context context) {
        context.put(JavacElements.class, this);
        javaCompiler = JavaCompiler.instance(context);
        syms = Symtab.instance(context);
        names = Names.instance(context);
        types = Types.instance(context);
        enter = Enter.instance(context);
    }
287887
public function compile(Expression $expr, CompilationContext $compilationContext)
    {
        $this->expression = $expr;
        $expression = $expr->getExpression();

        switch ($expression['call-type']) {
            case self::CALL_NORMAL:
                return $this->_callNormal($expression, $compilationContext);
            case self::CALL_DYNAMIC:
                return $this->_callDynamic($expression, $compilationContext);
        }

        return new CompiledExpression('null', null, $expression);
    }
183095
public function addCallStatusOrJump(CompilationContext $compilationContext)
    {
        $compilationContext->headersManager->add('kernel/fcall');
        if ($compilationContext->insideTryCatch) {
            $compilationContext->codePrinter->output(
                'zephir_check_call_status_or_jump(try_end_'.$compilationContext->currentTryCatch.');'
            );

            return;
        }

        $compilationContext->codePrinter->output('zephir_check_call_status();');
    }
839566
public function compile(array $expression, CompilationContext $compilationContext)
    {
        $expr = new Expression($expression['right']);
        $expr->setReadOnly(true);
        $resolved = $expr->compile($compilationContext);

        if ('variable' != $resolved->getType()) {
            throw new CompilerException('Type-Hints only can be applied to dynamic variables.', $expression);
        }

        $symbolVariable = $compilationContext->symbolTable->getVariableForRead(
            $resolved->getCode(),
            $compilationContext,
            $expression
        );

        if (!$symbolVariable->isVariable()) {
            throw new CompilerException('Type-Hints only can be applied to dynamic variables.', $expression);
        }

        $symbolVariable->setDynamicTypes('object');
        $symbolVariable->setClassTypes($compilationContext->getFullName($expression['left']['value']));

        return $resolved;
    }
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);
            }
        }
    }
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;
        }
    }
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);
    }
60436
public function compile($expression, CompilationContext $compilationContext)
    {
        /**
         * Resolve the left part of the expression.
         */
        $expr = new Expression($expression['left']);
        $expr->setReadOnly(true);
        $exprVariable = $expr->compile($compilationContext);

        /*
         * Only dynamic variables can be used as arrays
         */
        switch ($exprVariable->getType()) {
            case 'variable':
                $variableVariable = $compilationContext->symbolTable->getVariableForRead($exprVariable->getCode(), $compilationContext, $expression);
                switch ($variableVariable->getType()) {
                    case 'variable':
                    case 'array':
                    case 'string':
                        break;

                    default:
                        throw new CompilerException('Variable type: '.$variableVariable->getType().' cannot be used as array', $expression['left']);
                }
                break;

            default:
                throw new CompilerException('Cannot use expression: '.$exprVariable->getType().' as an array', $expression['left']);
        }

        /*
         * Resolve the dimension according to variable's type
         */
        switch ($variableVariable->getType()) {
            case 'variable':
                return $this->_accessDimensionArray($expression, $variableVariable, $compilationContext);

            case 'array':
                return $this->_accessDimensionArray($expression, $variableVariable, $compilationContext);

            case 'string':
                return $this->_accessStringOffset($expression, $variableVariable, $compilationContext);
        }
    }
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);
    }
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;
    }
719318
public function compile($expression, CompilationContext $compilationContext)
    {
        /*
         * This variable is used to check if the compound and expression is evaluated as true or false:
         * Ensure that newly allocated variables are local-only (setReadOnly)
         */
        $this->setReadOnly(false);
        $returnVariable = $this->getExpected($compilationContext, $expression, false);
        /* Make sure that passed variables (passed symbol variables) are promoted */
        $returnVariable->setLocalOnly(false);

        if ('variable' != $returnVariable->getType() || 'return_value' == $returnVariable->getName()) {
            $returnVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
            if ($returnVariable->isTemporal()) {
                $returnVariable->skipInitVariant(2);
            }
        }

        $ifBuilder = new IfStatementBuilder(
            new UnaryOperatorBuilder(
                'not',
                $expression['left']
            ),
            new StatementsBlockBuilder([
                /*
                 * Create an implicit 'let' operation to update the evaluated right operator
                 */
                new LetStatementBuilder([
                    'assign-type' => 'variable',
                    'variable' => $returnVariable->getName(),
                    'operator' => 'assign',
                    'expr' => $expression['extra'],
                    'file' => $expression['file'],
                    'line' => $expression['line'],
                    'char' => $expression['char'],
                ], $expression['extra']),
            ]),
            new StatementsBlockBuilder([
                /*
                 * Create an implicit 'let' operation to update the evaluated right operator
                 */
                new LetStatementBuilder([
                    'assign-type' => 'variable',
                    'variable' => $returnVariable->getName(),
                    'operator' => 'assign',
                    'expr' => $expression['left'],
                    'file' => $expression['file'],
                    'line' => $expression['line'],
                    'char' => $expression['char'],
                ], $expression['extra']),
            ])
        );

        $ifStatement = new IfStatement($ifBuilder->get());
        $ifStatement->compile($compilationContext);

        return new CompiledExpression('variable', $returnVariable->getName(), $expression);
    }
936398
public function compile(CompilationContext $compilationContext)
    {
        $expression = $this->expression;
        $type = $expression['type'];
        $compilableExpression = null;

        switch ($type) {
            case 'null':
                return new LiteralCompiledExpression('null', null, $expression);

            case 'int':
            case 'integer':
                return new LiteralCompiledExpression('int', $expression['value'], $expression);

            case 'long':
            case 'double':
            case 'bool':
                return new LiteralCompiledExpression($type, $expression['value'], $expression);

            case 'string':
                return new LiteralCompiledExpression('string', str_replace(PHP_EOL, '\\n', $expression['value']), $expression);
            case 'istring':
                return new LiteralCompiledExpression('istring', str_replace(PHP_EOL, '\\n', $expression['value']), $expression);

            case 'char':
                if (!\strlen($expression['value'])) {
                    throw new CompilerException('Invalid empty char literal', $expression);
                }
                if (\strlen($expression['value']) > 2) {
                    if (\strlen($expression['value']) > 10) {
                        throw new CompilerException("Invalid char literal: '".substr($expression['value'], 0, 10)."...'", $expression);
                    } else {
                        throw new CompilerException("Invalid char literal: '".$expression['value']."'", $expression);
                    }
                }

                return new LiteralCompiledExpression('char', $expression['value'], $expression);

            case 'variable':
                $var = $compilationContext->symbolTable->getVariable($expression['value']);
                if ($var) {
                    if ('this' == $var->getRealName()) {
                        $var = 'this';
                    } else {
                        $var = $var->getName();
                    }
                } else {
                    $var = $expression['value'];
                }

                return new CompiledExpression('variable', $var, $expression);

            case 'constant':
                $compilableExpression = new Constants();
                break;

            case 'empty-array':
                return $this->emptyArray($expression, $compilationContext);

            case 'array-access':
                $compilableExpression = new NativeArrayAccess();
                $compilableExpression->setNoisy($this->isNoisy());
                break;

            case 'property-access':
                $compilableExpression = new PropertyAccess();
                $compilableExpression->setNoisy($this->isNoisy());
                break;

            case 'property-string-access':
            case 'property-dynamic-access':
                $compilableExpression = new PropertyDynamicAccess();
                $compilableExpression->setNoisy($this->isNoisy());
                break;

            case 'static-constant-access':
                $compilableExpression = new StaticConstantAccess();
                break;

            case 'static-property-access':
                $compilableExpression = new StaticPropertyAccess();
                break;

            case 'fcall':
                $functionCall = new FunctionCall();

                return $functionCall->compile($this, $compilationContext);

            case 'mcall':
                $methodCall = new MethodCall();

                return $methodCall->compile($this, $compilationContext);

            case 'scall':
                $staticCall = new StaticCall();

                return $staticCall->compile($this, $compilationContext);

            case 'isset':
                $compilableExpression = new IssetOperator();
                break;

            case 'fetch':
                $compilableExpression = new FetchOperator();
                break;

            case 'empty':
                $compilableExpression = new EmptyOperator();
                break;

            case 'array':
                $compilableExpression = new NativeArray();
                break;

            case 'new':
                $compilableExpression = new NewInstanceOperator();
                break;

            case 'new-type':
                $compilableExpression = new NewInstanceTypeOperator();
                break;

            case 'not':
                $compilableExpression = new NotOperator();
                break;

            case 'bitwise_not':
                $compilableExpression = new BitwiseNotOperator();
                break;

            case 'equals':
                $compilableExpression = new EqualsOperator();
                break;

            case 'not-equals':
                $compilableExpression = new NotEqualsOperator();
                break;

            case 'identical':
                $compilableExpression = new IdenticalOperator();
                break;

            case 'not-identical':
                $compilableExpression = new NotIdenticalOperator();
                break;

            case 'greater':
                $compilableExpression = new GreaterOperator();
                break;

            case 'less':
                $compilableExpression = new LessOperator();
                break;

            case 'less-equal':
                $compilableExpression = new LessEqualOperator();
                break;

            case 'greater-equal':
                $compilableExpression = new GreaterEqualOperator();
                break;

            case 'add':
                $compilableExpression = new AddOperator();
                break;

            case 'minus':
                $compilableExpression = new MinusOperator();
                break;

            case 'sub':
                $compilableExpression = new SubOperator();
                break;

            case 'mul':
                $compilableExpression = new MulOperator();
                break;

            case 'div':
                $compilableExpression = new DivOperator();
                break;

            case 'mod':
                $compilableExpression = new ModOperator();
                break;

            case 'and':
                $compilableExpression = new AndOperator();
                break;

            case 'or':
                $compilableExpression = new OrOperator();
                break;

            case 'bitwise_and':
                $compilableExpression = new BitwiseAndOperator();
                break;

            case 'bitwise_or':
                $compilableExpression = new BitwiseOrOperator();
                break;

            case 'bitwise_xor':
                $compilableExpression = new BitwiseXorOperator();
                break;

            case 'bitwise_shiftleft':
                $compilableExpression = new ShiftLeftOperator();
                break;

            case 'bitwise_shiftright':
                $compilableExpression = new ShiftRightOperator();
                break;

            case 'concat':
                $expr = new ConcatOperator();
                $expr->setExpectReturn($this->expecting, $this->expectingVariable);

                return $expr->compile($expression, $compilationContext);

            case 'irange':
                $compilableExpression = new RangeInclusiveOperator();
                break;

            case 'erange':
                $compilableExpression = new RangeExclusiveOperator();
                break;

            case 'list':
                if ('list' == $expression['left']['type']) {
                    $compilationContext->logger->warning(
                        'Unnecessary extra parentheses',
                        ['extra-parentheses', $expression]
                    );
                }
                $numberPrints = $compilationContext->codePrinter->getNumberPrints();
                $expr = new self($expression['left']);
                $expr->setExpectReturn($this->expecting, $this->expectingVariable);
                $resolved = $expr->compile($compilationContext);
                if (($compilationContext->codePrinter->getNumberPrints() - $numberPrints) <= 1) {
                    if (false !== strpos($resolved->getCode(), ' ')) {
                        return new CompiledExpression($resolved->getType(), '('.$resolved->getCode().')', $expression);
                    }
                }

                return $resolved;

            case 'cast':
                $compilableExpression = new CastOperator();
                break;

            case 'type-hint':
                $expr = new TypeHintOperator();
                $expr->setReadOnly($this->isReadOnly());
                $expr->setExpectReturn($this->expecting, $this->expectingVariable);

                return $expr->compile($expression, $compilationContext);

            case 'instanceof':
                $compilableExpression = new InstanceOfOperator();
                break;

            case 'clone':
                $compilableExpression = new CloneOperator();
                break;

            case 'ternary':
                $compilableExpression = new TernaryOperator();
                break;

            case 'short-ternary':
                $expr = new ShortTernaryOperator();
                $expr->setReadOnly($this->isReadOnly());
                $expr->setExpectReturn($this->expecting, $this->expectingVariable);

                return $expr->compile($expression, $compilationContext);

            case 'likely':
                if (!$this->evalMode) {
                    throw new CompilerException("'likely' operator can only be used in evaluation expressions", $expression);
                }
                $expr = new LikelyOperator();
                $expr->setReadOnly($this->isReadOnly());

                return $expr->compile($expression, $compilationContext);

            case 'unlikely':
                if (!$this->evalMode) {
                    throw new CompilerException("'unlikely' operator can only be used in evaluation expressions", $expression);
                }
                $expr = new UnlikelyOperator();
                $expr->setReadOnly($this->isReadOnly());

                return $expr->compile($expression, $compilationContext);

            case 'typeof':
                $compilableExpression = new TypeOfOperator();
                break;

            case 'require':
                $compilableExpression = new RequireOperator();
                break;

            case 'closure':
                $compilableExpression = new Closure();
                break;

            case 'closure-arrow':
                $compilableExpression = new ClosureArrow();
                break;

            case 'reference':
                $compilableExpression = new Reference();
                break;

            default:
                throw new CompilerException('Unknown expression: '.$type, $expression);
        }

        if (!$compilableExpression) {
            throw new CompilerException('Unknown expression passed as compilableExpression', $expression);
        }
        $compilableExpression->setReadOnly($this->isReadOnly());
        $compilableExpression->setExpectReturn($this->expecting, $this->expectingVariable);

        return $compilableExpression->compile($expression, $compilationContext);
    }
1026282
public function markTemporalVariablesIdle(CompilationContext $compilationContext)
    {
        $compilationContext = $compilationContext ?: $this->compilationContext;
        $branchId = $compilationContext->branchManager->getCurrentBranchId();

        if (!isset($this->branchTempVariables[$branchId])) {
            return;
        }

        foreach ($this->branchTempVariables[$branchId] as $location => $typeVariables) {
            foreach ($typeVariables as $type => $variables) {
                foreach ($variables as $variable) {
                    $pos = strpos($variable->getName(), Variable::BRANCH_MAGIC);
                    $otherBranchId = 1;
                    if ($pos > -1) {
                        $otherBranchId = (int) (substr($variable->getName(), $pos + \strlen(Variable::BRANCH_MAGIC)));
                    }
                    if ($branchId == $otherBranchId) {
                        $variable->setIdle(true);
                    }
                }
            }
        }
    }
214919
protected function _beforeInsert(DatabaseContext $context)
    {
        $mixer = $this->getMixer();
        $table = $mixer instanceof DatabaseRowInterface ?  $mixer->getTable() : $mixer;

        if($this->hasProperty('created_by') && empty($this->created_by)) {
            $this->created_by  = (int) $this->getObject('user')->getId();
        }

        if($this->hasProperty('created_on') && (empty($this->created_on) || $this->created_on == $table->getDefault('created_on'))) {
            $this->created_on  = gmdate('Y-m-d H:i:s');
        }
    }
612598
public function optimize($exprRaw, CompilationContext $compilationContext)
    {
        $conditions = $this->optimizeNot($exprRaw, $compilationContext);

        if (false !== $conditions) {
            return $conditions;
        }

        /*
         * Discard first level parentheses
         */
        if ('list' == $exprRaw['type']) {
            $expr = new Expression($exprRaw['left']);
        } else {
            $expr = new Expression($exprRaw);
        }

        $expr->setReadOnly(true);
        $expr->setEvalMode(true);
        $compiledExpression = $expr->compile($compilationContext);

        /*
         * Possible corrupted expression?
         */
        if (!\is_object($compiledExpression)) {
            throw new CompilerException('Corrupted expression: '.$exprRaw['type'], $exprRaw);
        }

        /*
         * Generate the condition according to the value returned by the evaluated expression
         */
        switch ($compiledExpression->getType()) {
            case 'null':
                $this->unreachable = true;

                return '0';

            case 'int':
            case 'uint':
            case 'long':
            case 'ulong':
            case 'double':
                $code = $compiledExpression->getCode();
                if (is_numeric($code)) {
                    if ('1' == $code) {
                        $this->unreachableElse = true;
                    } else {
                        $this->unreachable = true;
                    }
                }

                return $code;

            case 'char':
            case 'uchar':
                return $compiledExpression->getCode();

            case 'bool':
                $code = $compiledExpression->getBooleanCode();
                if ('1' == $code) {
                    $this->unreachableElse = true;
                } else {
                    if ('0' == $code) {
                        $this->unreachable = true;
                    }
                }

                return $code;

            case 'variable':
                $variableRight = $compilationContext->symbolTable->getVariableForRead($compiledExpression->getCode(), $compilationContext, $exprRaw);
                $possibleValue = $variableRight->getPossibleValue();
                if (\is_object($possibleValue)) {
                    $possibleValueBranch = $variableRight->getPossibleValueBranch();
                    if ($possibleValueBranch instanceof Branch) {
                        /*
                         * Check if the possible value was assigned in the root branch
                         */
                        if (Branch::TYPE_ROOT == $possibleValueBranch->getType()) {
                            if ($possibleValue instanceof LiteralCompiledExpression) {
                                switch ($possibleValue->getType()) {
                                    case 'null':
                                        $this->unreachable = true;
                                        break;

                                    case 'bool':
                                        if ('0' == $possibleValue->getBooleanCode()) {
                                            $this->unreachable = true;
                                        } else {
                                            $this->unreachableElse = true;
                                        }
                                        break;

                                    case 'int':
                                        if (!(int) ($possibleValue->getCode())) {
                                            $this->unreachable = true;
                                        } else {
                                            $this->unreachableElse = true;
                                        }
                                        break;

                                    case 'double':
                                        if (!(float) ($possibleValue->getCode())) {
                                            $this->unreachable = true;
                                        } else {
                                            $this->unreachableElse = true;
                                        }
                                        break;

                                    default:
                                        //echo $possibleValue->getType();
                                }
                            }
                        }
                    }
                }

                $this->usedVariables[] = $variableRight->getName();

                /*
                 * Evaluate the variable
                 */
                switch ($variableRight->getType()) {
                    case 'int':
                    case 'uint':
                    case 'char':
                    case 'uchar':
                    case 'long':
                    case 'ulong':
                        return $variableRight->getName();

                    case 'string':
                        $variableRightCode = $compilationContext->backend->getVariableCode($variableRight);

                        return '!('.$compilationContext->backend->ifVariableValueUndefined($variableRight, $compilationContext, true, false).') && Z_STRLEN_P('.$variableRightCode.')';

                    case 'bool':
                        return $variableRight->getName();

                    case 'double':
                        return $variableRight->getName();

                    case 'variable':
                        $compilationContext->headersManager->add('kernel/operators');
                        $variableRightCode = $compilationContext->backend->getVariableCode($variableRight);

                        return 'zephir_is_true('.$variableRightCode.')';

                    default:
                        throw new CompilerException("Variable can't be evaluated ".$variableRight->getType(), $exprRaw);
                }
                break;

            default:
                throw new CompilerException('Expression '.$compiledExpression->getType()." can't be evaluated", $exprRaw);
        }
    }