1179 lines
32 KiB
HolyC
Executable File
1179 lines
32 KiB
HolyC
Executable File
#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 *PrsAddOp(CCmpCtrl *cc,I64 stk_op,CHashClass *tmpc)
|
|
{
|
|
CIntermediateCode *tmpi=cc->coc.coc_head.last;
|
|
Bool div_sizeof=FALSE;
|
|
switch (stk_op.u16[0]) {
|
|
case IC_ADD:
|
|
if (tmpc->ptr_stars_cnt && !tmpi->ic_class->ptr_stars_cnt &&
|
|
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_cnt && tmpi->ic_class->raw_type!=RT_F64) {
|
|
if (!tmpi->ic_class->ptr_stars_cnt) {
|
|
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_cnt) {
|
|
ICAdd(cc,IC_SIZEOF,1,cmp.internal_types[RT_I64]);
|
|
ICAdd(cc,IC_MUL,0,cmp.internal_types[RT_I64]);
|
|
}
|
|
break;
|
|
}
|
|
tmpi=ICAdd(cc,stk_op,0,tmpc);
|
|
if (stk_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 PrsExpression2(CCmpCtrl *cc,I64 *_max_prec,CPrsStk *ps)
|
|
{
|
|
I64 i,cur_op,stk_op,state,max_prec=PREC_NULL,unary_pre_prec,paren_prec,
|
|
unary_post_prec,left_prec=PREC_MAX;
|
|
CIntermediateCode *tmpi;
|
|
CHashClass *tmpc;
|
|
CMemberLst *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=PrsUnaryTerm(cc,ps,&local_var,&tmpad,
|
|
&max_prec,&unary_pre_prec,&paren_prec);
|
|
break;
|
|
case PE_UNARY_MODIFIERS:
|
|
state=PrsUnaryModifier(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=PrsUnaryModifier(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:
|
|
stk_op=PrsPop(ps);
|
|
tmpc=PrsPop(ps);
|
|
if (!(0<stk_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 &&
|
|
stk_op.u16[0]==IC_UNARY_MINUS) {
|
|
Lex(cc); //skip ` op
|
|
left_prec=cur_op.i8[2];
|
|
PrsPush(ps,tmpc);
|
|
PrsPush(ps,stk_op);
|
|
PrsPush(ps,cc->coc.coc_head.last->ic_class);
|
|
PrsPush(ps,cur_op);
|
|
goto pe_unary_term1;
|
|
} else {
|
|
tmpi=cc->coc.coc_head.last;
|
|
tmpc=tmpi->ic_class;
|
|
if (stk_op.u16[0]==IC_DEREF && tmpc->ptr_stars_cnt)
|
|
tmpc--;
|
|
else if (stk_op.u16[0]==IC_ADDR) {
|
|
cc->abs_cnts.c_addres++;
|
|
if (intermediate_code_table[tmpi->ic_code].type==IST_DEREF)
|
|
OptFree(tmpi);
|
|
tmpc++;
|
|
}
|
|
tmpc=OptClassFwd(tmpc);
|
|
if (stk_op)
|
|
ICAdd(cc,stk_op,0,tmpc);
|
|
goto pe_check_binary_ops2;
|
|
}
|
|
|
|
case PE_DO_BINARY_OP:
|
|
pe_do_binary_op:
|
|
PrsPush(ps,tmpc);
|
|
PrsPush(ps,stk_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_cnt &&
|
|
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_cnt && !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:
|
|
stk_op=PrsPop(ps); //pop ops of higher prec
|
|
tmpc=PrsPop(ps);
|
|
if (!stk_op)
|
|
goto pe_push_lower;
|
|
else if (cur_op.u8[2]&~ASSOC_MASK==stk_op.u8[2]&~ASSOC_MASK) {
|
|
if (cur_op.u8[2]&ASSOCF_RIGHT)
|
|
goto pe_push_lower;
|
|
} else if (cur_op.u8[2]&~ASSOC_MASK<=stk_op.u8[2]&~ASSOC_MASK)
|
|
goto pe_push_lower;
|
|
|
|
tmpi=PrsAddOp(cc,stk_op,tmpc);
|
|
|
|
if (intermediate_code_table[cur_op.u16[0]].type==IST_CMP &&
|
|
intermediate_code_table[stk_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:
|
|
PrsPush(ps,tmpc);
|
|
PrsPush(ps,stk_op);
|
|
PrsPush(ps,cc->coc.coc_head.last->ic_class);
|
|
PrsPush(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:
|
|
stk_op=PrsPop(ps);
|
|
tmpc=PrsPop(ps);
|
|
if (!stk_op.u16[0])
|
|
goto pe_done;
|
|
PrsAddOp(cc,stk_op,tmpc);
|
|
goto pe_pop_all2;
|
|
}
|
|
}
|
|
pe_done:
|
|
if (_max_prec)
|
|
*_max_prec=max_prec;
|
|
}
|
|
|
|
Bool PrsExpression(CCmpCtrl *cc,I64 *_max_prec,Bool end_exp,CPrsStk *_ps=NULL)
|
|
{
|
|
Bool res=TRUE;
|
|
I64 old_flags=cc->flags;
|
|
CPrsStk *ps;
|
|
if (_ps)
|
|
ps=_ps;
|
|
else {
|
|
ps=MAlloc(sizeof(CPrsStk));
|
|
ps->ptr=0;
|
|
ps->ptr2=0;
|
|
}
|
|
PrsPush(ps,0); //terminate
|
|
PrsPush(ps,0); //terminate
|
|
try
|
|
//try catch causes noreg vars in function
|
|
PrsExpression2(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 PrsSizeOf(CCmpCtrl *cc)
|
|
{
|
|
CHashClass *tmpc;
|
|
CMemberLst *tmpm;
|
|
CDbgInfo *dbg_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_cnt;
|
|
if (Lex(cc)=='.')
|
|
goto pu_sizeof_member;
|
|
} else {
|
|
if (!(tmpc=cc->hash_entry) || !(tmpc->type &
|
|
(HTT_CLASS|HTT_INTERNAL_TYPE|HTT_GLBL_VAR|
|
|
HTT_FUN|HTT_EXPORT_SYS_SYM)))
|
|
LexExcept(cc,"Invalid class at ");
|
|
if (tmpc->type&(HTT_FUN|HTT_EXPORT_SYS_SYM)) {
|
|
if (!(dbg_info=tmpc(CHashFun *)->dbg_info))
|
|
LexExcept(cc,"Size not defined at ");
|
|
i=dbg_info->body[dbg_info->max_line+1-dbg_info->min_line]
|
|
-dbg_info->body[0];
|
|
Lex(cc);
|
|
} else {
|
|
i=tmpc->size;
|
|
while (Lex(cc)=='.') {
|
|
pu_sizeof_member:
|
|
if (!(tmpc->type & (HTT_CLASS|HTT_GLBL_VAR)))
|
|
LexExcept(cc,"Invalid class at ");
|
|
else if (tmpc->type & HTT_GLBL_VAR)
|
|
tmpc=tmpc(CHashGlblVar *)->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_cnt--;
|
|
tmpc=tmpm->member_class;
|
|
//Probably others like this:
|
|
#assert offset(CHashClass.size)==offset(CHashGlblVar.size)
|
|
i=tmpc->size*tmpm->dim.total_cnt;
|
|
}
|
|
}
|
|
}
|
|
if (cc->token=='*') {
|
|
while (Lex(cc)=='*');
|
|
i=sizeof(U8 *);
|
|
}
|
|
ICAdd(cc,IC_IMM_I64,i,cmp.internal_types[RT_I64]);
|
|
}
|
|
|
|
U0 PrsOffsetOf(CCmpCtrl *cc)
|
|
{
|
|
CHashClass *tmpc;
|
|
CMemberLst *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_GLBL_VAR)))
|
|
LexExcept(cc,"Invalid class at ");
|
|
else if (tmpc->type & HTT_GLBL_VAR)
|
|
tmpc=tmpc(CHashGlblVar *)->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_cnt--;
|
|
i+=tmpm->offset;
|
|
tmpc=tmpm->member_class;
|
|
} while (Lex(cc)=='.');
|
|
ICAdd(cc,IC_IMM_I64,i,cmp.internal_types[RT_I64]);
|
|
}
|
|
|
|
I64 PrsFunCall(CCmpCtrl *cc,CPrsStk *ps,Bool indirect,CHashFun *tmpf)
|
|
{
|
|
I64 i,argc_cnt,dft_val;
|
|
Bool is_first_arg=TRUE,needs_right_paren,is_print,is_putchars,
|
|
is_template_fun;
|
|
CHashClass *tmpc2,*last_class=NULL;
|
|
CMemberLst *tmpm;
|
|
CCodeCtrl *tmpcbh,*tmpcbh1;
|
|
CCodeMisc *cm;
|
|
CIntermediateCode *tmpi;
|
|
|
|
if (!tmpf) {
|
|
if (cc->token==TK_CHAR_CONST) {
|
|
if (!(tmpf=HashFind("PutChars",cc->htc.hash_table_lst,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_lst,HTT_FUN)))
|
|
LexExcept(cc,"Missing header for Print() and PutChars() at ");
|
|
if (!*cc->cur_str) //empty string signals Print with variable fmt_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_SET_RAX,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_cnt;
|
|
tmpm=tmpf->member_lst_and_root;
|
|
argc_cnt=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_DFT_AVAILABLE &&
|
|
(cc->token==')' || cc->token==',' || !needs_right_paren)) {
|
|
dft_val=tmpm->dft_val;
|
|
if (tmpm->flags & MLF_LASTCLASS && last_class)
|
|
dft_val=(last_class-last_class->ptr_stars_cnt)->str;
|
|
if (tmpm->flags & (MLF_STR_DFT_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(dft_val)+1;
|
|
cm->str=StrNew(dft_val);
|
|
cc->flags|=CCF_HAS_MISC_DATA;
|
|
} else
|
|
ICAdd(cc,IC_IMM_I64,dft_val,tmpm->member_class);
|
|
} else {
|
|
if (!PrsExpression(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 (!PrsExpression(cc,NULL,FALSE,ps))
|
|
throw('Compiler');
|
|
COCPush(cc);
|
|
is_first_arg=FALSE;
|
|
argc_cnt++;
|
|
} 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 (!PrsExpression(cc,NULL,FALSE,ps))
|
|
throw('Compiler');
|
|
COCPush(cc);
|
|
is_first_arg=FALSE;
|
|
argc_cnt++;
|
|
} while (cc->token==',');
|
|
}
|
|
}
|
|
tmpi->ic_data=argc_cnt++; //++ 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_cnt+tmpf->arg_cnt)<<3,tmpf->return_class);
|
|
else if (Bt(&tmpf->flags,Cf_EXTERN)) {
|
|
cc->abs_cnts.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_cnt+tmpf->arg_cnt)<<3,tmpf->return_class);
|
|
ICAdd(cc,IC_ADD_RSP,8,tmpf->return_class);
|
|
} else
|
|
ICAdd(cc,IC_ADD_RSP1,(argc_cnt+tmpf->arg_cnt)<<3,tmpf->return_class);
|
|
} else {
|
|
if (indirect)
|
|
argc_cnt++;
|
|
ICAdd(cc,IC_ADD_RSP,(argc_cnt+tmpf->arg_cnt)<<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 PrsUnaryTerm(CCmpCtrl *cc,CPrsStk *ps,CMemberLst **_local_var,
|
|
CArrayDim **_tmpad,I64 *max_prec,I64 *unary_pre_prec,I64 *paren_prec)
|
|
{
|
|
I64 i,j;
|
|
CHashExport *tmpex;
|
|
CHashClass *tmpc;
|
|
CHashFun *tmpf;
|
|
CHashGlblVar *tmpg;
|
|
CMemberLst *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_lst,
|
|
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_cnts.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_cnts.abs_addres++;
|
|
} else
|
|
ICAdd(cc,IC_IMM_I64,
|
|
tmpf->exe_addr,cmp.internal_types[RT_PTR]);
|
|
}
|
|
cc->abs_cnts.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_cnts.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:
|
|
PrsPush(ps,tmpc);
|
|
PrsPush(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_cnts.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 TempleOS postfix typecasting at ");
|
|
else {
|
|
if (PREC_TERM>*max_prec)
|
|
*max_prec=PREC_TERM;
|
|
if (cc->lex_include_stk->flags&LFSF_DEFINE)
|
|
paren_warn=FALSE;
|
|
else
|
|
paren_warn=TRUE;
|
|
if (!PrsExpression(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)) {
|
|
PrsPopDeref(ps);
|
|
cc->flags|=CCF_FUN_EXP;
|
|
PrsPush2(ps,tmpm->fun_ptr-tmpm->fun_ptr->ptr_stars_cnt);
|
|
}
|
|
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_GLBL,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=PrsPop(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 &&
|
|
StrCmp(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_lst &&
|
|
*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.glbl_hash_table);
|
|
else
|
|
HashAdd(tmpex,cc->htc.glbl_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_cnts.abs_addres++;
|
|
if (tmpex->type & HTF_UNRESOLVED) {
|
|
if (!(cc->flags&CCF_ASM_EXPRESSIONS))
|
|
LexExcept(cc,"Illegal fwd 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_cnts.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 PrsFunCall(cc,ps,FALSE,tmpex);
|
|
case HTt_GLBL_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_GLBL,tmpg->heap_glbl,tmpc);
|
|
else
|
|
ICAdd(cc,IC_ABS_ADDR,tmpg->data_addr_rip,tmpc);
|
|
}
|
|
}
|
|
} else {
|
|
if (tmpg->flags & GVF_EXTERN) {
|
|
cc->abs_cnts.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) {
|
|
PrsPopDeref(ps);
|
|
cc->flags|=CCF_FUN_EXP;
|
|
PrsPush2(ps,tmpg->fun_ptr-tmpg->fun_ptr->ptr_stars_cnt);
|
|
}
|
|
return PE_UNARY_MODIFIERS;
|
|
case HTt_CLASS:
|
|
PrsOffsetOf(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++;
|
|
PrsSizeOf(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++;
|
|
PrsOffsetOf(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 PrsUnaryModifier(CCmpCtrl *cc,CPrsStk *ps,CMemberLst **_local_var,
|
|
CArrayDim **_tmpad,I64 *unary_post_prec)
|
|
{
|
|
CHashClass *tmpc,*tmpc1;
|
|
CHashFun *fun_ptr;
|
|
CMemberLst *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_cnt || 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_cnt--;
|
|
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) {
|
|
PrsPopDeref(ps);
|
|
PrsPush2(ps,tmpm->fun_ptr-tmpm->fun_ptr->ptr_stars_cnt);
|
|
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 PrsFunCall(cc,ps,TRUE,PrsPop2(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=PrsType(cc,&tmpc,&mode,NULL,NULL,&fun_ptr,NULL,&tmpad2,0);
|
|
if (fun_ptr) {
|
|
PrsPopDeref(ps);
|
|
Bts(&cc->flags,CCf_FUN_EXP);
|
|
PrsPush2(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_cnt)
|
|
LexExcept(cc,"Not array or ptr ");
|
|
if (!(cc->flags & (CCF_ARRAY | CCF_RAX))) {
|
|
tmpc=OptClassFwd(tmpc-1);
|
|
if (!tmpc->ptr_stars_cnt)
|
|
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_cnt*tmpc1->size,tmpc);
|
|
if (*_tmpad=tmpad1->next) {
|
|
old_flags=cc->flags;
|
|
if (!PrsExpression(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 (!PrsExpression(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(CCmpCtrl *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 (PrsExpression(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);
|
|
BEqu(&cc->flags,CCf_PASS_TRACE_PRESENT,old_trace);
|
|
return res;
|
|
}
|
|
|
|
Bool IsLexExpression2Bin(CCmpCtrl *cc,U8 **_machine_code)
|
|
{//Compile cc expression to bin. Return err status.
|
|
return ToBool(*_machine_code=LexExpression2Bin(cc));
|
|
}
|
|
|
|
I64 LexExpressionI64(CCmpCtrl *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(CCmpCtrl *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(CCmpCtrl *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;
|
|
}
|