Zephir\Statements\ThrowStatement::compile PHP Метод

compile() публичный Метод

public compile ( Zephir\CompilationContext $compilationContext )
$compilationContext Zephir\CompilationContext
    public function compile(CompilationContext $compilationContext)
    {
        $compilationContext->headersManager->add('kernel/exception');
        $codePrinter = $compilationContext->codePrinter;
        $statement = $this->_statement;
        $expr = $statement['expr'];
        /**
         * This optimizes throw new Exception("hello")
         */
        if (!$compilationContext->insideTryCatch) {
            if (isset($expr['class']) && isset($expr['parameters']) && count($expr['parameters']) == 1 && $expr['parameters'][0]['parameter']['type'] == 'string') {
                $className = Utils::getFullName($expr['class'], $compilationContext->classDefinition->getNamespace(), $compilationContext->aliasManager);
                if ($compilationContext->compiler->isClass($className)) {
                    $classDefinition = $compilationContext->compiler->getClassDefinition($className);
                    $message = $expr['parameters'][0]['parameter']['value'];
                    $class = $classDefinition->getClassEntry($compilationContext);
                    $this->throwStringException($codePrinter, $class, $message, $statement['expr']);
                    return;
                } else {
                    if ($compilationContext->compiler->isBundledClass($className)) {
                        $classEntry = $compilationContext->classDefinition->getClassEntryByClassName($className, $compilationContext, true);
                        if ($classEntry) {
                            $message = $expr['parameters'][0]['parameter']['value'];
                            $this->throwStringException($codePrinter, $classEntry, $message, $statement['expr']);
                            return;
                        }
                    }
                }
            } else {
                if (in_array($expr['type'], array('string', 'char', 'int', 'double'))) {
                    $class = $compilationContext->classDefinition->getClassEntryByClassName('Exception', $compilationContext);
                    $this->throwStringException($codePrinter, $class, $expr['value'], $expr);
                    return;
                }
            }
        }
        $throwExpr = new Expression($expr);
        $resolvedExpr = $throwExpr->compile($compilationContext);
        if (!in_array($resolvedExpr->getType(), array('variable', 'string'))) {
            throw new CompilerException("Expression '" . $resolvedExpr->getType() . '" cannot be used as exception', $expr);
        }
        $variableVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $expr);
        if (!in_array($variableVariable->getType(), array('variable', 'string'))) {
            throw new CompilerException("Variable '" . $variableVariable->getType() . "' cannot be used as exception", $expr);
        }
        $variableCode = $compilationContext->backend->getVariableCode($variableVariable);
        $codePrinter->output('zephir_throw_exception_debug(' . $variableCode . ', "' . Compiler::getShortUserPath($statement['expr']['file']) . '", ' . $statement['expr']['line'] . ' TSRMLS_CC);');
        if (!$compilationContext->insideTryCatch) {
            $codePrinter->output('ZEPHIR_MM_RESTORE();');
            $codePrinter->output('return;');
        } else {
            $codePrinter->output('goto try_end_' . $compilationContext->currentTryCatch . ';');
            $codePrinter->outputBlankLine();
        }
        if ($variableVariable->isTemporal()) {
            $variableVariable->setIdle(true);
        }
    }

Usage Example

Пример #1
0
 /**
  * @param CompilationContext $compilationContext
  * @param boolean $unreachable
  * @param int $branchType
  * @return Branch
  */
 public function compile(CompilationContext $compilationContext, $unreachable = false, $branchType = Branch::TYPE_UNKNOWN)
 {
     $compilationContext->codePrinter->increaseLevel();
     $compilationContext->currentBranch++;
     /**
      * Create a new branch
      */
     $currentBranch = new Branch();
     $currentBranch->setType($branchType);
     $currentBranch->setUnreachable($unreachable);
     /**
      * Activate branch in the branch manager
      */
     $compilationContext->branchManager->addBranch($currentBranch);
     $this->_unreachable = $unreachable;
     $statements = $this->_statements;
     foreach ($statements as $statement) {
         /**
          * Generate GDB hints
          */
         if ($this->_debug) {
             if (isset($statement['file'])) {
                 if ($statement['type'] != 'declare' && $statement['type'] != 'comment') {
                     $compilationContext->codePrinter->outputNoIndent('#line ' . $statement['line'] . ' "' . $statement['file'] . '"');
                 }
             }
         }
         /**
          * Show warnings if code is generated when the 'unreachable state' is 'on'
          */
         if ($this->_unreachable === true) {
             switch ($statement['type']) {
                 case 'echo':
                     $compilationContext->logger->warning('Unreachable code', "unreachable-code", $statement['expressions'][0]);
                     break;
                 case 'let':
                     $compilationContext->logger->warning('Unreachable code', "unreachable-code", $statement['assignments'][0]);
                     break;
                 case 'fetch':
                 case 'fcall':
                 case 'mcall':
                 case 'scall':
                 case 'if':
                 case 'while':
                 case 'do-while':
                 case 'switch':
                 case 'for':
                 case 'return':
                 case 'c-block':
                     if (isset($statement['expr'])) {
                         $compilationContext->logger->warning('Unreachable code', "unreachable-code", $statement['expr']);
                     } else {
                         $compilationContext->logger->warning('Unreachable code', "unreachable-code", $statement);
                     }
                     break;
                 default:
                     $compilationContext->logger->warning('Unreachable code', "unreachable-code", $statement);
             }
         }
         switch ($statement['type']) {
             case 'let':
                 $letStatement = new LetStatement($statement);
                 $letStatement->compile($compilationContext);
                 break;
             case 'echo':
                 $echoStatement = new EchoStatement($statement);
                 $echoStatement->compile($compilationContext);
                 break;
             case 'declare':
                 $declareStatement = new DeclareStatement($statement);
                 $declareStatement->compile($compilationContext);
                 break;
             case 'if':
                 $ifStatement = new IfStatement($statement);
                 $ifStatement->compile($compilationContext);
                 break;
             case 'while':
                 $whileStatement = new WhileStatement($statement);
                 $whileStatement->compile($compilationContext);
                 break;
             case 'do-while':
                 $doWhileStatement = new DoWhileStatement($statement);
                 $doWhileStatement->compile($compilationContext);
                 break;
             case 'switch':
                 $switchStatement = new SwitchStatement($statement);
                 $switchStatement->compile($compilationContext);
                 break;
             case 'for':
                 $forStatement = new ForStatement($statement);
                 $forStatement->compile($compilationContext);
                 break;
             case 'return':
                 $returnStatement = new ReturnStatement($statement);
                 $returnStatement->compile($compilationContext);
                 $this->_unreachable = true;
                 break;
             case 'require':
                 $requireStatement = new RequireStatement($statement);
                 $requireStatement->compile($compilationContext);
                 break;
             case 'loop':
                 $loopStatement = new LoopStatement($statement);
                 $loopStatement->compile($compilationContext);
                 break;
             case 'break':
                 $breakStatement = new BreakStatement($statement);
                 $breakStatement->compile($compilationContext);
                 $this->_unreachable = true;
                 break;
             case 'continue':
                 $continueStatement = new ContinueStatement($statement);
                 $continueStatement->compile($compilationContext);
                 $this->_unreachable = true;
                 break;
             case 'unset':
                 $unsetStatement = new UnsetStatement($statement);
                 $unsetStatement->compile($compilationContext);
                 break;
             case 'throw':
                 $throwStatement = new ThrowStatement($statement);
                 $throwStatement->compile($compilationContext);
                 $this->_unreachable = true;
                 break;
             case 'try-catch':
                 $throwStatement = new TryCatchStatement($statement);
                 $throwStatement->compile($compilationContext);
                 $this->_unreachable = false;
                 break;
             case 'fetch':
                 $expr = new Expression($statement['expr']);
                 $expr->setExpectReturn(false);
                 $compiledExpression = $expr->compile($compilationContext);
                 $compilationContext->codePrinter->output($compiledExpression->getCode() . ';');
                 break;
             case 'mcall':
                 $methodCall = new MethodCall();
                 $expr = new Expression($statement['expr']);
                 $expr->setExpectReturn(false);
                 $methodCall->compile($expr, $compilationContext);
                 break;
             case 'fcall':
                 $functionCall = new FunctionCall();
                 $expr = new Expression($statement['expr']);
                 $expr->setExpectReturn(false);
                 $compiledExpression = $functionCall->compile($expr, $compilationContext);
                 switch ($compiledExpression->getType()) {
                     case 'int':
                     case 'double':
                     case 'uint':
                     case 'long':
                     case 'ulong':
                     case 'char':
                     case 'uchar':
                     case 'bool':
                         $compilationContext->codePrinter->output($compiledExpression->getCode() . ';');
                         break;
                 }
                 break;
             case 'scall':
                 $methodCall = new StaticCall();
                 $expr = new Expression($statement['expr']);
                 $expr->setExpectReturn(false);
                 $methodCall->compile($expr, $compilationContext);
                 break;
             case 'cblock':
                 $compilationContext->codePrinter->output($statement['value']);
                 break;
             case 'empty':
                 break;
             default:
                 throw new Exception('Unsupported statement: ' . $statement['type']);
         }
         if ($statement['type'] != 'comment') {
             $this->_lastStatement = $statement;
         }
     }
     /**
      * Traverses temporal variables created in a specific branch
      * marking them as idle
      */
     $compilationContext->symbolTable->markTemporalVariablesIdle($compilationContext);
     $compilationContext->branchManager->removeBranch($currentBranch);
     $compilationContext->currentBranch--;
     $compilationContext->codePrinter->decreaseLevel();
     return $currentBranch;
 }