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());
}
}