// File: /workspace/github_c_makefile_star2_O0/alexj136[P]minijit/src/interpreter.c
// Function: interpret_Expr
InterpretResult *interpret_Expr(Prog *prog, Expr *expr, int *store) {
    if(Expr_isInt(expr)) {
        return InterpretSuccess_init(Int_value(expr));
    }
    else if(Expr_isAdd(expr) || Expr_isSub(expr)) {
        InterpretResult *lhs;
        InterpretResult *rhs;

        if(Expr_isAdd(expr)) {
            lhs = interpret_Expr(prog, Add_lhs(expr), store);
            rhs = interpret_Expr(prog, Add_rhs(expr), store);
        }
        else /* if(Expr_isSub(expr)) */ {
            lhs = interpret_Expr(prog, Sub_lhs(expr), store);
            rhs = interpret_Expr(prog, Sub_rhs(expr), store);
        }

        if((lhs->type == iSuccess) && (rhs->type == iSuccess)) {
            int lhs_val = lhs->result;
            int rhs_val = rhs->result;

            free(lhs);
            free(rhs);

            return InterpretSuccess_init(
                    lhs_val + (Expr_isSub(expr) ? -rhs_val : rhs_val));
        }

        else if(lhs->type != iSuccess) {
            free(rhs);
            return lhs;
        }

        else /* if(rhs->type != iSuccess) */ {
            free(lhs);
            return rhs;
        }
    }
    else if(Expr_isCall(expr)) {

        Func *callee = Prog_func(prog, Call_name(expr));

        if(callee == NULL) {
            return InterpretFailFunctionNotFound_init(Expr_src_line_no(expr),
                    Expr_src_char_no(expr));
        }

        if(Func_num_args(callee) != Call_num_args(expr)) {
            return InterpretFailIncorrectNumArgs_init(Expr_src_line_no(expr),
                    Expr_src_char_no(expr));
        }

        int *callee_store = challoc(sizeof(int) * Func_num_vars(callee));
        bool failed_arg_eval = false;
        InterpretResult *arg_res;

        // Evaluate each argument expression. Stop early if we encounter an
        // error.
        int idx;
        for(idx = 0; idx < Call_num_args(expr); idx++) {

            arg_res = interpret_Expr(prog, Call_arg(expr, idx), store);
            callee_store[idx] = arg_res->result;

            if(arg_res->type != iSuccess) {
                failed_arg_eval = true;
                break;
            }

            free(arg_res);
        }

        // If an error was encountered in argument evaluation, clean up and
        // return an error as the result of the entire call
        if(failed_arg_eval) {
            free(callee_store);
            return arg_res;
        }

        // Argument evaluation succeeded, so write zero in place for the initial
        // values of the other variables in the callee's store
        for(idx = Func_num_args(callee); idx < Func_num_vars(callee); idx++) {
            callee_store[idx] = 0;
        }

        // Make the call, free the argument array, and return the call result
        InterpretResult *call_res = interpret_Func(prog, callee, callee_store);
        free(callee_store);
        return call_res;
    }
    else if(Expr_isVar(expr)) {
        return InterpretSuccess_init(store[Var_name(expr)]);
    }
    else {
        ERROR("Expr type not recognised.");
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1ff0, %rsp           # imm = 0x1FF0
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x19535
movq -0x18(%rbp), %rax
movl 0x4(%rax), %edi
callq 0x19390
movq %rax, -0x8(%rbp)
jmp 0x1992b
movq -0x18(%rbp), %rax
cmpl $0x1, (%rax)
je 0x1954b
movq -0x18(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x1966b
movq -0x18(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x19588
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x20(%rbp), %rdx
callq 0x19500
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rsi
movq -0x20(%rbp), %rdx
callq 0x19500
movq %rax, -0x30(%rbp)
jmp 0x195ba
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x20(%rbp), %rdx
callq 0x19500
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rsi
movq -0x20(%rbp), %rdx
callq 0x19500
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x19636
movq -0x30(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x19636
movq -0x28(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x34(%rbp)
movq -0x30(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x38(%rbp)
movq -0x28(%rbp), %rdi
callq 0x6030
movq -0x30(%rbp), %rdi
callq 0x6030
movl -0x34(%rbp), %eax
movl %eax, -0x1fc8(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x19611
xorl %eax, %eax
subl -0x38(%rbp), %eax
movl %eax, -0x1fcc(%rbp)
jmp 0x1961a
movl -0x38(%rbp), %eax
movl %eax, -0x1fcc(%rbp)
movl -0x1fc8(%rbp), %edi
movl -0x1fcc(%rbp), %eax
addl %eax, %edi
callq 0x19390
movq %rax, -0x8(%rbp)
jmp 0x1992b
movq -0x28(%rbp), %rax
cmpl $0x0, (%rax)
je 0x19655
movq -0x30(%rbp), %rdi
callq 0x6030
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x1992b
movq -0x28(%rbp), %rdi
callq 0x6030
movq -0x30(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x1992b
movq -0x18(%rbp), %rax
cmpl $0x3, (%rax)
jne 0x1983c
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movq -0x18(%rbp), %rax
movl 0x4(%rax), %esi
callq 0x9860
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0x196b2
movq -0x18(%rbp), %rax
movl 0x20(%rax), %edi
movq -0x18(%rbp), %rax
movl 0x24(%rax), %esi
callq 0x193f0
movq %rax, -0x8(%rbp)
jmp 0x1992b
movq -0x40(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x1fd0(%rbp)
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0xb790
movl %eax, %ecx
movl -0x1fd0(%rbp), %eax
cmpl %ecx, %eax
je 0x196f4
movq -0x18(%rbp), %rax
movl 0x20(%rax), %edi
movq -0x18(%rbp), %rax
movl 0x24(%rax), %esi
callq 0x193c0
movq %rax, -0x8(%rbp)
jmp 0x1992b
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x7e20
cltq
shlq $0x2, %rax
movl %eax, %edi
callq 0x62f0
movq %rax, -0x48(%rbp)
movl $0x0, -0x4c(%rbp)
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
movl %eax, -0x1fd4(%rbp)
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0xb790
movl %eax, %ecx
movl -0x1fd4(%rbp), %eax
cmpl %ecx, %eax
jge 0x197af
movq -0x10(%rbp), %rax
movq %rax, -0x1fe0(%rbp)
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rdi
movl -0x5c(%rbp), %esi
callq 0xbb50
movq -0x1fe0(%rbp), %rdi
movq %rax, %rsi
movq -0x20(%rbp), %rdx
callq 0x19500
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
movl 0x4(%rax), %edx
movq -0x48(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x58(%rbp), %rax
cmpl $0x0, (%rax)
je 0x19798
movl $0x1, -0x4c(%rbp)
jmp 0x197af
movq -0x58(%rbp), %rdi
callq 0x6030
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x19720
cmpl $0x0, -0x4c(%rbp)
je 0x197cb
movq -0x48(%rbp), %rdi
callq 0x6030
movq -0x58(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x1992b
movq -0x40(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
movl %eax, -0x1fe4(%rbp)
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x7e20
movl %eax, %ecx
movl -0x1fe4(%rbp), %eax
cmpl %ecx, %eax
jge 0x19811
movq -0x48(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movl $0x0, (%rax,%rcx,4)
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x197d5
movq -0x10(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x48(%rbp), %rdx
callq 0x19940
movq %rax, -0x68(%rbp)
movq -0x48(%rbp), %rdi
callq 0x6030
movq -0x68(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x1992b
movq -0x18(%rbp), %rax
cmpl $0x4, (%rax)
jne 0x19862
movq -0x20(%rbp), %rax
movq -0x18(%rbp), %rcx
movslq 0x4(%rcx), %rcx
movl (%rax,%rcx,4), %edi
callq 0x19390
movq %rax, -0x8(%rbp)
jmp 0x1992b
jmp 0x19864
leaq 0xa799(%rip), %rdi      # 0x24004
leaq 0xbbf0(%rip), %rsi      # 0x25462
movl $0xf3, %edx
leaq 0xbc05(%rip), %rcx      # 0x25483
movb $0x0, %al
callq 0x60f0
leaq 0xa7a0(%rip), %rdi      # 0x2402c
leaq 0xab3f(%rip), %rsi      # 0x243d2
movb $0x0, %al
callq 0x60f0
leaq -0x1fb0(%rbp), %rdi
movl $0x3e8, %esi            # imm = 0x3E8
callq 0x60d0
movl %eax, -0x1fb4(%rbp)
leaq -0x1fb0(%rbp), %rdi
movl -0x1fb4(%rbp), %esi
callq 0x60a0
movq %rax, -0x1fc0(%rbp)
leaq 0xa77a(%rip), %rdi      # 0x2404b
movb $0x0, %al
callq 0x60f0
movl $0x0, -0x1fc4(%rbp)
movl -0x1fc4(%rbp), %eax
cmpl -0x1fb4(%rbp), %eax
jge 0x19921
movq -0x1fc0(%rbp), %rax
movslq -0x1fc4(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0xa723(%rip), %rdi      # 0x2402c
movb $0x0, %al
callq 0x60f0
movl -0x1fc4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1fc4(%rbp)
jmp 0x198e2
movl $0x1, %edi
callq 0x61a0
movq -0x8(%rbp), %rax
addq $0x1ff0, %rsp           # imm = 0x1FF0
popq %rbp
retq
nopl (%rax,%rax)