// File: /workspace/github_c_makefile_star2_O1/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 0x35b9
movq %rsi, %rbx
movq %rdi, %r15
leaq 0x85d2(%rip), %rdx      # 0xb4e0
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movq 0x20(%rbx), %rsi
movq %r15, %rdi
callq 0x2eed
movq %rax, %r14
movq 0x18(%rbx), %rsi
movq %r15, %rdi
callq 0x2eed
movq %rax, %rcx
testq %r14, %r14
sete %al
testq %rcx, %rcx
sete %dl
orb %al, %dl
jne 0x311f
movl 0x10(%rbx), %eax
movq 0x4(%rbx), %rdx
xorpd %xmm0, %xmm0
movupd %xmm0, (%rbx)
movupd %xmm0, 0x20(%rbx)
movupd %xmm0, 0x30(%rbx)
movupd %xmm0, 0x10(%rbx)
movq $0x0, 0x40(%rbx)
movl $0x5, (%rbx)
movq %rdx, 0x4(%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 0x35b6
leaq 0x856f(%rip), %rdx      # 0xb518
movslq (%rdx,%rax,4), %rax
addq %rdx, %rax
jmpq *%rax
movl 0x10(%r14), %eax
cmpl $0x5, %eax
je 0x2fc4
cmpl $0x2, %eax
jne 0x33b9
cmpl $0x3, 0x10(%rcx)
jne 0x3363
cvttsd2si 0x18(%rcx), %rax
addq 0x18(%r14), %rax
jmp 0x3375
xorl %eax, %eax
cmpl $0x1, 0x10(%rbx)
cmovneq %rbx, %rax
jmp 0x35b9
movq 0x20(%rbx), %rsi
movq %r15, %rdi
callq 0x2eed
movq %rax, %r14
movq 0x18(%rbx), %rsi
movq %r15, %rdi
callq 0x2eed
testq %r14, %r14
sete %cl
testq %rax, %rax
sete %dl
orb %cl, %dl
jne 0x311f
movl 0x10(%rbx), %ecx
movq 0x4(%rbx), %rdx
xorpd %xmm0, %xmm0
movupd %xmm0, (%rbx)
movupd %xmm0, 0x10(%rbx)
movupd %xmm0, 0x20(%rbx)
movupd %xmm0, 0x30(%rbx)
movq $0x0, 0x40(%rbx)
movl $0x5, (%rbx)
movq %rdx, 0x4(%rbx)
movl $0x2, 0x10(%rbx)
addl $-0x7, %ecx
cmpl $0x7, %ecx
ja 0x35b6
leaq 0x8493(%rip), %rdx      # 0xb4f8
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x3080
cmpl $0x2, %ecx
jne 0x34dc
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rdx
movl $0x1, %ecx
jne 0x342a
testq %rdx, %rdx
jne 0x3116
cvttsd2si 0x18(%rax), %rax
xorl %ecx, %ecx
testq %rax, %rax
jmp 0x3530
movq 0x10(%rbx), %rsi
movq %r15, %rdi
callq 0x2eed
testq %rax, %rax
je 0x311f
movq 0x4(%rbx), %rcx
xorpd %xmm0, %xmm0
movupd %xmm0, (%rbx)
movupd %xmm0, 0x10(%rbx)
movupd %xmm0, 0x20(%rbx)
movupd %xmm0, 0x30(%rbx)
movq $0x0, 0x40(%rbx)
movl $0x5, (%rbx)
movq %rcx, 0x4(%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)
cmpl $0x5, 0x10(%rax)
je 0x365d
cmpl $0x2, 0x10(%rax)
jne 0x3126
xorl %ecx, %ecx
subq 0x18(%rax), %rcx
movq %rcx, 0x18(%rbx)
jmp 0x35b6
xorl %eax, %eax
jmp 0x35b9
movsd 0x18(%rax), %xmm0
xorpd 0x844d(%rip), %xmm0     # 0xb580
movlpd %xmm0, 0x18(%rbx)
jmp 0x35b6
movl 0x10(%r14), %eax
cmpl $0x2, %eax
je 0x314f
cmpl $0x5, %eax
jne 0x3675
movq 0x18(%r14), %rax
cqto
idivq 0x18(%rcx)
movq %rdx, 0x18(%r14)
jmp 0x35b6
movl 0x10(%r14), %eax
cmpl $0x5, %eax
je 0x3174
cmpl $0x2, %eax
jne 0x3382
cmpl $0x3, 0x10(%rcx)
jne 0x334c
cvttsd2si 0x18(%rcx), %rcx
movq 0x18(%r14), %rax
cqto
idivq %rcx
jmp 0x3375
movl 0x10(%r14), %eax
cmpl $0x5, %eax
je 0x31a4
cmpl $0x2, %eax
jne 0x33a1
cmpl $0x3, 0x10(%rcx)
jne 0x3358
cvttsd2si 0x18(%rcx), %rax
imulq 0x18(%r14), %rax
jmp 0x3375
movl 0x10(%r14), %eax
cmpl $0x5, %eax
je 0x31d0
cmpl $0x2, %eax
jne 0x33d1
cmpl $0x3, 0x10(%rcx)
jne 0x336d
cvttsd2si 0x18(%rcx), %rax
movq 0x18(%r14), %rcx
subq %rax, %rcx
movq %rcx, 0x18(%r14)
jmp 0x3116
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x3202
cmpl $0x2, %ecx
jne 0x3448
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x33fe
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x3404
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x3232
cmpl $0x2, %ecx
jne 0x3480
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x3409
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x340f
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x3262
cmpl $0x2, %ecx
jne 0x34a1
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x3414
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x341a
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x3292
cmpl $0x2, %ecx
jne 0x34bc
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x341f
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x3425
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x32c2
cmpl $0x2, %ecx
jne 0x3509
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x3438
testq %rcx, %rcx
je 0x3634
cvttsd2si 0x18(%rax), %rcx
xorl %eax, %eax
testq %rcx, %rcx
setne %al
jmp 0x3379
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x32fe
cmpl $0x2, %ecx
jne 0x3538
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x3463
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x3469
movl 0x10(%r14), %ecx
cmpl $0x5, %ecx
je 0x332e
cmpl $0x2, %ecx
jne 0x3559
cmpl $0x3, 0x10(%rax)
movq 0x18(%r14), %rcx
jne 0x346e
cvttsd2si 0x18(%rax), %rax
xorl %edx, %edx
cmpq %rax, %rcx
jmp 0x3474
movq 0x18(%r14), %rax
cqto
idivq 0x18(%rcx)
jmp 0x3375
movq 0x18(%r14), %rax
imulq 0x18(%rcx), %rax
jmp 0x3375
movq 0x18(%r14), %rax
addq 0x18(%rcx), %rax
jmp 0x3375
movq 0x18(%r14), %rax
subq 0x18(%rcx), %rax
movq %rax, 0x18(%r14)
movq %rax, 0x18(%rbx)
jmp 0x35b6
cmpl $0x2, 0x10(%rcx)
jne 0x3579
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%rcx), %xmm0
movsd 0x18(%r14), %xmm1
divsd %xmm0, %xmm1
jmp 0x33ee
cmpl $0x2, 0x10(%rcx)
jne 0x3586
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%rcx), %xmm0
jmp 0x358b
cmpl $0x2, 0x10(%rcx)
jne 0x3593
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%rcx), %xmm0
jmp 0x3598
cmpl $0x2, 0x10(%rcx)
jne 0x35a0
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%rcx), %xmm0
movsd 0x18(%r14), %xmm1
subsd %xmm0, %xmm1
movsd %xmm1, 0x18(%r14)
movsd %xmm1, 0x18(%rbx)
jmp 0x35b6
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
setl %dl
jmp 0x3477
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
setg %dl
jmp 0x3477
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
setle %dl
jmp 0x3477
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
setne %dl
jmp 0x3477
testq %rdx, %rdx
jne 0x3116
jmp 0x3505
testq %rcx, %rcx
jne 0x3505
xorl %ecx, %ecx
jmp 0x3116
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x35bf
cvtsi2sdq 0x18(%rax), %xmm1
jmp 0x35c4
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
setge %dl
jmp 0x3477
xorl %edx, %edx
cmpq 0x18(%rax), %rcx
sete %dl
movq %rdx, 0x18(%rbx)
jmp 0x35b6
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x35d2
cvtsi2sdq 0x18(%rax), %xmm1
xorl %eax, %eax
ucomisd %xmm1, %xmm0
jmp 0x35ca
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x35e1
cvtsi2sdq 0x18(%rax), %xmm1
jmp 0x35e6
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x35f4
cvtsi2sdq 0x18(%rax), %xmm1
cmpneqsd %xmm1, %xmm0
jmp 0x3650
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
movl $0x1, %ecx
xorpd %xmm1, %xmm1
jne 0x35fc
ucomisd %xmm1, %xmm0
jne 0x3116
jp 0x3116
xorl %ecx, %ecx
jmp 0x352b
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
xorpd %xmm1, %xmm1
jne 0x361f
xorl %ecx, %ecx
ucomisd %xmm1, %xmm0
jne 0x352b
jnp 0x3116
cmpq $0x0, 0x18(%rax)
setne %cl
jmp 0x3116
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x363b
cvtsi2sdq 0x18(%rax), %xmm1
xorl %eax, %eax
ucomisd %xmm1, %xmm0
jmp 0x35ec
cmpl $0x2, 0x10(%rax)
movsd 0x18(%r14), %xmm0
jne 0x364a
cvtsi2sdq 0x18(%rax), %xmm1
cmpeqsd %xmm1, %xmm0
jmp 0x3650
movsd 0x18(%r14), %xmm0
divsd 0x18(%rcx), %xmm0
jmp 0x35ab
movsd 0x18(%rcx), %xmm0
mulsd 0x18(%r14), %xmm0
jmp 0x35ab
movsd 0x18(%rcx), %xmm0
addsd 0x18(%r14), %xmm0
jmp 0x35ab
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 0x3379
xorl %ecx, %ecx
ucomisd 0x18(%rax), %xmm0
seta %cl
jmp 0x3116
movsd 0x18(%rax), %xmm1
xorl %eax, %eax
ucomisd %xmm0, %xmm1
setae %al
jmp 0x3379
cmpneqsd 0x18(%rax), %xmm0
jmp 0x3650
ucomisd %xmm1, %xmm0
jne 0x3116
jp 0x3116
cmpneqsd 0x18(%rax), %xmm1
movq %xmm1, %rcx
andl $0x1, %ecx
jmp 0x3116
ucomisd %xmm1, %xmm0
jne 0x3627
jnp 0x3634
cmpneqsd 0x18(%rax), %xmm1
movq %xmm1, %rax
jmp 0x3655
xorl %eax, %eax
jmp 0x3379
xorl %ecx, %ecx
ucomisd 0x18(%rax), %xmm0
setae %cl
jmp 0x3116
cmpeqsd 0x18(%rax), %xmm0
movq %xmm0, %rax
andl $0x1, %eax
jmp 0x3379
movq 0x18(%rax), %rcx
leaq 0x8381(%rip), %rdx      # 0xb9e9
movq %r15, %rdi
movq %rbx, %rsi
xorl %eax, %eax
callq 0x2285
leaq 0x833d(%rip), %rdx      # 0xb9b9
movq %r15, %rdi
movq %rbx, %rsi
xorl %eax, %eax
callq 0x2285