// File: /workspace/github_cpp_makefile_star2_O3/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 $0x2a8, %rsp            # imm = 0x2A8
movq %rdx, %r14
movq %rsi, %rbx
movq %rdi, %r15
movl (%rsi), %eax
cmpq $0x6, %rax
ja 0x13bb3
leaq 0x5769(%rip), %rcx      # 0x191d8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq $0x0, 0x8(%rbx)
xorl %r14d, %r14d
jmp 0x13f88
movq 0xa8(%rbx), %rbx
movq (%r14), %rax
leaq 0x270(%rsp), %r12
movq %rax, -0x8(%r12)
leaq 0x8(%r14), %rsi
movq %r12, %rdi
callq 0x147b2
movups 0x20(%r14), %xmm0
movups 0x30(%r14), %xmm1
movups %xmm1, 0x28(%r12)
movups %xmm0, 0x18(%r12)
leaq 0x268(%rsp), %rdx
movq %r15, %rdi
movq %rbx, %rsi
callq 0x13a42
movq %rax, %r14
decq %r14
movq %r12, %rdi
jmp 0x13e38
movq $0x1, 0x8(%rbx)
movl $0x1, %r14d
jmp 0x13f88
leaq 0xd8(%rsp), %r13
movq %r13, -0x10(%r13)
movq 0x88(%rbx), %rsi
movq 0x90(%rbx), %rdx
addq %rsi, %rdx
leaq 0xc8(%rsp), %r12
movq %r12, %rdi
callq 0x179ce
movq %r14, %rdi
movq %r12, %rsi
callq 0xfef4
movl %eax, %ebp
movq 0xc8(%rsp), %rdi
cmpq %r13, %rdi
je 0x13b4c
movq 0xd8(%rsp), %rsi
incq %rsi
callq 0x3280
testb %bpl, %bpl
je 0x13e42
leaq 0xb8(%rsp), %r12
movq %r12, -0x10(%r12)
movq 0x88(%rbx), %rsi
movq 0x90(%rbx), %rdx
addq %rsi, %rdx
leaq 0xa8(%rsp), %r15
movq %r15, %rdi
callq 0x179ce
movq %r14, %rdi
movq %r15, %rsi
callq 0x14186
movq (%rax), %r14
movq %r14, 0x8(%rbx)
movq 0xa8(%rsp), %rdi
cmpq %r12, %rdi
je 0x13f88
movq 0xb8(%rsp), %rsi
jmp 0x13ecc
movq 0x108(%rbx), %r12
movl 0x110(%rbx), %eax
testl %eax, %eax
je 0x13ed9
cmpl $0x2, %eax
ja 0x13f2b
movq (%r14), %rax
leaq 0x130(%rsp), %r13
movq %rax, -0x8(%r13)
leaq 0x8(%r14), %rsi
movq %r13, %rdi
callq 0x147b2
movups 0x20(%r14), %xmm0
movups 0x30(%r14), %xmm1
movups %xmm1, 0x28(%r13)
movups %xmm0, 0x18(%r13)
leaq 0x128(%rsp), %rdx
movq %r15, %rdi
movq %r12, %rsi
callq 0x13a42
jmp 0x13e2e
leaq 0x10(%rsp), %r15
movq %r15, -0x10(%r15)
movq 0xb8(%rbx), %rsi
movq 0xc0(%rbx), %rdx
addq %rsi, %rdx
movq %rsp, %rdi
callq 0x179ce
leaq 0x20(%rsp), %rdi
leaq 0xd8(%rbx), %rsi
callq 0xf82a
leaq 0x98(%rsp), %r12
movq %r12, -0x10(%r12)
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
addq %rsi, %rdx
leaq 0x88(%rsp), %rdi
callq 0x179ce
leaq 0x88(%rsp), %rsi
movq %r14, %rdi
callq 0xfef4
movl %eax, %ebp
movq 0x88(%rsp), %rdi
cmpq %r12, %rdi
je 0x13ca0
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x3280
testb %bpl, %bpl
je 0x13e98
leaq 0x78(%rsp), %r12
movq %r12, -0x10(%r12)
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
addq %rsi, %rdx
leaq 0x68(%rsp), %rdi
callq 0x179ce
leaq 0x68(%rsp), %rsi
movq %r14, %rdi
callq 0x14186
movq (%rax), %r14
movq %r14, 0x8(%rbx)
movq 0x68(%rsp), %rdi
cmpq %r12, %rdi
je 0x13ea3
movq 0x78(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x13ea3
movq 0xf0(%rbx), %r12
movl 0x100(%rbx), %eax
cmpl $0x4, %eax
ja 0x13dd5
movq 0xf8(%rbx), %rax
movq %rax, 0x40(%rsp)
movq (%r14), %rax
leaq 0x230(%rsp), %r13
movq %rax, -0x8(%r13)
leaq 0x8(%r14), %rbp
movq %r13, %rdi
movq %rbp, %rsi
callq 0x147b2
movups 0x20(%r14), %xmm0
movups 0x30(%r14), %xmm1
movups %xmm1, 0x28(%r13)
movups %xmm0, 0x18(%r13)
leaq 0x228(%rsp), %rdx
movq %r15, %rdi
movq %r12, %rsi
callq 0x13a42
movq %rax, 0x38(%rsp)
leaq 0x20(%r14), %r12
movq %r13, %rdi
callq 0x1553e
movq (%r14), %rax
leaq 0x1f0(%rsp), %r13
movq %rax, -0x8(%r13)
movq %r13, %rdi
movq %rbp, %rsi
callq 0x147b2
movups (%r12), %xmm0
movups 0x10(%r12), %xmm1
movups %xmm1, 0x28(%r13)
movups %xmm0, 0x18(%r13)
leaq 0x1e8(%rsp), %rdx
movq %r15, %rdi
movq 0x40(%rsp), %rsi
callq 0x13a42
movq %rax, %r14
movq %r13, %rdi
callq 0x1553e
movq 0x38(%rsp), %rax
cmpq %r14, %rax
cmovgq %rax, %r14
jmp 0x13f84
cmpl $0x1c, %eax
ja 0x13a78
movl $0x19c007e0, %ecx       # imm = 0x19C007E0
btl %eax, %ecx
jae 0x13a78
movq (%r14), %rax
leaq 0x1b0(%rsp), %r13
movq %rax, -0x8(%r13)
leaq 0x8(%r14), %rsi
movq %r13, %rdi
callq 0x147b2
movups 0x20(%r14), %xmm0
movups 0x30(%r14), %xmm1
movups %xmm1, 0x28(%r13)
movups %xmm0, 0x18(%r13)
leaq 0x1a8(%rsp), %rdx
movq %r15, %rdi
movq %r12, %rsi
callq 0x13a42
movq %rax, %r14
movq %rax, 0x8(%rbx)
movq %r13, %rdi
callq 0x1553e
jmp 0x13f88
leaq 0x88(%rbx), %rdx
leaq 0x5cc4(%rip), %rsi      # 0x19b14
movq %rsp, %r14
movq %r14, %rdi
callq 0xa256
leaq 0x5d3b(%rip), %rsi      # 0x19b9d
movq %r14, %rdi
callq 0x33f0
leaq 0x58(%rsp), %r14
movq %r14, -0x10(%r14)
movq (%rax), %rdx
movq %rax, %rcx
addq $0x10, %rcx
cmpq %rcx, %rdx
je 0x13f9d
movq %rdx, 0x48(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x58(%rsp)
jmp 0x13fa4
movq $0x0, 0x8(%rbx)
xorl %r14d, %r14d
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
je 0x13eba
movq 0x30(%rsp), %rsi
subq %rdi, %rsi
callq 0x3280
movq (%rsp), %rdi
cmpq %r15, %rdi
je 0x13f88
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x13f88
movq (%r14), %rax
leaq 0x170(%rsp), %r13
movq %rax, -0x8(%r13)
leaq 0x8(%r14), %rsi
movq %r13, %rdi
callq 0x147b2
movups 0x20(%r14), %xmm0
movups 0x30(%r14), %xmm1
movups %xmm1, 0x28(%r13)
movups %xmm0, 0x18(%r13)
leaq 0x168(%rsp), %rdx
movq %r15, %rdi
movq %r12, %rsi
callq 0x13a42
movq %rax, %r14
movq %r13, %rdi
callq 0x1553e
decq %r14
jmp 0x13f84
cmpl $0x3, %eax
jne 0x13a78
movq (%r14), %rax
leaq 0xf0(%rsp), %r13
movq %rax, -0x8(%r13)
leaq 0x8(%r14), %rsi
movq %r13, %rdi
callq 0x147b2
movups 0x20(%r14), %xmm0
movups 0x30(%r14), %xmm1
movups %xmm1, 0x28(%r13)
movups %xmm0, 0x18(%r13)
leaq 0xe8(%rsp), %rdx
movq %r15, %rdi
movq %r12, %rsi
callq 0x13a42
movq %rax, %r14
movq %r13, %rdi
callq 0x1553e
incq %r14
movq %r14, 0x8(%rbx)
movq %r14, %rax
addq $0x2a8, %rsp            # imm = 0x2A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movups (%rcx), %xmm0
movups %xmm0, (%r14)
movq 0x8(%rax), %rdx
leaq 0x48(%rsp), %rsi
movq %rdx, 0x8(%rsi)
movq %rcx, (%rax)
movq $0x0, 0x8(%rax)
movb $0x0, 0x10(%rax)
movq %r15, %rdi
movq %rbx, %rdx
callq 0x140f8
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x13fe2
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x3280
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x13a78
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x13a78
jmp 0x14078
jmp 0x14078
jmp 0x14078
jmp 0x14078
movq %rax, %rbx
movq 0x68(%rsp), %rdi
cmpq %r12, %rdi
je 0x140e7
movq 0x78(%rsp), %rsi
jmp 0x14098
movq %rax, %rbx
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x14047
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x14047
jmp 0x14078
movq %rax, %rbx
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
jne 0x140ae
jmp 0x140ef
movq %rax, %rbx
movq 0xa8(%rsp), %rdi
cmpq %r12, %rdi
je 0x140ef
movq 0xb8(%rsp), %rsi
jmp 0x140cd
movq %rax, %rbx
movq %r13, %rdi
jmp 0x140dd
movq %rax, %rbx
movq 0x88(%rsp), %rdi
cmpq %r12, %rdi
je 0x140e7
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x140e7
movq %rax, %rbx
movq (%rsp), %rdi
cmpq %r15, %rdi
je 0x140ef
movq 0x10(%rsp), %rsi
jmp 0x140cd
movq %rax, %rbx
movq 0xc8(%rsp), %rdi
cmpq %r13, %rdi
je 0x140ef
movq 0xd8(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x140ef
movq %rax, %rbx
movq %r12, %rdi
callq 0x1553e
jmp 0x140ef
movq %rax, %rbx
movq %rsp, %rdi
callq 0xfa02
movq %rbx, %rdi
callq 0x33b0
nop