Example #1
0
 def c_gen_code(self):
   import code_gen.access as access
   left_asm = self.left.c_gen_code()
   left_t = self.left.expr_type
   if left_t.is_array:
     return access.get_array_field(self.right, left_asm)
   return access.get_field_from_parts(left_t, self.right, left_asm)
Example #2
0
  def c_gen_code(self):
    import code_gen.access as access
    result = self.right.c_gen_code()

    # The left hand side is either an ASTArrayAccess, ASTFieldAccess or
    # ASTIdentifiers.
    if isinstance(self.left, ASTIdentifiers):
      # For assignment expressions, we evaluate the left hand side first. If
      # the left hand side is an ASTIdentifiers, the same ASTIdentifiers could
      # be used on the right hand side in an assignment.
      # Thus, we must store a reference to where the left hand side points
      # before evaluating the right hand side.

      if self.left.is_simple:
        # If the left hand side is simple, it is either a method parameter,
        # local variable or an instance field on the enclosing type. The
        # location for all of these cannot be altered by the right hand side,
        # so we can calculate the right hand side first.
        return [
          result,
          access.set_simple_var(self.left.simple_decl, 'eax'),
        ]
      else:
        import code_gen.annotate_ids as annotate_ids

        annotations = annotate_ids.annotate_identifier(self.left)
        if len(annotations) == 0:
          # If we do not have any annotations then the left hand side is a
          # static field. This address cannot change.
          return [
            result,
            access.set_simple_static_field(self.left, 'eax'),
          ]
        else:
          # _get_to_final provides code to store a pointer to the second last
          # part of the identifier in $eax.
          type_, code = access._get_to_final(self.left, annotations)
          env = type_.definition.environment

          final_part = str(self.left.parts[-1])
          f, _ = env.lookup_field(final_part)

          return [
            code,
            common.check_null('eax'),
            'push eax ; save instance that we want to store a field on',
            result,
            'pop ebx ; instance to store a field on',
            common.save_instance_field('ebx', f, 'eax'),
          ]

    elif isinstance(self.left, ASTFieldAccess):
      left_asm = self.left.left.c_gen_code()
      left_t = self.left.left.expr_type
      if left_t.is_array:
        raise Exception('Trying to write to array field')
      return [
        '; FieldAccess assignment',
        access.get_field_from_parts(
            left_t, self.left.right, left_asm, get_addr=True),
        'push eax  ; Save field addr',
        result,
        '; RHS of assignment should be eax',
        'pop ebx  ; Pop addr of field',
        'mov [ebx], eax  ; Assign!'
      ]

    elif isinstance(self.left, ASTArrayAccess):
      array_soundness_pass = manager.CodeGenManager.get_label('array_soundness_pass')

      soundness_asm = []
      if not self.left.array_expression.expr_type.is_primitive:
        soundness_asm = [
          'push eax',
          'push ebx',
          'push ecx',
          '; Get CIT of right side',
          'mov ecx, [ecx]'
          '; Get subtype col of right side',
          'mov ecx, [ecx + 4]',
          '; get subtype offset',
          'mov ebx, [ebx + 4]',
          '; index into subtype col',
          'mov ecx, [ecx + ebx]',
          'cmp ecx, 1  ; 1 means that RHS is a subtype of LHS',
          'je {0}'.format(array_soundness_pass),
          'call __exception',
          '{0}:'.format(array_soundness_pass),
          'pop ecx',
          'pop ebx',
          'pop eax',
        ]

      # The result is calculated after the array index offset.
      return [
        self.left.c_gen_code_get_array_pointer(),
        'push ebx ; save array pointer',
        'push eax ; save array offset',
        result,
        'mov ecx, eax ; move result',
        'pop eax ; restore array offset',
        'pop ebx ; restore array pointer',
        '; do array type soundness check',
        soundness_asm,
        'mov [ebx + eax], ecx',
        'mov eax, ecx ; result should be in eax',
      ]

    raise Exception('Programmer error: trying to assign to invalid AST')