// File: rofl0r[P]ascc/cs_parser.cpp
// Function: evaluate_assignment(ccInternalList*, ccCompiledScript*, bool, int, long, long*, bool)
int evaluate_assignment(ccInternalList *targ, ccCompiledScript *scrip, bool expectCloseBracket, int cursym, long lilen, long *vnlist, bool insideBracketedDeclaration) {
    if (!sym.entries[cursym].is_loadable_variable()) {
        // allow through static properties
        if ((sym.get_type(cursym) == SYM_VARTYPE) && (lilen > 2) &&
            (sym.entries[vnlist[2]].flags & SFLG_STATIC))
        { }
        else {
            cc_error("variable required on left of assignment %s ", sym.get_name(cursym));
            return -1;
        }
    }
    bool isAccessingDynamicArray = false;

    if (((sym.entries[cursym].flags & SFLG_DYNAMICARRAY) != 0) && (lilen < 2))
    {
        if (sym.get_type(targ->peeknext()) != SYM_ASSIGN)
        {
            cc_error("invalid use of operator with array");
            return -1;
        }
        isAccessingDynamicArray = true;
    }
    else if (isRawPointer(cursym) && (lilen < 2)) { }
    else if (((sym.entries[cursym].flags & SFLG_ARRAY) != 0) && (lilen < 2))
    {
        cc_error("cannot assign value to entire array");
        return -1;
    }
    if (sym.entries[cursym].flags & SFLG_ISSTRING) {
        cc_error ("cannot assign to string; use Str* functions instead");
        return -1;
    }
    int MARIntactAssumption = 0;
    int asstype = targ->getnext();
    if (sym.get_type(asstype) == SYM_SASSIGN) {

        // ++ or --
        readonly_cannot_cause_error = 0;

        if (read_variable_into_ax(lilen,&vnlist[0],scrip, 1))
            return -1;

        int cpuOp = sym.entries[asstype].ssize;

        if (check_operator_valid_for_type(&cpuOp, scrip->ax_val_type, 0))
            return -1;

        int addend = 1;
        if (isRawPointer(cursym)) addend = sym.entries[cursym].ssize;

        scrip->write_cmd2(cpuOp, SREG_AX, addend);

        if (!readonly_cannot_cause_error) {
            MARIntactAssumption = 1;
            // since the MAR won't have changed, we can directly write
            // the value back to it without re-calculating the offset
            scrip->write_cmd1(get_readcmd_for_size(readcmd_lastcalledwith,1),SREG_AX);
        }
    }
    // not ++ or --, so we need to evaluate the RHS
    else if (evaluate_expression(targ,scrip,0,insideBracketedDeclaration) < 0)
        return -1;

    if (sym.get_type(asstype) == SYM_MASSIGN) {
        // it's a += or -=, so read in and adjust the result
        int cpuOp = sym.entries[asstype].ssize;

        if(isRawPointer(cursym) && sym.entries[cursym].ssize != 1) {
            if (!(cpuOp == SCMD_SUBREG || cpuOp == SCMD_ADDREG)) {
                cc_error("invalid operation for raw pointer");
                return -1;
            }
            // got to multiply the addend by pointed-to size
            scrip->write_cmd2(SCMD_LITTOREG, SREG_BX, sym.entries[cursym].ssize);
            scrip->write_cmd2(SCMD_MULREG, SREG_AX, SREG_BX);
        }

        // ax contains the addend
        scrip->push_reg(SREG_AX);
        int varTypeRHS = scrip->ax_val_type;

        if (read_variable_into_ax(lilen,&vnlist[0],scrip))
            return -1;
        if (check_type_mismatch(varTypeRHS, scrip->ax_val_type, 1))
            return -1;

        if (check_operator_valid_for_type(&cpuOp, varTypeRHS, scrip->ax_val_type))
            return -1;

        scrip->pop_reg(SREG_BX);
        scrip->write_cmd2(cpuOp, SREG_AX, SREG_BX);
    }

    if (sym.get_type(asstype) == SYM_ASSIGN) {
        // Convert normal literal string into String object
        int finalPartOfLHS = lilen - 1;
        if (sym.get_type(vnlist[lilen - 1]) == SYM_CLOSEBRACKET) {
            // deal with  a[1] = b
            finalPartOfLHS = findOpeningBracketOffs(lilen - 1, vnlist) - 1;
            if (finalPartOfLHS < 0) {
                cc_error("No [ for ] to match");
                return -1;
            }
        }
        PerformStringConversionInAX(scrip, &scrip->ax_val_type, sym.entries[vnlist[finalPartOfLHS]].vartype);
    }

    if (MARIntactAssumption) ;
    // so copy the result (currently in AX) into the variable
    else if (write_ax_to_variable(lilen,&vnlist[0],scrip))
        return -1;

    if(expectCloseBracket) {
        if (sym.get_type(targ->getnext()) != SYM_CLOSEPARENTHESIS) {
            cc_error("Expected ')'");
            return -1;
        }
    }
    else
        if (sym.get_type(targ->getnext()) != SYM_SEMICOLON) {
            cc_error("Expected ';'");
            return -1;
        }

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movb 0x10(%rbp), %al
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
andb $0x1, %dl
movb %dl, -0x19(%rbp)
movl %ecx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
andb $0x1, %al
movb %al, -0x31(%rbp)
movslq -0x20(%rbp), %rsi
leaq 0x32ecc(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq %rax, %rdi
callq 0x1e260
cmpl $0x0, %eax
jne 0xfa2d
movl -0x20(%rbp), %esi
leaq 0x32eac(%rip), %rdi     # 0x42870
callq 0x1e1e0
cmpl $0x2e, %eax
jne 0xf9ff
cmpq $0x2, -0x28(%rbp)
jle 0xf9ff
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rsi
leaq 0x32e8c(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq 0x28(%rax), %rax
andq $0x2000, %rax           # imm = 0x2000
cmpq $0x0, %rax
je 0xf9ff
jmp 0xfa2b
movl -0x20(%rbp), %esi
leaq 0x32e67(%rip), %rdi     # 0x42870
callq 0x1f730
movq %rax, %rsi
leaq 0x22ced(%rip), %rdi     # 0x32705
movb $0x0, %al
callq 0x1bac0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
jmp 0xfa2d
movb $0x0, -0x32(%rbp)
movslq -0x20(%rbp), %rsi
leaq 0x32e34(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq 0x28(%rax), %rax
andq $0x40000, %rax          # imm = 0x40000
cmpq $0x0, %rax
je 0xfa98
cmpq $0x2, -0x28(%rbp)
jge 0xfa98
movq -0x10(%rbp), %rdi
callq 0x1dd60
movl %eax, %esi
leaq 0x32e02(%rip), %rdi     # 0x42870
callq 0x1e1e0
cmpl $0x19, %eax
je 0xfa92
leaq 0x22cb2(%rip), %rdi     # 0x32731
movb $0x0, %al
callq 0x1bac0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
movb $0x1, -0x32(%rbp)
jmp 0xfaf5
movl -0x20(%rbp), %edi
callq 0xdb90
cmpl $0x0, %eax
je 0xfaae
cmpq $0x2, -0x28(%rbp)
jge 0xfaae
jmp 0xfaf3
movslq -0x20(%rbp), %rsi
leaq 0x32db7(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq 0x28(%rax), %rax
andq $0x2, %rax
cmpq $0x0, %rax
je 0xfaf1
cmpq $0x2, -0x28(%rbp)
jge 0xfaf1
leaq 0x22c76(%rip), %rdi     # 0x32754
movb $0x0, %al
callq 0x1bac0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
jmp 0xfaf3
jmp 0xfaf5
movslq -0x20(%rbp), %rsi
leaq 0x32d70(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq 0x28(%rax), %rax
andq $0x20, %rax
cmpq $0x0, %rax
je 0xfb31
leaq 0x22c5a(%rip), %rdi     # 0x32778
movb $0x0, %al
callq 0x1bac0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
movl $0x0, -0x38(%rbp)
movq -0x10(%rbp), %rdi
callq 0x1de00
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %esi
leaq 0x32d22(%rip), %rdi     # 0x42870
callq 0x1e1e0
cmpl $0x22, %eax
jne 0xfc50
movl $0x0, 0x32cde(%rip)     # 0x42844
movq -0x28(%rbp), %rax
movl %eax, %edi
movq -0x30(%rbp), %rsi
movq -0x18(%rbp), %rdx
movl $0x1, %ecx
xorl %r8d, %r8d
callq 0xf8e0
cmpl $0x0, %eax
je 0xfb92
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
movslq -0x3c(%rbp), %rsi
leaq 0x32cd3(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq 0x38(%rax), %rax
movl %eax, -0x40(%rbp)
movq -0x18(%rbp), %rax
movl 0x8d4c(%rax), %esi
leaq -0x40(%rbp), %rdi
xorl %edx, %edx
callq 0xa510
cmpl $0x0, %eax
je 0xfbd3
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
movl $0x1, -0x44(%rbp)
movl -0x20(%rbp), %edi
callq 0xdb90
cmpl $0x0, %eax
je 0xfc02
movslq -0x20(%rbp), %rsi
leaq 0x32c7e(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq 0x38(%rax), %rax
movl %eax, -0x44(%rbp)
movq -0x18(%rbp), %rdi
movl -0x40(%rbp), %esi
movl -0x44(%rbp), %ecx
movl $0x3, %edx
callq 0x25240
cmpl $0x0, 0x32c27(%rip)     # 0x42844
jne 0xfc4e
movl $0x1, -0x38(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x58(%rbp)
movl 0x32c0c(%rip), %edi     # 0x42840
movl $0x1, %esi
callq 0xb960
movq -0x58(%rbp), %rdi
movl %eax, %esi
movl $0x3, %edx
callq 0x25200
jmp 0xfc7a
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movb -0x31(%rbp), %al
xorl %edx, %edx
andb $0x1, %al
movzbl %al, %ecx
callq 0x7d10
cmpl $0x0, %eax
jge 0xfc78
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
jmp 0xfc7a
movl -0x3c(%rbp), %esi
leaq 0x32bec(%rip), %rdi     # 0x42870
callq 0x1e1e0
cmpl $0x1a, %eax
jne 0xfe04
movslq -0x3c(%rbp), %rsi
leaq 0x32bd3(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq 0x38(%rax), %rax
movl %eax, -0x48(%rbp)
movl -0x20(%rbp), %edi
callq 0xdb90
cmpl $0x0, %eax
je 0xfd4c
movslq -0x20(%rbp), %rsi
leaq 0x32ba7(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
cmpq $0x1, 0x38(%rax)
je 0xfd4c
cmpl $0xc, -0x48(%rbp)
je 0xfcff
cmpl $0xb, -0x48(%rbp)
je 0xfcff
leaq 0x22ac0(%rip), %rdi     # 0x327ac
movb $0x0, %al
callq 0x1bac0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
movq -0x18(%rbp), %rax
movq %rax, -0x60(%rbp)
movslq -0x20(%rbp), %rsi
leaq 0x32b5e(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq -0x60(%rbp), %rdi
movq 0x38(%rax), %rax
movl %eax, %ecx
movl $0x6, %esi
movl $0x4, %edx
callq 0x25240
movq -0x18(%rbp), %rdi
movl $0x9, %esi
movl $0x3, %edx
movl $0x4, %ecx
callq 0x25240
movq -0x18(%rbp), %rdi
movl $0x3, %esi
callq 0x252f0
movq -0x18(%rbp), %rax
movl 0x8d4c(%rax), %eax
movl %eax, -0x4c(%rbp)
movq -0x28(%rbp), %rax
movl %eax, %edi
movq -0x30(%rbp), %rsi
movq -0x18(%rbp), %rdx
xorl %r8d, %r8d
movl %r8d, %ecx
callq 0xf8e0
cmpl $0x0, %eax
je 0xfd91
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
movl -0x4c(%rbp), %edi
movq -0x18(%rbp), %rax
movl 0x8d4c(%rax), %esi
movl $0x1, %edx
callq 0xa7c0
cmpl $0x0, %eax
je 0xfdb9
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
movl -0x4c(%rbp), %esi
movq -0x18(%rbp), %rax
movl 0x8d4c(%rax), %edx
leaq -0x48(%rbp), %rdi
callq 0xa510
cmpl $0x0, %eax
je 0xfde0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
movq -0x18(%rbp), %rdi
movl $0x4, %esi
callq 0x25330
movq -0x18(%rbp), %rdi
movl -0x48(%rbp), %esi
movl $0x3, %edx
movl $0x4, %ecx
callq 0x25240
movl -0x3c(%rbp), %esi
leaq 0x32a62(%rip), %rdi     # 0x42870
callq 0x1e1e0
cmpl $0x19, %eax
jne 0xfec8
movq -0x28(%rbp), %rax
subq $0x1, %rax
movl %eax, -0x50(%rbp)
movq -0x30(%rbp), %rax
movq -0x28(%rbp), %rcx
subq $0x1, %rcx
movq (%rax,%rcx,8), %rax
movl %eax, %esi
leaq 0x32a30(%rip), %rdi     # 0x42870
callq 0x1e1e0
cmpl $0x8, %eax
jne 0xfe85
movq -0x28(%rbp), %rax
subq $0x1, %rax
movl %eax, %edi
movq -0x30(%rbp), %rsi
callq 0xb740
subl $0x1, %eax
movl %eax, -0x50(%rbp)
cmpl $0x0, -0x50(%rbp)
jge 0xfe83
leaq 0x2295e(%rip), %rdi     # 0x327ce
movb $0x0, %al
callq 0x1bac0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
jmp 0xfe85
movq -0x18(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x18(%rbp), %rax
addq $0x8d4c, %rax           # imm = 0x8D4C
movq %rax, -0x68(%rbp)
movq -0x30(%rbp), %rax
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0x329c2(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq -0x70(%rbp), %rdi
movq -0x68(%rbp), %rsi
movswl 0x30(%rax), %edx
callq 0xb5a0
cmpl $0x0, -0x38(%rbp)
je 0xfed0
jmp 0xfef3
movq -0x28(%rbp), %rax
movl %eax, %edi
movq -0x30(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0xf930
cmpl $0x0, %eax
je 0xfef1
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
jmp 0xfef3
testb $0x1, -0x19(%rbp)
je 0xff2e
movq -0x10(%rbp), %rdi
callq 0x1de00
movl %eax, %esi
leaq 0x32965(%rip), %rdi     # 0x42870
callq 0x1e1e0
cmpl $0x6, %eax
je 0xff2c
leaq 0x228c6(%rip), %rdi     # 0x327e2
movb $0x0, %al
callq 0x1bac0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
jmp 0xff63
movq -0x10(%rbp), %rdi
callq 0x1de00
movl %eax, %esi
leaq 0x32930(%rip), %rdi     # 0x42870
callq 0x1e1e0
cmpl $0x28, %eax
je 0xff61
leaq 0x2289e(%rip), %rdi     # 0x327ef
movb $0x0, %al
callq 0x1bac0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xff6a
jmp 0xff63
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x70, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)