// File: kram[P]kram/./src/vm/vm.cpp
// Function: VM::call(Instruction*, vm::ON)
Value* VM::call(Instruction* ins, vm::ON on) {

	this->env_push();

	// Get the method name or function declaration
	Value* fun = this->name(ins->left[0], on);

	// Result pointer
	Value* res;

	// Function and class methods
	if (fun->type == Type::FUNCTION) {
		// Parse arguments first
		auto arguments = this->run_vector(ins->right);

		// Assign "self" to the parent
		if (on == vm::ON::PUSHED_CLASS) {
			this->name_create("self", this->lib_stack.back());
		}

		// Execute function
		res = fun->exec_method("exec", arguments);

	// Pushed classes (the class has to be fetched from the stack)
	} else if (on == vm::ON::PUSHED_CLASS && fun->type == Type::NAME) {
		Value* top = this->lib_stack.back();

		switch (top->type) {
			case Type::NUMBER:
			case Type::STRING:
			case Type::BOOL:
				res = this->call_builtin(ins, fun);
				break;

			default:
				res = top->exec_method(fun->getString(), this->run_vector(ins->right));
				break;
		}

	// Default action is built in libraries
	} else {
		res = this->call_library(ins);
	}

	this->env_pop();

	return res;
}

// Assembly:
subq $0x168, %rsp            # imm = 0x168
movq %rdi, 0x160(%rsp)
movq %rsi, 0x158(%rsp)
movl %edx, 0x154(%rsp)
movq 0x160(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0xff30
movq 0x158(%rsp), %rdi
addq $0x38, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x13710
movq 0x38(%rsp), %rdi
movq (%rax), %rsi
movl 0x154(%rsp), %edx
callq 0x103b0
movq %rax, 0x148(%rsp)
movq 0x148(%rsp), %rax
cmpl $0x5, 0x8(%rax)
jne 0x124cf
movq 0x158(%rsp), %rsi
addq $0x50, %rsi
leaq 0x110(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x5460
movq 0x38(%rsp), %rsi
movq 0x30(%rsp), %rdx
leaq 0x128(%rsp), %rdi
callq 0x120e0
jmp 0x122aa
leaq 0x110(%rsp), %rdi
callq 0x5560
cmpl $0x1, 0x154(%rsp)
jne 0x1239e
leaq 0xdf(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x34a0
movq 0x28(%rsp), %rdx
leaq 0x193b2(%rip), %rsi     # 0x2b695
leaq 0xe0(%rsp), %rdi
callq 0x3390
jmp 0x122f2
movq 0x38(%rsp), %rdi
callq 0x134e0
movq 0x38(%rsp), %rdi
movq (%rax), %rdx
leaq 0xe0(%rsp), %rsi
callq 0xfc10
jmp 0x12313
leaq 0xe0(%rsp), %rdi
callq 0x31f0
leaq 0xdf(%rsp), %rdi
callq 0x3310
jmp 0x1239e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x5560
jmp 0x1266a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
jmp 0x1238c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x31f0
leaq 0xdf(%rsp), %rdi
callq 0x3310
jmp 0x124bd
movq 0x148(%rsp), %rax
movq %rax, 0x18(%rsp)
leaq 0xb7(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x34a0
movq 0x20(%rsp), %rdx
leaq 0x192d1(%rip), %rsi     # 0x2b69a
leaq 0xb8(%rsp), %rdi
callq 0x3390
jmp 0x123d8
leaq 0x98(%rsp), %rdi
leaq 0x128(%rsp), %rsi
callq 0x14280
jmp 0x123ef
movq 0x18(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
leaq 0x98(%rsp), %rdx
callq 0x1e140
movq %rax, 0x10(%rsp)
jmp 0x12410
movq 0x10(%rsp), %rax
movq %rax, 0x140(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x5850
leaq 0xb8(%rsp), %rdi
callq 0x31f0
leaq 0xb7(%rsp), %rdi
callq 0x3310
leaq 0x128(%rsp), %rdi
callq 0x5850
jmp 0x12650
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
jmp 0x124b0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
jmp 0x124a3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x5850
leaq 0xb8(%rsp), %rdi
callq 0x31f0
leaq 0xb7(%rsp), %rdi
callq 0x3310
leaq 0x128(%rsp), %rdi
callq 0x5850
jmp 0x1266a
cmpl $0x1, 0x154(%rsp)
jne 0x12634
movq 0x148(%rsp), %rax
cmpl $0x7, 0x8(%rax)
jne 0x12634
movq 0x38(%rsp), %rdi
callq 0x134e0
movq (%rax), %rax
movq %rax, 0x90(%rsp)
movq 0x90(%rsp), %rax
movl 0x8(%rax), %eax
decl %eax
subl $0x2, %eax
ja 0x1253f
jmp 0x12518
movq 0x38(%rsp), %rdi
movq 0x158(%rsp), %rsi
movq 0x148(%rsp), %rdx
callq 0x12680
movq %rax, 0x140(%rsp)
jmp 0x12632
movq 0x90(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x148(%rsp), %rsi
leaq 0x70(%rsp), %rdi
callq 0x1e9e0
movq 0x158(%rsp), %rsi
addq $0x50, %rsi
leaq 0x40(%rsp), %rdi
callq 0x5460
jmp 0x12576
movq 0x38(%rsp), %rsi
leaq 0x58(%rsp), %rdi
leaq 0x40(%rsp), %rdx
callq 0x120e0
jmp 0x1258c
movq 0x8(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x58(%rsp), %rdx
callq 0x1e140
movq %rax, (%rsp)
jmp 0x125a6
movq (%rsp), %rax
movq %rax, 0x140(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x5850
leaq 0x40(%rsp), %rdi
callq 0x5560
leaq 0x70(%rsp), %rdi
callq 0x31f0
jmp 0x12632
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
jmp 0x12626
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
jmp 0x1261c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x5850
leaq 0x40(%rsp), %rdi
callq 0x5560
leaq 0x70(%rsp), %rdi
callq 0x31f0
jmp 0x1266a
jmp 0x1264e
movq 0x38(%rsp), %rdi
movq 0x158(%rsp), %rsi
callq 0x12a60
movq %rax, 0x140(%rsp)
jmp 0x12650
movq 0x38(%rsp), %rdi
callq 0xff00
movq 0x140(%rsp), %rax
addq $0x168, %rsp            # imm = 0x168
retq
movq 0x108(%rsp), %rdi
callq 0x3490
nopw (%rax,%rax)