// File: kram[P]kram/./src/vm/vm.cpp
// Function: VM::math_number(Instruction*, Value*, Value*)
Value* VM::math_number(Instruction* ins, Value* left, Value* right) {

	double res_number = 0;
	bool res_bool = false;
	bool is_bool = false;
	double l = left->getNumber();
	double r = right->getNumber();

	switch (ins->type) {
		case lexer::Type::OPERATOR_PLUS:
			res_number = l + r;
			break;

		case lexer::Type::OPERATOR_MINUS:
			res_number = l - r;
			break;

		case lexer::Type::OPERATOR_DIV:
			res_number = l / r;
			break;

		case lexer::Type::OPERATOR_MUL:
			res_number = l * r;
			break;

		case lexer::Type::OPERATOR_LT:
			res_bool = l < r;
			is_bool = true;
			break;

		case lexer::Type::OPERATOR_GTEQ:
			res_bool = l >= r;
			is_bool = true;
			break;

		case lexer::Type::OPERATOR_GT:
			res_bool = l > r;
			is_bool = true;
			break;

		case lexer::Type::OPERATOR_LTEQ:
			res_bool = l <= r;
			is_bool = true;
			break;

		case lexer::Type::OPERATOR_EQEQ:
			res_bool = l == r;
			is_bool = true;
			break;

		case lexer::Type::OPERATOR_NOT_EQ:
			res_bool = l != r;
			is_bool = true;
			break;

		case lexer::Type::OPERATOR_2DOT:
		case lexer::Type::OPERATOR_3DOT:
			return this->list_range(l, r, ins->type == lexer::Type::OPERATOR_3DOT);

		default:
			std::cout << "Unknown math_number() operator\n";
			exit(0);
			break;
	}

	if (is_bool) {
		return this->get_value_bool(res_bool);
	}

	return this->get_value_number(res_number);
}

// Assembly:
subq $0x58, %rsp
movq %rdi, 0x48(%rsp)
movq %rsi, 0x40(%rsp)
movq %rdx, 0x38(%rsp)
movq %rcx, 0x30(%rsp)
movq 0x48(%rsp), %rax
movq %rax, (%rsp)
movq $0x0, 0x28(%rsp)
movb $0x0, 0x27(%rsp)
movb $0x0, 0x26(%rsp)
movq 0x38(%rsp), %rdi
callq 0x1ea10
movsd %xmm0, 0x18(%rsp)
movq 0x30(%rsp), %rdi
callq 0x1ea10
movsd %xmm0, 0x10(%rsp)
movq 0x40(%rsp), %rax
movl 0x30(%rax), %eax
addl $-0x17, %eax
movl %eax, %ecx
movq %rcx, 0x8(%rsp)
subl $0x16, %eax
ja 0x10bb4
movq 0x8(%rsp), %rax
leaq 0x1a8e9(%rip), %rcx     # 0x2b344
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movsd 0x18(%rsp), %xmm0
addsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
jmp 0x10bce
movsd 0x18(%rsp), %xmm0
subsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
jmp 0x10bce
movsd 0x18(%rsp), %xmm0
divsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
jmp 0x10bce
movsd 0x18(%rsp), %xmm0
mulsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
jmp 0x10bce
movsd 0x18(%rsp), %xmm1
movsd 0x10(%rsp), %xmm0
ucomisd %xmm1, %xmm0
seta %al
andb $0x1, %al
movb %al, 0x27(%rsp)
movb $0x1, 0x26(%rsp)
jmp 0x10bce
movsd 0x18(%rsp), %xmm0
ucomisd 0x10(%rsp), %xmm0
setae %al
andb $0x1, %al
movb %al, 0x27(%rsp)
movb $0x1, 0x26(%rsp)
jmp 0x10bce
movsd 0x18(%rsp), %xmm0
ucomisd 0x10(%rsp), %xmm0
seta %al
andb $0x1, %al
movb %al, 0x27(%rsp)
movb $0x1, 0x26(%rsp)
jmp 0x10bce
movsd 0x18(%rsp), %xmm1
movsd 0x10(%rsp), %xmm0
ucomisd %xmm1, %xmm0
setae %al
andb $0x1, %al
movb %al, 0x27(%rsp)
movb $0x1, 0x26(%rsp)
jmp 0x10bce
movsd 0x18(%rsp), %xmm0
ucomisd 0x10(%rsp), %xmm0
sete %al
setnp %cl
andb %cl, %al
andb $0x1, %al
movb %al, 0x27(%rsp)
movb $0x1, 0x26(%rsp)
jmp 0x10bce
movsd 0x18(%rsp), %xmm0
ucomisd 0x10(%rsp), %xmm0
setne %al
setp %cl
orb %cl, %al
andb $0x1, %al
movb %al, 0x27(%rsp)
movb $0x1, 0x26(%rsp)
jmp 0x10bce
movq (%rsp), %rdi
cvttsd2si 0x18(%rsp), %esi
cvttsd2si 0x10(%rsp), %edx
movq 0x40(%rsp), %rax
cmpl $0x2d, 0x30(%rax)
sete %al
movzbl %al, %ecx
andl $0x1, %ecx
callq 0x10dc0
movq %rax, 0x50(%rsp)
jmp 0x10c02
movq 0x2941d(%rip), %rdi     # 0x39fd8
leaq 0x1a99f(%rip), %rsi     # 0x2b561
callq 0x32d0
xorl %edi, %edi
callq 0x3330
testb $0x1, 0x26(%rsp)
je 0x10bee
movq (%rsp), %rdi
movb 0x27(%rsp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x1d850
movq %rax, 0x50(%rsp)
jmp 0x10c02
movq (%rsp), %rdi
movsd 0x28(%rsp), %xmm0
callq 0x1d780
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rax
addq $0x58, %rsp
retq
nopl (%rax)