Zephir\FunctionCall::_callDynamic PHP Method

_callDynamic() protected method

protected _callDynamic ( array $expression, zephir\CompilationContext $compilationContext ) : zephir\CompiledExpression
$expression array
$compilationContext zephir\CompilationContext
return zephir\CompiledExpression
    protected function _callDynamic(array $expression, CompilationContext $compilationContext)
    {
        $variable = $compilationContext->symbolTable->getVariableForRead($expression['name'], $compilationContext, $expression);
        switch ($variable->getType()) {
            case 'variable':
            case 'string':
                break;
            default:
                throw new CompilerException("Variable type: " . $variable->getType() . " cannot be used as dynamic caller", $expression['left']);
        }
        /**
         * Resolve parameters
         */
        if (isset($expression['parameters'])) {
            $params = $this->getResolvedParams($expression['parameters'], $compilationContext, $expression);
        } else {
            $params = array();
        }
        $codePrinter = $compilationContext->codePrinter;
        /**
         * Process the expected symbol to be returned
         */
        $this->processExpectedObservedReturn($compilationContext);
        /**
         * At this point the function will be called in the PHP userland.
         * PHP functions only return zvals so we need to validate the target variable is also a zval
         */
        $symbolVariable = $this->getSymbolVariable();
        if ($symbolVariable) {
            if (!$symbolVariable->isVariable()) {
                throw new CompilerException("Returned values by functions can only be assigned to variant variables", $expression);
            }
            /**
             * We don't know the exact dynamic type returned by the method call
             */
            $symbolVariable->setDynamicTypes('undefined');
        }
        /**
         * Include fcall header
         */
        $compilationContext->headersManager->add('kernel/fcall');
        /**
         * Add the last call status to the current symbol table
         */
        $this->addCallStatusFlag($compilationContext);
        /**
         * Call functions must grown the stack
         */
        $compilationContext->symbolTable->mustGrownStack(true);
        if (!isset($expression['parameters'])) {
            if ($this->isExpectingReturn()) {
                if ($symbolVariable->getName() != 'return_value') {
                    if ($this->mustInitSymbolVariable()) {
                        $symbolVariable->setMustInitNull(true);
                        $symbolVariable->trackVariant($compilationContext);
                    }
                }
                $compilationContext->backend->callDynamicFunction($symbolVariable, $variable, $compilationContext);
            } else {
                $compilationContext->backend->callDynamicFunction(null, $variable, $compilationContext);
            }
        } else {
            if (count($params)) {
                if ($this->isExpectingReturn()) {
                    if ($symbolVariable->getName() != 'return_value') {
                        if ($this->mustInitSymbolVariable()) {
                            $symbolVariable->setMustInitNull(true);
                            $symbolVariable->trackVariant($compilationContext);
                        }
                    }
                    $compilationContext->backend->callDynamicFunction($symbolVariable, $variable, $compilationContext, $params);
                } else {
                    $compilationContext->backend->callDynamicFunction(null, $variable, $compilationContext, $params);
                }
            } else {
                if ($this->isExpectingReturn()) {
                    if ($symbolVariable->getName() != 'return_value') {
                        if ($this->mustInitSymbolVariable()) {
                            $symbolVariable->setMustInitNull(true);
                            $symbolVariable->trackVariant($compilationContext);
                        }
                    }
                    $compilationContext->backend->callDynamicFunction($symbolVariable, $variable, $compilationContext);
                } else {
                    $compilationContext->backend->callDynamicFunction(null, $variable, $compilationContext);
                }
            }
        }
        /**
         * Temporary variables must be copied if they have more than one reference
         */
        foreach ($this->getMustCheckForCopyVariables() as $checkVariable) {
            $codePrinter->output('zephir_check_temp_parameter(' . $checkVariable . ');');
        }
        $this->addCallStatusOrJump($compilationContext);
        /**
         * We can mark temporary variables generated as idle
         */
        foreach ($this->getTemporalVariables() as $tempVariable) {
            $tempVariable->setIdle(true);
        }
        if ($this->isExpectingReturn()) {
            return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
        }
        return new CompiledExpression('null', null, $expression);
    }