// File: /workspace/github_c_makefile_star2_O0/adamjedlicka[P]blu/src/vm/compiler/compiler.c
// Function: function
static void function(bluCompiler* compiler, bluFunctionType type) {
	bluCompiler fnCompiler;
	initCompiler(&fnCompiler, compiler, compiler->scopeDepth + 1, type);

	// Compile the parameter list.
	consume(&fnCompiler, TOKEN_LEFT_PAREN, "Expect '(' after function name.");

	if (!check(&fnCompiler, TOKEN_RIGHT_PAREN)) {
		do {
			uint16_t parameter = parseVariable(&fnCompiler, "Expect parameter name.");
			defineVariable(&fnCompiler, parameter);

			fnCompiler.function->arity++;
			if (fnCompiler.function->arity > 8) {
				error(&fnCompiler, "Cannot have more than 8 parameters.");
			}
		} while (match(&fnCompiler, TOKEN_COMMA));
	}

	consume(&fnCompiler, TOKEN_RIGHT_PAREN, "Expect ')' after function parameters.");

	// The body
	if (type == TYPE_ANONYMOUS && match(compiler, TOKEN_COLON)) {
		expression(&fnCompiler);
		emitByte(&fnCompiler, OP_RETURN);
	} else if (type != TYPE_INITIALIZER && match(compiler, TOKEN_COLON)) {
		expression(&fnCompiler);
		expectNewlineOrSemicolon(&fnCompiler);
		emitByte(&fnCompiler, OP_RETURN);
	} else {
		consume(&fnCompiler, TOKEN_LEFT_BRACE, "Expect '{' before function body.");
		beginScope(&fnCompiler);
		block(&fnCompiler);
		endScope(&fnCompiler);
	}

	// Create the function object.
	bluObjFunction* function = endCompiler(&fnCompiler);
	function->chunk.file = compiler->file;
	function->chunk.name = function->name != NULL ? function->name->chars : "__anonymous";

#ifdef DEBUG_COMPILER_DISASSEMBLE
	bluDisassembleChunk(&function->chunk);
#endif

	// Capture the upvalues in the new closure object.
	emitByte(compiler, OP_CLOSURE);
	emitShort(compiler, makeConstant(compiler, OBJ_VAL(function)));

	// Emit arguments for each upvalue to know whether to capture a local or an upvalue.
	for (uint16_t i = 0; i < function->upvalueCount; i++) {
		emitByte(compiler, fnCompiler.upvalues.data[i].isLocal ? 1 : 0);
		emitShort(compiler, fnCompiler.upvalues.data[i].index);
	}

	freeCompiler(&fnCompiler);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq -0x8(%rbp), %rsi
movq -0x8(%rbp), %rax
movsbl 0x58(%rax), %eax
addl $0x1, %eax
movl -0xc(%rbp), %ecx
leaq -0x70(%rbp), %rdi
movsbl %al, %edx
callq 0x2970
leaq -0x70(%rbp), %rdi
movl $0x7, %esi
leaq 0xac02(%rip), %rdx      # 0xe242
callq 0x3200
leaq -0x70(%rbp), %rdi
movl $0xa, %esi
callq 0x2bf0
testb $0x1, %al
jne 0x36ba
jmp 0x3659
leaq -0x70(%rbp), %rdi
leaq 0xabfe(%rip), %rsi      # 0xe262
callq 0x39b0
movw %ax, -0x72(%rbp)
leaq -0x70(%rbp), %rdi
movzwl -0x72(%rbp), %esi
callq 0x3a20
movq -0x48(%rbp), %rax
movb 0x20(%rax), %cl
addb $0x1, %cl
movb %cl, 0x20(%rax)
movq -0x48(%rbp), %rax
movsbl 0x20(%rax), %eax
cmpl $0x8, %eax
jle 0x36a4
leaq -0x70(%rbp), %rdi
leaq 0xabda(%rip), %rsi      # 0xe279
callq 0x2db0
jmp 0x36a6
leaq -0x70(%rbp), %rdi
movl $0x3, %esi
callq 0x2c40
testb $0x1, %al
jne 0x3659
jmp 0x36ba
leaq -0x70(%rbp), %rdi
movl $0xa, %esi
leaq 0xabd3(%rip), %rdx      # 0xe29d
callq 0x3200
cmpl $0x2, -0xc(%rbp)
jne 0x3702
movq -0x8(%rbp), %rdi
movl $0x2, %esi
callq 0x2c40
testb $0x1, %al
jne 0x36e9
jmp 0x3702
leaq -0x70(%rbp), %rdi
callq 0x3450
leaq -0x70(%rbp), %rdi
movl $0x30, %esi
callq 0x32b0
jmp 0x3770
cmpl $0x4, -0xc(%rbp)
je 0x373e
movq -0x8(%rbp), %rdi
movl $0x2, %esi
callq 0x2c40
testb $0x1, %al
jne 0x371c
jmp 0x373e
leaq -0x70(%rbp), %rdi
callq 0x3450
leaq -0x70(%rbp), %rdi
callq 0x3a70
leaq -0x70(%rbp), %rdi
movl $0x30, %esi
callq 0x32b0
jmp 0x376e
leaq -0x70(%rbp), %rdi
movl $0x5, %esi
leaq 0xab75(%rip), %rdx      # 0xe2c3
callq 0x3200
leaq -0x70(%rbp), %rdi
callq 0x3ad0
leaq -0x70(%rbp), %rdi
callq 0x3af0
leaq -0x70(%rbp), %rdi
callq 0x3b60
jmp 0x3770
leaq -0x70(%rbp), %rdi
callq 0x2d10
movq %rax, -0x80(%rbp)
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rcx
movq -0x80(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x80(%rbp), %rax
cmpq $0x0, 0x78(%rax)
je 0x37ad
movq -0x80(%rbp), %rax
movq 0x78(%rax), %rax
addq $0x28, %rax
movq %rax, -0xa0(%rbp)
jmp 0x37bd
leaq 0xab30(%rip), %rax      # 0xe2e4
movq %rax, -0xa0(%rbp)
jmp 0x37bd
movq -0xa0(%rbp), %rcx
movq -0x80(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x8(%rbp), %rdi
movl $0x28, %esi
callq 0x32b0
movq -0x8(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0x8(%rbp), %rdi
movl $0x3, -0x90(%rbp)
movq -0x80(%rbp), %rax
movq %rax, -0x88(%rbp)
movl -0x90(%rbp), %esi
movq -0x88(%rbp), %rdx
callq 0x3190
movq -0xa8(%rbp), %rdi
movzwl %ax, %esi
callq 0x3140
movw $0x0, -0x92(%rbp)
movzwl -0x92(%rbp), %eax
movq -0x80(%rbp), %rcx
movzwl 0x22(%rcx), %ecx
cmpl %ecx, %eax
jge 0x388f
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rax
movzwl -0x92(%rbp), %ecx
movb 0x2(%rax,%rcx,4), %dl
xorl %eax, %eax
movl $0x1, %ecx
testb $0x1, %dl
cmovnel %ecx, %eax
movzbl %al, %esi
callq 0x32b0
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rax
movzwl -0x92(%rbp), %ecx
movzwl (%rax,%rcx,4), %esi
callq 0x3140
movw -0x92(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x92(%rbp)
jmp 0x3828
leaq -0x70(%rbp), %rdi
callq 0x2d80
addq $0xb0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)