// File: /workspace/github_c_makefile_star2_O3/Encryptr[P]O-plus-plus/opp/analysis/analysis.c
// Function: opp_analize_time_eval
static struct Opp_Node* opp_analize_time_eval(struct Opp_Analize* ctx, struct Opp_Node* expr)
{
	#define CLEAR_NODE(node, lhs) { \
		temp.line = node->debug.line;\
		temp.colum = node->debug.colum; \
		memset(node, 0, sizeof(struct Opp_Node)); \
		node->type = EUNARY; \
		node->debug = temp; \
		if (lhs->unary_expr.type == TSTR || lhs->unary_expr.type == TINTEGER) \
			node->unary_expr.type = TINTEGER; \
		else \
			node->unary_expr.type = TFLOAT; \
	}

	#define NUM_OP(op) { \
		if (lhs->unary_expr.type == TINTEGER || lhs->unary_expr.type == TSTR) { \
			if (rhs->unary_expr.type == TFLOAT) \
				expr->unary_expr.val.i64val = lhs->unary_expr.val.i64val op (int64_t)rhs->unary_expr.val.f64val; \
			else \
				expr->unary_expr.val.i64val = lhs->unary_expr.val.i64val op rhs->unary_expr.val.i64val; \
		} \
		else { \
			if (rhs->unary_expr.type == TINTEGER) \
				expr->unary_expr.val.f64val = lhs->unary_expr.val.f64val op (double)rhs->unary_expr.val.i64val; \
			else \
				expr->unary_expr.val.f64val = lhs->unary_expr.val.f64val op rhs->unary_expr.val.f64val; \
		} \
	}

	#define CMP_OP(op) { \
		if (lhs->unary_expr.type == TINTEGER || lhs->unary_expr.type == TSTR) { \
			if (rhs->unary_expr.type == TFLOAT) \
				expr->unary_expr.val.i64val = lhs->unary_expr.val.i64val op (int64_t)rhs->unary_expr.val.f64val; \
			else \
				expr->unary_expr.val.i64val = lhs->unary_expr.val.i64val op rhs->unary_expr.val.i64val; \
		} \
		else { \
			if (rhs->unary_expr.type == TINTEGER) \
				expr->unary_expr.val.i64val = lhs->unary_expr.val.f64val op (double)rhs->unary_expr.val.i64val; \
			else \
				expr->unary_expr.val.i64val = lhs->unary_expr.val.f64val op rhs->unary_expr.val.f64val; \
		} \
	}

	struct Opp_Node* lhs = NULL;
	struct Opp_Node* rhs = NULL;
	struct Opp_Debug temp;

	switch (expr->type)
	{
		case EUNARY: {
			if (expr->unary_expr.type == TIDENT)
				return NULL;
			return expr;
		}

		case EBIN: {
			// TODO: add x * 0 and x* 1 optimizations
			lhs = opp_analize_time_eval(ctx, expr->bin_expr.left);
			rhs = opp_analize_time_eval(ctx, expr->bin_expr.right);
			
			if (lhs == NULL || rhs == NULL) return NULL;

			const int op = expr->bin_expr.tok;
			CLEAR_NODE(expr, lhs);


			switch (op)
			{
				case TADD: NUM_OP(+=); break;
				case TMIN: NUM_OP(-=); break;
				case TMUL: NUM_OP(*=); break;
				case TDIV: NUM_OP(/=); break;
				case TMOD: 
					if (lhs->unary_expr.type != TINTEGER && lhs->unary_expr.type != TSTR)
						opp_semantics_error(ctx, expr, "Mod operation can only be preformed on integers");
					lhs->unary_expr.val.i64val %= rhs->unary_expr.val.i64val;
					break;

				default: break;
			}

			return expr;
		}

		case ELOGIC: {
			lhs = opp_analize_time_eval(ctx, expr->logic_expr.left);
			rhs = opp_analize_time_eval(ctx, expr->logic_expr.right);
			
			if (lhs == NULL || rhs == NULL) return NULL;

			const int op = expr->logic_expr.tok;
			CLEAR_NODE(expr, lhs);
			expr->unary_expr.type = TINTEGER;

			switch (op)
			{
				case TEQEQ:  CMP_OP(==); break;
				case TNOTEQ: CMP_OP(!=); break;
				case TLT:    CMP_OP(<);  break;
				case TLE:    CMP_OP(<=); break;
				case TGT:    CMP_OP(>);  break;
				case TGE:    CMP_OP(>=); break;
				case TOR:    CMP_OP(||); break;
				case TAND:   CMP_OP(&&); break;
				default: break;
			}

			return expr;
		}

		case ESUB: {
			lhs = opp_analize_time_eval(ctx, expr->sub_expr.unary);
			
			if (lhs == NULL) return NULL;
			
			CLEAR_NODE(expr, lhs);
			if (lhs->unary_expr.type == TSTR)
				opp_semantics_error(ctx, expr, "Attempting to negate str '%s'",
					lhs->unary_expr.val.strval);

			if (lhs->unary_expr.type == TINTEGER)
				expr->unary_expr.val.i64val = -lhs->unary_expr.val.i64val;
			else
				expr->unary_expr.val.f64val = -lhs->unary_expr.val.f64val;

			return expr;
		}

		// TODO: Add sizeof here

		default: break;
	}
	return NULL;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movl (%rsi), %ecx
xorl %eax, %eax
decl %ecx
cmpl $0x5, %ecx
ja 0x3543
movq %rsi, %rbx
movq %rdi, %r15
leaq 0x862a(%rip), %rdx      # 0xb4d8
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movq 0x20(%rbx), %rsi
movq %r15, %rdi
callq 0x2e8d
movq %rax, %r14
movq 0x18(%rbx), %rsi
movq %r15, %rdi
callq 0x2e8d
movq %rax, %rcx
testq %r14, %r14
sete %al
testq %rcx, %rcx
sete %dl
orb %al, %dl
jne 0x30b1
movl 0x8(%rbx), %edx
movl 0x10(%rbx), %eax
xorpd %xmm0, %xmm0
movupd %xmm0, 0x8(%rbx)
movupd %xmm0, 0x18(%rbx)
movupd %xmm0, 0x28(%rbx)
movupd %xmm0, 0x38(%rbx)
movl $0x5, (%rbx)
movl %edx, 0x8(%rbx)
movl 0x10(%r14), %edx
cmpl $0x5, %edx
sete %sil
cmpl $0x2, %edx
sete %dl
orb %sil, %dl
movzbl %dl, %edx
xorl $0x3, %edx
movl %edx, 0x10(%rbx)
addl $-0x13, %eax
cmpl $0x4, %eax
ja 0x3540
leaq 0x85d0(%rip), %rdx      # 0xb510
movslq (%rdx,%rax,4), %rax
addq %rdx, %rax
jmpq *%rax
movl 0x10(%r14), %eax
cmpl $0x5, %eax
je 0x2f5b
cmpl $0x2, %eax
jne 0x3343
cmpl $0x3, 0x10(%rcx)
jne 0x32ed
cvttsd2si 0x18(%rcx), %rax
addq 0x18(%r14), %rax
jmp 0x32ff
xorl %eax, %eax
cmpl $0x1, 0x10(%rbx)
cmovneq %rbx, %rax
jmp 0x3543
movq 0x20(%rbx), %rsi
movq %r15, %rdi
callq 0x2e8d
movq %rax, %r14
movq 0x18(%rbx), %rsi
movq %r15, %rdi
callq 0x2e8d
testq %r14, %r14
sete %cl
testq %rax, %rax
sete %dl
orb %cl, %dl
jne 0x30b1
movl 0x8(%rbx), %edx
movl 0x10(%rbx), %ecx
xorpd %xmm0, %xmm0
movupd %xmm0, 0x8(%rbx)
movupd %xmm0, 0x18(%rbx)
movupd %xmm0, 0x28(%rbx)
movupd %xmm0, 0x38(%rbx)
movl $0x5, (%rbx)
movl %edx, 0x8(%rbx)
movl $0x2, 0x10(%rbx)
addl $-0x7, %ecx
cmpl $0x7, %ecx
ja 0x3540
leaq 0x84fd(%rip), %rdx      # 0xb4f0
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x300e
cmpl $0x2, %ecx
jne 0x3466
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rdx
movl $0x1, %ecx
jne 0x33b4
testq %rdx, %rdx
jne 0x30be
cvttsd2si 0x18(%rax), %rax
xorl %ecx, %ecx
testq %rax, %rax
jmp 0x34ba
movq 0x10(%rbx), %rsi
movq %r15, %rdi
callq 0x2e8d
testq %rax, %rax
je 0x30b1
movl 0x8(%rbx), %ecx
xorpd %xmm0, %xmm0
movupd %xmm0, 0x8(%rbx)
movupd %xmm0, 0x18(%rbx)
movupd %xmm0, 0x28(%rbx)
movupd %xmm0, 0x38(%rbx)
movl $0x5, (%rbx)
movl %ecx, 0x8(%rbx)
movl 0x10(%rax), %ecx
cmpl $0x5, %ecx
sete %dl
cmpl $0x2, %ecx
sete %cl
orb %dl, %cl
movzbl %cl, %ecx
xorl $0x3, %ecx
movl %ecx, 0x10(%rbx)
movl 0x10(%rax), %ecx
cmpl $0x2, %ecx
je 0x30b8
cmpl $0x5, %ecx
je 0x35e7
movsd 0x18(%rax), %xmm0
xorpd 0x84d9(%rip), %xmm0     # 0xb580
movlpd %xmm0, 0x18(%rbx)
jmp 0x3540
xorl %eax, %eax
jmp 0x3543
xorl %ecx, %ecx
subq 0x18(%rax), %rcx
movq %rcx, 0x18(%rbx)
jmp 0x3540
movl 0x10(%r14), %eax
cmpl $0x2, %eax
je 0x30d9
cmpl $0x5, %eax
jne 0x35ff
movq 0x18(%r14), %rax
cqto
idivq 0x18(%rcx)
movq %rdx, 0x18(%r14)
jmp 0x3540
movl 0x10(%r14), %eax
cmpl $0x5, %eax
je 0x30fe
cmpl $0x2, %eax
jne 0x330c
cmpl $0x3, 0x10(%rcx)
jne 0x32d6
cvttsd2si 0x18(%rcx), %rcx
movq 0x18(%r14), %rax
cqto
idivq %rcx
jmp 0x32ff
movl 0x10(%r14), %eax
cmpl $0x5, %eax
je 0x312e
cmpl $0x2, %eax
jne 0x332b
cmpl $0x3, 0x10(%rcx)
jne 0x32e2
cvttsd2si 0x18(%rcx), %rax
imulq 0x18(%r14), %rax
jmp 0x32ff
movl 0x10(%r14), %eax
cmpl $0x5, %eax
je 0x315a
cmpl $0x2, %eax
jne 0x335b
cmpl $0x3, 0x10(%rcx)
jne 0x32f7
cvttsd2si 0x18(%rcx), %rax
movq 0x18(%r14), %rcx
subq %rax, %rcx
movq %rcx, 0x18(%r14)
jmp 0x30be
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x318c
cmpl $0x2, %ecx
jne 0x33d2
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x3388
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x338e
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x31bc
cmpl $0x2, %ecx
jne 0x340a
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x3393
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x3399
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x31ec
cmpl $0x2, %ecx
jne 0x342b
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x339e
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x33a4
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x321c
cmpl $0x2, %ecx
jne 0x3446
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x33a9
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x33af
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x324c
cmpl $0x2, %ecx
jne 0x3493
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x33c2
testq %rcx, %rcx
je 0x35be
cvttsd2si 0x18(%rax), %rcx
xorl %eax, %eax
testq %rcx, %rcx
setne %al
jmp 0x3303
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x3288
cmpl $0x2, %ecx
jne 0x34c2
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x33ed
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x33f3
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x32b8
cmpl $0x2, %ecx
jne 0x34e3
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x33f8
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x33fe
movq 0x18(%r14), %rax
cqto
idivq 0x18(%rcx)
jmp 0x32ff
movq 0x18(%r14), %rax
imulq 0x18(%rcx), %rax
jmp 0x32ff
movq 0x18(%r14), %rax
addq 0x18(%rcx), %rax
jmp 0x32ff
movq 0x18(%r14), %rax
subq 0x18(%rcx), %rax
movq %rax, 0x18(%r14)
movq %rax, 0x18(%rbx)
jmp 0x3540
cmpl $0x2, 0x10(%rcx)
jne 0x3503
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%rcx), %xmm0
movsd 0x18(%r14), %xmm1
divsd %xmm0, %xmm1
jmp 0x3378
cmpl $0x2, 0x10(%rcx)
jne 0x3510
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%rcx), %xmm0
jmp 0x3515
cmpl $0x2, 0x10(%rcx)
jne 0x351d
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%rcx), %xmm0
jmp 0x3522
cmpl $0x2, 0x10(%rcx)
jne 0x352a
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%rcx), %xmm0
movsd 0x18(%r14), %xmm1
subsd %xmm0, %xmm1
movsd %xmm1, 0x18(%r14)
movsd %xmm1, 0x18(%rbx)
jmp 0x3540
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
setl %dl
jmp 0x3401
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
setg %dl
jmp 0x3401
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
setle %dl
jmp 0x3401
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
setne %dl
jmp 0x3401
testq %rdx, %rdx
jne 0x30be
jmp 0x348f
testq %rcx, %rcx
jne 0x348f
xorl %ecx, %ecx
jmp 0x30be
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x3549
cvtsi2sdq 0x18(%rax), %xmm1
jmp 0x354e
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
setge %dl
jmp 0x3401
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
sete %dl
movq %rdx, 0x18(%rbx)
jmp 0x3540
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x355c
cvtsi2sdq 0x18(%rax), %xmm1
xorl %eax, %eax
ucomisd %xmm1, %xmm0
jmp 0x3554
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x356b
cvtsi2sdq 0x18(%rax), %xmm1
jmp 0x3570
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x357e
cvtsi2sdq 0x18(%rax), %xmm1
cmpneqsd %xmm1, %xmm0
jmp 0x35da
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
movl $0x1, %ecx
xorpd %xmm1, %xmm1
jne 0x3586
ucomisd %xmm1, %xmm0
jne 0x30be
jp 0x30be
xorl %ecx, %ecx
jmp 0x34b5
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
xorpd %xmm1, %xmm1
jne 0x35a9
xorl %ecx, %ecx
ucomisd %xmm1, %xmm0
jne 0x34b5
jnp 0x30be
cmpq $0x0, 0x18(%rax)
setne %cl
jmp 0x30be
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x35c5
cvtsi2sdq 0x18(%rax), %xmm1
xorl %eax, %eax
ucomisd %xmm1, %xmm0
jmp 0x3576
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x35d4
cvtsi2sdq 0x18(%rax), %xmm1
cmpeqsd %xmm1, %xmm0
jmp 0x35da
movsd 0x18(%r14), %xmm0
divsd 0x18(%rcx), %xmm0
jmp 0x3535
movsd 0x18(%rcx), %xmm0
mulsd 0x18(%r14), %xmm0
jmp 0x3535
movsd 0x18(%rcx), %xmm0
addsd 0x18(%r14), %xmm0
jmp 0x3535
movsd 0x18(%r14), %xmm0
subsd 0x18(%rcx), %xmm0
movsd %xmm0, 0x18(%r14)
movsd %xmm0, 0x18(%rbx)
movq %rbx, %rax
popq %rbx
popq %r14
popq %r15
retq
movsd 0x18(%rax), %xmm1
xorl %eax, %eax
ucomisd %xmm0, %xmm1
seta %al
jmp 0x3303
xorl %ecx, %ecx
ucomisd 0x18(%rax), %xmm0
seta %cl
jmp 0x30be
movsd 0x18(%rax), %xmm1
xorl %eax, %eax
ucomisd %xmm0, %xmm1
setae %al
jmp 0x3303
cmpneqsd 0x18(%rax), %xmm0
jmp 0x35da
ucomisd %xmm1, %xmm0
jne 0x30be
jp 0x30be
cmpneqsd 0x18(%rax), %xmm1
movq %xmm1, %rcx
andl $0x1, %ecx
jmp 0x30be
ucomisd %xmm1, %xmm0
jne 0x35b1
jnp 0x35be
cmpneqsd 0x18(%rax), %xmm1
movq %xmm1, %rax
jmp 0x35df
xorl %eax, %eax
jmp 0x3303
xorl %ecx, %ecx
ucomisd 0x18(%rax), %xmm0
setae %cl
jmp 0x30be
cmpeqsd 0x18(%rax), %xmm0
movq %xmm0, %rax
andl $0x1, %eax
jmp 0x3303
movq 0x18(%rax), %rcx
leaq 0x83f7(%rip), %rdx      # 0xb9e9
movq %r15, %rdi
movq %rbx, %rsi
xorl %eax, %eax
callq 0x2286
leaq 0x83b3(%rip), %rdx      # 0xb9b9
movq %r15, %rdi
movq %rbx, %rsi
xorl %eax, %eax
callq 0x2286