// File: /workspace/github_c_makefile_star2_O3/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 0x4039
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 0x198(%rdi), %rax
movq %rax, -0x60(%rbp)
leaq 0x50(%rsi), %r13
xorl %eax, %eax
movq %r12, -0x38(%rbp)
movq %r13, -0x58(%rbp)
cmpq $0x0, 0x80(%rbx)
movl %eax, %ecx
movl $0x1, %eax
cmovel %eax, %ecx
movq %rcx, -0x40(%rbp)
movslq 0x124c5(%rip), %rsi     # 0x16248
movq %r12, %rdi
callq 0xdcf3
cmpq $0x0, 0xa0(%rax)
je 0x3de4
movq %rax, %r13
movq %rax, %r15
addq $0x90, %r15
xorl %r12d, %r12d
movq %r15, %rdi
movq %r12, %rsi
callq 0xdcf3
movq (%rax), %rax
cmpb $0x0, 0x24(%rax)
je 0x3dc7
incq %r12
cmpq %r12, 0xa0(%r13)
ja 0x3da5
jmp 0x3de4
movq 0x30(%rax), %rsi
movups (%rax), %xmm0
movups 0x10(%rax), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
xorl %eax, %eax
callq 0x24e1
jmp 0x3db9
cmpq $0x0, 0x2c8(%r14)
movq -0x38(%rbp), %r12
leaq 0x8c71(%rip), %r13      # 0xca68
je 0x3e24
xorl %r15d, %r15d
movq %r12, %rdi
movq %r15, %rsi
callq 0xdcf3
leaq 0xb0(%rax), %rdi
movq %r13, %rsi
xorl %edx, %edx
callq 0xe29a
incq %r15
cmpq %r15, 0x2c8(%r14)
ja 0x3dfc
movl 0x1e8(%r14), %eax
movl %eax, -0x44(%rbp)
cmpq $0x0, 0x10(%rbx)
movq -0x58(%rbp), %r13
je 0x3e66
xorl %r15d, %r15d
movq %rbx, %rdi
movq %r15, %rsi
callq 0xdcf3
movslq (%rax), %rsi
movq %r12, %rdi
callq 0xdcf3
movq %r14, %rdi
movq %rax, %rsi
callq 0x3d12
incq %r15
cmpq %r15, 0x10(%rbx)
ja 0x3e3c
movq -0x40(%rbp), %rcx
testl %ecx, %ecx
je 0x3f1e
cmpl $0x1, %ecx
jne 0x402a
movq 0x1e8(%r14), %rax
movq %rax, 0x20(%rbx)
cmpq $0x0, 0x60(%rbx)
je 0x4012
xorl %r15d, %r15d
movq %r13, %rdi
movq %r15, %rsi
callq 0xdcf3
movq (%rax), %r12
movb 0x123a3(%rip), %r13b    # 0x1624c
movq %r14, %rdi
movq %r12, %rsi
callq 0x89c7
testb %r13b, %r13b
jne 0x3ec2
testb $0x1, 0x1238c(%rip)     # 0x1624c
jne 0x3ecd
movq %r14, %rdi
movq %r12, %rsi
callq 0x8d6c
incq %r15
movq 0x60(%rbx), %rax
cmpq %r15, %rax
movq -0x58(%rbp), %r13
ja 0x3e94
cmpb $0x0, 0x12368(%rip)     # 0x1624c
movq -0x38(%rbp), %r12
jne 0x4056
testq %rax, %rax
je 0x401b
xorl %r15d, %r15d
movq %r13, %rdi
movq %r15, %rsi
callq 0xdcf3
movq (%rax), %rsi
movq %r14, %rdi
callq 0xc3d5
incq %r15
cmpq %r15, 0x60(%rbx)
ja 0x3efa
jmp 0x401b
movq 0x1e8(%r14), %rax
movq %rax, 0x20(%rbx)
cmpq $0x0, 0x80(%rbx)
je 0x3f98
xorl %r15d, %r15d
movq -0x68(%rbp), %rdi
movq %r15, %rsi
callq 0xdcf3
movq (%rax), %r12
movb 0x12300(%rip), %r13b    # 0x1624c
movq %r14, %rdi
movq %r12, %rsi
callq 0x89c7
testb %r13b, %r13b
jne 0x3f69
testb $0x1, 0x122e9(%rip)     # 0x1624c
jne 0x4048
movq %r14, %rdi
movq %r12, %rsi
callq 0x8d6c
cmpb $0x0, 0x122d1(%rip)     # 0x1624c
jne 0x4048
movq %r14, %rdi
movq %r12, %rsi
callq 0xc3d5
incq %r15
cmpq %r15, 0x80(%rbx)
ja 0x3f36
movb $0x30, -0x29(%rbp)
movq -0x50(%rbp), %rdi
leaq -0x29(%rbp), %rsi
callq 0xdd50
movq 0x1e8(%r14), %rax
movq %rax, 0x28(%rbx)
movq -0x60(%rbp), %rdi
callq 0xdfab
movq %r14, %rdi
callq 0x457f
leaq 0xd9df(%rip), %rdi      # 0x119ab
callq 0x2060
movl -0x44(%rbp), %eax
movl %eax, 0x11c(%r14)
testl %eax, %eax
js 0x3ff1
movq %r14, %rdi
callq 0x4601
cmpl $0x0, 0x11c(%r14)
jns 0x3fdf
leaq 0xd9d2(%rip), %rdi      # 0x119ca
callq 0x2060
movq 0x20(%rbx), %rsi
movq -0x50(%rbp), %rdi
xorl %edx, %edx
callq 0xdc8d
movq -0x38(%rbp), %r12
jmp 0x4026
cmpb $0x0, 0x12233(%rip)     # 0x1624c
jne 0x4056
movq 0x1e8(%r14), %rax
movq %rax, 0x28(%rbx)
movq -0x40(%rbp), %rcx
leal 0x1(%rcx), %eax
testl %ecx, %ecx
jle 0x3d66
movb $0x1, 0x49(%rbx)
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xd44e(%rip), %rdi      # 0x1149d
xorl %eax, %eax
callq 0x388c
leaq 0xd41c(%rip), %rdi      # 0x11479
jmp 0x404f