Zephir\Statements\Let\Variable::doVariableAssignment PHP Method

doVariableAssignment() private method

private doVariableAssignment ( $codePrinter, $resolvedExpr, $symbolVariable, $variable, $statement, $compilationContext, $readDetector )
    private function doVariableAssignment($codePrinter, $resolvedExpr, $symbolVariable, $variable, $statement, $compilationContext, $readDetector)
    {
        switch ($resolvedExpr->getType()) {
            case 'null':
                switch ($statement['operator']) {
                    case 'assign':
                        $symbolVariable->initVariant($compilationContext);
                        $symbolVariable->setDynamicTypes('null');
                        $compilationContext->backend->assignNull($symbolVariable, $compilationContext);
                        break;
                }
                break;
            case 'int':
            case 'uint':
            case 'long':
            case 'ulong':
                $symbol = $compilationContext->backend->getVariableCode($symbolVariable);
                switch ($statement['operator']) {
                    case 'mul-assign':
                    case 'sub-assign':
                    case 'add-assign':
                        switch ($statement['operator']) {
                            case 'mul-assign':
                                $functionName = 'ZEPHIR_MUL_ASSIGN';
                                break;
                            case 'sub-assign':
                                $functionName = 'ZEPHIR_SUB_ASSIGN';
                                break;
                            case 'add-assign':
                                $functionName = 'ZEPHIR_ADD_ASSIGN';
                                break;
                        }
                        $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                        $compilationContext->backend->assignLong($tempVariable, $resolvedExpr->getCode(), $compilationContext);
                        $compilationContext->symbolTable->mustGrownStack(true);
                        $compilationContext->headersManager->add('kernel/operators');
                        $codePrinter->output($functionName . '(' . $symbol . ', ' . $compilationContext->backend->getVariableCode($tempVariable) . ');');
                        break;
                    case 'assign':
                        $symbolVariable->setDynamicTypes('long');
                        if ($readDetector->detect($variable, $resolvedExpr->getOriginal())) {
                            $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('int', $compilationContext);
                            $codePrinter->output($tempVariable->getName() . ' = ' . $resolvedExpr->getCode() . ';');
                            $symbolVariable->initVariant($compilationContext);
                            $compilationContext->backend->assignLong($symbolVariable, $tempVariable, $compilationContext);
                        } else {
                            $symbolVariable->initVariant($compilationContext);
                            $compilationContext->backend->assignLong($symbolVariable, $resolvedExpr->getCode(), $compilationContext);
                        }
                        break;
                    case 'div-assign':
                        $symbolVariable->setDynamicTypes('double');
                        if ($readDetector->detect($variable, $resolvedExpr->getOriginal())) {
                            $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('double', $compilationContext);
                            $codePrinter->output($tempVariable->getName() . ' = ' . $resolvedExpr->getCode() . ';');
                            $symbolVariable->initVariant($compilationContext);
                            $compilationContext->backend->assignDouble($symbolVariable, $tempVariable, $compilationContext);
                        } else {
                            $symbolVariable->initVariant($compilationContext);
                            $compilationContext->backend->assignDouble($symbolVariable, $resolvedExpr->getCode(), $compilationContext);
                        }
                        break;
                    default:
                        throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                }
                break;
            case 'char':
            case 'uchar':
                switch ($statement['operator']) {
                    case 'assign':
                        $symbolVariable->setDynamicTypes('long');
                        if ($readDetector->detect($variable, $resolvedExpr->getOriginal())) {
                            $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('char', $compilationContext);
                            $codePrinter->output($tempVariable->getName() . ' = ' . $resolvedExpr->getCode() . ';');
                            $symbolVariable->initVariant($compilationContext);
                            $compilationContext->backend->assignLong($symbolVariable, $tempVariable, $compilationContext);
                        } else {
                            $symbolVariable->initVariant($compilationContext);
                            $compilationContext->backend->assignLong($symbolVariable, '\'' . $resolvedExpr->getCode() . '\'', $compilationContext);
                        }
                        break;
                    default:
                        throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                }
                break;
            case 'double':
                switch ($statement['operator']) {
                    case 'mul-assign':
                    case 'sub-assign':
                    case 'add-assign':
                        switch ($statement['operator']) {
                            case 'mul-assign':
                                $functionName = 'ZEPHIR_MUL_ASSIGN';
                                break;
                            case 'sub-assign':
                                $functionName = 'ZEPHIR_SUB_ASSIGN';
                                break;
                            case 'add-assign':
                                $functionName = 'ZEPHIR_ADD_ASSIGN';
                                break;
                        }
                        $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                        $tempVariable->setDynamicTypes('double');
                        $compilationContext->backend->assignDouble($tempVariable, $resolvedExpr->getCode(), $compilationContext);
                        $compilationContext->symbolTable->mustGrownStack(true);
                        $compilationContext->headersManager->add('kernel/operators');
                        $codePrinter->output($functionName . '(' . $compilationContext->backend->getVariableCode($symbolVariable) . ', ' . $compilationContext->backend->getVariableCode($tempVariable) . ');');
                        break;
                    case 'assign':
                        $symbolVariable->setDynamicTypes('double');
                        if ($readDetector->detect($variable, $resolvedExpr->getOriginal())) {
                            $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('double', $compilationContext);
                            $codePrinter->output($tempVariable->getName() . ' = ' . $resolvedExpr->getCode() . ';');
                            $symbolVariable->initVariant($compilationContext);
                            $compilationContext->backend->assignDouble($symbolVariable, $tempVariable, $compilationContext);
                        } else {
                            $symbolVariable->initVariant($compilationContext);
                            $compilationContext->backend->assignDouble($symbolVariable, $resolvedExpr->getCode(), $compilationContext);
                        }
                        break;
                    default:
                        throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                }
                break;
            case 'bool':
                switch ($statement['operator']) {
                    case 'assign':
                        $symbolVariable->setDynamicTypes('bool');
                        if ($resolvedExpr->getCode() == 'true') {
                            $symbolVariable->initVariant($compilationContext);
                            $compilationContext->backend->assignBool($symbolVariable, '1', $compilationContext);
                        } else {
                            if ($resolvedExpr->getCode() == 'false') {
                                $symbolVariable->initVariant($compilationContext);
                                $compilationContext->backend->assignBool($symbolVariable, '0', $compilationContext);
                            } else {
                                if ($readDetector->detect($variable, $resolvedExpr->getOriginal())) {
                                    $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('double', $compilationContext);
                                    $codePrinter->output($tempVariable->getName() . ' = ' . $resolvedExpr->getBooleanCode() . ';');
                                    $symbolVariable->initVariant($compilationContext);
                                    $compilationContext->backend->assignBool($symbolVariable, $tempVariable, $compilationContext);
                                } else {
                                    $symbolVariable->initVariant($compilationContext);
                                    $compilationContext->backend->assignBool($symbolVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
                                }
                            }
                        }
                        break;
                    default:
                        throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                }
                break;
            case 'string':
                switch ($statement['operator']) {
                    case 'assign':
                        $symbolVariable->initVariant($compilationContext);
                        $symbolVariable->setDynamicTypes('string');
                        $compilationContext->backend->assignString($symbolVariable, $resolvedExpr->getCode(), $compilationContext);
                        break;
                    case 'concat-assign':
                        $compilationContext->headersManager->add('kernel/operators');
                        $codePrinter->output('zephir_concat_self_str(&' . $variable . ', SL("' . $resolvedExpr->getCode() . '") TSRMLS_CC);');
                        break;
                    default:
                        throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                }
                break;
            case 'array':
                switch ($statement['operator']) {
                    case 'assign':
                        if ($variable != $resolvedExpr->getCode()) {
                            $symbolVariable->setMustInitNull(true);
                            $compilationContext->symbolTable->mustGrownStack(true);
                            /* Inherit the dynamic type data from the assigned value */
                            $symbolVariable->setDynamicTypes('array');
                            $symbolVariable->increaseVariantIfNull();
                            $symbol = $compilationContext->backend->getVariableCode($symbolVariable);
                            $codePrinter->output('ZEPHIR_CPY_WRT(' . $symbol . ', ' . $compilationContext->backend->resolveValue($resolvedExpr, $compilationContext) . ');');
                        }
                        break;
                    default:
                        throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                }
                break;
            case 'variable':
                $itemVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $resolvedExpr->getOriginal());
                switch ($itemVariable->getType()) {
                    case 'int':
                    case 'uint':
                    case 'long':
                    case 'ulong':
                    case 'char':
                    case 'uchar':
                        switch ($statement['operator']) {
                            case 'assign':
                                $symbolVariable->initVariant($compilationContext);
                                $symbolVariable->setDynamicTypes('long');
                                $compilationContext->backend->assignLong($symbolVariable, $itemVariable, $compilationContext);
                                break;
                            case 'add-assign':
                                $compilationContext->headersManager->add('kernel/operators');
                                $symbolVariable->initVariant($compilationContext);
                                $symbolVariable->setDynamicTypes('long');
                                $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite($itemVariable->getType(), $compilationContext);
                                $codePrinter->output($tempVariable->getName() . ' = zephir_get_numberval(' . $compilationContext->backend->getVariableCode($symbolVariable) . ') + ' . $itemVariable->getName() . ';');
                                $compilationContext->backend->assignLong($symbolVariable, $tempVariable, $compilationContext);
                                break;
                            case 'sub-assign':
                                $compilationContext->headersManager->add('kernel/operators');
                                $symbolVariable->initVariant($compilationContext);
                                $symbolVariable->setDynamicTypes('long');
                                $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite($itemVariable->getType(), $compilationContext);
                                $codePrinter->output($tempVariable->getName() . ' = zephir_get_numberval(' . $compilationContext->backend->getVariableCode($symbolVariable) . ');');
                                $compilationContext->backend->assignLong($symbolVariable, $tempVariable->getName() . ' - ' . $itemVariable->getName(), $compilationContext);
                                break;
                            default:
                                throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                        }
                        break;
                    case 'double':
                        switch ($statement['operator']) {
                            case 'assign':
                                $symbolVariable->initVariant($compilationContext);
                                $symbolVariable->setDynamicTypes('double');
                                $compilationContext->backend->assignDouble($symbolVariable, $itemVariable, $compilationContext);
                                break;
                            default:
                                throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                        }
                        break;
                    case 'bool':
                        switch ($statement['operator']) {
                            case 'assign':
                                $symbolVariable->initVariant($compilationContext);
                                $symbolVariable->setDynamicTypes('bool');
                                $compilationContext->backend->assignBool($symbolVariable, $itemVariable, $compilationContext);
                                break;
                            default:
                                throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                        }
                        break;
                    case 'array':
                        switch ($statement['operator']) {
                            case 'assign':
                                if ($variable != $resolvedExpr->getCode()) {
                                    $symbolVariable->setMustInitNull(true);
                                    $compilationContext->symbolTable->mustGrownStack(true);
                                    /* Inherit the dynamic type data from the assigned value */
                                    $symbolVariable->setDynamicTypes('array');
                                    $symbolVariable->increaseVariantIfNull();
                                    $symbol = $compilationContext->backend->getVariableCode($symbolVariable);
                                    $codePrinter->output('ZEPHIR_CPY_WRT(' . $symbol . ', ' . $compilationContext->backend->resolveValue($resolvedExpr, $compilationContext) . ');');
                                }
                                break;
                            default:
                                throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                        }
                        break;
                    case 'variable':
                        switch ($statement['operator']) {
                            case 'assign':
                                if ($itemVariable->getName() != $variable) {
                                    $symbolVariable->setMustInitNull(true);
                                    $compilationContext->symbolTable->mustGrownStack(true);
                                    /* Inherit the dynamic type data from the assigned value */
                                    $symbolVariable->setDynamicTypes(array_keys($itemVariable->getDynamicTypes()));
                                    $symbolVariable->setClassTypes($itemVariable->getClassTypes());
                                    $symbolVariable->increaseVariantIfNull();
                                    $compilationContext->backend->copyOnWrite($symbolVariable, $itemVariable, $compilationContext);
                                    if ($itemVariable->isTemporal()) {
                                        $itemVariable->setIdle(true);
                                    }
                                }
                                break;
                            case 'concat-assign':
                                $compilationContext->headersManager->add('kernel/operators');
                                $compilationContext->backend->concatSelf($symbolVariable, $itemVariable, $compilationContext);
                                break;
                            case 'add-assign':
                                $compilationContext->symbolTable->mustGrownStack(true);
                                $compilationContext->headersManager->add('kernel/operators');
                                $codePrinter->output('ZEPHIR_ADD_ASSIGN(' . $compilationContext->backend->getVariableCode($symbolVariable) . ', ' . $compilationContext->backend->getVariableCode($itemVariable) . ');');
                                break;
                            case 'sub-assign':
                                $compilationContext->symbolTable->mustGrownStack(true);
                                $compilationContext->headersManager->add('kernel/operators');
                                $codePrinter->output('ZEPHIR_SUB_ASSIGN(' . $compilationContext->backend->getVariableCode($symbolVariable) . ', ' . $compilationContext->backend->getVariableCode($itemVariable) . ');');
                                break;
                            default:
                                throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                        }
                        break;
                    case 'string':
                        switch ($statement['operator']) {
                            case 'assign':
                                if ($itemVariable->getName() != $variable) {
                                    $symbolVariable->setMustInitNull(true);
                                    $compilationContext->symbolTable->mustGrownStack(true);
                                    /* Inherit the dynamic type data from the assigned value */
                                    $symbolVariable->setDynamicTypes(array_keys($itemVariable->getDynamicTypes()));
                                    $symbolVariable->setClassTypes($itemVariable->getClassTypes());
                                    $symbolVariable->increaseVariantIfNull();
                                    $compilationContext->backend->copyOnWrite($symbolVariable, $itemVariable, $compilationContext);
                                    if ($itemVariable->isTemporal()) {
                                        $itemVariable->setIdle(true);
                                    }
                                }
                                break;
                            case 'concat-assign':
                                $compilationContext->headersManager->add('kernel/operators');
                                $compilationContext->backend->concatSelf($symbolVariable, $itemVariable, $compilationContext);
                                break;
                            default:
                                throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                        }
                        break;
                    default:
                        throw new CompilerException("Unknown type: " . $itemVariable->getType(), $resolvedExpr->getOriginal());
                }
                break;
            default:
                throw new CompilerException("Unknown type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
        }
    }