Zephir\Operators\Logical\LogicalBaseOperator::compile PHP Method

compile() public method

public compile ( $expression, Zephir\CompilationContext $compilationContext )
$compilationContext Zephir\CompilationContext
    public function compile($expression, CompilationContext $compilationContext)
    {
        if (!isset($expression['left'])) {
            throw new CompilerException("Missing left part of the expression", $expression);
        }
        if (!isset($expression['right'])) {
            throw new CompilerException("Missing right part of the expression", $expression);
        }
        $leftExpr = new Expression($expression['left']);
        $leftExpr->setReadOnly($this->_readOnly);
        $left = $leftExpr->compile($compilationContext);
        $rightExpr = new Expression($expression['right']);
        $rightExpr->setReadOnly($this->_readOnly);
        $right = $rightExpr->compile($compilationContext);
        switch ($left->getType()) {
            case 'int':
                switch ($right->getType()) {
                    case 'int':
                        return new CompiledExpression('int', '(' . $left->getCode() . ' ' . $this->_operator . ' ' . $right->getCode() . ')', $expression);
                    case 'double':
                        return new CompiledExpression('double', '((double) ' . $left->getCode() . ' ' . $this->_operator . ' ' . $right->getCode() . ')', $expression);
                    case 'bool':
                        return new CompiledExpression('int', '(' . $left->getCode() . ' ' . $this->_operator . ' ' . $right->getBooleanCode() . ')', $expression);
                    case 'variable':
                        $variableRight = $compilationContext->symbolTable->getVariableForRead($right->getCode(), $compilationContext, $expression);
                        switch ($variableRight->getType()) {
                            case 'int':
                                return new CompiledExpression('bool', '(' . $left->getCode() . ' ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
                            case 'bool':
                                return new CompiledExpression('bool', '(' . $left->getCode() . ' ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
                            case 'double':
                                return new CompiledExpression('bool', '(' . $left->getCode() . ' ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
                            case 'variable':
                                $compilationContext->headersManager->add('kernel/operators');
                                $variableCode = $compilationContext->backend->getVariableCode($variableRight);
                                return new CompiledExpression('bool', '(' . $left->getCode() . ' ' . $this->_operator . ' zephir_is_true(' . $variableCode . '))', $expression);
                            default:
                                throw new CompilerException("Cannot compare variable('int') with variable('" . $variableRight->getType() . "')", $expression);
                        }
                        break;
                    default:
                        throw new CompilerException("Cannot compare 'int' with '" . $right->getType() . "'", $expression);
                }
                break;
            case 'bool':
                switch ($right->getType()) {
                    case 'int':
                    case 'double':
                        return new CompiledExpression('bool', '(' . $left->getBooleanCode() . ' ' . $this->_bitOperator . ' ((' . $right->getCode() . ') ? 1 : 0))', $expression);
                    case 'bool':
                        return new CompiledExpression('bool', '(' . $left->getBooleanCode() . ' ' . $this->_bitOperator . ' ' . $right->getBooleanCode() . ')', $expression);
                    case 'variable':
                        $variableRight = $compilationContext->symbolTable->getVariableForRead($right->getCode(), $compilationContext, $expression);
                        switch ($variableRight->getType()) {
                            case 'int':
                                return new CompiledExpression('bool', '(' . $left->getBooleanCode() . ' ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
                            case 'bool':
                                return new CompiledExpression('bool', '(' . $left->getBooleanCode() . ' ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
                            case 'double':
                                return new CompiledExpression('bool', '(' . $left->getBooleanCode() . ' ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
                            case 'variable':
                                $variableCode = $compilationContext->backend->getVariableCode($variableRight);
                                $compilationContext->headersManager->add('kernel/operators');
                                return new CompiledExpression('bool', '(' . $left->getBooleanCode() . ' ' . $this->_operator . ' zephir_is_true(' . $variableCode . '))', $expression);
                            default:
                                throw new CompilerException("Cannot add variable('int') with variable('" . $variableRight->getType() . "')", $expression);
                        }
                        break;
                    default:
                        throw new CompilerException("Cannot compare 'bool' with '" . $right->getType() . "'", $expression);
                }
                break;
            case 'double':
                switch ($right->getType()) {
                    case 'int':
                        return new CompiledExpression('bool', '(' . $left->getCode() . ' ' . $this->_operator . ' ' . $right->getCode() . ')', $expression);
                    case 'double':
                        return new CompiledExpression('bool', '(' . $left->getCode() . ' ' . $this->_operator . ' ' . $right->getCode() . ')', $expression);
                    case 'bool':
                        return new CompiledExpression('bool', '(' . $left->getCode() . ' ' . $this->_operator . ' ' . $right->getBooleanCode() . ')', $expression);
                    default:
                        throw new CompilerException("Cannot compare 'double' with '" . $right->getType() . "'", $expression);
                }
                break;
            case 'string':
                switch ($right->getType()) {
                    default:
                        throw new CompilerException("Operation is not supported between strings", $expression);
                }
                break;
            case 'variable':
                $variableLeft = $compilationContext->symbolTable->getVariableForRead($left->resolve(null, $compilationContext), $compilationContext, $expression);
                switch ($variableLeft->getType()) {
                    case 'int':
                        switch ($right->getType()) {
                            case 'int':
                                return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' ' . $this->_operator . ' ' . $right->getCode() . ')', $expression);
                            case 'variable':
                                $variableRight = $compilationContext->symbolTable->getVariableForRead($right->getCode(), $compilationContext, $expression['right']);
                                switch ($variableRight->getType()) {
                                    case 'int':
                                        return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
                                    case 'bool':
                                        return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
                                    case 'double':
                                        return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
                                    case 'variable':
                                        $compilationContext->headersManager->add('kernel/operators');
                                        $variableCode = $compilationContext->backend->getVariableCode($variableRight);
                                        return new CompiledExpression('int', '(' . $variableLeft->getName() . ' ' . $this->_operator . ' zephir_is_true(' . $variableCode . '))', $expression);
                                    default:
                                        throw new CompilerException("Cannot compare variable('int') with variable('" . $variableRight->getType() . "')", $expression);
                                }
                                break;
                            default:
                                throw new CompilerException("Cannot compare variable('int') with '" . $right->getType() . "'", $expression);
                        }
                        break;
                    case 'bool':
                        switch ($right->getType()) {
                            case 'int':
                                return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' ' . $this->_operator . ' ' . $right->getCode() . ')', $expression);
                            case 'bool':
                                return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' ' . $this->_bitOperator . ' ' . $right->getBooleanCode() . ')', $expression);
                            case 'variable':
                                $variableRight = $compilationContext->symbolTable->getVariableForRead($right->getCode(), $compilationContext, $expression['right']);
                                switch ($variableRight->getType()) {
                                    case 'int':
                                        return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
                                    case 'bool':
                                        return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' ' . $this->_bitOperator . ' ' . $variableRight->getName() . ')', $expression);
                                    case 'variable':
                                        $compilationContext->headersManager->add('kernel/operators');
                                        $variableCode = $compilationContext->backend->getVariableCode($variableRight);
                                        return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' ' . $this->_operator . ' zephir_is_true(' . $variableCode . '))', $expression);
                                    default:
                                        throw new CompilerException("Cannot compare variable('int') with variable('" . $variableRight->getType() . "')", $expression);
                                }
                                break;
                            default:
                                throw new CompilerException("Cannot compare variable('int') with '" . $right->getType() . "'", $expression);
                        }
                        break;
                    case 'double':
                        switch ($right->getType()) {
                            case 'int':
                                return new CompiledExpression('bool', $variableLeft->getName() . ' ' . $this->_operator . ' ' . $right->getCode(), $expression);
                            case 'double':
                                return new CompiledExpression('bool', $variableLeft->getName() . ' ' . $this->_operator . ' ' . $right->getCode(), $expression);
                            case 'bool':
                                return new CompiledExpression('bool', $variableLeft->getName() . ' ' . $this->_bitOperator . '' . $right->getBooleanCode(), $expression);
                            case 'variable':
                                $variableRight = $compilationContext->symbolTable->getVariableForRead($right->getCode(), $compilationContext, $expression['right']);
                                switch ($variableRight->getType()) {
                                    case 'int':
                                        return new CompiledExpression('bool', $variableLeft->getName() . ' ' . $this->_operator . '  (double) ' . $variableRight->getName(), $expression);
                                    case 'double':
                                        return new CompiledExpression('bool', $variableLeft->getName() . ' ' . $this->_operator . '  ' . $variableRight->getName(), $expression);
                                    case 'bool':
                                        return new CompiledExpression('bool', $variableLeft->getName() . ' ' . $this->_bitOperator . '' . $variableRight->getName(), $expression);
                                    case 'variable':
                                        $compilationContext->headersManager->add('kernel/operators');
                                        $variableCode = $compilationContext->backend->getVariableCode($variableRight);
                                        return new CompiledExpression('bool', $variableLeft->getName() . ' ' . $this->_operator . ' zephir_is_true(' . $variableCode . ')', $expression);
                                    default:
                                        throw new CompilerException("Cannot compare variable('double') with variable('" . $variableRight->getType() . "')", $expression);
                                }
                                break;
                            default:
                                throw new CompilerException("Cannot compare variable('int') with '" . $right->getType() . "'", $expression);
                        }
                        break;
                    case 'string':
                        switch ($right->getType()) {
                            case 'int':
                                return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' && Z_STRLEN_P(' . $variableLeft->getName() . ')) ' . $this->_operator . ' ' . $right->getCode(), $expression);
                            case 'double':
                                return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' && Z_STRLEN_P(' . $variableLeft->getName() . ')) ' . $this->_operator . ' ' . $right->getCode(), $expression);
                            case 'bool':
                                return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' && Z_STRLEN_P(' . $variableLeft->getName() . ')) ' . $this->_bitOperator . '' . $right->getBooleanCode(), $expression);
                            case 'variable':
                                $variableRight = $compilationContext->symbolTable->getVariableForRead($right->getCode(), $compilationContext, $expression['right']);
                                switch ($variableRight->getType()) {
                                    case 'int':
                                        return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' && Z_STRLEN_P(' . $variableLeft->getName() . ')) ' . $this->_operator . ' ' . $variableRight->getName(), $expression);
                                    case 'double':
                                        return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' && Z_STRLEN_P(' . $variableLeft->getName() . ')) ' . $this->_operator . '  ' . $variableRight->getName(), $expression);
                                    case 'string':
                                        return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' && Z_STRLEN_P(' . $variableLeft->getName() . ')) ' . $this->_operator . ' (' . $variableRight->getName() . ' && Z_STRLEN_P(' . $variableRight->getName() . '))', $expression);
                                    case 'bool':
                                        return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' && Z_STRLEN_P(' . $variableLeft->getName() . ')) ' . $this->_bitOperator . ' ' . $variableRight->getName(), $expression);
                                    case 'variable':
                                        $compilationContext->headersManager->add('kernel/operators');
                                        $variableCode = $compilationContext->backend->getVariableCode($variableRight);
                                        return new CompiledExpression('bool', '(' . $variableLeft->getName() . ' && Z_STRLEN_P(' . $variableLeft->getName() . ')) ' . ' ' . $this->_operator . ' zephir_is_true(' . $variableCode . ')', $expression);
                                    default:
                                        throw new CompilerException("Cannot compare variable('double') with variable('" . $variableRight->getType() . "')", $expression);
                                }
                                break;
                            default:
                                throw new CompilerException("Cannot compare variable('int') with '" . $right->getType() . "'", $expression);
                        }
                        break;
                    case 'variable':
                        $variableLeftCode = $compilationContext->backend->getVariableCode($variableLeft);
                        switch ($right->getType()) {
                            /* a && 1 */
                            case 'int':
                            case 'double':
                                $compilationContext->headersManager->add('kernel/operators');
                                $op = $this->_operator;
                                $op1 = $variableLeftCode;
                                $op2 = $right->getCode();
                                $compilationContext->headersManager->add('kernel/operators');
                                return new CompiledExpression('bool', 'zephir_is_true(' . $op1 . ') ' . $op . ' ' . $op2, $expression);
                                /* a && 1 */
                            /* a && 1 */
                            case 'bool':
                                $compilationContext->headersManager->add('kernel/operators');
                                $op = $this->_operator;
                                $op1 = $variableLeftCode;
                                $op2 = $right->getCode();
                                $compilationContext->headersManager->add('kernel/operators');
                                return new CompiledExpression('bool', 'zephir_is_true(' . $op1 . ') ' . $op . ' ' . $op2, $expression);
                                /* a(var) && a(x) */
                            /* a(var) && a(x) */
                            case 'variable':
                                $variableRight = $compilationContext->symbolTable->getVariableForRead($right->resolve(null, $compilationContext), $compilationContext, $expression);
                                $variableRightCode = $compilationContext->backend->getVariableCode($variableRight);
                                switch ($variableRight->getType()) {
                                    /* a(var) && a(int) */
                                    case 'int':
                                        $compilationContext->headersManager->add('kernel/operators');
                                        return new CompiledExpression('bool', 'zephir_is_true(' . $variableLeftCode . ') ' . $this->_operator . ' ' . $variableRightCode, $expression);
                                        /* a(var) && a(bool) */
                                    /* a(var) && a(bool) */
                                    case 'bool':
                                        $compilationContext->headersManager->add('kernel/operators');
                                        return new CompiledExpression('bool', 'zephir_is_true(' . $variableLeftCode . ') ' . $this->_operator . ' ' . $variableRightCode, $expression);
                                        /* a(var) && a(var) */
                                    /* a(var) && a(var) */
                                    case 'variable':
                                        $compilationContext->headersManager->add('kernel/operators');
                                        $op1 = $variableLeftCode;
                                        $op2 = $variableRightCode;
                                        $expected = $this->getExpected($compilationContext, $expression);
                                        if ($expected->isLocalOnly()) {
                                            $compilationContext->codePrinter->output('add_function(&' . $expected->getName() . ', ' . $op1 . ', ' . $op2 . ' TSRMLS_CC);');
                                        } else {
                                            $compilationContext->codePrinter->output('add_function(' . $expected->getName() . ', ' . $op1 . ', ' . $op2 . ' TSRMLS_CC);');
                                        }
                                        return new CompiledExpression('variable', $expected->getName(), $expression);
                                    default:
                                        throw new CompilerException("Cannot compare 'variable' with variable ('" . $variableRight->getType() . "')", $expression);
                                }
                                break;
                            default:
                                throw new CompilerException("Cannot compare 'variable' with '" . $right->getType() . "'", $expression);
                        }
                        break;
                    default:
                        throw new CompilerException("Unknown '" . $variableLeft->getType() . "'", $expression);
                }
                break;
            default:
                throw new CompilerException("Unsupported type: " . $left->getType(), $expression);
        }
    }
LogicalBaseOperator