// File: /workspace/github_c_makefile_star2_O2/Ihsoh[P]ilang/compiler/frontend/semantics.c
// Function: _type
static void __type(
	ParserContext *ctx,
	ParserASTNode *node,
	uint8_t *type,
	bool first_type
) {
	assert(ctx);
	assert(node);
	
	#define _SET_TYPE(t) { if (type != NULL) { *type = (t); } }

	switch (node->type) {
		case FE_NODE_TYPE_CHAR: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_CHAR)
			break;
		}
		case FE_NODE_TYPE_INT8: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_INT8)
			break;
		}
		case FE_NODE_TYPE_UINT8: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_UINT8)
			break;
		}
		case FE_NODE_TYPE_INT16: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_INT16)
			break;
		}
		case FE_NODE_TYPE_UINT16: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_UINT16)
			break;
		}
		case FE_NODE_TYPE_INT32: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_INT32)
			break;
		}
		case FE_NODE_TYPE_UINT32: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_UINT32)
			break;
		}
		case FE_NODE_TYPE_INT64: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_INT64)
			break;
		}
		case FE_NODE_TYPE_UINT64: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_UINT64)
			break;
		}
		case FE_NODE_TYPE_FLOAT: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_FLOAT)
			break;
		}
		case FE_NODE_TYPE_DOUBLE: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_DOUBLE)
			break;
		}
		case FE_NODE_TYPE_VA_LIST: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_VA_LIST)
			break;
		}
		case FE_NODE_TYPE_STRUCT: {
			assert(node->nchilds == 1);

			_SET_TYPE(FE_TYPE_STRUCT)

			ParserASTNode *node_id = node->childs[0];
			assert(node_id->type == FE_NODE_IDENTIFIER);

			LexerToken *token = node_id->token;
			ParserSymbol *symbol_struct = parser_get_symbol_from_node(ctx, node, FE_SYM_STRUCT, token);
			if (symbol_struct == NULL) {
				_SYNERR_TOKEN(ctx, token, "undefined struct.");
			} else {
				if (first_type
						&& FE_STRUCT_SYMBOL_GET_DUMMY(symbol_struct)) {
					_SYNERR_TOKEN(ctx, token, "struct not implemented.");
				}
			}

			break;
		}
		case FE_NODE_TYPE_ARRAY: {
			assert(node->nchilds == 2);

			_SET_TYPE(FE_TYPE_ARRAY)

			ParserASTNode *node_array_dims = node->childs[0];
			assert(node_array_dims->type == FE_NODE_TYPE_ARRAY_DIMS);
			for (int i = 0; i < node_array_dims->nchilds; i++) {
				ParserASTNode *node_array_dim = node_array_dims->childs[i];
				assert(node_array_dim->type == FE_NODE_LITERAL_UINT);

				uint64_t dim = fe_parser_get_uint_val(ctx, node_array_dim);
				if (dim == 0) {
					_SYNERR_NODE(
						ctx,
						node_array_dim,
						"array dimension size cannot be 0."
					);
				}
			}
			
			ParserASTNode *node_type = node->childs[1];
			__type(ctx, node_type, NULL, false);

			break;
		}
		case FE_NODE_TYPE_FUNC: {
			assert(node->nchilds == 1 || node->nchilds == 2);

			_SET_TYPE(FE_TYPE_FUNC)

			ParserASTNode *node_params = NULL;
			ParserASTNode *node_type = NULL;

			node_params = node->childs[0];
			for (int i = 0; i < node_params->nchilds; i++) {
				ParserASTNode *node_param = node_params->childs[i];
				switch (node_param->type) {
					case FE_NODE_FUNC_PARAMS_ELLIPSIS_ITEM: {

						break;
					}
					case FE_NODE_FUNC_PARAMS_ITEM: {
						assert(node_param->nchilds == 2);
						
						ParserASTNode *node_param_id = node_param->childs[0];

						ParserASTNode *node_param_type = node_param->childs[1];
						__type(ctx, node_param_type, NULL, false);

						break;
					}
					default: {
						assert(0);
					}
				}
			}
			
			if (node->nchilds == 2) {
				node_type = node->childs[1];
				__type(ctx, node_type, NULL, false);
			}

			break;
		}
		case FE_NODE_TYPE_POINTER: {
			assert(node->nchilds == 1);

			_SET_TYPE(FE_TYPE_POINTER)

			ParserASTNode *node_type = node->childs[0];
			__type(ctx, node_type, NULL, false);

			break;
		}
		case FE_NODE_TYPE_VOID: {
			assert(node->nchilds == 0);
			_SET_TYPE(FE_TYPE_VOID)
			break;
		}
		default: {
			assert(0);
		}
	}

	#undef	_SET_TYPE
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x408, %rsp            # imm = 0x408
movl %ecx, %r15d
movq %rsi, %r14
movq %rdi, %rbx
testq %r14, %r14
je 0x2a0d3
movl (%r14), %eax
cmpl $0x430, %eax            # imm = 0x430
je 0x29d54
cmpl $0x440, %eax            # imm = 0x440
jne 0x29ddf
cmpl $0x1, 0x44(%r14)
jne 0x2a130
testq %rdx, %rdx
je 0x29d4e
movb $0x10, (%rdx)
movq 0x48(%r14), %rax
jmp 0x29dd2
movl 0x44(%r14), %eax
decl %eax
cmpl $0x2, %eax
jae 0x2a111
testq %rdx, %rdx
je 0x29d6b
movb $0xf, (%rdx)
movq 0x48(%r14), %rax
movq (%rax), %r15
xorl %r12d, %r12d
movslq 0x44(%r15), %rax
cmpq %rax, %r12
jge 0x29dbf
movq 0x48(%r15), %rax
movq (%rax,%r12,8), %rax
movl (%rax), %ecx
cmpl $0xa03, %ecx            # imm = 0xA03
je 0x29dba
cmpl $0xa02, %ecx            # imm = 0xA02
jne 0x2a095
cmpl $0x2, 0x44(%rax)
jne 0x2a0b4
movq 0x48(%rax), %rax
movq 0x8(%rax), %rsi
movq %rbx, %rdi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x29d00
incq %r12
jmp 0x29d75
cmpl $0x2, 0x44(%r14)
jne 0x2a05f
movq 0x48(%r14), %rax
addq $0x8, %rax
movq (%rax), %r14
xorl %edx, %edx
xorl %r15d, %r15d
jmp 0x29d1d
leal -0x400(%rax), %ecx
cmpl $0x20, %ecx
ja 0x29e16
leaq 0x1d1b3(%rip), %rax     # 0x46fa4
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
cmpl $0x0, 0x44(%r14)
jne 0x2a16e
testq %rdx, %rdx
je 0x2a05f
movb $0x1, (%rdx)
jmp 0x2a05f
cmpl $0x4ff, %eax            # imm = 0x4FF
jne 0x2a0f2
cmpl $0x0, 0x44(%r14)
jne 0x2a35e
testq %rdx, %rdx
je 0x2a05f
movb $-0x1, (%rdx)
jmp 0x2a05f
cmpl $0x0, 0x44(%r14)
jne 0x2a18d
testq %rdx, %rdx
je 0x2a05f
movb $0xb, (%rdx)
jmp 0x2a05f
cmpl $0x0, 0x44(%r14)
jne 0x2a1ac
testq %rdx, %rdx
je 0x2a05f
movb $0xc, (%rdx)
jmp 0x2a05f
cmpl $0x2, 0x44(%r14)
jne 0x2a1cb
testq %rdx, %rdx
je 0x29e88
movb $0xe, (%rdx)
movq 0x48(%r14), %rax
movq (%rax), %r13
cmpl $0x421, (%r13)          # imm = 0x421
jne 0x2a320
xorl %r15d, %r15d
movslq 0x44(%r13), %rax
cmpq %rax, %r15
jge 0x2a04b
movq 0x48(%r13), %rax
movq (%rax,%r15,8), %r12
cmpl $0x300, (%r12)          # imm = 0x300
jne 0x2a14f
movq %rbx, %rdi
movq %r12, %rsi
callq 0x23493
testq %rax, %rax
jne 0x29f08
movups 0x1de33(%rip), %xmm0    # 0x47d0d
movaps %xmm0, -0x420(%rbp)
movups 0x1de15(%rip), %xmm0    # 0x47cfd
movaps %xmm0, -0x430(%rbp)
movw $0x2e, -0x410(%rbp)
movq %rbx, %rdi
movq %r12, %rsi
leaq -0x430(%rbp), %rdx
callq *0x58(%rbx)
incq %r15
jmp 0x29ea0
cmpl $0x1, 0x44(%r14)
jne 0x2a1ea
testq %rdx, %rdx
je 0x29f20
movb $0xd, (%rdx)
movq 0x48(%r14), %rax
movq (%rax), %rax
cmpl $0x200, (%rax)          # imm = 0x200
jne 0x2a33f
movq 0x10(%rax), %r12
pushq $0x2
popq %rdx
movq %rbx, %rdi
movq %r14, %rsi
movq %r12, %rcx
callq 0x6779
testq %rax, %rax
je 0x2a071
testb $0x1, %r15b
je 0x2a05f
cmpb $0x1, 0x40(%rax)
jne 0x2a05f
movq 0x50(%rbx), %rax
leaq 0x1dd75(%rip), %rdx     # 0x47ce5
jmp 0x2a07c
cmpl $0x0, 0x44(%r14)
jne 0x2a209
testq %rdx, %rdx
je 0x2a05f
movb $0x7, (%rdx)
jmp 0x2a05f
cmpl $0x0, 0x44(%r14)
jne 0x2a228
testq %rdx, %rdx
je 0x2a05f
movb $0x4, (%rdx)
jmp 0x2a05f
cmpl $0x0, 0x44(%r14)
jne 0x2a247
testq %rdx, %rdx
je 0x2a05f
movb $0x8, (%rdx)
jmp 0x2a05f
cmpl $0x0, 0x44(%r14)
jne 0x2a266
testq %rdx, %rdx
je 0x2a05f
movb $0x5, (%rdx)
jmp 0x2a05f
cmpl $0x0, 0x44(%r14)
jne 0x2a285
testq %rdx, %rdx
je 0x2a05f
movb $0x9, (%rdx)
jmp 0x2a05f
cmpl $0x0, 0x44(%r14)
jne 0x2a2a4
testq %rdx, %rdx
je 0x2a05f
movb $0x3, (%rdx)
jmp 0x2a05f
cmpl $0x0, 0x44(%r14)
jne 0x2a2c3
testq %rdx, %rdx
je 0x2a05f
movb $0x6, (%rdx)
jmp 0x2a05f
cmpl $0x0, 0x44(%r14)
jne 0x2a2e2
testq %rdx, %rdx
je 0x2a05f
movb $0xa, (%rdx)
jmp 0x2a05f
cmpl $0x0, 0x44(%r14)
jne 0x2a301
testq %rdx, %rdx
je 0x2a05f
movb $0x2, (%rdx)
jmp 0x2a05f
movq 0x48(%r14), %rax
movq 0x8(%rax), %rsi
movq %rbx, %rdi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x29d00
addq $0x408, %rsp            # imm = 0x408
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x50(%rbx), %rax
leaq 0x1dc57(%rip), %rdx     # 0x47cd3
movq %rbx, %rdi
movq %r12, %rsi
addq $0x408, %rsp            # imm = 0x408
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmpq *%rax
leaq 0x122c4(%rip), %rdi     # 0x3c360
leaq 0x1d897(%rip), %rsi     # 0x4793a
leaq 0x1dbd6(%rip), %rcx     # 0x47c80
movl $0x3d9, %edx            # imm = 0x3D9
callq 0x30a0
leaq 0x14885(%rip), %rdi     # 0x3e940
leaq 0x1d878(%rip), %rsi     # 0x4793a
leaq 0x1dbb7(%rip), %rcx     # 0x47c80
movl $0x3cf, %edx            # imm = 0x3CF
callq 0x30a0
leaq 0x15d18(%rip), %rdi     # 0x3fdf2
leaq 0x1d859(%rip), %rsi     # 0x4793a
leaq 0x1db98(%rip), %rcx     # 0x47c80
movl $0x34e, %edx            # imm = 0x34E
callq 0x30a0
leaq 0x12267(%rip), %rdi     # 0x3c360
leaq 0x1d83a(%rip), %rsi     # 0x4793a
leaq 0x1db79(%rip), %rcx     # 0x47c80
movl $0x3f5, %edx            # imm = 0x3F5
callq 0x30a0
leaq 0x1dc07(%rip), %rdi     # 0x47d1f
leaq 0x1d81b(%rip), %rsi     # 0x4793a
leaq 0x1db5a(%rip), %rcx     # 0x47c80
movl $0x3bf, %edx            # imm = 0x3BF
callq 0x30a0
leaq 0x1e699(%rip), %rdi     # 0x487d0
leaq 0x1d7fc(%rip), %rsi     # 0x4793a
leaq 0x1db3b(%rip), %rcx     # 0x47c80
movl $0x3e6, %edx            # imm = 0x3E6
callq 0x30a0
leaq 0x14688(%rip), %rdi     # 0x3e7de
leaq 0x1d7dd(%rip), %rsi     # 0x4793a
leaq 0x1db1c(%rip), %rcx     # 0x47c80
movl $0x3ad, %edx            # imm = 0x3AD
callq 0x30a0
leaq 0x1db4b(%rip), %rdi     # 0x47cc0
leaq 0x1d7be(%rip), %rsi     # 0x4793a
leaq 0x1dafd(%rip), %rcx     # 0x47c80
movl $0x354, %edx            # imm = 0x354
callq 0x30a0
leaq 0x1db2c(%rip), %rdi     # 0x47cc0
leaq 0x1d79f(%rip), %rsi     # 0x4793a
leaq 0x1dade(%rip), %rcx     # 0x47c80
movl $0x386, %edx            # imm = 0x386
callq 0x30a0
leaq 0x1db0d(%rip), %rdi     # 0x47cc0
leaq 0x1d780(%rip), %rsi     # 0x4793a
leaq 0x1dabf(%rip), %rcx     # 0x47c80
movl $0x38b, %edx            # imm = 0x38B
callq 0x30a0
leaq 0x1db63(%rip), %rdi     # 0x47d35
leaq 0x1d761(%rip), %rsi     # 0x4793a
leaq 0x1daa0(%rip), %rcx     # 0x47c80
movl $0x3a5, %edx            # imm = 0x3A5
callq 0x30a0
leaq 0x1e5df(%rip), %rdi     # 0x487d0
leaq 0x1d742(%rip), %rsi     # 0x4793a
leaq 0x1da81(%rip), %rcx     # 0x47c80
movl $0x390, %edx            # imm = 0x390
callq 0x30a0
leaq 0x1dab0(%rip), %rdi     # 0x47cc0
leaq 0x1d723(%rip), %rsi     # 0x4793a
leaq 0x1da62(%rip), %rcx     # 0x47c80
movl $0x368, %edx            # imm = 0x368
callq 0x30a0
leaq 0x1da91(%rip), %rdi     # 0x47cc0
leaq 0x1d704(%rip), %rsi     # 0x4793a
leaq 0x1da43(%rip), %rcx     # 0x47c80
movl $0x36d, %edx            # imm = 0x36D
callq 0x30a0
leaq 0x1da72(%rip), %rdi     # 0x47cc0
leaq 0x1d6e5(%rip), %rsi     # 0x4793a
leaq 0x1da24(%rip), %rcx     # 0x47c80
movl $0x372, %edx            # imm = 0x372
callq 0x30a0
leaq 0x1da53(%rip), %rdi     # 0x47cc0
leaq 0x1d6c6(%rip), %rsi     # 0x4793a
leaq 0x1da05(%rip), %rcx     # 0x47c80
movl $0x377, %edx            # imm = 0x377
callq 0x30a0
leaq 0x1da34(%rip), %rdi     # 0x47cc0
leaq 0x1d6a7(%rip), %rsi     # 0x4793a
leaq 0x1d9e6(%rip), %rcx     # 0x47c80
movl $0x37c, %edx            # imm = 0x37C
callq 0x30a0
leaq 0x1da15(%rip), %rdi     # 0x47cc0
leaq 0x1d688(%rip), %rsi     # 0x4793a
leaq 0x1d9c7(%rip), %rcx     # 0x47c80
movl $0x363, %edx            # imm = 0x363
callq 0x30a0
leaq 0x1d9f6(%rip), %rdi     # 0x47cc0
leaq 0x1d669(%rip), %rsi     # 0x4793a
leaq 0x1d9a8(%rip), %rcx     # 0x47c80
movl $0x35e, %edx            # imm = 0x35E
callq 0x30a0
leaq 0x1d9d7(%rip), %rdi     # 0x47cc0
leaq 0x1d64a(%rip), %rsi     # 0x4793a
leaq 0x1d989(%rip), %rcx     # 0x47c80
movl $0x381, %edx            # imm = 0x381
callq 0x30a0
leaq 0x1d9b8(%rip), %rdi     # 0x47cc0
leaq 0x1d62b(%rip), %rsi     # 0x4793a
leaq 0x1d96a(%rip), %rcx     # 0x47c80
movl $0x359, %edx            # imm = 0x359
callq 0x30a0
leaq 0x14469(%rip), %rdi     # 0x3e790
leaq 0x1d60c(%rip), %rsi     # 0x4793a
leaq 0x1d94b(%rip), %rcx     # 0x47c80
movl $0x3aa, %edx            # imm = 0x3AA
callq 0x30a0
leaq 0x14426(%rip), %rdi     # 0x3e76c
leaq 0x1d5ed(%rip), %rsi     # 0x4793a
leaq 0x1d92c(%rip), %rcx     # 0x47c80
movl $0x395, %edx            # imm = 0x395
callq 0x30a0
leaq 0x1d95b(%rip), %rdi     # 0x47cc0
leaq 0x1d5ce(%rip), %rsi     # 0x4793a
leaq 0x1d90d(%rip), %rcx     # 0x47c80
movl $0x3f0, %edx            # imm = 0x3F0
callq 0x30a0