// File: /workspace/github_c_makefile_star2_O1/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 %r12
pushq %rbx
subq $0x10, %rsp
movq %rdi, %rbx
movq 0x28(%rdi), %r15
movq 0x30(%rdi), %rdi
callq 0x1c48
movq %rax, %r14
movq 0x18(%rbx), %rax
cmpl $0x1b, (%rax)
jne 0x1ecd
cmpl $0x9, (%r15)
je 0x1e30
leaq 0x3382(%rip), %rdi      # 0x51ad
callq 0x1b8d
movq %rbx, %rdi
callq 0x12b2
movq 0x18(%r15), %rcx
movq 0x8(%rcx), %rsi
movq %rax, %rdi
callq 0x482a
movq %rax, %rbx
testq %rax, %rax
jne 0x1e5c
leaq 0x3377(%rip), %rdi      # 0x51ce
callq 0x1b8d
movq %r14, %rdi
callq 0x1c48
movq %rax, %r14
movl 0x20(%rbx), %eax
leal -0x29(%rax), %ecx
cmpl $0x4, %ecx
ja 0x1ec4
leaq 0x32b3(%rip), %rdx      # 0x512c
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
cmpl $0x3, (%r14)
jne 0x1eb8
cmpl $0x2d, %eax
je 0x1eb2
cmpl $0x2b, %eax
je 0x1ea7
cmpl $0x2a, %eax
jne 0x1ec4
cmpl $0x4, (%r14)
jne 0x1eb8
cmpl $0x2d, %eax
je 0x1eb2
cmpl $0x2b, %eax
jne 0x1ec4
cmpl $0x0, (%r14)
jne 0x1eb8
cmpl $0x2d, %eax
jne 0x1ec4
cmpl $0x5, (%r14)
je 0x1ec4
leaq 0x3345(%rip), %rdi      # 0x5204
callq 0x1b8d
movq %r14, 0x28(%rbx)
jmp 0x24ea
movq 0x28(%rbx), %rdi
callq 0x1c48
movl (%rax), %ecx
cmpl $0x3, %ecx
jne 0x1f2e
cmpl $0x3, (%r14)
jne 0x1f2e
movl 0x20(%rax), %r12d
movl 0x20(%r14), %r15d
movq 0x18(%rbx), %rax
movl (%rax), %ecx
movb $0x1, %al
cmpl $0x15, %ecx
jg 0x20d4
addl $-0x5, %ecx
cmpl $0x3, %ecx
ja 0x24e3
leaq 0x320d(%rip), %rax      # 0x511c
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x4a78
addl %r12d, %r15d
jmp 0x2299
cmpl $0x4, %ecx
jne 0x1f98
cmpl $0x4, (%r14)
jne 0x1f98
movss 0x20(%rax), %xmm0
movss 0x20(%r14), %xmm1
movq 0x18(%rbx), %rax
movl (%rax), %ecx
movb $0x1, %al
cmpl $0x15, %ecx
jg 0x210b
addl $-0x5, %ecx
cmpl $0x3, %ecx
ja 0x24e3
movss %xmm1, -0x28(%rbp)
movss %xmm0, -0x24(%rbp)
leaq 0x319a(%rip), %rax      # 0x510c
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x4a78
movss -0x24(%rbp), %xmm0
addss -0x28(%rbp), %xmm0
jmp 0x24d6
cmpl $0x3, %ecx
jne 0x1fff
cmpl $0x4, (%r14)
jne 0x1fff
movl 0x20(%rax), %r15d
movss 0x20(%r14), %xmm0
movq 0x18(%rbx), %rax
movl (%rax), %ecx
movb $0x1, %al
cmpl $0x15, %ecx
jg 0x214e
addl $-0x5, %ecx
cmpl $0x3, %ecx
ja 0x24e3
movss %xmm0, -0x24(%rbp)
leaq 0x3126(%rip), %rax      # 0x50fc
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x4a78
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
subss -0x24(%rbp), %xmm0
jmp 0x24d6
cmpl $0x4, %ecx
jne 0x2066
cmpl $0x3, (%r14)
jne 0x2066
movss 0x20(%rax), %xmm0
movl 0x20(%r14), %r15d
movq 0x18(%rbx), %rax
movl (%rax), %ecx
movb $0x1, %al
cmpl $0x15, %ecx
jg 0x2198
addl $-0x5, %ecx
cmpl $0x3, %ecx
ja 0x24e3
movss %xmm0, -0x24(%rbp)
leaq 0x30b0(%rip), %rax      # 0x50ec
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x4a78
cvtsi2ss %r15d, %xmm1
movss -0x24(%rbp), %xmm0
addss %xmm1, %xmm0
jmp 0x24d6
cmpl $0x5, %ecx
jne 0x20c3
cmpl $0x5, (%r14)
jne 0x20c3
movq 0x20(%rax), %r15
movq 0x20(%r14), %r14
movq 0x18(%rbx), %rax
movl (%rax), %eax
cmpl $0x24, %eax
je 0x2406
cmpl $0x1a, %eax
je 0x23e0
cmpl $0x5, %eax
jne 0x2432
movq %r15, %rdi
movq %r14, %rsi
callq 0x1140
movq 0x20(%rbx), %rsi
movl $0x3, %edi
callq 0x4a78
movq %rax, %rdi
movq %r15, %rsi
callq 0x1664
jmp 0x24de
leaq 0x314a(%rip), %rdi      # 0x5214
callq 0x1b8d
jmp 0x24e7
cmpl $0x19, %ecx
jg 0x216a
cmpl $0x16, %ecx
je 0x224f
cmpl $0x17, %ecx
jne 0x24e3
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x4a78
xorl %esi, %esi
cmpl %r15d, %r12d
setg %sil
jmp 0x237c
cmpl $0x19, %ecx
jg 0x2215
cmpl $0x16, %ecx
je 0x2329
cmpl $0x17, %ecx
jne 0x24e3
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x24(%rbp)
movss %xmm1, -0x28(%rbp)
callq 0x4a78
xorl %esi, %esi
movss -0x24(%rbp), %xmm0
ucomiss -0x28(%rbp), %xmm0
jmp 0x234c
cmpl $0x19, %ecx
jg 0x21d9
cmpl $0x16, %ecx
je 0x21af
cmpl $0x17, %ecx
je 0x230a
jmp 0x24e3
cmpl $0x1a, %ecx
je 0x226b
cmpl $0x24, %ecx
jne 0x24e3
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x4a78
xorl %esi, %esi
cmpl %r15d, %r12d
sete %sil
jmp 0x237c
cmpl $0x19, %ecx
jg 0x21d9
cmpl $0x16, %ecx
je 0x230a
cmpl $0x17, %ecx
jne 0x24e3
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x24(%rbp)
callq 0x4a78
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
xorl %esi, %esi
movss -0x24(%rbp), %xmm1
ucomiss %xmm0, %xmm1
jmp 0x234c
cmpl $0x1a, %ecx
je 0x22df
cmpl $0x24, %ecx
jne 0x24e3
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x24(%rbp)
callq 0x4a78
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
movss -0x24(%rbp), %xmm1
cmpeqss %xmm0, %xmm1
jmp 0x2304
cmpl $0x1a, %ecx
je 0x2352
cmpl $0x24, %ecx
jne 0x24e3
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x24(%rbp)
movss %xmm1, -0x28(%rbp)
callq 0x4a78
movss -0x24(%rbp), %xmm0
cmpeqss -0x28(%rbp), %xmm0
jmp 0x2375
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x4a78
xorl %esi, %esi
cmpl %r15d, %r12d
setl %sil
jmp 0x237c
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x4a78
xorl %esi, %esi
cmpl %r15d, %r12d
setne %sil
jmp 0x237c
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x4a78
imull %r12d, %r15d
movq %rax, %rdi
movl %r15d, %esi
jmp 0x237f
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x4a78
movq %rax, %rdi
movl %r12d, %eax
cltd
idivl %r15d
movl %eax, %esi
jmp 0x237f
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x4a78
subl %r15d, %r12d
movq %rax, %rdi
movl %r12d, %esi
jmp 0x237f
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x24(%rbp)
callq 0x4a78
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
movss -0x24(%rbp), %xmm1
cmpneqss %xmm0, %xmm1
movd %xmm1, %esi
jmp 0x2379
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x24(%rbp)
callq 0x4a78
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
xorl %esi, %esi
jmp 0x2348
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x24(%rbp)
movss %xmm1, -0x28(%rbp)
callq 0x4a78
xorl %esi, %esi
movss -0x28(%rbp), %xmm0
ucomiss -0x24(%rbp), %xmm0
seta %sil
jmp 0x237c
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x24(%rbp)
movss %xmm1, -0x28(%rbp)
callq 0x4a78
movss -0x24(%rbp), %xmm0
cmpneqss -0x28(%rbp), %xmm0
movd %xmm0, %esi
andl $0x1, %esi
movq %rax, %rdi
callq 0x15c4
jmp 0x24de
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x4a78
movss -0x24(%rbp), %xmm0
mulss -0x28(%rbp), %xmm0
jmp 0x24d6
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x4a78
movss -0x24(%rbp), %xmm0
divss -0x28(%rbp), %xmm0
jmp 0x24d6
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x4a78
movss -0x24(%rbp), %xmm0
subss -0x28(%rbp), %xmm0
jmp 0x24d6
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x4a78
movq %rax, %r12
movq %r15, %rdi
movq %r14, %rsi
callq 0x10c0
xorl %esi, %esi
testl %eax, %eax
setne %sil
jmp 0x242a
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x4a78
movq %rax, %r12
movq %r15, %rdi
movq %r14, %rsi
callq 0x10c0
xorl %esi, %esi
testl %eax, %eax
sete %sil
movq %r12, %rdi
jmp 0x237f
movb $0x1, %al
jmp 0x24e3
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x4a78
cvtsi2ss %r15d, %xmm1
movss -0x24(%rbp), %xmm0
mulss %xmm1, %xmm0
jmp 0x24d6
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x4a78
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
divss -0x24(%rbp), %xmm0
jmp 0x24d6
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x4a78
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
movss -0x24(%rbp), %xmm1
mulss %xmm0, %xmm1
cvttss2si %xmm1, %esi
jmp 0x237c
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x4a78
cvtsi2ss %r15d, %xmm1
movss -0x24(%rbp), %xmm0
divss %xmm1, %xmm0
jmp 0x24d6
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x4a78
cvtsi2ss %r15d, %xmm1
movss -0x24(%rbp), %xmm0
subss %xmm1, %xmm0
movq %rax, %rdi
callq 0x1484
movq %rax, %r14
xorl %eax, %eax
testb %al, %al
je 0x24ea
movq %rbx, %r14
movq %r14, %rax
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq