isLocalOnly() public method

Checks if the variable is local-only scoped
public isLocalOnly ( ) : boolean
return boolean
Exemplo n.º 1
0
 /**
  * Compiles obj->x++
  *
  * @param string $variable
  * @param string $property
  * @param ZephirVariable $symbolVariable
  * @param CompilationContext $compilationContext
  * @param array $statement
  */
 public function assign($variable, $property, ZephirVariable $symbolVariable, CompilationContext $compilationContext, $statement)
 {
     if (!$symbolVariable->isInitialized()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is not initialized", $statement);
     }
     /**
      * Arrays must be stored in the HEAP
      */
     if ($symbolVariable->isLocalOnly()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is local only", $statement);
     }
     if (!$symbolVariable->isInitialized()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is not initialized", $statement);
     }
     /**
      * Only dynamic variables can be used as arrays
      */
     if ($symbolVariable->getType() != 'variable') {
         throw new CompilerException("Cannot use variable type: '" . $symbolVariable->getType() . "' as array", $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 increment non-object dynamic variable', 'non-object-update', $statement);
     }
     $compilationContext->headersManager->add('kernel/object');
     $compilationContext->codePrinter->output('RETURN_ON_FAILURE(zephir_property_incr(' . $symbolVariable->getName() . ', SL("' . $property . '") TSRMLS_CC));');
 }
Exemplo n.º 2
0
 /**
  * Compiles obj->x++
  *
  * @param string $variable
  * @param string $property
  * @param ZephirVariable $symbolVariable
  * @param CompilationContext $compilationContext
  * @param array $statement
  */
 public function assign($variable, $property, ZephirVariable $symbolVariable, CompilationContext $compilationContext, $statement)
 {
     if (!$symbolVariable->isInitialized()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is not initialized", $statement);
     }
     /**
      * Arrays must be stored in the HEAP
      */
     if ($symbolVariable->isLocalOnly()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is local only", $statement);
     }
     if (!$symbolVariable->isInitialized()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is not initialized", $statement);
     }
     /**
      * Only dynamic variables can be used as arrays
      */
     if (!$symbolVariable->isVariable()) {
         throw new CompilerException("Cannot use variable type: '" . $symbolVariable->getType() . "' as array", $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 increment non-object dynamic variable', 'non-object-update', $statement);
     }
     /**
      * 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);
                 }
             }
         }
     }
     $compilationContext->headersManager->add('kernel/object');
     $compilationContext->codePrinter->output('RETURN_ON_FAILURE(zephir_property_incr(' . $symbolVariable->getName() . ', SL("' . $property . '") TSRMLS_CC));');
 }
Exemplo n.º 3
0
 /**
  * Compiles x--
  *
  * @param string $variable
  * @param ZephirVariable $symbolVariable
  * @param CompilationContext $compilationContext
  * @param array $statement
  */
 public function assign($variable, ZephirVariable $symbolVariable, 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);
     }
     $codePrinter = $compilationContext->codePrinter;
     switch ($symbolVariable->getType()) {
         case 'int':
         case 'uint':
         case 'long':
         case 'ulong':
         case 'double':
         case 'char':
         case 'uchar':
             $codePrinter->output($variable . '--;');
             break;
         case 'variable':
             /**
              * Variable is probably not initialized here
              */
             if ($symbolVariable->hasAnyDynamicType('unknown')) {
                 throw new CompilerException("Attempt to increment uninitialized variable", $statement);
             }
             /**
              * Decrement non-numeric variables could be expensive
              */
             if (!$symbolVariable->hasAnyDynamicType(array('undefined', 'int', 'long', 'double', 'uint'))) {
                 $compilationContext->logger->warning('Possible attempt to decrement non-numeric dynamic variable', 'non-valid-decrement', $statement);
             }
             $compilationContext->headersManager->add('kernel/operators');
             if ($symbolVariable->isLocalOnly()) {
                 $codePrinter->output('zephir_decrement(&' . $variable . ');');
             } else {
                 $symbolVariable->separate($compilationContext);
                 $codePrinter->output('zephir_decrement(' . $variable . ');');
             }
             break;
         default:
             throw new CompilerException("Cannot decrement variable: " . $symbolVariable->getType(), $statement);
     }
 }
Exemplo n.º 4
0
 /**
  * Compiles x++
  *
  * @param string $variable
  * @param ZephirVariable $symbolVariable
  * @param CompilationContext $compilationContext
  * @param array $statement
  *
  * @throws CompilerException
  */
 public function assign($variable, ZephirVariable $symbolVariable, CompilationContext $compilationContext, $statement)
 {
     if (!$symbolVariable->isInitialized()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is not initialized", $statement);
     }
     if ($symbolVariable->isReadOnly()) {
         /**
          * @TODO implement increment of objects members
          */
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is read only", $statement);
     }
     $codePrinter =& $compilationContext->codePrinter;
     switch ($symbolVariable->getType()) {
         case 'int':
         case 'uint':
         case 'long':
         case 'ulong':
         case 'double':
         case 'char':
         case 'uchar':
             $codePrinter->output($variable . '++;');
             break;
         case 'variable':
             /**
              * Update non-numeric dynamic variables could be expensive
              */
             if (!$symbolVariable->hasAnyDynamicType(array('undefined', 'long', 'double'))) {
                 $compilationContext->logger->warning('Possible attempt to increment non-numeric dynamic variable', 'non-valid-increment', $statement);
             }
             $compilationContext->headersManager->add('kernel/operators');
             if (!$symbolVariable->isLocalOnly()) {
                 $symbolVariable->separate($compilationContext);
             }
             $symbol = $compilationContext->backend->getVariableCode($symbolVariable);
             $codePrinter->output('zephir_increment(' . $symbol . ');');
             break;
         default:
             throw new CompilerException("Cannot increment: " . $symbolVariable->getType(), $statement);
     }
 }
Exemplo n.º 5
0
 public function generateInitCode(&$groupVariables, $type, $pointer, Variable $variable)
 {
     $isComplex = $type == 'variable' || $type == 'string' || $type == 'array' || $type == 'resource' || $type == 'callable' || $type == 'object';
     if ($isComplex && !$variable->isDoublePointer()) {
         /* && $variable->mustInitNull() */
         $groupVariables[] = $variable->getName();
         if ($variable->getRealname() == '__$null') {
             return "\t" . 'ZVAL_NULL(&' . $variable->getName() . ');';
         } else {
             if ($variable->getRealname() == '__$true') {
                 return "\t" . 'ZVAL_BOOL(&' . $variable->getName() . ', 1);';
             } else {
                 if ($variable->getRealname() == '__$false') {
                     return "\t" . 'ZVAL_BOOL(&' . $variable->getName() . ', 0);';
                 }
             }
         }
         return "\t" . 'ZVAL_UNDEF(&' . $variable->getName() . ');';
     }
     if ($variable->isLocalOnly()) {
         $groupVariables[] = $variable->getName();
         return;
     }
     if ($variable->isDoublePointer()) {
         /* Double pointers for ZE3 are used as zval * */
         $ptr = $isComplex ? $pointer : $pointer . $pointer;
         if ($variable->mustInitNull()) {
             $groupVariables[] = $ptr . $variable->getName() . ' = NULL';
         } else {
             $groupVariables[] = $ptr . $variable->getName();
         }
         return;
     }
     $defaultValue = $variable->getDefaultInitValue();
     if ($defaultValue !== null) {
         switch ($type) {
             case 'variable':
             case 'string':
             case 'array':
             case 'resource':
             case 'callable':
             case 'object':
                 $groupVariables[] = $pointer . $variable->getName();
                 break;
             case 'char':
                 if (strlen($defaultValue) > 4) {
                     if (strlen($defaultValue) > 10) {
                         throw new CompilerException("Invalid char literal: '" . substr($defaultValue, 0, 10) . "...'", $variable->getOriginal());
                     } else {
                         throw new CompilerException("Invalid char literal: '" . $defaultValue . "'", $variable->getOriginal());
                     }
                 }
                 /* no break */
             /* no break */
             default:
                 $groupVariables[] = $pointer . $variable->getName() . ' = ' . $defaultValue;
                 break;
         }
         return;
     }
     if ($variable->mustInitNull() && $pointer) {
         $groupVariables[] = $pointer . $variable->getName() . ' = NULL';
         return;
     }
     $groupVariables[] = $pointer . $variable->getName();
 }
Exemplo n.º 6
0
 public function generateInitCode(&$groupVariables, $type, $pointer, Variable $variable)
 {
     $isComplex = $type == 'variable' || $type == 'string' || $type == 'array' || $type == 'resource' || $type == 'callable' || $type == 'object';
     if ($isComplex && $variable->mustInitNull()) {
         if ($variable->isLocalOnly()) {
             $groupVariables[] = $variable->getName() . ' = zval_used_for_init';
         } else {
             if ($variable->isDoublePointer()) {
                 $groupVariables[] = $pointer . $pointer . $variable->getName() . ' = NULL';
             } else {
                 $groupVariables[] = $pointer . $variable->getName() . ' = NULL';
             }
         }
         return;
     }
     if ($variable->isLocalOnly()) {
         $groupVariables[] = $variable->getName();
         return;
     }
     if ($variable->isDoublePointer()) {
         if ($variable->mustInitNull()) {
             $groupVariables[] = $pointer . $pointer . $variable->getName() . ' = NULL';
         } else {
             $groupVariables[] = $pointer . $pointer . $variable->getName();
         }
         return;
     }
     $defaultValue = $variable->getDefaultInitValue();
     if ($defaultValue !== null) {
         switch ($type) {
             case 'variable':
             case 'string':
             case 'array':
             case 'resource':
             case 'callable':
             case 'object':
                 $groupVariables[] = $pointer . $variable->getName();
                 break;
             case 'char':
                 if (strlen($defaultValue) > 4) {
                     if (strlen($defaultValue) > 10) {
                         throw new CompilerException("Invalid char literal: '" . substr($defaultValue, 0, 10) . "...'", $variable->getOriginal());
                     } else {
                         throw new CompilerException("Invalid char literal: '" . $defaultValue . "'", $variable->getOriginal());
                     }
                 }
                 /* no break */
             /* no break */
             default:
                 $groupVariables[] = $pointer . $variable->getName() . ' = ' . $defaultValue;
                 break;
         }
         return;
     }
     if ($variable->mustInitNull() && $pointer) {
         $groupVariables[] = $pointer . $variable->getName() . ' = NULL';
         return;
     }
     $groupVariables[] = $pointer . $variable->getName();
 }
Exemplo n.º 7
0
 /**
  * Compiles foo[y] = {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)
 {
     /**
      * Arrays must be stored in the HEAP
      */
     if ($symbolVariable->isLocalOnly()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is local only", $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 can be used as arrays
      */
     if ($symbolVariable->isNotVariableAndArray()) {
         throw new CompilerException("Cannot use variable type: '" . $symbolVariable->getType() . "' as array", $statement);
     }
     if ($symbolVariable->getType() == 'variable') {
         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', 'array', 'null'))) {
             $compilationContext->logger->warning('Possible attempt to update index on a non-array dynamic variable', 'non-array-update', $statement);
         }
     }
     /**
      * Choose one-offset or multiple-offset functions
      */
     if (count($statement['index-expr']) == 1) {
         $this->_assignArrayIndexSingle($variable, $symbolVariable, $resolvedExpr, $compilationContext, $statement);
     } else {
         $this->_assignArrayIndexMultiple($variable, $symbolVariable, $resolvedExpr, $compilationContext, $statement);
     }
 }
Exemplo n.º 8
0
 /**
  * Compiles foo = {expr}
  * Changes the value of a mutable variable
  *
  * @param $variable
  * @param Variable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param ReadDetector $readDetector
  * @param CompilationContext $compilationContext
  * @param $statement
  * @throws CompilerException
  */
 public function assign($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, ReadDetector $readDetector, CompilationContext $compilationContext, $statement)
 {
     if ($symbolVariable->isReadOnly()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is read only", $statement);
     }
     $codePrinter = $compilationContext->codePrinter;
     /**
      * Only initialize variables if it's direct assignment
      */
     if ($statement['operator'] == 'assign') {
         $symbolVariable->setIsInitialized(true, $compilationContext, $statement);
     } else {
         if (!$symbolVariable->isInitialized()) {
             throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is not initialized", $statement);
         }
     }
     /**
      * Set the assigned value to the variable as a CompiledExpression
      * We could use this expression for further analysis
      */
     $symbolVariable->setPossibleValue($resolvedExpr, $compilationContext);
     $type = $symbolVariable->getType();
     switch ($type) {
         case 'int':
         case 'uint':
         case 'long':
         case 'ulong':
         case 'char':
         case 'uchar':
             switch ($resolvedExpr->getType()) {
                 case 'null':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = 0;');
                             break;
                         case 'add-assign':
                             $codePrinter->output($variable . ' += 0;');
                             break;
                         case 'sub-assign':
                             $codePrinter->output($variable . ' -= 0;');
                             break;
                         case 'mul-assign':
                             $codePrinter->output($variable . ' *= 0;');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: int", $statement);
                     }
                     break;
                 case 'int':
                 case 'uint':
                 case 'long':
                 case 'ulong':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = ' . $resolvedExpr->getCode() . ';');
                             break;
                         case 'add-assign':
                             $codePrinter->output($variable . ' += ' . $resolvedExpr->getCode() . ';');
                             break;
                         case 'sub-assign':
                             $codePrinter->output($variable . ' -= ' . $resolvedExpr->getCode() . ';');
                             break;
                         case 'mul-assign':
                             $codePrinter->output($variable . ' *= ' . $resolvedExpr->getCode() . ';');
                             break;
                         case 'div-assign':
                             $codePrinter->output($variable . ' /= ' . $resolvedExpr->getCode() . ';');
                             break;
                         case 'mod-assign':
                             $codePrinter->output($variable . ' %= ' . $resolvedExpr->getCode() . ';');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: int", $statement);
                     }
                     break;
                 case 'char':
                 case 'uchar':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = \'' . $resolvedExpr->getCode() . '\';');
                             break;
                         case 'add-assign':
                             $codePrinter->output($variable . ' += \'' . $resolvedExpr->getCode() . '\';');
                             break;
                         case 'sub-assign':
                             $codePrinter->output($variable . ' -= \'' . $resolvedExpr->getCode() . '\';');
                             break;
                         case 'mul-assign':
                             $codePrinter->output($variable . ' *= \'' . $resolvedExpr->getCode() . '\';');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: int", $statement);
                     }
                     break;
                 case 'double':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = (long) (' . $resolvedExpr->getCode() . ');');
                             break;
                         case 'add-assign':
                             $codePrinter->output($variable . ' += (long) (' . $resolvedExpr->getCode() . ');');
                             break;
                         case 'sub-assign':
                             $codePrinter->output($variable . ' -= (long) (' . $resolvedExpr->getCode() . ');');
                             break;
                         case 'mul-assign':
                             $codePrinter->output($variable . ' *= (long) (' . $resolvedExpr->getCode() . ');');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: int", $statement);
                     }
                     break;
                 case 'bool':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = ' . $resolvedExpr->getBooleanCode() . ';');
                             break;
                         case 'add-assign':
                             $codePrinter->output($variable . ' += ' . $resolvedExpr->getBooleanCode() . ';');
                             break;
                         case 'sub-assign':
                             $codePrinter->output($variable . ' -= ' . $resolvedExpr->getBooleanCode() . ';');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: int", $statement);
                     }
                     break;
                 case 'variable':
                     $itemVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
                     switch ($itemVariable->getType()) {
                         case 'int':
                         case 'uint':
                         case 'long':
                         case 'ulong':
                         case 'bool':
                         case 'char':
                         case 'uchar':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $codePrinter->output($variable . ' = ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'add-assign':
                                     $codePrinter->output($variable . ' += ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'sub-assign':
                                     $codePrinter->output($variable . ' -= ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'mul-assign':
                                     $codePrinter->output($variable . ' *= ' . $itemVariable->getName() . ';');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: int", $statement);
                             }
                             break;
                         case 'double':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $codePrinter->output($variable . ' = (long) ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'add-assign':
                                     $codePrinter->output($variable . ' += (long) ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'sub-assign':
                                     $codePrinter->output($variable . ' -= (long) ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'mul-assign':
                                     $codePrinter->output($variable . ' *= (long) ' . $itemVariable->getName() . ';');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: int", $statement);
                             }
                             break;
                         case 'variable':
                             $compilationContext->headersManager->add('kernel/operators');
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $codePrinter->output($variable . ' = zephir_get_numberval(' . $resolvedExpr->resolve(null, $compilationContext) . ');');
                                     break;
                                 case 'add-assign':
                                     $codePrinter->output($variable . ' += zephir_get_numberval(' . $resolvedExpr->resolve(null, $compilationContext) . ');');
                                     break;
                                 case 'sub-assign':
                                     $codePrinter->output($variable . ' -= zephir_get_numberval(' . $resolvedExpr->resolve(null, $compilationContext) . ');');
                                     break;
                                 case 'mul-assign':
                                     $codePrinter->output($variable . ' *= zephir_get_numberval(' . $resolvedExpr->resolve(null, $compilationContext) . ');');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: int", $statement);
                             }
                             break;
                         default:
                             throw new CompilerException("Unknown type: " . $itemVariable->getType(), $statement);
                     }
                     break;
                 default:
                     throw new CompilerException("Value type '" . $resolvedExpr->getType() . "' cannot be assigned to variable: int", $statement);
             }
             break;
         case 'double':
             switch ($resolvedExpr->getType()) {
                 case 'null':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = 0.0;');
                             break;
                         case 'add-assign':
                             $codePrinter->output($variable . ' += 0.0;');
                             break;
                         case 'sub-assign':
                             $codePrinter->output($variable . ' -= 0.0;');
                             break;
                         case 'mul-assign':
                             $codePrinter->output($variable . ' *= 0.0;');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: double", $statement);
                     }
                     break;
                 case 'int':
                 case 'uint':
                 case 'long':
                 case 'ulong':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = (double) (' . $resolvedExpr->getCode() . ');');
                             break;
                         case 'add-assign':
                             $codePrinter->output($variable . ' += (double) (' . $resolvedExpr->getCode() . ');');
                             break;
                         case 'sub-assign':
                             $codePrinter->output($variable . ' -= (double) (' . $resolvedExpr->getCode() . ');');
                             break;
                         case 'mul-assign':
                             $codePrinter->output($variable . ' *= (double) (' . $resolvedExpr->getCode() . ');');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: double", $statement);
                     }
                     break;
                 case 'double':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = ' . $resolvedExpr->getCode() . ';');
                             break;
                         case 'add-assign':
                             $codePrinter->output($variable . ' += ' . $resolvedExpr->getCode() . ';');
                             break;
                         case 'sub-assign':
                             $codePrinter->output($variable . ' -= ' . $resolvedExpr->getCode() . ';');
                             break;
                         case 'mul-assign':
                             $codePrinter->output($variable . ' *= ' . $resolvedExpr->getCode() . ';');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: double", $statement);
                     }
                     break;
                 case 'bool':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = ' . $resolvedExpr->getBooleanCode() . ';');
                             break;
                         case 'add-assign':
                             $codePrinter->output($variable . ' += ' . $resolvedExpr->getBooleanCode() . ';');
                             break;
                         case 'sub-assign':
                             $codePrinter->output($variable . ' -= ' . $resolvedExpr->getBooleanCode() . ';');
                             break;
                         case 'mul-assign':
                             $codePrinter->output($variable . ' *= ' . $resolvedExpr->getBooleanCode() . ';');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: double", $statement);
                     }
                     break;
                 case 'variable':
                     $itemVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
                     switch ($itemVariable->getType()) {
                         case 'int':
                         case 'uint':
                         case 'long':
                         case 'ulong':
                         case 'bool':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $codePrinter->output($variable . ' = (double) ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'add-assign':
                                     $codePrinter->output($variable . ' += (double) ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'sub-assign':
                                     $codePrinter->output($variable . ' -= (double) ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'mul-assign':
                                     $codePrinter->output($variable . ' *= (double) ' . $itemVariable->getName() . ';');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: double", $statement);
                             }
                             break;
                         case 'double':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $codePrinter->output($variable . ' = ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'add-assign':
                                     $codePrinter->output($variable . ' += ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'sub-assign':
                                     $codePrinter->output($variable . ' -= ' . $itemVariable->getName() . ';');
                                     break;
                                 case 'mul-assign':
                                     $codePrinter->output($variable . ' *= ' . $itemVariable->getName() . ';');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: double", $statement);
                             }
                             break;
                         case 'variable':
                             $compilationContext->headersManager->add('kernel/operators');
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $codePrinter->output($variable . ' = zephir_get_numberval(' . $itemVariable->getName() . ');');
                                     break;
                                 case 'add-assign':
                                     $codePrinter->output($variable . ' += zephir_get_numberval(' . $itemVariable->getName() . ');');
                                     break;
                                 case 'sub-assign':
                                     $codePrinter->output($variable . ' -= zephir_get_numberval(' . $itemVariable->getName() . ');');
                                     break;
                                 case 'mul-assign':
                                     $codePrinter->output($variable . ' *= zephir_get_numberval(' . $itemVariable->getName() . ');');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: double", $statement);
                             }
                             break;
                         default:
                             throw new CompilerException("Unknown type: " . $itemVariable->getType(), $statement);
                     }
                     break;
                 default:
                     throw new CompilerException("Unknown type " . $resolvedExpr->getType(), $statement);
             }
             break;
         case 'array':
             switch ($resolvedExpr->getType()) {
                 case 'variable':
                 case 'array':
                     switch ($statement['operator']) {
                         case 'assign':
                             if ($variable != $resolvedExpr->getCode()) {
                                 $symbolVariable->setMustInitNull(true);
                                 $compilationContext->symbolTable->mustGrownStack(true);
                                 /* Inherit the dynamic type data from the assigned value */
                                 $symbolVariable->setDynamicTypes('array');
                                 $codePrinter->output('ZEPHIR_CPY_WRT(' . $variable . ', ' . $resolvedExpr->getCode() . ');');
                             }
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                     }
                     break;
                 default:
                     throw new CompilerException("You cannot {$statement['operator']} {$resolvedExpr->getType()} for array type", $resolvedExpr->getOriginal());
             }
             break;
         case 'string':
             switch ($resolvedExpr->getType()) {
                 case 'null':
                     switch ($statement['operator']) {
                         case 'assign':
                             $symbolVariable->initVariant($compilationContext);
                             $codePrinter->output('ZVAL_EMPTY_STRING(' . $variable . ');');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: string", $statement);
                     }
                     break;
                 case 'string':
                     switch ($statement['operator']) {
                         case 'assign':
                             $symbolVariable->initVariant($compilationContext);
                             if ($resolvedExpr->getCode()) {
                                 $codePrinter->output('ZVAL_STRING(' . $variable . ', "' . $resolvedExpr->getCode() . '", 1);');
                             } else {
                                 $codePrinter->output('ZVAL_EMPTY_STRING(' . $variable . ');');
                             }
                             break;
                         case 'concat-assign':
                             $codePrinter->output('zephir_concat_self_str(&' . $variable . ', "' . $resolvedExpr->getCode() . '", sizeof("' . $resolvedExpr->getCode() . '")-1 TSRMLS_CC);');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: string", $statement);
                     }
                     break;
                 case 'char':
                 case 'uchar':
                     switch ($statement['operator']) {
                         case 'assign':
                             $symbolVariable->initVariant($compilationContext);
                             if ($resolvedExpr->getCode()) {
                                 $codePrinter->output('ZVAL_STRING(' . $variable . ', "' . $resolvedExpr->getCode() . '", 1);');
                             } else {
                                 $codePrinter->output('ZVAL_EMPTY_STRING(' . $variable . ');');
                             }
                             break;
                         case 'concat-assign':
                             $compilationContext->headersManager->add('kernel/operators');
                             $codePrinter->output('zephir_concat_self_str(&' . $variable . ', "' . $resolvedExpr->getCode() . '", sizeof("' . $resolvedExpr->getCode() . '")-1 TSRMLS_CC);');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: string", $statement);
                     }
                     break;
                 case 'variable':
                     $itemVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
                     switch ($itemVariable->getType()) {
                         case 'int':
                         case 'uint':
                         case 'long':
                         case 'ulong':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $symbolVariable->initVariant($compilationContext);
                                     $compilationContext->headersManager->add('kernel/string');
                                     $codePrinter->output('Z_STRLEN_P(' . $variable . ') = zephir_spprintf(&Z_STRVAL_P(' . $variable . '), 0, "%ld", ' . $itemVariable->getName() . ');');
                                     $codePrinter->output('Z_TYPE_P(' . $variable . ') = IS_STRING;');
                                     break;
                                 case 'concat-assign':
                                     $compilationContext->headersManager->add('kernel/operators');
                                     $codePrinter->output('zephir_concat_self_long(&' . $variable . ', ' . $itemVariable->getName() . ' TSRMLS_CC);');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: string", $statement);
                             }
                             break;
                         case 'char':
                         case 'uchar':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $symbolVariable->initVariant($compilationContext);
                                     $compilationContext->headersManager->add('kernel/string');
                                     $codePrinter->output('Z_STRLEN_P(' . $variable . ') = zephir_spprintf(&Z_STRVAL_P(' . $variable . '), 0, "%c", ' . $itemVariable->getName() . ');');
                                     $codePrinter->output('Z_TYPE_P(' . $variable . ') = IS_STRING;');
                                     break;
                                 case 'concat-assign':
                                     $compilationContext->headersManager->add('kernel/operators');
                                     $codePrinter->output('zephir_concat_self_char(&' . $variable . ', ' . $itemVariable->getName() . ' TSRMLS_CC);');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: string", $statement);
                             }
                             break;
                         case 'string':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $symbolVariable->setMustInitNull(true);
                                     $compilationContext->symbolTable->mustGrownStack(true);
                                     if ($variable != $itemVariable->getName()) {
                                         $codePrinter->output('ZEPHIR_CPY_WRT(' . $variable . ', ' . $itemVariable->getName() . ');');
                                     }
                                     break;
                                 case 'concat-assign':
                                     $compilationContext->headersManager->add('kernel/operators');
                                     $codePrinter->output('zephir_concat_self(&' . $variable . ', ' . $itemVariable->getName() . ' TSRMLS_CC);');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: string", $statement);
                             }
                             break;
                         case 'variable':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $symbolVariable->setMustInitNull(true);
                                     $compilationContext->symbolTable->mustGrownStack(true);
                                     $compilationContext->headersManager->add('kernel/operators');
                                     $codePrinter->output('zephir_get_strval(' . $variable . ', ' . $itemVariable->getName() . ');');
                                     break;
                                 case 'concat-assign':
                                     $compilationContext->headersManager->add('kernel/operators');
                                     $codePrinter->output('zephir_concat_self(&' . $variable . ', ' . $itemVariable->getName() . ' TSRMLS_CC);');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                             }
                             break;
                         default:
                             throw new CompilerException("Unknown type: " . $itemVariable->getType(), $statement);
                     }
                     break;
                 default:
                     throw new CompilerException("Unknown type " . $resolvedExpr->getType(), $statement);
             }
             break;
         case 'bool':
             switch ($resolvedExpr->getType()) {
                 case 'null':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = 0;');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: null", $statement);
                     }
                     break;
                 case 'int':
                 case 'uint':
                 case 'long':
                 case 'ulong':
                 case 'double':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = (' . $resolvedExpr->getCode() . ') ? 1 : 0;');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $statement);
                     }
                     break;
                 case 'char':
                 case 'uchar':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = (\'' . $resolvedExpr->getCode() . '\') ? 1 : 0;');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $statement);
                     }
                     break;
                 case 'bool':
                     switch ($statement['operator']) {
                         case 'assign':
                             $codePrinter->output($variable . ' = ' . $resolvedExpr->getBooleanCode() . ';');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $statement);
                     }
                     break;
                 case 'variable':
                     $itemVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
                     switch ($itemVariable->getType()) {
                         case 'int':
                         case 'uint':
                         case 'long':
                         case 'ulong':
                         case 'double':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $codePrinter->output($variable . ' = (' . $itemVariable->getName() . ') ? 1 : 0;');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                             }
                             break;
                         case 'bool':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $codePrinter->output($variable . ' = ' . $itemVariable->getName() . ';');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                             }
                             break;
                         case 'variable':
                         case 'string':
                         case 'array':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $codePrinter->output($variable . ' = zephir_is_true(' . $itemVariable->getName() . ');');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                             }
                             break;
                         default:
                             throw new CompilerException("Cannot assign variable: " . $itemVariable->getType(), $statement);
                     }
                     break;
                 default:
                     throw new CompilerException("Unknown type: " . $resolvedExpr->getType(), $statement);
             }
             break;
         case 'variable':
             switch ($resolvedExpr->getType()) {
                 case 'null':
                     switch ($statement['operator']) {
                         case 'assign':
                             $symbolVariable->initVariant($compilationContext);
                             $symbolVariable->setDynamicTypes('null');
                             if ($symbolVariable->isLocalOnly()) {
                                 $codePrinter->output('ZVAL_NULL(&' . $variable . ');');
                             } else {
                                 $codePrinter->output('ZVAL_NULL(' . $variable . ');');
                             }
                             break;
                     }
                     break;
                 case 'int':
                 case 'uint':
                 case 'long':
                 case 'ulong':
                     if ($symbolVariable->isLocalOnly()) {
                         $symbol = '&' . $variable;
                     } else {
                         $symbol = $variable;
                     }
                     switch ($statement['operator']) {
                         case 'mul-assign':
                         case 'sub-assign':
                         case 'add-assign':
                             switch ($statement['operator']) {
                                 case 'mul-assign':
                                     $functionName = 'ZEPHIR_MUL_ASSIGN';
                                     break;
                                 case 'sub-assign':
                                     $functionName = 'ZEPHIR_SUB_ASSIGN';
                                     break;
                                 case 'add-assign':
                                     $functionName = 'ZEPHIR_ADD_ASSIGN';
                                     break;
                             }
                             $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext);
                             $codePrinter->output('ZVAL_LONG(' . $tempVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
                             $compilationContext->symbolTable->mustGrownStack(true);
                             $compilationContext->headersManager->add('kernel/operators');
                             $codePrinter->output($functionName . '(' . $symbol . ', ' . $tempVariable->getName() . ');');
                             break;
                         case 'assign':
                             $symbolVariable->setDynamicTypes('long');
                             if ($readDetector->detect($variable, $resolvedExpr->getOriginal())) {
                                 $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('int', $compilationContext);
                                 $codePrinter->output($tempVariable->getName() . ' = ' . $resolvedExpr->getCode() . ';');
                                 $symbolVariable->initVariant($compilationContext);
                                 $codePrinter->output('ZVAL_LONG(' . $symbol . ', ' . $tempVariable->getName() . ');');
                             } else {
                                 $symbolVariable->initVariant($compilationContext);
                                 $codePrinter->output('ZVAL_LONG(' . $symbol . ', ' . $resolvedExpr->getCode() . ');');
                             }
                             break;
                         case 'div-assign':
                             $symbolVariable->setDynamicTypes('double');
                             if ($readDetector->detect($variable, $resolvedExpr->getOriginal())) {
                                 $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('double', $compilationContext);
                                 $codePrinter->output($tempVariable->getName() . ' = ' . $resolvedExpr->getCode() . ';');
                                 $symbolVariable->initVariant($compilationContext);
                                 $codePrinter->output('ZVAL_DOUBLE(' . $symbol . ', ' . $tempVariable->getName() . ');');
                             } else {
                                 $symbolVariable->initVariant($compilationContext);
                                 $codePrinter->output('ZVAL_DOUBLE(' . $symbol . ', ' . $resolvedExpr->getCode() . ');');
                             }
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                     }
                     break;
                 case 'char':
                 case 'uchar':
                     if ($symbolVariable->isLocalOnly()) {
                         $symbol = '&' . $variable;
                     } else {
                         $symbol = $variable;
                     }
                     switch ($statement['operator']) {
                         case 'assign':
                             $symbolVariable->setDynamicTypes('long');
                             if ($readDetector->detect($variable, $resolvedExpr->getOriginal())) {
                                 $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('char', $compilationContext);
                                 $codePrinter->output($tempVariable->getName() . ' = ' . $resolvedExpr->getCode() . ';');
                                 $symbolVariable->initVariant($compilationContext);
                                 $codePrinter->output('ZVAL_LONG(' . $symbol . ', ' . $tempVariable->getName() . ');');
                             } else {
                                 $symbolVariable->initVariant($compilationContext);
                                 $codePrinter->output('ZVAL_LONG(' . $symbol . ', \'' . $resolvedExpr->getCode() . '\');');
                             }
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                     }
                     break;
                 case 'double':
                     if ($symbolVariable->isLocalOnly()) {
                         $symbol = '&' . $variable;
                     } else {
                         $symbol = $variable;
                     }
                     switch ($statement['operator']) {
                         case 'assign':
                             $symbolVariable->setDynamicTypes('double');
                             if ($readDetector->detect($variable, $resolvedExpr->getOriginal())) {
                                 $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('double', $compilationContext);
                                 $codePrinter->output($tempVariable->getName() . ' = ' . $resolvedExpr->getCode() . ';');
                                 $symbolVariable->initVariant($compilationContext);
                                 $codePrinter->output('ZVAL_DOUBLE(' . $symbol . ', ' . $tempVariable->getName() . ');');
                             } else {
                                 $symbolVariable->initVariant($compilationContext);
                                 $codePrinter->output('ZVAL_DOUBLE(' . $symbol . ', ' . $resolvedExpr->getCode() . ');');
                             }
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                     }
                     break;
                 case 'bool':
                     if ($symbolVariable->isLocalOnly()) {
                         $symbol = '&' . $variable;
                     } else {
                         $symbol = $variable;
                     }
                     switch ($statement['operator']) {
                         case 'assign':
                             $symbolVariable->setDynamicTypes('bool');
                             if ($resolvedExpr->getCode() == 'true') {
                                 $symbolVariable->initVariant($compilationContext);
                                 $codePrinter->output('ZVAL_BOOL(' . $symbol . ', 1);');
                             } else {
                                 if ($resolvedExpr->getCode() == 'false') {
                                     $symbolVariable->initVariant($compilationContext);
                                     $codePrinter->output('ZVAL_BOOL(' . $symbol . ', 0);');
                                 } else {
                                     if ($readDetector->detect($variable, $resolvedExpr->getOriginal())) {
                                         $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite('double', $compilationContext);
                                         $codePrinter->output($tempVariable->getName() . ' = ' . $resolvedExpr->getBooleanCode() . ';');
                                         $symbolVariable->initVariant($compilationContext);
                                         $codePrinter->output('ZVAL_BOOL(' . $symbol . ', ' . $tempVariable->getName() . ');');
                                     } else {
                                         $symbolVariable->initVariant($compilationContext);
                                         $codePrinter->output('ZVAL_BOOL(' . $symbol . ', ' . $resolvedExpr->getBooleanCode() . ');');
                                     }
                                 }
                             }
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                     }
                     break;
                 case 'string':
                     switch ($statement['operator']) {
                         case 'assign':
                             $symbolVariable->initVariant($compilationContext);
                             $symbolVariable->setDynamicTypes('string');
                             if ($symbolVariable->isLocalOnly()) {
                                 $codePrinter->output('ZVAL_STRING(&' . $variable . ', "' . $resolvedExpr->getCode() . '", 1);');
                             } else {
                                 $codePrinter->output('ZVAL_STRING(' . $variable . ', "' . $resolvedExpr->getCode() . '", 1);');
                             }
                             break;
                         case 'concat-assign':
                             $compilationContext->headersManager->add('kernel/operators');
                             $codePrinter->output('zephir_concat_self_str(&' . $variable . ', SL("' . $resolvedExpr->getCode() . '") TSRMLS_CC);');
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                     }
                     break;
                 case 'array':
                     switch ($statement['operator']) {
                         case 'assign':
                             if ($variable != $resolvedExpr->getCode()) {
                                 $symbolVariable->setMustInitNull(true);
                                 $compilationContext->symbolTable->mustGrownStack(true);
                                 /* Inherit the dynamic type data from the assigned value */
                                 $symbolVariable->setDynamicTypes('array');
                                 $codePrinter->output('ZEPHIR_CPY_WRT(' . $variable . ', ' . $resolvedExpr->getCode() . ');');
                             }
                             break;
                         default:
                             throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                     }
                     break;
                 case 'variable':
                     $itemVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $resolvedExpr->getOriginal());
                     switch ($itemVariable->getType()) {
                         case 'int':
                         case 'uint':
                         case 'long':
                         case 'ulong':
                         case 'char':
                         case 'uchar':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $symbolVariable->initVariant($compilationContext);
                                     $symbolVariable->setDynamicTypes('long');
                                     if ($symbolVariable->isLocalOnly()) {
                                         $codePrinter->output('ZVAL_LONG(&' . $variable . ', ' . $itemVariable->getName() . ');');
                                     } else {
                                         $codePrinter->output('ZVAL_LONG(' . $variable . ', ' . $itemVariable->getName() . ');');
                                     }
                                     break;
                                 case 'add-assign':
                                     $compilationContext->headersManager->add('kernel/operators');
                                     $symbolVariable->initVariant($compilationContext);
                                     $symbolVariable->setDynamicTypes('long');
                                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite($itemVariable->getType(), $compilationContext);
                                     if ($symbolVariable->isLocalOnly()) {
                                         $codePrinter->output($tempVariable->getName() . ' = zephir_get_numberval(&' . $variable . ');');
                                         $codePrinter->output('ZVAL_LONG(&' . $variable . ', ' . $tempVariable->getName() . ' + ' . $itemVariable->getName() . ');');
                                     } else {
                                         $codePrinter->output($tempVariable->getName() . ' = zephir_get_numberval(' . $variable . ');');
                                         $codePrinter->output('ZVAL_LONG(' . $variable . ', ' . $tempVariable->getName() . ' + ' . $itemVariable->getName() . ');');
                                     }
                                     break;
                                 case 'sub-assign':
                                     $compilationContext->headersManager->add('kernel/operators');
                                     $symbolVariable->initVariant($compilationContext);
                                     $symbolVariable->setDynamicTypes('long');
                                     $tempVariable = $compilationContext->symbolTable->getTempVariableForWrite($itemVariable->getType(), $compilationContext);
                                     if ($symbolVariable->isLocalOnly()) {
                                         $codePrinter->output($tempVariable->getName() . ' = zephir_get_numberval(&' . $variable . ');');
                                         $codePrinter->output('ZVAL_LONG(&' . $variable . ', ' . $tempVariable->getName() . ' - ' . $itemVariable->getName() . ');');
                                     } else {
                                         $codePrinter->output($tempVariable->getName() . ' = zephir_get_numberval(' . $variable . ');');
                                         $codePrinter->output('ZVAL_LONG(' . $variable . ', ' . $tempVariable->getName() . ' - ' . $itemVariable->getName() . ');');
                                     }
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                             }
                             break;
                         case 'double':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $symbolVariable->initVariant($compilationContext);
                                     $symbolVariable->setDynamicTypes('double');
                                     if ($symbolVariable->isLocalOnly()) {
                                         $codePrinter->output('ZVAL_DOUBLE(&' . $variable . ', ' . $itemVariable->getName() . ');');
                                     } else {
                                         $codePrinter->output('ZVAL_DOUBLE(' . $variable . ', ' . $itemVariable->getName() . ');');
                                     }
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                             }
                             break;
                         case 'bool':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     $symbolVariable->initVariant($compilationContext);
                                     $symbolVariable->setDynamicTypes('bool');
                                     if ($symbolVariable->isLocalOnly()) {
                                         $codePrinter->output('ZVAL_BOOL(&' . $variable . ', ' . $itemVariable->getName() . ');');
                                     } else {
                                         $codePrinter->output('ZVAL_BOOL(' . $variable . ', ' . $itemVariable->getName() . ');');
                                     }
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                             }
                             break;
                         case 'array':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     if ($variable != $resolvedExpr->getCode()) {
                                         $symbolVariable->setMustInitNull(true);
                                         $compilationContext->symbolTable->mustGrownStack(true);
                                         /* Inherit the dynamic type data from the assigned value */
                                         $symbolVariable->setDynamicTypes('array');
                                         $codePrinter->output('ZEPHIR_CPY_WRT(' . $variable . ', ' . $resolvedExpr->getCode() . ');');
                                     }
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
                             }
                             break;
                         case 'variable':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     if ($itemVariable->getName() != $variable) {
                                         $symbolVariable->setMustInitNull(true);
                                         $compilationContext->symbolTable->mustGrownStack(true);
                                         /* Inherit the dynamic type data from the assigned value */
                                         $symbolVariable->setDynamicTypes($itemVariable->getDynamicTypes());
                                         $symbolVariable->setClassTypes($itemVariable->getClassTypes());
                                         $codePrinter->output('ZEPHIR_CPY_WRT(' . $variable . ', ' . $itemVariable->getName() . ');');
                                         if ($itemVariable->isTemporal()) {
                                             $itemVariable->setIdle(true);
                                         }
                                     }
                                     break;
                                 case 'concat-assign':
                                     $compilationContext->headersManager->add('kernel/operators');
                                     $codePrinter->output('zephir_concat_self(&' . $variable . ', ' . $itemVariable->getName() . ' TSRMLS_CC);');
                                     break;
                                 case 'add-assign':
                                     $compilationContext->symbolTable->mustGrownStack(true);
                                     $compilationContext->headersManager->add('kernel/operators');
                                     $codePrinter->output('ZEPHIR_ADD_ASSIGN(' . $variable . ', ' . $itemVariable->getName() . ');');
                                     break;
                                 case 'sub-assign':
                                     $compilationContext->symbolTable->mustGrownStack(true);
                                     $compilationContext->headersManager->add('kernel/operators');
                                     $codePrinter->output('ZEPHIR_SUB_ASSIGN(' . $variable . ', ' . $itemVariable->getName() . ');');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                             }
                             break;
                         case 'string':
                             switch ($statement['operator']) {
                                 case 'assign':
                                     if ($itemVariable->getName() != $variable) {
                                         $symbolVariable->setMustInitNull(true);
                                         $compilationContext->symbolTable->mustGrownStack(true);
                                         /* Inherit the dynamic type data from the assigned value */
                                         $symbolVariable->setDynamicTypes($itemVariable->getDynamicTypes());
                                         $symbolVariable->setClassTypes($itemVariable->getClassTypes());
                                         $codePrinter->output('ZEPHIR_CPY_WRT(' . $variable . ', ' . $itemVariable->getName() . ');');
                                         if ($itemVariable->isTemporal()) {
                                             $itemVariable->setIdle(true);
                                         }
                                     }
                                     break;
                                 case 'concat-assign':
                                     $compilationContext->headersManager->add('kernel/operators');
                                     $codePrinter->output('zephir_concat_self(&' . $variable . ', ' . $itemVariable->getName() . ' TSRMLS_CC);');
                                     break;
                                 default:
                                     throw new CompilerException("Operator '" . $statement['operator'] . "' is not supported for variable type: " . $itemVariable->getType(), $statement);
                             }
                             break;
                         default:
                             throw new CompilerException("Unknown type: " . $itemVariable->getType(), $resolvedExpr->getOriginal());
                     }
                     break;
                 default:
                     throw new CompilerException("Unknown type: " . $resolvedExpr->getType(), $resolvedExpr->getOriginal());
             }
             break;
         default:
             throw new CompilerException("Unknown type: " . $type, $statement);
     }
 }
Exemplo n.º 9
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);
     }
 }
Exemplo n.º 10
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);
     }
 }