Files
TempleOS-Rijn/LT/COMPILE/PARSE.CPZ
T
2018-09-08 21:45:17 +02:00

774 lines
21 KiB
Plaintext

/*
void PrsPush(ParseStack *ps,U4 val)
{
ps->stk[ps->ptr++]=val;
}
U8 PrsPop(ParseStack *ps)
{
return ps->stk[--ps->ptr];
}
*/
LTextern CP_PRSPUSH void PrsPush(ParseStack *ps,U4 val);
LTextern CP_PRSPOP U4 PrsPop(ParseStack *ps);
#define PRST_UNARY_TERM 0
#define PRST_UNARY_MODIFIERS 1
#define PRST_DEREFERRENCE 2
#define PRST_CHECK_BINARY_OPS 3
BoolU4 PrsParseExpression(LexStruct *l,BoolU4 add_esp=FALSE)
{
BoolU4 result=TRUE,question_clause=FALSE,
cont_unary,cont_check_binary_ops,is_lower;
I8 i,j,k;
IntermediateCode *tempi,*tempi_first=l->cb.cb_out_ptr;
ClassStruct *tempc;
ParseStack *ps=MAlloc(sizeof(ParseStack));
ps->ptr=0;
PrsPush(ps,0); //terminate
PrsPush(ps,0); //terminate
try {
do {
l->flags&=~(LF_PREINC+LF_PREDEC+LF_POSTINC+LF_POSTDEC+LF_FUNCTION);
do i=PrsUnaryTerm(l,ps);
while (i==PRST_UNARY_TERM);
while (i==PRST_UNARY_MODIFIERS)
i=PrsUnaryModifier(l,ps);
if (i==PRST_DEREFERRENCE)
PrsDereferrence(l,ps);
//Check for binary Ops
do {
i=PrsPop(ps);
tempc=PrsPop(ps);
if (i && i.u2[1]<=1) {
tempi=l->cb.cb_last_out_ptr;
i&=0xFFFF;
tempc=tempi->ic_class;
if (Bt(deref_bitmap,i) && tempc->pointer_cnt) {
tempc=tempc-sizeof(ClassStruct);
while (tempc->return_class)
tempc=tempc->return_class;
if (tempc->type & HTT_INTERNAL_TYPE)
i=EC_DEREF_U8+0x10000+it_to_ec_offset[tempc->sub_type];
else
i=EC_DEREF_U4+0x10000;
} else {
if (i==EC_ADDRESS) {
if (!(l->flags & (LF_EAX|LF_ARRAY))) {
j=tempi->ic_code.u2[0];
if (!Bt(deref_bitmap,j))
PrsExcept(l,"ST_INVALID_LVALUE");
tempi->ic_code=EC_NOP;
tempc=tempc+sizeof(ClassStruct);
}
}
}
CbAddIc(l,i,0,tempc);
cont_check_binary_ops=TRUE;
} else {
PrsPush(ps,tempc);
PrsPush(ps,i);
i=l->token;
k=binary_ops_table[i];
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.u2[1]) {
cont_check_binary_ops=FALSE;
cont_unary=FALSE; //DONE
} else {
Lex(l); //skip op
if (Bt(assign_bitmap,k.u2[0])) {
tempi=l->cb.cb_last_out_ptr;
tempc=tempi->ic_class;
j=tempi->ic_code.u2[0];
if (!Bt(deref_bitmap,j))
PrsExcept(l,"ST_INVALID_LVALUE");
tempi->ic_code=EC_NOP;
while (tempc->return_class)
tempc=tempc->return_class;
if (!(tempc->type & HTT_INTERNAL_TYPE))
k=k.u2[0]+0x100000+it_to_ec_offset[IT_U4];
else
k=k.u2[0]+0x100000+it_to_ec_offset[tempc->sub_type];
}
do {
i=PrsPop(ps); //pop ops of higher prec
tempc=PrsPop(ps);
is_lower=FALSE;
if (i) {
if (k.u2[1]==i.u2[1]) {
if (!Bt(assign_bitmap,k.u2[0]) ||
!Bt(assign_bitmap,i.u2[0]))
is_lower=TRUE;
} else if (k.u2[1]>i.u2[1])
is_lower=TRUE;
}
if (is_lower)
CbAddIc(l,i,0,tempc);
else {
PrsPush(ps,tempc);
PrsPush(ps,i);
tempi=l->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)
CbAddIc(l,i,0,tempc);
else
break;
}
} catch {
if (Fs->except_argc>0) {
if (Fs->except_argv[0]==EXCEPT_COMPILER) {
l->statement_cnt=0;
l->braces_cnt=0;
result=FALSE;
Fs->catch_except=TRUE;
}
}
}
Free(ps);
if (add_esp && result) {
if (Bt(push_bitmap,tempi_first->ic_code.u2[0])) {
tempi_first->ic_flags|=ICF_NO_PUSHES;
CbAddIc(l,EC_END_EXP,0,0);
} else
CbAddIc(l,EC_ADD_ESP32,8,0);
}
return result;
}
U8 PrsUnaryTerm(LexStruct *l,ParseStack *ps)
{
I8 i,*i_ptr;
I8 argc_cnt,size;
U8 d;
SysHashEntry *temph,**temph1;
ClassStruct *tempc,*tempc1,*tempc2;
GlblVarStruct *tempg;
MemberListStruct *tempm;
LexUndefEntry *templu;
CbMiscStruct *tempmc;
IntermediateCode *tempi;
BoolU4 needs_right_paren;
LexCbStack *templ,*templ1;
if (l->token==TK_INTEGER) {
if (l->cur_i<0)
CbAddIc(l,EC_U8,l->cur_i,sys_internal_types[IT_U8]);
else
CbAddIc(l,EC_U8,l->cur_i,sys_internal_types[IT_I8]);
Lex(l);
return PRST_CHECK_BINARY_OPS;
}
if (l->token==TK_DOUBLE) {
i_ptr=&l->cur_d;
CbAddIc(l,EC_DOUBLE,*i_ptr,sys_internal_types[IT_DOUBLE]);
Lex(l);
return PRST_CHECK_BINARY_OPS;
}
if (l->token==TK_STRING) {
d=LexExtendString(l,&size);
if (l->flags & LF_ASM_EXPRESSIONS)
CbAddIc(l,EC_U8,d,sys_internal_types[IT_I1]+sizeof(ClassStruct));
else {
tempmc=CbMiscNew(l,CBMT_STRING_CONSTANT);
CbAddIc(l,EC_STRING_CONSTANT,tempmc,sys_internal_types[IT_I1]+sizeof(ClassStruct));
tempmc->st_len=size;
tempmc->string=d;
l->flags|=LF_HAS_MISC_DATA;
}
return PRST_CHECK_BINARY_OPS;
}
if (l->token==TK_INSERT_BINARY) {
d=l->ident;
size=l->ident_len;
l->ident=NULL;
Lex(l);
if (l->flags & LF_ASM_EXPRESSIONS)
CbAddIc(l,EC_U8,d,sys_internal_types[IT_I1]+sizeof(ClassStruct));
else {
tempmc=CbMiscNew(l,CBMT_STRING_CONSTANT);
CbAddIc(l,EC_STRING_CONSTANT,tempmc,sys_internal_types[IT_I1]+sizeof(ClassStruct));
tempmc->st_len=size;
tempmc->string=d;
l->flags|=LF_HAS_MISC_DATA;
}
return PRST_CHECK_BINARY_OPS;
}
if (l->token==TK_INSERT_BINARY_TYPE ||
l->token==TK_INSERT_BINARY_SIZE) {
CbAddIc(l,EC_U8,l->cur_i,sys_internal_types[IT_U8]);
Lex(l);
return PRST_CHECK_BINARY_OPS;
}
if (l->token=='(') {
Lex(l); //Skip (
if (!PrsParseExpression(l))
throw(EXCEPT_COMPILER,2);
if (l->token!=')')
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
Lex(l); //skip )
l->flags=(l->flags & ~(LF_ARRAY+LF_FUNCTION)) | LF_EAX;
return PRST_UNARY_MODIFIERS;
}
i=unary_ops_table[l->token];
if (i.u2[1]) {
Lex(l); //Skip op
if (i.u2[0]==EC_ADDRESS && l->token==TK_IDENT) {
if (tempc=l->hash_entry) {
if (tempc->type & HTT_FUNCTION) {
if (!Bt(&tempc->flags,Cf_INTERNAL)) {
Lex(l); //skip fun name
if (Bt(&tempc->flags,Cf_EXTERN)) {
if (l->a)
CbAddIc(l,EC_ABSOLUTE_ADDRESS,
tempc->executable_address,sys_internal_types[IT_U4]);
else
CbAddIc(l,EC_U8,
&tempc->executable_address,sys_internal_types[IT_U4]);
CbAddIc(l,EC_DEREF_U4,0,
sys_internal_types[IT_U4]);
} else {
if (l->a)
CbAddIc(l,EC_ABSOLUTE_ADDRESS,
tempc->executable_address,sys_internal_types[IT_U4]);
else
CbAddIc(l,EC_U8,
tempc->executable_address,sys_internal_types[IT_U4]);
}
return PRST_CHECK_BINARY_OPS;
} //TODO: is this an error?
}//TODO: is this an error?
}//TODO: is this an error?
}
PrsPush(ps,tempc);
PrsPush(ps,i);
return PRST_UNARY_TERM;
}
if (l->token=='+') {
Lex(l);
return PRST_UNARY_TERM;
}
if (l->token!=TK_IDENT) {
if (l->token==TK_PLUS_PLUS) {
Lex(l);
l->flags|=LF_PREINC;
return PRST_UNARY_TERM;
}
if (l->token==TK_MINUS_MINUS) {
Lex(l);
l->flags|=LF_PREDEC;
return PRST_UNARY_TERM;
}
if (l->token=='$$' && l->flags & LF_ASM_EXPRESSIONS) {
Lex(l);
CbAddIc(l,EC_U8,l->instruction_pointer,sys_internal_types[IT_U4]);
return PRST_CHECK_BINARY_OPS;
}
PrsExcept(l,"ST_MISSING_EXPRESSION");
}
if (tempm=l->local_var_entry) {
l->flags&=~(LF_EAX+LF_ARRAY+LF_FUNCTION);
tempc=tempm->member_class+sizeof(ClassStruct);
if (tempm->flags & MLF_FUNCTION) {
l->flags|=LF_FUNCTION;
PrsPush(ps,0);
PrsPush(ps,tempm->parameter_cnt);
}
if (tempm->cnt) {
l->flags|=LF_ARRAY;
tempc+=sizeof(ClassStruct);
}
CbAddIc(l,EC_EBP,0,tempc);
CbAddIc(l,EC_U8,tempm->offset,tempc);
CbAddIc(l,EC_ADDITION,0,tempc);
Lex(l); //skip var name
return PRST_UNARY_MODIFIERS;
}
if (!(temph=l->hash_entry)) {
if (!(l->flags & LF_ASM_EXPRESSIONS))
PrsExcept(l,"ST_INVALID_LVALUE");
temph=MAllocZ(sizeof(SysHashEntry));
temph->string=l->ident;
l->ident=NULL;
if (temph->string[0]=='@' &&
temph->string[1]=='@') {
temph->type=HTT_SYS_SYMBOL | HTT_UNRESOLVED_LOCAL;
temph1=FindHashBucket(temph->string,l->local_hash_table);
} else {
temph->type=HTT_SYS_SYMBOL | HTT_UNRESOLVED_GLBL;
temph1=FindHashBucket(temph->string,l->glbl_hash_table);
}
temph->use_cnt=0;
SetSourceFileInfo(l,temph);
temph->next=*temph1;
*temph1=temph;
temph->user0=0;
}
if (temph->type & HTT_SYS_SYMBOL) {
if (!(temph->type & HTT_LITERAL) &&
!(temph->type & HTT_IMPORT))
l->absolute_address_cnt++;
if (temph->type & (HTT_UNRESOLVED_LOCAL|HTT_UNRESOLVED_GLBL)) {
templu=MAlloc(sizeof(LexUndefEntry));
templu->hash=temph;
templu->next=l->undef_hash_entry;
l->undef_hash_entry=templu;
if (temph->type & HTT_UNRESOLVED_LOCAL)
l->flags|=LF_UNRESOLVED_LOCAL;
else
l->flags|=LF_UNRESOLVED_GLBL;
CbAddIc(l,EC_U8,&temph->user0,sys_internal_types[IT_U4]);
CbAddIc(l,EC_DEREF_U4,0,sys_internal_types[IT_U4]);
} else {
if (l->a && !(temph->type & HTT_LITERAL))
CbAddIc(l,EC_ABSOLUTE_ADDRESS,temph->user0,sys_internal_types[IT_U4]);
else
CbAddIc(l,EC_U8,temph->user0,sys_internal_types[IT_U4]);
}
Lex(l);
return PRST_CHECK_BINARY_OPS;
}
if (temph->type & HTT_FUNCTION) {
Lex(l); //skip fun name
CbPush(l);
templ=l->cb.cb_next;
l->cb.cb_next=NULL;
tempc=temph;
i=tempc->parameter_cnt;
tempm=tempc->member_list;
argc_cnt=0;
if (l->token!='(')
needs_right_paren=FALSE;
else {
Lex(l);
needs_right_paren=TRUE;
}
while (i--) {
if (l->token==',')
Lex(l);
CbInitOutPtrs(&l->cb);
if (tempm->flags & MLF_DEFAULT_AVAILABLE &&
(l->token==')' || !needs_right_paren))
CbAddIc(l,EC_U8,tempm->default_value,tempm->member_class);
else
if (!PrsParseExpression(l))
throw(EXCEPT_COMPILER,3);
else {
CbPush(l);
CbAddIc(l,0,0,0);
tempi=CmpOptPass1(l,NULL,FALSE);
CbPop(l);
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_TO_DOUBLE;
else
if (tempc2->sub_type!=IT_DOUBLE &&
tempc1->sub_type==IT_DOUBLE)
tempi->ic_flags|=ICF_TO_INT;
}
CbAddIc(l,0,0,0);
CbPush(l);
tempm=tempm->next;
}
if (tempm && tempm->flags & MLF_DOT_DOT_DOT) {
CbInitOutPtrs(&l->cb);
CbAddIc(l,EC_U8,0,tempm->member_class);
tempi=l->cb.cb_last_out_ptr;
CbAddIc(l,0,0,0);
CbPush(l);
if (needs_right_paren) {
if (l->token!=')') {
do {
if (l->token==',')
Lex(l);
CbInitOutPtrs(&l->cb);
if (!PrsParseExpression(l))
throw(EXCEPT_COMPILER,4);
CbAddIc(l,0,0,0);
CbPush(l);
argc_cnt++;
} while (l->token==',');
}
}
tempi->ic_data=argc_cnt++; //++ so add_esp latter works
}
if (needs_right_paren) {
if (l->token!=')')
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
Lex(l);
}
templ1=templ->cb_next;
templ->cb_next=l->cb.cb_next;
l->cb.cb_next=templ;
CbPop(l);
templ=l->cb.cb_next;
l->cb.cb_next=templ1;
while (templ) {
templ1=templ->cb_next;
CbAppend(l,templ);
templ=templ1;
}
if (Bt(&tempc->flags,Cf_INTERNAL))
CbAddIc(l,tempc->executable_address,0,tempc->return_class);
else if (Bt(&tempc->flags,Cf_EXTERN)) {
if (l->a)
CbAddIc(l,EC_CALL_INDIRECT2,tempc->executable_address,tempc->return_class);
else
CbAddIc(l,EC_CALL_INDIRECT2,&tempc->executable_address,tempc->return_class);
CbAddIc(l,EC_ADD_ESP32,(argc_cnt+tempc->parameter_cnt)<<3,tempc->return_class);
} else {
CbAddIc(l,EC_CALL,tempc->executable_address,tempc->return_class);
CbAddIc(l,EC_ADD_ESP32,(argc_cnt+tempc->parameter_cnt)<<3,tempc->return_class);
}
l->flags=(l->flags|LF_EAX) & ~(LF_ARRAY|LF_FUNCTION);
return PRST_UNARY_MODIFIERS;
}
if (temph->type & HTT_GLBL_VAR) {
tempg=temph;
tempc=tempg->var_class+sizeof(ClassStruct);
l->flags&=~(LF_EAX|LF_ARRAY|LF_FUNCTION);
if (tempg->cnt) {
tempc+=sizeof(ClassStruct);
l->flags|=LF_ARRAY;
}
if (tempg->flags & GVAF_FUNCTION) {
//TODO:Not implemented
l->flags|=LF_FUNCTION;
}
if (l->a) {
if (tempg->flags & GVAF_EXTERN) { //TODO: Untested
CbAddIc(l,EC_U8,&tempg->data_address,tempc);
CbAddIc(l,EC_DEREF_U4,0,tempc);
} else {
CbAddIc(l,EC_ABSOLUTE_ADDRESS,tempg->data_address,tempc);
if (tempg->flags & GVAF_IMPORT)
CbAddIc(l,EC_DEREF_U4,0,tempc);
}
} else {
if (tempg->flags & GVAF_EXTERN) {
CbAddIc(l,EC_U8,&tempg->data_address,tempc);
CbAddIc(l,EC_DEREF_U4,0,tempc);
} else
CbAddIc(l,EC_U8,tempg->data_address,tempc);
}
Lex(l);
return PRST_UNARY_MODIFIERS;
}
if (!(temph->type & HTT_KEYWORD))
PrsExcept(l,"ST_MISSING_EXPRESSION");
if (temph->user0==KW_SIZEOF) {
if (Lex(l)!='(') PrsExcept(l,"ST_EXPECTING_LEFT_PAREN");
if (Lex(l)!=TK_IDENT)
PrsExcept(l,"ST_INVALID_CLASS");
if (tempm=l->local_var_entry) {
tempc=tempm->member_class;
i=(tempm->cnt) ? tempm->cnt:1;
CbAddIc(l,EC_U8,tempc->size*i,sys_internal_types[IT_U4]);
} else {
tempc=l->hash_entry;
if (!tempc || !(tempc->type & (HTT_CLASS|HTT_INTERNAL_TYPE|HTT_GLBL_VAR)))
PrsExcept(l,"ST_INVALID_CLASS");
CbAddIc(l,EC_U8,tempc->size,sys_internal_types[IT_U4]);
} //TODO: should allow '*' and '.member', etc;
if (Lex(l)!=')')
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
Lex(l);
return PRST_CHECK_BINARY_OPS;
} else if (temph->user0==KW_OFFSET) {
if (Lex(l)!='(') PrsExcept(l,"ST_EXPECTING_LEFT_PAREN");
if (Lex(l)!=TK_IDENT)
PrsExcept(l,"ST_INVALID_CLASS");
if (tempm=l->local_var_entry)
tempc=tempm->member_class;
else {
tempc=l->hash_entry;
if (!tempc || !(tempc->type & (HTT_CLASS|HTT_GLBL_VAR)))
PrsExcept(l,"ST_INVALID_CLASS");
else if (tempc->type & HTT_GLBL_VAR) {
tempg=tempc;
tempc=tempg->var_class;
}
}
if (Lex(l)!='.')
PrsExcept(l,"ST_EXPECTING_DOT");
if (Lex(l)!=TK_IDENT)
PrsExcept(l,"ST_INVALID_MEMBER");
if (!(tempm=FindMember(l->ident,tempc)))
PrsExcept(l,"ST_INVALID_MEMBER");
CbAddIc(l,EC_U8,tempm->offset,sys_internal_types[IT_U4]);
if (Lex(l)!=')')
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
Lex(l);
return PRST_CHECK_BINARY_OPS;
}
PrsExcept(l,"ST_MISSING_EXPRESSION");
}
U8 PrsUnaryModifier(LexStruct *l,ParseStack *ps)
{
I8 i,j;
LexCbStack *templ,*templ2,*templl;
ClassStruct *tempc,*tempc1;
MemberListStruct *tempm;
IntermediateCode *tempi;
if (l->flags & LF_ASM_EXPRESSIONS)
return PRST_CHECK_BINARY_OPS;
if (l->token==TK_DEREFERRENCE) {
tempi=l->cb.cb_last_out_ptr;
if (!(l->flags & (LF_EAX | LF_ARRAY))) {
tempc=tempi->ic_class-sizeof(ClassStruct);
CbAddIc(l,EC_DEREF_U4+0x10000,0,tempc);
} else
tempi->ic_class-=sizeof(ClassStruct);
}
if (l->token=='.' || l->token==TK_DEREFERRENCE) {
tempi=l->cb.cb_last_out_ptr;
tempc=tempi->ic_class;
if (!(l->flags & LF_EAX))
tempc-=sizeof(ClassStruct);
if (!(tempc->type & HTT_CLASS))
PrsExcept(l,"ST_INVALID_CLASS");
if (Lex(l)!=TK_IDENT)
PrsExcept(l,"ST_INVALID_MEMBER");
if (!(tempm=FindMember(l->ident,tempc)))
PrsExcept(l,"ST_INVALID_MEMBER");
Lex(l); //skip member name
tempc1=tempm->member_class+sizeof(ClassStruct);
CbAddIc(l,EC_U8,tempm->offset,tempc1);
l->flags&=~(LF_EAX|LF_ARRAY|LF_FUNCTION);
if (tempm->cnt) {
tempc1+=sizeof(ClassStruct);
l->flags|=LF_ARRAY;
}
if(tempm->flags & MLF_FUNCTION) {
PrsPush(ps,0);
PrsPush(ps,tempm->parameter_cnt);
l->flags|=LF_FUNCTION;
}
CbAddIc(l,EC_ADDITION,0,tempc1);
return PRST_UNARY_MODIFIERS;
}
if (l->token==TK_CAST) {
if (Lex(l)!='(')
PrsExcept(l,"ST_EXPECTING_LEFT_PAREN");
if (Lex(l)!=TK_IDENT)
PrsExcept(l,"ST_INVALID_CLASS");
tempc=l->hash_entry;
if (!tempc || !(tempc->type & (HTT_CLASS|HTT_INTERNAL_TYPE)))
PrsExcept(l,"ST_INVALID_CLASS");
while (Lex(l)=='*')
tempc+=sizeof(ClassStruct);
tempc+=sizeof(ClassStruct);
tempi=l->cb.cb_last_out_ptr;
tempi->ic_class=tempc;
if (l->token!=')')
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
Lex(l);
return PRST_UNARY_MODIFIERS;
}
if (l->token=='[') {
Lex(l);
tempi=l->cb.cb_last_out_ptr;
if (!(l->flags & (LF_ARRAY | LF_EAX))) {
tempc=tempi->ic_class-sizeof(ClassStruct);
while (!(tempc->type & HTT_INTERNAL_TYPE) && tempc->return_class)
tempc=tempc->return_class;
if (tempc->type==HTT_INTERNAL_TYPE)
i=EC_DEREF_U8+0x10000+it_to_ec_offset[tempc->sub_type];
else
i=EC_DEREF_U4+0x10000;
CbAddIc(l,i,0,tempc);
} else {
tempc=tempi->ic_class;
if (!(l->flags & LF_EAX))
tempc-=sizeof(ClassStruct);
}
tempc1=tempc-sizeof(ClassStruct);
CbAddIc(l,EC_U8,tempc1->size,tempc);
if (!PrsParseExpression(l))
throw(EXCEPT_COMPILER,5);
if (l->token!=']')
PrsExcept(l,"ST_MISSING_RIGHT_BRACKET");
Lex(l); //skip ]
CbAddIc(l,EC_MULTIPLICATION,0,tempc);
CbAddIc(l,EC_ADDITION,0,tempc);
l->flags&=~(LF_EAX|LF_ARRAY);
return PRST_UNARY_MODIFIERS;
}
if (l->token=='(' && l->flags & LF_FUNCTION) {
tempi=l->cb.cb_last_out_ptr;
if (!(l->flags & (LF_EAX | LF_ARRAY))) {
tempc=tempi->ic_class-sizeof(ClassStruct);
CbAddIc(l,EC_DEREF_U4+0x10000,0,tempc);
} else {
tempi->ic_class=tempi->ic_class-sizeof(ClassStruct);
tempc=tempi;
}
i=PrsPop(ps);
PrsPop(ps);
j=i;
Lex(l); //skip '('
CbPush(l);
templ=l->cb.cb_next;
l->cb.cb_next=NULL;
while (i--) {
if (l->token==',')
Lex(l);
CbInitOutPtrs(&l->cb);
if (!PrsParseExpression(l))
throw(EXCEPT_COMPILER,6);
CbAddIc(l,0,0,0);
CbPush(l);
}
if (l->token!=')')
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
Lex(l); //skip ')'
templl=templ->cb_next;
templ->cb_next=l->cb.cb_next;
l->cb.cb_next=templ;
CbPop(l);
templ=l->cb.cb_next;
l->cb.cb_next=templl;
while (templ) {
templ2=templ->cb_next;
CbAppend(l,templ);
templ=templ2;
}
CbAddIc(l,EC_CALL_INDIRECT,j<<3,tempc);
CbAddIc(l,EC_ADD_ESP32,j<<3+8,tempc);
l->flags=(l->flags | LF_EAX)&~(LF_ARRAY | LF_FUNCTION);
return PRST_UNARY_MODIFIERS;
}
if (l->token==TK_PLUS_PLUS) {
Lex(l);
l->flags|=LF_POSTINC;
return PRST_DEREFERRENCE;
}
if (l->token==TK_MINUS_MINUS) {
Lex(l);
l->flags|=LF_POSTDEC;
return PRST_DEREFERRENCE;
}
return PRST_DEREFERRENCE;
}
U8 PrsDereferrence(LexStruct *l,ParseStack *ps)
{
I8 i;
ClassStruct *tempc;
IntermediateCode *tempi;
if (l->flags & LF_FUNCTION) {
i=PrsPop(ps);
tempc=PrsPop(ps);
}
if (l->flags & LF_EAX)
return PRST_CHECK_BINARY_OPS;
tempi=l->cb.cb_last_out_ptr;
tempc=tempi->ic_class-sizeof(ClassStruct);
if (l->flags & LF_ARRAY) {
tempi->ic_class=tempc;
return PRST_CHECK_BINARY_OPS;
}
if (l->flags & LF_PREINC) {
l->flags&=~LF_PREINC;
i=EC_PP_U8;
} else if (l->flags & LF_PREDEC) {
l->flags&=~LF_PREDEC;
i=EC_MM_U8;
} else if (l->flags & LF_POSTINC) {
l->flags&=~LF_POSTINC;
i=EC_U8_PP;
} else if (l->flags & LF_POSTDEC) {
l->flags&=~LF_POSTDEC;
i=EC_U8_MM;
} else
i=EC_DEREF_U8;
while (tempc->return_class)
tempc=tempc->return_class;
if (tempc->type & HTT_INTERNAL_TYPE)
i+=it_to_ec_offset[tempc->sub_type];
else
i+=it_to_ec_offset[IT_U4];
CbAddIc(l,i+0x10000,0,tempc);
return PRST_CHECK_BINARY_OPS;
}
U1 *CompileExpression(LexStruct *l)
{
U1 *result;
U8 size;
DbgInfo *dbg=NULL;
CbPush(l);
CbInitOutPtrs(&l->cb);
if (PrsParseExpression(l,TRUE)) {
CbAddIc(l,EC_RET,0,0);
CbAddIc(l,0,0,0);
result=CbCompile(l,NULL,&size,&dbg);
} else
result=NULL;
CbPop(l);
Free(dbg);
return result;
}
BoolU4 GetExpression(LexStruct *l,U1 **e) //FALSE=no err
{
*e=CompileExpression(l);
if (*e)
return TRUE;
else
return FALSE;
}
I8 Expression(LexStruct *l) //FALSE=no err
{
I8 result;
U1 *e=CompileExpression(l);
if (e) {
result=Run(e);
DelExpression(e);
} else
result=0;
return result;
}