// File: /workspace/github_cpp_makefile_star2_O2/s0sasaki[P]ExecutableBlockchain/compiler.cpp
// Function: Compiler::compile(int*, char const*, unsigned int)
void Compiler::compile(int32_t *bin_data, const char *src_data, uint32_t bc_length) {
    std::vector<std::string> strtable;
    int32_t rsp = 0;
    int32_t rspbuf[256];
    int32_t i    = 0;
    int32_t midx = 2; 
    bool capture = false;
    std::string recur = "";
    read(strtable, src_data);
    while(i < strtable.size()) {
        std::string wordstr = strtable[i++];

        if(var_dict.count(wordstr)>0){
            bin_data[midx++] = VM::OP_PUSH;
            bin_data[midx++] = var_dict[wordstr];
            continue;
        }
        
        if(wordstr == "VARIABLE"){
            var_dict[strtable[i]] = (int32_t) stoi(strtable[i+1]);
            i+=2;
            continue;
        }

        if(capture) {
            func_dict[wordstr] = std::make_pair(midx, bc_length);
            capture = false;
            recur = wordstr;
            continue;
        }

        if(wordstr == ":")    {
            capture = true;
            continue;
        }

        if(wordstr == ";")    {
            bin_data[midx++] = VM::OP_RET;
            recur       = "";
            continue;
        }

        if(func_dict.count(wordstr) > 0){
            if(recur == wordstr && strtable[i] == "THEN" && strtable[i+1] == ";") {
                bin_data[midx++] = VM::OP_JMP;
                bin_data[midx++] = func_dict[wordstr].first;
                continue;
            }
            bin_data[midx++] = VM::OP_CALL;
            bin_data[midx++] = func_dict[wordstr].second;
            bin_data[midx++] = func_dict[wordstr].first;
            continue;
        }

        if(isNum(wordstr.c_str())) {
            bin_data[midx++] = VM::OP_PUSH;
            int32_t val = stoi(wordstr);
            bin_data[midx++] = val;
            continue;
        }

        if(wordstr == "IF") {
            bin_data[midx++] = VM::OP_JZ;
            rspbuf[++rsp] = midx++;
            continue;
        }

        if(wordstr == "ELSE") {
            int32_t rsptemp = rspbuf[rsp--];
            bin_data[midx++] = VM::OP_JMP;
            rspbuf[++rsp] = midx++;
            bin_data[rsptemp] = midx;
            continue;
        }

        if(wordstr == "THEN") {
            int32_t rsptemp = rspbuf[rsp--];
            bin_data[rsptemp] = midx;
            continue;
        }

        if(wordstr == "+")    { bin_data[midx++] = VM::OP_ADD;   continue; }
        if(wordstr == "-")    { bin_data[midx++] = VM::OP_SUB;   continue; }
        if(wordstr == "*")    { bin_data[midx++] = VM::OP_MUL;   continue; }
        if(wordstr == "/")    { bin_data[midx++] = VM::OP_DIV;   continue; }
        if(wordstr == ".")    { bin_data[midx++] = VM::OP_DOT;   continue; }
        if(wordstr == "<=")   { bin_data[midx++] = VM::OP_GE;    continue; }
        if(wordstr == ">=")   { bin_data[midx++] = VM::OP_LE;    continue; }
        if(wordstr == "<")    { bin_data[midx++] = VM::OP_GNE;   continue; }
        if(wordstr == ">")    { bin_data[midx++] = VM::OP_LNE;   continue; }
        if(wordstr == "HALT") { bin_data[midx++] = VM::OP_HALT;  continue; }
        if(wordstr == "POP")  { bin_data[midx++] = VM::OP_POP;   continue; }
        if(wordstr == "DROP") { bin_data[midx++] = VM::OP_DROP;  continue; }
        if(wordstr == "DUP")  { bin_data[midx++] = VM::OP_DUP;   continue; }
        if(wordstr == "OVER") { bin_data[midx++] = VM::OP_OVER;  continue; }
        if(wordstr == "SWAP") { bin_data[midx++] = VM::OP_SWAP;  continue; }
        if(wordstr == "@")    { bin_data[midx++] = VM::OP_LOAD;  continue; }
        if(wordstr == "!")    { bin_data[midx++] = VM::OP_STORE; continue; }

        std::cout << "ERROR UNKNOWN WORD: " << wordstr << std::endl;
        for(int32_t i = 0; i < Block::DATA_SIZE; i++) {
            bin_data[i] = VM::OP_HALT;
        }
        return;
    }
    if (func_dict.count("MAIN") > 0 && func_dict["MAIN"].second == bc_length ){
        bin_data[0]  = VM::OP_JMP;
        bin_data[1]  = func_dict["MAIN"].first;
    } else {
        bin_data[0]  = VM::OP_HALT;
        bin_data[1]  = VM::OP_HALT;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x4b8, %rsp            # imm = 0x4B8
movl %ecx, -0x74(%rbp)
movq %rdx, %r14
movq %rsi, %rbx
movq %rdi, %r15
xorps %xmm0, %xmm0
movaps %xmm0, -0xa0(%rbp)
andq $0x0, -0x90(%rbp)
leaq 0x380d(%rip), %rsi      # 0x631a
leaq -0xc0(%rbp), %rdi
leaq -0x60(%rbp), %rdx
callq 0x20a0
movq %rbx, -0x38(%rbp)
leaq -0xa0(%rbp), %rsi
movq %r15, %rdi
movq %r14, %rdx
callq 0x29f4
leaq 0x30(%r15), %rax
movq %rax, -0x68(%rbp)
movq $0x0, -0x40(%rbp)
pushq $0x2
popq %r13
leaq -0x60(%rbp), %r14
xorl %r12d, %r12d
movl $0x0, -0x6c(%rbp)
movq %r15, -0x80(%rbp)
movq %r13, %rbx
movslq %r12d, %r13
movq -0xa0(%rbp), %rsi
movq -0x98(%rbp), %rax
subq %rsi, %rax
sarq $0x5, %rax
cmpq %r13, %rax
jbe 0x31e2
shlq $0x5, %r13
addq %r13, %rsi
movq %r14, %rdi
callq 0x2240
movq %r15, %rdi
movq %r14, %rsi
callq 0x3342
leal 0x1(%r12), %r14d
movq %rbx, %rcx
movslq %ecx, %r15
testq %rax, %rax
je 0x2be0
movl %r14d, %r12d
movq -0x38(%rbp), %rax
movl $0x9, (%rax,%r15,4)
movq -0x80(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x3366
movl (%rax), %eax
leal 0x2(%r15), %r13d
movq -0x38(%rbp), %rcx
movl %eax, 0x4(%rcx,%r15,4)
movb $0x1, %bl
leaq -0x60(%rbp), %r14
movl %r12d, %r15d
jmp 0x2c9e
leaq -0x60(%rbp), %rdi
leaq 0x3543(%rip), %rsi      # 0x612e
callq 0x33cf
movl %r14d, -0x2c(%rbp)
movslq %r14d, %r14
testb %al, %al
je 0x2c3e
movq -0xa0(%rbp), %rax
leaq (%rax,%r13), %rdi
addq $0x40, %rdi
xorl %esi, %esi
pushq $0xa
popq %rdx
callq 0x33df
movl %eax, %r15d
shlq $0x5, %r14
addq -0xa0(%rbp), %r14
movq -0x80(%rbp), %rdi
movq %r14, %rsi
callq 0x3366
movl %r15d, (%rax)
addl $0x3, %r12d
movl %r12d, %r15d
leaq -0x60(%rbp), %r14
jmp 0x2c99
testb $0x1, -0x40(%rbp)
je 0x2c75
movq -0x68(%rbp), %rdi
leaq -0x60(%rbp), %r14
movq %r14, %rsi
callq 0x3400
movl %ebx, (%rax)
movl -0x74(%rbp), %ecx
movl %ecx, 0x4(%rax)
leaq -0xc0(%rbp), %rdi
movq %r14, %rsi
callq 0x2100
movq $0x0, -0x40(%rbp)
jmp 0x2c95
leaq -0x60(%rbp), %r12
movq %r12, %rdi
leaq 0x34b4(%rip), %rsi      # 0x6137
callq 0x33cf
testb %al, %al
je 0x2cba
movb $0x1, %al
movq %rax, -0x40(%rbp)
movq %r12, %r14
movl -0x2c(%rbp), %r15d
movq %rbx, %r13
movb $0x1, %bl
movq %r14, %rdi
callq 0x20d0
movl %r15d, %r12d
testb %bl, %bl
movq -0x80(%rbp), %r15
jne 0x2b59
jmp 0x32a6
movq %r12, %rdi
leaq 0x3475(%rip), %rsi      # 0x6139
callq 0x33cf
testb %al, %al
je 0x2cf4
movq -0x38(%rbp), %rax
andl $0x0, (%rax,%r15,4)
leaq -0xc0(%rbp), %rdi
leaq 0x3636(%rip), %rsi      # 0x631a
callq 0x22d0
movq %rbx, %r13
incl %r13d
jmp 0x2dc5
movq -0x68(%rbp), %rdi
movq %r12, %rsi
callq 0x346a
testq %rax, %rax
je 0x2dda
leaq -0xc0(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x348e
testb %al, %al
je 0x2d84
shlq $0x5, %r14
addq -0xa0(%rbp), %r14
movq %r14, %rdi
leaq 0x3409(%rip), %rsi      # 0x613b
callq 0x33cf
testb %al, %al
je 0x2d84
movq -0xa0(%rbp), %rax
leaq (%rax,%r13), %rdi
addq $0x40, %rdi
leaq 0x33e8(%rip), %rsi      # 0x6139
callq 0x33cf
testb %al, %al
je 0x2d84
movq -0x38(%rbp), %rax
movl $0x2, (%rax,%r15,4)
movq -0x68(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x3400
movl (%rax), %eax
leal 0x2(%r15), %r13d
movq -0x38(%rbp), %rcx
movl %eax, 0x4(%rcx,%r15,4)
jmp 0x2dc5
movq -0x38(%rbp), %rax
movl $0x1, (%rax,%r15,4)
movq -0x68(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x3400
movl 0x4(%rax), %eax
movq -0x38(%rbp), %rcx
movl %eax, 0x4(%rcx,%r15,4)
movq -0x68(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x3400
movl (%rax), %eax
leal 0x3(%r15), %r13d
movq -0x38(%rbp), %rcx
movl %eax, 0x8(%rcx,%r15,4)
movq $0x0, -0x40(%rbp)
leaq -0x60(%rbp), %r14
movl -0x2c(%rbp), %r15d
jmp 0x2c9c
movq -0x60(%rbp), %rsi
movq -0x80(%rbp), %rdi
callq 0x34b2
testb %al, %al
je 0x2e1e
movq -0x38(%rbp), %r12
movl $0x9, (%r12,%r15,4)
leaq -0x60(%rbp), %r14
movq %r14, %rdi
xorl %esi, %esi
pushq $0xa
popq %rdx
callq 0x33df
movq %rbx, %r13
addl $0x2, %r13d
movl %eax, 0x4(%r12,%r15,4)
movq $0x0, -0x40(%rbp)
jmp 0x2dd1
movq %r12, %rdi
leaq 0x3318(%rip), %rsi      # 0x6140
callq 0x33cf
movslq -0x6c(%rbp), %r14
testb %al, %al
movq %rbx, %r13
je 0x2e5d
leal 0x1(%r13), %eax
movq -0x38(%rbp), %rcx
movl $0x3, (%rcx,%r15,4)
addl $0x2, %r13d
leal 0x1(%r14), %ecx
movl %ecx, -0x6c(%rbp)
movl %eax, -0x4dc(%rbp,%r14,4)
jmp 0x2ec4
movq %r12, %rdi
leaq 0x32dc(%rip), %rsi      # 0x6143
callq 0x33cf
testb %al, %al
je 0x2e9a
movslq -0x4e0(%rbp,%r14,4), %rax
leal 0x1(%r13), %ecx
movq -0x38(%rbp), %rbx
movl $0x2, (%rbx,%r15,4)
addl $0x2, %r13d
movl %ecx, -0x4e0(%rbp,%r14,4)
movl %r13d, (%rbx,%rax,4)
jmp 0x2ec4
movq %r12, %rdi
leaq 0x3297(%rip), %rsi      # 0x613b
callq 0x33cf
testb %al, %al
je 0x2ed4
leal -0x1(%r14), %eax
movl %eax, -0x6c(%rbp)
movslq -0x4e0(%rbp,%r14,4), %rax
movq -0x38(%rbp), %rcx
movl %r13d, (%rcx,%rax,4)
movq $0x0, -0x40(%rbp)
movq %r12, %r14
jmp 0x2dd1
movq %r12, %rdi
leaq 0x326a(%rip), %rsi      # 0x6148
callq 0x33cf
testb %al, %al
movq %r12, %r14
je 0x2eff
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0xf, (%rax,%r15,4)
jmp 0x2e14
movq %r14, %rdi
leaq 0x3241(%rip), %rsi      # 0x614a
callq 0x33cf
testb %al, %al
je 0x2f27
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0x10, (%rax,%r15,4)
jmp 0x2e14
movq %r14, %rdi
leaq 0x321b(%rip), %rsi      # 0x614c
callq 0x33cf
testb %al, %al
je 0x2f4f
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0x11, (%rax,%r15,4)
jmp 0x2e14
movq %r14, %rdi
leaq 0x31f5(%rip), %rsi      # 0x614e
callq 0x33cf
testb %al, %al
je 0x2f77
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0x12, (%rax,%r15,4)
jmp 0x2e14
movq %r14, %rdi
leaq 0x31cf(%rip), %rsi      # 0x6150
callq 0x33cf
testb %al, %al
je 0x2f9f
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0x13, (%rax,%r15,4)
jmp 0x2e14
movq %r14, %rdi
leaq 0x31a9(%rip), %rsi      # 0x6152
callq 0x33cf
testb %al, %al
je 0x2fc7
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0x5, (%rax,%r15,4)
jmp 0x2e14
movq %r14, %rdi
leaq 0x3184(%rip), %rsi      # 0x6155
callq 0x33cf
testb %al, %al
je 0x2fef
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0x6, (%rax,%r15,4)
jmp 0x2e14
movq %r14, %rdi
leaq 0x315f(%rip), %rsi      # 0x6158
callq 0x33cf
testb %al, %al
je 0x3017
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0x7, (%rax,%r15,4)
jmp 0x2e14
movq %r14, %rdi
leaq 0x3139(%rip), %rsi      # 0x615a
callq 0x33cf
testb %al, %al
je 0x303f
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0x8, (%rax,%r15,4)
jmp 0x2dc5
leaq -0x60(%rbp), %rdi
leaq 0x3112(%rip), %rsi      # 0x615c
callq 0x33cf
testb %al, %al
je 0x3068
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0x14, (%rax,%r15,4)
jmp 0x2dc5
leaq -0x60(%rbp), %rdi
leaq 0x30ee(%rip), %rsi      # 0x6161
callq 0x33cf
testb %al, %al
je 0x3091
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0xa, (%rax,%r15,4)
jmp 0x2dc5
leaq -0x60(%rbp), %rdi
leaq 0x30c9(%rip), %rsi      # 0x6165
callq 0x33cf
testb %al, %al
je 0x30ba
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0xe, (%rax,%r15,4)
jmp 0x2dc5
leaq -0x60(%rbp), %rdi
leaq 0x30a5(%rip), %rsi      # 0x616a
callq 0x33cf
testb %al, %al
je 0x30e3
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0xb, (%rax,%r15,4)
jmp 0x2dc5
leaq -0x60(%rbp), %rdi
leaq 0x3080(%rip), %rsi      # 0x616e
callq 0x33cf
testb %al, %al
je 0x310c
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0xc, (%rax,%r15,4)
jmp 0x2dc5
leaq -0x60(%rbp), %rdi
leaq 0x305c(%rip), %rsi      # 0x6173
callq 0x33cf
testb %al, %al
je 0x3135
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0xd, (%rax,%r15,4)
jmp 0x2dc5
leaq -0x60(%rbp), %rdi
leaq 0x3038(%rip), %rsi      # 0x6178
callq 0x33cf
testb %al, %al
je 0x315e
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0x16, (%rax,%r15,4)
jmp 0x2dc5
leaq -0x60(%rbp), %rdi
leaq 0x3011(%rip), %rsi      # 0x617a
callq 0x33cf
testb %al, %al
je 0x3187
leal 0x1(%r15), %r13d
movq -0x38(%rbp), %rax
movl $0x17, (%rax,%r15,4)
jmp 0x2dc5
movq 0x6e42(%rip), %rdi      # 0x9fd0
leaq 0x2fe7(%rip), %rsi      # 0x617c
callq 0x21e0
movq %rax, %rdi
leaq -0x60(%rbp), %rsi
callq 0x21a0
movq %rax, %rdi
callq 0x20e0
xorl %eax, %eax
cmpq $0x400, %rax            # imm = 0x400
je 0x31c8
movq -0x38(%rbp), %rcx
movl $0x14, (%rcx,%rax,4)
incq %rax
jmp 0x31b0
movq $0x0, -0x40(%rbp)
leaq -0x60(%rbp), %r14
movl -0x2c(%rbp), %r15d
movq %rbx, %r13
xorl %ebx, %ebx
jmp 0x2c9e
leaq 0x2fa8(%rip), %rsi      # 0x6191
leaq -0x60(%rbp), %rdi
leaq -0x6e(%rbp), %rdx
callq 0x20a0
leaq -0x60(%rbp), %rsi
movq -0x68(%rbp), %rdi
callq 0x346a
movq -0x38(%rbp), %r14
testq %rax, %rax
je 0x3290
leaq 0x2f7a(%rip), %rsi      # 0x6191
leaq -0xe0(%rbp), %rdi
leaq -0x6d(%rbp), %rdx
callq 0x20a0
leaq -0xe0(%rbp), %rsi
movq -0x68(%rbp), %rdi
callq 0x34cc
movl 0x4(%rax), %ebx
leaq -0xe0(%rbp), %rdi
callq 0x20d0
leaq -0x60(%rbp), %rdi
callq 0x20d0
cmpl -0x74(%rbp), %ebx
jne 0x3299
movl $0x2, (%r14)
leaq 0x2f2f(%rip), %rsi      # 0x6191
leaq -0x60(%rbp), %rdi
leaq -0xe0(%rbp), %rdx
callq 0x20a0
leaq -0x60(%rbp), %rsi
movq -0x68(%rbp), %rdi
callq 0x34cc
movl (%rax), %eax
movl %eax, 0x4(%r14)
leaq -0x60(%rbp), %rdi
callq 0x20d0
jmp 0x32a6
leaq -0x60(%rbp), %rdi
callq 0x20d0
movabsq $0x1400000014, %rax     # imm = 0x1400000014
movq %rax, (%r14)
leaq -0xc0(%rbp), %rdi
callq 0x20d0
leaq -0xa0(%rbp), %rdi
callq 0x3536
addq $0x4b8, %rsp            # imm = 0x4B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x32fb
jmp 0x32fb
jmp 0x32f6
movq %rax, %rbx
leaq -0xe0(%rbp), %rdi
callq 0x20d0
jmp 0x32fe
jmp 0x32fb
jmp 0x32fb
jmp 0x32f6
jmp 0x32f6
movq %rax, %rbx
jmp 0x3313
jmp 0x32fb
movq %rax, %rbx
jmp 0x3307
movq %rax, %rbx
leaq -0x60(%rbp), %rdi
callq 0x20d0
leaq -0xc0(%rbp), %rdi
callq 0x20d0
leaq -0xa0(%rbp), %rdi
callq 0x3536
movq %rbx, %rdi
callq 0x22b0
nop