// File: /workspace/github_c_makefile_star2_O0/adamjedlicka[P]blu/src/vm/vm.c
// Function: callValue
static bool callValue(bluVM* vm, bluValue callee, int8_t argCount) {
	if (!IS_OBJ(callee)) {
		runtimeError(vm, "Can only call functions and classes.");
		return false;
	}

	switch (OBJ_TYPE(callee)) {

	case OBJ_BOUND_METHOD: {
		bluObjBoundMethod* boundMethod = AS_BOUND_METHOD(callee);

		// Replace the bound method with the new receiver so it's in the right slot when the method is called.
		vm->stackTop[-argCount - 1] = boundMethod->receiver;
		return call(vm, boundMethod->closure, argCount);
	}

	case OBJ_CLASS: {
		bluObjClass* class = AS_CLASS(callee);

		// Create the instance.
		vm->stackTop[-argCount - 1] = OBJ_VAL(bluNewInstance(vm, class));

		// Call the initializer, if there is one.
		bluValue initializer;
		if (bluTableGet(vm, &class->methods, vm->stringInitializer, &initializer)) {
			if (!callValue(vm, initializer, argCount)) {
				return false;
			}
		} else if (argCount != 0) {
			runtimeError(vm, "Expected 0 arguments but got %d.", argCount);
			return false;
		}

		if (class->construct != NULL) {
			class->construct(vm, AS_INSTANCE(vm->stackTop[-argCount - 1]));
		}

		return true;
	}

	case OBJ_CLOSURE: {
		return call(vm, AS_CLOSURE(callee), argCount);
	}

	case OBJ_NATIVE: {
		bluObjNative* native = AS_NATIVE(callee);

		if (argCount < native->arity) {
			runtimeError(vm, "Expected %d arguments but got %d.", native->arity, argCount);
			return false;
		}

		int8_t result = native->function(vm, argCount, vm->stackTop - argCount - 1);
		if (result < 0) {
			runtimeError(vm, "Something went wrong.");
			return false;
		}

		vm->stackTop -= argCount + 1 - result;

		return true;
	}

	default: {
		runtimeError(vm, "Can only call functions and classes.");
		return false;
	}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movb %cl, %al
movl %esi, -0x18(%rbp)
movq %rdx, -0x10(%rbp)
movq %rdi, -0x20(%rbp)
movb %al, -0x21(%rbp)
cmpl $0x3, -0x18(%rbp)
je 0x999c
movq -0x20(%rbp), %rdi
leaq 0x634c(%rip), %rsi      # 0xfcd8
movb $0x0, %al
callq 0xc650
movb $0x0, -0x1(%rbp)
jmp 0x9c34
movq -0x10(%rbp), %rax
movl (%rax), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x70(%rbp)
subl $0x5, %eax
ja 0x9c1e
movq -0x70(%rbp), %rax
leaq 0x622a(%rip), %rcx      # 0xfbe8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x10(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x20(%rbp), %rax
movq 0x100000(%rax), %rax
movsbl -0x21(%rbp), %edx
xorl %ecx, %ecx
subl %edx, %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq -0x30(%rbp), %rcx
movq 0x20(%rcx), %rdx
movq %rdx, (%rax)
movq 0x28(%rcx), %rcx
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rdi
movq -0x30(%rbp), %rax
movq 0x30(%rax), %rsi
movsbl -0x21(%rbp), %edx
callq 0xc7d0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x9c34
movq -0x10(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rax
movq 0x100000(%rax), %rax
movsbl -0x21(%rbp), %edx
xorl %ecx, %ecx
subl %edx, %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, -0x78(%rbp)
movl $0x3, -0x48(%rbp)
movq -0x20(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x7a10
movq %rax, %rcx
movq -0x78(%rbp), %rax
movq %rcx, -0x40(%rbp)
movq -0x48(%rbp), %rcx
movq %rcx, (%rax)
movq -0x40(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rdi
movq -0x38(%rbp), %rsi
addq $0x30, %rsi
movq -0x20(%rbp), %rax
movq 0x101870(%rax), %rdx
leaq -0x58(%rbp), %rcx
callq 0x8db0
testb $0x1, %al
jne 0x9aa1
jmp 0x9ac6
movq -0x20(%rbp), %rdi
movb -0x21(%rbp), %al
movl -0x58(%rbp), %esi
movq -0x50(%rbp), %rdx
movsbl %al, %ecx
callq 0x9960
testb $0x1, %al
jne 0x9ac4
movb $0x0, -0x1(%rbp)
jmp 0x9c34
jmp 0x9af0
movsbl -0x21(%rbp), %eax
cmpl $0x0, %eax
je 0x9aee
movq -0x20(%rbp), %rdi
movsbl -0x21(%rbp), %edx
leaq 0x621f(%rip), %rsi      # 0xfcfd
movb $0x0, %al
callq 0xc650
movb $0x0, -0x1(%rbp)
jmp 0x9c34
jmp 0x9af0
movq -0x38(%rbp), %rax
cmpq $0x0, 0x50(%rax)
je 0x9b2d
movq -0x38(%rbp), %rax
movq 0x50(%rax), %rax
movq -0x20(%rbp), %rdi
movq -0x20(%rbp), %rcx
movq 0x100000(%rcx), %rcx
movsbl -0x21(%rbp), %esi
xorl %edx, %edx
subl %esi, %edx
subl $0x1, %edx
movslq %edx, %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movq 0x8(%rcx), %rsi
callq *%rax
movb $0x1, -0x1(%rbp)
jmp 0x9c34
movq -0x20(%rbp), %rdi
movq -0x10(%rbp), %rsi
movsbl -0x21(%rbp), %edx
callq 0xc7d0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x9c34
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
movsbl -0x21(%rbp), %eax
movq -0x60(%rbp), %rcx
movsbl 0x20(%rcx), %ecx
cmpl %ecx, %eax
jge 0x9b90
movq -0x20(%rbp), %rdi
movq -0x60(%rbp), %rax
movsbl 0x20(%rax), %edx
movsbl -0x21(%rbp), %ecx
leaq 0x619e(%rip), %rsi      # 0xfd1e
movb $0x0, %al
callq 0xc650
movb $0x0, -0x1(%rbp)
jmp 0x9c34
movq -0x60(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x20(%rbp), %rdi
movb -0x21(%rbp), %cl
movq -0x20(%rbp), %rdx
movq 0x100000(%rdx), %rdx
movsbl -0x21(%rbp), %esi
movslq %esi, %r8
xorl %esi, %esi
subq %r8, %rsi
shlq $0x4, %rsi
addq %rsi, %rdx
addq $-0x10, %rdx
movsbl %cl, %esi
callq *%rax
movb %al, -0x61(%rbp)
movsbl -0x61(%rbp), %eax
cmpl $0x0, %eax
jge 0x9bea
movq -0x20(%rbp), %rdi
leaq 0x6163(%rip), %rsi      # 0xfd40
movb $0x0, %al
callq 0xc650
movb $0x0, -0x1(%rbp)
jmp 0x9c34
movsbl -0x21(%rbp), %edx
addl $0x1, %edx
movsbl -0x61(%rbp), %eax
subl %eax, %edx
movq -0x20(%rbp), %rax
movq 0x100000(%rax), %rcx
movslq %edx, %rsi
xorl %edx, %edx
subq %rsi, %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movq %rcx, 0x100000(%rax)
movb $0x1, -0x1(%rbp)
jmp 0x9c34
movq -0x20(%rbp), %rdi
leaq 0x60af(%rip), %rsi      # 0xfcd8
movb $0x0, %al
callq 0xc650
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x80, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)