// File: /workspace/github_c_makefile_star2_O2/goodpaul6[P]generic/script.c
// Function: compile_module
static void compile_module(script_t* script, script_module_t* module)
{
	char symbol_error = 0;
	
	if(!module->compiled)
	{
		for (int pass = 0; pass <= 1; ++pass)
		{
			// NOTE: Skip first pass if there is no compile
			// time code
			if (module->compile_time_blocks.length == 0)
				pass = 1;

			check_all_tags_defined(script);
			finalize_types(script);

			int ct_start_pc = script->code.length;

			// NOTE: We must compile all referenced modules so that this 
			// module can access their code
			for (int i = 0; i < module->referenced_modules.length; ++i)
			{
				script_module_t* ref_module = vec_get(&script->modules, vec_get_value(&module->referenced_modules, i, int));

				// NOTE: This will compile its referenced modules too
				compile_module(script, ref_module);
			}

			// NOTE: Pass to resolve symbols and types
			if (pass == 1)
			{
				module->start_pc = script->code.length;

				for (int expr_index = 0; expr_index < module->expr_list.length; ++expr_index)
				{
					expr_t* node = vec_get_value(&module->expr_list, expr_index, expr_t*);

					char prev_error = g_has_error;
					resolve_symbols(script, node);
					symbol_error = prev_error ? 0 : g_has_error;
					if (!symbol_error) resolve_type_tags(script, node);
				}

				if (g_has_error) error_exit("Errors in script code. Stopping...\n");

				for (int expr_index = 0; expr_index < module->expr_list.length; ++expr_index)
				{
					expr_t* node = vec_get_value(&module->expr_list, expr_index, expr_t*);
					compile_expr(script, node);
				}

				module->end_pc = script->code.length;
			}
			
			// NOTE: The first pass is the compile-time execution pass
			
			// TODO: VERY IMPORTANT: you cannot access the code in the current
			// module in these compile-time blocks because this module is subject
			// to change during the execution of this code
			
			// Option A: I could do a thing where I look at the code in these blocks and 
			// see the symbols it references and compile the code associated
			// with them but that's very complicated and the compiler isn't set up for 
			// that
			
			// Option B: I have the compiler act differently during the first pass
			// in that it ignores missing symbols and just carries on without compiling
			// any code related to them (this could be pretty complex to do without errors
			// since it may lead to stuff like call expressions being compiled but missing
			// arguments etc; c compilers do this I believe)

			// Option C: What I'm doing now, where you can't call code in this module
			// It's just better if you create a file called "your_file_name_meta.gn"
			// and then put all the compile time functions related to this module
			// in that and you're golden (the compiler handles this just fine since
			// that code will be in a separate module and thus free from edits by this
			// code) OR you could even just label code #on_compile and it would 
			// be available to the compile time code it's super easy fam
			if (pass == 0)
			{
				module->start_pc = script->code.length;

				for (int i = 0; i < module->compile_time_blocks.length; ++i)
				{
					expr_t* exp = vec_get_value(&module->compile_time_blocks, i, expr_t*);

					char prev_error = g_has_error;
					resolve_symbols(script, exp);
					symbol_error = prev_error ? 0 : g_has_error;
					if (!symbol_error) resolve_type_tags(script, exp);

					//debug_expr(script, node);
					//printf("\n");

					if (!g_has_error)
						compile_expr(script, exp);
					else
						error_exit("Found errors in compile-time code. Stopping compilation\n");
				}

				// NOTE: Must stop after all compile time code is executed
				append_code(script, OP_HALT);

				// NOTE: Temporary end_pc for debugging
				module->end_pc = script->code.length;

				// NOTE: setup script for compile-time execution
				vec_clear(&script->stack);
				allocate_globals(script);

				printf("Executing compile-time code...\n");

				script->pc = ct_start_pc;
				while (script->pc >= 0)
					script_execute_cycle(script);

				printf("Finished compile-time execution.\n");

				// NOTE: Reset the script code so it doesn't include the compile time code
				vec_resize(&script->code, module->start_pc, NULL);
			}
		}
		module->compiled = 1;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
cmpb $0x0, 0x49(%rsi)
jne 0x3c23
movq %rsi, %rbx
movq %rdi, %r14
leaq 0x70(%rsi), %rax
movq %rax, -0x68(%rbp)
leaq 0x2b8(%rdi), %r12
leaq 0x1d8(%rdi), %rax
movq %rax, -0x50(%rbp)
leaq 0x50(%rsi), %rax
movq %rax, -0x40(%rbp)
leaq 0x198(%rdi), %rax
movq %rax, -0x48(%rbp)
xorl %eax, %eax
movq %r12, -0x38(%rbp)
cmpl $0x2, %eax
jge 0x3c1f
movl %eax, -0x2c(%rbp)
movq 0x80(%rbx), %rax
movq %rax, -0x60(%rbp)
movslq 0x108a2(%rip), %rsi     # 0x14248
movq %r12, %rdi
callq 0xc15c
movq %rax, %r13
movq %rax, %r15
addq $0x90, %r15
xorl %r12d, %r12d
cmpq %r12, 0xa0(%r13)
jbe 0x39fb
movq %r15, %rdi
movq %r12, %rsi
callq 0xc15c
movq (%rax), %rax
cmpb $0x0, 0x24(%rax)
jne 0x39f6
movq 0x30(%rax), %rsi
movups (%rax), %xmm0
movups 0x10(%rax), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
xorl %eax, %eax
callq 0xb1fc
incq %r12
jmp 0x39be
xorl %r15d, %r15d
movq -0x38(%rbp), %r12
cmpq %r15, 0x2c8(%r14)
jbe 0x3a30
movq %r12, %rdi
movq %r15, %rsi
callq 0xc15c
leaq 0xb0(%rax), %rdi
leaq 0x788c(%rip), %rsi      # 0xb2b0
xorl %edx, %edx
callq 0xc656
incq %r15
jmp 0x3a02
movq 0x1e8(%r14), %rax
movq %rax, -0x58(%rbp)
xorl %r15d, %r15d
cmpq %r15, 0x10(%rbx)
jbe 0x3a6a
movq %rbx, %rdi
movq %r15, %rsi
callq 0xc15c
movslq (%rax), %rsi
movq %r12, %rdi
callq 0xc15c
movq %r14, %rdi
movq %rax, %rsi
callq 0x3934
incq %r15
jmp 0x3a3e
cmpq $0x0, -0x60(%rbp)
pushq $0x1
popq %rax
movl -0x2c(%rbp), %ecx
cmovel %eax, %ecx
movl %ecx, %eax
testl %ecx, %ecx
je 0x3b21
cmpl $0x1, %eax
jne 0x3c18
movl %eax, -0x2c(%rbp)
movq 0x1e8(%r14), %rax
movq %rax, 0x20(%rbx)
xorl %r15d, %r15d
movq 0x60(%rbx), %rax
cmpq %r15, %rax
jbe 0x3ae8
movq -0x40(%rbp), %rdi
movq %r15, %rsi
callq 0xc15c
movq (%rax), %r12
movb 0x10791(%rip), %r13b    # 0x1424c
movq %r14, %rdi
movq %r12, %rsi
callq 0x7ae1
testb %r13b, %r13b
jne 0x3ad4
testb $0x1, 0x1077a(%rip)     # 0x1424c
jne 0x3adf
movq %r14, %rdi
movq %r12, %rsi
callq 0x7eea
incq %r15
movq -0x38(%rbp), %r12
jmp 0x3a9c
cmpb $0x0, 0x1075d(%rip)     # 0x1424c
jne 0x3c40
xorl %r15d, %r15d
cmpq %r15, %rax
jbe 0x3b9a
movq -0x40(%rbp), %rdi
movq %r15, %rsi
callq 0xc15c
movq (%rax), %rsi
movq %r14, %rdi
callq 0xae2e
incq %r15
movq 0x60(%rbx), %rax
jmp 0x3af8
movl %eax, -0x2c(%rbp)
movq 0x1e8(%r14), %rax
movq %rax, 0x20(%rbx)
xorl %r15d, %r15d
cmpq %r15, 0x80(%rbx)
jbe 0x3ba7
movq -0x68(%rbp), %rdi
movq %r15, %rsi
callq 0xc15c
movq (%rax), %r12
movb 0x106fb(%rip), %r13b    # 0x1424c
movq %r14, %rdi
movq %r12, %rsi
callq 0x7ae1
testb %r13b, %r13b
jne 0x3b6e
testb $0x1, 0x106e4(%rip)     # 0x1424c
jne 0x3c32
movq %r14, %rdi
movq %r12, %rsi
callq 0x7eea
cmpb $0x0, 0x106cc(%rip)     # 0x1424c
jne 0x3c32
movq %r14, %rdi
movq %r12, %rsi
callq 0xae2e
incq %r15
movq -0x38(%rbp), %r12
jmp 0x3b32
movq 0x1e8(%r14), %rax
movq %rax, 0x28(%rbx)
jmp 0x3c15
movq %r14, %rdi
pushq $0x30
popq %rsi
callq 0x7117
movq 0x1e8(%r14), %rax
movq %rax, 0x28(%rbx)
movq -0x48(%rbp), %rdi
callq 0xc3ea
movq %r14, %rdi
callq 0x4140
leaq 0xbdde(%rip), %rdi      # 0xf9b3
callq 0x2060
movq -0x58(%rbp), %rax
movl %eax, 0x11c(%r14)
testl %eax, %eax
js 0x3bfa
movq %r14, %rdi
callq 0x41b4
movl 0x11c(%r14), %eax
jmp 0x3be5
leaq 0xbdd1(%rip), %rdi      # 0xf9d2
callq 0x2060
movq 0x20(%rbx), %rsi
movq -0x50(%rbp), %rdi
xorl %edx, %edx
callq 0xc10a
movl -0x2c(%rbp), %eax
incl %eax
jmp 0x3988
movb $0x1, 0x49(%rbx)
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xb86c(%rip), %rdi      # 0xf4a5
xorl %eax, %eax
callq 0x34e8
leaq 0xb83a(%rip), %rdi      # 0xf481
jmp 0x3c39