// File: /workspace/github_c_makefile_star2_O2/Yamsman[P]scc/src/eval.c
// Function: eval_constexpr
int eval_constexpr(lexer *lx, vector *input, int *err) {
	//Initialize stacks
	vector ops, vals;
	vector_init(&ops, VECTOR_DEFAULT);
	vector_init(&vals, VECTOR_DEFAULT);

	//Process input token by token
	int i = 0;
	int eflag_prev = c_errflag;
	s_pos *last_loc = NULL;
	for (; i<input->len; i++) {
		token *t = input->table[i];
		last_loc = &t->loc;
		if (t->type == TOK_CONST) {
			//Ensure the constant is an integer
			if (t->dtype->kind == TYPE_FLOAT) {
				c_error(&t->loc, "Floating point value in constant expression\n");
				continue;
			}

			//Push the operand
			vector_push(&vals, (void*)t->dat.ival);
		} else if (t->type == TOK_DEFINED) {
			//Move to the next token and check for an identifier
			token *ident = input->table[++i];
			if (i >= input->len || ident->type != TOK_IDENT) {
				c_error(&t->loc, "Expected identifier after 'defined'\n");
				continue;
			}

			//Search the symbol table to check if the identifier is defined
			long long res = (symtable_search(lx->stb, t->dat.sval) != NULL);
			vector_push(&vals, (void*)res);
		} else if (t->type == TOK_IDENT) {
			vector_add(&vals, (void*)0);
		} else if (t->type == TOK_LPR) {
			//Push a left parentheses
			vector_push(&ops, (void*)(long long)t->type);
		} else if (t->type == TOK_RPR) {
			//Perform calculations until a right parentheses is reached
			while ((long long)vector_top(&ops) != TOK_LPR) {
				if (ops.len == 0) {
					c_error(&t->loc, "Missing '(' in constant expression\n");
					break;
				}
				do_calc(&ops, &vals);
			}
			vector_pop(&ops);
		} else {
			//Check if the operator is valid
			int op = t->type;
			int prec = rankof(t->type);
			if (prec < 0) {
				c_error(&t->loc, "Invalid operation in constant expression\n");
				continue;
			}

			//Error for no LHS
			if (vals.len == 0 && !is_unary(t->type)) {
				c_error(&t->loc, "Operator in constant expression has no LHS\n");
				continue;
			}

			//Handle special case for ternary operator
			if (t->type == TOK_COL) {
				int has_qmk = 0;
				for (int j=0; j<ops.len; j++)
					if ((long long)(ops.table[j]) == TOK_QMK) has_qmk = 1;
				if (!has_qmk)
					c_error(&t->loc, "Missing '?' before ':' in "
							"constant expresion\n");
				continue;
			}

			//Repeat until the current operation's precedence is less than
			//the precedence of the operator at the top of the stack
			for (;;) {
				if (ops.len < 1) break;
				int top_prec = rankof((long long)vector_top(&ops));
				if (prec >= top_prec) break;
				do_calc(&ops, &vals);
			}
			vector_push(&ops, (void*)(long long)t->type);
		}
	}

	//Finish calculations if the condition has ended
	while (ops.len > 0) {
		if (vals.len < 1) {
			c_error(last_loc, "Operator in constant expression has no RHS\n");
			break;
		}
		do_calc(&ops, &vals);
	}
	if (vals.len > 1) {
		c_error(last_loc, "Missing operator in constant expression\n");
	}

	//Get result
	int res = (long long)vector_top(&vals);
	*err = !eflag_prev && c_errflag;
	vector_close(&ops);
	vector_close(&vals);

	return res;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdx, 0x38(%rsp)
movq %rsi, %r15
movq %rdi, 0x40(%rsp)
leaq 0x20(%rsp), %r13
pushq $0x10
popq %rbx
movq %r13, %rdi
movl %ebx, %esi
callq 0xbe8a
leaq 0x10(%rsp), %rdi
movl %ebx, %esi
callq 0xbe8a
leaq 0xfb0e(%rip), %rax      # 0x13474
movl (%rax), %eax
movl %eax, 0x34(%rsp)
xorl %ebx, %ebx
xorl %r14d, %r14d
movl 0x8(%r15), %ecx
cmpl %ecx, %r14d
jge 0x3b76
movq (%r15), %rax
movslq %r14d, %rdx
movq (%rax,%rdx,8), %rbp
leaq 0x8(%rbp), %rbx
movl (%rbp), %r12d
cmpl $0x7, %r12d
je 0x3a9b
cmpl $0x35, %r12d
je 0x39e2
cmpl $0x32, %r12d
je 0x3a0f
cmpl $0x33, %r12d
je 0x39f3
cmpl $0x8, %r12d
jne 0x3a44
movq %r13, %rdi
callq 0xbfae
cmpq $0x7, %rax
je 0x3ad3
cmpl $0x0, 0x28(%rsp)
je 0x3ac2
movq %r13, %rdi
leaq 0x10(%rsp), %rsi
callq 0x38af
jmp 0x39b6
leaq 0x10(%rsp), %rdi
xorl %esi, %esi
callq 0xbf10
jmp 0x3b49
movq 0x28(%rbp), %rax
cmpl $0x7, (%rax)
jne 0x3aaf
movq %rbx, %rdi
leaq 0x889a(%rip), %rsi      # 0xc2a4
jmp 0x3aec
incl %r14d
cmpl %ecx, %r14d
jge 0x3aa3
movslq %r14d, %rcx
movq (%rax,%rcx,8), %rax
cmpl $0x35, (%rax)
jne 0x3aa3
movq 0x40(%rsp), %rax
movq 0x60(%rax), %rdi
movq 0x20(%rbp), %rsi
callq 0xb822
xorl %esi, %esi
testq %rax, %rax
setne %sil
jmp 0x3ab3
movq %rbx, 0x8(%rsp)
movl %r12d, %edi
callq 0x37ac
testl %eax, %eax
js 0x3add
movl %eax, %ebx
cmpl $0x0, 0x18(%rsp)
je 0x3af5
cmpl $0x2, %r12d
jne 0x3b01
movl 0x28(%rsp), %eax
movq 0x20(%rsp), %rcx
xorl %edx, %edx
testl %eax, %eax
cmovlel %edx, %eax
xorl %esi, %esi
pushq $0x1
popq %rdi
cmpq %rdx, %rax
je 0x3b40
cmpq $0xf, (%rcx,%rdx,8)
cmovel %edi, %esi
incq %rdx
jmp 0x3a85
movq %r13, %rdi
pushq $0x7
popq %rsi
jmp 0x3ab8
movq %rbx, %rdi
leaq 0x8824(%rip), %rsi      # 0xc2d1
jmp 0x3aec
movq 0x20(%rbp), %rsi
leaq 0x10(%rsp), %rdi
callq 0xbf86
jmp 0x3b49
movq %rbx, %rdi
leaq 0x882a(%rip), %rsi      # 0xc2f6
xorl %eax, %eax
callq 0x35e4
movq %r13, %rdi
callq 0xbf8b
jmp 0x3b49
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
leaq 0x882e(%rip), %rsi      # 0xc31a
xorl %eax, %eax
callq 0x35e4
jmp 0x3b49
cmpl $0x18, %r12d
je 0x3b01
cmpl $0x21, %r12d
jne 0x3b51
cmpl $0x0, 0x28(%rsp)
jle 0x3b33
movq %r13, %rdi
callq 0xbfae
movl %eax, %edi
callq 0x37ac
cmpl %eax, %ebx
jge 0x3b2f
movq %r13, %rdi
leaq 0x10(%rsp), %rsi
callq 0x38af
cmpl $0x0, 0x28(%rsp)
jg 0x3b08
movl (%rbp), %r12d
movslq %r12d, %rsi
movq %r13, %rdi
callq 0xbf86
jmp 0x3b44
testl %esi, %esi
je 0x3b62
movq 0x8(%rsp), %rbx
incl %r14d
jmp 0x3971
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
leaq 0x87e4(%rip), %rsi      # 0xc344
jmp 0x3aec
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
leaq 0x87ff(%rip), %rsi      # 0xc370
jmp 0x3aec
movq %rbx, %r14
leaq 0x20(%rsp), %rbx
leaq 0x10(%rsp), %r15
cmpl $0x0, 0x28(%rsp)
jle 0x3baf
cmpl $0x0, 0x18(%rsp)
jle 0x3b9e
movq %rbx, %rdi
movq %r15, %rsi
callq 0x38af
jmp 0x3b83
leaq 0x87f9(%rip), %rsi      # 0xc39e
movq %r14, %rdi
xorl %eax, %eax
callq 0x35e4
cmpl $0x2, 0x18(%rsp)
jl 0x3bc7
leaq 0x880d(%rip), %rsi      # 0xc3ca
movq %r14, %rdi
xorl %eax, %eax
callq 0x35e4
leaq 0x10(%rsp), %rbx
movq %rbx, %rdi
callq 0xbfae
movq %rax, %r14
cmpl $0x0, 0x34(%rsp)
sete %al
leaq 0xf88e(%rip), %rcx      # 0x13474
cmpl $0x0, (%rcx)
setne %cl
andb %al, %cl
movzbl %cl, %eax
movq 0x38(%rsp), %rcx
movl %eax, (%rcx)
leaq 0x20(%rsp), %rdi
callq 0xbecc
movq %rbx, %rdi
callq 0xbecc
movl %r14d, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq