// File: /workspace/github_cpp_makefile_star2_O1/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 0x1415d
leaq 0x518f(%rip), %rcx      # 0x191a8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq $0x0, 0x8(%rbx)
xorl %r14d, %r14d
jmp 0x14532
movq 0xa8(%rbx), %rbx
movq (%r14), %rax
leaq 0x270(%rsp), %r12
movq %rax, -0x8(%r12)
leaq 0x8(%r14), %rsi
movq %r12, %rdi
callq 0x14d6e
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 0x13fec
movq %rax, %r14
decq %r14
movq %r12, %rdi
jmp 0x143e2
movq $0x1, 0x8(%rbx)
movl $0x1, %r14d
jmp 0x14532
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 0x17a38
movq %r14, %rdi
movq %r12, %rsi
callq 0x1041e
movl %eax, %ebp
movq 0xc8(%rsp), %rdi
cmpq %r13, %rdi
je 0x140f6
movq 0xd8(%rsp), %rsi
incq %rsi
callq 0x3280
testb %bpl, %bpl
je 0x143ec
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 0x17a38
movq %r14, %rdi
movq %r15, %rsi
callq 0x14730
movq (%rax), %r14
movq %r14, 0x8(%rbx)
movq 0xa8(%rsp), %rdi
cmpq %r12, %rdi
je 0x14532
movq 0xb8(%rsp), %rsi
jmp 0x14476
movq 0x108(%rbx), %r12
movl 0x110(%rbx), %eax
testl %eax, %eax
je 0x14483
cmpl $0x2, %eax
ja 0x144d5
movq (%r14), %rax
leaq 0x130(%rsp), %r13
movq %rax, -0x8(%r13)
leaq 0x8(%r14), %rsi
movq %r13, %rdi
callq 0x14d6e
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 0x13fec
jmp 0x143d8
leaq 0x10(%rsp), %r15
movq %r15, -0x10(%r15)
movq 0xb8(%rbx), %rsi
movq 0xc0(%rbx), %rdx
addq %rsi, %rdx
movq %rsp, %rdi
callq 0x17a38
leaq 0x20(%rsp), %rdi
leaq 0xd8(%rbx), %rsi
callq 0xfd62
leaq 0x98(%rsp), %r12
movq %r12, -0x10(%r12)
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
addq %rsi, %rdx
leaq 0x88(%rsp), %rdi
callq 0x17a38
leaq 0x88(%rsp), %rsi
movq %r14, %rdi
callq 0x1041e
movl %eax, %ebp
movq 0x88(%rsp), %rdi
cmpq %r12, %rdi
je 0x1424a
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x3280
testb %bpl, %bpl
je 0x14442
leaq 0x78(%rsp), %r12
movq %r12, -0x10(%r12)
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
addq %rsi, %rdx
leaq 0x68(%rsp), %rdi
callq 0x17a38
leaq 0x68(%rsp), %rsi
movq %r14, %rdi
callq 0x14730
movq (%rax), %r14
movq %r14, 0x8(%rbx)
movq 0x68(%rsp), %rdi
cmpq %r12, %rdi
je 0x1444d
movq 0x78(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x1444d
movq 0xf0(%rbx), %r12
movl 0x100(%rbx), %eax
cmpl $0x4, %eax
ja 0x1437f
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 0x14d6e
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 0x13fec
movq %rax, 0x38(%rsp)
leaq 0x20(%r14), %r12
movq %r13, %rdi
callq 0x15538
movq (%r14), %rax
leaq 0x1f0(%rsp), %r13
movq %rax, -0x8(%r13)
movq %r13, %rdi
movq %rbp, %rsi
callq 0x14d6e
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 0x13fec
movq %rax, %r14
movq %r13, %rdi
callq 0x15538
movq 0x38(%rsp), %rax
cmpq %r14, %rax
cmovgq %rax, %r14
jmp 0x1452e
cmpl $0x1c, %eax
ja 0x14022
movl $0x19c007e0, %ecx       # imm = 0x19C007E0
btl %eax, %ecx
jae 0x14022
movq (%r14), %rax
leaq 0x1b0(%rsp), %r13
movq %rax, -0x8(%r13)
leaq 0x8(%r14), %rsi
movq %r13, %rdi
callq 0x14d6e
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 0x13fec
movq %rax, %r14
movq %rax, 0x8(%rbx)
movq %r13, %rdi
callq 0x15538
jmp 0x14532
leaq 0x88(%rbx), %rdx
leaq 0x56ea(%rip), %rsi      # 0x19ae4
movq %rsp, %r14
movq %r14, %rdi
callq 0xa33e
leaq 0x5761(%rip), %rsi      # 0x19b6d
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 0x14547
movq %rdx, 0x48(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x58(%rsp)
jmp 0x1454e
movq $0x0, 0x8(%rbx)
xorl %r14d, %r14d
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
je 0x14464
movq 0x30(%rsp), %rsi
subq %rdi, %rsi
callq 0x3280
movq (%rsp), %rdi
cmpq %r15, %rdi
je 0x14532
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x14532
movq (%r14), %rax
leaq 0x170(%rsp), %r13
movq %rax, -0x8(%r13)
leaq 0x8(%r14), %rsi
movq %r13, %rdi
callq 0x14d6e
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 0x13fec
movq %rax, %r14
movq %r13, %rdi
callq 0x15538
decq %r14
jmp 0x1452e
cmpl $0x3, %eax
jne 0x14022
movq (%r14), %rax
leaq 0xf0(%rsp), %r13
movq %rax, -0x8(%r13)
leaq 0x8(%r14), %rsi
movq %r13, %rdi
callq 0x14d6e
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 0x13fec
movq %rax, %r14
movq %r13, %rdi
callq 0x15538
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 0x146a2
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x1458c
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x3280
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x14022
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x14022
jmp 0x14622
jmp 0x14622
jmp 0x14622
jmp 0x14622
movq %rax, %rbx
movq 0x68(%rsp), %rdi
cmpq %r12, %rdi
je 0x14691
movq 0x78(%rsp), %rsi
jmp 0x14642
movq %rax, %rbx
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x145f1
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x145f1
jmp 0x14622
movq %rax, %rbx
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
jne 0x14658
jmp 0x14699
movq %rax, %rbx
movq 0xa8(%rsp), %rdi
cmpq %r12, %rdi
je 0x14699
movq 0xb8(%rsp), %rsi
jmp 0x14677
movq %rax, %rbx
movq %r13, %rdi
jmp 0x14687
movq %rax, %rbx
movq 0x88(%rsp), %rdi
cmpq %r12, %rdi
je 0x14691
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x14691
movq %rax, %rbx
movq (%rsp), %rdi
cmpq %r15, %rdi
je 0x14699
movq 0x10(%rsp), %rsi
jmp 0x14677
movq %rax, %rbx
movq 0xc8(%rsp), %rdi
cmpq %r13, %rdi
je 0x14699
movq 0xd8(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x14699
movq %rax, %rbx
movq %r12, %rdi
callq 0x15538
jmp 0x14699
movq %rax, %rbx
movq %rsp, %rdi
callq 0xff3a
movq %rbx, %rdi
callq 0x33b0
nop