// File: /workspace/github_c_makefile_star2_O0/Yamsman[P]scc/src/ast.c
// Function: astn_type
s_type *astn_type(ast_n *node) {
	if (node == NULL) return NULL;
	if (node->kind != EXPR) return NULL;
	switch (node->dat.expr.kind) {
		//Expressions that always result in an integer
		case EXPR_LOGIC_OR:
		case EXPR_LOGIC_AND:
		case EXPR_OR:	
		case EXPR_XOR:	
		case EXPR_AND:	
		case EXPR_GTH:	
		case EXPR_LTH:	
		case EXPR_GEQ:	
		case EXPR_LEQ:	
		case EXPR_LSHIFT:
		case EXPR_RSHIFT:
		case EXPR_EQ:	
		case EXPR_NEQ:	
		case EXPR_MOD:	
		case EXPR_NOT:	
		case EXPR_LOGIC_NOT:
			return type_new(TYPE_INT);

		//Binary operations
		case EXPR_ADD:	
		case EXPR_SUB:	
		case EXPR_MUL:	
		case EXPR_DIV: {
			//Get types of LHS and RHS
			s_type *lhs = astn_type(node->dat.expr.left);
			s_type *rhs = astn_type(node->dat.expr.right);

			/*
			 * Valid cases:
			 * int/int (int)
			 * int/ptr ptr/int (ptr)
			 * int/float float/int float/float (float)
			 */
			s_type *type = NULL;
			if (lhs->kind == TYPE_FLOAT || rhs->kind == TYPE_FLOAT) {
				if (lhs->kind != TYPE_PTR && rhs->kind != TYPE_PTR)
					type = type_new(TYPE_FLOAT);
			}
			if (lhs->kind == TYPE_INT || rhs->kind == TYPE_INT) {
				if (lhs->kind == TYPE_PTR) {
					type = type_clone(lhs);
				} else if (rhs->kind == TYPE_PTR) {
					type = type_clone(rhs);
				} else {
					type = type_new(TYPE_INT);
				}
			}

			type_del(lhs);
			type_del(rhs);
			return type;
			}

		//Unary operations
		case EXPR_POS:	
		case EXPR_NEG:
		case EXPR_INC_PRE:
		case EXPR_DEC_PRE:
		case EXPR_INC_POST:
		case EXPR_DEC_POST:
			return astn_type(node->dat.expr.left);

		//Cast operation resulting in the casted type
		case EXPR_CAST:
			return type_clone(node->dat.expr.type);

		//Conditional
		case EXPR_COND:
			//Move to the result and fall through
			node = node->dat.expr.right;
		case EXPR_COND_RES: {
			s_type *lhs = astn_type(node->dat.expr.left);
			s_type *rhs = astn_type(node->dat.expr.right);
			
			//Ensure the two possible types are compatible
			s_type *type = NULL;
			if (lhs->kind == rhs->kind)
				type = type_clone(lhs);

			type_del(lhs);
			type_del(rhs);
			return type;
			}

		//Referencing
		case EXPR_REF: {
			//Add a new reference to the front of the pointer chain
			s_type *type = astn_type(node->dat.expr.left);
			s_type *r_type = type_new(TYPE_PTR);
			r_type->ref = type;
			return r_type;
		}

		//Dereferencing 
		case EXPR_DEREF:
		case EXPR_ARRAY: {
			//Follow the type chain
			s_type *type = astn_type(node->dat.expr.left);
			s_type *d_type = NULL;
			if (type != NULL) d_type = type->ref;
			type->ref = NULL;
			type_del(type);
			return d_type;
			}

		//Struct/union member access
		case EXPR_PTR_MEMB:
		case EXPR_MEMB:	{
			s_type *st_type = astn_type(node->dat.expr.left);
			s_type *m_type = NULL;
			if (node->dat.expr.kind == EXPR_PTR_MEMB)
				st_type = st_type->ref;

			//Find matching parameter
			for (int i=0; i<st_type->param.len; i++) {
				s_param *param = (s_param*)st_type->param.table[i];
				if (!strcmp(param->name, node->dat.expr.sym->name))
					m_type = type_clone(param->type);
			}

			type_del(st_type);
			return m_type;
			}

		//Return type
		case EXPR_CALL:	
			return type_clone(node->dat.expr.left->dat.expr.sym->type->ret);

		//Variable
		case EXPR_IDENT:
			return type_clone(node->dat.expr.sym->type);

		//Literals
		case EXPR_CONST:
		case EXPR_STR:
			return type_clone(node->tok.dtype);
	}
	return NULL;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
jne 0x3523
movq $0x0, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
cmpl $0x1, (%rax)
je 0x3539
movq $0x0, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
movl 0x8(%rax), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x88(%rbp)
subl $0x25, %eax
ja 0x385d
movq -0x88(%rbp), %rax
leaq 0xdaa2(%rip), %rcx      # 0x11004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x6, %edi
callq 0xf720
movq %rax, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x3500
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x3500
movq %rax, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x7, (%rax)
je 0x35ba
movq -0x20(%rbp), %rax
cmpl $0x7, (%rax)
jne 0x35dc
movq -0x18(%rbp), %rax
cmpl $0x3, (%rax)
je 0x35da
movq -0x20(%rbp), %rax
cmpl $0x3, (%rax)
je 0x35da
movl $0x7, %edi
callq 0xf720
movq %rax, -0x28(%rbp)
jmp 0x35dc
movq -0x18(%rbp), %rax
cmpl $0x6, (%rax)
je 0x35ee
movq -0x20(%rbp), %rax
cmpl $0x6, (%rax)
jne 0x3630
movq -0x18(%rbp), %rax
cmpl $0x3, (%rax)
jne 0x3606
movq -0x18(%rbp), %rdi
callq 0xfdc0
movq %rax, -0x28(%rbp)
jmp 0x362e
movq -0x20(%rbp), %rax
cmpl $0x3, (%rax)
jne 0x361e
movq -0x20(%rbp), %rdi
callq 0xfdc0
movq %rax, -0x28(%rbp)
jmp 0x362c
movl $0x6, %edi
callq 0xf720
movq %rax, -0x28(%rbp)
jmp 0x362e
jmp 0x3630
movq -0x18(%rbp), %rdi
callq 0xfca0
movq -0x20(%rbp), %rdi
callq 0xfca0
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x3500
movq %rax, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0xfdc0
movq %rax, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x3500
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x3500
movq %rax, -0x38(%rbp)
movq $0x0, -0x40(%rbp)
movq -0x30(%rbp), %rax
movl (%rax), %eax
movq -0x38(%rbp), %rcx
cmpl (%rcx), %eax
jne 0x36cc
movq -0x30(%rbp), %rdi
callq 0xfdc0
movq %rax, -0x40(%rbp)
movq -0x30(%rbp), %rdi
callq 0xfca0
movq -0x38(%rbp), %rdi
callq 0xfca0
movq -0x40(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x3500
movq %rax, -0x48(%rbp)
movl $0x3, %edi
callq 0xf720
movq %rax, -0x50(%rbp)
movq -0x48(%rbp), %rcx
movq -0x50(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x50(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x3500
movq %rax, -0x58(%rbp)
movq $0x0, -0x60(%rbp)
cmpq $0x0, -0x58(%rbp)
je 0x374f
movq -0x58(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x60(%rbp)
movq -0x58(%rbp), %rax
movq $0x0, 0x18(%rax)
movq -0x58(%rbp), %rdi
callq 0xfca0
movq -0x60(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x3500
movq %rax, -0x68(%rbp)
movq $0x0, -0x70(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x21, 0x8(%rax)
jne 0x37a0
movq -0x68(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x68(%rbp)
movl $0x0, -0x74(%rbp)
movl -0x74(%rbp), %eax
movq -0x68(%rbp), %rcx
cmpl 0x30(%rcx), %eax
jge 0x3801
movq -0x68(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x74(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
movq (%rax), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq (%rax), %rsi
callq 0x3120
cmpl $0x0, %eax
jne 0x37f4
movq -0x80(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xfdc0
movq %rax, -0x70(%rbp)
jmp 0x37f6
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x37a7
movq -0x68(%rbp), %rdi
callq 0xfca0
movq -0x70(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq 0x18(%rax), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rdi
callq 0xfdc0
movq %rax, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x8(%rax), %rdi
callq 0xfdc0
movq %rax, -0x8(%rbp)
jmp 0x3865
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0xfdc0
movq %rax, -0x8(%rbp)
jmp 0x3865
movq $0x0, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)