LTextern CP_PRSPUSH void PrsPush(ParseStack *ps,I8 val); LTextern CP_PRSPOP I8 PrsPop(ParseStack *ps); #define PRST_UNARY_TERM 0 #define PRST_UNARY_MODIFIERS 1 #define PRST_DEREFERRENCE 2 #define PRST_CHECK_BINARY_OPS 3 BoolU8 PrsParseExpression(LexStruct *lx,BoolU4 end_exp=FALSE) { BoolU4 result=TRUE,question_clause=FALSE, cont_unary,cont_check_binary_ops,is_lower; I8 i,j,k; IntermediateCode *tempi,*tempi_first=lx->cb.cb_out_ptr,*tempi2; ClassStruct *tempc; ParseStack *ps=MAlloc(sizeof(ParseStack)); MemberListStruct *local_var; ArrayDimStruct *tempad=NULL; ps->ptr=0; PrsPush(ps,0); //terminate PrsPush(ps,0); //terminate try { do { lx->flags&=~(LF_PREINC+LF_PREDEC+LF_POSTINC+LF_POSTDEC+LF_FUNCTION); do i=PrsUnaryTerm(lx,ps,&local_var,&tempad); while (i==PRST_UNARY_TERM); while (i==PRST_UNARY_MODIFIERS) i=PrsUnaryModifier(lx,ps,&local_var,&tempad); if (i==PRST_DEREFERRENCE) PrsDereferrence(lx,ps); //Check for binary Ops do { i=PrsPop(ps); tempc=PrsPop(ps); if (i && i.u1[2]<=1) { tempi=lx->cb.cb_last_out_ptr; i=i.u2[0]; tempc=tempi->ic_class; if (Bt(deref_bitmap,i) && tempc->ptr_cnt) { tempc-=sizeof(ClassStruct); while (tempc->return_class) tempc=tempc->return_class; i=EC_DEREF+0x10000; } else { if (i==EC_ADDRESS) { if (!(lx->flags & (LF_RAX|LF_ARRAY))) { j=tempi->ic_opcode; if (!Bt(deref_bitmap,j)) PrsExcept(lx,"ST_INVALID_LVALUE"); tempi->ic_opcode=EC_NOP; tempc+=sizeof(ClassStruct); } } } CbAddIc(lx,i,0,tempc); cont_check_binary_ops=TRUE; } else { PrsPush(ps,tempc); PrsPush(ps,i); i=lx->token; k=binary_ops_table[i]; if (k.u2[0]==EC_AND_AND || k.u2[0]==EC_OR_OR) CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]); if (k.u2[0]==EC_QUESTION) question_clause=TRUE; else if (k.u2[0]==EC_COLON) { if (!question_clause) k=0; else question_clause=FALSE; } if (!k.u1[2]) { cont_check_binary_ops=FALSE; cont_unary=FALSE; //DONE } else { Lex(lx); //skip op if (Bt(assign_bitmap,k.u2[0])) { tempi=lx->cb.cb_last_out_ptr; tempc=tempi->ic_class; j=tempi->ic_opcode; if (!Bt(deref_bitmap,j)) PrsExcept(lx,"ST_INVALID_LVALUE"); tempi->ic_opcode=EC_NOP; while (tempc->return_class) tempc=tempc->return_class; k.u1[2]=0x10; } do { i=PrsPop(ps); //pop ops of higher prec tempc=PrsPop(ps); is_lower=FALSE; if (i) { if (k.u1[2]==i.u1[2]) { if (!Bt(assign_bitmap,k.u2[0]) || !Bt(assign_bitmap,i.u2[0])) is_lower=TRUE; } else if (k.u1[2]>i.u1[2]) is_lower=TRUE; } if (is_lower) { if (i.u2[0]==EC_AND_AND || i.u2[0]==EC_OR_OR) CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]); CbAddIc(lx,i,0,tempc); tempi2=lx->cb.cb_last_out_ptr; if (i.u1[3]&ECF_HAS_PUSH_CMP) { tempi2->ic_flags|=ICF_POP_CMP; CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]); CbAddIc(lx,EC_AND_AND,0,sys_internal_types[IT_I8]); tempi=lx->cb.cb_last_out_ptr; tempi->ic_flags|=ICF_POP_CMP; } if (Bt(cmp_bitmap,k.u2[0]) && Bt(cmp_bitmap,i.u2[0])) { tempi2->ic_flags|=ICF_PUSH_CMP; CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]); CbAddIc(lx,EC_PUSH_CMP,0,tempc); k.u1[3]|=ECF_HAS_PUSH_CMP; } else if (k.u2[0]==EC_AND_AND || k.u2[0]==EC_OR_OR) CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]); } else { PrsPush(ps,tempc); PrsPush(ps,i); tempi=lx->cb.cb_last_out_ptr; tempc=tempi->ic_class; PrsPush(ps,tempc); PrsPush(ps,k); cont_check_binary_ops=FALSE; cont_unary=TRUE; break; } } while (TRUE); } } } while (cont_check_binary_ops); } while (cont_unary); while (TRUE) { i=PrsPop(ps); tempc=PrsPop(ps); if (i) { if (i.u2[0]==EC_AND_AND || i.u2[0]==EC_OR_OR) CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]); CbAddIc(lx,i,0,tempc); if (i.u1[3]&ECF_HAS_PUSH_CMP) { tempi=lx->cb.cb_last_out_ptr; tempi->ic_flags|=ICF_POP_CMP; CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]); CbAddIc(lx,EC_AND_AND,0,sys_internal_types[IT_I8]); tempi=lx->cb.cb_last_out_ptr; tempi->ic_flags|=ICF_POP_CMP; } } else break; } } catch { if (Fs->except_argc>0) { if (Fs->except_argv[0]==EXCEPT_COMPILER) { lx->statement_cnt=0; lx->braces_cnt=0; result=FALSE; Fs->catch_except=TRUE; } } } Free(ps); if (end_exp && result) CbAddIc(lx,EC_END_EXP,0,0); return result; } U8 PrsUnaryTerm(LexStruct *lx,ParseStack *ps,MemberListStruct **local_var,ArrayDimStruct **tempad) { I8 i,*i_ptr; I8 argc_cnt,size; U8 d; SysHashEntry *temph; ClassStruct *tempc,*tempc1,*tempc2; GlblVarStruct *tempg; MemberListStruct *tempm; LexUndefEntry *templu; CbMiscStruct *tempmc; IntermediateCode *tempi; BoolU4 needs_right_paren,is_first_param; LexCbStack *templ,*templ1; *local_var=NULL; switch (lx->token) { case TK_INTEGER: if (lx->cur_i<0) CbAddIc(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_U8]); else CbAddIc(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_I8]); Lex(lx); return PRST_CHECK_BINARY_OPS; case TK_DOUBLE: i_ptr=&lx->cur_d; CbAddIc(lx,EC_DOUBLE,*i_ptr,sys_internal_types[IT_DOUBLE]); Lex(lx); return PRST_CHECK_BINARY_OPS; case TK_STR: d=LexExtendStr(lx,&size); if (lx->flags & LF_ASM_EXPRESSIONS) CbAddIc(lx,EC_IMM,d,sys_internal_types[IT_I1]+sizeof(ClassStruct)); else { tempmc=CbMiscNew(lx,CBMT_STR_CONST); CbAddIc(lx,EC_STR_CONST,tempmc,sys_internal_types[IT_I1]+sizeof(ClassStruct)); tempmc->st_len=size; tempmc->str=d; lx->flags|=LF_HAS_MISC_DATA; } return PRST_CHECK_BINARY_OPS; case TK_INSERT_BINARY: d=lx->ident; size=lx->ident_len; lx->ident=NULL; Lex(lx); if (lx->flags & LF_ASM_EXPRESSIONS) CbAddIc(lx,EC_IMM,d,sys_internal_types[IT_I1]+sizeof(ClassStruct)); else { tempmc=CbMiscNew(lx,CBMT_STR_CONST); CbAddIc(lx,EC_STR_CONST,tempmc,sys_internal_types[IT_I1]+sizeof(ClassStruct)); tempmc->st_len=size; tempmc->str=d; lx->flags|=LF_HAS_MISC_DATA; } return PRST_CHECK_BINARY_OPS; case TK_INSERT_BINARY_TYPE: case TK_INSERT_BINARY_SIZE: CbAddIc(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_U8]); Lex(lx); return PRST_CHECK_BINARY_OPS; case '(': Lex(lx); //Skip ( if (!PrsParseExpression(lx)) throw(EXCEPT_COMPILER,2); if (lx->token!=')') PrsExcept(lx,"ST_MISSING_RIGHT_PAREN"); Lex(lx); //skip ) lx->flags=(lx->flags & ~(LF_ARRAY+LF_FUNCTION)) | LF_RAX; return PRST_UNARY_MODIFIERS; } i=unary_ops_table[lx->token]; if (i.u1[2]) { Lex(lx); //Skip op if (i.u2[0]==EC_ADDRESS && lx->token==TK_IDENT) { if (tempc=lx->hash_entry) { if (tempc->type & HTT_FUNCTION) { if (!Bt(&tempc->flags,Cf_INTERNAL)) { Lex(lx); //skip fun name if (Bt(&tempc->flags,Cf_EXTERN)) { if (lx->a) PrsExcept(lx,"ST_ADDRESS_EXTERN"); else CbAddIc(lx,EC_IMM, &tempc->executable_address,sys_internal_types[IT_PTR]); CbAddIc(lx,EC_DEREF,0, sys_internal_types[IT_PTR]); } else { if (lx->a) CbAddIc(lx,EC_ABSOLUTE_ADDRESS, tempc->executable_address,sys_internal_types[IT_PTR]); else CbAddIc(lx,EC_IMM, tempc->executable_address,sys_internal_types[IT_PTR]); } return PRST_CHECK_BINARY_OPS; } } } } PrsPush(ps,tempc); PrsPush(ps,i); return PRST_UNARY_TERM; } if (lx->token=='+') { Lex(lx); return PRST_UNARY_TERM; } if (lx->token!=TK_IDENT) { if (lx->token==TK_PLUS_PLUS) { Lex(lx); lx->flags|=LF_PREINC; return PRST_UNARY_TERM; } if (lx->token==TK_MINUS_MINUS) { Lex(lx); lx->flags|=LF_PREDEC; return PRST_UNARY_TERM; } if (lx->token=='$$' && lx->flags & LF_ASM_EXPRESSIONS) { Lex(lx); CbAddIc(lx,EC_IMM,lx->instruction_pointer,sys_internal_types[IT_I8]); return PRST_CHECK_BINARY_OPS; } PrsExcept(lx,"ST_MISSING_EXPRESSION"); } if (tempm=lx->local_var_entry) { lx->flags&=~(LF_RAX+LF_ARRAY+LF_FUNCTION); tempc=tempm->member_class+sizeof(ClassStruct); if (tempm->flags & MLF_FUNCTION) { lx->flags|=LF_FUNCTION; PrsPush(ps,tempm->return_class); PrsPush(ps,tempm->parameter_cnt); } if (tempm->cnt) { *tempad=tempm->dim_list; lx->flags|=LF_ARRAY; tempc+=sizeof(ClassStruct); } CbAddIc(lx,EC_RBP,0,tempc); CbAddIc(lx,EC_IMM,tempm->offset,tempc); CbAddIc(lx,EC_ADD,0,tempc); Lex(lx); //skip var name *local_var=tempm; return PRST_UNARY_MODIFIERS; } if (!(temph=lx->hash_entry)) { if (!(lx->flags & LF_ASM_EXPRESSIONS)) PrsExcept(lx,"ST_INVALID_LVALUE"); temph=MAllocZ(sizeof(SysHashEntry)); temph->str=lx->ident; lx->ident=NULL; temph->use_cnt=0; SetSourceFileInfo(lx,temph); temph->user_data0=0; if (temph->str[0]=='@' && temph->str[1]=='@') { temph->type=HTT_SYS_SYMBOL | HTT_UNRESOLVED_LOCAL; AddSysHashEntry(temph,lx->local_hash_table); } else { temph->type=HTT_SYS_SYMBOL | HTT_UNRESOLVED_GLBL; AddSysHashEntry(temph,lx->glbl_hash_table); } } if (temph->type & HTT_SYS_SYMBOL) { if (!(temph->type & HTT_LITERAL) && !(temph->type & HTT_IMPORT)) lx->absolute_address_cnt++; if (temph->type & (HTT_UNRESOLVED_LOCAL|HTT_UNRESOLVED_GLBL)) { templu=MAlloc(sizeof(LexUndefEntry)); templu->hash=temph; templu->next=lx->undef_hash_entry; lx->undef_hash_entry=templu; if (temph->type & HTT_UNRESOLVED_LOCAL) lx->flags|=LF_UNRESOLVED_LOCAL; else lx->flags|=LF_UNRESOLVED_GLBL; CbAddIc(lx,EC_IMM,&temph->user_data0,sys_internal_types[IT_PTR]); CbAddIc(lx,EC_DEREF,0,sys_internal_types[IT_PTR]); } else { if (lx->a && !(temph->type & HTT_LITERAL)) CbAddIc(lx,EC_ABSOLUTE_ADDRESS,temph->user_data0,sys_internal_types[IT_PTR]); else CbAddIc(lx,EC_IMM,temph->user_data0,sys_internal_types[IT_PTR]); } Lex(lx); return PRST_CHECK_BINARY_OPS; } if (temph->type & HTT_FUNCTION) { is_first_param=TRUE; Lex(lx); //skip fun name CbPush(lx); templ=lx->cb.cb_next; lx->cb.cb_next=NULL; tempc=temph; i=tempc->parameter_cnt; tempm=tempc->member_list; argc_cnt=0; if (lx->token!='(') needs_right_paren=FALSE; else { Lex(lx); needs_right_paren=TRUE; } while (i--) { if (lx->token==',') Lex(lx); else if (!is_first_param && lx->token!=')') PrsExcept(lx,"ST_EXPECTING_COMMA"); CbInitOutPtrs(&lx->cb); if (tempm->flags & MLF_DEFAULT_AVAILABLE && (lx->token==')' || !needs_right_paren)) CbAddIc(lx,EC_IMM,tempm->default_value,tempm->member_class); else if (!PrsParseExpression(lx)) throw(EXCEPT_COMPILER,3); else { is_first_param=FALSE; CbPush(lx); CbAddIc(lx,EC_NULL,0,0); tempi=CmpOptPass1(lx,NULL,FALSE); CbPop(lx); tempc1=tempi->ic_class; while (tempc1->return_class) tempc1=tempc1->return_class; tempc2=tempm->member_class; while (tempc2->return_class) tempc2=tempc2->return_class; if (tempc2->sub_type==IT_DOUBLE && tempc1->sub_type!=IT_DOUBLE) tempi->ic_flags|=ICF_R_TO_DOUBLE; else if (tempc2->sub_type!=IT_DOUBLE && tempc1->sub_type==IT_DOUBLE) tempi->ic_flags|=ICF_R_TO_INT; } CbAddIc(lx,EC_NULL,0,0); CbPush(lx); tempm=tempm->next; } if (tempm && tempm->flags & MLF_DOT_DOT_DOT) { CbInitOutPtrs(&lx->cb); CbAddIc(lx,EC_IMM,0,tempm->member_class); tempi=lx->cb.cb_last_out_ptr; CbAddIc(lx,EC_NULL,0,0); CbPush(lx); if (needs_right_paren) { if (lx->token!=')') { do { if (lx->token==',') Lex(lx); else if (!is_first_param) PrsExcept(lx,"ST_EXPECTING_COMMA"); CbInitOutPtrs(&lx->cb); if (!PrsParseExpression(lx)) throw(EXCEPT_COMPILER,4); is_first_param=FALSE; CbAddIc(lx,EC_NULL,0,0); CbPush(lx); argc_cnt++; } while (lx->token==','); } } tempi->ic_data=argc_cnt++; //++ so add_esp latter works } if (needs_right_paren) { if (lx->token!=')') PrsExcept(lx,"ST_MISSING_RIGHT_PAREN"); Lex(lx); } templ1=templ->cb_next; templ->cb_next=lx->cb.cb_next; lx->cb.cb_next=templ; CbPop(lx); templ=lx->cb.cb_next; lx->cb.cb_next=templ1; CbAddIc(lx,EC_CALL_START,tempc,0); while (templ) { templ1=templ->cb_next; CbAppend(lx,templ); if (!Bt(&tempc->flags,Cf_INTERNAL)) lx->cb.cb_last_out_ptr->ic_flags|=ICF_PUSH_RESULT; templ=templ1; } if (Bt(&tempc->flags,Cf_INTERNAL)) CbAddIc(lx,tempc->executable_address,0,tempc->return_class); else if (Bt(&tempc->flags,Cf_EXTERN)) { if (lx->a) { if (tempc->type&HTT_IMPORT) CbAddIc(lx,EC_CALL_INDIRECT2,tempc->executable_address,tempc->return_class); else CbAddIc(lx,EC_CALL_EXTERN,tempc,tempc->return_class); } else CbAddIc(lx,EC_CALL_INDIRECT2,&tempc->executable_address,tempc->return_class); CbAddIc(lx,EC_ADD_RSP,(argc_cnt+tempc->parameter_cnt)<<3,tempc->return_class); } else { CbAddIc(lx,EC_CALL,tempc->executable_address,tempc->return_class); CbAddIc(lx,EC_ADD_RSP,(argc_cnt+tempc->parameter_cnt)<<3,tempc->return_class); } CbAddIc(lx,EC_CALL_END,tempc,tempc->return_class); lx->flags=(lx->flags|LF_RAX) & ~(LF_ARRAY|LF_FUNCTION); return PRST_UNARY_MODIFIERS; } if (temph->type & HTT_GLBL_VAR) { tempg=temph; tempc=tempg->var_class+sizeof(ClassStruct); lx->flags&=~(LF_RAX|LF_ARRAY|LF_FUNCTION); if (tempg->cnt) { *tempad=tempg->dim_list; tempc+=sizeof(ClassStruct); lx->flags|=LF_ARRAY; } if (tempg->flags & GVAF_FUNCTION) { //TODO:Not implemented lx->flags|=LF_FUNCTION; } if (lx->a) { if (tempg->flags & GVAF_EXTERN) { CbAddIc(lx,EC_IMM,&tempg->data_address,tempc); CbAddIc(lx,EC_DEREF,0,tempc); } else { if (tempg->flags & GVAF_IMPORT) { CbAddIc(lx,EC_ABSOLUTE_ADDRESS,tempg->data_address,tempc+sizeof(ClassStruct)); CbAddIc(lx,EC_DEREF,0,tempc); } else CbAddIc(lx,EC_ABSOLUTE_ADDRESS,tempg->data_address,tempc); } } else { if (tempg->flags & GVAF_EXTERN) { CbAddIc(lx,EC_IMM,&tempg->data_address,tempc); CbAddIc(lx,EC_DEREF,0,tempc); } else CbAddIc(lx,EC_IMM,tempg->data_address,tempc); } Lex(lx); return PRST_UNARY_MODIFIERS; } if (!(temph->type & HTT_KEYWORD)) PrsExcept(lx,"ST_MISSING_EXPRESSION"); if (temph->user_data0==KW_SIZEOF) { if (Lex(lx)!='(') PrsExcept(lx,"ST_EXPECTING_LEFT_PAREN"); if (Lex(lx)!=TK_IDENT) PrsExcept(lx,"ST_INVALID_CLASS"); if (tempm=lx->local_var_entry) { tempc=tempm->member_class; i=tempc->size; if (tempm->cnt) i*=tempm->cnt; } else { tempc=lx->hash_entry; if (!tempc || !(tempc->type & (HTT_CLASS|HTT_INTERNAL_TYPE|HTT_GLBL_VAR))) PrsExcept(lx,"ST_INVALID_CLASS"); i=tempc->size; } //TODO: should allow '.member', etc; if (Lex(lx)=='*') { while (Lex(lx)=='*'); i=sizeof(void *); } CbAddIc(lx,EC_IMM,i,sys_internal_types[IT_I8]); if (lx->token!=')') PrsExcept(lx,"ST_MISSING_RIGHT_PAREN"); Lex(lx); return PRST_CHECK_BINARY_OPS; } else if (temph->user_data0==KW_OFFSET) { if (Lex(lx)!='(') PrsExcept(lx,"ST_EXPECTING_LEFT_PAREN"); if (Lex(lx)!=TK_IDENT) PrsExcept(lx,"ST_INVALID_CLASS"); if (tempm=lx->local_var_entry) tempc=tempm->member_class; else { tempc=lx->hash_entry; if (!tempc || !(tempc->type & (HTT_CLASS|HTT_GLBL_VAR))) PrsExcept(lx,"ST_INVALID_CLASS"); else if (tempc->type & HTT_GLBL_VAR) tempc=tempc><(GlblVarStruct *)->var_class; } if (Lex(lx)!='.') PrsExcept(lx,"ST_EXPECTING_DOT"); if (Lex(lx)!=TK_IDENT) PrsExcept(lx,"ST_INVALID_MEMBER"); if (!(tempm=FindMember(lx->ident,tempc))) PrsExcept(lx,"ST_INVALID_MEMBER"); CbAddIc(lx,EC_IMM,tempm->offset,sys_internal_types[IT_I8]); if (Lex(lx)!=')') PrsExcept(lx,"ST_MISSING_RIGHT_PAREN"); Lex(lx); return PRST_CHECK_BINARY_OPS; } PrsExcept(lx,"ST_MISSING_EXPRESSION"); } U8 PrsUnaryModifier(LexStruct *lx,ParseStack *ps,MemberListStruct **local_var,ArrayDimStruct **tempad) { I8 i,j; LexCbStack *templ,*templ2,*templl; ClassStruct *tempc,*tempc1; MemberListStruct *tempm; IntermediateCode *tempi,*tempi1; ArrayDimStruct *tempad1; if (lx->flags & LF_ASM_EXPRESSIONS) return PRST_CHECK_BINARY_OPS; if (lx->token==TK_DEREFERRENCE) { tempi=lx->cb.cb_last_out_ptr; if (!(lx->flags & (LF_RAX | LF_ARRAY))) { tempc=tempi->ic_class-sizeof(ClassStruct); CbAddIc(lx,EC_DEREF+0x10000,0,tempc); } else tempi->ic_class-=sizeof(ClassStruct); } else if (lx->token=='.') { if (*local_var) { tempm=*local_var; tempm->flags|=MLF_NO_REG_VARIABLE; } } *local_var=NULL; if (lx->token=='.' || lx->token==TK_DEREFERRENCE) { tempi=lx->cb.cb_last_out_ptr; tempc=tempi->ic_class; if (!(lx->flags & LF_RAX)) tempc-=sizeof(ClassStruct); if (!(tempc->type & HTT_CLASS)) PrsExcept(lx,"ST_INVALID_CLASS"); if (Lex(lx)!=TK_IDENT) PrsExcept(lx,"ST_INVALID_MEMBER"); if (!(tempm=FindMember(lx->ident,tempc))) PrsExcept(lx,"ST_INVALID_MEMBER"); Lex(lx); //skip member name tempc1=tempm->member_class+sizeof(ClassStruct); CbAddIc(lx,EC_IMM,tempm->offset,tempc1); lx->flags&=~(LF_RAX|LF_ARRAY|LF_FUNCTION); if (tempm->cnt) { *tempad=tempm->dim_list; tempc1+=sizeof(ClassStruct); lx->flags|=LF_ARRAY; } if(tempm->flags & MLF_FUNCTION) { PrsPush(ps,tempm->return_class); PrsPush(ps,tempm->parameter_cnt); lx->flags|=LF_FUNCTION; } CbAddIc(lx,EC_ADD,0,tempc1); return PRST_UNARY_MODIFIERS; } if (lx->token==TK_CAST) { if (Lex(lx)!='(') PrsExcept(lx,"ST_EXPECTING_LEFT_PAREN"); if (Lex(lx)!=TK_IDENT) PrsExcept(lx,"ST_INVALID_CLASS"); tempc=lx->hash_entry; if (!tempc || !(tempc->type & (HTT_CLASS|HTT_INTERNAL_TYPE))) PrsExcept(lx,"ST_INVALID_CLASS"); while (Lex(lx)=='*') tempc+=sizeof(ClassStruct); tempc+=sizeof(ClassStruct); tempi=lx->cb.cb_last_out_ptr; tempi->ic_class=tempc; if (lx->token!=')') PrsExcept(lx,"ST_MISSING_RIGHT_PAREN"); Lex(lx); return PRST_UNARY_MODIFIERS; } if (lx->token=='[') { Lex(lx); tempi=lx->cb.cb_last_out_ptr; if (!(lx->flags & (LF_ARRAY | LF_RAX))) { tempc=tempi->ic_class-sizeof(ClassStruct); while (!(tempc->type & HTT_INTERNAL_TYPE) && tempc->return_class) tempc=tempc->return_class; i=EC_DEREF+0x10000; CbAddIc(lx,i,0,tempc); } else { tempc=tempi->ic_class; if (!(lx->flags & LF_RAX)) tempc-=sizeof(ClassStruct); } tempc1=tempc-sizeof(ClassStruct); if (tempad1=*tempad) { CbAddIc(lx,EC_IMM,tempad1->cnt*tempc1->size,tempc); if (*tempad=tempad1->next) { if (!PrsParseExpression(lx)) throw(EXCEPT_COMPILER,5); if (lx->token!=']') PrsExcept(lx,"ST_MISSING_RIGHT_BRACKET"); Lex(lx); //skip ] tempi1=lx->cb.cb_last_out_ptr; if (tempi1->ic_class->sub_type==IT_DOUBLE) tempi1->ic_flags|=ICF_R_TO_INT; CbAddIc(lx,EC_MUL,0,tempc); tempi1=lx->cb.cb_last_out_ptr; tempi1->ic_flags|=ICF_USE_INT; CbAddIc(lx,EC_ADD,0,tempc); tempi1=lx->cb.cb_last_out_ptr; tempi1->ic_flags|=ICF_USE_INT; lx->flags|=LF_RAX; return PRST_UNARY_MODIFIERS; } } else CbAddIc(lx,EC_IMM,tempc1->size,tempc); if (!PrsParseExpression(lx)) throw(EXCEPT_COMPILER,5); if (lx->token!=']') PrsExcept(lx,"ST_MISSING_RIGHT_BRACKET"); Lex(lx); //skip ] tempi1=lx->cb.cb_last_out_ptr; if (tempi1->ic_class->sub_type==IT_DOUBLE) tempi1->ic_flags|=ICF_R_TO_INT; CbAddIc(lx,EC_MUL,0,tempc); tempi1=lx->cb.cb_last_out_ptr; tempi1->ic_flags|=ICF_USE_INT; CbAddIc(lx,EC_ADD,0,tempc); tempi1=lx->cb.cb_last_out_ptr; tempi1->ic_flags|=ICF_USE_INT; lx->flags&=~(LF_RAX|LF_ARRAY); return PRST_UNARY_MODIFIERS; } if (lx->token=='(' && lx->flags & LF_FUNCTION) { tempi=lx->cb.cb_last_out_ptr; tempc=tempi->ic_class-sizeof(ClassStruct); if (!(lx->flags & (LF_RAX | LF_ARRAY))) CbAddIc(lx,EC_DEREF,0,sys_internal_types[IT_PTR]); else tempi->ic_class=tempc; CbAddIc(lx,EC_SET_RAX,0,sys_internal_types[IT_PTR]); CbAddIc(lx,EC_NOP1,1,sys_internal_types[IT_PTR]); //balance the books CbAddIc(lx,EC_CALL_START,0,tempc); CbAddIc(lx,EC_PUSH_REGS,1<cb.cb_next; lx->cb.cb_next=NULL; while (i--) { if (lx->token==',') Lex(lx); CbInitOutPtrs(&lx->cb); if (!PrsParseExpression(lx)) throw(EXCEPT_COMPILER,6); CbAddIc(lx,EC_NULL,0,0); CbPush(lx); } if (lx->token!=')') PrsExcept(lx,"ST_MISSING_RIGHT_PAREN"); Lex(lx); //skip ')' templl=templ->cb_next; templ->cb_next=lx->cb.cb_next; lx->cb.cb_next=templ; CbPop(lx); templ=lx->cb.cb_next; lx->cb.cb_next=templl; while (templ) { templ2=templ->cb_next; CbAppend(lx,templ); lx->cb.cb_last_out_ptr->ic_flags|=ICF_PUSH_RESULT; templ=templ2; } CbAddIc(lx,EC_CALL_INDIRECT,j<<3,tempc); CbAddIc(lx,EC_ADD_RSP,j<<3+8,tempc); CbAddIc(lx,EC_CALL_END,0,tempc); lx->flags=(lx->flags | LF_RAX)&~(LF_ARRAY | LF_FUNCTION); return PRST_UNARY_MODIFIERS; } if (lx->token==TK_PLUS_PLUS) { Lex(lx); lx->flags|=LF_POSTINC; return PRST_DEREFERRENCE; } if (lx->token==TK_MINUS_MINUS) { Lex(lx); lx->flags|=LF_POSTDEC; return PRST_DEREFERRENCE; } return PRST_DEREFERRENCE; } U8 PrsDereferrence(LexStruct *lx,ParseStack *ps) { I8 i; ClassStruct *tempc; IntermediateCode *tempi; if (lx->flags & LF_FUNCTION) { ps->ptr--; tempc=PrsPop(ps); } if (lx->flags & LF_RAX) return PRST_CHECK_BINARY_OPS; tempi=lx->cb.cb_last_out_ptr; tempc=tempi->ic_class-sizeof(ClassStruct); if (lx->flags & LF_ARRAY) { tempi->ic_class=tempc; return PRST_CHECK_BINARY_OPS; } if (lx->flags & LF_PREINC) { lx->flags&=~LF_PREINC; i=EC_PP_; } else if (lx->flags & LF_PREDEC) { lx->flags&=~LF_PREDEC; i=EC_MM_; } else if (lx->flags & LF_POSTINC) { lx->flags&=~LF_POSTINC; i=EC__PP; } else if (lx->flags & LF_POSTDEC) { lx->flags&=~LF_POSTDEC; i=EC__MM; } else i=EC_DEREF; while (tempc->return_class) tempc=tempc->return_class; CbAddIc(lx,i+0x10000,0,tempc); return PRST_CHECK_BINARY_OPS; } void *CompileExpression(LexStruct *lx,U8 *type=NULL) { void *result; U8 size; DbgInfo *dbg=NULL; BoolU4 old_trace=Btr(&lx->flags,LFf_OPT_TRACE_PRESENT); CbPush(lx); CbInitOutPtrs(&lx->cb); CbAddIc(lx,EC_RETURN_START,0,0); if (PrsParseExpression(lx,TRUE)) { CbAddIc(lx,EC_RETURN_END,0,sys_internal_types[IT_I8]); CbAddIc(lx,EC_RET,0,0); CbAddIc(lx,EC_NULL,0,0); result=CbCompile(lx,NULL,&size,&dbg,type); } else result=NULL; CbPop(lx); Free(dbg); AssignBit(&lx->flags,LFf_OPT_TRACE_PRESENT,old_trace); return result; } BoolU8 GetExpression(LexStruct *lx,void **e) //FALSE=no err { *e=CompileExpression(lx); if (*e) return TRUE; else return FALSE; } I8 Expression(LexStruct *lx) //FALSE=no err { I8 result; void *e=CompileExpression(lx); if (e) { result=Call(e); DelExpression(e); } else result=0; return result; }