Zephir\CompilerFile::preCompile PHP Méthode

preCompile() public méthode

Pre-compiles a Zephir file. Generates the IR and perform basic validations
public preCompile ( Compiler $compiler )
$compiler Compiler
    public function preCompile(Compiler $compiler)
    {
        $ir = $this->genIR($compiler);
        if (!is_array($ir)) {
            throw new Exception("Cannot parse file: " . realpath($this->_filePath));
        }
        if (isset($ir['type']) && $ir['type'] == 'error') {
            throw new ParseException($ir['message'], $ir);
        }
        /**
         * Compilation context stores common objects required by compilation entities
         */
        $compilationContext = new CompilationContext();
        /**
         * Set global compiler in the compilation context
         */
        $compilationContext->compiler = $compiler;
        /**
         * Set global config in the compilation context
         */
        $compilationContext->config = $this->_config;
        /**
         * Set global logger in the compilation context
         */
        $compilationContext->logger = $this->_logger;
        /**
         * Alias manager
         */
        $compilationContext->aliasManager = $this->_aliasManager;
        $compilationContext->backend = $compiler->backend;
        /**
         * Traverse the top level statements looking for the namespace
         */
        $namespace = null;
        foreach ($ir as $topStatement) {
            switch ($topStatement['type']) {
                case 'namespace':
                    if ($namespace !== null) {
                        throw new CompilerException("The namespace must be defined just one time", $topStatement);
                    }
                    $namespace = $topStatement['name'];
                    $this->_namespace = $namespace;
                    if (!preg_match('/^[A-Z]/', $namespace)) {
                        throw new CompilerException("Namespace '" . $namespace . "' must be in camelized-form", $topStatement);
                    }
                    break;
                case 'cblock':
                    $this->_headerCBlocks[] = $topStatement['value'];
                    break;
                case 'function':
                    /* Just do the precompilation of the function */
                    $functionDefinition = new FunctionDefinition($namespace, $topStatement['name'], isset($topStatement['parameters']) ? new ClassMethodParameters($topStatement['parameters']) : null, isset($topStatement['statements']) ? new StatementsBlock($topStatement['statements']) : null, isset($topStatement['return-type']) ? $topStatement['return-type'] : null, $topStatement);
                    $functionDefinition->preCompile($compilationContext);
                    $this->addFunction($compiler, $functionDefinition, $topStatement);
                    break;
            }
        }
        if (!$namespace) {
            throw new CompilerException("A namespace is required", $topStatement);
        }
        /* Set namespace and flag as global, if before namespace declaration */
        foreach ($this->_functionDefinitions as $funcDef) {
            if ($funcDef->getNamespace() == null) {
                $funcDef->setGlobal(true);
                $funcDef->setNamespace($compiler->getConfig()->get('namespace'));
            }
        }
        $class = false;
        $interface = false;
        $lastComment = null;
        foreach ($ir as $topStatement) {
            switch ($topStatement['type']) {
                case 'class':
                    if ($class || $interface) {
                        throw new CompilerException("More than one class/interface defined in the same file", $topStatement);
                    }
                    $class = true;
                    $name = $topStatement['name'];
                    $this->preCompileClass($compilationContext, $namespace, $topStatement, $lastComment);
                    $this->_originalNode = $topStatement;
                    $lastComment = null;
                    break;
                case 'interface':
                    if ($class || $interface) {
                        throw new CompilerException("More than one class/interface defined in the same file", $topStatement);
                    }
                    $interface = true;
                    $name = $topStatement['name'];
                    $this->preCompileInterface($namespace, $topStatement, $lastComment);
                    $this->_originalNode = $topStatement;
                    $lastComment = null;
                    break;
                case 'use':
                    if ($interface || $class) {
                        throw new CompilerException("Aliasing must be done before declaring any class or interface", $topStatement);
                    }
                    $this->_aliasManager->add($topStatement);
                    break;
                case 'comment':
                    $lastComment = $topStatement;
                    break;
            }
        }
        if (!$class && !$interface) {
            throw new CompilerException("Every file must contain at least a class or an interface", $topStatement);
        }
        if (!$this->_external) {
            $expectedPath = strtolower(str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR . $name) . '.zep';
            if (strtolower($this->_filePath) != $expectedPath) {
                $className = str_replace('\\', '/', $namespace) . '\\' . $name;
                $message = 'Unexpected class name ' . $className . ' in file: ' . $this->_filePath . ', expected: ' . $expectedPath;
                throw new CompilerException($message);
            }
        }
        if ($compilationContext->classDefinition) {
            if ($extendsClass = $compilationContext->classDefinition->getExtendsClass()) {
                $compiler->isClass($extendsClass);
            }
            if ($interfaces = $compilationContext->classDefinition->getImplementedInterfaces()) {
                foreach ($interfaces as $interface) {
                    $compiler->isInterface($interface);
                }
            }
        }
        $this->_ir = $ir;
    }