// File: /workspace/github_cpp_makefile_star2_O2/CobaltXII[P]cxcc/./semantic/semantic_analyzer.hpp
// Function: semantic_analyzer_t::expression_type(expression_t*, symbol_table_t)
type_t expression_type(expression_t* expression, symbol_table_t symbols) {
		if (expression->type == et_integer_literal) {
			// An integer literal is of type int.
			return expression->return_type = {0};
		} else if (expression->type == et_string_literal) {
			// A string literal is of type int*.
			return expression->return_type = {1};
		} else if (expression->type == et_character_literal) {
			// A character literal is of type int.
			return expression->return_type = {0};
		} else if (expression->type == et_identifier) {
			// An identifier literal's type is equivalent to the type of the
			// entry in the symbol table under the name of the identifier.
			if (symbols.exists(expression->identifier)) {
				return expression->return_type = symbols.fetch(expression->identifier).type;
			} else {
				die("unknown identifier '" + expression->identifier + "'", expression);
				return expression->return_type = {0};
			}
		} else if (expression->type == et_indexing) {
			// An indexing expression's return type is the type of the array
			// expression with one less pointer-depth.
			return {expression_type(expression->indexing.array, symbols).pointer_depth - 1};
		} else if (expression->type == et_function_call) {
			// A function call's type is equivalent to the type of the entry
			// in the symbol table under the name of the function.
			function_call_expression_t function_call = expression->function_call;
			if (symbols.exists(function_call.function)) {
				return expression->return_type = symbols.fetch(function_call.function).type;
			} else {
				// Assume that the return type is int, it shouldn't matter
				// since all types are compatible.
				return expression->return_type = {0};
			}
		} else if (expression->type == et_binary) {
			binary_expression_t binary = expression->binary;
			if (binary.binary_operator == bi_addition ||
				binary.binary_operator == bi_subtraction ||
				binary.binary_operator == bi_multiplication ||
				binary.binary_operator == bi_division ||
				binary.binary_operator == bi_modulo)
			{
				// The return type of these types of binary expressions is
				// equivalent to the return type of the operand with the
				// greatest pointer depth.
				type_t left_type = expression_type(binary.left_operand, symbols);
				type_t right_type = expression_type(binary.right_operand, symbols);
				return expression->return_type = {std::max(left_type.pointer_depth, right_type.pointer_depth)};
			} else if (binary.binary_operator == bi_assignment ||
					   binary.binary_operator == bi_addition_assignment ||
					   binary.binary_operator == bi_subtraction_assignment ||
					   binary.binary_operator == bi_multiplication_assignment ||
					   binary.binary_operator == bi_division_assignment ||
					   binary.binary_operator == bi_modulo_assignment ||
					   binary.binary_operator == bi_binary_and_assignment ||
					   binary.binary_operator == bi_binary_or_assignment ||
					   binary.binary_operator == bi_binary_xor_assignment ||
					   binary.binary_operator == bi_binary_left_shift_assignment ||
					   binary.binary_operator == bi_binary_right_shift_assignment)
			{
				// The return type of this type of binary expression is
				// equivalent to the return type of the left-hand operand.
				return expression->return_type = expression_type(binary.left_operand, symbols);
			} else {
				// bi_logical_and,
				// bi_logical_or,
				// bi_relational_equal,
				// bi_relational_non_equal,
				// bi_relational_greater_than,
				// bi_relational_lesser_than,
				// bi_relational_greater_than_or_equal_to,
	            // bi_relational_lesser_than_or_equal_to,
	            // bi_binary_and,
				// bi_binary_or,
				// bi_binary_xor,
				// bi_binary_and_assignment,
				// bi_binary_or_assignment,
				// bi_binary_xor_assignment,
				// bi_binary_left_shift,
				// bi_binary_right_shift
				//
				// The return type of these types of binary expressions is
				// int.
				return expression->return_type = {0};
			}
		} else {
			unary_expression_t unary = expression->unary;
			if (unary.unary_operator == un_value_of) {
				// The return type of this type of unary expression is the
				// return type of the operand with one less pointer-depth.
				type_t operand_type = expression_type(unary.operand, symbols);
				return expression->return_type = {operand_type.pointer_depth - 1};
			} else if (unary.unary_operator == un_arithmetic_positive ||
					   unary.unary_operator == un_arithmetic_negative)
			{
				// The return type of these types of unary expressions is
				// equivalent to the return type of the operand.
				return expression->return_type = expression_type(unary.operand, symbols);
			} else if (unary.unary_operator == un_address_of) {
				// The return type of this type of unary expression is the
				// return type of the operand with one more pointer-depth.
				type_t operand_type = expression_type(unary.operand, symbols);
				return expression->return_type = {operand_type.pointer_depth + 1};
			} else {
				// un_logical_not
				// un_binary_not
				//
				// The return type of this type of unary expression is int.
				return expression->return_type = {0};
			}
		}
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x298, %rsp            # imm = 0x298
movq %rdx, %r14
movq %rsi, %rbx
movq %rdi, %r15
movl (%rsi), %eax
cmpq $0x6, %rax
ja 0xc8c7
leaq 0x399f(%rip), %rcx      # 0x10190
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
andq $0x0, 0x8(%rbx)
xorl %r14d, %r14d
jmp 0xcb40
movq 0xa8(%rbx), %rbx
leaq 0x258(%rsp), %r12
movq %r12, %rdi
movq %r14, %rsi
callq 0xc78c
movq %r15, %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq 0xc7c4
movq %rax, %r14
decq %r14
leaq 0x260(%rsp), %rdi
jmp 0xca57
movq $0x1, 0x8(%rbx)
pushq $0x1
popq %r14
jmp 0xcb40
leaq 0x88(%rbx), %r12
leaq 0xb8(%rsp), %r13
movq %r13, %rdi
movq %r12, %rsi
callq 0x22e0
movq %r14, %rdi
movq %r13, %rsi
callq 0xa168
movl %eax, %ebp
leaq 0xb8(%rsp), %rdi
callq 0x2100
testb %bpl, %bpl
je 0xca61
leaq 0x98(%rsp), %r15
movq %r15, %rdi
movq %r12, %rsi
callq 0x22e0
movq %r14, %rdi
movq %r15, %rsi
callq 0xcc74
movq (%rax), %r14
movq %r14, 0x8(%rbx)
leaq 0x98(%rsp), %rdi
callq 0x2100
jmp 0xcb40
movq 0x108(%rbx), %r12
movl 0x110(%rbx), %eax
testl %eax, %eax
je 0xcac9
cmpl $0x2, %eax
ja 0xcaff
leaq 0x118(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
callq 0xc78c
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0xc7c4
movq %rax, %r14
movq %rax, 0x8(%rbx)
leaq 0x120(%rsp), %rdi
jmp 0xca57
leaq 0xb8(%rbx), %rsi
leaq 0x40(%rsp), %r15
movq %r15, %rdi
callq 0xd096
leaq 0x20(%rsp), %rdi
movq %r15, %rsi
callq 0x22e0
leaq 0x20(%rsp), %rsi
movq %r14, %rdi
callq 0xa168
movl %eax, %ebp
leaq 0x20(%rsp), %rdi
callq 0x2100
testb %bpl, %bpl
je 0xcab5
movq %rsp, %rdi
leaq 0x40(%rsp), %rsi
callq 0x22e0
movq %rsp, %rsi
movq %r14, %rdi
callq 0xcc74
movq (%rax), %r14
movq %r14, 0x8(%rbx)
movq %rsp, %rdi
callq 0x2100
jmp 0xcabd
movq 0xf0(%rbx), %r12
movl 0x100(%rbx), %eax
cmpl $0x4, %eax
ja 0xca10
movq 0xf8(%rbx), %r13
leaq 0x218(%rsp), %rbp
movq %rbp, %rdi
movq %r14, %rsi
callq 0xc78c
movq %r15, %rdi
movq %r12, %rsi
movq %rbp, %rdx
callq 0xc7c4
movq %rax, %r12
leaq 0x220(%rsp), %rdi
callq 0xdbb0
leaq 0x1d8(%rsp), %rbp
movq %rbp, %rdi
movq %r14, %rsi
callq 0xc78c
movq %r15, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0xc7c4
movq %rax, %r14
leaq 0x1e0(%rsp), %rdi
callq 0xdbb0
cmpq %r14, %r12
cmovgq %r12, %r14
jmp 0xcb3c
cmpl $0x1c, %eax
ja 0xc7fa
movl $0x19c007e0, %ecx       # imm = 0x19C007E0
btl %eax, %ecx
jae 0xc7fa
leaq 0x198(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
callq 0xc78c
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0xc7c4
movq %rax, %r14
movq %rax, 0x8(%rbx)
leaq 0x1a0(%rsp), %rdi
callq 0xdbb0
jmp 0xcb40
leaq 0x40f4(%rip), %rsi      # 0x10b5c
leaq 0x40(%rsp), %r14
movq %r14, %rdi
movq %r12, %rdx
callq 0x6775
leaq 0x4166(%rip), %rdx      # 0x10be5
leaq 0x78(%rsp), %rdi
movq %r14, %rsi
callq 0x3ae1
leaq 0x78(%rsp), %rsi
movq %r15, %rdi
movq %rbx, %rdx
callq 0xcc22
leaq 0x78(%rsp), %rdi
callq 0x2100
leaq 0x40(%rsp), %rdi
callq 0x2100
jmp 0xc7fa
andq $0x0, 0x8(%rbx)
xorl %r14d, %r14d
leaq 0x40(%rsp), %rdi
callq 0x9afc
jmp 0xcb40
leaq 0x158(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
callq 0xc78c
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0xc7c4
movq %rax, %r14
leaq 0x160(%rsp), %rdi
callq 0xdbb0
decq %r14
jmp 0xcb3c
cmpl $0x3, %eax
jne 0xc7fa
leaq 0xd8(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
callq 0xc78c
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0xc7c4
movq %rax, %r14
leaq 0xe0(%rsp), %rdi
callq 0xdbb0
incq %r14
movq %r14, 0x8(%rbx)
movq %r14, %rax
addq $0x298, %rsp            # imm = 0x298
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0xe0(%rsp), %rdi
jmp 0xcc06
movq %rax, %rbx
leaq 0x120(%rsp), %rdi
jmp 0xcc06
movq %rax, %rbx
leaq 0x160(%rsp), %rdi
jmp 0xcc06
movq %rax, %rbx
leaq 0x1a0(%rsp), %rdi
jmp 0xcc06
movq %rax, %rbx
movq %rsp, %rdi
jmp 0xcbe2
movq %rax, %rbx
leaq 0x78(%rsp), %rdi
callq 0x2100
jmp 0xcbb9
movq %rax, %rbx
leaq 0x1e0(%rsp), %rdi
jmp 0xcc06
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
jmp 0xcbf4
movq %rax, %rbx
leaq 0x98(%rsp), %rdi
jmp 0xcbf4
movq %rax, %rbx
leaq 0x220(%rsp), %rdi
jmp 0xcc06
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x2100
jmp 0xcc10
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
callq 0x2100
jmp 0xcc1a
movq %rax, %rbx
leaq 0x260(%rsp), %rdi
callq 0xdbb0
jmp 0xcc1a
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x9afc
movq %rbx, %rdi
callq 0x2390