Zephir\Optimizers\EvalExpression::optimize PHP Method

optimize() public method

Optimizes expressions
public optimize ( $exprRaw, Zephir\CompilationContext $compilationContext ) : boolean | string
$exprRaw
$compilationContext Zephir\CompilationContext
return boolean | string
    public function optimize($exprRaw, CompilationContext $compilationContext)
    {
        $conditions = $this->optimizeNot($exprRaw, $compilationContext);
        if ($conditions !== false) {
            return $conditions;
        }
        /**
         * Discard first level parentheses
         */
        if ($exprRaw['type'] == 'list') {
            $expr = new Expression($exprRaw['left']);
        } else {
            $expr = new Expression($exprRaw);
        }
        $expr->setReadOnly(true);
        $expr->setEvalMode(true);
        $compiledExpression = $expr->compile($compilationContext);
        /**
         * Possible corrupted expression?
         */
        if (!is_object($compiledExpression)) {
            throw new CompilerException('Corrupted expression: ' . $exprRaw['type'], $exprRaw);
        }
        /**
         * Generate the condition according to the value returned by the evaluated expression
         */
        switch ($compiledExpression->getType()) {
            case 'null':
                $this->_unreachable = true;
                return '0';
            case 'int':
            case 'uint':
            case 'long':
            case 'ulong':
            case 'double':
                $code = $compiledExpression->getCode();
                if (is_numeric($code)) {
                    if ($code == '1') {
                        $this->_unreachableElse = true;
                    } else {
                        $this->_unreachable = true;
                    }
                }
                return $code;
            case 'char':
            case 'uchar':
                return $compiledExpression->getCode();
            case 'bool':
                $code = $compiledExpression->getBooleanCode();
                if ($code == '1') {
                    $this->_unreachableElse = true;
                } else {
                    if ($code == '0') {
                        $this->_unreachable = true;
                    }
                }
                return $code;
            case 'variable':
                $variableRight = $compilationContext->symbolTable->getVariableForRead($compiledExpression->getCode(), $compilationContext, $exprRaw);
                $possibleValue = $variableRight->getPossibleValue();
                if (is_object($possibleValue)) {
                    $possibleValueBranch = $variableRight->getPossibleValueBranch();
                    if ($possibleValueBranch instanceof Branch) {
                        /**
                         * Check if the possible value was assigned in the root branch
                         */
                        if ($possibleValueBranch->getType() == Branch::TYPE_ROOT) {
                            if ($possibleValue instanceof LiteralCompiledExpression) {
                                switch ($possibleValue->getType()) {
                                    case 'null':
                                        $this->_unreachable = true;
                                        break;
                                    case 'bool':
                                        if ($possibleValue->getBooleanCode() == '0') {
                                            $this->_unreachable = true;
                                        } else {
                                            $this->_unreachableElse = true;
                                        }
                                        break;
                                    case 'int':
                                        if (!intval($possibleValue->getCode())) {
                                            $this->_unreachable = true;
                                        } else {
                                            $this->_unreachableElse = true;
                                        }
                                        break;
                                    case 'double':
                                        if (!floatval($possibleValue->getCode())) {
                                            $this->_unreachable = true;
                                        } else {
                                            $this->_unreachableElse = true;
                                        }
                                        break;
                                    default:
                                        //echo $possibleValue->getType();
                                }
                            }
                        }
                    }
                }
                $this->_usedVariables[] = $variableRight->getName();
                /**
                 * Evaluate the variable
                 */
                switch ($variableRight->getType()) {
                    case 'int':
                    case 'uint':
                    case 'char':
                    case 'uchar':
                    case 'long':
                    case 'ulong':
                        return $variableRight->getName();
                    case 'string':
                        $variableRightCode = $compilationContext->backend->getVariableCode($variableRight);
                        return '!(' . $compilationContext->backend->ifVariableValueUndefined($variableRight, $compilationContext, true, false) . ') && Z_STRLEN_P(' . $variableRightCode . ')';
                    case 'bool':
                        return $variableRight->getName();
                    case 'double':
                        return $variableRight->getName();
                    case 'variable':
                        $compilationContext->headersManager->add('kernel/operators');
                        $variableRightCode = $compilationContext->backend->getVariableCode($variableRight);
                        return 'zephir_is_true(' . $variableRightCode . ')';
                    default:
                        throw new CompilerException("Variable can't be evaluated " . $variableRight->getType(), $exprRaw);
                }
                break;
            default:
                throw new CompilerException("Expression " . $compiledExpression->getType() . " can't be evaluated", $exprRaw);
        }
    }

Usage Example

Example #1
0
 /**
  * @param CompilationContext $compilationContext
  */
 public function compile(CompilationContext $compilationContext)
 {
     $exprRaw = $this->_statement['expr'];
     $codePrinter = $compilationContext->codePrinter;
     $codePrinter->output('do {');
     /**
      * Variables are initialized in a different way inside cycle
      */
     $compilationContext->insideCycle++;
     /**
      * Compile statements in the 'while' block
      */
     if (isset($this->_statement['statements'])) {
         $st = new StatementsBlock($this->_statement['statements']);
         $st->compile($compilationContext);
     }
     $compilationContext->codePrinter->increaseLevel();
     $expr = new EvalExpression();
     $condition = $expr->optimize($exprRaw, $compilationContext);
     $compilationContext->codePrinter->decreaseLevel();
     /**
      * Restore the cycle counter
      */
     $compilationContext->insideCycle--;
     /**
      * Compound conditions can be evaluated in a single line of the C-code
      */
     $codePrinter->output('} while (' . $condition . ');');
 }
All Usage Examples Of Zephir\Optimizers\EvalExpression::optimize