// File: /workspace/github_c_makefile_star2_O0/Ihsoh[P]ilang/compiler/frontend/semantics.c
// Function: var_with_parent
static void _var_with_parent(
	ParserContext *ctx,
	ParserASTNode *node,
	ParserASTNode *node_parent
) {
	assert(ctx);
	assert(node);
	assert(node->type == FE_NODE_VAR);
	assert(node->nchilds > 0);
	assert(node_parent);

	ParserASTNode *align_node = FE_VAR_AST_NODE_GET_ALIGN_NODE(node);
	int align = 0;
	if (align_node != NULL) {
		assert(align_node->nchilds == 1);
		switch (_get_node_catagory(align_node->childs[0]->type)) {
			case FE_SEM_NODE_CATEGORY_TYPE: {
				ParserASTNode *type_node = align_node->childs[0];
				_type(ctx, type_node, NULL);
				align = (int) _calc_type_align(ctx, node, type_node);
				assert(align >= 1);
				FE_VAR_AST_NODE_SET_ALIGN(node, align);
				break;
			}
			case FE_SEM_NODE_CATAGORY_EXPR: {
				ParserASTNode *expr_node = align_node->childs[0];
				_expr(ctx, expr_node);
				if (!FE_EXPR_AST_NODE_GET_CONSTANT(expr_node)) {
					_SYNERR_NODE(ctx, expr_node, "align parameter must be constant expression.");
				}
				align = _get_constexpr_int(ctx, expr_node);
				if (align <= 0) {
					_SYNERR_NODE(ctx, expr_node, "align parameter must be greater than 0.");
				}
				if (align != 1 && align % 2 != 0) {
					_SYNERR_NODE(ctx, expr_node, "align parameter is not a power of 2.");
				}
				FE_VAR_AST_NODE_SET_ALIGN(node, align);
				break;
			}
			default: {
				assert(0);
				break;
			}
		}
	}

	ParserSymbol *func_symbol = NULL;
	uint8_t var_scope_type = _get_var_scope_type(node, &func_symbol);
	FE_VAR_AST_NODE_SET_TYPE(node, var_scope_type);

	for (int i = 0; i < node->nchilds; i++) {
		ParserASTNode *node_var_item = node->childs[i];
		assert(node_var_item->type == FE_NODE_VAR_ITEM);
		assert(node_var_item->nchilds == 2 || node_var_item->nchilds == 3);

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

		ParserASTNode *node_type = node_var_item->childs[1];
		uint8_t var_type = 0;
		_type(ctx, node_type, &var_type);
		if (var_type == FE_TYPE_FUNC) {
			_SYNERR_NODE(
					ctx,
					node,
					"cannot define a function type variable, "
					"but can define a function pointer type(*function(...)) variable."
				);
		}
		
		ParserSymbol *symbol = fe_parser_add_var_symbol_to_node(
			ctx,
			node_parent,
			node_id->token,
			var_type,
			node_type
		);
		FE_VAR_SYMBOL_SET_FUNC_SYMBOL(symbol, func_symbol);
		if (align > 0) {
			FE_VAR_SYMBOL_SET_ALIGN(symbol, align);
		} else {
			FE_VAR_SYMBOL_SET_ALIGN(symbol, _calc_type_align(ctx, node, node_type));
		}

		FE_VAR_ITEM_AST_NODE_SET_SYMBOL(node_var_item, symbol);

		if (node_var_item->nchilds == 3) {
			// 如果变量是结构体成员变量，则不被允许包含初始化表达式。
			if (var_scope_type == FE_VAR_TYPE_STRUCT_MEMBER) {
				_SYNERR_NODE(
					ctx,
					node,
					"struct member variable cannot contain initial expression."
				);
			}

			ParserASTNode *node_expr = node_var_item->childs[2];

			// 插入一个cast节点进行类型强制转换。
			ParserASTNode *node_cast = fe_parser_new_node(
				ctx, FE_NODE_EXPR_CAST, "FE_NODE_EXPR_CAST", NULL
			);
			parser_add_child(ctx, node_cast, node_type);
			parser_insert_node(ctx, &(node_expr->childs[0]), node_cast);

			_expr_wrapper(ctx, node_expr);

			// 如果变量是全局变量，则初始化表达式只允许常量表达式。
			bool const_expr = FE_EXPR_AST_NODE_GET_CONSTANT(node_expr);
			if (var_scope_type == FE_VAR_TYPE_GLOBAL && !const_expr) {
				_SYNERR_NODE(
					ctx,
					node,
					"variable initial expression must be constant expression."
				);
			}

			ParserASTNode *node_expr_type = FE_EXPR_AST_NODE_GET_TYPE_NODE(node_expr);
			if (!_is_compatible_type_for_assign(ctx, node_type, node_expr_type, false)) {
				_SYNERR_NODE(
					ctx,
					node,
					"incompatible initial expression."
				);
			}
		}

	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1cc0, %rsp           # imm = 0x1CC0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
cmpq $0x0, -0x8(%rbp)
je 0x4ea20
jmp 0x4ea3f
leaq 0x2db2f(%rip), %rdi     # 0x7c556
leaq 0x2f81c(%rip), %rsi     # 0x7e24a
movl $0x435, %edx            # imm = 0x435
leaq 0x2f969(%rip), %rcx     # 0x7e3a3
callq 0x30a0
cmpq $0x0, -0x10(%rbp)
je 0x4ea48
jmp 0x4ea67
leaq 0x27584(%rip), %rdi     # 0x75fd3
leaq 0x2f7f4(%rip), %rsi     # 0x7e24a
movl $0x436, %edx            # imm = 0x436
leaq 0x2f941(%rip), %rcx     # 0x7e3a3
callq 0x30a0
movq -0x10(%rbp), %rax
cmpl $0xc00, (%rax)          # imm = 0xC00
jne 0x4ea75
jmp 0x4ea94
leaq 0x2fd5a(%rip), %rdi     # 0x7e7d6
leaq 0x2f7c7(%rip), %rsi     # 0x7e24a
movl $0x437, %edx            # imm = 0x437
leaq 0x2f914(%rip), %rcx     # 0x7e3a3
callq 0x30a0
movq -0x10(%rbp), %rax
cmpl $0x0, 0x44(%rax)
jle 0x4eaa0
jmp 0x4eabf
leaq 0x25b0e(%rip), %rdi     # 0x745b5
leaq 0x2f79c(%rip), %rsi     # 0x7e24a
movl $0x438, %edx            # imm = 0x438
leaq 0x2f8e9(%rip), %rcx     # 0x7e3a3
callq 0x30a0
cmpq $0x0, -0x18(%rbp)
je 0x4eac8
jmp 0x4eae7
leaq 0x2f8c8(%rip), %rdi     # 0x7e397
leaq 0x2f774(%rip), %rsi     # 0x7e24a
movl $0x439, %edx            # imm = 0x439
leaq 0x2f8c1(%rip), %rcx     # 0x7e3a3
callq 0x30a0
movq -0x10(%rbp), %rax
movq 0x68(%rax), %rax
movq %rax, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x4ecd4
movq -0x20(%rbp), %rax
cmpl $0x1, 0x44(%rax)
jne 0x4eb11
jmp 0x4eb30
leaq 0x2f8d4(%rip), %rdi     # 0x7e3ec
leaq 0x2f72b(%rip), %rsi     # 0x7e24a
movl $0x43e, %edx            # imm = 0x43E
leaq 0x2f878(%rip), %rcx     # 0x7e3a3
callq 0x30a0
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movl (%rax), %edi
callq 0x4f080
movl %eax, %ecx
movl %ecx, -0x1cb4(%rbp)
subl $0x1, %eax
je 0x4eb61
jmp 0x4eb51
movl -0x1cb4(%rbp), %eax
subl $0x2, %eax
je 0x4ebcb
jmp 0x4ecb3
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x4f0d0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x4f150
movl %eax, -0x24(%rbp)
cmpl $0x1, -0x24(%rbp)
jl 0x4eb9d
jmp 0x4ebbc
leaq 0x2f861(%rip), %rdi     # 0x7e405
leaq 0x2f69f(%rip), %rsi     # 0x7e24a
movl $0x444, %edx            # imm = 0x444
leaq 0x2f7ec(%rip), %rcx     # 0x7e3a3
callq 0x30a0
movl -0x24(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x70(%rax)
jmp 0x4ecd2
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x4f4b0
movq -0x38(%rbp), %rax
testb $0x1, 0x70(%rax)
jne 0x4ec1f
leaq -0x440(%rbp), %rdi
leaq 0x2f811(%rip), %rsi     # 0x7e410
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
leaq -0x440(%rbp), %rdx
callq *%rax
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x4f530
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
jg 0x4ec63
leaq -0x840(%rbp), %rdi
leaq 0x2f7fa(%rip), %rsi     # 0x7e43d
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
leaq -0x840(%rbp), %rdx
callq *%rax
cmpl $0x1, -0x24(%rbp)
je 0x4eca7
movl -0x24(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0x4eca7
leaq -0xc40(%rbp), %rdi
leaq 0x2f7de(%rip), %rsi     # 0x7e465
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
leaq -0xc40(%rbp), %rdx
callq *%rax
movl -0x24(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x70(%rax)
jmp 0x4ecd2
leaq 0x237a1(%rip), %rdi     # 0x7245b
leaq 0x2f589(%rip), %rsi     # 0x7e24a
movl $0x459, %edx            # imm = 0x459
leaq 0x2f6d6(%rip), %rcx     # 0x7e3a3
callq 0x30a0
jmp 0x4ecd4
movq $0x0, -0xc48(%rbp)
movq -0x10(%rbp), %rdi
leaq -0xc48(%rbp), %rsi
callq 0x4f560
movb %al, -0xc49(%rbp)
movb -0xc49(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0x60(%rax)
movl $0x0, -0xc50(%rbp)
movl -0xc50(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0x44(%rcx), %eax
jge 0x4f06c
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0xc50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xc58(%rbp)
movq -0xc58(%rbp), %rax
cmpl $0xc01, (%rax)          # imm = 0xC01
jne 0x4ed4a
jmp 0x4ed69
leaq 0x25876(%rip), %rdi     # 0x745c7
leaq 0x2f4f2(%rip), %rsi     # 0x7e24a
movl $0x465, %edx            # imm = 0x465
leaq 0x2f63f(%rip), %rcx     # 0x7e3a3
callq 0x30a0
movq -0xc58(%rbp), %rax
cmpl $0x2, 0x44(%rax)
je 0x4ed83
movq -0xc58(%rbp), %rax
cmpl $0x3, 0x44(%rax)
jne 0x4ed85
jmp 0x4eda4
leaq 0x25863(%rip), %rdi     # 0x745ef
leaq 0x2f4b7(%rip), %rsi     # 0x7e24a
movl $0x466, %edx            # imm = 0x466
leaq 0x2f604(%rip), %rcx     # 0x7e3a3
callq 0x30a0
movq -0xc58(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movq %rax, -0xc60(%rbp)
movq -0xc60(%rbp), %rax
cmpl $0x200, (%rax)          # imm = 0x200
jne 0x4edca
jmp 0x4ede9
leaq 0x259bb(%rip), %rdi     # 0x7478c
leaq 0x2f472(%rip), %rsi     # 0x7e24a
movl $0x469, %edx            # imm = 0x469
leaq 0x2f5bf(%rip), %rcx     # 0x7e3a3
callq 0x30a0
movq -0xc58(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0xc68(%rbp)
movb $0x0, -0xc69(%rbp)
movq -0x8(%rbp), %rdi
movq -0xc68(%rbp), %rsi
leaq -0xc69(%rbp), %rdx
callq 0x4f0d0
movzbl -0xc69(%rbp), %eax
cmpl $0xf, %eax
jne 0x4ee57
leaq -0x1070(%rbp), %rdi
leaq 0x2f653(%rip), %rsi     # 0x7e48a
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x1070(%rbp), %rdx
callq *%rax
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0xc60(%rbp), %rax
movq 0x10(%rax), %rdx
movb -0xc69(%rbp), %al
movq -0xc68(%rbp), %r8
movzbl %al, %ecx
callq 0x42d60
movq %rax, -0x1078(%rbp)
movq -0xc48(%rbp), %rcx
movq -0x1078(%rbp), %rax
movq %rcx, 0x40(%rax)
cmpl $0x0, -0x24(%rbp)
jle 0x4eead
movl -0x24(%rbp), %ecx
movq -0x1078(%rbp), %rax
movl %ecx, 0x60(%rax)
jmp 0x4eecd
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0xc68(%rbp), %rdx
callq 0x4f150
movl %eax, %ecx
movq -0x1078(%rbp), %rax
movl %ecx, 0x60(%rax)
movq -0x1078(%rbp), %rcx
movq -0xc58(%rbp), %rax
movq %rcx, 0x60(%rax)
movq -0xc58(%rbp), %rax
cmpl $0x3, 0x44(%rax)
jne 0x4f056
movzbl -0xc49(%rbp), %eax
cmpl $0x3, %eax
jne 0x4ef2a
leaq -0x1480(%rbp), %rdi
leaq 0x2f5e9(%rip), %rsi     # 0x7e4f3
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x1480(%rbp), %rdx
callq *%rax
movq -0xc58(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x1488(%rbp)
movq -0x8(%rbp), %rdi
movl $0xec8, %esi            # imm = 0xEC8
leaq 0x2dbf8(%rip), %rdx     # 0x7cb48
xorl %eax, %eax
movl %eax, %ecx
callq 0x42020
movq %rax, -0x1490(%rbp)
movq -0x8(%rbp), %rdi
movq -0x1490(%rbp), %rsi
movq -0xc68(%rbp), %rdx
callq 0x7e20
movq -0x8(%rbp), %rdi
movq -0x1488(%rbp), %rax
movq 0x48(%rax), %rsi
movq -0x1490(%rbp), %rdx
callq 0x7ce0
movq -0x8(%rbp), %rdi
movq -0x1488(%rbp), %rsi
callq 0x4f680
movq -0x1488(%rbp), %rax
movb 0x70(%rax), %al
andb $0x1, %al
movb %al, -0x1491(%rbp)
movzbl -0xc49(%rbp), %eax
cmpl $0x1, %eax
jne 0x4eff7
testb $0x1, -0x1491(%rbp)
jne 0x4eff7
leaq -0x18a0(%rbp), %rdi
leaq 0x2f556(%rip), %rsi     # 0x7e52d
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x18a0(%rbp), %rdx
callq *%rax
movq -0x1488(%rbp), %rax
movq 0x68(%rax), %rax
movq %rax, -0x18a8(%rbp)
movq -0x8(%rbp), %rdi
movq -0xc68(%rbp), %rsi
movq -0x18a8(%rbp), %rdx
xorl %ecx, %ecx
callq 0x4f750
testb $0x1, %al
jne 0x4f054
leaq -0x1cb0(%rbp), %rdi
leaq 0x2f532(%rip), %rsi     # 0x7e566
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x1cb0(%rbp), %rdx
callq *%rax
jmp 0x4f056
jmp 0x4f058
movl -0xc50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc50(%rbp)
jmp 0x4ed0c
addq $0x1cc0, %rsp           # imm = 0x1CC0
popq %rbp
retq
nopw %cs:(%rax,%rax)