// File: 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
movq %rsp, %rbp
subq $0x4a0, %rsp            # imm = 0x4A0
movq %rdx, -0x3b0(%rbp)
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x3a8(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x1fde3
movq $0x0, -0x28(%rbp)
movq -0x18(%rbp), %rax
movq -0x28(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x2075e
movq -0x18(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x1fe0d
movq $0x1, -0x30(%rbp)
movq -0x18(%rbp), %rax
movq -0x30(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x2075e
movq -0x18(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x1fe37
movq $0x0, -0x38(%rbp)
movq -0x18(%rbp), %rax
movq -0x38(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x2075e
movq -0x18(%rbp), %rax
cmpl $0x3, (%rax)
jne 0x1fffe
movq -0x18(%rbp), %rsi
addq $0x88, %rsi
leaq -0x58(%rbp), %rdi
movq %rdi, -0x3c0(%rbp)
callq 0x3130
movq -0x3b0(%rbp), %rdi
movq -0x3c0(%rbp), %rsi
callq 0x194e0
movb %al, -0x3b1(%rbp)
jmp 0x1fe7a
leaq -0x58(%rbp), %rdi
callq 0x31c0
movb -0x3b1(%rbp), %al
testb $0x1, %al
jne 0x1fe92
jmp 0x1ff2e
movq -0x18(%rbp), %rsi
addq $0x88, %rsi
leaq -0x88(%rbp), %rdi
movq %rdi, -0x3d0(%rbp)
callq 0x3130
movq -0x3b0(%rbp), %rdi
movq -0x3d0(%rbp), %rsi
callq 0x20800
movq %rax, -0x3c8(%rbp)
jmp 0x1fecc
movq -0x3c8(%rbp), %rcx
movq -0x18(%rbp), %rax
movq (%rcx), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x31c0
jmp 0x2075e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x31c0
jmp 0x2076b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x31c0
jmp 0x2076b
movq -0x18(%rbp), %rdx
addq $0x88, %rdx
leaq 0x892e(%rip), %rsi      # 0x2886e
leaq -0xc8(%rbp), %rdi
movq %rdi, -0x3d8(%rbp)
callq 0xeda0
movq -0x3d8(%rbp), %rsi
leaq 0x89f5(%rip), %rdx      # 0x28956
leaq -0xa8(%rbp), %rdi
callq 0x7160
jmp 0x1ff6f
movq -0x3a8(%rbp), %rdi
movq -0x18(%rbp), %rdx
leaq -0xa8(%rbp), %rsi
callq 0x20780
jmp 0x1ff88
leaq -0xa8(%rbp), %rdi
callq 0x31c0
leaq -0xc8(%rbp), %rdi
callq 0x31c0
movq $0x0, -0xd0(%rbp)
movq -0x18(%rbp), %rax
movq -0xd0(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x2075e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x1ffed
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x31c0
leaq -0xc8(%rbp), %rdi
callq 0x31c0
jmp 0x2076b
movq -0x18(%rbp), %rax
cmpl $0x4, (%rax)
jne 0x200b6
movq -0x3b0(%rbp), %rsi
leaq -0x8(%rbp), %rax
movq %rax, -0x3f8(%rbp)
movq -0x18(%rbp), %rax
movq 0xa8(%rax), %rax
movq %rax, -0x3f0(%rbp)
leaq -0x118(%rbp), %rdi
movq %rdi, -0x3e8(%rbp)
callq 0x1fd20
movq -0x3a8(%rbp), %rdi
movq -0x3f0(%rbp), %rsi
movq -0x3e8(%rbp), %rdx
callq 0x1fd90
movq %rax, -0x3e0(%rbp)
jmp 0x20065
movq -0x3f8(%rbp), %rax
movq -0x3e0(%rbp), %rcx
movq %rcx, -0xd8(%rbp)
movq -0xd8(%rbp), %rcx
subq $0x1, %rcx
movq %rcx, (%rax)
leaq -0x118(%rbp), %rdi
callq 0x19c10
jmp 0x2075e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x118(%rbp), %rdi
callq 0x19c10
jmp 0x2076b
movq -0x18(%rbp), %rax
cmpl $0x5, (%rax)
jne 0x2021f
movq -0x18(%rbp), %rsi
addq $0xb8, %rsi
leaq -0x150(%rbp), %rdi
movq %rdi, -0x400(%rbp)
callq 0x21240
movq -0x400(%rbp), %rsi
leaq -0x170(%rbp), %rdi
callq 0x3130
jmp 0x200f6
movq -0x3b0(%rbp), %rdi
leaq -0x170(%rbp), %rsi
callq 0x194e0
movb %al, -0x401(%rbp)
jmp 0x20111
leaq -0x170(%rbp), %rdi
callq 0x31c0
movb -0x401(%rbp), %al
testb $0x1, %al
jne 0x2012c
jmp 0x201d1
leaq -0x190(%rbp), %rdi
leaq -0x150(%rbp), %rsi
callq 0x3130
jmp 0x20141
movq -0x3b0(%rbp), %rdi
leaq -0x190(%rbp), %rsi
callq 0x20800
movq %rax, -0x410(%rbp)
jmp 0x2015d
movq -0x410(%rbp), %rcx
movq -0x18(%rbp), %rax
movq (%rcx), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
leaq -0x190(%rbp), %rdi
callq 0x31c0
movl $0x1, -0x194(%rbp)
jmp 0x201fd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x2020e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x170(%rbp), %rdi
callq 0x31c0
jmp 0x2020e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x190(%rbp), %rdi
callq 0x31c0
jmp 0x2020e
movq $0x0, -0x1a0(%rbp)
movq -0x18(%rbp), %rax
movq -0x1a0(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0x194(%rbp)
leaq -0x150(%rbp), %rdi
callq 0x16c50
jmp 0x2075e
leaq -0x150(%rbp), %rdi
callq 0x16c50
jmp 0x2076b
movq -0x18(%rbp), %rax
cmpl $0x6, (%rax)
jne 0x204f4
movq -0x18(%rbp), %rax
movq 0xf0(%rax), %rcx
movq %rcx, -0x1b8(%rbp)
movq 0xf8(%rax), %rcx
movq %rcx, -0x1b0(%rbp)
movq 0x100(%rax), %rax
movq %rax, -0x1a8(%rbp)
cmpl $0x0, -0x1a8(%rbp)
je 0x2028b
cmpl $0x1, -0x1a8(%rbp)
je 0x2028b
cmpl $0x2, -0x1a8(%rbp)
je 0x2028b
cmpl $0x3, -0x1a8(%rbp)
je 0x2028b
cmpl $0x4, -0x1a8(%rbp)
jne 0x203c8
movq -0x3b0(%rbp), %rsi
movq -0x1b8(%rbp), %rax
movq %rax, -0x428(%rbp)
leaq -0x200(%rbp), %rdi
movq %rdi, -0x420(%rbp)
callq 0x1fd20
movq -0x3a8(%rbp), %rdi
movq -0x428(%rbp), %rsi
movq -0x420(%rbp), %rdx
callq 0x1fd90
movq %rax, -0x418(%rbp)
jmp 0x202d6
movq -0x418(%rbp), %rax
movq %rax, -0x1c0(%rbp)
leaq -0x200(%rbp), %rdi
callq 0x19c10
movq -0x3b0(%rbp), %rsi
movq -0x1b0(%rbp), %rax
movq %rax, -0x440(%rbp)
leaq -0x248(%rbp), %rdi
movq %rdi, -0x438(%rbp)
callq 0x1fd20
movq -0x3a8(%rbp), %rdi
movq -0x440(%rbp), %rsi
movq -0x438(%rbp), %rdx
callq 0x1fd90
movq %rax, -0x430(%rbp)
jmp 0x2033b
movq -0x430(%rbp), %rax
movq %rax, -0x208(%rbp)
leaq -0x248(%rbp), %rdi
callq 0x19c10
leaq -0x1c0(%rbp), %rdi
leaq -0x208(%rbp), %rsi
callq 0x21ae0
movq (%rax), %rax
movq %rax, -0x250(%rbp)
movq -0x18(%rbp), %rax
movq -0x250(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x2075e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x200(%rbp), %rdi
callq 0x19c10
jmp 0x2076b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x248(%rbp), %rdi
callq 0x19c10
jmp 0x2076b
cmpl $0x5, -0x1a8(%rbp)
je 0x2042f
cmpl $0x6, -0x1a8(%rbp)
je 0x2042f
cmpl $0x7, -0x1a8(%rbp)
je 0x2042f
cmpl $0x8, -0x1a8(%rbp)
je 0x2042f
cmpl $0x9, -0x1a8(%rbp)
je 0x2042f
cmpl $0xa, -0x1a8(%rbp)
je 0x2042f
cmpl $0x16, -0x1a8(%rbp)
je 0x2042f
cmpl $0x17, -0x1a8(%rbp)
je 0x2042f
cmpl $0x18, -0x1a8(%rbp)
je 0x2042f
cmpl $0x1b, -0x1a8(%rbp)
je 0x2042f
cmpl $0x1c, -0x1a8(%rbp)
jne 0x204cd
movq -0x3b0(%rbp), %rsi
movq -0x1b8(%rbp), %rax
movq %rax, -0x458(%rbp)
leaq -0x298(%rbp), %rdi
movq %rdi, -0x450(%rbp)
callq 0x1fd20
movq -0x3a8(%rbp), %rdi
movq -0x458(%rbp), %rsi
movq -0x450(%rbp), %rdx
callq 0x1fd90
movq %rax, -0x448(%rbp)
jmp 0x2047a
movq -0x448(%rbp), %rax
movq %rax, -0x258(%rbp)
movq -0x18(%rbp), %rax
movq -0x258(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
leaq -0x298(%rbp), %rdi
callq 0x19c10
jmp 0x2075e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x298(%rbp), %rdi
callq 0x19c10
jmp 0x2076b
movq $0x0, -0x2a0(%rbp)
movq -0x18(%rbp), %rax
movq -0x2a0(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x2075e
movq -0x18(%rbp), %rax
movq 0x108(%rax), %rcx
movq %rcx, -0x2b0(%rbp)
movq 0x110(%rax), %rax
movq %rax, -0x2a8(%rbp)
cmpl $0x0, -0x2a8(%rbp)
jne 0x205d1
movq -0x3b0(%rbp), %rsi
movq -0x2b0(%rbp), %rax
movq %rax, -0x470(%rbp)
leaq -0x2f8(%rbp), %rdi
movq %rdi, -0x468(%rbp)
callq 0x1fd20
movq -0x3a8(%rbp), %rdi
movq -0x470(%rbp), %rsi
movq -0x468(%rbp), %rdx
callq 0x1fd90
movq %rax, -0x460(%rbp)
jmp 0x2056c
movq -0x460(%rbp), %rax
movq %rax, -0x2b8(%rbp)
leaq -0x2f8(%rbp), %rdi
callq 0x19c10
movq -0x2b8(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x300(%rbp)
movq -0x18(%rbp), %rax
movq -0x300(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x2075e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x2f8(%rbp), %rdi
callq 0x19c10
jmp 0x2076b
cmpl $0x1, -0x2a8(%rbp)
je 0x205e7
cmpl $0x2, -0x2a8(%rbp)
jne 0x20685
movq -0x3b0(%rbp), %rsi
movq -0x2b0(%rbp), %rax
movq %rax, -0x488(%rbp)
leaq -0x348(%rbp), %rdi
movq %rdi, -0x480(%rbp)
callq 0x1fd20
movq -0x3a8(%rbp), %rdi
movq -0x488(%rbp), %rsi
movq -0x480(%rbp), %rdx
callq 0x1fd90
movq %rax, -0x478(%rbp)
jmp 0x20632
movq -0x478(%rbp), %rax
movq %rax, -0x308(%rbp)
movq -0x18(%rbp), %rax
movq -0x308(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
leaq -0x348(%rbp), %rdi
callq 0x19c10
jmp 0x2075e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x348(%rbp), %rdi
callq 0x19c10
jmp 0x2076b
cmpl $0x3, -0x2a8(%rbp)
jne 0x2073c
movq -0x3b0(%rbp), %rsi
movq -0x2b0(%rbp), %rax
movq %rax, -0x4a0(%rbp)
leaq -0x390(%rbp), %rdi
movq %rdi, -0x498(%rbp)
callq 0x1fd20
movq -0x3a8(%rbp), %rdi
movq -0x4a0(%rbp), %rsi
movq -0x498(%rbp), %rdx
callq 0x1fd90
movq %rax, -0x490(%rbp)
jmp 0x206dd
movq -0x490(%rbp), %rax
movq %rax, -0x350(%rbp)
leaq -0x390(%rbp), %rdi
callq 0x19c10
movq -0x350(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x398(%rbp)
movq -0x18(%rbp), %rax
movq -0x398(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x2075e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x390(%rbp), %rdi
callq 0x19c10
jmp 0x2076b
movq $0x0, -0x3a0(%rbp)
movq -0x18(%rbp), %rax
movq -0x3a0(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x4a0, %rsp            # imm = 0x4A0
popq %rbp
retq
movq -0x60(%rbp), %rdi
callq 0x34c0
nopw %cs:(%rax,%rax)
nop