// File: /workspace/github_c_makefile_star2_O3/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 0x1c40
movq %rax, %r14
movq 0x18(%rbx), %rax
cmpl $0x1b, (%rax)
jne 0x1e7e
cmpl $0x9, (%r15)
je 0x1e19
leaq 0x3399(%rip), %rdi      # 0x51ad
callq 0x1b85
movq %rbx, %rdi
callq 0x12b2
movq 0x18(%r15), %rcx
movq 0x8(%rcx), %rsi
movq %rax, %rdi
callq 0x4685
movq %rax, %r15
testq %rax, %rax
jne 0x1e45
leaq 0x338e(%rip), %rdi      # 0x51ce
callq 0x1b85
movq %r14, %rdi
callq 0x1c40
movq %rax, %rbx
movl 0x20(%r15), %eax
addl $-0x29, %eax
cmpl $0x4, %eax
ja 0x1fe8
leaq 0x32c5(%rip), %rcx      # 0x512c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpl $0x3, (%rbx)
jne 0x1fdc
jmp 0x1fe8
movq 0x28(%rbx), %rdi
callq 0x1c40
movl (%rax), %ecx
cmpl $0x5, %ecx
je 0x1f70
cmpl $0x4, %ecx
je 0x1efe
cmpl $0x3, %ecx
jne 0x1fc9
movl (%r14), %ecx
cmpl $0x4, %ecx
je 0x2052
cmpl $0x3, %ecx
jne 0x1fc9
movl 0x20(%rax), %r15d
movl 0x20(%r14), %r14d
movq 0x18(%rbx), %rax
movl (%rax), %eax
cmpl $0x15, %eax
jg 0x212b
addl $-0x5, %eax
cmpl $0x3, %eax
ja 0x1fec
leaq 0x323d(%rip), %rcx      # 0x511c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x48cc
addl %r15d, %r14d
jmp 0x2464
movl (%r14), %ecx
cmpl $0x3, %ecx
je 0x2008
cmpl $0x4, %ecx
jne 0x1fc9
movss 0x20(%rax), %xmm0
movss 0x20(%r14), %xmm1
movq 0x18(%rbx), %rax
movl (%rax), %eax
cmpl $0x15, %eax
jg 0x20ad
addl $-0x5, %eax
cmpl $0x3, %eax
ja 0x1fec
movss %xmm1, -0x20(%rbp)
movss %xmm0, -0x1c(%rbp)
leaq 0x31b2(%rip), %rcx      # 0x50fc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
movss -0x1c(%rbp), %xmm0
addss -0x20(%rbp), %xmm0
jmp 0x255c
cmpl $0x5, (%r14)
jne 0x1fc9
movq 0x20(%rax), %r15
movq 0x20(%r14), %r14
movq 0x18(%rbx), %rax
movl (%rax), %eax
cmpl $0x24, %eax
je 0x21c3
cmpl $0x1a, %eax
je 0x219d
cmpl $0x5, %eax
jne 0x1fec
movq %r15, %rdi
movq %r14, %rsi
callq 0x1140
movq 0x20(%rbx), %rsi
movl $0x3, %edi
callq 0x48cc
movq %rax, %rdi
movq %r15, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x165c
leaq 0x3244(%rip), %rdi      # 0x5214
callq 0x1b85
jmp 0x1fec
cmpl $0x0, (%rbx)
je 0x1fe8
leaq 0x3221(%rip), %rdi      # 0x5204
callq 0x1b85
movq %rbx, 0x28(%r15)
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
cmpl $0x4, (%rbx)
jne 0x1fdc
jmp 0x1fe8
cmpl $0x5, (%rbx)
jne 0x1fdc
jmp 0x1fe8
movss 0x20(%rax), %xmm0
movl 0x20(%r14), %r14d
movq 0x18(%rbx), %rax
movl (%rax), %eax
cmpl $0x15, %eax
jg 0x20f0
addl $-0x5, %eax
cmpl $0x3, %eax
ja 0x1fec
movss %xmm0, -0x1c(%rbp)
leaq 0x30b8(%rip), %rcx      # 0x50ec
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
cvtsi2ss %r14d, %xmm1
jmp 0x209f
movl 0x20(%rax), %r15d
movss 0x20(%r14), %xmm0
movq 0x18(%rbx), %rax
movl (%rax), %eax
cmpl $0x15, %eax
jg 0x2162
addl $-0x5, %eax
cmpl $0x3, %eax
ja 0x1fec
movss %xmm0, -0x1c(%rbp)
leaq 0x3089(%rip), %rcx      # 0x510c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
cvtsi2ss %r15d, %xmm1
movss -0x1c(%rbp), %xmm0
addss %xmm1, %xmm0
jmp 0x255c
cmpl $0x19, %eax
jg 0x21ef
cmpl $0x16, %eax
je 0x22c2
cmpl $0x17, %eax
jne 0x1fec
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
movss %xmm1, -0x20(%rbp)
callq 0x48cc
xorl %esi, %esi
movss -0x1c(%rbp), %xmm0
ucomiss -0x20(%rbp), %xmm0
jmp 0x23f1
cmpl $0x19, %eax
jg 0x2229
cmpl $0x16, %eax
je 0x230f
cmpl $0x17, %eax
jne 0x1fec
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
callq 0x48cc
xorps %xmm0, %xmm0
cvtsi2ss %r14d, %xmm0
jmp 0x23e7
cmpl $0x19, %eax
jg 0x2258
cmpl $0x16, %eax
je 0x2372
cmpl $0x17, %eax
jne 0x1fec
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x48cc
xorl %esi, %esi
cmpl %r14d, %r15d
setg %sil
jmp 0x2423
cmpl $0x19, %eax
jg 0x2286
cmpl $0x16, %eax
je 0x23cc
cmpl $0x17, %eax
jne 0x1fec
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
callq 0x48cc
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
jmp 0x232a
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x48cc
movq %rax, %rbx
movq %r15, %rdi
movq %r14, %rsi
callq 0x10c0
xorl %esi, %esi
testl %eax, %eax
setne %sil
jmp 0x21e7
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x48cc
movq %rax, %rbx
movq %r15, %rdi
movq %r14, %rsi
callq 0x10c0
xorl %esi, %esi
testl %eax, %eax
sete %sil
movq %rbx, %rdi
jmp 0x2426
cmpl $0x1a, %eax
je 0x22e3
cmpl $0x24, %eax
jne 0x1fec
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
movss %xmm1, -0x20(%rbp)
callq 0x48cc
movss -0x1c(%rbp), %xmm0
cmpeqss -0x20(%rbp), %xmm0
jmp 0x2306
cmpl $0x1a, %eax
je 0x2335
cmpl $0x24, %eax
jne 0x1fec
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
callq 0x48cc
xorps %xmm0, %xmm0
cvtsi2ss %r14d, %xmm0
jmp 0x22b3
cmpl $0x1a, %eax
je 0x238e
cmpl $0x24, %eax
jne 0x1fec
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x48cc
xorl %esi, %esi
cmpl %r14d, %r15d
sete %sil
jmp 0x2423
cmpl $0x1a, %eax
je 0x23f7
cmpl $0x24, %eax
jne 0x1fec
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
callq 0x48cc
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
movss -0x1c(%rbp), %xmm1
cmpeqss %xmm0, %xmm1
jmp 0x241c
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
movss %xmm1, -0x20(%rbp)
callq 0x48cc
xorl %esi, %esi
movss -0x20(%rbp), %xmm0
jmp 0x232c
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
movss %xmm1, -0x20(%rbp)
callq 0x48cc
movss -0x1c(%rbp), %xmm0
cmpneqss -0x20(%rbp), %xmm0
movd %xmm0, %esi
jmp 0x2420
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
callq 0x48cc
xorps %xmm0, %xmm0
cvtsi2ss %r14d, %xmm0
xorl %esi, %esi
ucomiss -0x1c(%rbp), %xmm0
jmp 0x23f1
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
callq 0x48cc
xorps %xmm0, %xmm0
cvtsi2ss %r14d, %xmm0
jmp 0x2412
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
movss -0x1c(%rbp), %xmm0
mulss -0x20(%rbp), %xmm0
jmp 0x255c
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x48cc
xorl %esi, %esi
cmpl %r14d, %r15d
setl %sil
jmp 0x2423
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x48cc
xorl %esi, %esi
cmpl %r14d, %r15d
setne %sil
jmp 0x2423
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
xorps %xmm0, %xmm0
cvtsi2ss %r14d, %xmm0
movss -0x1c(%rbp), %xmm1
mulss %xmm0, %xmm1
cvttss2si %xmm1, %esi
jmp 0x2423
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
callq 0x48cc
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
xorl %esi, %esi
movss -0x1c(%rbp), %xmm1
ucomiss %xmm0, %xmm1
seta %sil
jmp 0x2423
movq 0x20(%rbx), %rsi
movl $0x2, %edi
movss %xmm0, -0x1c(%rbp)
callq 0x48cc
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
movss -0x1c(%rbp), %xmm1
cmpneqss %xmm0, %xmm1
movd %xmm1, %esi
andl $0x1, %esi
movq %rax, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x15bc
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
movss -0x1c(%rbp), %xmm0
divss -0x20(%rbp), %xmm0
jmp 0x255c
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x48cc
imull %r15d, %r14d
movq %rax, %rdi
movl %r14d, %esi
jmp 0x2426
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
movss -0x1c(%rbp), %xmm0
subss -0x20(%rbp), %xmm0
jmp 0x255c
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
cvtsi2ss %r14d, %xmm1
movss -0x1c(%rbp), %xmm0
divss %xmm1, %xmm0
jmp 0x255c
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
cvtsi2ss %r14d, %xmm1
movss -0x1c(%rbp), %xmm0
subss %xmm1, %xmm0
jmp 0x255c
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
cvtsi2ss %r15d, %xmm1
movss -0x1c(%rbp), %xmm0
mulss %xmm1, %xmm0
jmp 0x255c
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x48cc
movq %rax, %rdi
movl %r15d, %eax
cltd
idivl %r14d
movl %eax, %esi
jmp 0x2426
movq 0x20(%rbx), %rsi
movl $0x2, %edi
callq 0x48cc
subl %r14d, %r15d
movq %rax, %rdi
movl %r15d, %esi
jmp 0x2426
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
divss -0x1c(%rbp), %xmm0
jmp 0x255c
movq 0x20(%rbx), %rsi
movl $0x27, %edi
callq 0x48cc
xorps %xmm0, %xmm0
cvtsi2ss %r15d, %xmm0
subss -0x1c(%rbp), %xmm0
movq %rax, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x147c