// File: /workspace/github_c_makefile_star2_O2/sebbekarlsson[P]cola/src/interpret.c
// Function: interpret_visit_binop
ast_node* interpret_visit_binop(ast_node_binop* node) {
    ast_node* left = node->left;
    ast_node* right = interpret_visit(node->right);
    ast_node_variable_definition* definition;

    if (node->tok->type == _EQUALS) {
        if (left->type != AST_TYPE_VARIABLE)
            error_in_interpreter("Can only use assign on variables");

        ast_node_variable* ast_var = (ast_node_variable*) left;

        definition = get_variable_definition(
            (scope*) ast_node_get_scope((ast_node*)node),
            ast_var->tok->value
        );

        if (!definition)
            error_in_interpreter("Variables must be defined before they can be assigned");

        // this causes undefined behaviour
        //free(definition->value);
        //definition->value = malloc(sizeof(right));
        ast_node* value = interpret_visit(right);

        if (
            (definition->data_type == _DATA_TYPE_INTEGER && value->type != AST_TYPE_INTEGER) ||
            (definition->data_type == _DATA_TYPE_FLOAT && value->type != AST_TYPE_FLOAT) ||
            (definition->data_type == _DATA_TYPE_VOID && value->type != AST_TYPE_EMPTY) ||
            (definition->data_type == _DATA_TYPE_STRING && value->type != AST_TYPE_STRING)
        ) {
            error_in_interpreter("Wrong data_type");
        }

        definition->value = value;
        return definition->value;
    }

    left = interpret_visit(node->left);

    if (left->type == AST_TYPE_INTEGER && right->type == AST_TYPE_INTEGER) {
        int left_integer = ((ast_node_integer*) left)->value;
        int right_integer = ((ast_node_integer*) right)->value;
        
        if (node->tok->type == _OP_PLUS) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer + right_integer);
        } else if (node->tok->type == _OP_SUBTRACT) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer - right_integer);
        } else if (node->tok->type == _OP_DIVIDE) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer / right_integer);
        } else if (node->tok->type == _OP_MULTIPLY) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer * right_integer);
        } else if (node->tok->type == _EQUALS_EQUALS) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer == right_integer);
        } else if (node->tok->type == _NOT_EQUALS) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer != right_integer);
        } else if (node->tok->type == _LESS_THAN) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer < right_integer);
        } else if (node->tok->type == _LARGER_THAN) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer > right_integer);
        }
    } else if (left->type == AST_TYPE_FLOAT && right->type == AST_TYPE_FLOAT) {
        float left_float = ((ast_node_float*) left)->value;
        float right_float = ((ast_node_float*) right)->value;
        
        if (node->tok->type == _OP_PLUS) {
            return (ast_node*) init_ast_node_float(init_token(_FLOAT, node->value), left_float + right_float);
        } else if (node->tok->type == _OP_SUBTRACT) {
            return (ast_node*) init_ast_node_float(init_token(_FLOAT, node->value), left_float - right_float);
        } else if (node->tok->type == _OP_DIVIDE) {
            return (ast_node*) init_ast_node_float(init_token(_FLOAT, node->value), left_float / right_float);
        } else if (node->tok->type == _OP_MULTIPLY) {
            return (ast_node*) init_ast_node_float(init_token(_FLOAT, node->value), left_float * right_float);
        } else if (node->tok->type == _EQUALS_EQUALS) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_float == right_float);
        } else if (node->tok->type == _NOT_EQUALS) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_float != right_float);
        } else if (node->tok->type == _LESS_THAN) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_float < right_float);
        } else if (node->tok->type == _LARGER_THAN) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_float > right_float);
        }
    } else if (left->type == AST_TYPE_INTEGER && right->type == AST_TYPE_FLOAT) {
        int left_integer = ((ast_node_integer*) left)->value;
        float right_float = ((ast_node_float*) right)->value;
        
        if (node->tok->type == _OP_PLUS) {
            return (ast_node*) init_ast_node_float(init_token(_FLOAT, node->value), left_integer + right_float);
        } else if (node->tok->type == _OP_SUBTRACT) {
            return (ast_node*) init_ast_node_float(init_token(_FLOAT, node->value), left_integer - right_float);
        } else if (node->tok->type == _OP_DIVIDE) {
            return (ast_node*) init_ast_node_float(init_token(_FLOAT, node->value), left_integer / right_float);
        } else if (node->tok->type == _OP_MULTIPLY) {
            return (ast_node*) init_ast_node_float(init_token(_FLOAT, node->value), left_integer * right_float);
        } else if (node->tok->type == _EQUALS_EQUALS) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer == right_float);
        } else if (node->tok->type == _NOT_EQUALS) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer != right_float);
        } else if (node->tok->type == _LESS_THAN) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer < right_float);
        } else if (node->tok->type == _LARGER_THAN) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_integer > right_float);
        }
    } else if (left->type == AST_TYPE_FLOAT && right->type == AST_TYPE_INTEGER) {
        float left_float = ((ast_node_float*) left)->value;
        int right_integer = ((ast_node_integer*) right)->value;
        
        if (node->tok->type == _OP_PLUS) {
            return (ast_node*) init_ast_node_float(init_token(_FLOAT, node->value), left_float + right_integer);
        } else if (node->tok->type == _OP_SUBTRACT) {
            return (ast_node*) init_ast_node_float(init_token(_FLOAT, node->value), left_float - right_integer);
        } else if (node->tok->type == _OP_DIVIDE) {
            return (ast_node*) init_ast_node_float(init_token(_FLOAT, node->value), left_float / right_integer);
        } else if (node->tok->type == _OP_MULTIPLY) {
            return (ast_node*) init_ast_node_integer(init_token(_FLOAT, node->value), left_float * right_integer);
        } else if (node->tok->type == _EQUALS_EQUALS) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_float == right_integer);
        } else if (node->tok->type == _NOT_EQUALS) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_float != right_integer);
        } else if (node->tok->type == _LESS_THAN) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_float < right_integer);
        } else if (node->tok->type == _LARGER_THAN) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), left_float > right_integer);
        }
    } else if (left->type == AST_TYPE_STRING && right->type == AST_TYPE_STRING) {
        char* left_string = ((ast_node_string*) left)->value;
        char* right_string = ((ast_node_string*) right)->value;

        
        if (node->tok->type == _OP_PLUS) {
            strcat(left_string, right_string);
            return (ast_node*) init_ast_node_string(init_token(_STRING, node->value), left_string);
        } else if (node->tok->type == _EQUALS_EQUALS) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), strcmp(left_string, right_string) == 0);
        } else if (node->tok->type == _NOT_EQUALS) {
            return (ast_node*) init_ast_node_integer(init_token(_INTEGER, node->value), strcmp(left_string, right_string) != 0);
        }
    } else {
        error_in_interpreter("Invalid binop"); 
    }

    return (ast_node*) node;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq 0x28(%rdi), %r15
movq 0x30(%rdi), %rdi
callq 0x1b80
movq %rax, %r14
movq 0x18(%rbx), %rax
cmpl $0x1b, (%rax)
jne 0x1d79
cmpl $0x9, (%r15)
je 0x1d14
leaq 0x349e(%rip), %rdi      # 0x51ad
callq 0x1ad9
movq %rbx, %rdi
callq 0x12b9
movq 0x18(%r15), %rcx
movq 0x8(%rcx), %rsi
movq %rax, %rdi
callq 0x4085
movq %rax, %r15
testq %rax, %rax
jne 0x1d40
leaq 0x3493(%rip), %rdi      # 0x51ce
callq 0x1ad9
movq %r14, %rdi
callq 0x1b80
movq %rax, %rbx
movl 0x20(%r15), %eax
addl $-0x29, %eax
cmpl $0x4, %eax
ja 0x1efa
leaq 0x33ca(%rip), %rcx      # 0x512c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpl $0x3, (%rbx)
jne 0x1eee
jmp 0x1efa
movq 0x28(%rbx), %rdi
callq 0x1b80
movl (%rax), %ecx
cmpl $0x5, %ecx
je 0x1e84
cmpl $0x4, %ecx
je 0x1e08
cmpl $0x3, %ecx
jne 0x1edb
movl (%r14), %ecx
cmpl $0x4, %ecx
je 0x1f6d
cmpl $0x3, %ecx
jne 0x1edb
movl 0x20(%rax), %r15d
movl 0x20(%r14), %r14d
movq 0x18(%rbx), %rax
movl (%rax), %eax
leal -0x5(%rax), %ecx
cmpl $0x3, %ecx
jbe 0x202f
cmpl $0x16, %eax
je 0x2150
cmpl $0x17, %eax
je 0x2355
cmpl $0x1a, %eax
je 0x229e
cmpl $0x24, %eax
jne 0x1efe
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
callq 0x42a0
xorl %esi, %esi
cmpl %r14d, %r15d
sete %sil
jmp 0x23b4
movl (%r14), %ecx
cmpl $0x3, %ecx
je 0x1f1a
cmpl $0x4, %ecx
jne 0x1edb
movss 0x20(%rax), %xmm0
movss 0x20(%r14), %xmm1
movq 0x18(%rbx), %rax
movl (%rax), %eax
leal -0x5(%rax), %ecx
cmpl $0x3, %ecx
jbe 0x1fd2
cmpl $0x16, %eax
je 0x20d5
cmpl $0x17, %eax
je 0x223a
cmpl $0x1a, %eax
je 0x216a
cmpl $0x24, %eax
jne 0x1efe
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
movss %xmm1, -0x20(%rbp)
callq 0x42a0
movss -0x1c(%rbp), %xmm0
cmpeqss -0x20(%rbp), %xmm0
jmp 0x218b
cmpl $0x5, (%r14)
jne 0x1edb
movq 0x20(%rax), %r15
movq 0x20(%r14), %r14
movq 0x18(%rbx), %rax
movl (%rax), %eax
cmpl $0x24, %eax
je 0x20ab
cmpl $0x1a, %eax
je 0x2087
cmpl $0x5, %eax
jne 0x1efe
movq %r15, %rdi
movq %r14, %rsi
callq 0x1140
movq 0x20(%rbx), %rsi
pushq $0x3
popq %rdi
callq 0x42a0
movq %rax, %rdi
movq %r15, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x1624
leaq 0x3332(%rip), %rdi      # 0x5214
callq 0x1ad9
jmp 0x1efe
cmpl $0x0, (%rbx)
je 0x1efa
leaq 0x330f(%rip), %rdi      # 0x5204
callq 0x1ad9
movq %rbx, 0x28(%r15)
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
cmpl $0x4, (%rbx)
jne 0x1eee
jmp 0x1efa
cmpl $0x5, (%rbx)
jne 0x1eee
jmp 0x1efa
movss 0x20(%rax), %xmm0
movl 0x20(%r14), %r14d
movq 0x18(%rbx), %rax
movl (%rax), %eax
leal -0x5(%rax), %ecx
cmpl $0x3, %ecx
jbe 0x2007
cmpl $0x16, %eax
je 0x20f7
cmpl $0x17, %eax
je 0x22b8
cmpl $0x1a, %eax
je 0x21af
cmpl $0x24, %eax
jne 0x1efe
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
callq 0x42a0
cvtsi2ss %r14d, %xmm0
jmp 0x1fc3
movl 0x20(%rax), %r15d
movss 0x20(%r14), %xmm0
movq 0x18(%rbx), %rax
movl (%rax), %eax
leal -0x5(%rax), %ecx
cmpl $0x3, %ecx
jbe 0x2053
cmpl $0x16, %eax
je 0x21ca
cmpl $0x17, %eax
je 0x2394
cmpl $0x1a, %eax
je 0x22fa
cmpl $0x24, %eax
jne 0x1efe
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
callq 0x42a0
cvtsi2ss %r15d, %xmm0
movss -0x1c(%rbp), %xmm1
cmpeqss %xmm0, %xmm1
jmp 0x231a
movss %xmm1, -0x20(%rbp)
movss %xmm0, -0x1c(%rbp)
leaq 0x3119(%rip), %rax      # 0x50fc
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
movss -0x1c(%rbp), %xmm0
addss -0x20(%rbp), %xmm0
jmp 0x2382
movss %xmm0, -0x1c(%rbp)
leaq 0x30d9(%rip), %rax      # 0x50ec
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
cvtsi2ss %r14d, %xmm1
jmp 0x2079
leaq 0x30e6(%rip), %rax      # 0x511c
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
callq 0x42a0
addl %r15d, %r14d
jmp 0x222f
movss %xmm0, -0x1c(%rbp)
leaq 0x30ad(%rip), %rax      # 0x510c
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
cvtsi2ss %r15d, %xmm1
movss -0x1c(%rbp), %xmm0
addss %xmm1, %xmm0
jmp 0x2382
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
callq 0x42a0
movq %rax, %rbx
movq %r15, %rdi
movq %r14, %rsi
callq 0x10c0
xorl %esi, %esi
testl %eax, %eax
setne %sil
jmp 0x20cd
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
callq 0x42a0
movq %rax, %rbx
movq %r15, %rdi
movq %r14, %rsi
callq 0x10c0
xorl %esi, %esi
testl %eax, %eax
sete %sil
movq %rbx, %rdi
jmp 0x23b7
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
movss %xmm1, -0x20(%rbp)
callq 0x42a0
xorl %esi, %esi
movss -0x20(%rbp), %xmm0
jmp 0x23ac
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
callq 0x42a0
cvtsi2ss %r14d, %xmm0
jmp 0x23aa
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
movss -0x1c(%rbp), %xmm0
mulss -0x20(%rbp), %xmm0
jmp 0x2382
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
cvtsi2ss %r14d, %xmm0
movss -0x1c(%rbp), %xmm1
mulss %xmm0, %xmm1
cvttss2si %xmm1, %esi
jmp 0x23b4
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
callq 0x42a0
xorl %esi, %esi
cmpl %r14d, %r15d
setl %sil
jmp 0x23b4
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
movss %xmm1, -0x20(%rbp)
callq 0x42a0
movss -0x1c(%rbp), %xmm0
cmpneqss -0x20(%rbp), %xmm0
movd %xmm0, %esi
jmp 0x231e
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
movss -0x1c(%rbp), %xmm0
divss -0x20(%rbp), %xmm0
jmp 0x2382
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
callq 0x42a0
cvtsi2ss %r14d, %xmm0
jmp 0x2310
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
callq 0x42a0
cvtsi2ss %r15d, %xmm0
jmp 0x22ce
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
movss -0x1c(%rbp), %xmm0
subss -0x20(%rbp), %xmm0
jmp 0x2382
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
cvtsi2ss %r14d, %xmm1
movss -0x1c(%rbp), %xmm0
divss %xmm1, %xmm0
jmp 0x2382
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
callq 0x42a0
imull %r15d, %r14d
movq %rax, %rdi
movl %r14d, %esi
jmp 0x23b7
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
movss %xmm1, -0x20(%rbp)
callq 0x42a0
xorl %esi, %esi
movss -0x1c(%rbp), %xmm0
ucomiss -0x20(%rbp), %xmm0
jmp 0x23b0
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
cvtsi2ss %r14d, %xmm1
movss -0x1c(%rbp), %xmm0
subss %xmm1, %xmm0
jmp 0x2382
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
cvtsi2ss %r15d, %xmm1
movss -0x1c(%rbp), %xmm0
mulss %xmm1, %xmm0
jmp 0x2382
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
callq 0x42a0
xorl %esi, %esi
cmpl %r14d, %r15d
setne %sil
jmp 0x23b4
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
callq 0x42a0
cvtsi2ss %r14d, %xmm0
xorl %esi, %esi
movss -0x1c(%rbp), %xmm1
ucomiss %xmm0, %xmm1
jmp 0x23b0
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
callq 0x42a0
movq %rax, %rdi
movl %r15d, %eax
cltd
idivl %r14d
movl %eax, %esi
jmp 0x23b7
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
callq 0x42a0
cvtsi2ss %r15d, %xmm0
movss -0x1c(%rbp), %xmm1
cmpneqss %xmm0, %xmm1
movd %xmm1, %esi
andl $0x1, %esi
jmp 0x23b4
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
callq 0x42a0
subl %r14d, %r15d
movq %rax, %rdi
movl %r15d, %esi
jmp 0x23b7
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
cvtsi2ss %r15d, %xmm0
divss -0x1c(%rbp), %xmm0
jmp 0x2382
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
callq 0x42a0
xorl %esi, %esi
cmpl %r14d, %r15d
setg %sil
jmp 0x23b4
movq 0x20(%rbx), %rsi
pushq $0x27
popq %rdi
callq 0x42a0
cvtsi2ss %r15d, %xmm0
subss -0x1c(%rbp), %xmm0
movq %rax, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x1464
movq 0x20(%rbx), %rsi
pushq $0x2
popq %rdi
movss %xmm0, -0x1c(%rbp)
callq 0x42a0
cvtsi2ss %r15d, %xmm0
xorl %esi, %esi
ucomiss -0x1c(%rbp), %xmm0
seta %sil
movq %rax, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x1590