// File: AshOlogn[P]ash-language-interpreter/src/parser.cpp
// Function: handleMemberAccess(AbstractExpressionNode*)
AbstractExpressionNode* handleMemberAccess(AbstractExpressionNode* head) {

  if(head->evalType != STRING_T && head->evalType != ARRAY_T) {
      
    //first write message
    const char* arrayAccessErrorMessage = "A value must be of array or string type to be indexed";
    throw StaticTypeError(head->startLine+1, peek()->line+1, getCodeLineBlock(head->startLine, peek()->line), arrayAccessErrorMessage);
  }
  
  Token* leftBracketToken = consume(); //consume [

  //if next value is colon, this is a slice with implicit start = 0
  if(peek()->type == COLON) {

    Token* colonToken = consume(); //consume :
    
    //start = 0
    ParseData startIndex;
    startIndex.type = INT32_T;
    startIndex.value.integer = 0;

    //if next value is ], implicit end = -1
    if(peek()->type == RIGHT_BRACKET) {

      Token* rightBracketToken = consume(); //consume ]
      ParseData endIndex;
      endIndex.type = INT32_T;
      endIndex.value.integer = (int32_t) -1;
      
      return new ArrayAccessNode(head, new LiteralNode(startIndex, leftBracketToken->line+1), 
                                  new LiteralNode(endIndex, rightBracketToken->line+1), getCodeLineBlock(head->startLine-1, rightBracketToken->line), rightBracketToken->line+1);

    } else {

      //defined end index
      AbstractExpressionNode* end = evalExpression();
      
      //make sure that the expression evaluates to an integer
      if(!typecheckMemberAccessExpression(end->evalType)) {
        throw StaticTypeError(head->startLine+1, end->endLine+1, getCodeLineBlock(head->startLine, end->endLine), "array indexing", end->evalType);
      }

      if(peek()->type != RIGHT_BRACKET) {
        
        //!!! If [ does not have a corresponding ], throw an error
        throw ParseSyntaxError(leftBracketToken->line+1, codeLines->at(leftBracketToken->line), "[", "Array access operation must end with ']'");
        
      } else {
  
        Token* rightBracketToken = consume(); //consume ]
        return new ArrayAccessNode(head, new LiteralNode(startIndex, leftBracketToken->line+1), end, getCodeLineBlock(head->startLine-1, rightBracketToken->line), rightBracketToken->line+1);
      }
    }

  } else {

    //defined start index
    AbstractExpressionNode* start = evalExpression();
    
    //make sure that the expression evaluates to an integer
    if(!typecheckMemberAccessExpression(start->evalType)) {
      throw StaticTypeError(head->startLine+1, start->endLine+1, getCodeLineBlock(head->startLine, start->endLine), "array indexing", start->evalType);
    }

    //accessing a slice with explicit start
    if(peek()->type == COLON) {
  
      consume(); //consume :

      //end = -1 implied
      if(peek()->type == RIGHT_BRACKET) {

        Token* rightBracketToken = consume(); //consume ]
        ParseData endIndex;
        endIndex.type = INT32_T;
        endIndex.value.integer = (int32_t) -1;
    
        return new ArrayAccessNode(head, start, new LiteralNode(endIndex, rightBracketToken->line+1), getCodeLineBlock(head->startLine-1, rightBracketToken->line), rightBracketToken->line+1);

      } else {

        //defined end index
        AbstractExpressionNode* end = evalExpression();
        
        //make sure that the expression evaluates to an integer
        if(!typecheckMemberAccessExpression(end->evalType)) {
          throw StaticTypeError(head->startLine+1, end->endLine+1, getCodeLineBlock(head->startLine, end->endLine), "array indexing", end->evalType);            
        }
          
        if(peek()->type != RIGHT_BRACKET) {
          
          //If [ does not have a corresponding ], throw an error
          throw ParseSyntaxError(leftBracketToken->line+1, codeLines->at(leftBracketToken->line), "[", "Array access operation must end with ']'");

        } else {
          Token* rightBracketToken = consume(); //consume ]
          return new ArrayAccessNode(head, start, end, getCodeLineBlock(head->startLine-1, rightBracketToken->line), rightBracketToken->line+1);
        }
      }

    } else {
      
      //accessing single value
      if(peek()->type != RIGHT_BRACKET) {
        
        //!!! If [ does not have a corresponding ], throw an error
        throw ParseSyntaxError(leftBracketToken->line+1, codeLines->at(leftBracketToken->line), "[", "Array access operation must end with ']'");

      } else {
        Token* rightBracketToken = consume(); //consume ]
        return new ArrayAccessNode(head, start, getCodeLineBlock(head->startLine-1, rightBracketToken->line), rightBracketToken->line+1);
      }
    }
  }

  return NULL;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x270, %rsp            # imm = 0x270
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
cmpl $0xb, 0x10(%rax)
je 0x36b1b
movq -0x10(%rbp), %rax
cmpl $0xc, 0x10(%rax)
je 0x36b1b
leaq 0xdfa7(%rip), %rax      # 0x449e9
movq %rax, -0x18(%rbp)
movl $0x38, %edi
callq 0x4130
movq %rax, -0x100(%rbp)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %eax
incl %eax
movl %eax, -0xf4(%rbp)
callq 0x2fe60
movq %rax, -0xf0(%rbp)
jmp 0x36a74
movq -0xf0(%rbp), %rax
movl 0x10(%rax), %eax
incl %eax
movl %eax, -0x110(%rbp)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x10c(%rbp)
callq 0x2fe60
movq %rax, -0x108(%rbp)
jmp 0x36aa1
movl -0x10c(%rbp), %edi
movq -0x108(%rbp), %rax
movl 0x10(%rax), %esi
callq 0x2feb0
movq %rax, -0x118(%rbp)
jmp 0x36abf
movq -0x118(%rbp), %rcx
movl -0x110(%rbp), %edx
movl -0xf4(%rbp), %esi
movq -0x100(%rbp), %rdi
movq -0x18(%rbp), %r8
callq 0x3a620
jmp 0x36ae4
movq -0x100(%rbp), %rdi
leaq 0x1cbf6(%rip), %rsi     # 0x536e8
leaq -0x2fb39(%rip), %rdx    # 0x6fc0
callq 0x43f0
movq -0x100(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x41d0
jmp 0x3750d
callq 0x2fe10
movq %rax, -0x30(%rbp)
callq 0x2fe60
cmpl $0x1e, (%rax)
jne 0x36f45
callq 0x2fe10
movq %rax, -0x38(%rbp)
movl $0x2, -0x48(%rbp)
movq $0x0, -0x40(%rbp)
callq 0x2fe60
cmpl $0x3, (%rax)
jne 0x36cb2
callq 0x2fe10
movq %rax, -0x50(%rbp)
movl $0x2, -0x60(%rbp)
movq $-0x1, -0x58(%rbp)
movl $0x40, %edi
callq 0x4260
movq %rax, -0x130(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x128(%rbp)
movl $0x28, %edi
callq 0x4260
movq %rax, -0x120(%rbp)
jmp 0x36b9f
movq -0x120(%rbp), %rdi
movups -0x48(%rbp), %xmm0
movaps %xmm0, -0x70(%rbp)
movq -0x30(%rbp), %rax
movl 0x10(%rax), %ecx
incl %ecx
movl -0x70(%rbp), %esi
movq -0x68(%rbp), %rdx
callq 0xe260
jmp 0x36bc5
movl $0x28, %edi
callq 0x4260
movq %rax, -0x138(%rbp)
jmp 0x36bd8
movq -0x138(%rbp), %rdi
movups -0x60(%rbp), %xmm0
movaps %xmm0, -0x80(%rbp)
movq -0x50(%rbp), %rax
movl 0x10(%rax), %ecx
incl %ecx
movl -0x80(%rbp), %esi
movq -0x78(%rbp), %rdx
callq 0xe260
jmp 0x36bfe
movq -0x10(%rbp), %rax
movl 0x8(%rax), %edi
decl %edi
movq -0x50(%rbp), %rax
movl 0x10(%rax), %esi
callq 0x2feb0
movq %rax, -0x140(%rbp)
jmp 0x36c1c
movq -0x140(%rbp), %r8
movq -0x138(%rbp), %rcx
movq -0x120(%rbp), %rdx
movq -0x128(%rbp), %rsi
movq -0x130(%rbp), %rdi
movq -0x50(%rbp), %rax
movl 0x10(%rax), %r9d
incl %r9d
callq 0xd940
jmp 0x36c51
movq -0x130(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x37500
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
jmp 0x36ca1
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x4240
jmp 0x36ca1
movq -0x138(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x4240
movq -0x130(%rbp), %rdi
callq 0x4240
jmp 0x3750d
callq 0x369a0
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
movl 0x10(%rax), %edi
callq 0x2b400
testb $0x1, %al
jne 0x36d83
movl $0x38, %edi
callq 0x4130
movq %rax, -0x158(%rbp)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %edi
movl %edi, %eax
incl %eax
movl %eax, -0x150(%rbp)
movq -0x88(%rbp), %rax
movl 0xc(%rax), %esi
movl %esi, %eax
incl %eax
movl %eax, -0x14c(%rbp)
callq 0x2feb0
movq %rax, -0x148(%rbp)
jmp 0x36d19
movq -0x148(%rbp), %rcx
movl -0x14c(%rbp), %edx
movl -0x150(%rbp), %esi
movq -0x158(%rbp), %rdi
movq -0x88(%rbp), %rax
movl 0x10(%rax), %r9d
leaq 0xdcda(%rip), %r8       # 0x44a1f
callq 0x3a720
jmp 0x36d4c
movq -0x158(%rbp), %rdi
leaq 0x1c98e(%rip), %rsi     # 0x536e8
leaq -0x2fda1(%rip), %rdx    # 0x6fc0
callq 0x43f0
movq -0x158(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x41d0
jmp 0x3750d
callq 0x2fe60
cmpl $0x3, (%rax)
je 0x36e2d
movl $0x28, %edi
callq 0x4130
movq %rax, -0x170(%rbp)
movq -0x30(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, %esi
movl %esi, %eax
incl %eax
movl %eax, -0x164(%rbp)
movq 0x1d64c(%rip), %rdi     # 0x54408
callq 0xa7c0
movq %rax, -0x160(%rbp)
jmp 0x36dca
movl -0x164(%rbp), %esi
movq -0x170(%rbp), %rdi
movq -0x160(%rbp), %rax
movq (%rax), %rdx
leaq 0x9585(%rip), %rcx      # 0x4036d
leaq 0xdc3f(%rip), %r8       # 0x44a2e
callq 0x3a420
jmp 0x36df6
movq -0x170(%rbp), %rdi
leaq 0x1c8a4(%rip), %rsi     # 0x536a8
leaq -0x2fe9b(%rip), %rdx    # 0x6f70
callq 0x43f0
movq -0x170(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x41d0
jmp 0x3750d
callq 0x2fe10
movq %rax, -0x90(%rbp)
movl $0x40, %edi
callq 0x4260
movq %rax, -0x188(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x180(%rbp)
movl $0x28, %edi
callq 0x4260
movq %rax, -0x178(%rbp)
jmp 0x36e68
movq -0x178(%rbp), %rdi
movups -0x48(%rbp), %xmm0
movaps %xmm0, -0xa0(%rbp)
movq -0x30(%rbp), %rax
movl 0x10(%rax), %ecx
incl %ecx
movl -0xa0(%rbp), %esi
movq -0x98(%rbp), %rdx
callq 0xe260
jmp 0x36e97
movq -0x88(%rbp), %rax
movq %rax, -0x198(%rbp)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %edi
decl %edi
movq -0x90(%rbp), %rax
movl 0x10(%rax), %esi
callq 0x2feb0
movq %rax, -0x190(%rbp)
jmp 0x36ec6
movq -0x190(%rbp), %r8
movq -0x198(%rbp), %rcx
movq -0x178(%rbp), %rdx
movq -0x180(%rbp), %rsi
movq -0x188(%rbp), %rdi
movq -0x90(%rbp), %rax
movl 0x10(%rax), %r9d
incl %r9d
callq 0xd940
jmp 0x36efe
movq -0x188(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x37500
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
jmp 0x36f34
movq -0x178(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x4240
movq -0x188(%rbp), %rdi
callq 0x4240
jmp 0x3750d
callq 0x369a0
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
movl 0x10(%rax), %edi
callq 0x2b400
testb $0x1, %al
jne 0x37016
movl $0x38, %edi
callq 0x4130
movq %rax, -0x1b0(%rbp)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %edi
movl %edi, %eax
incl %eax
movl %eax, -0x1a8(%rbp)
movq -0xa8(%rbp), %rax
movl 0xc(%rax), %esi
movl %esi, %eax
incl %eax
movl %eax, -0x1a4(%rbp)
callq 0x2feb0
movq %rax, -0x1a0(%rbp)
jmp 0x36fac
movq -0x1a0(%rbp), %rcx
movl -0x1a4(%rbp), %edx
movl -0x1a8(%rbp), %esi
movq -0x1b0(%rbp), %rdi
movq -0xa8(%rbp), %rax
movl 0x10(%rax), %r9d
leaq 0xda47(%rip), %r8       # 0x44a1f
callq 0x3a720
jmp 0x36fdf
movq -0x1b0(%rbp), %rdi
leaq 0x1c6fb(%rip), %rsi     # 0x536e8
leaq -0x30034(%rip), %rdx    # 0x6fc0
callq 0x43f0
movq -0x1b0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x41d0
jmp 0x3750d
callq 0x2fe60
cmpl $0x1e, (%rax)
jne 0x373ab
callq 0x2fe10
callq 0x2fe60
cmpl $0x3, (%rax)
jne 0x3716a
callq 0x2fe10
movq %rax, -0xb0(%rbp)
movl $0x2, -0xc0(%rbp)
movq $-0x1, -0xb8(%rbp)
movl $0x40, %edi
callq 0x4260
movq %rax, -0x1d0(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x1c8(%rbp)
movq -0xa8(%rbp), %rax
movq %rax, -0x1c0(%rbp)
movl $0x28, %edi
callq 0x4260
movq %rax, -0x1b8(%rbp)
jmp 0x37095
movq -0x1b8(%rbp), %rdi
movups -0xc0(%rbp), %xmm0
movaps %xmm0, -0xd0(%rbp)
movq -0xb0(%rbp), %rax
movl 0x10(%rax), %ecx
incl %ecx
movl -0xd0(%rbp), %esi
movq -0xc8(%rbp), %rdx
callq 0xe260
jmp 0x370ca
movq -0x10(%rbp), %rax
movl 0x8(%rax), %edi
decl %edi
movq -0xb0(%rbp), %rax
movl 0x10(%rax), %esi
callq 0x2feb0
movq %rax, -0x1d8(%rbp)
jmp 0x370eb
movq -0x1d8(%rbp), %r8
movq -0x1b8(%rbp), %rcx
movq -0x1c0(%rbp), %rdx
movq -0x1c8(%rbp), %rsi
movq -0x1d0(%rbp), %rdi
movq -0xb0(%rbp), %rax
movl 0x10(%rax), %r9d
incl %r9d
callq 0xd940
jmp 0x37123
movq -0x1d0(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x37500
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
jmp 0x37159
movq -0x1b8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x4240
movq -0x1d0(%rbp), %rdi
callq 0x4240
jmp 0x3750d
callq 0x369a0
movq %rax, -0xd8(%rbp)
movq -0xd8(%rbp), %rax
movl 0x10(%rax), %edi
callq 0x2b400
testb $0x1, %al
jne 0x3723b
movl $0x38, %edi
callq 0x4130
movq %rax, -0x1f0(%rbp)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %edi
movl %edi, %eax
incl %eax
movl %eax, -0x1e8(%rbp)
movq -0xd8(%rbp), %rax
movl 0xc(%rax), %esi
movl %esi, %eax
incl %eax
movl %eax, -0x1e4(%rbp)
callq 0x2feb0
movq %rax, -0x1e0(%rbp)
jmp 0x371d1
movq -0x1e0(%rbp), %rcx
movl -0x1e4(%rbp), %edx
movl -0x1e8(%rbp), %esi
movq -0x1f0(%rbp), %rdi
movq -0xd8(%rbp), %rax
movl 0x10(%rax), %r9d
leaq 0xd822(%rip), %r8       # 0x44a1f
callq 0x3a720
jmp 0x37204
movq -0x1f0(%rbp), %rdi
leaq 0x1c4d6(%rip), %rsi     # 0x536e8
leaq -0x30259(%rip), %rdx    # 0x6fc0
callq 0x43f0
movq -0x1f0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x41d0
jmp 0x3750d
callq 0x2fe60
cmpl $0x3, (%rax)
je 0x372e5
movl $0x28, %edi
callq 0x4130
movq %rax, -0x208(%rbp)
movq -0x30(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, %esi
movl %esi, %eax
incl %eax
movl %eax, -0x1fc(%rbp)
movq 0x1d194(%rip), %rdi     # 0x54408
callq 0xa7c0
movq %rax, -0x1f8(%rbp)
jmp 0x37282
movl -0x1fc(%rbp), %esi
movq -0x208(%rbp), %rdi
movq -0x1f8(%rbp), %rax
movq (%rax), %rdx
leaq 0x90cd(%rip), %rcx      # 0x4036d
leaq 0xd787(%rip), %r8       # 0x44a2e
callq 0x3a420
jmp 0x372ae
movq -0x208(%rbp), %rdi
leaq 0x1c3ec(%rip), %rsi     # 0x536a8
leaq -0x30353(%rip), %rdx    # 0x6f70
callq 0x43f0
movq -0x208(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x41d0
jmp 0x3750d
callq 0x2fe10
movq %rax, -0xe0(%rbp)
movl $0x40, %edi
callq 0x4260
movq %rax, -0x230(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x228(%rbp)
movq -0xa8(%rbp), %rcx
movq %rcx, -0x220(%rbp)
movq -0xd8(%rbp), %rcx
movq %rcx, -0x218(%rbp)
movl 0x8(%rax), %edi
decl %edi
movq -0xe0(%rbp), %rax
movl 0x10(%rax), %esi
callq 0x2feb0
movq %rax, -0x210(%rbp)
jmp 0x37346
movq -0x210(%rbp), %r8
movq -0x218(%rbp), %rcx
movq -0x220(%rbp), %rdx
movq -0x228(%rbp), %rsi
movq -0x230(%rbp), %rdi
movq -0xe0(%rbp), %rax
movl 0x10(%rax), %r9d
incl %r9d
callq 0xd940
jmp 0x3737e
movq -0x230(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x37500
movq -0x230(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x4240
jmp 0x3750d
callq 0x2fe60
cmpl $0x3, (%rax)
je 0x37455
movl $0x28, %edi
callq 0x4130
movq %rax, -0x248(%rbp)
movq -0x30(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, %esi
movl %esi, %eax
incl %eax
movl %eax, -0x23c(%rbp)
movq 0x1d024(%rip), %rdi     # 0x54408
callq 0xa7c0
movq %rax, -0x238(%rbp)
jmp 0x373f2
movl -0x23c(%rbp), %esi
movq -0x248(%rbp), %rdi
movq -0x238(%rbp), %rax
movq (%rax), %rdx
leaq 0x8f5d(%rip), %rcx      # 0x4036d
leaq 0xd617(%rip), %r8       # 0x44a2e
callq 0x3a420
jmp 0x3741e
movq -0x248(%rbp), %rdi
leaq 0x1c27c(%rip), %rsi     # 0x536a8
leaq -0x304c3(%rip), %rdx    # 0x6f70
callq 0x43f0
movq -0x248(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x41d0
jmp 0x3750d
callq 0x2fe10
movq %rax, -0xe8(%rbp)
movl $0x40, %edi
callq 0x4260
movq %rax, -0x268(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x260(%rbp)
movq -0xa8(%rbp), %rcx
movq %rcx, -0x258(%rbp)
movl 0x8(%rax), %edi
decl %edi
movq -0xe8(%rbp), %rax
movl 0x10(%rax), %esi
callq 0x2feb0
movq %rax, -0x250(%rbp)
jmp 0x374a8
movq -0x250(%rbp), %rcx
movq -0x258(%rbp), %rdx
movq -0x260(%rbp), %rsi
movq -0x268(%rbp), %rdi
movq -0xe8(%rbp), %rax
movl 0x10(%rax), %r8d
incl %r8d
callq 0xd8a0
jmp 0x374d9
movq -0x268(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x37500
movq -0x268(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x4240
jmp 0x3750d
movq -0x8(%rbp), %rax
addq $0x270, %rsp            # imm = 0x270
popq %rbp
retq
movq -0x20(%rbp), %rdi
callq 0x4420
nopw %cs:(%rax,%rax)