// File: /workspace/github_c_makefile_star2_O3/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, 0x40(%rsp)
movq %rsi, %r14
movq %rdi, 0x38(%rsp)
leaq 0x8(%rsp), %rdi
movl $0x10, %esi
callq 0xc88c
leaq 0x28(%rsp), %rdi
movl $0x10, %esi
callq 0xc88c
leaq 0x10a41(%rip), %rax     # 0x14474
movl (%rax), %eax
movl %eax, 0x24(%rsp)
movl 0x8(%r14), %eax
testl %eax, %eax
jle 0x3cad
leaq 0x28(%rsp), %rbx
leaq 0x98c9(%rip), %r13      # 0xd31a
xorl %ebp, %ebp
movq %r14, (%rsp)
movq %rbx, %r15
movq (%r14), %rcx
movslq %ebp, %rdx
movq (%rcx,%rdx,8), %r14
leaq 0x8(%r14), %r12
movl (%r14), %ebx
cmpl $0x31, %ebx
jle 0x3a9d
cmpl $0x32, %ebx
je 0x3af9
cmpl $0x33, %ebx
je 0x3b33
cmpl $0x35, %ebx
jne 0x3b63
movq %r15, %rbx
movq %r15, %rdi
xorl %esi, %esi
callq 0xc922
jmp 0x3c07
cmpl $0x7, %ebx
je 0x3b4f
cmpl $0x8, %ebx
jne 0x3b63
leaq 0x8(%rsp), %r14
movq %r14, %rdi
callq 0xc9fc
cmpq $0x7, %rax
movq %r15, %rbx
movq %r14, %r15
movq (%rsp), %r14
je 0x3c2f
cmpl $0x0, 0x10(%rsp)
je 0x3c1e
movq %r15, %rdi
movq %rbx, %rsi
callq 0x3966
movq %r15, %rdi
callq 0xc9fc
cmpq $0x7, %rax
jne 0x3ad0
jmp 0x3c2f
incl %ebp
cmpl %eax, %ebp
jge 0x3bd5
movslq %ebp, %rax
movq (%rcx,%rax,8), %rax
cmpl $0x35, (%rax)
jne 0x3bd5
movq 0x38(%rsp), %rax
movq 0x60(%rax), %rdi
movq 0x20(%r14), %rsi
callq 0xc187
xorl %esi, %esi
testq %rax, %rax
setne %sil
jmp 0x3be5
movq 0x28(%r14), %rax
cmpl $0x7, (%rax)
jne 0x3be1
movq %r12, %rdi
leaq 0x975a(%rip), %rsi      # 0xd2a4
jmp 0x3bfd
movl $0x7, %esi
leaq 0x8(%rsp), %rdi
callq 0xc9d2
jmp 0x3c04
movq %r12, 0x18(%rsp)
movl %ebx, %edi
callq 0x385c
testl %eax, %eax
js 0x3bf2
movl %eax, %r12d
cmpl $0x0, 0x30(%rsp)
je 0x3c39
cmpl $0x2, %ebx
jne 0x3c43
movslq 0x10(%rsp), %rax
testq %rax, %rax
movq 0x18(%rsp), %r12
movq %r15, %rbx
movq (%rsp), %r14
movl $0x1, %edi
jle 0x3bc2
xorl %ecx, %ecx
movq 0x8(%rsp), %rdx
xorl %esi, %esi
cmpq $0xf, (%rdx,%rcx,8)
cmovel %edi, %esi
incq %rcx
cmpq %rcx, %rax
jne 0x3bae
testl %esi, %esi
jne 0x3c0b
movq %r12, %rdi
leaq 0x97a4(%rip), %rsi      # 0xd370
xorl %eax, %eax
callq 0x3250
jmp 0x3c0b
movq %r12, %rdi
leaq 0x96f2(%rip), %rsi      # 0xd2d1
jmp 0x3bfd
movq 0x20(%r14), %rsi
movq %r15, %rbx
movq %r15, %rdi
callq 0xc9d2
jmp 0x3c07
movq 0x18(%rsp), %r12
movq %r12, %rdi
movq %r13, %rsi
xorl %eax, %eax
callq 0x3250
movq %r15, %rbx
movq (%rsp), %r14
incl %ebp
movl 0x8(%r14), %eax
cmpl %eax, %ebp
jl 0x3a57
jmp 0x3cb0
movq %r12, %rdi
leaq 0x96ce(%rip), %rsi      # 0xd2f6
xorl %eax, %eax
callq 0x3250
movq %r15, %rdi
callq 0xc9d7
jmp 0x3c0b
cmpl $0x18, %ebx
je 0x3c43
cmpl $0x21, %ebx
jne 0x3c99
cmpl $0x0, 0x10(%rsp)
jle 0x3c82
movq %r15, %rbx
leaq 0x8(%rsp), %r13
movq %r13, %rdi
callq 0xc9fc
movl %eax, %edi
callq 0x385c
cmpl %eax, %r12d
jge 0x3c78
movq %r13, %rdi
movq %rbx, %rsi
callq 0x3966
cmpl $0x0, 0x10(%rsp)
jg 0x3c52
movl (%r14), %ebx
leaq 0x9698(%rip), %r13      # 0xd31a
movslq %ebx, %rsi
leaq 0x8(%rsp), %rdi
callq 0xc9d2
movq 0x18(%rsp), %r12
jmp 0x3c04
movq 0x18(%rsp), %r12
movq %r12, %rdi
leaq 0x969c(%rip), %rsi      # 0xd344
jmp 0x3bfd
xorl %r12d, %r12d
cmpl $0x0, 0x10(%rsp)
jle 0x3ced
leaq 0x8(%rsp), %rbx
leaq 0x28(%rsp), %r15
cmpl $0x0, 0x30(%rsp)
jle 0x3cdc
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3966
cmpl $0x0, 0x10(%rsp)
jg 0x3cc1
jmp 0x3ced
leaq 0x96bb(%rip), %rsi      # 0xd39e
movq %r12, %rdi
xorl %eax, %eax
callq 0x3250
cmpl $0x2, 0x30(%rsp)
jl 0x3d05
leaq 0x96cf(%rip), %rsi      # 0xd3ca
movq %r12, %rdi
xorl %eax, %eax
callq 0x3250
leaq 0x28(%rsp), %rbx
movq %rbx, %rdi
callq 0xc9fc
movq %rax, %r14
cmpl $0x0, 0x24(%rsp)
sete %al
leaq 0x10750(%rip), %rcx     # 0x14474
cmpl $0x0, (%rcx)
setne %cl
andb %al, %cl
movzbl %cl, %eax
movq 0x40(%rsp), %rcx
movl %eax, (%rcx)
leaq 0x8(%rsp), %rdi
callq 0xc8d9
movq %rbx, %rdi
callq 0xc8d9
movl %r14d, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq