Updates object properties dynamically
Inheritance: extends ArrayIndex
Example #1
0
 /**
  * @param CompilationContext $compilationContext
  * @throws CompilerException
  */
 public function compile(CompilationContext $compilationContext)
 {
     $readDetector = new ReadDetector();
     $statement = $this->_statement;
     foreach ($statement['assignments'] as $assignment) {
         $variable = $assignment['variable'];
         /**
          * Get the symbol from the symbol table if necessary
          */
         switch ($assignment['assign-type']) {
             case 'static-property':
             case 'static-property-append':
             case 'static-property-array-index':
             case 'static-property-array-index-append':
             case 'dynamic-variable-string':
                 $symbolVariable = null;
                 break;
             case 'array-index':
             case 'variable-append':
             case 'object-property':
             case 'array-index-append':
             case 'string-dynamic-object-property':
             case 'variable-dynamic-object-property':
                 $symbolVariable = $compilationContext->symbolTable->getVariableForUpdate($variable, $compilationContext, $assignment);
                 break;
             default:
                 $symbolVariable = $compilationContext->symbolTable->getVariableForWrite($variable, $compilationContext, $assignment);
                 break;
         }
         /**
          * Incr/Decr assignments don't require an expression
          */
         if (isset($assignment['expr'])) {
             $expr = new Expression($assignment['expr']);
             switch ($assignment['assign-type']) {
                 case 'variable':
                     if (!$readDetector->detect($variable, $assignment['expr'])) {
                         if (isset($assignment['operator'])) {
                             if ($assignment['operator'] == 'assign') {
                                 $expr->setExpectReturn(true, $symbolVariable);
                             }
                         } else {
                             $expr->setExpectReturn(true, $symbolVariable);
                         }
                     } else {
                         if (isset($assignment['operator'])) {
                             if ($assignment['operator'] == 'assign') {
                                 $expr->setExpectReturn(true);
                             }
                         } else {
                             $expr->setExpectReturn(true);
                         }
                     }
                     break;
             }
             switch ($assignment['expr']['type']) {
                 case 'property-access':
                 case 'array-access':
                 case 'type-hint':
                     $expr->setReadOnly(true);
                     break;
             }
             $resolvedExpr = $expr->compile($compilationContext);
             /**
              * Bad implemented operators could return values different than objects
              */
             if (!is_object($resolvedExpr)) {
                 throw new CompilerException("Resolved expression is not valid", $assignment['expr']);
             }
         }
         /**
          * There are four types of assignments
          */
         switch ($assignment['assign-type']) {
             case 'variable':
                 $let = new LetVariable();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $readDetector, $compilationContext, $assignment);
                 break;
             case 'variable-append':
                 $let = new LetVariableAppend();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'object-property':
                 $let = new LetObjectProperty();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'variable-dynamic-object-property':
                 $let = new LetObjectDynamicProperty();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'string-dynamic-object-property':
                 $let = new LetObjectDynamicStringProperty();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'static-property':
                 $let = new LetStaticProperty();
                 $let->assignStatic($variable, $assignment['property'], $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'static-property-append':
                 $let = new LetStaticPropertyAppend();
                 $let->assignStatic($variable, $assignment['property'], $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'static-property-array-index':
                 $let = new LetStaticPropertyArrayIndex();
                 $let->assignStatic($variable, $assignment['property'], $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'static-property-array-index-append':
                 $let = new LetStaticPropertyArrayIndexAppend();
                 $let->assignStatic($variable, $assignment['property'], $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'array-index':
                 $let = new LetArrayIndex();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'array-index-append':
                 $let = new LetArrayIndexAppend();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'object-property-append':
                 $let = new LetObjectPropertyAppend();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'object-property-array-index':
                 $let = new LetObjectPropertyArrayIndex();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'object-property-array-index-append':
                 $let = new LetObjectPropertyArrayIndexAppend();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'incr':
                 $let = new LetIncr();
                 $let->assign($variable, $symbolVariable, $compilationContext, $assignment);
                 break;
             case 'decr':
                 $let = new LetDecr();
                 $let->assign($variable, $symbolVariable, $compilationContext, $assignment);
                 break;
             case 'object-property-incr':
                 $let = new LetObjectPropertyIncr();
                 $let->assign($variable, $assignment['property'], $symbolVariable, $compilationContext, $assignment);
                 break;
             case 'object-property-decr':
                 $let = new LetObjectPropertyDecr();
                 $let->assign($variable, $assignment['property'], $symbolVariable, $compilationContext, $assignment);
                 break;
             case 'dynamic-variable':
                 $let = new LetExportSymbol();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                 break;
             case 'dynamic-variable-string':
                 $let = new LetExportSymbolString();
                 $let->assign($variable, $symbolVariable, $resolvedExpr, $compilationContext, $assignment);
                 break;
             default:
                 throw new CompilerException("Unknown assignment: " . $assignment['assign-type'], $assignment);
         }
     }
 }