// File: /workspace/github_c_makefile_star2_O1/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x438, %rsp            # imm = 0x438
movq %rdx, -0x60(%rbp)
testq %rsi, %rsi
je 0x2baf1
movq %rsi, %r13
cmpl $0xc00, (%rsi)          # imm = 0xC00
jne 0x2bb10
cmpl $0x0, 0x44(%r13)
jle 0x2bb2f
movq %rdi, %r14
movq 0x68(%r13), %rax
testq %rax, %rax
je 0x2b6cb
cmpl $0x1, 0x44(%rax)
jne 0x2bb6d
movq 0x48(%rax), %rax
movq (%rax), %rbx
movzbl 0x1(%rbx), %eax
shll $0x8, %eax
xorl %ecx, %ecx
cmpl $0xe00, %eax            # imm = 0xE00
sete %cl
addl %ecx, %ecx
cmpl $0x400, %eax            # imm = 0x400
movl $0x1, %eax
cmovnel %ecx, %eax
cmpl $0x2, %eax
je 0x2b6d3
cmpl $0x1, %eax
jne 0x2bb8c
movq %r14, %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x2bbca
movq %r14, %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x2bbfc
testq %rax, %rax
je 0x2bbab
movq %rax, %r15
jmp 0x2b79f
xorl %r15d, %r15d
jmp 0x2b7a3
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2c01f
cmpb $0x0, 0x70(%rbx)
jne 0x2b715
movups 0x20323(%rip), %xmm0    # 0x4ba0e
leaq -0x460(%rbp), %rdx
movups %xmm0, 0x1d(%rdx)
movups 0x20304(%rip), %xmm0    # 0x4ba01
movaps %xmm0, 0x10(%rdx)
movups 0x202e9(%rip), %xmm0    # 0x4b9f1
movaps %xmm0, (%rdx)
movq %r14, %rdi
movq %rbx, %rsi
callq *0x58(%r14)
movq %rbx, %rdi
callq 0x32cd8
movq %rax, %r15
testl %r15d, %r15d
jg 0x2b759
movups 0x20302(%rip), %xmm0    # 0x4ba2e
leaq -0x460(%rbp), %rdx
movaps %xmm0, 0x10(%rdx)
movups 0x202e0(%rip), %xmm0    # 0x4ba1e
movaps %xmm0, (%rdx)
movabsq $0x2e30206e616874, %rax # imm = 0x2E30206E616874
movq %rax, 0x20(%rdx)
movq %r14, %rdi
movq %rbx, %rsi
callq *0x58(%r14)
cmpl $0x1, %r15d
sete %al
testb $0x1, %r15b
sete %cl
orb %al, %cl
jne 0x2b79f
movups 0x202e4(%rip), %xmm0    # 0x4ba56
leaq -0x460(%rbp), %rdx
movaps %xmm0, 0x10(%rdx)
movups 0x202c2(%rip), %xmm0    # 0x4ba46
movaps %xmm0, (%rdx)
movabsq $0x2e3220666f2072, %rax # imm = 0x2E3220666F2072
movq %rax, 0x1d(%rdx)
movq %r14, %rdi
movq %rbx, %rsi
callq *0x58(%r14)
movl %r15d, 0x70(%r13)
cmpl $0xc00, (%r13)          # imm = 0xC00
jne 0x2bb4e
movq %r13, %rax
movq %r14, -0x40(%rbp)
movq %r15, -0x58(%rbp)
movq 0x30(%rax), %rax
testq %rax, %rax
je 0x2bad2
movl (%rax), %ecx
cmpl $0x100, %ecx            # imm = 0x100
je 0x2b7f6
cmpl $0xd00, %ecx            # imm = 0xD00
je 0x2b80e
cmpl $0xa00, %ecx            # imm = 0xA00
jne 0x2b7bc
movq 0x60(%rax), %rax
movq %rax, -0x50(%rbp)
movb $0x2, %al
movl $0x0, -0x34(%rbp)
jmp 0x2b81d
movb $0x1, %al
movl %eax, -0x30(%rbp)
movq $0x0, -0x50(%rbp)
movl $0x0, -0x34(%rbp)
movb $0x1, %al
jmp 0x2b824
movb $0x3, %al
movb $0x1, %cl
movl %ecx, -0x34(%rbp)
movq $0x0, -0x50(%rbp)
movl $0x0, -0x30(%rbp)
movb %al, 0x60(%r13)
cmpl $0x0, 0x44(%r13)
jle 0x2ba63
xorl %r14d, %r14d
movq 0x48(%r13), %rax
movq (%rax,%r14,8), %r12
cmpl $0xc01, (%r12)          # imm = 0xC01
jne 0x2bab3
movl 0x44(%r12), %eax
andl $-0x2, %eax
cmpl $0x2, %eax
jne 0x2ba94
movq %r13, %r15
movq 0x48(%r12), %rax
movq (%rax), %r13
cmpl $0x200, (%r13)          # imm = 0x200
jne 0x2ba75
movq 0x8(%rax), %rsi
movb $0x0, -0x29(%rbp)
movq -0x40(%rbp), %rbx
movq %rbx, %rdi
movq %rsi, -0x48(%rbp)
leaq -0x29(%rbp), %rdx
callq 0x2bbca
cmpb $0xf, -0x29(%rbp)
jne 0x2b8c0
movl $0x69, %edx
leaq -0x460(%rbp), %rdi
leaq 0x201c0(%rip), %rsi     # 0x4ba6b
callq 0x3100
movq %rbx, %rdi
movq %r15, %rsi
leaq -0x460(%rbp), %rdx
callq *0x58(%rbx)
movq 0x10(%r13), %rdx
movzbl -0x29(%rbp), %ecx
movq %rbx, %rdi
movq -0x60(%rbp), %rsi
movq -0x48(%rbp), %r8
callq 0x2514e
movq %rax, %r13
movq -0x50(%rbp), %rax
movq %rax, 0x40(%r13)
movq -0x58(%rbp), %rcx
movl %ecx, %eax
testl %ecx, %ecx
jg 0x2b8fd
movq -0x40(%rbp), %rdi
movq %r15, %rsi
movq -0x48(%rbp), %rdx
callq 0x2bbfc
movl %eax, 0x60(%r13)
movq %r13, 0x60(%r12)
cmpl $0x3, 0x44(%r12)
movq %r15, %r13
jne 0x2ba53
cmpb $0x0, -0x34(%rbp)
je 0x2b964
movups 0x201dc(%rip), %xmm0    # 0x4bafe
movups %xmm0, -0x436(%rbp)
movups 0x201c4(%rip), %xmm0    # 0x4baf4
movaps %xmm0, -0x440(%rbp)
movups 0x201a6(%rip), %xmm0    # 0x4bae4
movaps %xmm0, -0x450(%rbp)
movups 0x20188(%rip), %xmm0    # 0x4bad4
movaps %xmm0, -0x460(%rbp)
movq -0x40(%rbp), %rdi
movq %r13, %rsi
leaq -0x460(%rbp), %rdx
callq *0x58(%rdi)
movq 0x48(%r12), %rax
movq 0x10(%rax), %r13
movq -0x40(%rbp), %rbx
movq %rbx, %rdi
movl $0xec8, %esi            # imm = 0xEC8
leaq 0x1e6b2(%rip), %rdx     # 0x4a032
xorl %ecx, %ecx
callq 0x24383
movq %rax, %r12
movq %rbx, %rdi
movq %rax, %rsi
movq -0x48(%rbp), %rdx
callq 0x69ff
movq 0x48(%r13), %rsi
movq %rbx, %rdi
movq %r12, %rdx
callq 0x691e
movq %rbx, %rdi
movq %r13, %rsi
callq 0x2c76c
cmpb $0x0, -0x30(%rbp)
je 0x2ba08
cmpb $0x0, 0x70(%r13)
jne 0x2ba08
movups 0x20170(%rip), %xmm0    # 0x4bb37
movups %xmm0, -0x437(%rbp)
movups 0x20159(%rip), %xmm0    # 0x4bb2e
movaps %xmm0, -0x440(%rbp)
movups 0x2013b(%rip), %xmm0    # 0x4bb1e
movaps %xmm0, -0x450(%rbp)
movups 0x2011d(%rip), %xmm0    # 0x4bb0e
movaps %xmm0, -0x460(%rbp)
movq %rbx, %rdi
movq %r15, %rsi
leaq -0x460(%rbp), %rdx
callq *0x58(%rbx)
movq 0x68(%r13), %rdx
movq %rbx, %rdi
movq -0x48(%rbp), %rsi
callq 0x2c7f6
testb %al, %al
movq %r15, %r13
jne 0x2ba53
movups 0x20131(%rip), %xmm0    # 0x4bb57
movaps %xmm0, -0x450(%rbp)
movups 0x20113(%rip), %xmm0    # 0x4bb47
movaps %xmm0, -0x460(%rbp)
movb $0x0, -0x440(%rbp)
movq -0x40(%rbp), %rdi
movq %r13, %rsi
leaq -0x460(%rbp), %rdx
callq *0x58(%rdi)
incq %r14
movslq 0x44(%r13), %rax
cmpq %rax, %r14
jl 0x2b836
addq $0x438, %rsp            # imm = 0x438
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x16c94(%rip), %rdi     # 0x42710
leaq 0x1fdd7(%rip), %rsi     # 0x4b85a
leaq 0x1fefa(%rip), %rcx     # 0x4b984
movl $0x469, %edx            # imm = 0x469
callq 0x30a0
leaq 0x16ad8(%rip), %rdi     # 0x42573
leaq 0x1fdb8(%rip), %rsi     # 0x4b85a
leaq 0x1fedb(%rip), %rcx     # 0x4b984
movl $0x466, %edx            # imm = 0x466
callq 0x30a0
leaq 0x16a91(%rip), %rdi     # 0x4254b
leaq 0x1fd99(%rip), %rsi     # 0x4b85a
leaq 0x1febc(%rip), %rcx     # 0x4b984
movl $0x465, %edx            # imm = 0x465
callq 0x30a0
leaq 0x148ab(%rip), %rdi     # 0x40384
leaq 0x1fd7a(%rip), %rsi     # 0x4b85a
leaq 0x21baf(%rip), %rcx     # 0x4d696
movl $0x42d, %edx            # imm = 0x42D
callq 0x30a0
leaq 0x1829e(%rip), %rdi     # 0x43d96
leaq 0x1fd5b(%rip), %rsi     # 0x4b85a
leaq 0x1fe7e(%rip), %rcx     # 0x4b984
movl $0x436, %edx            # imm = 0x436
callq 0x30a0
leaq 0x202a0(%rip), %rdi     # 0x4bdb7
leaq 0x1fd3c(%rip), %rsi     # 0x4b85a
leaq 0x1fe5f(%rip), %rcx     # 0x4b984
movl $0x437, %edx            # imm = 0x437
callq 0x30a0
leaq 0x16a03(%rip), %rdi     # 0x42539
leaq 0x1fd1d(%rip), %rsi     # 0x4b85a
leaq 0x1fe40(%rip), %rcx     # 0x4b984
movl $0x438, %edx            # imm = 0x438
callq 0x30a0
leaq 0x20262(%rip), %rdi     # 0x4bdb7
leaq 0x1fcfe(%rip), %rsi     # 0x4b85a
leaq 0x21b33(%rip), %rcx     # 0x4d696
movl $0x414, %edx            # imm = 0x414
callq 0x30a0
leaq 0x1fe59(%rip), %rdi     # 0x4b9cd
leaq 0x1fcdf(%rip), %rsi     # 0x4b85a
leaq 0x1fe02(%rip), %rcx     # 0x4b984
movl $0x43e, %edx            # imm = 0x43E
callq 0x30a0
leaq 0x147f1(%rip), %rdi     # 0x40384
leaq 0x1fcc0(%rip), %rsi     # 0x4b85a
leaq 0x1fde3(%rip), %rcx     # 0x4b984
movl $0x459, %edx            # imm = 0x459
callq 0x30a0
leaq 0x1fe34(%rip), %rdi     # 0x4b9e6
leaq 0x1fca1(%rip), %rsi     # 0x4b85a
leaq 0x1fdc4(%rip), %rcx     # 0x4b984
movl $0x444, %edx            # imm = 0x444
callq 0x30a0