@param array              $expression
@param Call               $call
@param CompilationContext $context

@throws CompilerException

@return bool|CompiledExpression|mixed
420159
public function optimize(array $expression, Call $call, CompilationContext $context)
    {
        if (isset($expression['parameters']) && \count($expression['parameters']) > 1) {
            return false;
        }

        $context->headersManager->add('kernel/exit');
        if (isset($expression['parameters'])) {
            //TODO: protect resolvedParams[0] from restore
        }
        if (!isset($expression['parameters'])) {
            $context->codePrinter->output('ZEPHIR_MM_RESTORE();');
            $context->codePrinter->output('zephir_exit_empty();');
        } else {
            $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);
            $context->codePrinter->output('ZEPHIR_MM_RESTORE();');
            $context->codePrinter->output('zephir_exit('.$resolvedParams[0].');');
        }

        return new CompiledExpression('void ', '', $expression);
    }
663163
public function optimize(array $expression, Call $call, CompilationContext $context)
    {
        if (!isset($expression['parameters'])) {
            return false;
        }

        /*
         * Process the expected symbol to be returned
         */
        $call->processExpectedReturn($context);

        $symbolVariable = $call->getSymbolVariable();
        if ($symbolVariable) {
            if (!$symbolVariable->isVariable()) {
                throw new CompilerException('Returned values by functions can only be assigned to variant variables', $expression);
            }
        }

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

        if (!$symbolVariable || !$symbolVariable->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);
        }
        $variableSymbol = $context->backend->getVariableCodePointer($variable);

        /*
         * let a = var_export(val);
         */
        if ($symbolVariable) {
            if ('return_value' == $symbolVariable->getName()) {
                $symbolVariable = $context->symbolTable->getTempVariableForWrite('variable', $context);
            } else {
                $symbolVariable->initVariant($context);
            }
            $symbol = $context->backend->getVariableCode($symbolVariable);
            $context->codePrinter->output('zephir_var_export_ex('.$symbol.', '.$variableSymbol.' TSRMLS_CC);');

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

        $context->codePrinter->output('zephir_var_export('.$variableSymbol.' TSRMLS_CC);');

        return new CompiledExpression('null', 'null', $expression);
    }
628548
public function optimize(array $expression, Call $call, CompilationContext $context)
    {
        if (isset($expression['parameters'])) {
            if (0 != \count($expression['parameters'])) {
                throw new CompilerException("This function doesn't require parameters", $expression);
            }
        }

        /*
         * Process the expected symbol to be returned
         */
        $call->processExpectedReturn($context);

        $symbolVariable = $call->getSymbolVariable(true, $context);
        if ($symbolVariable) {
            if (!$symbolVariable->isVariable()) {
                throw new CompilerException('Returned values by functions can only be assigned to variant variables', $expression);
            }
        }

        if ($call->mustInitSymbolVariable()) {
            $symbolVariable->initVariant($context);
        }

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

        $context->codePrinter->output('zephir_create_symbol_table(TSRMLS_C);');
        $context->codePrinter->output('');

        return new CompiledExpression('null', null, $expression);
    }
1285190
public function optimizeTypeOf($expr, CompilationContext $compilationContext)
    {
        if (!isset($expr['left'])) {
            return false;
        }

        if (!isset($expr['right']) && !isset($expr['right']['value'])) {
            return false;
        }

        if ('typeof' == $expr['left']['type']) {
            if ('string' != $expr['right']['type']) {
                $compilationContext->logger->warning(
                    "Possible invalid comparison for 'typeof' operator with non-string",
                    ['invalid-typeof-comparison', $expr['right']]
                );

                return false;
            }

            if (isset($expr['type'])) {
                switch ($expr['type']) {
                    case 'identical':
                    case 'equals':
                        $operator = '==';
                        break;

                    case 'not-identical':
                    case 'not-equals':
                        $operator = '!=';
                        break;

                    default:
                        return false;
                }
            }

            $expression = new Expression($expr['left']['left']);
            $condition = $expression->compile($compilationContext);
            $variableVariable = $compilationContext->symbolTable->getVariableForRead($condition->getCode(), $compilationContext, $expr);

            if ('string' != $expr['right']['type']) {
                throw new CompilerException('Right expression of typeof operator must be "string" type', $expr['right']);
            }

            $value = strtolower($expr['right']['value']);

            switch ($variableVariable->getType()) {
                case 'double':
                    switch ($value) {
                        case 'double':
                        case 'float':
                            $condition = '1 '.$operator.' 1';
                            break;

                        default:
                            $condition = '1 '.$operator.' 0';
                            break;
                    }
                    break;

                case 'int':
                case 'integer':
                case 'long':
                    switch ($value) {
                        case 'int':
                        case 'integer':
                        case 'long':
                            $condition = '1 '.$operator.' 1';
                            break;

                        default:
                            $condition = '1 '.$operator.' 0';
                            break;
                    }
                    break;

                case 'bool':
                    switch ($value) {
                        case 'bool':
                        case 'boolean':
                            $condition = '1 '.$operator.' 1';
                            break;

                        default:
                            $condition = '1 '.$operator.' 0';
                            break;
                    }
                    break;

                case 'array':
                    switch ($value) {
                        case 'array':
                            $condition = '1 '.$operator.' 1';
                            break;

                        default:
                            $condition = '1 '.$operator.' 0';
                            break;
                    }
                    break;

                case 'string':
                    switch ($value) {
                        case 'string':
                            $condition = '1 '.$operator.' 1';
                            break;

                        default:
                            $condition = '1 '.$operator.' 0';
                            break;
                    }
                    break;

                case 'variable':
                    $condition = $compilationContext->backend->getTypeofCondition($variableVariable, $operator, $value, $compilationContext);
                    break;

                default:
                    return false;
            }

            return new CompiledExpression('bool', $condition, $expr);
        }

        return false;
    }
38022
public function parse(Context $context) {
	    $this->context = $context;
		$this->viewElement = $context->tag;

		//Interpret an empty expression as boolean false.
		if(trim($this->expression) == '') {
		  $this->pushOperand(new TokenLiteral(false));
		  return true;
		}

		$char = '';

		try {
			$expressionSize = strlen($this->expression);
			for($this->parsingPosition = 0; $this->parsingPosition < $expressionSize; ++ $this->parsingPosition) {
				$char = $this->expression[$this->parsingPosition];
				$this->currentState->input($this, $char);
			}

			$this->currentState->endOfInput($this);

			while(count($this->stackOperators)) {
				$operator = array_pop($this->stackOperators);
				$nbOperands = $operator->getNumOperands();
				if($nbOperands) {
					// Check that we have enough operands on the stack.
					if (count($this->stackRP) < $nbOperands) {
						throw new LexerSyntaxErrorException('Missing operand', $this->getViewFile(), $this->getViewLine());
					}
					$operator->setOperands(array_splice($this->stackRP, count($this->stackRP) - $nbOperands, $nbOperands));
				}
				$this->stackRP[] = $operator;
				if($operator instanceof TokenFunction) {
									array_pop($this->stackFunctions);
				}
			}
		}

		// Enrich the Lexer parsing and tokenizing exceptions with template file and line
		catch (LexerUnbalancedParenthesesException $exception) {
		    throw new LexerUnbalancedParenthesesException($exception->getMessage(), $this->getViewFile(), $this->getViewLine());
        } catch (LexerSyntaxErrorException $exception) {
		    throw new LexerSyntaxErrorException($exception->getMessage(), $this->getViewFile(), $this->getViewLine());
        } catch (Exception $exception) {
			$errorMsg = "Unexpected character: $char at position: {$this->parsingPosition} in expression: {$this->expression}.";
			throw new LexerUnexpectedCharException($errorMsg, $this->getViewFile(), $this->getViewLine());
		}

		if( (count($this->stackOperators) > 0) ||
				(count($this->stackFunctions) > 0) ||
				(count($this->stackRP) != 1)
			)
		{
			$message = $this->getViewFile() . '(' . $this->getViewLine() . '): Syntax error in expression: ' . $this->expression;
			throw new LexerSyntaxErrorException($message,
					$this->getViewFile(),
					$this->getViewLine());
		}

		// Check for unbalanced parentheses:
		if( ($this->stackRP[0] instanceof TokenFunction) &&
		    (! $this->stackRP[0]->isClosed())
		)
		{
		  $message = $this->getViewFile() . '(' . $this->getViewLine() . '): Unbalanced parentheses in expression: ' . $this->expression;
		  throw new LexerUnbalancedParenthesesException($message,
		    $this->getViewFile(),
		    $this->getViewLine());
		}

		return true;
	}
338530
public function fromCall(Call $call): CallVerifier
    {
        return new CallVerifier(
            $call,
            $this->matcherFactory,
            $this->matcherVerifier,
            $this->generatorVerifierFactory,
            $this->iterableVerifierFactory,
            $this->assertionRecorder,
            $this->assertionRenderer
        );
    }
748439
private function processOptionals(array &$expression, Call $call, CompilationContext $context)
    {
        $flags = null;
        $offset = null;

        $offsetParamOffset = 4;
        if (isset($expression['parameters'][4]) && 'int' === $expression['parameters'][4]['parameter']['type']) {
            $offset = $expression['parameters'][4]['parameter']['value'].' ';
            unset($expression['parameters'][4]);
        }

        if (isset($expression['parameters'][3]) && 'int' === $expression['parameters'][3]['parameter']['type']) {
            $flags = $expression['parameters'][3]['parameter']['value'].' ';
            $offsetParamOffset = 3;
            unset($expression['parameters'][3]);
        }

        try {
            $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);

            if (null === $offset && isset($resolvedParams[$offsetParamOffset])) {
                $context->headersManager->add('kernel/operators');
                $offset = 'zephir_get_intval('.$resolvedParams[$offsetParamOffset].') ';
            }

            if (null === $flags && isset($resolvedParams[3])) {
                $context->headersManager->add('kernel/operators');
                $flags = 'zephir_get_intval('.$resolvedParams[3].') ';
            }
        } catch (Exception $e) {
            throw new CompilerException($e->getMessage(), $expression, $e->getCode(), $e);
        }

        if (null === $flags) {
            $flags = '0 ';
        }

        if (null === $offset) {
            $offset = '0 ';
        }

        return [$flags, $offset];
    }
390358
function create(context) {
    return {
        CallExpression(node) {
            if (isNamedDefine(node)) {
                context.report(node, message);
            }
        }
    };
}
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);
        }
    }
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);
    }
534043
public function compile(array $expression, CompilationContext $compilationContext)
    {
        $compilationContext->headersManager->add('kernel/operators');

        if (!isset($expression['left'])) {
            throw new CompilerException("Invalid 'left' operand for 'empty' expression", $expression['left']);
        }

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

        if ('variable' != $left->getType() && 'array' != $left->getType()) {
            throw new CompilerException("'empty' operand only can be a variable", $expression['left']);
        }

        $variableLeft = $compilationContext->symbolTable->getVariableForRead($left->getCode(), $compilationContext, $expression['left']);
        if (!$variableLeft->isVariable() && !$variableLeft->isString() && !$variableLeft->isArray()) {
            throw new CompilerException("Only dynamic/string variables can be used in 'empty' operators", $expression['left']);
        }

        return new CompiledExpression('bool', 'ZEPHIR_IS_EMPTY('.$compilationContext->backend->getVariableCode($variableLeft).')', $expression);
    }
990303
public function compile($expression, CompilationContext $context)
    {
        $left = new Expression($expression['left']);
        $resolved = $left->compile($context);

        if ('variable' != $resolved->getType()) {
            throw new CompilerException("InstanceOf requires a 'dynamic variable' in the left operand", $expression);
        }

        $symbolVariable = $context->symbolTable->getVariableForRead($resolved->getCode(), $context, $expression);
        if (!$symbolVariable->isVariable()) {
            throw new CompilerException("InstanceOf requires a 'dynamic variable' in the left operand", $expression);
        }

        $right = new Expression($expression['right']);
        $resolved = $right->compile($context);
        $resolvedVariable = $resolved->getCode();

        switch ($resolved->getType()) {
            case 'string':
                $className = fqcn($resolvedVariable, $context->classDefinition->getNamespace(), $context->aliasManager);

                if ($context->compiler->isClass($className)) {
                    $classDefinition = $context->compiler->getClassDefinition($className);
                    $classEntry = $classDefinition->getClassEntry($context);
                } else {
                    if (!class_exists($className, false)) {
                        $code = 'SL("'.$resolvedVariable.'")';
                    } else {
                        $classEntry = $context->classDefinition->getClassEntryByClassName($className, $context, true);
                        if (!$classEntry) {
                            $code = 'SL("'.$resolvedVariable.'")';
                        }
                    }
                }
                break;
            default:
                switch ($resolved->getType()) {
                    case 'variable':
                        if ('this' == $resolvedVariable) {
                            /**
                             * @todo It's an optimization variant, but maybe we need to get entry in runtime?
                             */
                            $classEntry = $context->classDefinition->getClassEntry($context);
                        } elseif (!$context->symbolTable->hasVariable($resolvedVariable)) {
                            $className = $context->getFullName($resolvedVariable);

                            if ('Traversable' == $className) {
                                $symbol = $context->backend->getVariableCode($symbolVariable);

                                return new CompiledExpression('bool', 'zephir_zval_is_traversable('.$symbol.' TSRMLS_CC)', $expression);
                            }

                            if ($context->compiler->isClass($className)) {
                                $classDefinition = $context->compiler->getClassDefinition($className);
                                $classEntry = $classDefinition->getClassEntry($context);
                            } else {
                                if ($context->compiler->isInterface($className)) {
                                    $classDefinition = $context->compiler->getClassDefinition($className);
                                    $classEntry = $classDefinition->getClassEntry($context);
                                } else {
                                    if (!class_exists($className, false)) {
                                        $code = 'SL("'.trim(escape_class($className), '\\').'")';
                                    } else {
                                        $classEntry = $context->classDefinition->getClassEntryByClassName($className, $context, true);
                                        if (!$classEntry) {
                                            $code = 'SL("'.trim(escape_class($className), '\\').'")';
                                        }
                                    }
                                }
                            }
                        } else {
                            $code = $this->prepareBackendSpecificCode($resolvedVariable, $context);
                        }
                        break;

                    case 'property-access':
                    case 'array-access':
                        $context->headersManager->add('kernel/operators');
                        $tempVariable = $context->symbolTable->getTempVariableForWrite('string', $context);
                        $tempVariable->setMustInitNull(true);
                        $tempVariableName = $tempVariable->getName();
                        $context->codePrinter->output('zephir_get_strval('.$tempVariableName.', '.$resolvedVariable.');');
                        $code = $this->prepareBackendSpecificCode($tempVariableName, $context);
                        break;

                    default:
                        throw new CompilerException("InstanceOf requires a 'variable' or a 'string' in the right operand", $expression);
                }
        }

        /* @TODO, Possible optimization is use zephir_is_instance when the const class name is an internal class or interface */
        $context->headersManager->add('kernel/object');
        $symbol = $context->backend->getVariableCode($symbolVariable);
        if (isset($code)) {
            return new CompiledExpression('bool', 'zephir_is_instance_of('.$symbol.', '.$code.' TSRMLS_CC)', $expression);
        }

        return new CompiledExpression('bool', 'zephir_instance_of_ev('.$symbol.', '.$classEntry.' TSRMLS_CC)', $expression);
    }
359647
public function optimize(array $expression, Call $call, CompilationContext $context)
    {
        if (!isset($expression['parameters'])) {
            return false;
        }

        if (\count($expression['parameters']) > 1) {
            return false;
        }

        /*
         * Resolve parameters as vars
         */
        $call->getResolvedParams($expression['parameters'], $context, $expression);
        /**
         * Get CompiledExpression(s) for resolved var(s).
         */
        $resolvedParams = $call->getResolvedParamsAsExpr($expression['parameters'], $context, $expression);
        $compiledExpression = $resolvedParams[0];

        switch ($compiledExpression->getType()) {
            case 'int':
            case 'float':
            case 'long':
            case 'ulong':
            case 'double':
                $context->headersManager->add('math');

                return $this->passNativeFCall($compiledExpression, $expression);
                break;
            case 'variable':
                $variable = $context->symbolTable->getVariable($compiledExpression->getCode());
                switch ($variable->getType()) {
                    case 'int':
                    case 'float':
                    case 'long':
                    case 'ulong':
                    case 'double':
                        $context->headersManager->add('math');

                        return $this->passNativeFCall($compiledExpression, $expression);
                        break;
                    case 'variable':
                        $context->headersManager->add('kernel/math');

                        return new CompiledExpression(
                            'double',
                            'zephir_'.$this->getFunctionName().'('.$context->backend->getVariableCode($variable).' TSRMLS_CC)',
                            $expression
                        );
                        break;
                }
                break;
        }

        return false;
    }
172194
public function join($caller, CompilationContext $compilationContext, Call $call, array $expression)
    {
        $functionCall = BuilderFactory::getInstance()->statements()
            ->functionCall('join', $expression['parameters'])
            ->addArgument($caller)
            ->setFile($expression['file'])
            ->setLine($expression['line'])
            ->setChar($expression['char']);

        $expression = new Expression($functionCall->build());

        return $expression->compile($compilationContext);
    }
367649
public function optimize(array $expression, Call $call, CompilationContext $context)
    {
        if (!isset($expression['parameters'])) {
            return false;
        }

        if (1 != \count($expression['parameters'])) {
            throw new CompilerException("'globals_get' only accepts one parameter", $expression);
        }

        if ('string' != $expression['parameters'][0]['parameter']['type']) {
            throw new CompilerException("A string parameter is required for 'globals_get'", $expression);
        }

        $globalName = $expression['parameters'][0]['parameter']['value'];

        if (!$context->compiler->isExtensionGlobal($globalName)) {
            throw new CompilerException("Global '".$globalName."' cannot be read because it isn't defined", $expression);
        }

        $globalDefinition = $context->compiler->getExtensionGlobal($globalName);

        if (false !== strpos($globalName, '.')) {
            $parts = explode('.', $globalName);

            return new CompiledExpression($globalDefinition['type'], 'ZEPHIR_GLOBAL('.$parts[0].').'.$parts[1], $expression);
        }

        return new CompiledExpression($globalDefinition['type'], 'ZEPHIR_GLOBAL('.$globalName.')', $expression);
    }
137608
public function compile(CompilationContext $compilationContext)
    {
        $exprRaw = $this->statement['expr'];

        /*
         * @TODO implement optimizers here
         */
        if ('fcall' == $exprRaw['type']) {
            if ('range' == $exprRaw['name']) {
                $status = $this->compileRange($exprRaw, $compilationContext);
                if (false !== $status) {
                    return;
                }
            }

            if ('iterator' == $exprRaw['name']) {
                $status = $this->compileIterator($exprRaw, $compilationContext);
                if (false !== $status) {
                    return;
                }
            }
        }

        $expr = new Expression($exprRaw);
        $expr->setReadOnly(true);
        $expression = $expr->compile($compilationContext);

        /*
         * Check for traversing a constant string
         */
        if ('string' == $expression->getType()) {
            $this->compileStringTraverse($expression, $compilationContext, null);

            return;
        }

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

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

            case 'string':
                $this->compileStringTraverse($expression, $compilationContext, $exprVariable);
                break;

            default:
                throw new CompilerException('Cannot traverse value type: '.$exprVariable->getType(), $exprRaw);
        }
    }
266801
public function compile(array $expression, CompilationContext $compilationContext)
    {
        if (!isset($expression['parameters'])) {
            throw new CompilerException("Invalid 'parameters' for new-type", $expression);
        }

        switch ($expression['internal-type']) {
            case 'array':
                $compilationContext->headersManager->add('kernel/array');
                $functionName = 'create_array';
                break;

            case 'string':
                $compilationContext->headersManager->add('kernel/string');
                $functionName = 'create_string';
                break;

            default:
                throw new CompilerException('Cannot build instance of type', $expression);
        }

        $builder = new FunctionCallBuilder(
            $functionName,
            $expression['parameters'],
            1,
            $expression['file'],
            $expression['line'],
            $expression['char']
        );

        /**
         * Implicit type coercing.
         */
        $castBuilder = new CastOperatorBuilder($expression['internal-type'], $builder);

        $expression = new Expression($castBuilder->get());
        $expression->setReadOnly($this->readOnly);

        try {
            return $expression->compile($compilationContext);
        } catch (Exception $e) {
            throw new CompilerException($e->getMessage(), $expression, $e->getCode(), $e);
        }
    }