mirror of https://github.com/minexew/Shrine.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1178 lines
32 KiB
1178 lines
32 KiB
#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; |
|
}
|
|
|