// File: /workspace/github_c_makefile_star2_O1/hsjoihs[P]c-compiler/parse_analyze_statement.c
// Function: parse_compound_statement
struct Statement parse_compound_statement(struct AnalyzerState *ptr_ps,
                                          const struct Token **ptr_tokvec)
{
	const struct Token *tokvec = *ptr_tokvec;
	struct Statement statement;
	statement.category = COMPOUND_STATEMENT;
	statement.labels = init_vector();
	statement.statement_vector = init_vector();
	if (tokvec[0].kind == LEFT_BRACE) {

		struct ScopeChain current_table = ptr_ps->scope_chain;

		struct ScopeChain new_table;
		new_table.var_table = init_map();

		/* current_table disappears at the end of this function,
		   but there is no problem because new_table itself gets overwritten at
		   the end of this function.
		 */
		new_table.outer = &current_table;

		ptr_ps->scope_chain = new_table;

		++tokvec;
		*ptr_tokvec = tokvec;
		while (1) {
			if (tokvec[0].kind == RIGHT_BRACE) {
				++tokvec;
				*ptr_tokvec = tokvec;
				ptr_ps->scope_chain = current_table;

				return statement;
			} else if (can_start_a_type(tokvec)) {
				struct Type *optional_ptr_type =
				    try_parse_type_specifier_and_semicolon(&tokvec);
				if (optional_ptr_type) {
					struct Statement s;
					s.category = DECLARATION_STATEMENT;
					s.declaration.type = *optional_ptr_type;
					s.declaration.ident_str = 0;
					s.labels = init_vector(); /* must initialize this, since it
					                             is used in goto traversal */
					struct Statement *ptr_s =
					    calloc(1, sizeof(struct Statement));
					*ptr_s = s;
					push_vector(&statement.statement_vector, ptr_s);
					continue;
				}

				const char *str;
				struct UntypedExpr *ptr_uexpr;
				const struct Type vartype =
				    parse_declaration(&tokvec, &str, &ptr_uexpr);

				/* while function prototypes are also allowed here in C, I will
				 * not implement it here */
				if (vartype.type_category == FN) {
					unsupported(
					    "declaring a function inside a compound statement\n");
					exit(EXIT_FAILURE);
				}

				struct Expr *ptr_expr = declare_var_and_return_initializer(
				    ptr_ps, &vartype, str, ptr_uexpr, &statement);

				if (ptr_expr) {
					struct Statement assignment;
					assignment.category = EXPRESSION_STATEMENT;
					assignment.expr1 = *ptr_expr;
					assignment.labels = init_vector();
					struct Statement *ptr_s =
					    calloc(1, sizeof(struct Statement));
					*ptr_s = assignment;
					push_vector(&statement.statement_vector, ptr_s);
				}

			} else {
				struct Statement s = parse_statement(ptr_ps, &tokvec);
				struct Statement *ptr_s = calloc(1, sizeof(struct Statement));
				*ptr_s = s;
				push_vector(&statement.statement_vector, ptr_s);
			}
		}
	} else {
		fprintf(stderr,
		        "****************************\n"
		        "* INTERNAL COMPILER ERROR @ %s\n"
		        "* Unexpected value: `tokvec[0].kind` != `LEFT_BRACE` (which "
		        "is %d), and is instead %d\n\n"
		        "****************************\n",
		        __func__, LEFT_BRACE, tokvec[0].kind);
		exit(EXIT_FAILURE);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x418, %rsp            # imm = 0x418
movq %rdx, %r15
movq %rsi, %r14
movq %rdi, %rbx
movq (%rdx), %rax
movq %rax, -0x30(%rbp)
movl $0x0, (%rdi)
callq 0x5af4
movq %rax, 0x378(%rbx)
movq %rdx, 0x380(%rbx)
callq 0x5af4
movq %rax, 0x8(%rbx)
movq %rbx, -0x38(%rbp)
movq %rdx, 0x10(%rbx)
movq -0x30(%rbp), %rax
movl (%rax), %edi
cmpl $0x1e, %edi
jne 0x4855
movups (%r14), %xmm0
leaq -0x60(%rbp), %rbx
movaps %xmm0, (%rbx)
callq 0xa39e
movq %rax, (%r14)
movq %rbx, 0x8(%r14)
movq -0x30(%rbp), %rax
leaq 0x20(%rax), %rdi
movq %rdi, -0x30(%rbp)
movq %r15, -0x40(%rbp)
movq %rdi, (%r15)
cmpl $0x1f, 0x20(%rax)
je 0x481c
movq -0x38(%rbp), %rax
leaq 0x8(%rax), %r12
leaq -0x30(%rbp), %r13
leaq -0xb0(%rbp), %rbx
callq 0x9d5f
testl %eax, %eax
je 0x471a
movq %r13, %rdi
callq 0x9c4d
testq %rax, %rax
je 0x4763
movl $0x14, %ecx
leaq -0x124(%rbp), %rdi
movq %rax, %rsi
rep  movsl (%rsi), %es:(%rdi)
callq 0x5af4
movq %rax, %rbx
movq %rdx, %r13
movl $0x1, %edi
movl $0x390, %esi            # imm = 0x390
callq 0x10d0
movq %rax, %r15
movl $0xa, (%rax)
leaq 0x4(%rax), %rdi
movl $0x36c, %edx            # imm = 0x36C
leaq -0x440(%rbp), %rsi
callq 0x1100
movq $0x0, 0x370(%r15)
movq %rbx, 0x378(%r15)
leaq -0xb0(%rbp), %rbx
movq %r13, 0x380(%r15)
leaq -0x30(%rbp), %r13
movq %r12, %rdi
movq %r15, %rsi
jmp 0x480a
leaq -0x440(%rbp), %r15
movq %r15, %rdi
movq %r14, %rsi
movq %r13, %rdx
callq 0x3a5f
movl $0x1, %edi
movl $0x390, %esi            # imm = 0x390
callq 0x10d0
movq %rax, %rbx
movl $0x390, %edx            # imm = 0x390
movq %rax, %rdi
movq %r15, %rsi
callq 0x1100
movq %r12, %rdi
movq %rbx, %rsi
leaq -0xb0(%rbp), %rbx
jmp 0x480a
movq %rbx, %rdi
movq %r13, %rsi
leaq -0x50(%rbp), %rdx
leaq -0x48(%rbp), %rcx
callq 0x9d86
cmpl $0x3, -0xb0(%rbp)
je 0x4849
movq -0x50(%rbp), %rdx
movq -0x48(%rbp), %rcx
movq %r14, %rdi
movq %rbx, %rsi
movq -0x38(%rbp), %r8
callq 0x485a
testq %rax, %rax
je 0x480f
movl $0x100, %edx            # imm = 0x100
leaq -0x42c(%rbp), %rdi
movq %rax, %rsi
callq 0x1100
callq 0x5af4
movq %rax, %rbx
movq %rdx, %r15
movl $0x1, %edi
movl $0x390, %esi            # imm = 0x390
callq 0x10d0
movq %rax, %r13
movl $0x9, (%rax)
leaq 0x4(%rax), %rdi
movl $0x114, %edx            # imm = 0x114
leaq -0x440(%rbp), %rsi
callq 0x1100
movq %rbx, 0x378(%r13)
leaq -0xb0(%rbp), %rbx
movq %r15, 0x380(%r13)
movq %r12, %rdi
movq %r13, %rsi
leaq -0x30(%rbp), %r13
callq 0x5ba7
movq -0x30(%rbp), %rdi
cmpl $0x1f, (%rdi)
jne 0x4684
addq $0x20, %rdi
movq %rdi, -0x30(%rbp)
movq -0x40(%rbp), %rax
movq %rdi, (%rax)
movaps -0x60(%rbp), %xmm0
movups %xmm0, (%r14)
movq -0x38(%rbp), %rax
addq $0x418, %rsp            # imm = 0x418
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xa2f4(%rip), %rdi      # 0xeb44
callq 0x94cd
callq 0x14e8