#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 ZealOS 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;
}