Creates a closure.

@param array              $expression
@param CompilationContext $compilationContext

@throws CompilerException

@return CompiledExpression
322517
public function compile(array $expression, CompilationContext $compilationContext)
    {
        $classDefinition = new ClassDefinition(
            $compilationContext->config->get('namespace'),
            self::$id.'__closure'
        );

        $classDefinition->setIsFinal(true);

        $compilerFile = new CompilerFileAnonymous($classDefinition, $compilationContext->config);
        $compilerFile->setLogger($compilationContext->logger);

        $compilationContext->compiler->addClassDefinition($compilerFile, $classDefinition);

        /**
         * Builds parameters using the only parameter available.
         */
        $parameters = new ClassMethodParameters([
            [
                'type' => 'parameter',
                'name' => $expression['left']['value'],
                'const' => 0,
                'data-type' => 'variable',
                'mandatory' => 0,
                'reference' => 0,
                'file' => $expression['left']['file'],
                'line' => $expression['left']['line'],
                'char' => $expression['left']['char'],
            ],
        ]);

        $exprBuilder = BuilderFactory::getInstance();
        $statementBlockBuilder = $exprBuilder->statements()->block([
            $exprBuilder->statements()
                ->returnX($exprBuilder->raw($expression['right'])),
        ]);

        $block = $statementBlockBuilder->build();

        $classMethod = new ClassMethod(
            $classDefinition,
            ['public', 'final'],
            '__invoke',
            $parameters,
            new StatementsBlock($block),
            null,
            null,
            $expression
        );
        $classDefinition->addMethod($classMethod, $block);

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

        if ($this->expecting) {
            if ($this->expectingVariable) {
                $symbolVariable = $this->expectingVariable;
            } else {
                $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression);
            }
        } else {
            $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression);
        }

        $symbolVariable->initVariant($compilationContext);
        $compilationContext->backend->createClosure($symbolVariable, $classDefinition, $compilationContext);

        ++self::$id;

        return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
    }
1096895
private function createMatches(array $expression, CompilationContext $context)
    {
        if (isset($expression['parameters'][2])) {
            $type = $expression['parameters'][2]['parameter']['type'];

            if ('variable' !== $type) {
                throw new CompilerException('Only variables can be passed by reference', $expression);
            }

            $name = $expression['parameters'][2]['parameter']['value'];

            if (!$variable = $context->symbolTable->getVariable($name)) {
                throw new CompilerException(
                    sprintf("Cannot mutate variable '%s' because it wasn't defined", $name),
                    $expression
                );
            }

            if (!\in_array($variable->getType(), ['variable', 'array'], true)) {
                throw new CompilerException(
                    sprintf(
                        "The '%s' variable must be either a variable or an array, got %s",
                        $name,
                        $variable->getType()
                    ),
                    $expression
                );
            }

            if (false == $variable->isInitialized()) {
                $variable->initVariant($context);
                $variable->setIsInitialized(true, $context);
            }
        } else {
            $variable = $context->symbolTable->addTemp('variable', $context);
            $variable->initVariant($context);
        }

        $variable->setDynamicTypes('array');

        return $variable;
    }
958242
public function compile(array $expression, CompilationContext $compilationContext)
    {
        $codePrinter = $compilationContext->codePrinter;

        /*
         * Resolves the symbol that expects the value
         */
        $this->literalOnly = false;
        $symbolVariable = $this->getExpectedNonLiteral($compilationContext, $expression);
        if (!$symbolVariable->isVariable()) {
            throw new CompilerException('Objects can only be instantiated into dynamic variables', $expression);
        }

        if ($symbolVariable->isLocalOnly()) {
            throw new CompilerException('Cannot use non-heap variable to store new instance', $expression);
        }

        if ('return_value' != $symbolVariable->getName()) {
            if ($symbolVariable->hasDifferentDynamicType(['unknown', 'undefined', 'object', 'null'])) {
                $compilationContext->logger->warning(
                    'Possible attempt to use non-object in "new" operator',
                    ['non-valid-new', $expression]
                );
            }
        }

        /*
         * Mark variables as dynamic objects
         */
        $symbolVariable->setDynamicTypes('object');

        $dynamic = false;
        if ('self' == $expression['class'] || 'static' == $expression['class']) {
            $className = $compilationContext->classDefinition->getCompleteName();
        } else {
            $className = $expression['class'];
            $dynamic = $expression['dynamic'];
            if (!$dynamic) {
                $className = $compilationContext->getFullName($expression['class']);
            }
        }

        if (!$className) {
            throw new CompilerException('A class name is required to instantiate the object', $expression);
        }

        /**
         * stdclass doesn't have constructors.
         */
        $lowerClassName = strtolower($className);
        $isStdClass = 'stdclass' === $lowerClassName || '\stdclass' === $lowerClassName;

        if ($isStdClass) {
            if (isset($expression['parameters']) && \count($expression['parameters']) > 0) {
                throw new CompilerException('stdclass does not receive parameters in its constructor', $expression);
            }

            $compilationContext->backend->initObject($symbolVariable, null, $compilationContext);
            $symbolVariable->setClassTypes('stdclass');
        } else {
            $classDefinition = false;
            if ($compilationContext->compiler->isClass($className)) {
                $classDefinition = $compilationContext->compiler->getClassDefinition($className);
            }

            /*
             * Classes inside the same extension
             */
            if ($classDefinition) {
                $compilationContext->backend->initObject($symbolVariable, $classDefinition->getClassEntry($compilationContext), $compilationContext);
                $symbolVariable->setClassTypes($className);
                $symbolVariable->setAssociatedClass($classDefinition);
            } else {
                /*
                 * Classes outside the extension
                 */
                if ($dynamic) {
                    $classNameVariable = $compilationContext->symbolTable->getVariableForRead($className, $compilationContext, $expression);
                    if ($classNameVariable->isNotVariableAndString()) {
                        throw new CompilerException('Only dynamic/string variables can be used in new operator. '.$classNameVariable->getName(), $expression);
                    }

                    /*
                     * Use a safe string version of the variable to avoid segfaults
                     */
                    $compilationContext->headersManager->add('kernel/object');
                    $safeSymbolVariable = $compilationContext->symbolTable->getTempVariable('variable', $compilationContext);
                    $safeSymbolVariable->setMustInitNull(true);
                    $safeSymbolVariable->setIsInitialized(true, $compilationContext);
                    $safeSymbolVariable->increaseUses();
                    $safeSymbol = $compilationContext->backend->getVariableCode($safeSymbolVariable);
                    $classNameSymbol = $compilationContext->backend->getVariableCode($classNameVariable);

                    $compilationContext->codePrinter->output('zephir_fetch_safe_class('.$safeSymbol.', '.$classNameSymbol.');');
                    $classNameToFetch = 'Z_STRVAL_P('.$safeSymbol.'), Z_STRLEN_P('.$safeSymbol.')';
                    $zendClassEntry = $compilationContext->cacheManager->getClassEntryCache()->get($classNameToFetch, true, $compilationContext);
                    $classEntry = $zendClassEntry->getName();
                } else {
                    if (!class_exists($className, false)) {
                        $compilationContext->logger->warning(
                            'Class "'.$className.'" does not exist at compile time',
                            ['nonexistent-class', $expression]
                        );
                        $classNameToFetch = 'SL("'.escape_class($className).'")';

                        $zendClassEntry = $compilationContext->cacheManager->getClassEntryCache()->get($classNameToFetch, false, $compilationContext);
                        $classEntry = $zendClassEntry->getName();
                    } else {
                        $reflectionClass = new \ReflectionClass($className);
                        if ($reflectionClass->isInterface()) {
                            throw new CompilerException('Interfaces cannot be instantiated', $expression);
                        } else {
                            if (method_exists($reflectionClass, 'isTrait')) {
                                if ($reflectionClass->isTrait()) {
                                    throw new CompilerException('Traits cannot be instantiated', $expression);
                                }
                            }
                        }

                        $classEntry = $compilationContext->classDefinition->getClassEntryByClassName($className, $compilationContext, true);
                        if (!$classEntry) {
                            $classNameToFetch = 'SL("'.escape_class($className).'")';
                            $zendClassEntry = $compilationContext->cacheManager->getClassEntryCache()->get($classNameToFetch, false, $compilationContext);
                            $classEntry = $zendClassEntry->getName();
                        } else {
                            $symbolVariable->setAssociatedClass($reflectionClass);
                        }
                    }

                    $symbolVariable->setClassTypes($className);
                }
                $compilationContext->backend->initObject($symbolVariable, $classEntry, $compilationContext);
            }
        }

        /*
         * Mark variable initialized
         */
        $symbolVariable->setIsInitialized(true, $compilationContext);

        /*
         * Don't check the constructor for stdclass instances
         */
        if ($isStdClass) {
            return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
        }

        /**
         * Call the constructor
         * For classes in the same extension we check if the class does implement a constructor
         * For external classes we always assume the class does implement a constructor.
         */
        $callConstructor = false;
        if ($compilationContext->compiler->isClass($className)) {
            $classDefinition = $compilationContext->compiler->getClassDefinition($className);

            if ('class' != $classDefinition->getType()) {
                throw new CompilerException('Only classes can be instantiated', $expression);
            }

            $callConstructor = $classDefinition->hasMethod('__construct');
        } else {
            if ($compilationContext->compiler->isBundledClass($className)) {
                $classDefinition = $compilationContext->compiler->getInternalClassDefinition($className);
                $callConstructor = $classDefinition->hasMethod('__construct');
            }
        }

        /* @TODO use the MethodBuilder here */
        if (isset($expression['parameters'])) {
            $callExpr = new Expression([
                'variable' => ['type' => 'variable', 'value' => $symbolVariable->getRealName()],
                'name' => '__construct',
                'parameters' => $expression['parameters'],
                'call-type' => MethodCall::CALL_NORMAL,
                'file' => $expression['file'],
                'line' => $expression['line'],
                'char' => $expression['char'],
                'check' => $callConstructor,
            ]);
        } else {
            $callExpr = new Expression([
                'variable' => ['type' => 'variable', 'value' => $symbolVariable->getRealName()],
                'name' => '__construct',
                'call-type' => MethodCall::CALL_NORMAL,
                'file' => $expression['file'],
                'line' => $expression['line'],
                'char' => $expression['char'],
                'check' => $callConstructor,
            ]);
        }

        /*
         * If we are certain that there is a constructor we call it, otherwise we checked it at runtime.
         */
        if ($callConstructor) {
            $methodCall = new MethodCall();
            $callExpr->setExpectReturn(false);
            $methodCall->compile($callExpr, $compilationContext);
        } else {
            $compilationContext->headersManager->add('kernel/fcall');

            /* @todo, generate the code using builders */
            $compilationContext->backend->checkConstructor($symbolVariable, $compilationContext);
            $codePrinter->increaseLevel();

            $methodCall = new MethodCall();
            $callExpr->setExpectReturn(false);
            $methodCall->compile($callExpr, $compilationContext);

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

        return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
    }
459055
public function compile(array $expression, CompilationContext $compilationContext)
    {
        if ('list' == $expression['left']['type']) {
            $left = $expression['left']['left'];
        } else {
            $left = $expression['left'];
        }

        switch ($left['type']) {
            case 'array-access':
                $compilationContext->headersManager->add('kernel/array');

                $exprVariable = new Expression($left['left']);
                $exprVariable->setReadOnly(true);
                $exprVariable->setNoisy(false);

                $exprCompiledVariable = $exprVariable->compile($compilationContext);
                if ('variable' != $exprCompiledVariable->getType() && 'array' != $exprCompiledVariable->getType()) {
                    throw new CompilerException('Expression type: '.$exprCompiledVariable->getType().' cannot be used as array', $left['left']);
                }

                $variable = $compilationContext->symbolTable->getVariableForRead($exprCompiledVariable->getCode(), $compilationContext, $left['left']);
                switch ($variable->getType()) {
                    case 'array':
                    case 'variable':
                        break;

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

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

                $expr = new Expression($left['right']);
                $expr->setReadOnly(true);
                $expr->setNoisy(false);
                $resolvedExpr = $expr->compile($compilationContext);

                switch ($resolvedExpr->getType()) {
                    case 'int':
                    case 'long':
                    case 'string':
                        return $compilationContext->backend->arrayIsset($variable, $resolvedExpr, $left['right'], $compilationContext);

                    case 'variable':
                        $indexVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $left['right']);

                        return $compilationContext->backend->arrayIsset($variable, $indexVariable, $left['right'], $compilationContext);
                        break;

                    default:
                        throw new CompilerException('['.$left['right']['type'].']', $expression);
                }
                break;

            case 'property-access':
            case 'property-dynamic-access':
                $compilationContext->headersManager->add('kernel/object');

                $exprVariable = new Expression($left['left']);
                $exprVariable->setReadOnly(true);

                $exprCompiledVariable = $exprVariable->compile($compilationContext);
                if ('variable' != $exprCompiledVariable->getType()) {
                    throw new CompilerException('Expression type: '.$exprCompiledVariable->getType().' cannot be used as object', $left['left']);
                }

                $variable = $compilationContext->symbolTable->getVariableForRead($exprCompiledVariable->getCode(), $compilationContext, $left['left']);
                if ('variable' != $variable->getType()) {
                    throw new CompilerException('Variable type: '.$variable->getType().' cannot be used as object', $left['left']);
                }

                if ($variable->hasDifferentDynamicType(['undefined', 'object', 'null'])) {
                    $compilationContext->logger->warning(
                        'Possible attempt to use non object in isset operator',
                        ['non-valid-isset', $expression]
                    );
                }
                $variableCode = $compilationContext->backend->getVariableCode($variable);

                if ('property-access' == $left['type']) {
                    return $compilationContext->backend->propertyIsset($variable, $left['right']['value'], $compilationContext);
                }

                $expr = new Expression($left['right']);
                $expr->setReadOnly(true);
                $expr->setNoisy(false);
                $resolvedExpr = $expr->compile($compilationContext);

                switch ($resolvedExpr->getType()) {
                    case 'variable':
                        $indexVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $left['right']);
                        switch ($indexVariable->getType()) {
                            case 'variable':
                            case 'string':
                                $indexVariableCode = $compilationContext->backend->getVariableCode($indexVariable);

                                return new CompiledExpression('bool', 'zephir_isset_property_zval('.$variableCode.', '.$indexVariableCode.' TSRMLS_CC)', $left['right']);

                            default:
                                throw new CompilerException('['.$indexVariable->getType().']', $expression);
                        }
                        break;

                    default:
                        throw new CompilerException('['.$expression['left']['right']['type'].']', $expression);
                }
                break;

            case 'property-string-access':
                return new CompiledExpression('bool', '(0 == 0)', $left);

            case 'static-property-access':
                return new CompiledExpression('bool', '(0 == 0)', $left);

            default:
                throw new CompilerException('This expression is not valid for "isset" operator', $expression);
        }
    }
1132176
public function optimize(array $expression, Call $call, CompilationContext $context)
    {
        if (!isset($expression['parameters']) || 1 != \count($expression['parameters'])) {
            return false;
        }

        if ('string' == $expression['parameters'][0]['parameter']['type']) {
            $str = add_slashes($expression['parameters'][0]['parameter']['value']);
            unset($expression['parameters'][0]);
        }

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

        $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);
        if (isset($str)) {
            /* TODO: Solve this macro stuff better, move to backend */
            $macro = $context->backend->isZE3() ? 'SL' : 'SS';

            return new CompiledExpression('bool', '(zephir_function_exists_ex('.$macro.'("'.strtolower($str).'") TSRMLS_CC) == SUCCESS)', $expression);
        }

        return new CompiledExpression('bool', '(zephir_function_exists('.$resolvedParams[0].' TSRMLS_CC)  == SUCCESS)', $expression);
    }
1131886
public static function fromExpressions(array $expressions, IEvaluationContext $context = null)
    {
        $evaluator            = new self($context);
        $namespace            = $evaluator->context->getNamespace();
        $contextParameterName = self::CONTEXT_PARAMETER_NAME;
        $variableTable        = $evaluator->context->getVariableTable();

        //Replace any non value types with references in the variable table.
        $expressions = (new DynamicExpressionWalker([
                ValueExpression::getType() =>
                        function (ValueExpression $expression) use ($evaluator, $variableTable, &$name) {
                            $value = $expression->getValue();
                            if (!ValueExpression::isValueType($value)) {
                                $name = $name !== null ? $name : 0;
                                do {
                                    $name++;
                                } while (isset($variableTable['o' . $name]));

                                $name                             = 'o' . $name;
                                $evaluator->extraVariables[$name] = $value;

                                return Expression::variable(Expression::value($name));
                            }

                            return $expression;
                        }
        ]))->walkAll($expressions);

        $bodyCode = '';
        foreach ($evaluator->extraVariables + $variableTable as $variable => $value) {
            $variableName = Expression::value($variable);
            $variableCode = Expression::variable($variableName)->compile();
            $bodyCode .= "$variableCode =& $$contextParameterName" . '[' . $variableName->compile() . '];';
        }

        $bodyCode .= "unset($$contextParameterName);";
        $bodyCode .= implode(';', Expression::compileAll($expressions)) . ';';
        $evaluator->code = <<<PHP
namespace {$namespace} {
    return function ($$contextParameterName) {
        $bodyCode
    };
}
PHP;

        $evaluator->initializeEvaluator();

        return $evaluator;
    }
1209314
public function compile($expression, CompilationContext $compilationContext)
    {
        $expr = new Expression($expression['right']);
        $resolved = $expr->compile($compilationContext);

        switch ($expression['left']) {
            case 'int':
                switch ($resolved->getType()) {
                    case 'null':
                        return new CompiledExpression('int', 0, $expression);

                    case 'int':
                        return new CompiledExpression('int', $resolved->getCode(), $expression);

                    case 'double':
                        return new CompiledExpression('int', '(int) '.$resolved->getCode(), $expression);

                    case 'bool':
                        return new CompiledExpression('int', $resolved->getBooleanCode(), $expression);

                    case 'string':
                        $compilationContext->headersManager->add('kernel/operators');

                        /**
                         * zephir_get_intval_ex use zval variable
                         * before use with it we create a new variable and assign value of literal.
                         *
                         * @todo Optimize by creating native function for string without zval using
                         */
                        $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('string', $compilationContext);
                        $let = new LetVariable();
                        $original = $resolved->getOriginal();
                        $original['operator'] = 'assign';
                        $let->assign($symbolVariable->getName(), $symbolVariable, $resolved, new ReadDetector(), $compilationContext, $original);
                        $symbol = $compilationContext->backend->getVariableCode($symbolVariable);

                        return new CompiledExpression('int', 'zephir_get_intval_ex('.$symbol.')', $expression);

                    case 'array':
                        $compilationContext->headersManager->add('kernel/operators');
                        $symbolVariable = $compilationContext->symbolTable->getVariableForRead($resolved->getCode(), $compilationContext, $expression);
                        $symbol = $compilationContext->backend->getVariableCode($symbolVariable);

                        return new CompiledExpression('int', 'zephir_get_intval('.$symbol.')', $expression);

                    case 'variable':
                        $compilationContext->headersManager->add('kernel/operators');
                        $symbolVariable = $compilationContext->symbolTable->getVariableForRead($resolved->getCode(), $compilationContext, $expression);
                        switch ($symbolVariable->getType()) {
                            case 'int':
                                return new CompiledExpression('int', $symbolVariable->getName(), $expression);

                            case 'double':
                                return new CompiledExpression('int', '(int) ('.$symbolVariable->getName().')', $expression);

                            case 'bool':
                                return new CompiledExpression('int', '(int) ('.$symbolVariable->getName().')', $expression);

                            case 'array':
                            case 'variable':
                            case 'string':
                                $symbol = $compilationContext->backend->getVariableCode($symbolVariable);

                                return new CompiledExpression('int', 'zephir_get_intval('.$symbol.')', $expression);

                            default:
                                throw new CompilerException('Cannot cast: '.$resolved->getType().'('.$symbolVariable->getType().') to '.$expression['left'], $expression);
                        }
                        break;

                    default:
                        throw new CompilerException('Cannot cast: '.$resolved->getType().' to '.$expression['left'], $expression);
                }
                break;

            case 'long':
                switch ($resolved->getType()) {
                    case 'int':
                        return new CompiledExpression('long', $resolved->getCode(), $expression);

                    case 'double':
                        return new CompiledExpression('long', '(long) '.$resolved->getCode(), $expression);

                    case 'bool':
                        return new CompiledExpression('long', $resolved->getBooleanCode(), $expression);

                    case 'array':
                        $compilationContext->headersManager->add('kernel/operators');
                        $symbolVariable = $compilationContext->symbolTable->getVariableForRead($resolved->getCode(), $compilationContext, $expression);

                        return new CompiledExpression('long', 'zephir_get_intval('.$symbolVariable->getName().')', $expression);

                    case 'variable':
                        $compilationContext->headersManager->add('kernel/operators');
                        $symbolVariable = $compilationContext->symbolTable->getVariableForRead($resolved->getCode(), $compilationContext, $expression);
                        switch ($symbolVariable->getType()) {
                            case 'int':
                                return new CompiledExpression('long', $symbolVariable->getName(), $expression);
                            case 'double':
                                return new CompiledExpression('long', '(long) ('.$symbolVariable->getName().')', $expression);
                            case 'variable':
                                $symbol = $compilationContext->backend->getVariableCode($symbolVariable);

                                return new CompiledExpression('long', 'zephir_get_intval('.$symbol.')', $expression);
                            default:
                                throw new CompilerException('Cannot cast: '.$resolved->getType().'('.$symbolVariable->getType().') to '.$expression['left'], $expression);
                        }
                        break;

                    default:
                        throw new CompilerException('Cannot cast: '.$resolved->getType().' to '.$expression['left'], $expression);
                }
                break;

            case 'double':
                switch ($resolved->getType()) {
                    case 'null':
                        return new CompiledExpression('double', 0, $expression);

                    case 'bool':
                        return new CompiledExpression('double', $resolved->getBooleanCode(), $expression);

                    case 'double':
                        return new CompiledExpression('double', $resolved->getCode(), $expression);

                    case 'array':
                        $compilationContext->headersManager->add('kernel/operators');
                        $symbolVariable = $compilationContext->symbolTable->getVariableForRead($resolved->getCode(), $compilationContext, $expression);
                        $symbol = $compilationContext->backend->getVariableCode($symbolVariable);

                        return new CompiledExpression('double', 'zephir_get_doubleval('.$symbol.')', $expression);

                    case 'variable':
                        $compilationContext->headersManager->add('kernel/operators');
                        $symbolVariable = $compilationContext->symbolTable->getVariableForRead($resolved->getCode(), $compilationContext, $expression);

                        switch ($symbolVariable->getType()) {
                            case 'int':
                                return new CompiledExpression('double', $symbolVariable->getName(), $expression);
                            case 'double':
                                return new CompiledExpression('double', '(double) ('.$symbolVariable->getName().')', $expression);
                            case 'bool':
                                return new CompiledExpression('double', '(double) ('.$symbolVariable->getName().')', $expression);
                            case 'array':
                            case 'variable':
                                $symbol = $compilationContext->backend->getVariableCode($symbolVariable);

                                return new CompiledExpression('double', 'zephir_get_doubleval('.$symbol.')', $expression);
                            default:
                                throw new CompilerException('Cannot cast: '.$resolved->getType().'('.$symbolVariable->getType().') to '.$expression['left'], $expression);
                        }
                        break;

                    default:
                        throw new CompilerException('Cannot cast: '.$resolved->getType().' to '.$expression['left'], $expression);
                }
                break;

            case 'bool':
                switch ($resolved->getType()) {
                    case 'int':
                        return new CompiledExpression('bool', '(zend_bool) '.$resolved->getCode(), $expression);
                    case 'bool':
                        return new CompiledExpression('bool', $resolved->getCode(), $expression);

                    case 'variable':
                        $compilationContext->headersManager->add('kernel/operators');
                        $symbolVariable = $compilationContext->symbolTable->getVariableForRead($resolved->getCode(), $compilationContext, $expression);
                        $symbol = $compilationContext->backend->getVariableCode($symbolVariable);
                        if ($symbolVariable->isTemporal()) {
                            $symbolVariable->setIdle(true);
                        }
                        switch ($symbolVariable->getType()) {
                            case 'variable':
                                return new CompiledExpression('bool', 'zephir_get_boolval('.$symbol.')', $expression);
                            default:
                                throw new CompilerException('Cannot cast: '.$resolved->getType().'('.$symbolVariable->getType().') to '.$expression['left'], $expression);
                        }
                        break;

                    default:
                        throw new CompilerException('Cannot cast: '.$resolved->getType().' to '.$expression['left'], $expression);
                }
                break;

            case 'char':
                switch ($resolved->getType()) {
                    case 'variable':
                        $compilationContext->headersManager->add('kernel/operators');
                        $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('char', $compilationContext);
                        $symbolVariable = $compilationContext->symbolTable->getVariableForRead($resolved->getCode(), $compilationContext, $expression);
                        $variableCode = $compilationContext->backend->getVariableCode($symbolVariable);
                        $compilationContext->codePrinter->output($tempVariable->getName().' = (char) zephir_get_intval('.$variableCode.');');

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

                    default:
                        throw new CompilerException('Cannot cast: '.$resolved->getType().' to '.$expression['left'], $expression);
                }
                break;

            case 'string':
                switch ($resolved->getType()) {
                    case 'variable':
                        $compilationContext->headersManager->add('kernel/operators');
                        $compilationContext->symbolTable->mustGrownStack(true);
                        $symbolVariable = $compilationContext->symbolTable->getTempVariable('string', $compilationContext);
                        $symbolVariable->setMustInitNull(true);
                        $symbolVariable->setIsInitialized(true, $compilationContext);
                        $symbolVariable->increaseUses();
                        $symbol = $compilationContext->backend->getVariableCode($symbolVariable);
                        $resolvedVariable = $compilationContext->symbolTable->getVariableForRead($resolved->getCode(), $compilationContext);
                        $resolvedCode = $compilationContext->backend->getVariableCode($resolvedVariable);
                        $compilationContext->codePrinter->output('zephir_get_strval('.$symbol.', '.$resolvedCode.');');
                        if ($symbolVariable->isTemporal()) {
                            $symbolVariable->setIdle(true);
                        }

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

                    default:
                        throw new CompilerException('Cannot cast: '.$resolved->getType().' to '.$expression['left'], $expression);
                }
                break;

            case 'array':
                switch ($resolved->getType()) {
                    case 'variable':
                        $compilationContext->headersManager->add('kernel/operators');
                        $compilationContext->symbolTable->mustGrownStack(true);
                        $symbolVariable = $compilationContext->symbolTable->getTempVariable('array', $compilationContext);
                        $symbolVariable->setMustInitNull(true);
                        $symbolVariable->setIsInitialized(true, $compilationContext);
                        $symbolVariable->increaseUses();
                        $symbol = $compilationContext->backend->getVariableCode($symbolVariable);
                        $resolvedVariable = $compilationContext->symbolTable->getVariableForRead($resolved->getCode(), $compilationContext);
                        $resolvedCode = $compilationContext->backend->getVariableCode($resolvedVariable);
                        $compilationContext->codePrinter->output('zephir_get_arrval('.$symbol.', '.$resolvedCode.');');
                        if ($symbolVariable->isTemporal()) {
                            $symbolVariable->setIdle(true);
                        }

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

                    default:
                        throw new CompilerException('Cannot cast: '.$resolved->getType().' to '.$expression['left'], $expression);
                }
                break;

            case 'object':
                switch ($resolved->getType()) {
                    case 'int':
                    case 'double':
                    case 'bool':
                    case 'null':
                    case 'string':
                    case 'array':
                        $compilationContext->headersManager->add('kernel/operators');
                        $compilationContext->symbolTable->mustGrownStack(true);
                        $symbolVariable = $compilationContext->symbolTable->getTempVariable('variable', $compilationContext);
                        $symbol = $compilationContext->backend->getVariableCode($symbolVariable);

                        /**
                         * zephir_convert_to_object use zval variable
                         * before use with it we create a new variable and assign value of literal.
                         */
                        $let = new LetVariable();
                        $original = $resolved->getOriginal();
                        $original['operator'] = 'assign';
                        $let->assign($symbolVariable->getName(), $symbolVariable, $resolved, new ReadDetector(), $compilationContext, $original);

                        $compilationContext->codePrinter->output('zephir_convert_to_object('.$symbol.');');

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

                    case 'variable':
                        $compilationContext->headersManager->add('kernel/operators');
                        $symbolVariable = $compilationContext->symbolTable->getVariableForRead($resolved->getCode(), $compilationContext, $expression);
                        $symbol = $compilationContext->backend->getVariableCode($symbolVariable);
                        if ($symbolVariable->isTemporal()) {
                            $symbolVariable->setIdle(true);
                        }

                        $compilationContext->codePrinter->output('zephir_convert_to_object('.$symbol.');');

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

                    default:
                        throw new CompilerException('Cannot cast: '.$resolved->getType().' to '.$expression['left'], $expression);
                }
                break;

            default:
                throw new CompilerException('Cannot cast: '.$resolved->getType().' to '.$expression['left'], $expression);
        }
    }
107948
public function optimize(array $expression, Call $call, CompilationContext $context)
    {
        if (!isset($expression['parameters'])) {
            return false;
        }

        $context->headersManager->add('kernel/variables');
        $resolvedParams = $call->getResolvedParamsAsExpr($expression['parameters'], $context, $expression);

        foreach ($resolvedParams as $resolvedParam) {
            $variable = $context->symbolTable->getVariable($resolvedParam->getCode());
            if (!$variable || !$variable->isVariable()) {
                /*
                 * Complex expressions require a temporary variable
                 */
                switch ($resolvedParam->getType()) {
                    case 'array':
                        $type = 'array';
                        break;
                    default:
                        $type = 'variable';
                        break;
                }

                $variable = $context->symbolTable->addTemp($type, $context);
                $variable->initVariant($context);

                $statement = new LetStatement([
                    'type' => 'let',
                    'assignments' => [
                        [
                            'assign-type' => $type,
                            'variable' => $variable->getName(),
                            'operator' => 'assign',
                            'expr' => [
                                'type' => $resolvedParam->getType(),
                                'value' => $resolvedParam->getCode(),
                                'file' => $expression['file'],
                                'line' => $expression['line'],
                                'char' => $expression['char'],
                            ],
                            'file' => $expression['file'],
                            'line' => $expression['line'],
                            'char' => $expression['char'],
                        ],
                    ],
                ]);
                $statement->compile($context);
            } else {
                /**
                 * This mark the variable as used.
                 */
                $variable = $context->symbolTable->getVariableForRead($resolvedParam->getCode(), $context, $expression);
            }

            $symbol = $context->backend->getVariableCodePointer($variable);
            $context->codePrinter->output('zephir_var_dump('.$symbol.' TSRMLS_CC);');
        }

        return new CompiledExpression('null', 'null', $expression);
    }
661163
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);
            }
        }

        $expr = new EvalExpression();
        $condition = $expr->optimize($expression['left'], $compilationContext);
        $compilationContext->codePrinter->output('if ('.$condition.') {');

        $compilationContext->codePrinter->increaseLevel();

        /**
         * Create an implicit 'let' operation to update the evaluated left operator.
         */
        $statement = new LetStatement([
            'type' => 'let',
            'assignments' => [
                [
                    'assign-type' => 'variable',
                    'variable' => $returnVariable->getName(),
                    'operator' => 'assign',
                    'expr' => $expression['right'],
                    'file' => $expression['file'],
                    'line' => $expression['line'],
                    'char' => $expression['char'],
                ],
            ],
        ]);
        $statement->compile($compilationContext);

        $compilationContext->codePrinter->decreaseLevel();
        $compilationContext->codePrinter->output('} else {');
        $compilationContext->codePrinter->increaseLevel();

        /**
         * Create an implicit 'let' operation to update the evaluated left operator.
         */
        $statement = new LetStatement([
            'type' => 'let',
            'assignments' => [
                [
                    'assign-type' => 'variable',
                    'variable' => $returnVariable->getName(),
                    'operator' => 'assign',
                    'expr' => $expression['extra'],
                    'file' => $expression['file'],
                    'line' => $expression['line'],
                    'char' => $expression['char'],
                ],
            ],
        ]);
        $statement->compile($compilationContext);

        $compilationContext->codePrinter->decreaseLevel();
        $compilationContext->codePrinter->output('}');

        return new CompiledExpression('variable', $returnVariable->getName(), $expression);
    }
1102184
public function compile($expression, CompilationContext $compilationContext)
    {
        $propertyAccess = $expression;

        $expr = new Expression($propertyAccess['left']);
        $expr->setReadOnly(true);
        $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']);
        }

        $property = $propertyAccess['right']['value'];

        $propertyDefinition = null;
        $classDefinition = null;
        $currentClassDefinition = $compilationContext->classDefinition;

        /*
         * If the property is accessed on 'this', we check if the method does exist
         */
        if ('this' == $variableVariable->getRealName()) {
            $classDefinition = $currentClassDefinition;
            if (!$classDefinition->hasProperty($property)) {
                throw new CompilerException("Class '".$classDefinition->getCompleteName()."' does not have a property called: '".$property."'", $expression);
            }

            $propertyDefinition = $classDefinition->getProperty($property);
        } else {
            /*
             * If we know the class related to a variable we could check if the property
             * is defined on that class
             */
            if ($variableVariable->hasAnyDynamicType('object')) {
                $classType = current($variableVariable->getClassTypes());
                $compiler = $compilationContext->compiler;

                if ($compiler->isClass($classType)) {
                    $classDefinition = $compiler->getClassDefinition($classType);
                    if (!$classDefinition) {
                        throw new CompilerException('Cannot locate class definition for class: '.$classType, $expression);
                    }

                    if (!$classDefinition->hasProperty($property)) {
                        throw new CompilerException("Class '".$classType."' does not have a property called: '".$property."'", $expression);
                    }

                    $propertyDefinition = $classDefinition->getProperty($property);
                }
            }
        }

        /*
         * Having a proper propertyDefinition we can check if the property is readable
         * according to its modifiers
         */
        if ($propertyDefinition) {
            if ($propertyDefinition->isStatic()) {
                throw new CompilerException("Attempt to access static property '".$property."' as non static", $expression);
            }

            if (!$propertyDefinition->isPublic()) {
                /*
                 * Protected variables only can be read in the class context
                 * where they were declared
                 */
                if ($classDefinition == $currentClassDefinition) {
                    if ($propertyDefinition->isPrivate()) {
                        $declarationDefinition = $propertyDefinition->getClassDefinition();
                        if ($declarationDefinition !== $currentClassDefinition) {
                            throw new CompilerException("Attempt to access private property '".$property."' outside of its declared class context: '".$declarationDefinition->getCompleteName()."'", $expression);
                        }
                    }
                } else {
                    if ($propertyDefinition->isProtected()) {
                    } else {
                        if ($propertyDefinition->isPrivate()) {
                            $declarationDefinition = $propertyDefinition->getClassDefinition();
                            if ($declarationDefinition !== $currentClassDefinition) {
                                throw new CompilerException("Attempt to access private property '".$property."' outside of its declared class context: '".$declarationDefinition->getCompleteName()."'", $expression);
                            }
                        }
                    }
                }
            }
        }

        /**
         * Resolves the symbol that expects the value.
         */
        $readOnly = false;
        $makeSymbolVariable = false;
        if ($this->expecting) {
            if ($this->expectingVariable) {
                $symbolVariable = $this->expectingVariable;

                /*
                 * If a variable is assigned once in the method, we try to promote it
                 * to a read only variable
                 */
                if ('return_value' != $symbolVariable->getName()) {
                    $line = $compilationContext->symbolTable->getLastCallLine();
                    if (false === $line || ($line > 0 && $line < $expression['line'])) {
                        $numberMutations = $compilationContext->symbolTable->getExpectedMutations($symbolVariable->getName());
                        if (1 == $numberMutations) {
                            if ($symbolVariable->getNumberMutations() == $numberMutations) {
                                $symbolVariable->setMemoryTracked(false);
                                $readOnly = true;
                            }
                        }
                    }
                }

                /*
                 * Variable is not read only or it wasn't promoted
                 */
                if (!$readOnly) {
                    if ('return_value' != $symbolVariable->getName()) {
                        $symbolVariable->observeVariant($compilationContext);
                        $this->readOnly = false;
                    } else {
                        $makeSymbolVariable = true;
                    }
                }

                $this->readOnly = false;
            } else {
                $makeSymbolVariable = true;
            }
        } else {
            $makeSymbolVariable = true;
        }

        $readOnly = $this->readOnly || $readOnly;
        $useOptimized = $classDefinition == $currentClassDefinition;
        if (!$compilationContext->backend->isZE3()) {
            $readOnly = $useOptimized && $readOnly;
        }
        if ($makeSymbolVariable) {
            if ($readOnly) {
                $symbolVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
            } else {
                $symbolVariable = $compilationContext->symbolTable->getTempVariableForObserve('variable', $compilationContext, $expression);
            }
        }

        /*
         * Variable that receives a property value must be polymorphic
         */
        if (!$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');

        $compilationContext->backend->fetchProperty($symbolVariable, $variableVariable, $property, $readOnly, $compilationContext, $useOptimized);

        return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
    }
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;
    }
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);
    }
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);
    }
413
function compile($expression) {
        $options = $this->parser->parse($expression);
        $command = $this->commandFactory->create($options);
        return new Executable($command, $this->variables);
    }
1284267
public function getExpected(CompilationContext $compilationContext, $expression, $init = true)
    {
        $isExpecting = $this->expecting;
        $symbolVariable = $this->expectingVariable;

        if ($isExpecting) {
            if (\is_object($symbolVariable)) {
                if ('variable' == $symbolVariable->getType()) {
                    if (!$init) {
                        return $symbolVariable;
                    }
                    $symbolVariable->initVariant($compilationContext);
                } else {
                    if (!$this->readOnly) {
                        if (!$this->literalOnly) {
                            $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression);
                        } else {
                            $symbolVariable = $compilationContext->symbolTable->getTempComplexLiteralVariableForWrite('variable', $compilationContext, $expression);
                        }
                    } else {
                        $symbolVariable = $compilationContext->symbolTable->getTempLocalVariableForWrite('variable', $compilationContext, $expression);
                    }
                }
            } else {
                if (!$this->readOnly) {
                    if (!$this->literalOnly) {
                        $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression);
                    } else {
                        $symbolVariable = $compilationContext->symbolTable->getTempComplexLiteralVariableForWrite('variable', $compilationContext, $expression);
                    }
                } else {
                    $symbolVariable = $compilationContext->symbolTable->getTempLocalVariableForWrite('variable', $compilationContext, $expression);
                }
            }
        }

        return $symbolVariable;
    }
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;
        }
    }
201274
protected function _compileExpressionTerms(
        ExpressionInterface $expression,
        array $renderedTerms,
        $context = null
    ) {
        $opStr = $this->_getOperatorString();
        $argsStr = implode(', ', $renderedTerms);

        return sprintf('%1$s(%2$s)', $opStr, $argsStr);
    }