Files
TempleOS-Rijn/LT/Compiler/ExpParser.CPZ
T
2018-09-08 21:45:20 +02:00

838 lines
24 KiB
Plaintext

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<<CREG_RAX,tempc);
i=PrsPop(ps);
tempc=PrsPop(ps);
j=i;
Lex(lx); //skip '('
CbPush(lx);
templ=lx->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;
}