// File: AshOlogn[P]ash-language-interpreter/src/parser.cpp
// Function: evalPrefixCastSignNot()
AbstractExpressionNode* evalPrefixCastSignNot() {
 
  //check if prefix
  if(isPrefixStructure()) {

    Token* firstPlus = consume();
    Token* secondPlus = consume(); //consume second +

    AbstractExpressionNode* head = evalPostfixMemberAccess();
    VariableNode* varNode = dynamic_cast<VariableNode*>(head);

    //if it's not a variable, throw a syntax error
    if(!varNode) {
      throw ParseSyntaxError(firstPlus->line+1, head->endLine, getCodeLineBlock(firstPlus->line, head->endLine-1), "Prefix operator expects variable argument");
    }

    ParseDataType type = varNode->evalType;
    ParseOperatorType op = (firstPlus->type == ADD) ? PREFIX_INC_OP : PREFIX_DEC_OP;

    //if it's not a number, throw a type error
    if(!typecheckUnaryExpression(op, type)) {
      throw StaticTypeError(firstPlus->line+1, head->endLine, getCodeLineBlock(firstPlus->line, head->endLine-1), (op == PREFIX_INC_OP) ? "prefix increment" : "prefix decrement", type);
    }

    return new UnaryOperatorNode(op, varNode, symbolTable, firstPlus->line+1);

  } else if(isSignNotTokenType(peek()->type)) {

    Token* signNotToken = consume();
    ParseOperatorType op = unaryTokenConversion(signNotToken->type);
    AbstractExpressionNode* next = evalPrefixCastSignNot();

    if(typecheckUnaryExpression(op, next->evalType)) {
      return new UnaryOperatorNode(op, next, signNotToken->line+1);
    } else {
      //if type mismatch, throw error
      throw StaticTypeError(signNotToken->line+1, next->endLine+1, getCodeLineBlock(signNotToken->line, next->endLine), toWordParseOperatorType(op), next->evalType);
    }

  } else if(isCastStructure()) {   
    
    Token* leftParenToken = consume(); //consume (
		Token* typeToken = consume();
    ParseDataType finalType = typeTokenConversion(typeToken->type);
    Token* rightParenToken = consume(); //consume ')'

		//if there is no closing ')', throw error
		if(rightParenToken->type != RIGHT_PAREN) {

			uint32_t startLine = leftParenToken->line+1;
			uint32_t endLine = (rightParenToken->type == END) ? typeToken->line+1 : rightParenToken->line+1;

			if(rightParenToken->type == END) {
				throw ParseSyntaxError(startLine, endLine, getCodeLineBlock(startLine-1, endLine-1), "Expected ')' to end cast operation");
			} else {
				throw ParseSyntaxError(startLine, endLine, getCodeLineBlock(startLine-1, endLine-1), rightParenToken->lexeme, "Expected ')' to end cast operation");
			}
		}
    
    AbstractExpressionNode* next = evalPrefixCastSignNot();
    if(typecheckExplicitCastExpression(next->evalType, finalType)) {
      return new CastNode(next, finalType, leftParenToken->line+1);
    } else {
      throw StaticCastError(leftParenToken->line+1, next->endLine, getCodeLineBlock(leftParenToken->line, next->endLine-1), next->evalType, finalType, true);
    }
    
  } else {

    return evalPostfixMemberAccess();  
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x160, %rsp            # imm = 0x160
callq 0x37ab0
testb $0x1, %al
jne 0x37b29
jmp 0x37d9d
callq 0x2fe10
movq %rax, -0x10(%rbp)
callq 0x2fe10
movq %rax, -0x18(%rbp)
callq 0x37520
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x90(%rbp)
cmpq $0x0, %rax
je 0x37b7c
movq -0x90(%rbp), %rdi
leaq 0x1bf6d(%rip), %rsi     # 0x53ad0
leaq 0x1bf06(%rip), %rdx     # 0x53a70
xorl %eax, %eax
movl %eax, %ecx
callq 0x42b0
movq %rax, -0x98(%rbp)
jmp 0x37b87
xorl %eax, %eax
movq %rax, -0x98(%rbp)
jmp 0x37b87
movq -0x98(%rbp), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0x37c3b
movl $0x28, %edi
callq 0x4130
movq %rax, -0xb0(%rbp)
movq -0x10(%rbp), %rax
movl 0x10(%rax), %edi
movl %edi, %eax
incl %eax
movl %eax, -0xa8(%rbp)
movq -0x20(%rbp), %rax
movl 0xc(%rax), %esi
movl %esi, -0xa4(%rbp)
decl %esi
callq 0x2feb0
movq %rax, -0xa0(%rbp)
jmp 0x37bdc
movq -0xa0(%rbp), %rcx
movl -0xa4(%rbp), %edx
movl -0xa8(%rbp), %esi
movq -0xb0(%rbp), %rdi
leaq 0xce5a(%rip), %r8       # 0x44a57
callq 0x3a230
jmp 0x37c04
movq -0xb0(%rbp), %rdi
leaq 0x1ba96(%rip), %rsi     # 0x536a8
leaq -0x30ca9(%rip), %rdx    # 0x6f70
callq 0x43f0
movq -0xb0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
callq 0x41d0
jmp 0x38204
movq -0x28(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %edx
movl $0x3, %eax
movl $0x2, %ecx
cmpl $0x7, %edx
cmovel %ecx, %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %edi
movl -0x38(%rbp), %esi
callq 0x2b5d0
testb $0x1, %al
jne 0x37d39
movl $0x38, %edi
callq 0x4130
movq %rax, -0xc8(%rbp)
movq -0x10(%rbp), %rax
movl 0x10(%rax), %edi
movl %edi, %eax
incl %eax
movl %eax, -0xc0(%rbp)
movq -0x20(%rbp), %rax
movl 0xc(%rax), %esi
movl %esi, -0xbc(%rbp)
decl %esi
callq 0x2feb0
movq %rax, -0xb8(%rbp)
jmp 0x37cb0
cmpl $0x2, -0x3c(%rbp)
jne 0x37cc6
leaq 0x8379(%rip), %rax      # 0x40036
movq %rax, -0xd0(%rbp)
jmp 0x37cd6
leaq 0x837a(%rip), %rax      # 0x40047
movq %rax, -0xd0(%rbp)
jmp 0x37cd6
movq -0xb8(%rbp), %rcx
movl -0xbc(%rbp), %edx
movl -0xc0(%rbp), %esi
movq -0xc8(%rbp), %rdi
movq -0xd0(%rbp), %r8
movl -0x38(%rbp), %r9d
callq 0x3a720
jmp 0x37d02
movq -0xc8(%rbp), %rdi
leaq 0x1b9d8(%rip), %rsi     # 0x536e8
leaq -0x30d57(%rip), %rdx    # 0x6fc0
callq 0x43f0
movq -0xc8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
callq 0x41d0
jmp 0x38204
movl $0x30, %edi
callq 0x4260
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xd8(%rbp)
movl -0x3c(%rbp), %esi
movq -0x28(%rbp), %rdx
movq 0x1c6b2(%rip), %rcx     # 0x54410
movq -0x10(%rbp), %rax
movl 0x10(%rax), %r8d
incl %r8d
callq 0xd070
jmp 0x37d70
movq -0xd8(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x381f7
movq -0xd8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
callq 0x4240
jmp 0x38204
callq 0x2fe60
movl (%rax), %edi
callq 0x82e0
testb $0x1, %al
jne 0x37db2
jmp 0x37efb
callq 0x2fe10
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movl (%rax), %edi
callq 0xb6a0
movl %eax, -0x4c(%rbp)
callq 0x37b10
movq %rax, -0x58(%rbp)
movl -0x4c(%rbp), %edi
movq -0x58(%rbp), %rax
movl 0x10(%rax), %esi
callq 0x2b5d0
testb $0x1, %al
jne 0x37de7
jmp 0x37e42
movl $0x30, %edi
callq 0x4260
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xe0(%rbp)
movl -0x4c(%rbp), %esi
movq -0x58(%rbp), %rdx
movq -0x48(%rbp), %rax
movl 0x10(%rax), %ecx
incl %ecx
callq 0xcfd0
jmp 0x37e15
movq -0xe0(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x381f7
movq -0xe0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
callq 0x4240
jmp 0x38204
movl $0x38, %edi
callq 0x4130
movq %rax, -0xf8(%rbp)
movq -0x48(%rbp), %rax
movl 0x10(%rax), %edi
movl %edi, %eax
incl %eax
movl %eax, -0xf0(%rbp)
movq -0x58(%rbp), %rax
movl 0xc(%rax), %esi
movl %esi, %eax
incl %eax
movl %eax, -0xec(%rbp)
callq 0x2feb0
movq %rax, -0xe8(%rbp)
jmp 0x37e83
movl -0x4c(%rbp), %edi
callq 0xbc30
movq %rax, -0x100(%rbp)
jmp 0x37e94
movq -0x100(%rbp), %r8
movq -0xe8(%rbp), %rcx
movl -0xec(%rbp), %edx
movl -0xf0(%rbp), %esi
movq -0xf8(%rbp), %rdi
movq -0x58(%rbp), %rax
movl 0x10(%rax), %r9d
callq 0x3a720
jmp 0x37ec4
movq -0xf8(%rbp), %rdi
leaq 0x1b816(%rip), %rsi     # 0x536e8
leaq -0x30f19(%rip), %rdx    # 0x6fc0
callq 0x43f0
movq -0xf8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
callq 0x41d0
jmp 0x38204
callq 0x37a50
testb $0x1, %al
jne 0x37f09
jmp 0x381ee
callq 0x2fe10
movq %rax, -0x60(%rbp)
callq 0x2fe10
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movl (%rax), %edi
callq 0xb5e0
movl %eax, -0x6c(%rbp)
callq 0x2fe10
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
cmpl $0x1, (%rax)
je 0x380bd
movq -0x60(%rbp), %rax
movl 0x10(%rax), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
movq -0x78(%rbp), %rax
cmpl $0x4e, (%rax)
jne 0x37f67
movq -0x68(%rbp), %rax
movl 0x10(%rax), %eax
addl $0x1, %eax
movl %eax, -0x104(%rbp)
jmp 0x37f77
movq -0x78(%rbp), %rax
movl 0x10(%rax), %eax
addl $0x1, %eax
movl %eax, -0x104(%rbp)
movl -0x104(%rbp), %eax
movl %eax, -0x80(%rbp)
movq -0x78(%rbp), %rax
cmpl $0x4e, (%rax)
jne 0x38021
movl $0x28, %edi
callq 0x4130
movq %rax, -0x120(%rbp)
movl -0x7c(%rbp), %edi
movl %edi, -0x118(%rbp)
movl -0x80(%rbp), %esi
movl %esi, -0x114(%rbp)
decl %edi
decl %esi
callq 0x2feb0
movq %rax, -0x110(%rbp)
jmp 0x37fc2
movq -0x110(%rbp), %rcx
movl -0x114(%rbp), %edx
movl -0x118(%rbp), %esi
movq -0x120(%rbp), %rdi
leaq 0xca9e(%rip), %r8       # 0x44a81
callq 0x3a230
jmp 0x37fea
movq -0x120(%rbp), %rdi
leaq 0x1b6b0(%rip), %rsi     # 0x536a8
leaq -0x3108f(%rip), %rdx    # 0x6f70
callq 0x43f0
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
callq 0x41d0
jmp 0x38204
movl $0x28, %edi
callq 0x4130
movq %rax, -0x138(%rbp)
movl -0x7c(%rbp), %edi
movl %edi, -0x130(%rbp)
movl -0x80(%rbp), %esi
movl %esi, -0x12c(%rbp)
decl %edi
decl %esi
callq 0x2feb0
movq %rax, -0x128(%rbp)
jmp 0x38056
movq -0x128(%rbp), %rcx
movl -0x12c(%rbp), %edx
movl -0x130(%rbp), %esi
movq -0x138(%rbp), %rdi
movq -0x78(%rbp), %rax
movq 0x18(%rax), %r8
leaq 0xca02(%rip), %r9       # 0x44a81
callq 0x3a2a0
jmp 0x38086
movq -0x138(%rbp), %rdi
leaq 0x1b614(%rip), %rsi     # 0x536a8
leaq -0x3112b(%rip), %rdx    # 0x6f70
callq 0x43f0
movq -0x138(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
callq 0x41d0
jmp 0x38204
callq 0x37b10
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
movl 0x10(%rax), %edi
movl -0x6c(%rbp), %esi
callq 0x2b540
testb $0x1, %al
jne 0x380e1
jmp 0x3813f
movl $0x28, %edi
callq 0x4260
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x140(%rbp)
movq -0x88(%rbp), %rsi
movl -0x6c(%rbp), %edx
movq -0x60(%rbp), %rax
movl 0x10(%rax), %ecx
incl %ecx
callq 0xd6b0
jmp 0x38112
movq -0x140(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x381f7
movq -0x140(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
callq 0x4240
jmp 0x38204
movl $0x30, %edi
callq 0x4130
movq %rax, -0x158(%rbp)
movq -0x60(%rbp), %rax
movl 0x10(%rax), %edi
movl %edi, %eax
incl %eax
movl %eax, -0x150(%rbp)
movq -0x88(%rbp), %rax
movl 0xc(%rax), %esi
movl %esi, -0x14c(%rbp)
decl %esi
callq 0x2feb0
movq %rax, -0x148(%rbp)
jmp 0x38181
movq -0x148(%rbp), %rcx
movl -0x14c(%rbp), %edx
movl -0x150(%rbp), %esi
movq -0x158(%rbp), %rdi
movq -0x88(%rbp), %rax
movl 0x10(%rax), %r8d
movl -0x6c(%rbp), %r9d
movq %rsp, %rax
movl $0x1, (%rax)
callq 0x3a7a0
jmp 0x381ba
movq -0x158(%rbp), %rdi
leaq 0x1b5a0(%rip), %rsi     # 0x53768
leaq -0x3114f(%rip), %rdx    # 0x7080
callq 0x43f0
movq -0x158(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
callq 0x41d0
jmp 0x38204
callq 0x37520
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x160, %rsp            # imm = 0x160
popq %rbp
retq
movq -0x30(%rbp), %rdi
callq 0x4420
nopl (%rax)