// File: /workspace/github_c_makefile_star2_O1/qpfiffer[P]lair/src/eval.c
// Function: lair_call_function
static const struct _lair_type *_lair_call_function(struct _lair_runtime *r, const struct _lair_ast *ast_node, struct _lair_env *env) {
	if (!_is_callable(ast_node)) {
		char buf[512] = {0};
		snprintf(buf, sizeof(buf), "Cannot call a non-function: %s", _friendly_enum(ast_node->atom.type));
		throw_exception(r, ERR_RUNTIME, buf);
	}
	/* Determine if the thing we're trying to call is a function
	 * or not. It might be an atom, in which case we need to check
	 * or function/c_function maps to see if it's in there.
	 */
	const char *func_name = ast_node->atom.value.str;
	const size_t func_len = strlen(ast_node->atom.value.str);

	struct _lair_env *cur_env = env;
	while (cur_env != NULL) {
		const struct _lair_function *builtin_function = _tst_map_get(cur_env->c_functions, func_name, func_len);
		if (builtin_function != NULL)
			return _lair_call_builtin(r, ast_node, env, builtin_function);

		/* Well if we're at this point this is a program-defined function. */
		const struct _lair_ast *defined_function_ast = _tst_map_get(cur_env->functions, func_name, func_len);
		if (defined_function_ast != NULL) {
			/* Don't call it a stack frame. */
			const struct _lair_ast *last_func = env->current_function;
			env->current_function = defined_function_ast;
			const struct _lair_type *value = _lair_call_runtime_function(r, ast_node, defined_function_ast, env);
			env->current_function = last_func;
			return value;
		}

		const struct _lair_ast *not_variable_ast = _tst_map_get(cur_env->not_variables, func_name, func_len);
		if (not_variable_ast != NULL) {
			const struct _lair_ast *last_func = env->current_function;
			env->current_function = defined_function_ast;
			const struct _lair_type *value = _lair_call_function(r, not_variable_ast, env);
			env->current_function = last_func;
			return value;
		}

		cur_env = (struct _lair_env *)cur_env->parent;
	}

	char buf[512] = {0};
	snprintf(buf, sizeof(buf), "No such function: %s", func_name);
	throw_exception(r, ERR_RUNTIME, buf);
	return NULL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x248, %rsp            # imm = 0x248
movq %rdx, %rbx
movq %rdi, %r12
movq %rsi, 0x10(%rsp)
movl 0x28(%rsi), %ebp
cmpl $0xe, %ebp
ja 0x2580
movl $0x500e, %eax           # imm = 0x500E
btl %ebp, %eax
jae 0x2580
movq 0x10(%rsp), %rax
movq 0x30(%rax), %rbp
movq %rbp, %rdi
callq 0x1080
movq %rax, %r14
movq %rbx, %r15
movq %rbx, 0x8(%rsp)
movq %rbp, 0x28(%rsp)
movq %r14, 0x20(%rsp)
movq %r12, 0x18(%rsp)
testq %r15, %r15
je 0x2525
movq 0x8(%r15), %rdi
movq %rbp, %rsi
movq %r14, %rdx
callq 0x2a5e
movq %r14, %r13
testq %rax, %rax
je 0x2389
movq %rax, %r14
movl (%rax), %esi
movq %r12, %rdi
movq 0x10(%rsp), %rdx
movq %rbx, %rcx
callq 0x2732
movl (%r14), %esi
movq %r12, %rdi
movq %rax, %rdx
callq *0x10(%r14)
movq %rax, (%rsp)
xorl %eax, %eax
movq %r13, %r14
jmp 0x2514
movq 0x10(%r15), %rdi
movq %rbp, %rsi
movq %r13, %rdx
callq 0x2a5e
testq %rax, %rax
movq %r13, %r14
je 0x24a0
movq %r15, 0x38(%rsp)
movq 0x20(%rbx), %rcx
movq %rcx, 0x30(%rsp)
movq %rax, 0x20(%rbx)
movq 0x8(%rax), %r15
xorl %r13d, %r13d
cmpl $0x5, 0x28(%r15)
movq %r15, %rbp
jne 0x23da
xorl %r13d, %r13d
movq %r15, %rbp
incl %r13d
movq 0x8(%rbp), %rbp
cmpl $0x5, 0x28(%rbp)
je 0x23cd
movq %r12, %rdi
testl %r13d, %r13d
je 0x24f0
movl %r13d, %esi
movq 0x10(%rsp), %rdx
movq %rbx, %rcx
callq 0x2732
xorl %esi, %esi
movq %rax, (%rsp)
testq %rax, %rax
setne %sil
movq %r12, %rdi
movl $0x2, %edx
leaq 0x2166(%rip), %rcx      # 0x4578
callq 0x1600
movl $0x1, %edi
movl $0x30, %esi
callq 0x1130
movq %rax, %r14
movq %rbx, (%rax)
movl %r13d, %r13d
xorl %ebx, %ebx
leaq 0x214e(%rip), %r12      # 0x4586
xorl %esi, %esi
cmpl $0x5, 0x28(%r15)
sete %sil
movq 0x18(%rsp), %rdi
movl $0x1, %edx
movq %r12, %rcx
callq 0x1600
movq 0x30(%r15), %rsi
movq (%rsp), %rax
movq (%rax,%rbx,8), %rdx
movq %r14, %rdi
callq 0x25c9
movq 0x8(%r15), %r15
incq %rbx
cmpq %rbx, %r13
jne 0x2438
movq 0x18(%rsp), %r12
movq %r12, %rdi
movq %rbp, %rsi
movq %r14, %rdx
callq 0x1f69
movq %rax, (%rsp)
movq %r14, %rdi
callq 0x2701
movq 0x8(%rsp), %rbx
movq 0x20(%rsp), %r14
jmp 0x24ff
movq 0x18(%r15), %rdi
movq %rbp, %rsi
movq %r14, %rdx
callq 0x2a5e
testq %rax, %rax
je 0x251e
movq 0x8(%rsp), %rcx
movq 0x20(%rcx), %rbx
movq 0x8(%rsp), %rcx
movq $0x0, 0x20(%rcx)
movq %r12, %rdi
movq %rax, %rsi
movq 0x8(%rsp), %rdx
callq 0x22d8
movq %rax, (%rsp)
movq 0x8(%rsp), %rax
movq %rbx, 0x20(%rax)
movq 0x8(%rsp), %rbx
xorl %eax, %eax
jmp 0x2514
movq %rbp, %rsi
movq %rbx, %rdx
callq 0x1f69
movq %rax, (%rsp)
movq 0x30(%rsp), %rax
movq %rax, 0x20(%rbx)
xorl %eax, %eax
movq 0x28(%rsp), %rbp
movq 0x38(%rsp), %r15
testb %al, %al
jne 0x2339
jmp 0x256a
movq (%r15), %r15
movb $0x1, %al
jmp 0x2514
leaq 0x40(%rsp), %r14
movq $0x0, (%rsp)
movl $0x200, %edx            # imm = 0x200
movq %r14, %rdi
xorl %esi, %esi
callq 0x10d0
leaq 0x1fb4(%rip), %rdx      # 0x44fc
movl $0x200, %esi            # imm = 0x200
movq %r14, %rdi
movq %rbp, %rcx
xorl %eax, %eax
callq 0x10b0
movq %r12, %rdi
movl $0x2, %esi
movq %r14, %rdx
callq 0x1628
movq (%rsp), %rax
addq $0x248, %rsp            # imm = 0x248
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x40(%rsp), %r14
movl $0x200, %edx            # imm = 0x200
movq %r14, %rdi
xorl %esi, %esi
callq 0x10d0
movl %ebp, %edi
callq 0x2b90
leaq 0x1f3b(%rip), %rdx      # 0x44dd
movl $0x200, %esi            # imm = 0x200
movq %r14, %rdi
movq %rax, %rcx
xorl %eax, %eax
callq 0x10b0
movq %r12, %rdi
movl $0x2, %esi
movq %r14, %rdx
callq 0x1628
jmp 0x230e