Example #1
0
 /**
  * Compiles {var} = {expr}
  *
  * @param string $variable
  * @param ZephirVariable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext,
  * @param array $statement
  */
 public function assign($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, $statement)
 {
     $codePrinter = $compilationContext->codePrinter;
     $codePrinter->output('if (zephir_set_symbol(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getCode() . ' TSRMLS_CC) == FAILURE){');
     $codePrinter->output('  return;');
     $codePrinter->output('}');
 }
Example #2
0
 /**
  * Compiles {"var"} = {expr}
  *
  * @param string $variable
  * @param ZephirVariable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext,
  * @param array $statement
  */
 public function assign($variable, ZephirVariable $symbolVariable = null, CompiledExpression $resolvedExpr = null, CompilationContext $compilationContext = null, $statement = null)
 {
     $codePrinter = $compilationContext->codePrinter;
     $codePrinter->output('if (zephir_set_symbol_str(SS("' . $statement["variable"] . '"), ' . $resolvedExpr->getCode() . ' TSRMLS_CC) == FAILURE){');
     $codePrinter->output('  return;');
     $codePrinter->output('}');
 }
 /**
  * Compiles {"var"} = {expr}
  *
  * @param string $variable
  * @param ZephirVariable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext,
  * @param array $statement
  */
 public function assign($variable, ZephirVariable $symbolVariable = null, CompiledExpression $resolvedExpr = null, CompilationContext $compilationContext = null, $statement = null)
 {
     $codePrinter = $compilationContext->codePrinter;
     $variable = $compilationContext->symbolTable->getTempVariable('variable', $compilationContext, $statement);
     $variable->setMustInitNull(true);
     $letStatement = new LetStatement(array('type' => 'let', 'assignments' => array(array('assign-type' => 'variable', 'variable' => $variable->getName(), 'operator' => 'assign', 'expr' => array('type' => $resolvedExpr->getType(), 'value' => $resolvedExpr->getCode(), 'file' => $statement['file'], 'line' => $statement['line'], 'char' => $statement['char']), 'file' => $statement['file'], 'line' => $statement['line'], 'char' => $statement['char']))));
     $letStatement->compile($compilationContext);
     $codePrinter->output('if (zephir_set_symbol_str(SS("' . $statement["variable"] . '"), ' . $variable->getName() . ' TSRMLS_CC) == FAILURE){');
     $codePrinter->output('  return;');
     $codePrinter->output('}');
 }
Example #4
0
 /**
  * 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);
     }
 }
 /**
  * Compiles x->y[] = foo
  *
  * @param string $variable
  * @param ZephirVariable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext
  * @param array $statement
  * @throws CompilerException
  */
 public function assign($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, array $statement)
 {
     if (!$symbolVariable->isInitialized()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is not initialized", $statement);
     }
     if (!$symbolVariable->isVariable()) {
         throw new CompilerException("Attempt to use variable type: " . $symbolVariable->getType() . " as object", $statement);
     }
     $codePrinter = $compilationContext->codePrinter;
     $property = $statement['property'];
     $compilationContext->headersManager->add('kernel/object');
     /**
      * Check if the variable to update is defined
      */
     if ($symbolVariable->getRealName() == 'this') {
         $classDefinition = $compilationContext->classDefinition;
         if (!$classDefinition->hasProperty($property)) {
             throw new CompilerException("Class '" . $classDefinition->getCompleteName() . "' does not have a property called: '" . $property . "'", $statement);
         }
         $propertyDefinition = $classDefinition->getProperty($property);
     } else {
         /**
          * If we know the class related to a variable we could check if the property
          * is defined on that class
          */
         if ($symbolVariable->hasAnyDynamicType('object')) {
             $classType = current($symbolVariable->getClassTypes());
             $compiler = $compilationContext->compiler;
             if ($compiler->isClass($classType)) {
                 $classDefinition = $compiler->getClassDefinition($classType);
                 if (!$classDefinition) {
                     throw new CompilerException("Cannot locate class definition for class: " . $classType, $statement);
                 }
                 if (!$classDefinition->hasProperty($property)) {
                     throw new CompilerException("Class '" . $classType . "' does not have a property called: '" . $property . "'", $statement);
                 }
             }
         }
     }
     switch ($resolvedExpr->getType()) {
         case 'null':
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ZEPHIR_GLOBAL(global_null) TSRMLS_CC);');
             break;
         case 'bool':
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), (' . $resolvedExpr->getBooleanCode() . ') ? ZEPHIR_GLOBAL(global_true) : ZEPHIR_GLOBAL(global_false) TSRMLS_CC);');
             break;
         case 'char':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', \'' . $resolvedExpr->getCode() . '\');');
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'int':
         case 'long':
         case 'uint':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'double':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $codePrinter->output('ZVAL_DOUBLE(' . $tempVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'string':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $codePrinter->output('ZVAL_STRING(' . $tempVariable->getName() . ', "' . $resolvedExpr->getCode() . '", 1);');
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'array':
             $variableExpr = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $variableExpr->getName() . ' TSRMLS_CC);');
             break;
         case 'variable':
             $variableExpr = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
             switch ($variableExpr->getType()) {
                 case 'int':
                 case 'long':
                 case 'uint':
                 case 'char':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $variableExpr->getName() . ');');
                     $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'double':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $codePrinter->output('ZVAL_DOUBLE(' . $tempVariable->getName() . ', ' . $variableExpr->getName() . ');');
                     $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'bool':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $codePrinter->output('ZVAL_BOOL(' . $tempVariable->getName() . ', ' . $variableExpr->getName() . ');');
                     $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'variable':
                 case 'string':
                 case 'array':
                 case 'resource':
                 case 'object':
                     $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $variableExpr->getName() . ' TSRMLS_CC);');
                     if ($variableExpr->isTemporal()) {
                         $variableExpr->setIdle(true);
                     }
                     break;
                 default:
                     throw new CompilerException("Variable: " . $variableExpr->getType() . " cannot be appended to array property", $statement);
             }
             break;
         default:
             throw new CompilerException("Expression: " . $resolvedExpr->getType() . " cannot be appended to array property", $statement);
     }
 }
Example #6
0
 /**
  * Compiles foo->x = {expr}
  *
  * @param string $variable
  * @param ZephirVariable $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->isVariable()) {
         throw new CompilerException("Variable type '" . $symbolVariable->getType() . "' cannot be used as object", $statement);
     }
     $propertyName = $statement['property'];
     $className = $compilationContext->classDefinition->getCompleteName();
     if (!$symbolVariable->isInitialized()) {
         throw new CompilerException("Cannot mutate static property '" . $className . "::" . $propertyName . "' because it is not initialized", $statement);
     }
     if (!$symbolVariable->isVariable()) {
         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'))) {
         $compilationContext->logger->warning('Possible attempt to update property on non-object dynamic property', 'non-valid-objectupdate', $statement);
     }
     /**
      * Try to check if property is implemented on related object
      */
     if ($variable == 'this') {
         if (!$compilationContext->classDefinition->hasProperty($propertyName)) {
             throw new CompilerException("Property '" . $propertyName . "' is not defined on class '" . $className . "'", $statement);
         }
     }
     $codePrinter = $compilationContext->codePrinter;
     $compilationContext->headersManager->add('kernel/object');
     switch ($resolvedExpr->getType()) {
         case 'null':
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, 'null', $compilationContext);
             break;
         case 'int':
         case 'long':
         case 'uint':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
             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;
                     }
                     $resolvedVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $compilationContext->backend->assignLong($resolvedVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
                     $codePrinter->output($functionName . '(' . $compilationContext->backend->getVariableCode($tempVariable) . ', ' . $compilationContext->backend->getVariableCode($resolvedVariable) . ')');
                     break;
                 case 'assign':
                     $tempVariable->initNonReferenced($compilationContext);
                     $compilationContext->backend->assignLong($tempVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
                     break;
                 default:
                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for object property: " . $tempVariable->getType(), $statement);
             }
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
             $tempVariable->setIdle(true);
             break;
         case 'char':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
             switch ($statement['operator']) {
                 case 'assign':
                     $tempVariable->initNonReferenced($compilationContext);
                     $compilationContext->backend->assignLong($tempVariable, '\'' . $resolvedExpr->getBooleanCode() . '\'', $compilationContext);
                     break;
                 default:
                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for object property: " . $tempVariable->getType(), $statement);
             }
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
             $tempVariable->setIdle(true);
             break;
         case 'double':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
             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;
                     }
                     $resolvedVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $compilationContext->backend->assignDouble($resolvedVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
                     $codePrinter->output($functionName . '(' . $compilationContext->backend->getVariableCode($tempVariable) . ', ' . $compilationContext->backend->getVariableCode($resolvedVariable) . ')');
                     break;
                 case 'assign':
                     $tempVariable->initNonReferenced($compilationContext);
                     $compilationContext->backend->assignDouble($tempVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
                     break;
                 default:
                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for object property: " . $tempVariable->getType(), $statement);
             }
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
             $tempVariable->setIdle(true);
             break;
         case 'string':
             if ($compilationContext->backend->getName() == 'ZendEngine2') {
                 $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
             } else {
                 $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, false);
             }
             switch ($statement['operator']) {
                 case 'concat-assign':
                     $codePrinter->output('zephir_concat_self_str(&' . $tempVariable->getName() . ', "' . $resolvedExpr->getCode() . '", sizeof("' . $resolvedExpr->getCode() . '")-1 TSRMLS_CC);');
                     break;
                 case 'assign':
                     /* We only can use nonReferenced variables for not refcounted stuff in ZE3 */
                     if ($compilationContext->backend->getName() == 'ZendEngine2') {
                         $tempVariable->initNonReferenced($compilationContext);
                     } else {
                         $tempVariable->initVariant($compilationContext);
                     }
                     $compilationContext->backend->assignString($tempVariable, $resolvedExpr->getCode(), $compilationContext);
                     break;
             }
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
             $tempVariable->setIdle(true);
             break;
         case 'array':
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $resolvedExpr, $compilationContext);
             break;
         case 'bool':
             $codePrinter->output('if (' . $resolvedExpr->getBooleanCode() . ') {');
             $codePrinter->increaseLevel();
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, 'true', $compilationContext);
             $codePrinter->decreaseLevel();
             $codePrinter->output('} else {');
             $codePrinter->increaseLevel();
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, 'false', $compilationContext);
             $codePrinter->decreaseLevel();
             $codePrinter->output('}');
             break;
             /* unreachable code */
         /* unreachable code */
         case 'empty-array':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
             $compilationContext->backend->initArray($tempVariable, $compilationContext);
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $resolvedExpr->getCode(), $compilationContext);
             $tempVariable->setIdle(true);
             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->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $compilationContext->backend->assignLong($tempVariable, $variableVariable, $compilationContext);
                     $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
                     $tempVariable->setIdle(true);
                     break;
                 case 'double':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $compilationContext->backend->assignDouble($tempVariable, $variableVariable, $compilationContext);
                     $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
                     $tempVariable->setIdle(true);
                     break;
                 case 'bool':
                     $codePrinter->output('if (' . $variableVariable->getName() . ') {');
                     $codePrinter->increaseLevel();
                     $compilationContext->backend->updateProperty($symbolVariable, $propertyName, 'true', $compilationContext);
                     $codePrinter->decreaseLevel();
                     $codePrinter->output('} else {');
                     $codePrinter->increaseLevel();
                     $compilationContext->backend->updateProperty($symbolVariable, $propertyName, 'false', $compilationContext);
                     $codePrinter->decreaseLevel();
                     $codePrinter->output('}');
                     break;
                 case 'array':
                 case 'string':
                 case 'variable':
                     $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $variableVariable, $compilationContext);
                     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);
     }
 }
Example #7
0
 /**
  * Compiles foo->x = {expr}
  *
  * @param string $variable
  * @param ZephirVariable $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'];
     $className = $compilationContext->classDefinition->getCompleteName();
     if (!$symbolVariable->isInitialized()) {
         throw new CompilerException("Cannot mutate static property '" . $className . "::" . $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'))) {
         $compilationContext->logger->warning('Possible attempt to update property on non-object dynamic property', 'non-valid-objectupdate', $statement);
     }
     /**
      * Try to check if property is implemented on related object
      */
     if ($variable == 'this') {
         if (!$compilationContext->classDefinition->hasProperty($propertyName)) {
             throw new CompilerException("Property '" . $propertyName . "' is not defined on class '" . $className . "'", $statement);
         }
     }
     $codePrinter = $compilationContext->codePrinter;
     $compilationContext->headersManager->add('kernel/object');
     switch ($resolvedExpr->getType()) {
         case 'null':
             if ($variable == 'this') {
                 $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), ZEPHIR_GLOBAL(global_null) TSRMLS_CC);');
             } else {
                 $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), ZEPHIR_GLOBAL(global_null) TSRMLS_CC);');
             }
             break;
         case 'int':
         case 'long':
         case 'uint':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
             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;
                     }
                     $resolvedVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_LONG(' . $resolvedVariable->getName() . ', ' . $resolvedExpr->getBooleanCode() . ');');
                     $codePrinter->output($functionName . '(' . $tempVariable->getName() . ', ' . $resolvedVariable->getName() . ')');
                     break;
                 case 'assign':
                     $tempVariable->initNonReferenced($compilationContext);
                     $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $resolvedExpr->getBooleanCode() . ');');
                     break;
                 default:
                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for object property: " . $tempVariable->getType(), $statement);
             }
             if ($variable == 'this') {
                 $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             } else {
                 $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             }
             $tempVariable->setIdle(true);
             break;
         case 'char':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
             switch ($statement['operator']) {
                 case 'assign':
                     $tempVariable->initNonReferenced($compilationContext);
                     $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', \'' . $resolvedExpr->getBooleanCode() . '\');');
                     break;
                 default:
                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for object property: " . $tempVariable->getType(), $statement);
             }
             if ($variable == 'this') {
                 $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             } else {
                 $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             }
             $tempVariable->setIdle(true);
             break;
         case 'double':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
             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;
                     }
                     $resolvedVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_DOUBLE(' . $resolvedVariable->getName() . ', ' . $resolvedExpr->getBooleanCode() . ');');
                     $codePrinter->output($functionName . '(' . $tempVariable->getName() . ', ' . $resolvedVariable->getName() . ')');
                     break;
                 case 'assign':
                     $tempVariable->initNonReferenced($compilationContext);
                     $codePrinter->output('ZVAL_DOUBLE(' . $tempVariable->getName() . ', ' . $resolvedExpr->getBooleanCode() . ');');
                     break;
                 default:
                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for object property: " . $tempVariable->getType(), $statement);
             }
             if ($variable == 'this') {
                 $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             } else {
                 $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             }
             $tempVariable->setIdle(true);
             break;
         case 'string':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
             switch ($statement['operator']) {
                 case 'concat-assign':
                     $codePrinter->output('zephir_concat_self_str(&' . $tempVariable->getName() . ', "' . $resolvedExpr->getCode() . '", sizeof("' . $resolvedExpr->getCode() . '")-1 TSRMLS_CC);');
                     break;
                 case 'assign':
                     $tempVariable->initNonReferenced($compilationContext);
                     $codePrinter->output('ZVAL_STRING(' . $tempVariable->getName() . ', "' . $resolvedExpr->getCode() . '", 1);');
                     break;
             }
             if ($variable == 'this') {
                 $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             } else {
                 $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             }
             $tempVariable->setIdle(true);
             break;
         case 'array':
             if ($variable == 'this') {
                 $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), ' . $resolvedExpr->getCode() . ' TSRMLS_CC);');
             } else {
                 $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), ' . $resolvedExpr->getCode() . ' TSRMLS_CC);');
             }
             break;
         case 'bool':
             if ($variable == 'this') {
                 $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), (' . $resolvedExpr->getBooleanCode() . ') ? ZEPHIR_GLOBAL(global_true) : ZEPHIR_GLOBAL(global_false) TSRMLS_CC);');
             } else {
                 $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), (' . $resolvedExpr->getBooleanCode() . ') ? ZEPHIR_GLOBAL(global_true) : ZEPHIR_GLOBAL(global_false) TSRMLS_CC);');
             }
             break;
         case 'empty-array':
             /* unreachable code */
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
             $codePrinter->output('array_init(' . $tempVariable->getName() . ');');
             if ($variable == 'this') {
                 $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             } else {
                 $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             }
             $tempVariable->setIdle(true);
             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->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $variableVariable->getName() . ');');
                     if ($variable == 'this') {
                         $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     } else {
                         $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     }
                     $tempVariable->setIdle(true);
                     break;
                 case 'double':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $codePrinter->output('ZVAL_DOUBLE(' . $tempVariable->getName() . ', ' . $variableVariable->getName() . ');');
                     if ($variable == 'this') {
                         $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     } else {
                         $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     }
                     $tempVariable->setIdle(true);
                     break;
                 case 'bool':
                     if ($variable == 'this') {
                         $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), ' . $variableVariable->getName() . ' ? ZEPHIR_GLOBAL(global_true) : ZEPHIR_GLOBAL(global_false) TSRMLS_CC);');
                     } else {
                         $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), ' . $variableVariable->getName() . ' ? ZEPHIR_GLOBAL(global_true) : ZEPHIR_GLOBAL(global_false) TSRMLS_CC);');
                     }
                     break;
                 case 'array':
                 case 'string':
                 case 'variable':
                     if ($variable == 'this') {
                         $codePrinter->output('zephir_update_property_this(this_ptr, SL("' . $propertyName . '"), ' . $variableVariable->getName() . ' TSRMLS_CC);');
                     } else {
                         $codePrinter->output('zephir_update_property_zval(' . $symbolVariable->getName() . ', SL("' . $propertyName . '"), ' . $variableVariable->getName() . ' 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);
     }
 }
Example #8
0
 /**
  * Resolves an item that will be assigned to an array offset
  *
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext
  */
 protected function _getResolvedArrayItem(CompiledExpression $resolvedExpr, CompilationContext $compilationContext)
 {
     $codePrinter = $compilationContext->codePrinter;
     switch ($resolvedExpr->getType()) {
         case 'null':
             $symbolVariable = new GlobalConstant('ZEPHIR_GLOBAL(global_null)');
             break;
         case 'int':
         case 'uint':
         case 'long':
             $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $resolvedExpr->getOriginal());
             $codePrinter->output('ZVAL_LONG(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
             break;
         case 'char':
             $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $resolvedExpr->getOriginal());
             $codePrinter->output('ZVAL_LONG(' . $symbolVariable->getName() . ', \'' . $resolvedExpr->getCode() . '\');');
             break;
         case 'double':
             $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $resolvedExpr->getOriginal());
             $codePrinter->output('ZVAL_DOUBLE(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
             break;
         case 'bool':
             if ($resolvedExpr->getBooleanCode() == '1') {
                 $symbolVariable = new GlobalConstant('ZEPHIR_GLOBAL(global_true)');
             } else {
                 if ($resolvedExpr->getBooleanCode() == '0') {
                     $symbolVariable = new GlobalConstant('ZEPHIR_GLOBAL(global_false)');
                 } else {
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $resolvedExpr->getOriginal());
                     $codePrinter->output('ZVAL_BOOL(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getBooleanCode() . ');');
                 }
             }
             break;
         case 'string':
             $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $resolvedExpr->getOriginal());
             $codePrinter->output('ZVAL_STRING(' . $symbolVariable->getName() . ', "' . $resolvedExpr->getCode() . '", 1);');
             break;
         case 'array':
             $symbolVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $resolvedExpr->getOriginal());
             break;
         case 'variable':
             $variableExpr = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $resolvedExpr->getOriginal());
             switch ($variableExpr->getType()) {
                 case 'int':
                 case 'uint':
                 case 'long':
                 case 'ulong':
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $resolvedExpr->getOriginal());
                     $codePrinter->output('ZVAL_LONG(' . $symbolVariable->getName() . ', ' . $variableExpr->getName() . ');');
                     break;
                 case 'double':
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $resolvedExpr->getOriginal());
                     $codePrinter->output('ZVAL_DOUBLE(' . $symbolVariable->getName() . ', ' . $variableExpr->getName() . ');');
                     break;
                 case 'bool':
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $resolvedExpr->getOriginal());
                     $codePrinter->output('ZVAL_BOOL(' . $symbolVariable->getName() . ', ' . $variableExpr->getName() . ');');
                     break;
                 case 'variable':
                 case 'string':
                 case 'array':
                     $symbolVariable = $variableExpr;
                     break;
                 default:
                     throw new CompilerException("Variable: " . $variableExpr->getType() . " cannot be assigned to array offset", $resolvedExpr->getOriginal());
             }
             break;
         default:
             throw new CompilerException("Expression: " . $resolvedExpr->getType() . " cannot be assigned to array offset", $resolvedExpr->getOriginal());
     }
     return $symbolVariable;
 }
 /**
  * Compiles x->y[z] = {expr} (single offset assignment)
  *
  * @param string $variable
  * @param Variable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext,
  * @param array $statement
  */
 protected function _assignPropertyArraySingleIndex($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, $statement)
 {
     $codePrinter = $compilationContext->codePrinter;
     $property = $statement['property'];
     $compilationContext->headersManager->add('kernel/object');
     /**
      * Only string/variable/int
      */
     $indexExpression = new Expression($statement['index-expr'][0]);
     $resolvedIndex = $indexExpression->compile($compilationContext);
     switch ($resolvedIndex->getType()) {
         case 'string':
         case 'int':
         case 'uint':
         case 'ulong':
         case 'long':
         case 'variable':
             break;
         default:
             throw new CompilerException("Expression: " . $resolvedIndex->getType() . " cannot be used as index without cast", $statement['index-expr']);
     }
     if ($resolvedIndex->getType() == 'variable') {
         $indexVariable = $compilationContext->symbolTable->getVariableForRead($resolvedIndex->getCode(), $compilationContext, $statement['index-expr']);
         switch ($indexVariable->getType()) {
             case 'string':
             case 'int':
             case 'uint':
             case 'ulong':
             case 'long':
             case 'variable':
                 break;
             default:
                 throw new CompilerException("Variable: " . $indexVariable->getType() . " cannot be used as index without cast", $statement);
         }
         if ($indexVariable->getType() == 'variable') {
             if ($indexVariable->hasDifferentDynamicType(array('undefined', 'int', 'string'))) {
                 $compilationContext->logger->warning('Possible attempt to use non string/long dynamic variable as array index', 'invalid-array-offset', $statement);
             }
         }
     }
     switch ($resolvedIndex->getType()) {
         case 'int':
         case 'uint':
         case 'long':
             $indexVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
             $codePrinter->output('ZVAL_LONG(' . $indexVariable->getName() . ', ' . $resolvedIndex->getCode() . ');');
             break;
         case 'string':
             $indexVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
             $codePrinter->output('ZVAL_STRING(' . $indexVariable->getName() . ', "' . $resolvedIndex->getCode() . '", 1);');
             break;
         case 'variable':
             $variableIndex = $compilationContext->symbolTable->getVariableForRead($resolvedIndex->getCode(), $compilationContext, $statement['index-expr']);
             switch ($variableIndex->getType()) {
                 case 'int':
                 case 'uint':
                 case 'long':
                     $indexVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $codePrinter->output('ZVAL_LONG(' . $indexVariable->getName() . ', ' . $variableIndex->getName() . ');');
                     break;
             }
             break;
     }
     switch ($indexVariable->getType()) {
         case 'variable':
         case 'string':
             switch ($resolvedExpr->getType()) {
                 case 'null':
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ZEPHIR_GLOBAL(global_null) TSRMLS_CC);');
                     break;
                 case 'bool':
                     if ($resolvedExpr->getBooleanCode() == '1') {
                         $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ZEPHIR_GLOBAL(global_true) TSRMLS_CC);');
                     } else {
                         $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ZEPHIR_GLOBAL(global_false) TSRMLS_CC);');
                     }
                     break;
                 case 'int':
                 case 'long':
                 case 'uint':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     break;
                 case 'char':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', \'' . $resolvedExpr->getCode() . '\');');
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     break;
                 case 'double':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_DOUBLE(' . $tempVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     break;
                 case 'string':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_STRING(' . $tempVariable->getName() . ', "' . $resolvedExpr->getCode() . '", 1);');
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     break;
                 case 'array':
                     $variableExpr = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement['index-expr']);
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $variableExpr->getName() . ' TSRMLS_CC);');
                     break;
                 case 'variable':
                     $variableExpr = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement['index-expr']);
                     switch ($variableExpr->getType()) {
                         case 'bool':
                             $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                             $codePrinter->output('ZVAL_BOOL(' . $tempVariable->getName() . ', ' . $variableExpr->getName() . ');');
                             $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                             break;
                         case 'int':
                         case 'long':
                             $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                             $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $variableExpr->getName() . ');');
                             $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                             break;
                         case 'variable':
                         case 'string':
                         case 'array':
                             $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $variableExpr->getName() . ' TSRMLS_CC);');
                             if ($variableExpr->isTemporal()) {
                                 $variableExpr->setIdle(true);
                             }
                             break;
                         default:
                             throw new CompilerException("Cannot update variable type: " . $variableExpr->getType(), $statement);
                     }
                     break;
                 default:
                     throw new CompilerException("Variable index: " . $indexVariable->getType() . " cannot be updated into array property", $statement);
             }
             break;
         default:
             throw new CompilerException("Index: " . $resolvedIndex->getType() . " cannot be updated into array property", $statement);
     }
 }
Example #10
0
 /**
  * Compiles ClassName::foo = {expr}
  *
  * @param                    $className
  * @param                    $property
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext
  * @param array              $statement
  *
  * @throws CompilerException
  * @internal param string $variable
  */
 public function assignStatic($className, $property, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, $statement)
 {
     $compiler = $compilationContext->compiler;
     if (!in_array($className, array('self', 'static', 'parent'))) {
         $className = $compilationContext->getFullName($className);
         if ($compiler->isClass($className)) {
             $classDefinition = $compiler->getClassDefinition($className);
         } else {
             if ($compiler->isBundledClass($className)) {
                 $classDefinition = $compiler->getInternalClassDefinition($className);
             } else {
                 throw new CompilerException("Cannot locate class '" . $className . "'", $statement);
             }
         }
     } else {
         if (in_array($className, array('self', 'static'))) {
             $classDefinition = $compilationContext->classDefinition;
         } else {
             if ($className == 'parent') {
                 $classDefinition = $compilationContext->classDefinition;
                 $extendsClass = $classDefinition->getExtendsClass();
                 if (!$extendsClass) {
                     throw new CompilerException('Cannot assign static property "' . $property . '" on parent because class ' . $classDefinition->getCompleteName() . ' does not extend any class', $statement);
                 } else {
                     $classDefinition = $classDefinition->getExtendsClassDefinition();
                 }
             }
         }
     }
     if (!$classDefinition->hasProperty($property)) {
         throw new CompilerException("Class '" . $classDefinition->getCompleteName() . "' does not have a property called: '" . $property . "'", $statement);
     }
     /** @var $propertyDefinition ClassProperty */
     $propertyDefinition = $classDefinition->getProperty($property);
     if (!$propertyDefinition->isStatic()) {
         throw new CompilerException("Cannot access non-static property '" . $classDefinition->getCompleteName() . '::' . $property . "'", $statement);
     }
     if ($propertyDefinition->isPrivate()) {
         if ($classDefinition != $compilationContext->classDefinition) {
             throw new CompilerException("Cannot access private static property '" . $classDefinition->getCompleteName() . '::' . $property . "' out of its declaring context", $statement);
         }
     }
     $codePrinter = $compilationContext->codePrinter;
     $compilationContext->headersManager->add('kernel/object');
     $classEntry = $classDefinition->getClassEntry($compilationContext);
     switch ($resolvedExpr->getType()) {
         case 'null':
             $compilationContext->backend->updateStaticProperty($classEntry, $property, 'null', $compilationContext);
             break;
         case 'int':
         case 'uint':
         case 'long':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $compilationContext->backend->assignLong($tempVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
             $compilationContext->backend->updateStaticProperty($classEntry, $property, $tempVariable, $compilationContext);
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'char':
         case 'uchar':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $compilationContext->backend->assignLong($tempVariable, '\'' . $resolvedExpr->getCode() . '\'', $compilationContext);
             $compilationContext->backend->updateStaticProperty($classEntry, $property, $tempVariable, $compilationContext);
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'double':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $compilationContext->backend->assignDouble($tempVariable, $resolvedExpr->getCode(), $compilationContext);
             $compilationContext->backend->updateStaticProperty($classEntry, $property, $tempVariable, $compilationContext);
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'string':
             switch ($statement['operator']) {
                 case 'assign':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $tempVariable->initVariant($compilationContext);
                     if ($resolvedExpr->getCode()) {
                         $compilationContext->backend->assignString($tempVariable, $resolvedExpr->getCode(), $compilationContext);
                     } else {
                         $codePrinter->output('ZVAL_EMPTY_STRING(' . $tempVariable->getName() . ');');
                     }
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 default:
                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: string", $statement);
             }
             $codePrinter->output('zephir_update_static_property_ce(' . $classEntry . ', SL("' . $property . '"), &' . $tempVariable->getName() . ' TSRMLS_CC);');
             break;
         case 'bool':
             if ($resolvedExpr->getBooleanCode() == '1') {
                 $compilationContext->backend->updateStaticProperty($classEntry, $property, 'true', $compilationContext);
             } else {
                 if ($resolvedExpr->getBooleanCode() == '0') {
                     $compilationContext->backend->updateStaticProperty($classEntry, $property, 'false', $compilationContext);
                 } else {
                     $codePrinter->output('if (' . $resolvedExpr->getBooleanCode() . ') {');
                     $codePrinter->increaseLevel();
                     $compilationContext->backend->updateStaticProperty($classEntry, $property, 'true', $compilationContext);
                     $codePrinter->decreaseLevel();
                     $codePrinter->output('} else {');
                     $codePrinter->increaseLevel();
                     $compilationContext->backend->updateStaticProperty($classEntry, $property, 'false', $compilationContext);
                     $codePrinter->decreaseLevel();
                     $codePrinter->output('}');
                 }
             }
             break;
         case 'empty-array':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $compilationContext->backend->initArray($tempVariable, $compilationContext);
             $compilationContext->backend->updateStaticProperty($classEntry, $property, $tempVariable, $compilationContext);
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'array':
             $compilationContext->backend->updateStaticProperty($classEntry, $property, $resolvedExpr, $compilationContext);
             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->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $compilationContext->backend->assignLong($tempVariable, $variableVariable, $compilationContext);
                     if ($compilationContext->insideCycle) {
                         $propertyCache = $compilationContext->symbolTable->getTempVariableForWrite('zend_property_info', $compilationContext);
                         $propertyCache->setMustInitNull(true);
                         $propertyCache->setReusable(false);
                         $codePrinter->output('zephir_update_static_property_ce_cache(' . $classEntry . ', SL("' . $property . '"), &' . $tempVariable->getName() . ', &' . $propertyCache->getName() . ' TSRMLS_CC);');
                     } else {
                         $compilationContext->backend->updateStaticProperty($classEntry, $property, $tempVariable, $compilationContext);
                     }
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'double':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $compilationContext->backend->assignDouble($tempVariable, $variableVariable, $compilationContext);
                     if ($compilationContext->insideCycle) {
                         $propertyCache = $compilationContext->symbolTable->getTempVariableForWrite('zend_property_info', $compilationContext);
                         $propertyCache->setMustInitNull(true);
                         $propertyCache->setReusable(false);
                         $codePrinter->output('zephir_update_static_property_ce_cache(' . $classEntry . ', SL("' . $property . '"), &' . $tempVariable->getName() . ', &' . $propertyCache->getName() . ' TSRMLS_CC);');
                     } else {
                         $compilationContext->backend->updateStaticProperty($classEntry, $property, $tempVariable, $compilationContext);
                     }
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'bool':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $compilationContext->backend->assignBool($tempVariable, $variableVariable, $compilationContext);
                     $compilationContext->backend->updateStaticProperty($classEntry, $property, $tempVariable, $compilationContext);
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'string':
                     switch ($statement['operator']) {
                         case 'concat-assign':
                             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                             $expression = new Expression(array('type' => 'static-property-access', 'left' => array('value' => $statement['variable']), 'right' => array('value' => $statement['property'])));
                             $expression->setExpectReturn(true, $tempVariable);
                             $expression->compile($compilationContext);
                             $variableVariableCode = $compilationContext->backend->getVariableCode($variableVariable);
                             $tempVariableCode = $compilationContext->backend->getVariableCode($tempVariable);
                             $compilationContext->codePrinter->output('zephir_concat_function(' . $variableVariableCode . ', ' . $tempVariableCode . ', ' . $variableVariableCode . ');');
                             //continue
                         //continue
                         case 'assign':
                             $compilationContext->backend->updateStaticProperty($classEntry, $property, $variableVariable, $compilationContext);
                             if ($variableVariable->isTemporal()) {
                                 $variableVariable->setIdle(true);
                             }
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: string", $statement);
                     }
                     break;
                 case 'variable':
                 case 'array':
                     $compilationContext->backend->updateStaticProperty($classEntry, $property, $variableVariable, $compilationContext);
                     if ($variableVariable->isTemporal()) {
                         $variableVariable->setIdle(true);
                     }
                     break;
                 default:
                     throw new CompilerException("Unknown type " . $variableVariable->getType(), $statement);
             }
             break;
         default:
             throw new CompilerException("Unknown type " . $resolvedExpr->getType(), $statement);
     }
 }
Example #11
0
 /**
  * Resolves an item to be added in an array
  *
  * @param CompiledExpression $exprCompiled
  * @param CompilationContext $compilationContext
  * @return Variable
  */
 public function getArrayValue(CompiledExpression $exprCompiled, CompilationContext $compilationContext)
 {
     $codePrinter = $compilationContext->codePrinter;
     switch ($exprCompiled->getType()) {
         case 'int':
         case 'uint':
         case 'long':
             $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $compilationContext->backend->assignLong($tempVar, $exprCompiled->getCode(), $compilationContext);
             return $tempVar;
         case 'char':
         case 'uchar':
             $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $compilationContext->backend->assignLong($tempVar, '\'' . $exprCompiled->getCode() . '\'', $compilationContext);
             return $tempVar;
         case 'double':
             $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $compilationContext->backend->assignDouble($tempVar, $exprCompiled->getCode(), $compilationContext);
             return $tempVar;
         case 'bool':
             if ($exprCompiled->getCode() == 'true') {
                 return new GlobalConstant('ZEPHIR_GLOBAL(global_true)');
             }
             if ($exprCompiled->getCode() == 'false') {
                 return new GlobalConstant('ZEPHIR_GLOBAL(global_false)');
             }
             $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $compilationContext->backend->assignBool($tempVar, $exprCompiled->getCode(), $compilationContext);
             return $tempVar;
         case 'null':
             return new GlobalConstant('ZEPHIR_GLOBAL(global_null)');
         case 'string':
         case 'ulong':
             $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $compilationContext->backend->assignString($tempVar, $exprCompiled->getCode(), $compilationContext);
             return $tempVar;
         case 'array':
             return $compilationContext->symbolTable->getVariableForRead($exprCompiled->getCode(), $compilationContext, $exprCompiled->getOriginal());
         case 'variable':
             $itemVariable = $compilationContext->symbolTable->getVariableForRead($exprCompiled->getCode(), $compilationContext, $exprCompiled->getOriginal());
             switch ($itemVariable->getType()) {
                 case 'int':
                 case 'uint':
                 case 'long':
                 case 'ulong':
                     $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $compilationContext->backend->assignLong($tempVar, $itemVariable, $compilationContext);
                     return $tempVar;
                 case 'double':
                     $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $compilationContext->backend->assignDouble($tempVar, $itemVariable, $compilationContext);
                     return $tempVar;
                 case 'bool':
                     $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $compilationContext->backend->assignBool($tempVar, $itemVariable, $compilationContext);
                     return $tempVar;
                 case 'string':
                 case 'variable':
                 case 'array':
                     return $itemVariable;
                 default:
                     throw new CompilerException("Unknown " . $itemVariable->getType(), $itemVariable);
             }
             break;
         default:
             throw new CompilerException("Unknown", $exprCompiled);
     }
 }
Example #12
0
 /**
  * Compiles foo[] = {expr}
  *
  * @param $variable
  * @param ZephirVariable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext
  * @param $statement
  * @throws CompilerException
  */
 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->isReadOnly()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is read only", $statement);
     }
     if ($symbolVariable->isLocalOnly()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is local only", $statement);
     }
     if ($symbolVariable->getType() != 'variable') {
         throw new CompilerException("Cannot use variable type: '" . $symbolVariable->getType() . "' as array", $statement);
     }
     if ($symbolVariable->hasDifferentDynamicType(array('undefined', 'array'))) {
         $compilationContext->logger->warning('Possible attempt to append elements on a non-array dynamic variable', 'non-array-append', $statement);
     }
     $codePrinter = $compilationContext->codePrinter;
     $compilationContext->headersManager->add('kernel/array');
     $type = $symbolVariable->getType();
     switch ($type) {
         case 'variable':
             switch ($resolvedExpr->getType()) {
                 case 'null':
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ZEPHIR_GLOBAL(global_null), PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     break;
                 case 'int':
                 case 'uint':
                 case 'long':
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $codePrinter->output('ZVAL_LONG(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     $symbolVariable->setIdle(true);
                     break;
                 case 'double':
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $codePrinter->output('ZVAL_DOUBLE(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     $symbolVariable->setIdle(true);
                     break;
                 case 'bool':
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $codePrinter->output('ZVAL_BOOL(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getBooleanCode() . ');');
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     $symbolVariable->setIdle(true);
                     break;
                 case 'ulong':
                 case 'string':
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $codePrinter->output('ZVAL_STRING(' . $symbolVariable->getName() . ', "' . Utils::addSlashes($resolvedExpr->getCode(), true) . '", 1);');
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     $symbolVariable->setIdle(true);
                     break;
                 case 'array':
                     $exprVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $exprVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     break;
                 case 'variable':
                     $exprVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
                     switch ($exprVariable->getType()) {
                         case 'int':
                         case 'uint':
                         case 'long':
                             $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                             $codePrinter->output('ZVAL_LONG(' . $symbolVariable->getName() . ', ' . $exprVariable->getName() . ');');
                             $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                             $symbolVariable->setIdle(true);
                             break;
                         case 'double':
                             $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                             $codePrinter->output('ZVAL_DOUBLE(' . $symbolVariable->getName() . ', ' . $exprVariable->getName() . ');');
                             $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                             $symbolVariable->setIdle(true);
                             break;
                         case 'bool':
                             $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                             $codePrinter->output('ZVAL_BOOL(' . $symbolVariable->getName() . ', ' . $exprVariable->getName() . ');');
                             $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                             $symbolVariable->setIdle(true);
                             break;
                         case 'variable':
                         case 'string':
                         case 'array':
                             $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $exprVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                             break;
                         default:
                             throw new CompilerException("Unknown type " . $exprVariable->getType(), $statement);
                     }
                     break;
                 default:
                     throw new CompilerException("Unknown type " . $resolvedExpr->getType(), $statement);
             }
             break;
         default:
             throw new CompilerException("Unknown type", $statement);
     }
 }
 /**
  * Compiles foo->{"x"} = {expr}
  *
  * @param string $variable
  * @param ZephirVariable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext
  * @param array $statement
  * @throws CompilerException
  * @throws \Exception
  */
 public function assign($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, array $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'];
     if (!is_string($propertyName)) {
         throw new CompilerException("Expected string to update object property, " . gettype($propertyName) . " received", $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');
     switch ($resolvedExpr->getType()) {
         case 'null':
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, 'null', $compilationContext);
             break;
         case 'int':
         case 'long':
             $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $compilationContext->backend->assignLong($tempVariable, $resolvedExpr->getCode(), $compilationContext);
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
             break;
         case 'string':
             $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $compilationContext->backend->assignString($tempVariable, $resolvedExpr->getCode(), $compilationContext);
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
             break;
         case 'bool':
             if ($resolvedExpr->getBooleanCode() == '1') {
                 $value = 'true';
             } else {
                 if ($resolvedExpr->getBooleanCode() == '0') {
                     $value = 'false';
                 } else {
                     throw new \Exception("?");
                 }
             }
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $value, $compilationContext);
             break;
         case 'empty-array':
             $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $compilationContext->backend->initArray($tempVariable, $compilationContext);
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
             break;
         case 'array':
             $variableVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
             $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $variableVariable, $compilationContext);
             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);
                     $compilationContext->backend->assignLong($tempVariable, $variableVariable, $compilationContext);
                     $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
                     break;
                 case 'bool':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $compilationContext->backend->assignBool($tempVariable, $variableVariable, $compilationContext);
                     $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $tempVariable, $compilationContext);
                     break;
                 case 'string':
                 case 'variable':
                 case 'array':
                     $compilationContext->backend->updateProperty($symbolVariable, $propertyName, $resolvedExpr, $compilationContext);
                     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);
     }
 }
Example #14
0
 /**
  * Compiles foo[] = {expr}
  *
  * @param $variable
  * @param ZephirVariable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext
  * @param $statement
  * @throws CompilerException
  */
 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->isReadOnly()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is read only", $statement);
     }
     if ($symbolVariable->isLocalOnly()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is local only", $statement);
     }
     /**
      * Only dynamic variables and arrays can be used as arrays
      */
     if ($symbolVariable->isNotVariableAndArray()) {
         throw new CompilerException("Cannot use variable type: '" . $symbolVariable->getType() . "' as an array", $statement);
     }
     if ($symbolVariable->getType() == 'variable') {
         if ($symbolVariable->hasDifferentDynamicType(array('undefined', 'array'))) {
             $compilationContext->logger->warning('Possible attempt to append elements on a non-array dynamic variable', 'non-array-append', $statement);
         }
     }
     $codePrinter = $compilationContext->codePrinter;
     $compilationContext->headersManager->add('kernel/array');
     $type = $symbolVariable->getType();
     switch ($type) {
         case 'array':
         case 'variable':
             switch ($resolvedExpr->getType()) {
                 case 'null':
                     $compilationContext->backend->addArrayEntry($symbolVariable, null, 'null', $compilationContext, $statement);
                     break;
                 case 'int':
                 case 'uint':
                 case 'long':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $compilationContext->backend->assignLong($tempVariable, $resolvedExpr->getCode(), $compilationContext);
                     $compilationContext->backend->addArrayEntry($symbolVariable, null, $tempVariable, $compilationContext, $statement);
                     $tempVariable->setIdle(true);
                     break;
                 case 'double':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $compilationContext->backend->assignDouble($tempVariable, $resolvedExpr->getCode(), $compilationContext);
                     $compilationContext->backend->addArrayEntry($symbolVariable, null, $tempVariable, $compilationContext, $statement);
                     $tempVariable->setIdle(true);
                     break;
                 case 'bool':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $compilationContext->backend->assignBool($tempVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
                     $compilationContext->backend->addArrayEntry($symbolVariable, null, $tempVariable, $compilationContext, $statement);
                     $tempVariable->setIdle(true);
                     break;
                 case 'ulong':
                 case 'string':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $compilationContext->backend->assignString($tempVariable, $resolvedExpr->getBooleanCode(), $compilationContext);
                     $compilationContext->backend->addArrayEntry($symbolVariable, null, $tempVariable, $compilationContext, $statement);
                     $tempVariable->setIdle(true);
                     break;
                 case 'array':
                     $exprVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
                     $compilationContext->backend->addArrayEntry($symbolVariable, null, $exprVariable, $compilationContext, $statement);
                     break;
                 case 'variable':
                     $exprVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
                     switch ($exprVariable->getType()) {
                         case 'int':
                         case 'uint':
                         case 'long':
                             $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                             $compilationContext->backend->assignLong($tempVariable, $exprVariable, $compilationContext);
                             $compilationContext->backend->addArrayEntry($symbolVariable, null, $tempVariable, $compilationContext, $statement);
                             $tempVariable->setIdle(true);
                             break;
                         case 'double':
                             $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                             $compilationContext->backend->assignDouble($tempVariable, $exprVariable, $compilationContext);
                             $compilationContext->backend->addArrayEntry($symbolVariable, null, $tempVariable, $compilationContext, $statement);
                             $tempVariable->setIdle(true);
                             break;
                         case 'bool':
                             $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                             $compilationContext->backend->assignBool($tempVariable, $exprVariable, $compilationContext);
                             $compilationContext->backend->addArrayEntry($symbolVariable, null, $tempVariable, $compilationContext, $statement);
                             $tempVariable->setIdle(true);
                             break;
                         case 'variable':
                         case 'string':
                         case 'array':
                             $compilationContext->backend->addArrayEntry($symbolVariable, null, $exprVariable, $compilationContext, $statement);
                             break;
                         default:
                             throw new CompilerException("Unknown type: " . $exprVariable->getType(), $statement);
                     }
                     break;
                 default:
                     throw new CompilerException("Unknown type: " . $resolvedExpr->getType(), $statement);
             }
             break;
         default:
             throw new CompilerException("Unknown type: " . $type, $statement);
     }
 }
Example #15
0
 /**
  * @param CompiledExpression $compiledExpression
  * @param array $expression
  * @return CompiledExpression
  */
 protected function passNativeFCall($compiledExpression, $expression)
 {
     return new CompiledExpression('double', $this->getFunctionName() . '(' . $compiledExpression->getCode() . ')', $expression);
 }
Example #16
0
 /**
  * Compiles x->y[] = foo
  *
  * @param string $variable
  * @param ZephirVariable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext
  * @param array $statement
  * @throws CompilerException
  */
 public function assign($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, array $statement)
 {
     if (!$symbolVariable->isInitialized()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is not initialized", $statement);
     }
     if (!$symbolVariable->isVariable()) {
         throw new CompilerException("Attempt to use variable type: " . $symbolVariable->getType() . " as object", $statement);
     }
     $codePrinter = $compilationContext->codePrinter;
     $property = $statement['property'];
     $compilationContext->headersManager->add('kernel/object');
     /**
      * Check if the variable to update is defined
      */
     if ($symbolVariable->getRealName() == 'this') {
         $classDefinition = $compilationContext->classDefinition;
         if (!$classDefinition->hasProperty($property)) {
             throw new CompilerException("Class '" . $classDefinition->getCompleteName() . "' does not have a property called: '" . $property . "'", $statement);
         }
         $propertyDefinition = $classDefinition->getProperty($property);
     } else {
         /**
          * If we know the class related to a variable we could check if the property
          * is defined on that class
          */
         if ($symbolVariable->hasAnyDynamicType('object')) {
             $classType = current($symbolVariable->getClassTypes());
             $compiler = $compilationContext->compiler;
             if ($compiler->isClass($classType)) {
                 $classDefinition = $compiler->getClassDefinition($classType);
                 if (!$classDefinition) {
                     throw new CompilerException("Cannot locate class definition for class: " . $classType, $statement);
                 }
                 if (!$classDefinition->hasProperty($property)) {
                     throw new CompilerException("Class '" . $classType . "' does not have a property called: '" . $property . "'", $statement);
                 }
             }
         }
     }
     switch ($resolvedExpr->getType()) {
         case 'null':
             $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, 'null', $compilationContext);
             break;
         case 'bool':
             $codePrinter->output('if (' . $resolvedExpr->getBooleanCode() . ') {');
             $codePrinter->increaseLevel();
             $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, 'true', $compilationContext);
             $codePrinter->decreaseLevel();
             $codePrinter->output('} else {');
             $codePrinter->increaseLevel();
             $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, 'false', $compilationContext);
             $codePrinter->decreaseLevel();
             $codePrinter->output('}');
             break;
         case 'char':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $compilationContext->backend->assignLong($tempVariable, '\'' . $resolvedExpr->getCode() . '\'', $compilationContext);
             $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, $tempVariable, $compilationContext);
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'int':
         case 'long':
         case 'uint':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $compilationContext->backend->assignLong($tempVariable, $resolvedExpr->getCode(), $compilationContext);
             $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, $tempVariable, $compilationContext);
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'double':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $compilationContext->backend->assignDouble($tempVariable, $resolvedExpr->getCode(), $compilationContext);
             $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, $tempVariable, $compilationContext);
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'string':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $compilationContext->backend->assignString($tempVariable, $resolvedExpr->getCode(), $compilationContext);
             $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, $tempVariable, $compilationContext);
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'array':
             $variableExpr = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
             $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, $variableExpr, $compilationContext);
             break;
         case 'variable':
             $variableExpr = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
             switch ($variableExpr->getType()) {
                 case 'int':
                 case 'long':
                 case 'uint':
                 case 'char':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $compilationContext->backend->assignLong($tempVariable, $variableExpr, $compilationContext);
                     $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, $tempVariable, $compilationContext);
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'double':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $compilationContext->backend->assignDouble($tempVariable, $variableExpr, $compilationContext);
                     $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, $tempVariable, $compilationContext);
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'bool':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $compilationContext->backend->assignBool($tempVariable, $variableExpr, $compilationContext);
                     $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, $tempVariable, $compilationContext);
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'variable':
                 case 'string':
                 case 'array':
                 case 'resource':
                 case 'object':
                     $compilationContext->backend->assignArrayProperty($symbolVariable, $property, null, $variableExpr, $compilationContext);
                     if ($variableExpr->isTemporal()) {
                         $variableExpr->setIdle(true);
                     }
                     break;
                 default:
                     throw new CompilerException("Variable: " . $variableExpr->getType() . " cannot be appended to array property", $statement);
             }
             break;
         default:
             throw new CompilerException("Expression: " . $resolvedExpr->getType() . " cannot be appended to array property", $statement);
     }
 }
Example #17
0
 /**
  * Compiles x->y[z] = {expr} (single offset assignment)
  *
  * @param string $variable
  * @param ZephirVariable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext
  * @param array $statement
  * @throws CompilerException
  */
 protected function _assignPropertyArraySingleIndex($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, array $statement)
 {
     $codePrinter = $compilationContext->codePrinter;
     $property = $statement['property'];
     $compilationContext->headersManager->add('kernel/object');
     /**
      * Only string/variable/int
      */
     $indexExpression = new Expression($statement['index-expr'][0]);
     $resolvedIndex = $indexExpression->compile($compilationContext);
     switch ($resolvedIndex->getType()) {
         case 'string':
         case 'int':
         case 'uint':
         case 'ulong':
         case 'long':
         case 'variable':
             break;
         default:
             throw new CompilerException("Expression: " . $resolvedIndex->getType() . " cannot be used as index without cast", $statement);
     }
     if ($resolvedIndex->getType() == 'variable') {
         $indexVariable = $compilationContext->symbolTable->getVariableForRead($resolvedIndex->getCode(), $compilationContext, $statement);
         switch ($indexVariable->getType()) {
             case 'string':
             case 'int':
             case 'uint':
             case 'ulong':
             case 'long':
             case 'variable':
                 break;
             default:
                 throw new CompilerException("Variable: " . $indexVariable->getType() . " cannot be used as index without cast", $statement);
         }
         if ($indexVariable->getType() == 'variable') {
             if ($indexVariable->hasDifferentDynamicType(array('undefined', 'int', 'string'))) {
                 $compilationContext->logger->warning('Possible attempt to use non string/long dynamic variable as array index', 'invalid-array-offset', $statement);
             }
         }
     }
     switch ($resolvedIndex->getType()) {
         case 'int':
         case 'uint':
         case 'long':
             $indexVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
             $codePrinter->output('ZVAL_LONG(' . $indexVariable->getName() . ', ' . $resolvedIndex->getCode() . ');');
             break;
         case 'string':
             $indexVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
             $codePrinter->output('ZVAL_STRING(' . $indexVariable->getName() . ', "' . $resolvedIndex->getCode() . '", 1);');
             break;
         case 'variable':
             $variableIndex = $compilationContext->symbolTable->getVariableForRead($resolvedIndex->getCode(), $compilationContext, $statement['index-expr']);
             switch ($variableIndex->getType()) {
                 case 'int':
                 case 'uint':
                 case 'long':
                     $indexVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $codePrinter->output('ZVAL_LONG(' . $indexVariable->getName() . ', ' . $variableIndex->getName() . ');');
                     break;
             }
             break;
     }
     /**
      * Check if the variable to update is defined
      */
     if ($symbolVariable->getRealName() == 'this') {
         $classDefinition = $compilationContext->classDefinition;
         if (!$classDefinition->hasProperty($property)) {
             throw new CompilerException("Class '" . $classDefinition->getCompleteName() . "' does not have a property called: '" . $property . "'", $statement);
         }
         $propertyDefinition = $classDefinition->getProperty($property);
     } else {
         /**
          * If we know the class related to a variable we could check if the property
          * is defined on that class
          */
         if ($symbolVariable->hasAnyDynamicType('object')) {
             $classType = current($symbolVariable->getClassTypes());
             $compiler = $compilationContext->compiler;
             if ($compiler->isClass($classType)) {
                 $classDefinition = $compiler->getClassDefinition($classType);
                 if (!$classDefinition) {
                     throw new CompilerException("Cannot locate class definition for class: " . $classType, $statement);
                 }
                 if (!$classDefinition->hasProperty($property)) {
                     throw new CompilerException("Class '" . $classType . "' does not have a property called: '" . $property . "'", $statement);
                 }
             }
         }
     }
     switch ($indexVariable->getType()) {
         case 'variable':
         case 'string':
             switch ($resolvedExpr->getType()) {
                 case 'null':
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ZEPHIR_GLOBAL(global_null) TSRMLS_CC);');
                     break;
                 case 'bool':
                     $booleanCode = $resolvedExpr->getBooleanCode();
                     if ($booleanCode == '1') {
                         $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ZEPHIR_GLOBAL(global_true) TSRMLS_CC);');
                     } elseif ($booleanCode == '0') {
                         $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ZEPHIR_GLOBAL(global_false) TSRMLS_CC);');
                     } else {
                         $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                         $codePrinter->output('ZVAL_BOOL(' . $tempVariable->getName() . ', ' . $booleanCode . ');');
                         $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     }
                     break;
                 case 'int':
                 case 'long':
                 case 'uint':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     break;
                 case 'char':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', \'' . $resolvedExpr->getCode() . '\');');
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     break;
                 case 'double':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_DOUBLE(' . $tempVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     break;
                 case 'string':
                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_STRING(' . $tempVariable->getName() . ', "' . $resolvedExpr->getCode() . '", 1);');
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     break;
                 case 'array':
                     $variableExpr = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement['index-expr']);
                     $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $variableExpr->getName() . ' TSRMLS_CC);');
                     break;
                 case 'variable':
                     $variableExpr = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement['index-expr']);
                     switch ($variableExpr->getType()) {
                         case 'bool':
                             $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                             $codePrinter->output('ZVAL_BOOL(' . $tempVariable->getName() . ', ' . $variableExpr->getName() . ');');
                             $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                             break;
                         case 'int':
                         case 'long':
                             $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                             $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $variableExpr->getName() . ');');
                             $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $tempVariable->getName() . ' TSRMLS_CC);');
                             break;
                         case 'variable':
                         case 'string':
                         case 'array':
                             $codePrinter->output('zephir_update_property_array(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $indexVariable->getName() . ', ' . $variableExpr->getName() . ' TSRMLS_CC);');
                             if ($variableExpr->isTemporal()) {
                                 $variableExpr->setIdle(true);
                             }
                             break;
                         default:
                             throw new CompilerException("Cannot update variable type: " . $variableExpr->getType(), $statement);
                     }
                     break;
                 default:
                     throw new CompilerException("Variable index: " . $indexVariable->getType() . " cannot be updated into array property", $statement);
             }
             break;
         default:
             throw new CompilerException("Index: " . $resolvedIndex->getType() . " cannot be updated into array property", $statement);
     }
 }
Example #18
0
 /**
  * Resolves an item to be added in an array
  *
  * @param CompiledExpression $exprCompiled
  * @param CompilationContext $compilationContext
  * @return Variable
  */
 public function getArrayValue($exprCompiled, CompilationContext $compilationContext)
 {
     $codePrinter = $compilationContext->codePrinter;
     switch ($exprCompiled->getType()) {
         case 'int':
         case 'uint':
         case 'long':
             $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $codePrinter->output('ZVAL_LONG(' . $tempVar->getName() . ', ' . $exprCompiled->getCode() . ');');
             return $tempVar;
         case 'char':
         case 'uchar':
             $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $codePrinter->output('ZVAL_LONG(' . $tempVar->getName() . ', \'' . $exprCompiled->getCode() . '\');');
             return $tempVar;
         case 'double':
             $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $codePrinter->output('ZVAL_DOUBLE(' . $tempVar->getName() . ', ' . $exprCompiled->getCode() . ');');
             return $tempVar;
         case 'bool':
             if ($exprCompiled->getCode() == 'true') {
                 return new GlobalConstant('ZEPHIR_GLOBAL(global_true)');
             } else {
                 if ($exprCompiled->getCode() == 'false') {
                     return new GlobalConstant('ZEPHIR_GLOBAL(global_false)');
                 } else {
                     throw new Exception('?');
                 }
             }
             break;
         case 'null':
             return new GlobalConstant('ZEPHIR_GLOBAL(global_null)');
         case 'string':
         case 'ulong':
             $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
             $codePrinter->output('ZVAL_STRING(' . $tempVar->getName() . ', "' . $exprCompiled->getCode() . '", 1);');
             return $tempVar;
         case 'array':
             return $compilationContext->symbolTable->getVariableForRead($exprCompiled->getCode(), $compilationContext, $exprCompiled->getOriginal());
         case 'variable':
             $itemVariable = $compilationContext->symbolTable->getVariableForRead($exprCompiled->getCode(), $compilationContext, $exprCompiled->getOriginal());
             switch ($itemVariable->getType()) {
                 case 'int':
                 case 'uint':
                 case 'long':
                 case 'ulong':
                     $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_LONG(' . $tempVar->getName() . ', ' . $itemVariable->getName() . ');');
                     return $tempVar;
                 case 'double':
                     $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_DOUBLE(' . $tempVar->getName() . ', ' . $itemVariable->getName() . ');');
                     return $tempVar;
                 case 'bool':
                     $tempVar = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                     $codePrinter->output('ZVAL_BOOL(' . $tempVar->getName() . ', ' . $itemVariable->getName() . ');');
                     return $tempVar;
                 case 'string':
                 case 'variable':
                 case 'array':
                     return $itemVariable;
                 default:
                     throw new CompilerException("Unknown " . $itemVariable->getType(), $itemVariable);
             }
             break;
         default:
             throw new CompilerException("Unknown", $exprCompiled);
     }
 }
Example #19
0
 /**
  * Compiles x->y[] = foo
  *
  * @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("Attempt to use variable type: " . $symbolVariable->getType() . " as object", $statement);
     }
     $codePrinter = $compilationContext->codePrinter;
     $property = $statement['property'];
     $compilationContext->headersManager->add('kernel/object');
     /* @todo check whether property really does exist */
     switch ($resolvedExpr->getType()) {
         case 'null':
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ZEPHIR_GLOBAL(global_null) TSRMLS_CC);');
             break;
         case 'bool':
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), (' . $resolvedExpr->getBooleanCode() . ') ? ZEPHIR_GLOBAL(global_true) : ZEPHIR_GLOBAL(global_false) TSRMLS_CC);');
             break;
         case 'char':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', \'' . $resolvedExpr->getCode() . '\');');
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'int':
         case 'long':
         case 'uint':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'double':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $codePrinter->output('ZVAL_DOUBLE(' . $tempVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'string':
             $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
             $codePrinter->output('ZVAL_STRING(' . $tempVariable->getName() . ', "' . $resolvedExpr->getCode() . '", 1);');
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
             if ($tempVariable->isTemporal()) {
                 $tempVariable->setIdle(true);
             }
             break;
         case 'array':
             $variableExpr = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
             $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $variableExpr->getName() . ' TSRMLS_CC);');
             break;
         case 'variable':
             $variableExpr = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
             switch ($variableExpr->getType()) {
                 case 'int':
                 case 'long':
                 case 'uint':
                 case 'char':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $variableExpr->getName() . ');');
                     $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'double':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $codePrinter->output('ZVAL_DOUBLE(' . $tempVariable->getName() . ', ' . $variableExpr->getName() . ');');
                     $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'bool':
                     $tempVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext, true);
                     $codePrinter->output('ZVAL_BOOL(' . $tempVariable->getName() . ', ' . $variableExpr->getName() . ');');
                     $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $tempVariable->getName() . ' TSRMLS_CC);');
                     if ($tempVariable->isTemporal()) {
                         $tempVariable->setIdle(true);
                     }
                     break;
                 case 'variable':
                 case 'string':
                 case 'array':
                 case 'resource':
                 case 'object':
                     $codePrinter->output('zephir_update_property_array_append(' . $symbolVariable->getName() . ', SL("' . $property . '"), ' . $variableExpr->getName() . ' TSRMLS_CC);');
                     if ($variableExpr->isTemporal()) {
                         $variableExpr->setIdle(true);
                     }
                     break;
                 default:
                     throw new CompilerException("Variable: " . $variableExpr->getType() . " cannot be appended to array property", $statement);
             }
             break;
         default:
             throw new CompilerException("Expression: " . $resolvedExpr->getType() . " cannot be appended to array property", $statement);
     }
 }