#define PE_UNARY_TERM1			0
#define PE_UNARY_TERM2			1
#define PE_MAYBE_MODIFIERS		2
#define PE_UNARY_MODIFIERS		3
#define PE_DEREFERENCE			4
#define PE_CHECK_BINARY_OPS1	5
#define PE_CHECK_BINARY_OPS2	6
#define PE_DO_UNARY_OP			7
#define PE_DO_BINARY_OP 		8
#define PE_POP_HIGHER 			9
#define PE_PUSH_LOWER 			10
#define PE_POP_ALL1 			11
#define PE_POP_ALL2 			12

CIntermediateCode *ParseAddOp(CCompCtrl *cc, I64 stack_op, CHashClass *tmpc)
{
	CIntermediateCode	*tmpi = cc->coc.coc_head.last;
	Bool				 div_sizeof = FALSE;

	switch (stack_op.u16[0])
	{
		case IC_ADD:
			if (tmpc->ptr_stars_count && !tmpi->ic_class->ptr_stars_count && tmpi->ic_class->raw_type != RT_F64)
			{
				ICAdd(cc, IC_SIZEOF, 1, cmp.internal_types[RT_I64]);
				ICAdd(cc, IC_MUL, 0, cmp.internal_types[RT_I64]);
			}
			break;

		case IC_SUB:
			if (tmpc->ptr_stars_count && tmpi->ic_class->raw_type != RT_F64)
			{
				if (!tmpi->ic_class->ptr_stars_count)
				{
					ICAdd(cc, IC_SIZEOF, 1, cmp.internal_types[RT_I64]);
					ICAdd(cc, IC_MUL, 0, cmp.internal_types[RT_I64]);
				}
				else
					div_sizeof = TRUE;
			}
			break;

		case IC_AND_AND:
		case IC_OR_OR:
			ICAdd(cc, IC_NOP1, 0, cmp.internal_types[RT_I64]);
			break;

		case IC_ADD_EQU:
		case IC_SUB_EQU:
			if (tmpc->ptr_stars_count)
			{
				ICAdd(cc, IC_SIZEOF, 1, cmp.internal_types[RT_I64]);
				ICAdd(cc, IC_MUL, 0, cmp.internal_types[RT_I64]);
			}
			break;
	}
	tmpi = ICAdd(cc, stack_op, 0, tmpc);
	if (stack_op.u8[3] & ECF_HAS_PUSH_CMP)
	{
		tmpi->ic_flags |= ICF_POP_CMP;
		ICAdd(cc, IC_NOP1, 0, cmp.internal_types[RT_I64]);
		ICAdd(cc, IC_AND_AND, 0, cmp.internal_types[RT_I64], ICF_POP_CMP);
	}
	if (div_sizeof)
	{
		tmpc--;
		if (tmpc->size != 1)
		{
			ICAdd(cc, IC_IMM_I64, tmpc->size, cmp.internal_types[RT_I64]);
			ICAdd(cc, IC_DIV, 0, cmp.internal_types[RT_I64]);
			tmpc = cmp.internal_types[RT_I64];
		}
	}

	return tmpi;
}

U0 ParseExpression2(CCompCtrl *cc, I64 *_max_prec, CParseStack *ps)
{
	I64					 i, cur_op, stack_op, state,
						 max_prec = PREC_NULL, unary_pre_prec, paren_prec, unary_post_prec, left_prec = PREC_MAX;
	CIntermediateCode	*tmpi;
	CHashClass			*tmpc;
	CMemberList			*local_var;
	CArrayDim			*tmpad = NULL;

	goto pe_unary_term1;
	while (TRUE)
	{
		switch [state]
		{
			case PE_UNARY_TERM1:
pe_unary_term1:
				unary_pre_prec = PREC_NULL;
				unary_post_prec = PREC_NULL;
				cc->flags &= ~(CCF_PAREN + CCF_PREINC + CCF_PREDEC + CCF_POSTINC + CCF_POSTDEC + CCF_FUN_EXP);

			case PE_UNARY_TERM2:
				state = ParseUnaryTerm(cc, ps, &local_var, &tmpad, &max_prec, &unary_pre_prec, &paren_prec);
				break;

			case PE_UNARY_MODIFIERS:
				state = ParseUnaryModifier(cc, ps, &local_var, &tmpad, &unary_post_prec);
				break;

			case PE_MAYBE_MODIFIERS:
				if (cc->token == '(')
				{ //Typecast or fun_ptr
					cc->flags |= CCF_RAX;
					state = ParseUnaryModifier(cc, ps, &local_var, &tmpad, &unary_post_prec);
				}
				else
					goto pe_check_binary_ops1;
				break;

			case PE_DEREFERENCE:
				if (!(cc->flags & (CCF_PREINC | CCF_PREDEC | CCF_POSTINC | CCF_POSTDEC)))
					i = IC_DEREF + PREC_UNARY_PRE << 16;
				else
				{
					if (cc->flags & CCF_POSTINC)
						i = IC__PP + PREC_UNARY_POST << 16;
					else if (cc->flags & CCF_POSTDEC)
						i = IC__MM + PREC_UNARY_POST << 16;
					else if (cc->flags & CCF_PREDEC)
						i = IC_MM_ + PREC_UNARY_PRE << 16;
					else
						i = IC_PP_+PREC_UNARY_PRE << 16;
					cc->flags &= ~(CCF_PREINC | CCF_PREDEC | CCF_POSTINC | CCF_POSTDEC);
				}
				tmpi = cc->coc.coc_head.last;
				if (cc->flags & (CCF_RAX | CCF_ARRAY))
				{
					if (tmpi->ic_code == IC_DEREF)
						tmpi->ic_code = i;
				}
				else
				{
					tmpc = OptClassFwd(tmpi->ic_class - 1);
					ICAdd(cc, i, 0, tmpc);
				}

			case PE_CHECK_BINARY_OPS1:
pe_check_binary_ops1:
				if (paren_prec)
				{
					if (unary_pre_prec || unary_post_prec)
					{
						if (paren_prec <= unary_pre_prec && !unary_post_prec)
							ParenWarning(cc);
						paren_prec = PREC_NULL;
					}
					else if (paren_prec <= PREC_UNARY_PRE + ASSOC_MASK)
						ParenWarning(cc);
				}
				cur_op = cmp.binary_ops[cc->token];


			case PE_CHECK_BINARY_OPS2:
pe_check_binary_ops2:
				stack_op = ParsePop(ps);
				tmpc = ParsePop(ps);
				if (!(0 < stack_op.u8[2] <= PREC_UNARY_PRE + ASSOC_MASK))
					goto pe_do_binary_op;

			case PE_DO_UNARY_OP:
				if (cur_op.u16[0] == IC_POWER && stack_op.u16[0] == IC_UNARY_MINUS)
				{
					Lex(cc); //skip ` op
					left_prec = cur_op.i8[2];
					ParsePush(ps, tmpc);
					ParsePush(ps, stack_op);
					ParsePush(ps, cc->coc.coc_head.last->ic_class);
					ParsePush(ps, cur_op);
					goto pe_unary_term1;
				}
				else
				{
					tmpi = cc->coc.coc_head.last;
					tmpc = tmpi->ic_class;
					if (stack_op.u16[0] == IC_DEREF && tmpc->ptr_stars_count)
						tmpc--;
					else if (stack_op.u16[0] == IC_ADDR)
					{
						cc->abs_counts.c_addres++;
						if (intermediate_code_table[tmpi->ic_code].type == IST_DEREF)
							OptFree(tmpi);
						tmpc++;
					}
					tmpc = OptClassFwd(tmpc);
					if (stack_op)
						ICAdd(cc, stack_op, 0, tmpc);
					goto pe_check_binary_ops2;
				}

			case PE_DO_BINARY_OP:
pe_do_binary_op:
				ParsePush(ps, tmpc);
				ParsePush(ps, stack_op);
				if (!cur_op)
					goto pe_pop_all1;

				switch (cur_op.u16[0])
				{
					case IC_ADD:
					case IC_SUB:
						tmpi = cc->coc.coc_head.last;
						if (!tmpi->ic_class->ptr_stars_count && tmpi->ic_class->raw_type != RT_F64)
						{
							ICAdd(cc, IC_SIZEOF, 1, cmp.internal_types[RT_I64]);
							ICAdd(cc, IC_MUL, 0, cmp.internal_types[RT_I64]);
						}
						break;

					case IC_AND_AND:
					case IC_OR_OR:
						ICAdd(cc, IC_NOP1, 0, cmp.internal_types[RT_I64]);
						break;
				}
				if (cc->flags & CCF_FUN_EXP)
				{
					ps->ptr2--;
					cc->flags &= ~CCF_FUN_EXP;
				}
				Lex(cc); //skip op
				if (paren_prec > PREC_UNARY_PRE + ASSOC_MASK &&
						paren_prec & ~ASSOC_MASK < left_prec & ~ASSOC_MASK + paren_prec & ASSOCF_RIGHT &&
						paren_prec & ~ASSOC_MASK < cur_op.u8[2] & ~ASSOC_MASK + !(paren_prec & ASSOCF_RIGHT))
					ParenWarning(cc);
				if (cur_op.u8[2] > max_prec)
					max_prec = cur_op.u8[2];
				left_prec = cur_op.u8[2];
				if (intermediate_code_table[cur_op.u16[0]].type == IST_ASSIGN)
				{
					tmpi = cc->coc.coc_head.last;
					tmpc = OptClassFwd(tmpi->ic_class);
					if (intermediate_code_table[tmpi->ic_code].type != IST_DEREF || !tmpc->ptr_stars_count &&
							!Bt(&tmpc->flags, Cf_INTERNAL_TYPE))
						LexExcept(cc, "Invalid lval at ");
					tmpi->ic_code = IC_NOP1; //Important for setting class (pretty sure)
					cur_op.u8[2] = PREC_ASSIGN | ASSOCF_RIGHT;
				}

			case PE_POP_HIGHER:
pe_pop_higher:
				stack_op = ParsePop(ps); //pop ops of higher prec
				tmpc = ParsePop(ps);
				if (!stack_op)
					goto pe_push_lower;
				else if (cur_op.u8[2] & ~ASSOC_MASK == stack_op.u8[2] & ~ASSOC_MASK)
				{
					if (cur_op.u8[2] & ASSOCF_RIGHT)
						goto pe_push_lower;
				}
				else if (cur_op.u8[2] & ~ASSOC_MASK <= stack_op.u8[2] & ~ASSOC_MASK)
					goto pe_push_lower;

				tmpi = ParseAddOp(cc, stack_op, tmpc);

				if (intermediate_code_table[cur_op.u16[0]].type   == IST_CMP &&
					intermediate_code_table[stack_op.u16[0]].type == IST_CMP)
				{
					tmpi->ic_flags |= ICF_PUSH_CMP;
					ICAdd(cc, IC_NOP1, 0, cmp.internal_types[RT_I64]);
					ICAdd(cc, IC_PUSH_CMP, 0, tmpc);
					cur_op.u8[3] |= ECF_HAS_PUSH_CMP;
				}
				else if (cur_op.u16[0] == IC_AND_AND || cur_op.u16[0] == IC_OR_OR)
					ICAdd(cc, IC_NOP1, 0, cmp.internal_types[RT_I64]);
				goto pe_pop_higher;

			case PE_PUSH_LOWER:
pe_push_lower:
				ParsePush(ps, tmpc);
				ParsePush(ps, stack_op);
				ParsePush(ps, cc->coc.coc_head.last->ic_class);
				ParsePush(ps, cur_op);
				goto pe_unary_term1;

			case PE_POP_ALL1:
pe_pop_all1:
				if (paren_prec > PREC_UNARY_PRE + ASSOC_MASK && 
						paren_prec & ~ASSOC_MASK <= left_prec & ~ASSOC_MASK -
						paren_prec & ASSOCF_LEFT - left_prec & ASSOCF_LEFT)
					ParenWarning(cc);

			case PE_POP_ALL2:
pe_pop_all2:
				stack_op = ParsePop(ps);
				tmpc = ParsePop(ps);
				if (!stack_op.u16[0])
					goto pe_done;
				ParseAddOp(cc, stack_op, tmpc);
				goto pe_pop_all2;
		}
	}
pe_done:
	if (_max_prec)
		*_max_prec = max_prec;
}

Bool ParseExpression(CCompCtrl *cc, I64 *_max_prec, Bool end_exp, CParseStack *_ps=NULL)
{
	Bool		 res = TRUE;
	I64			 old_flags = cc->flags;
	CParseStack	*ps;

	if (_ps)
		ps = _ps;
	else
	{
		ps = MAlloc(sizeof(CParseStack));
		ps->ptr = 0;
		ps->ptr2 = 0;
	}
	ParsePush(ps, 0); //terminate
	ParsePush(ps, 0); //terminate
	try
//try catch causes noreg vars in function
		ParseExpression2(cc, _max_prec, ps);
	catch
	{
		if (Fs->except_ch == 'Compiler')
		{
			res = FALSE;
			Fs->catch_except = TRUE;
		}
	}
	if (!_ps)
	{
		if (ps->ptr)
			LexExcept(cc, "Compiler Parse Error at ");
		Free(ps);
	}
	if (res)
	{
		if (end_exp)
			ICAdd(cc, IC_END_EXP, 0, 0, ICF_RES_NOT_USED);
		if (cc->coc.coc_head.last->ic_class == cmp.internal_types[RT_U0])
			LexWarn(cc, "U0 Expression ");
	}
	cc->flags |= old_flags & (CCF_PREINC | CCF_PREDEC);

	return res;
}

U0 ParseSizeOf(CCompCtrl *cc)
{
	CHashClass	*tmpc;
	CMemberList	*tmpm;
	CDebugInfo	*debug_info;
	I64			 i;

	if (cc->token != TK_IDENT)
		LexExcept(cc, "Invalid class at ");
	if (tmpm = cc->local_var_entry)
	{
		tmpc = tmpm->member_class;
		i = tmpc->size * tmpm->dim.total_count;
		if (Lex(cc) == '.')
			goto pu_sizeof_member;
	}
	else
	{
		if (!(tmpc = cc->hash_entry) ||
				!(tmpc->type & (HTT_CLASS | HTT_INTERNAL_TYPE | HTT_GLOBAL_VAR | HTT_FUN | HTT_EXPORT_SYS_SYM)))
			LexExcept(cc, "Invalid class at ");
		if (tmpc->type & (HTT_FUN | HTT_EXPORT_SYS_SYM))
		{
			if (!(debug_info = tmpc(CHashFun *)->debug_info))
				LexExcept(cc, "Size not defined at ");
			i = debug_info->body[debug_info->max_line + 1 - debug_info->min_line] - debug_info->body[0];
			Lex(cc);
		}
		else
		{
			i = tmpc->size;
			while (Lex(cc) == '.')
			{
pu_sizeof_member:
				if (!(tmpc->type & (HTT_CLASS | HTT_GLOBAL_VAR)))
					LexExcept(cc, "Invalid class at ");
				else if (tmpc->type & HTT_GLOBAL_VAR)
					tmpc = tmpc(CHashGlobalVar *)->var_class;
				if (Lex(cc) != TK_IDENT || !(tmpm = MemberFind(cc->cur_str, tmpc)))
					LexExcept(cc, "Invalid member at ");
				else if (cc->local_var_entry)
					cc->local_var_entry->use_count--;
				tmpc = tmpm->member_class;
//Probably others like this:
				#assert offset(CHashClass.size) == offset(CHashGlobalVar.size)
				i = tmpc->size * tmpm->dim.total_count;
			}
		}
	}
	if (cc->token == '*')
	{
		while (Lex(cc) == '*');
		i = sizeof(U8 *);
	}
	ICAdd(cc, IC_IMM_I64, i, cmp.internal_types[RT_I64]);
}

U0 ParseOffsetOf(CCompCtrl *cc)
{
	CHashClass	*tmpc;
	CMemberList	*tmpm;
	I64			 i;

	if (cc->token != TK_IDENT)
		LexExcept(cc, "Invalid class at ");
	if (tmpm = cc->local_var_entry)
		tmpc = tmpm->member_class;
	else
	{
		tmpc = cc->hash_entry;
		if (!tmpc || !(tmpc->type & (HTT_CLASS | HTT_GLOBAL_VAR)))
			LexExcept(cc, "Invalid class at ");
		else if (tmpc->type & HTT_GLOBAL_VAR)
			tmpc = tmpc(CHashGlobalVar *)->var_class;
	}
	if (Lex(cc) != '.')
		LexExcept(cc, "Expecting '.' at ");
	i = 0;
	do
	{
		if (Lex(cc) != TK_IDENT || !(tmpm = MemberFind(cc->cur_str, tmpc)))
			LexExcept(cc, "Invalid member at ");
		else if (cc->local_var_entry)
			cc->local_var_entry->use_count--;
		i += tmpm->offset;
		tmpc = tmpm->member_class;
	}
	while (Lex(cc) == '.');

	ICAdd(cc, IC_IMM_I64, i, cmp.internal_types[RT_I64]);
}

I64 ParseFunCall(CCompCtrl *cc, CParseStack *ps, Bool indirect, CHashFun *tmpf)
{
	I64					 i, argc_count, default_val;
	Bool				 is_first_arg = TRUE, needs_right_paren, is_print, is_putchars, is_template_fun;
	CHashClass			*tmpc2, *last_class = NULL;
	CMemberList			*tmpm;
	CCodeCtrl			*tmpcbh, *tmpcbh1;
	CCodeMisc			*cm;
	CIntermediateCode	*tmpi;

	if (!tmpf)
	{
		if (cc->token == TK_CHAR_CONST)
		{
			if (!(tmpf = HashFind("PutChars", cc->htc.hash_table_list, HTT_FUN)))
				LexExcept(cc, "Missing header for Print() and PutChars() at ");
			if (!cc->cur_i64) //empty char signals PutChars with variable
				Lex(cc);
			is_print = FALSE;
			is_putchars = TRUE;
		}
		else
		{
			if (!(tmpf = HashFind("Print", cc->htc.hash_table_list, HTT_FUN)))
				LexExcept(cc, "Missing header for Print() and PutChars() at ");
			if (!*cc->cur_str) //empty string signals Print with variable format_str
				Lex(cc);
			is_putchars = FALSE;
			is_print = TRUE;
		}
	}
	else
	{
		is_print = FALSE;
		is_putchars = FALSE;
	}

	if (Bt(&tmpf->flags, Ff_INTERNAL) && IC_SQR <= tmpf->exe_addr <= IC_ATAN)
		is_template_fun = TRUE;
	else
		is_template_fun = FALSE;

	if (indirect)
	{
		if (!(cc->flags & (CCF_RAX | CCF_ARRAY)))
			ICAdd(cc, IC_DEREF, 0, cmp.internal_types[RT_PTR]);
		cc->coc.coc_head.last->ic_class = cmp.internal_types[RT_PTR];
		ICAdd(cc, IC_RAX_SET, 0, cmp.internal_types[RT_PTR]);
		ICAdd(cc, IC_NOP2, 1, cmp.internal_types[RT_PTR]); //balance the books
	}
	COCPush(cc);
	tmpcbh = cc->coc.coc_next;
	cc->coc.coc_next = NULL;
	i = tmpf->arg_count;
	tmpm = tmpf->member_list_and_root;
	argc_count = 0;
	if (cc->token == '(')
	{
		Lex(cc);
		needs_right_paren = TRUE;
	}
	else
		needs_right_paren = FALSE;
	while (i--)
	{
		COCInit(cc);
		if (!is_first_arg)
		{
			if (is_print)
			{
				if (cc->token == ',')
					Lex(cc);
				else if (cc->token != ';')
					LexExcept(cc, "Expecting ',' at ");
			}
			else
			{
				if (needs_right_paren)
				{
					if (cc->token == ',')
						Lex(cc);
					else if (cc->token != ')')
						LexExcept(cc, "Expecting ',' at ");
				}
			}
		}
		if (tmpm->flags & MLF_DEFAULT_AVAILABLE && (cc->token == ')' || cc->token == ',' || !needs_right_paren))
		{
			default_val = tmpm->default_val;
			if (tmpm->flags & MLF_LASTCLASS && last_class)
				default_val = (last_class - last_class->ptr_stars_count)->str;
			if (tmpm->flags & (MLF_STR_DEFAULT_AVAILABLE | MLF_LASTCLASS) && cc->flags & CCF_AOT_COMPILE)
			{
				cm = COCMiscNew(cc, CMT_STR_CONST);
				ICAdd(cc, IC_STR_CONST, cm, cmp.internal_types[RT_U8] + 1);
				cm->st_len = StrLen(default_val) + 1;
				cm->str = StrNew(default_val);
				cc->flags |= CCF_HAS_MISC_DATA;
			}
			else
				ICAdd(cc, IC_IMM_I64, default_val, tmpm->member_class);
		}
		else
		{
			if (!ParseExpression(cc, NULL, FALSE, ps))
				throw('Compiler');
			else
			{
				COCPush(cc);
				cc->pass = 0;
				OptPass012(cc);
				cc->pass = 1;
				tmpi = OptPass012(cc);
				COCPop(cc);
				last_class = OptClassFwd(tmpi->ic_class);
				tmpc2 = OptClassFwd(tmpm->member_class);
				if (tmpc2->raw_type == RT_F64 && !tmpm->dim.next && last_class->raw_type != RT_F64)
					tmpi->ic_flags |= ICF_RES_TO_F64;
				else
					if (tmpc2->raw_type != RT_F64 && last_class->raw_type == RT_F64)
						tmpi->ic_flags |= ICF_RES_TO_INT;
			}
		}
		COCPush(cc);
		is_first_arg = FALSE;
		tmpm = tmpm->next;
	}
	if (tmpm && tmpm->flags & MLF_DOT_DOT_DOT)
	{
		COCInit(cc);
		tmpi = ICAdd(cc, IC_IMM_I64, 0, tmpm->member_class);
		COCPush(cc);
		if (is_print)
		{
			if (cc->token != ';')
			{
				do
				{
					if (!is_first_arg)
					{
						if (cc->token == ',')
							Lex(cc);
						else
							LexExcept(cc, "Expecting ',' at ");
					}
					COCInit(cc);
					if (!ParseExpression(cc, NULL, FALSE, ps))
						throw('Compiler');
					COCPush(cc);
					is_first_arg = FALSE;
					argc_count++;
				}
				while (cc->token == ',');
			}
		}
		else if (needs_right_paren)
		{
			if (cc->token != ')')
			{
				do
				{
					if (!is_first_arg)
					{
						if (cc->token == ',')
							Lex(cc);
						else
							LexExcept(cc, "Expecting ',' at ");
					}
					COCInit(cc);
					if (!ParseExpression(cc, NULL, FALSE, ps))
						throw('Compiler');
					COCPush(cc);
					is_first_arg = FALSE;
					argc_count++;
				}
				while (cc->token == ',');
			}
		}
		tmpi->ic_data = argc_count++; //++ so add_esp latter works
	}
	if (needs_right_paren)
	{
		if (cc->token == ')')
			Lex(cc);
		else
			LexExcept(cc, "Missing ')' at ");
	}
	tmpcbh1 = tmpcbh->coc_next;
	tmpcbh->coc_next = cc->coc.coc_next;
	cc->coc.coc_next = tmpcbh;
	COCPop(cc);
	tmpcbh = cc->coc.coc_next;
	cc->coc.coc_next = tmpcbh1;
	if (!is_template_fun)
		ICAdd(cc, IC_CALL_START, tmpf, 0);
	if (indirect)
		ICAdd(cc, IC_PUSH_REGS, 1 << REG_RAX, tmpf->return_class);
	while (tmpcbh)
	{
		tmpcbh1 = tmpcbh->coc_next;
		COCAppend(cc, tmpcbh);
		if (!Bt(&tmpf->flags, Ff_INTERNAL))
			cc->coc.coc_head.last->ic_flags |= ICF_PUSH_RES;
		tmpcbh = tmpcbh1;
	}
	if (Bt(&tmpf->flags, Ff_INTERNAL))
		ICAdd(cc, tmpf->exe_addr, 0, tmpf->return_class);
	else
	{
		if (indirect)
			ICAdd(cc, IC_CALL_INDIRECT, (argc_count + tmpf->arg_count) << 3, tmpf->return_class);
		else if (Bt(&tmpf->flags, Cf_EXTERN))
		{
			cc->abs_counts.externs++;
			if (cc->flags & CCF_AOT_COMPILE)
			{
				if (tmpf->type & HTF_IMPORT)
					ICAdd(cc, IC_CALL_IMPORT, tmpf, tmpf->return_class);
				else
					ICAdd(cc, IC_CALL_EXTERN, tmpf, tmpf->return_class);
			}
			else
				ICAdd(cc, IC_CALL_INDIRECT2, &tmpf->exe_addr, tmpf->return_class);
		}
		else
			ICAdd(cc, IC_CALL, tmpf->exe_addr, tmpf->return_class);
		if ((Bt(&tmpf->flags, Ff_RET1) || Bt(&tmpf->flags, Ff_ARGPOP)) && !Bt(&tmpf->flags, Ff_NOARGPOP))
		{
			if (indirect)
			{
				ICAdd(cc, IC_ADD_RSP1, (argc_count + tmpf->arg_count) << 3, tmpf->return_class);
				ICAdd(cc, IC_ADD_RSP, 8, tmpf->return_class);
			}
			else
				ICAdd(cc, IC_ADD_RSP1, (argc_count + tmpf->arg_count) << 3, tmpf->return_class);
		}
		else
		{
			if (indirect)
				argc_count++;
			ICAdd(cc, IC_ADD_RSP, (argc_count + tmpf->arg_count) << 3, tmpf->return_class);
		}
	}
	if (!is_template_fun)
		ICAdd(cc, IC_CALL_END, tmpf, tmpf->return_class);
	if (is_print || is_putchars)
		ICAdd(cc, IC_END_EXP, 0, 0, ICF_RES_NOT_USED);
	cc->flags = (cc->flags | CCF_RAX) & ~(CCF_ARRAY | CCF_FUN_EXP);

	return PE_UNARY_MODIFIERS;
}

I64 ParseUnaryTerm(CCompCtrl *cc, CParseStack *ps, CMemberList **_local_var, CArrayDim **_tmpad,
				   I64 *max_prec, I64 *unary_pre_prec, I64 *paren_prec)
{
	I64				 i, j;
	CHashExport		*tmpex;
	CHashClass		*tmpc;
	CHashFun		*tmpf;
	CHashGlobalVar	*tmpg;
	CMemberList		*tmpm;
	CAsmUndefHash	*tmpauh;
	CCodeMisc		*cm;
	Bool			 paren_warn;

	*_local_var = NULL;
	*paren_prec = PREC_NULL;
	switch (cc->token)
	{
		start:
			if (PREC_UNARY_PRE > *max_prec)
				*max_prec = PREC_UNARY_PRE;
			*unary_pre_prec = PREC_UNARY_PRE;
			start:
				case '~': i = IC_COM;			break;
				case '!': i = IC_NOT; 			break;
				case '-': i = IC_UNARY_MINUS;	break;
				case '*': i = IC_DEREF; 		break;
			end:
				Lex(cc); //Skip op
				break;

			case '&':
				if (Lex(cc) == TK_IDENT)
				{
					if (tmpc = cc->hash_entry)
					{
						if (tmpc->type & HTT_FUN)
						{
							tmpf = tmpc;
							if (!Bt(&tmpf->flags, Ff_INTERNAL))
							{
								if (Bt(&tmpf->flags, Cf_EXTERN))
								{
									if (cc->flags & CCF_AOT_COMPILE)
									{
										if (cc->flags & CCF_ASM_EXPRESSIONS)
										{
											if (tmpex = HashFind(tmpf->str, cc->htc.hash_table_list, HTT_EXPORT_SYS_SYM))
												goto pu_export_sys_sym;
											else
												goto pu_new_sys_sym;
										}
										LexExcept(cc, "Can't take addr of extern fun");
									}
									cc->abs_counts.externs++;
									ICAdd(cc, IC_IMM_I64, &tmpf->exe_addr, cmp.internal_types[RT_PTR]);
									ICAdd(cc, IC_DEREF, 0, cmp.internal_types[RT_PTR]);
								}
								else
								{
									if (cc->flags & CCF_AOT_COMPILE)
									{
										ICAdd(cc, IC_ABS_ADDR, tmpf->exe_addr, cmp.internal_types[RT_PTR]);
										if (cc->flags & CCF_ASM_EXPRESSIONS)
											cc->abs_counts.abs_addres++;
									}
									else
										ICAdd(cc, IC_IMM_I64, tmpf->exe_addr, cmp.internal_types[RT_PTR]);
								}
								cc->abs_counts.c_addres++;
								Lex(cc);
								return PE_MAYBE_MODIFIERS;
							}
						}
						else if (tmpc->type & HTT_EXPORT_SYS_SYM)
						{
							tmpex = tmpc;
							if (cc->flags & CCF_ASM_EXPRESSIONS && !(cc->flags & CCF_AOT_COMPILE) && tmpex->type & HTF_IMM)
							{
								cc->abs_counts.c_addres++;
								ICAdd(cc, IC_IMM_I64, tmpex->val, cmp.internal_types[RT_PTR]);
								Lex(cc);
								return PE_MAYBE_MODIFIERS;
							}
							else
								goto pu_export_sys_sym;
						}
					}
					else if (cc->flags & CCF_ASM_EXPRESSIONS && !cc->local_var_entry)
						goto pu_ident_but_not_local_var;
				}
				i = IC_ADDR;
				break;
		end:
			ParsePush(ps, tmpc);
			ParsePush(ps, PREC_UNARY_PRE << 16 + i);
			return PE_UNARY_TERM2;

		start:
			case TK_I64:
			case TK_CHAR_CONST:
			case TK_INS_BIN_SIZE:
				if (cc->cur_i64 < 0)
					ICAdd(cc, IC_IMM_I64, cc->cur_i64, cmp.internal_types[RT_U64]);
				else
					ICAdd(cc, IC_IMM_I64, cc->cur_i64, cmp.internal_types[RT_I64]);
				Lex(cc);
				break;

			case TK_F64:
				ICAdd(cc, IC_IMM_F64, cc->cur_f64(I64), cmp.internal_types[RT_F64]);
				Lex(cc);
				break;

			case TK_STR:
				cm = COCMiscNew(cc, CMT_STR_CONST);
				ICAdd(cc, IC_STR_CONST, cm, cmp.internal_types[RT_U8] + 1);
				cm->str = LexExtStr(cc, &cm->st_len);
				cc->flags |= CCF_HAS_MISC_DATA;
				break;

			case TK_INS_BIN:
				cm = COCMiscNew(cc, CMT_STR_CONST);
				ICAdd(cc, IC_STR_CONST, cm, cmp.internal_types[RT_U8] + 1);
				cm->str = cc->cur_str;
				cm->st_len = cc->cur_str_len;
				cc->cur_str = NULL;
				cc->flags |= CCF_HAS_MISC_DATA;
				Lex(cc);
				break;

			case '$$':
				if (cc->flags & CCF_ASM_EXPRESSIONS)
				{
					cc->abs_counts.abs_addres++;
					if (cc->flags  &CCF_AOT_COMPILE)
						ICAdd(cc, IC_ABS_ADDR, cc->aotc->rip, cmp.internal_types[RT_PTR]);
					else
						ICAdd(cc, IC_IMM_I64, cc->aotc->rip, cmp.internal_types[RT_PTR]);
				}
				else
				{
					if (cc->flags & CCF_CLASS_DOL_OFFSET)
						ICAdd(cc, IC_IMM_I64, cc->class_dol_offset, cmp.internal_types[RT_I64]);
					else
						ICAdd(cc, IC_RIP, 0, cmp.internal_types[RT_PTR]);
				}
				Lex(cc);
				break;
		end:
			if (PREC_TERM > *max_prec)
				*max_prec = PREC_TERM;
			return PE_MAYBE_MODIFIERS;

		case '(':
			if (Lex(cc) == TK_IDENT && cc->hash_entry && cc->hash_entry->type & (HTT_CLASS | HTT_INTERNAL_TYPE))
				LexExcept(cc, "Use ZenithOS postfix typecasting at ");
			else
			{
				if (PREC_TERM > *max_prec)
					*max_prec = PREC_TERM;
				if (cc->lex_include_stack->flags & LFSF_DEFINE)
					paren_warn = FALSE;
				else
					paren_warn = TRUE;
				if (!ParseExpression(cc, paren_prec, FALSE, ps))
					throw('Compiler');
				if (!paren_warn)
					*paren_prec = PREC_NULL;
				if (cc->token != ')')
					LexExcept(cc, "Missing ')' at ");
				Lex(cc); //skip )
				cc->flags = cc->flags & ~CCF_ARRAY | CCF_RAX | CCF_PAREN;
				return PE_UNARY_MODIFIERS;
			}

		start:
			case '+':	break;
			case TK_PLUS_PLUS:	 cc->flags |= CCF_PREINC;	break;
			case TK_MINUS_MINUS: cc->flags |= CCF_PREDEC;	break;
		end:
			if (PREC_UNARY_PRE > *max_prec)
				*max_prec = PREC_UNARY_PRE;
			*unary_pre_prec = PREC_UNARY_PRE;
			Lex(cc);
			return PE_UNARY_TERM2;

		case TK_IDENT:
			if (tmpm = cc->local_var_entry)
			{
				if (PREC_TERM > *max_prec)
					*max_prec = PREC_TERM;
				cc->flags &= ~(CCF_RAX | CCF_ARRAY | CCF_FUN_EXP);
				tmpc = tmpm->member_class + 1;
				if (tmpm->flags & MLF_FUN && !(cc->flags & CCF_ASM_EXPRESSIONS))
				{
					ParsePopDeref(ps);
					cc->flags |= CCF_FUN_EXP;
					ParsePush2(ps, tmpm->fun_ptr - tmpm->fun_ptr->ptr_stars_count);
				}
				if (tmpm->dim.next)
				{
					*_tmpad = tmpm->dim.next;
					cc->flags |= CCF_ARRAY;
				}
				if (tmpm->flags & MLF_STATIC)
				{
					if (cc->flags & CCF_AOT_COMPILE)
					{
						//	if (tmpg->flags&GVF_DATA_HEAP) //TODO
						//		ICAdd(cc,IC_HEAP_GLOBAL,tmpm->static_data,tmpc);
						//	else
						ICAdd(cc, IC_ABS_ADDR, tmpm->static_data_rip, tmpc);
					}
					else
						ICAdd(cc, IC_IMM_I64, tmpm->static_data, tmpc);
				}
				else
				{
					if (cc->flags & CCF_ASM_EXPRESSIONS)
					{
						i = ParsePop(ps);
						ps->ptr--;
						if (i.u16[0] != IC_ADDR)
							LexExcept(cc, "Expecting '&' at ");
						ICAdd(cc, IC_IMM_I64, tmpm->offset, cmp.internal_types[RT_PTR]);
						*_local_var = tmpm;
						Lex(cc);
						return PE_MAYBE_MODIFIERS;
					}
					else
					{
						if (tmpm->dim.next && tmpm->offset > 0 && StrCompare(tmpm->str, "argv"))
						{
							tmpc++;
							cc->flags &= ~CCF_ARRAY;
						}
						ICAdd(cc, IC_RBP, 0, tmpc);
						ICAdd(cc, IC_IMM_I64, tmpm->offset, tmpc);
						ICAdd(cc, IC_ADD, 0, tmpc);
					}
				}
				Lex(cc); //skip var name
				*_local_var = tmpm;
				return PE_UNARY_MODIFIERS;
			}
pu_ident_but_not_local_var:
			if (!(tmpex = cc->hash_entry))
			{
				if (!(cc->flags & CCF_ASM_EXPRESSIONS))
					LexExcept(cc, "Invalid lval at ");
				tmpc = NULL;
pu_new_sys_sym:
				tmpex = CAlloc(sizeof(CHashExport), Fs->code_heap);
				tmpex->str = cc->cur_str;
				cc->cur_str = NULL;
				if (!cc->htc.local_var_list && *tmpex->str == '@' && tmpex->str[1] == '@')
				{
					tmpex->type = HTT_EXPORT_SYS_SYM | HTF_UNRESOLVED | HTF_LOCAL;
					HashAdd(tmpex, cc->htc.local_hash_table);
				}
				else
				{
					tmpex->type = HTT_EXPORT_SYS_SYM | HTF_UNRESOLVED;
					if (tmpc)
						HashAddAfter(tmpex, tmpc, cc->htc.global_hash_table);
					else
						HashAdd(tmpex, cc->htc.global_hash_table);
				}
			}
			switch (Bsf(tmpex->type))
			{
				case HTt_EXPORT_SYS_SYM:
pu_export_sys_sym:
					if (PREC_TERM > *max_prec)
						*max_prec = PREC_TERM;
					if (!(tmpex->type & (HTF_IMM | HTF_IMPORT)))
						cc->abs_counts.abs_addres++;
					if (tmpex->type & HTF_UNRESOLVED)
					{
						if (!(cc->flags & CCF_ASM_EXPRESSIONS))
							LexExcept(cc, "Illegal forward ref at ");
						tmpauh = MAlloc(sizeof(CAsmUndefHash));
						tmpauh->hash = tmpex;
						tmpauh->next = cc->asm_undef_hash;
						cc->asm_undef_hash = tmpauh;
						if (tmpex->type & HTF_LOCAL)
							cc->flags |= CCF_UNRESOLVED | CCF_LOCAL;
						else
							cc->flags |= CCF_UNRESOLVED;
						ICAdd(cc, IC_IMM_I64, &tmpex->val, cmp.internal_types[RT_PTR], ICF_NO_RIP);
						ICAdd(cc, IC_DEREF, 0, cmp.internal_types[RT_PTR]);
					}
					else
					{
						if (cc->flags & CCF_AOT_COMPILE && !(tmpex->type & HTF_IMM))
							ICAdd(cc, IC_ABS_ADDR, tmpex->val, cmp.internal_types[RT_PTR]);
						else
						{
							if (tmpex->type & HTF_IMM)
								cc->abs_counts.c_addres++;
							ICAdd(cc, IC_IMM_I64, tmpex->val, cmp.internal_types[RT_PTR]);
						}
					}
					Lex(cc);
					return PE_MAYBE_MODIFIERS;

				case HTt_FUN:
					if (PREC_TERM > *max_prec)
						*max_prec = PREC_TERM;
					Lex(cc);	//skip fun name
					return ParseFunCall(cc, ps, FALSE, tmpex);

				case HTt_GLOBAL_VAR:
					if (PREC_TERM > *max_prec)
						*max_prec = PREC_TERM;
					tmpg = tmpex;
					tmpc = tmpg->var_class + 1;
					cc->flags &= ~(CCF_RAX | CCF_ARRAY | CCF_FUN_EXP);
					if (tmpg->flags & GVF_ARRAY)
					{
						*_tmpad = tmpg->dim.next;
						cc->flags |= CCF_ARRAY;
					}
					if (cc->flags & CCF_AOT_COMPILE)
					{
						if (tmpg->flags & GVF_EXTERN) //TODO
							LexExcept(cc, "Feature not implemented ");
						else
						{
							if (tmpg->flags & GVF_IMPORT)
								ICAdd(cc, IC_ADDR_IMPORT, tmpg, tmpc);
							else
							{
								if (tmpg->flags & GVF_DATA_HEAP)
									ICAdd(cc, IC_HEAP_GLOBAL, tmpg->heap_global, tmpc);
								else
									ICAdd(cc, IC_ABS_ADDR, tmpg->data_addr_rip, tmpc);
							}
						}
					}
					else
					{
						if (tmpg->flags & GVF_EXTERN)
						{
							cc->abs_counts.externs++;
							ICAdd(cc, IC_IMM_I64, &tmpg->data_addr, tmpc);
							ICAdd(cc, IC_DEREF, 0, tmpc);
						}
						else
							ICAdd(cc, IC_IMM_I64, tmpg->data_addr, tmpc);
					}
					Lex(cc);
					if (tmpg->flags & GVF_FUN)
					{
						ParsePopDeref(ps);
						cc->flags |= CCF_FUN_EXP;
						ParsePush2(ps, tmpg->fun_ptr - tmpg->fun_ptr->ptr_stars_count);
					}
					return PE_UNARY_MODIFIERS;

				case HTt_CLASS:
					ParseOffsetOf(cc);
					return PE_MAYBE_MODIFIERS;

				case HTt_KEYWORD:
					switch (tmpex(CHashGeneric *)->user_data0)
					{
						case KW_SIZEOF:
							if (PREC_TERM > *max_prec)
								*max_prec = PREC_TERM;
							j = 0;
							while (Lex(cc) == '(')
								j++;
							ParseSizeOf(cc);
							while (j--)
							{
								if (cc->token != ')')
									LexExcept(cc, "Missing ')' at ");
								Lex(cc);
							}
							return PE_MAYBE_MODIFIERS;

						case KW_OFFSET:
							if (PREC_TERM > *max_prec)
								*max_prec = PREC_TERM;
							j = 0;
							while (Lex(cc) == '(')
								j++;
							ParseOffsetOf(cc);
							while (j--)
							{
								if (cc->token != ')')
									LexExcept(cc, "Missing ')' at ");
								Lex(cc);
							}
							return PE_MAYBE_MODIFIERS;

						case KW_DEFINED:
							if (PREC_TERM > *max_prec)
								*max_prec = PREC_TERM;
							j = 0;
							while (Lex(cc) == '(')
								j++;
							if (cc->token == TK_IDENT && (cc->hash_entry || cc->local_var_entry))
								ICAdd(cc, IC_IMM_I64, TRUE, cmp.internal_types[RT_I64]);
							else
								ICAdd(cc, IC_IMM_I64, FALSE, cmp.internal_types[RT_I64]);
							Lex(cc);
							while (j--)
							{
								if (cc->token != ')')
									LexExcept(cc, "Missing ')' at ");
								Lex(cc);
							}
							return PE_MAYBE_MODIFIERS;
					}
			}
	}
	LexExcept(cc, "Missing expression at ");
}

I64 ParseUnaryModifier(CCompCtrl *cc, CParseStack *ps, CMemberList **_local_var, CArrayDim **_tmpad, I64 *unary_post_prec)
{
	CHashClass			*tmpc, *tmpc1;
	CHashFun			*fun_ptr;
	CMemberList			*tmpm = *_local_var;
	CIntermediateCode	*tmpi, *tmpi1;
	CArrayDim			*tmpad1, tmpad2;
	CCodeMisc			*cm;
	I64					 mode, old_flags;
	Bool				 was_paren = Btr(&cc->flags, CCf_PAREN);

	*_local_var = NULL;
	switch (cc->token)
	{
		case '.':
			if (tmpm)
				tmpm->reg = REG_NONE;
			goto um_join;

		case TK_DEREFERENCE:
			tmpi = cc->coc.coc_head.last;
			if (!(cc->flags & (CCF_RAX | CCF_ARRAY)))
				ICAdd(cc, IC_DEREF + PREC_UNARY_PRE << 16, 0, tmpi->ic_class - 1);
			else
				tmpi->ic_class--;

				um_join:
			if (!*unary_post_prec)
				*unary_post_prec = PREC_TERM;
			tmpc = cc->coc.coc_head.last->ic_class;
			if ((!tmpc->ptr_stars_count || cc->flags & CCF_ARRAY) && cc->token == '.')
				LexExcept(cc, "Must be address, not value ");
			if (!(cc->flags & CCF_RAX))
				tmpc--;
			if (!(tmpc->type & HTT_CLASS))
				LexExcept(cc, "Invalid class at ");
			if (Lex(cc) != TK_IDENT || !(tmpm = MemberFind(cc->cur_str, tmpc)))
				LexExcept(cc, "Invalid member at ");
			else if (cc->local_var_entry)
				cc->local_var_entry->use_count--;
			Lex(cc);	//skip member name
			tmpc1 = tmpm->member_class + 1;
			ICAdd(cc, IC_IMM_I64, tmpm->offset, tmpc1);
			cc->flags &= ~(CCF_RAX | CCF_ARRAY | CCF_FUN_EXP);
			if (tmpm->dim.next)
			{
				*_tmpad = tmpm->dim.next;
				cc->flags |= CCF_ARRAY;
			}
			if (tmpm->flags & MLF_FUN)
			{
				ParsePopDeref(ps);
				ParsePush2(ps, tmpm->fun_ptr - tmpm->fun_ptr->ptr_stars_count);
				cc->flags |= CCF_FUN_EXP;
			}
			ICAdd(cc, IC_ADD, 0, tmpc1);
			return PE_UNARY_MODIFIERS;

		case '(':
			if (cc->flags & CCF_FUN_EXP)
			{
				if (!*unary_post_prec)
					*unary_post_prec = PREC_TERM;
				return ParseFunCall(cc, ps, TRUE, ParsePop2(ps));
			}
			if (!*unary_post_prec)
				*unary_post_prec = PREC_TERM;
			if (Lex(cc) != TK_IDENT)
				LexExcept(cc, "Invalid class at ");
			if (Btr(&cc->flags, CCf_FUN_EXP))
				ps->ptr2--;
			cc->flags &= ~CCF_ARRAY;
			tmpc = cc->hash_entry;
			Lex(cc);
			mode = PRS0_TYPECAST | PRS1_NULL;
			tmpc = ParseType(cc, &tmpc, &mode, NULL, NULL, &fun_ptr, NULL, &tmpad2, 0);
			if (fun_ptr)
			{
				ParsePopDeref(ps);
				Bts(&cc->flags, CCf_FUN_EXP);
				ParsePush2(ps, fun_ptr);
				cm=COCMiscNew(cc, CMT_HASH_ENTRY);
				cm->h = fun_ptr;
			}
			if (*_tmpad = tmpad2.next)
			{
				cc->flags |= CCF_ARRAY;
				tmpc++;
				cm = COCMiscNew(cc, CMT_ARRAY_DIM);
				cm->dim = *_tmpad;
			}
			if (!(cc->flags & (CCF_RAX | CCF_ARRAY)))
				tmpc++;
			tmpi = cc->coc.coc_head.last;
			tmpi->ic_class = tmpc;
			ICAdd(cc, IC_HOLYC_TYPECAST, was_paren, tmpc);
			if (cc->token != ')')
				LexExcept(cc, "Missing ')' at ");
			Lex(cc);
			return PE_UNARY_MODIFIERS;

		case '[':
			if (!*unary_post_prec)
				*unary_post_prec = PREC_TERM;
			Lex(cc);
			tmpc = OptClassFwd(cc->coc.coc_head.last->ic_class);
			if (!tmpc->ptr_stars_count)
				LexExcept(cc, "Not array or ptr ");
			if (!(cc->flags & (CCF_ARRAY | CCF_RAX)))
			{
				tmpc = OptClassFwd(tmpc - 1);
				if (!tmpc->ptr_stars_count)
					LexExcept(cc, "Not array or ptr ");
				ICAdd(cc, IC_DEREF + PREC_UNARY_PRE << 16, 0, tmpc);
			}
			tmpc1 = tmpc - 1;
			if (tmpad1 = *_tmpad)
			{
				ICAdd(cc, IC_IMM_I64, tmpad1->total_count * tmpc1->size, tmpc);
				if (*_tmpad = tmpad1->next)
				{
					old_flags = cc->flags;
					if (!ParseExpression(cc, NULL, FALSE, ps))
						throw('Compiler');
					cc->flags = cc->flags & ~CCF_FUN_EXP | old_flags & CCF_FUN_EXP;
					if (cc->token != ']')
						LexExcept(cc, "Missing ']' at ");
					Lex(cc); //skip ]
					tmpi1 = cc->coc.coc_head.last;
					tmpi1->ic_flags |= ICF_RES_TO_INT;
					ICAdd(cc, IC_MUL, 0, tmpc);
					ICAdd(cc, IC_ADD, 0, tmpc);
					cc->flags |= CCF_RAX;
					return PE_UNARY_MODIFIERS;
				}
			}
			else
				ICAdd(cc, IC_IMM_I64, tmpc1->size, tmpc);
			old_flags = cc->flags;
			if (!ParseExpression(cc, NULL, FALSE, ps))
				throw('Compiler');
			cc->flags = cc->flags & ~CCF_FUN_EXP | old_flags & CCF_FUN_EXP;
			if (cc->token != ']')
				LexExcept(cc,"Missing ']' at ");
			Lex(cc); //skip ]
			tmpi1 = cc->coc.coc_head.last;
			tmpi1->ic_flags |= ICF_RES_TO_INT;
			ICAdd(cc, IC_MUL, 0, tmpc);
			ICAdd(cc, IC_ADD, 0, tmpc);
			cc->flags &= ~(CCF_RAX | CCF_ARRAY);
			return PE_UNARY_MODIFIERS;
		start:
			case TK_PLUS_PLUS:
				cc->flags |= CCF_POSTINC;
				break;

			case TK_MINUS_MINUS:
				cc->flags |= CCF_POSTDEC;
				break;
		end:
			if (!*unary_post_prec)
				*unary_post_prec = PREC_UNARY_POST;
			Lex(cc);
			return PE_DEREFERENCE;
	}

	return PE_DEREFERENCE;
}

U8 *LexExpression2Bin(CCompCtrl *cc, I64 *_type=NULL)
{//Compile cc expression. You call the code.
	U8	*res;
	I64	 size;
	Bool old_trace = Btr(&cc->flags, CCf_PASS_TRACE_PRESENT);

	COCPush(cc);
	COCInit(cc);
	if (ParseExpression(cc, NULL, FALSE))
	{
		ICAdd(cc, IC_RETURN_VAL, 0, 0);
		ICAdd(cc, IC_RET, 0, 0);
		res = COCCompile(cc, &size, NULL, _type);
	}
	else
		res = NULL;
	COCPop(cc);
	BEqual(&cc->flags, CCf_PASS_TRACE_PRESENT, old_trace);

	return res;
}

Bool IsLexExpression2Bin(CCompCtrl *cc, U8 **_machine_code)
{//Compile cc expression to bin. Return error status.
	return ToBool(*_machine_code = LexExpression2Bin(cc));
}

I64 LexExpressionI64(CCompCtrl *cc)
{//Compile cc expression, forcing to I64 and eval.
	U8 *machine_code;
	I64 res, type;

	if (machine_code = LexExpression2Bin(cc, &type))
	{
		res = Call(machine_code);
		Free(machine_code);
		if (type == RT_F64)
			res = ToI64(res(F64));
	}
	else
		res = 0;

	return res;
}

F64 LexExpressionF64(CCompCtrl *cc)
{//Compile cc expression, forcing to F64 and eval.
	U8 *machine_code;
	I64 res, type;

	if (machine_code = LexExpression2Bin(cc, &type))
	{
		res = Call(machine_code);
		Free(machine_code);
		if (type != RT_F64)
			res(F64) = ToF64(res);
	}
	else
		res = 0;

	return res(F64);
}

I64 LexExpression(CCompCtrl *cc)
{//Compile cc expression and eval.	Might be I64 or F64.
	U8 *machine_code;
	I64 res;

	if (machine_code = LexExpression2Bin(cc))
	{
		res = Call(machine_code);
		Free(machine_code);
	}
	else
		res = 0;

	return res;
}
