Checks if a function exists or is a built-in Zephir function.

@param string             $functionName
@param CompilationContext $context

@return bool
175365
public function functionExists($functionName, CompilationContext $context)
    {
        if (\function_exists($functionName)) {
            return true;
        }
        if ($this->isBuiltInFunction($functionName)) {
            return true;
        }

        $internalName = ['f__'.$functionName];
        if (isset($context->classDefinition)) {
            $lowerNamespace = strtolower($context->classDefinition->getNamespace());
            $prefix = 'f_'.str_replace('\\', '_', $lowerNamespace);

            $internalName[] = $prefix.'_'.$functionName;
        }

        foreach ($internalName as $name) {
            if (isset($context->compiler->functionDefinitions[$name])) {
                return true;
            }
        }

        return false;
    }
740763
protected function matchesPatterns($functionName)
    {
        $matches = array_filter(
            array_map(
                function ($pattern) use ($functionName) {
                    return fnmatch($pattern, $functionName);
                },
                $this->methodPatterns
            )
        );
        return !empty($matches);
    }
659085
private function parseFunctionArguments($funcName, $context)
    {
        $args = array();

        // NO ARGS, RETURN
        if($this->tokenizer->is(TokenType::RIGHT_PAREN))
        {
            return $args;
        }

        while(true)
        {
            $args[] = $this->parseFunctionArgument($funcName, $context);

            if($this->tokenizer->is(TokenType::COMMA))
            {
                // ADVANCE TO NEXT ARGUMENT, OR CLOSING PARENTHESIS
                $this->tokenizer->readNextToken();

                continue;
            }
            break;
        }
        return $args;
    }
592852
public function optimize(array $expression, Call $call, CompilationContext $context)
    {
        if (!isset($expression['parameters'])) {
            return false;
        }

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

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

        return new CompiledExpression('bool', 'zephir_is_scalar('.$resolvedParams[0].')', $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;
    }
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);
    }
181491
public function hasMethod($methodName)
    {
        $methodNameLower = strtolower($methodName);
        foreach ($this->methods as $name => $method) {
            if ($methodNameLower == $name) {
                return true;
            }
        }

        $extendsClassDefinition = $this->getExtendsClassDefinition();
        if ($extendsClassDefinition instanceof ClassDefinitionRuntime) {
            try {
                $extendsClassDefinition = $this->compiler->getInternalClassDefinition(
                    $extendsClassDefinition->getName()
                );
            } catch (\ReflectionException $e) {
                // Do nothing
                return false;
            }
        }

        while ($extendsClassDefinition instanceof self) {
            if ($extendsClassDefinition->hasMethod($methodName)) {
                return true;
            }

            $extendsClassDefinition = $extendsClassDefinition->getExtendsClassDefinition();
        }

        return false;
    }
1188844
public function getFunction($functionName)
    {
        $lowFunc  = strtolower($functionName);
        $cacheKey = self::CACHE_KEY_FUNCS . $lowFunc;

        $reflectedFunc = $this->cache->fetch($cacheKey);

        if (false === $reflectedFunc) {
            $reflectedFunc = new ReflectionFunction($functionName);
            $this->cache->store($cacheKey, $reflectedFunc);
        }

        return $reflectedFunc;
    }
221508
public function get(CompilationContext $compilationContext, $methodName, Variable $caller)
    {
        $compiler = $compilationContext->compiler;

        $numberPoly = 0;

        if ('this' == $caller->getRealName()) {
            $classDefinition = $compilationContext->classDefinition;
            if ($classDefinition->hasMethod($methodName)) {
                ++$numberPoly;
                $method = $classDefinition->getMethod($methodName);
            }
        } else {
            $classTypes = $caller->getClassTypes();
            foreach ($classTypes as $classType) {
                if ($compiler->isClass($classType) || $compiler->isInterface($classType) || $compiler->isBundledClass($classType) || $compiler->isBundledInterface($classType)) {
                    if ($compiler->isInterface($classType)) {
                        continue;
                    }

                    if ($compiler->isClass($classType)) {
                        $classDefinition = $compiler->getClassDefinition($classType);
                    } else {
                        $classDefinition = $compiler->getInternalClassDefinition($classType);
                    }

                    if (!$classDefinition) {
                        continue;
                    }

                    if ($classDefinition->hasMethod($methodName) && !$classDefinition->isInterface()) {
                        ++$numberPoly;
                        $method = $classDefinition->getMethod($methodName);
                    }
                }
            }
        }

        if (!$numberPoly) {
            // Try to generate a cache based on the fact the variable is not modified within the loop block
            if ($compilationContext->insideCycle && !$caller->isTemporal()) {
                if (\count($compilationContext->cycleBlocks) && 'variable' == $caller->getType()) {
                    $currentBlock = $compilationContext->cycleBlocks[\count($compilationContext->cycleBlocks) - 1];

                    if (0 == $currentBlock->getMutateGatherer(true)->getNumberOfMutations($caller->getName())) {
                        $functionCache = $compilationContext->symbolTable->getTempVariableForWrite('zephir_fcall_cache_entry', $compilationContext);
                        $functionCache->setMustInitNull(true);
                        $functionCache->setReusable(false);

                        return '&'.$functionCache->getName().', 0';
                    }
                }
            }

            return 'NULL, 0';
        }

        if (!($method instanceof \ReflectionMethod)) {
            if ($method->getClassDefinition()->isExternal()) {
                return 'NULL, 0';
            }

            $completeName = $method->getClassDefinition()->getCompleteName();
            if (isset($this->cache[$completeName][$method->getName()])) {
                return $this->cache[$completeName][$method->getName()].', '.SlotsCache::getExistingMethodSlot($method);
            }

            $gatherer = $this->gatherer;
            if (\is_object($gatherer)) {
                $number = $gatherer->getNumberOfMethodCalls($method->getClassDefinition()->getCompleteName(), $method->getName());
            } else {
                $number = 0;
            }

            $staticCacheable = !$method->getClassDefinition()->isInterface() && ($compilationContext->currentMethod == $method || $method->getClassDefinition()->isFinal() || $method->isFinal() || $method->isPrivate());
            if ($number > 1 || $compilationContext->insideCycle) {
                $cacheable = true;
            } else {
                $cacheable = false;
            }
        } else {
            $staticCacheable = false;
            $cacheable = false;
        }

        // Recursive methods require warm-up
        if ($compilationContext->currentMethod == $method) {
            if (!$compilationContext->methodWarmUp) {
                $compilationContext->methodWarmUp = new MethodCallWarmUp();
            }
        }

        if ('this_ptr' != $caller->getName()) {
            $associatedClass = $caller->getAssociatedClass();
            if ($this->isClassCacheable($associatedClass)) {
                $staticCacheable = true;
            }
        }

        if ($staticCacheable) {
            $cacheSlot = SlotsCache::getMethodSlot($method);
        } else {
            $cacheSlot = '0';
        }

        if ($cacheable) {
            $functionCacheVar = $compilationContext->symbolTable->getTempVariableForWrite('zephir_fcall_cache_entry', $compilationContext);
            $functionCacheVar->setMustInitNull(true);
            $functionCacheVar->setReusable(false);
            $functionCache = '&'.$functionCacheVar->getName();
        } else {
            $functionCache = 'NULL';
        }

        if (!($method instanceof \ReflectionMethod)) {
            $this->cache[$completeName][$method->getName()] = $functionCache;
        }

        return $functionCache.', '.$cacheSlot;
    }
1053094
function preExecute( $functionName )
    {
        /* Code copied from this->execute() */
        $moduleName = $this->ModuleName;
        if ( !isset( $this->FunctionList[$functionName] ) )
        {
            eZDebug::writeError( "No such function '$functionName' in module '$moduleName'", __METHOD__ );
            return false;
        }
        $functionDefinition = $this->FunctionList[$functionName];
        if ( !isset( $functionDefinition['call_method'] ) )
        {
            eZDebug::writeError( "No call method defined for function '$functionName' in module '$moduleName'", __METHOD__ );
            return false;
        }
        if ( !isset( $functionDefinition['parameters'] ) )
        {
            eZDebug::writeError( "No parameters defined for function '$functionName' in module '$moduleName'", __METHOD__ );
            return false;
        }
        $callMethod = $functionDefinition['call_method'];
        if ( isset( $callMethod['class'] ) &&
             isset( $callMethod['method'] ) )
        {
            if ( !class_exists( $callMethod['class'] ) )
            {
                return false;
            }
            $classObject = $this->objectForClass( $callMethod['class'] );
            if ( $classObject === null )
            {
                return false;
            }
            if ( !method_exists( $classObject, $callMethod['method'] ) )
            {
                return false;
            }

            return $functionDefinition;
        }
        return false;
    }
1026258
public static function isBackgroundCall($functionName)
    {
        $matches = array();
        $pattern = '#' . static::BACKGROUND_COLOR_FUNCTION_NAME_REGEX . '#';

        if (!preg_match($pattern, $functionName, $matches)) {
            return false;
        }

        return $matches;
    }
701828
public function compile(CompilationContext $compilationContext)
    {
        $this->compiler = $compilationContext->compiler;

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

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

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

        $codePrinter->increaseLevel();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            $argInfo->render();
        }

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

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

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

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

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

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

        if (1 == \count($expression['parameters'])) {
            return new CompiledExpression('bool', 'false', $expression);
        }

        return false;
    }
1261243
public function preCompile(CompilationContext $compilationContext)
    {
        $this->compiler = $compilationContext->compiler;

        /*
         * Pre-Compile methods
         */
        foreach ($this->methods as $method) {
            if ('class' == $this->getType() && !$method->isAbstract()) {
                $method->preCompile($compilationContext);
            }
        }
    }
544167
public Function getFunction(String functionName) throws NoSuchFunctionException {
        if (!members.containsKey(functionName)) {
            throw new NoSuchFunctionException("Can not find function " + functionName + " in library " + name + " (" + prefix + ")");
        }

        return members.get(functionName);
    }
992875
public function optimize(array $expression, Call $call, CompilationContext $context)
    {
        if (!isset($expression['parameters']) || 1 != \count($expression['parameters'])) {
            throw new CompilerException(
                sprintf(
                    'func_get_arg() expects at exactly 1 parameter, %d given',
                    isset($expression['parameters']) ? \count($expression['parameters']) : 0
                ),
                $expression
            );
        }

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

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

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

        $symbol = $context->backend->getVariableCode($symbolVariable);

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

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

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

            if ($context->backend->isZE3()) {
                $template = 'zephir_get_arg(%s, zephir_get_intval(%s));';
            } else {
                $template = 'zephir_get_arg(%s, zephir_get_intval(%s) TSRMLS_CC);';
            }

            $context->codePrinter->output(sprintf($template, $symbol, $resolvedParams[0]));

            return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
        } catch (Exception $e) {
            throw new CompilerException($e->getMessage(), $expression, $e->getCode(), $e);
        }
    }
72610
public function optimize(array $expression, Call $call, CompilationContext $context)
    {
        if (!isset($expression['parameters'])) {
            return false;
        }

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

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

        if ($context->backend->isZE3()) {
            if ('IS_BOOL' == $this->getType()) {
                $condition = '(Z_TYPE_P('.$resolvedParams[0].') == IS_TRUE || Z_TYPE_P('.$resolvedParams[0].') == IS_FALSE)';
            } else {
                $condition = 'Z_TYPE_P('.$resolvedParams[0].') == '.$this->getType();
            }
        } else {
            $condition = 'Z_TYPE_P('.$resolvedParams[0].') == '.$this->getType();
        }

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