/**
* Compiles foo->{x} = {expr}
*
* @param string $variable
* @param Variable $symbolVariable
* @param CompiledExpression $resolvedExpr
* @param CompilationContext $compilationContext
* @param array $statement
*/
public function assign($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, $statement)
{
if (!$symbolVariable->isInitialized()) {
throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is not initialized", $statement);
}
if ($symbolVariable->getType() != 'variable') {
throw new CompilerException("Variable type '" . $symbolVariable->getType() . "' cannot be used as object", $statement);
}
$propertyName = $statement['property'];
$propertyVariable = $compilationContext->symbolTable->getVariableForRead($propertyName, $compilationContext, $statement);
if ($propertyVariable->isNotVariableAndString()) {
throw new CompilerException("Cannot use variable type '" . $propertyVariable->getType() . "' to update object property", $statement);
}
if (!$symbolVariable->isInitialized()) {
throw new CompilerException("Cannot mutate static property '" . $compilationContext->classDefinition->getCompleteName() . "::" . $propertyName . "' because it is not initialized", $statement);
}
if ($symbolVariable->getType() != 'variable') {
throw new CompilerException("Cannot use variable type: " . $symbolVariable->getType() . " as an object", $statement);
}
if ($symbolVariable->hasAnyDynamicType('unknown')) {
throw new CompilerException("Cannot use non-initialized variable as an object", $statement);
}
/**
* Trying to use a non-object dynamic variable as object
*/
if ($symbolVariable->hasDifferentDynamicType(array('undefined', 'object', 'null'))) {
$compilationContext->logger->warning('Possible attempt to update property on non-object dynamic property', 'non-valid-objectupdate', $statement);
}
$codePrinter = $compilationContext->codePrinter;
$compilationContext->headersManager->add('kernel/object');
$propertyVariableName = $compilationContext->symbolTable->getVariable($propertyName);
switch ($resolvedExpr->getType()) {
case 'null':
if ($variable == 'this') {
$codePrinter->output('zephir_update_property_this(this_ptr, Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ZEPHIR_GLOBAL(global_null) TSRMLS_CC);');
} else {
$codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ZEPHIR_GLOBAL(global_null) TSRMLS_CC);');
}
break;
case 'int':
case 'long':
$tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
$codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $resolvedExpr->getBooleanCode() . ');');
if ($variable == 'this') {
$codePrinter->output('zephir_update_property_this(this_ptr, Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ' . $tempVariable->getName() . ' TSRMLS_CC);');
} else {
$codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ' . $tempVariable->getName() . ' TSRMLS_CC);');
}
break;
case 'string':
$tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
$codePrinter->output('ZVAL_STRING(' . $tempVariable->getName() . ', "' . $resolvedExpr->getCode() . '", 1);');
if ($variable == 'this') {
$codePrinter->output('zephir_update_property_this(this_ptr, Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ' . $tempVariable->getName() . ' TSRMLS_CC);');
} else {
$codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ' . $tempVariable->getName() . ' TSRMLS_CC);');
}
break;
case 'bool':
if ($variable == 'this') {
if ($resolvedExpr->getBooleanCode() == '1') {
$codePrinter->output('zephir_update_property_this(this_ptr, Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ZEPHIR_GLOBAL(global_true) TSRMLS_CC);');
} else {
$codePrinter->output('zephir_update_property_this(this_ptr, Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ZEPHIR_GLOBAL(global_false) TSRMLS_CC);');
}
} else {
if ($resolvedExpr->getBooleanCode() == '1') {
$codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ZEPHIR_GLOBAL(global_true) TSRMLS_CC);');
} else {
$codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ZEPHIR_GLOBAL(global_false) TSRMLS_CC);');
}
}
break;
case 'empty-array':
$tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
$codePrinter->output('array_init(' . $tempVariable->getName() . ');');
if ($variable == 'this') {
$codePrinter->output('zephir_update_property_this(this_ptr, Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ' . $tempVariable->getName() . ' TSRMLS_CC);');
} else {
$codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ' . $tempVariable->getName() . ' TSRMLS_CC);');
}
break;
case 'variable':
$variableVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
switch ($variableVariable->getType()) {
case 'int':
case 'uint':
case 'long':
case 'ulong':
case 'char':
case 'uchar':
$tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
$codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $variableVariable->getName() . ');');
$codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ' . $tempVariable->getName() . ' TSRMLS_CC);');
break;
case 'bool':
$tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
$codePrinter->output('ZVAL_BOOL(' . $tempVariable->getName() . ', ' . $variableVariable->getName() . ');');
if ($variable == 'this') {
$codePrinter->output('zephir_update_property_this(this_ptr, Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ' . $tempVariable->getName() . ' TSRMLS_CC);');
} else {
$codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $propertyVariableName->getName() . '), Z_STRLEN_P(' . $propertyVariableName->getName() . '), ' . $tempVariable->getName() . ' TSRMLS_CC);');
}
break;
case 'string':
case 'variable':
$codePrinter->output('zephir_update_property_zval_zval(' . $symbolVariable->getName() . ', ' . $propertyVariable->getName() . ', ' . $resolvedExpr->getCode() . ' TSRMLS_CC);');
if ($symbolVariable->isTemporal()) {
$symbolVariable->setIdle(true);
}
break;
default:
throw new CompilerException("Unknown type " . $variableVariable->getType(), $statement);
}
break;
default:
throw new CompilerException("Unknown type " . $resolvedExpr->getType(), $statement);
}
}