1223 lines
33 KiB
HolyC
Executable File
1223 lines
33 KiB
HolyC
Executable File
CHashClass *PrsClass(CCmpCtrl *cc,I64 keyword,I64 fsp_flags,Bool is_extern)
|
||
{
|
||
CHashClass *tmpc,*base_class;
|
||
if (cc->token!=TK_IDENT)
|
||
LexExcept(cc,"Expecting identifier at ");
|
||
if (is_extern) {
|
||
tmpc=PrsClassNew;
|
||
tmpc->str=cc->cur_str;
|
||
cc->cur_str=NULL;
|
||
HashAdd(tmpc,cc->htc.glbl_hash_table);
|
||
LBts(&tmpc->flags,Cf_EXTERN);
|
||
HashSrcFileSet(cc,tmpc);
|
||
Lex(cc);
|
||
} else {
|
||
if (cc->flags&CCF_AOT_COMPILE)
|
||
tmpc=HashFind(cc->cur_str,cc->htc.glbl_hash_table,HTT_CLASS);
|
||
else
|
||
tmpc=HashSingleTableFind(cc->cur_str,cc->htc.glbl_hash_table,HTT_CLASS);
|
||
if (tmpc) {
|
||
if (!Bt(&tmpc->flags,Cf_EXTERN))
|
||
tmpc=NULL;
|
||
else if (tmpc->use_cnt<3)
|
||
UnusedExternWarning(cc,tmpc);
|
||
}
|
||
if (tmpc) {
|
||
Free(tmpc->src_link);
|
||
tmpc->src_link=NULL;
|
||
Free(tmpc->idx);
|
||
tmpc->idx=NULL;
|
||
} else {
|
||
tmpc=PrsClassNew;
|
||
tmpc->str=cc->cur_str;
|
||
cc->cur_str=NULL;
|
||
HashAdd(tmpc,cc->htc.glbl_hash_table);
|
||
}
|
||
LBtr(&tmpc->flags,Cf_EXTERN);
|
||
if (fsp_flags&FSF_PUBLIC)
|
||
tmpc->type|=HTF_PUBLIC;
|
||
tmpc->use_cnt=0;
|
||
if (cc->last_U16=='\n')
|
||
HashSrcFileSet(cc,tmpc,-1);
|
||
else
|
||
HashSrcFileSet(cc,tmpc,0);
|
||
if (Lex(cc)==':') {
|
||
if (Lex(cc)!=TK_IDENT || !(base_class=cc->hash_entry) ||
|
||
!(base_class->type&HTT_CLASS))
|
||
LexExcept(cc,"Invalid class at ");
|
||
if (Lex(cc)==',')
|
||
LexExcept(cc,"Only one base class allowed at this time at ");
|
||
tmpc->base_class=base_class;
|
||
tmpc->size+=base_class->size;
|
||
}
|
||
if (keyword==KW_UNION)
|
||
PrsVarLst(cc,tmpc,PRS0_NULL|PRS1_CLASS|PRSF_UNION);
|
||
else
|
||
PrsVarLst(cc,tmpc,PRS0_NULL|PRS1_CLASS);
|
||
tmpc->size+=tmpc->neg_offset;
|
||
}
|
||
return tmpc;
|
||
}
|
||
|
||
CHashFun *PrsFunJoin(CCmpCtrl *cc,CHashClass *tmp_return,
|
||
U8 *name,I64 fsp_flags)
|
||
{
|
||
CMemberLst *tmpm,*header_lst;
|
||
CAOTCtrl *aotc=cc->aotc;
|
||
CHashClass *header_return;
|
||
CHashFun *tmpf;
|
||
I64 header_arg_cnt;
|
||
if (name) {//if not fun_ptr
|
||
if (cc->flags&CCF_AOT_COMPILE) {
|
||
if ((tmpf=HashFind(name,cc->htc.glbl_hash_table,HTT_FUN)) &&
|
||
tmpf->type & HTF_IMPORT)
|
||
tmpf=NULL;
|
||
} else
|
||
if ((tmpf=HashSingleTableFind(name,cc->htc.glbl_hash_table,HTT_FUN)) &&
|
||
!Bt(&tmpf->flags,Cf_EXTERN))
|
||
tmpf=NULL;
|
||
if (tmpf && tmpf->use_cnt<3)
|
||
UnusedExternWarning(cc,tmpf);
|
||
} else
|
||
tmpf=NULL;
|
||
if (tmpf) {
|
||
tmpf->used_reg_mask=REGG_CLOBBERED+REGG_SAVED+REGG_STK_TMP;
|
||
Free(tmpf->src_link);
|
||
tmpf->src_link=NULL;
|
||
Free(tmpf->idx);
|
||
tmpf->idx=NULL;
|
||
Free(name);
|
||
header_arg_cnt=tmpf->arg_cnt;
|
||
header_lst=tmpf->member_lst_and_root;
|
||
header_return=tmpf->return_class;
|
||
tmpf->member_lst_and_root=NULL;
|
||
ClassMemberLstDel(tmpf);
|
||
} else {
|
||
tmpf=PrsFunNew;
|
||
header_return=NULL;
|
||
tmpf->used_reg_mask=REGG_CLOBBERED+REGG_SAVED+REGG_STK_TMP;
|
||
tmpf->clobbered_reg_mask=REGG_CLOBBERED+REGG_STK_TMP;
|
||
tmpf->str=name;
|
||
if (cc->flags&CCF_AOT_COMPILE)
|
||
tmpf->exe_addr=aotc->rip;
|
||
else
|
||
tmpf->exe_addr=&UndefinedExtern;
|
||
LBts(&tmpf->flags,Cf_EXTERN);
|
||
tmpf->flags|=fsp_flags&FSG_FUN_FLAGS1;
|
||
if (name) //if not fun_ptr
|
||
HashAdd(tmpf,cc->htc.glbl_hash_table);
|
||
}
|
||
BEqu(&tmpf->type,HTf_PUBLIC,fsp_flags&FSF_PUBLIC);
|
||
tmpf->return_class=tmp_return;
|
||
tmpf->use_cnt=0;
|
||
HashSrcFileSet(cc,tmpf);
|
||
PrsVarLst(cc,tmpf,PRS0_NULL|PRS1_FUN_ARG);
|
||
tmpf->arg_cnt=tmpf->member_cnt;
|
||
if (0<tmpf->arg_cnt<<3<=I16_MAX && !Bt(&tmpf->flags,Ff_DOT_DOT_DOT))
|
||
LBts(&tmpf->flags,Ff_RET1);
|
||
tmpm=tmpf->member_lst_and_root;
|
||
while (tmpm) {
|
||
tmpm->offset+=16; //RBP+RETURN
|
||
tmpm=tmpm->next;
|
||
}
|
||
tmpf->size=0;
|
||
if (header_return) {
|
||
if (GetOption(OPTf_WARN_HEADER_MISMATCH)) {
|
||
if (tmpf->return_class!=header_return) {
|
||
PrintWarn("Fun Header return mismatch '%s'\n",tmpf->str);
|
||
cc->warning_cnt++;
|
||
}
|
||
if (!MemberLstCmp(tmpf->member_lst_and_root,header_lst,header_arg_cnt)) {
|
||
PrintWarn("Fun header args mismatch '%s'\n",tmpf->str);
|
||
cc->warning_cnt++;
|
||
}
|
||
}
|
||
MemberLstDel(header_lst);
|
||
}
|
||
return tmpf;
|
||
}
|
||
|
||
U0 PrsFun(CCmpCtrl *cc,CHashClass *tmp_return,U8 *name,I64 fsp_flags)
|
||
{
|
||
CMemberLst *tmpm;
|
||
CCodeMisc *saved_leave_label;
|
||
I64 i,j,size,*r;
|
||
Bool old_trace;
|
||
|
||
cc->fun_lex_file=cc->lex_include_stk;
|
||
cc->min_line=cc->max_line=cc->lex_include_stk->line_num;
|
||
|
||
cc->flags&=~CCF_NO_REG_OPT;
|
||
cc->htc.local_var_lst=cc->htc.fun=PrsFunJoin(cc,tmp_return,name,fsp_flags);
|
||
|
||
COCPush(cc);
|
||
Btr(&cc->flags,CCf_PASS_TRACE_PRESENT);
|
||
COCInit(cc);
|
||
ICAdd(cc,IC_ENTER,0,0);
|
||
saved_leave_label=cc->lb_leave;
|
||
cc->lb_leave=COCMiscNew(cc,CMT_LABEL);
|
||
cc->flags&=~CCF_HAS_RETURN;
|
||
PrsStmt(cc,,,0);
|
||
|
||
if (cc->max_line<cc->min_line)
|
||
cc->max_line=cc->min_line;
|
||
|
||
if (cc->htc.fun->return_class->size && !(cc->flags&CCF_HAS_RETURN))
|
||
LexWarn(cc,"Function should return val ");
|
||
ICAdd(cc,IC_LABEL,cc->lb_leave,0);
|
||
cc->lb_leave=saved_leave_label;
|
||
ICAdd(cc,IC_LEAVE,0,cc->htc.fun->return_class);
|
||
cc->htc.fun->size&=~7;
|
||
if (cc->flags&CCF_AOT_COMPILE) {
|
||
cc->htc.fun->exe_addr=cc->aotc->rip;
|
||
cc->htc.fun->type|=HTF_EXPORT|HTF_RESOLVE;
|
||
r=COCCompile(cc,&size,&cc->htc.fun->dbg_info,NULL);
|
||
if (r) {
|
||
j=(size+7)>>3;
|
||
for (i=0;i<j;i++)
|
||
AOTStoreCodeU64(cc,r[i]);
|
||
Free(r);
|
||
}
|
||
} else {
|
||
old_trace=Btr(&cc->opts,OPTf_TRACE);
|
||
cc->htc.fun->exe_addr=COCCompile(
|
||
cc,&size,&cc->htc.fun->dbg_info,NULL);
|
||
if (old_trace) {
|
||
Bts(&cc->opts,OPTf_TRACE);
|
||
Un(cc->htc.fun->exe_addr,size,64);
|
||
}
|
||
SysSymImportsResolve(cc->htc.fun->str);
|
||
}
|
||
LBtr(&cc->htc.fun->flags,Cf_EXTERN);
|
||
COCPop(cc);
|
||
tmpm=cc->htc.fun->member_lst_and_root;
|
||
while (tmpm) {
|
||
if (tmpm->flags & MLF_NO_UNUSED_WARN) {
|
||
if (tmpm->use_cnt>1&&StrCmp(tmpm->str,"_anon_"))
|
||
PrintWarn("Unneeded no_warn\n $$LK,\"FL:%s,%d\"$$'%s' in '%s'\n",
|
||
cc->lex_include_stk->full_name,cc->lex_include_stk->line_num,
|
||
tmpm->str,cc->htc.fun->str);
|
||
} else if (!tmpm->use_cnt && GetOption(OPTf_WARN_UNUSED_VAR))
|
||
PrintWarn("Unused var\n $$LK,\"FL:%s,%d\"$$'%s' in '%s'\n",
|
||
cc->lex_include_stk->full_name,cc->lex_include_stk->line_num,
|
||
tmpm->str,cc->htc.fun->str);
|
||
tmpm=tmpm->next;
|
||
}
|
||
cc->htc.local_var_lst=cc->htc.fun=cc->fun_lex_file=NULL;
|
||
}
|
||
|
||
U0 PrsGlblVarLst(CCmpCtrl *cc,I64 saved_mode,CHashClass *saved_tmpc,
|
||
I64 saved_val,I64 fsp_flags)
|
||
{
|
||
I64 i,j,mode,k,val;
|
||
U8 *st;
|
||
CHashExport *tmpex;
|
||
CHashGlblVar *tmpg;
|
||
CAOTCtrl *aotc=cc->aotc;
|
||
CAOTHeapGlbl *tmphg;
|
||
CHashClass *tmpc;
|
||
CHashFun *tmpf,*tmpf_fun_ptr;
|
||
CArrayDim tmpad;
|
||
Bool has_alias,undef_array_size,is_array;
|
||
while (TRUE) {
|
||
tmpc=PrsType(cc,&saved_tmpc,&saved_mode,NULL,&st,
|
||
&tmpf_fun_ptr,&tmpex,&tmpad,fsp_flags);
|
||
|
||
if (!st) return;
|
||
if (tmpad.next)
|
||
is_array=TRUE;
|
||
else if (tmpad.total_cnt<0) {
|
||
is_array=TRUE;
|
||
tmpc--;
|
||
} else
|
||
is_array=FALSE;
|
||
|
||
val=saved_val;
|
||
mode=saved_mode;
|
||
if (tmpex && mode&255==PRS0_EXTERN && !(cc->flags&CCF_AOT_COMPILE) &&
|
||
tmpex->type&HTT_EXPORT_SYS_SYM) {
|
||
val=tmpex->val;
|
||
mode=PRS0__EXTERN|PRS1_NOT_REALLY__EXTERN;
|
||
}
|
||
if (cc->token=='(') {
|
||
switch (mode&255) {
|
||
case PRS0__INTERN:
|
||
tmpf=PrsFunJoin(cc,tmpc,st,fsp_flags);
|
||
tmpf->exe_addr=val;
|
||
Bts(&tmpf->flags,Ff_INTERNAL);
|
||
LBtr(&tmpf->flags,Cf_EXTERN);
|
||
return;
|
||
case PRS0__EXTERN:
|
||
if (!(fsp_flags&FSF__) && !(mode&PRS1_NOT_REALLY__EXTERN))
|
||
LexExcept(cc,"Expecting label with underscore at ");
|
||
tmpf=PrsFunJoin(cc,tmpc,st,fsp_flags);
|
||
tmpf->exe_addr=val;
|
||
SysSymImportsResolve(tmpf->str);
|
||
LBtr(&tmpf->flags,Cf_EXTERN);
|
||
if (saved_mode&255==PRS0__EXTERN)
|
||
LBts(&tmpf->flags,Ff__EXTERN);
|
||
if (cc->flags&CCF_AOT_COMPILE)
|
||
tmpf->type|=HTF_RESOLVE;
|
||
return;
|
||
case PRS0_EXTERN:
|
||
PrsFunJoin(cc,tmpc,st,fsp_flags);
|
||
return;
|
||
case PRS0__IMPORT:
|
||
if (!(fsp_flags&FSF__))
|
||
LexExcept(cc,"Expecting label with underscore at ");
|
||
case PRS0_IMPORT:
|
||
if (!(cc->flags&CCF_AOT_COMPILE))
|
||
LexExcept(cc,"import not needed at ");
|
||
else {
|
||
tmpf=PrsFunJoin(cc,tmpc,st,fsp_flags);
|
||
tmpf->type|=HTF_IMPORT;
|
||
if (mode&255==PRS0__IMPORT)
|
||
tmpf->import_name=StrNew(val);
|
||
else
|
||
tmpf->import_name=StrNew(st);
|
||
}
|
||
return;
|
||
default:
|
||
PrsFun(cc,tmpc,st,fsp_flags);
|
||
return;
|
||
}
|
||
} else {
|
||
if (tmpad.total_cnt<0) {
|
||
i=0;
|
||
undef_array_size=TRUE;
|
||
} else {
|
||
i=tmpad.total_cnt;
|
||
undef_array_size=FALSE;
|
||
}
|
||
if (tmpf_fun_ptr)
|
||
j=sizeof(U8 *);
|
||
else
|
||
j=tmpc->size;
|
||
j*=i;
|
||
has_alias=FALSE;
|
||
tmphg=NULL;
|
||
switch (mode&255) {
|
||
case PRS0__EXTERN:
|
||
if (cc->flags&CCF_AOT_COMPILE) {
|
||
tmpg=CAlloc(sizeof(CHashGlblVar));
|
||
tmpg->data_addr_rip=val;
|
||
tmpg->type=HTT_GLBL_VAR | HTF_EXPORT;
|
||
} else {
|
||
tmpg=CAlloc(sizeof(CHashGlblVar),Fs->code_heap);
|
||
tmpg->data_addr=val;
|
||
tmpg->type=HTT_GLBL_VAR;
|
||
}
|
||
tmpg->flags|=GVF_ALIAS;
|
||
break;
|
||
case PRS0__IMPORT:
|
||
case PRS0_IMPORT:
|
||
if (!(cc->flags&CCF_AOT_COMPILE))
|
||
LexExcept(cc,"import not needed at ");
|
||
else {
|
||
tmpg=CAlloc(sizeof(CHashGlblVar));
|
||
tmpg->type=HTT_GLBL_VAR | HTF_IMPORT;
|
||
if (mode&255==PRS0__IMPORT)
|
||
tmpg->import_name=StrNew(val);
|
||
else
|
||
tmpg->import_name=StrNew(st);
|
||
}
|
||
break;
|
||
case PRS0_EXTERN:
|
||
if (cc->flags&CCF_AOT_COMPILE) {
|
||
tmpg=CAlloc(sizeof(CHashGlblVar));
|
||
tmpg->type=HTT_GLBL_VAR;
|
||
} else {
|
||
tmpg=CAlloc(sizeof(CHashGlblVar),Fs->code_heap);
|
||
tmpg->type=HTT_GLBL_VAR|HTF_UNRESOLVED;
|
||
}
|
||
break;
|
||
default:
|
||
if (cc->flags&CCF_AOT_COMPILE) {
|
||
if (Bt(&cc->opts,OPTf_GLBLS_ON_DATA_HEAP)) {
|
||
if (cc->token=='=')
|
||
LexExcept(cc,"Can't init glbl var on data heap in AOT module ");
|
||
tmpg=CAlloc(sizeof(CHashGlblVar));
|
||
tmphg=tmpg->heap_glbl=CAlloc(sizeof(CAOTHeapGlbl));
|
||
tmphg->size=j;
|
||
tmphg->str=StrNew(st);
|
||
tmphg->next=aotc->heap_glbls;
|
||
aotc->heap_glbls=tmphg;
|
||
tmpg->flags=GVF_DATA_HEAP;
|
||
tmpg->type=HTT_GLBL_VAR; //TODO: HTF_EXPORT
|
||
if (tmpex && tmpex->type & HTT_GLBL_VAR) //TODO!! extern
|
||
LexExcept(cc,"Feature not implemented ");
|
||
} else {
|
||
tmpg=CAlloc(sizeof(CHashGlblVar));
|
||
if (cc->token=='=')
|
||
tmpg->data_addr=CAlloc(j);
|
||
if (tmpc->size>=8) //align
|
||
while (aotc->rip&7)
|
||
AOTStoreCodeU8(cc,0);
|
||
else if (tmpc->size==4)
|
||
while (aotc->rip&3)
|
||
AOTStoreCodeU8(cc,0);
|
||
else if (tmpc->size==2)
|
||
while (aotc->rip&1)
|
||
AOTStoreCodeU8(cc,0);
|
||
tmpg->data_addr_rip=aotc->rip;
|
||
tmpg->type=HTT_GLBL_VAR | HTF_EXPORT;
|
||
if (tmpex && tmpex->type & HTT_GLBL_VAR)
|
||
has_alias=TRUE;
|
||
for (k=0;k<j;k++)
|
||
AOTStoreCodeU8(cc,0); //Init AOT glbl to zero.
|
||
}
|
||
} else {
|
||
if (Bt(&cc->opts,OPTf_GLBLS_ON_DATA_HEAP)) {
|
||
tmpg=CAlloc(sizeof(CHashGlblVar),Fs->code_heap);
|
||
tmpg->data_addr=MAlloc(j);
|
||
tmpg->flags=GVF_DATA_HEAP;
|
||
} else {
|
||
tmpg=CAlloc(sizeof(CHashGlblVar),Fs->code_heap);
|
||
tmpg->data_addr=MAlloc(j,Fs->code_heap);
|
||
}
|
||
tmpg->type=HTT_GLBL_VAR;
|
||
if (tmpex && tmpex->type&HTT_GLBL_VAR &&
|
||
tmpex->type&HTF_UNRESOLVED &&
|
||
MHeapCtrl(tmpex)==MHeapCtrl(tmpg))
|
||
has_alias=TRUE;
|
||
if (sys_var_init_flag)
|
||
MemSet(tmpg->data_addr,sys_var_init_val,j);
|
||
}
|
||
}
|
||
tmpg->dim.next=tmpad.next;
|
||
if (fsp_flags&FSF_PUBLIC)
|
||
tmpg->type|=HTF_PUBLIC;
|
||
tmpg->var_class=tmpc;
|
||
tmpg->str=st;
|
||
tmpg->size=j;
|
||
tmpg->dim.total_cnt=i;
|
||
tmpg->use_cnt=0;
|
||
if (cc->last_U16=='\n')
|
||
HashSrcFileSet(cc,tmpg,-1);
|
||
else
|
||
HashSrcFileSet(cc,tmpg,0);
|
||
if (mode&255==PRS0_IMPORT || mode&255==PRS0__IMPORT)
|
||
tmpg->flags|=GVF_IMPORT;
|
||
if (mode&255==PRS0_EXTERN)
|
||
tmpg->flags|=GVF_EXTERN;
|
||
if (tmpf_fun_ptr) {
|
||
tmpg->fun_ptr=tmpf_fun_ptr;
|
||
tmpg->flags|=GVF_FUN;
|
||
}
|
||
if (is_array)
|
||
tmpg->flags|=GVF_ARRAY;
|
||
HashAdd(tmpg,cc->htc.glbl_hash_table);
|
||
if (!(cc->flags&CCF_AOT_COMPILE) && !(tmpg->flags&GVF_EXTERN))
|
||
SysSymImportsResolve(tmpg->str);
|
||
if (cc->token=='=') {
|
||
if (undef_array_size) {
|
||
LexPush(cc);
|
||
LexPush(cc);
|
||
Lex(cc);
|
||
PrsGlblInit(cc,tmpg,1);
|
||
LexPopNoRestore(cc);
|
||
tmpg->size=tmpg->dim.total_cnt*tmpc->size;
|
||
if (tmphg)
|
||
tmphg->size=tmpg->size;
|
||
if (cc->flags&CCF_AOT_COMPILE)
|
||
for (k=0;k<tmpg->size;k++)
|
||
AOTStoreCodeU8(cc,0);
|
||
else
|
||
if (sys_var_init_flag)
|
||
MemSet(tmpg->data_addr,sys_var_init_val,k);
|
||
LexPopRestore(cc);
|
||
}
|
||
LexPush(cc);
|
||
Lex(cc);
|
||
PrsGlblInit(cc,tmpg,2);
|
||
if (cc->flags&CCF_AOT_COMPILE)
|
||
for (k=0;k<tmpg->size;k++)
|
||
AOTStoreCodeU8At(cc,tmpg->data_addr_rip+k,tmpg->data_addr[k]);
|
||
LexPopNoRestore(cc);
|
||
}
|
||
if (has_alias) {
|
||
if (tmpex(CHashGlblVar *)->use_cnt<2) {
|
||
PrintWarn("Unused extern '%s'\n",tmpex(CHashGlblVar *)->str);
|
||
cc->warning_cnt++;
|
||
}
|
||
tmpex(CHashGlblVar *)->flags|=GVF_ALIAS;
|
||
tmpex(CHashGlblVar *)->data_addr=tmpg->data_addr;
|
||
tmpex(CHashGlblVar *)->data_addr_rip=tmpg->data_addr_rip;
|
||
}
|
||
if (cc->token==',')
|
||
Lex(cc);
|
||
else {
|
||
if (cc->token!=';')
|
||
LexExcept(cc,"Missing ';' at");
|
||
Lex(cc);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
U0 PrsIf(CCmpCtrl *cc,I64 try_cnt,CCodeMisc *lb_break)
|
||
{
|
||
CCodeMisc *lb,*lb1;
|
||
I64 k;
|
||
if (cc->token!='(')
|
||
LexExcept(cc,"Expecting '(' at ");
|
||
Lex(cc);
|
||
if (!PrsExpression(cc,NULL,FALSE))
|
||
throw('Compiler');
|
||
if (cc->token!=')')
|
||
LexExcept(cc,"Missing ')' at ");
|
||
Lex(cc);
|
||
lb=COCMiscNew(cc,CMT_LABEL);
|
||
ICAdd(cc,IC_BR_ZERO,lb,0);
|
||
PrsStmt(cc,try_cnt,lb_break);
|
||
k=PrsKeyWord(cc);
|
||
if (k==KW_ELSE) {
|
||
Lex(cc);
|
||
lb1=COCMiscNew(cc,CMT_LABEL);
|
||
ICAdd(cc,IC_JMP,lb1,0);
|
||
ICAdd(cc,IC_LABEL,lb,0);
|
||
PrsStmt(cc,try_cnt,lb_break);
|
||
ICAdd(cc,IC_LABEL,lb1,0);
|
||
} else
|
||
ICAdd(cc,IC_LABEL,lb,0);
|
||
}
|
||
|
||
U0 PrsWhile(CCmpCtrl *cc,I64 try_cnt)
|
||
{
|
||
CCodeMisc *lb,*lb_done;
|
||
if (cc->token!='(')
|
||
LexExcept(cc,"Expecting '(' at ");
|
||
Lex(cc);
|
||
lb=COCMiscNew(cc,CMT_LABEL);
|
||
ICAdd(cc,IC_LABEL,lb,0);
|
||
if (!PrsExpression(cc,NULL,FALSE))
|
||
throw('Compiler');
|
||
if (cc->token!=')')
|
||
LexExcept(cc,"Missing ')' at ");
|
||
Lex(cc);
|
||
lb_done=COCMiscNew(cc,CMT_LABEL);
|
||
ICAdd(cc,IC_BR_ZERO,lb_done,0);
|
||
PrsStmt(cc,try_cnt,lb_done);
|
||
ICAdd(cc,IC_JMP,lb,0);
|
||
ICAdd(cc,IC_LABEL,lb_done,0);
|
||
}
|
||
|
||
U0 PrsDoWhile(CCmpCtrl *cc,I64 try_cnt)
|
||
{
|
||
CCodeMisc *lb,*lb_done;
|
||
lb=COCMiscNew(cc,CMT_LABEL);
|
||
lb_done=COCMiscNew(cc,CMT_LABEL);
|
||
ICAdd(cc,IC_LABEL,lb,0);
|
||
PrsStmt(cc,try_cnt,lb_done);
|
||
if (PrsKeyWord(cc)!=KW_WHILE)
|
||
LexExcept(cc,"Missing 'while' at");
|
||
if (Lex(cc)!='(')
|
||
LexExcept(cc,"Expecting '(' at ");
|
||
Lex(cc);
|
||
if (!PrsExpression(cc,NULL,FALSE))
|
||
throw('Compiler');
|
||
if (cc->token!=')')
|
||
LexExcept(cc,"Missing ')' at ");
|
||
ICAdd(cc,IC_BR_NOT_ZERO,lb,0);
|
||
ICAdd(cc,IC_LABEL,lb_done,0);
|
||
if (Lex(cc)!=';')
|
||
LexExcept(cc,"Missing ';' at");
|
||
Lex(cc);
|
||
}
|
||
|
||
U0 PrsFor(CCmpCtrl *cc,I64 try_cnt)
|
||
{
|
||
CCodeCtrl *tmpcbh;
|
||
CCodeMisc *lb,*lb_done;
|
||
|
||
if (cc->token!='(')
|
||
LexExcept(cc,"Expecting '(' at ");
|
||
Lex(cc);
|
||
PrsStmt(cc,try_cnt);
|
||
|
||
lb=COCMiscNew(cc,CMT_LABEL);
|
||
ICAdd(cc,IC_LABEL,lb,0);
|
||
if (!PrsExpression(cc,NULL,FALSE))
|
||
throw('Compiler');
|
||
lb_done=COCMiscNew(cc,CMT_LABEL);
|
||
ICAdd(cc,IC_BR_ZERO,lb_done,0);
|
||
if (cc->token!=';')
|
||
LexExcept(cc,"Missing ';' at");
|
||
Lex(cc);
|
||
|
||
COCPush(cc);
|
||
COCInit(cc);
|
||
if (cc->token!=')')
|
||
PrsStmt(cc,try_cnt,NULL,0);
|
||
COCPush(cc);
|
||
tmpcbh=COCPopNoFree(cc);
|
||
COCPop(cc);
|
||
if (cc->token!=')')
|
||
LexExcept(cc,"Missing ')' at ");
|
||
Lex(cc);
|
||
|
||
PrsStmt(cc,try_cnt,lb_done);
|
||
COCAppend(cc,tmpcbh);
|
||
ICAdd(cc,IC_JMP,lb,0);
|
||
ICAdd(cc,IC_LABEL,lb_done,0);
|
||
}
|
||
|
||
class CSubSwitch {
|
||
CSubSwitch *next,*last;
|
||
CCodeMisc *lb_start,*lb_break;
|
||
};
|
||
|
||
class CSwitchCase {
|
||
CSwitchCase *next;
|
||
CCodeMisc *label;
|
||
I64 val;
|
||
CSubSwitch *ss;
|
||
};
|
||
|
||
U0 PrsSwitch(CCmpCtrl *cc,I64 try_cnt)
|
||
{
|
||
CSwitchCase *header=NULL,*tmps,*tmps1; //Leaks on except
|
||
CSubSwitch head,*tmpss; //Leaks on except
|
||
CCodeMisc *lb_dft,*lb_fwd_case,*mc_jt,*lb_entry,**jmp_table;
|
||
CIntermediateCode *tmpi_sub,*tmpi_cmp,*tmpi_jmp,*tmpi_start;
|
||
Bool dft_found=FALSE,nobound;
|
||
I64 i,k_start=I64_MIN,k_end,lo=I64_MAX,hi=I64_MIN,range;
|
||
|
||
if (cc->token=='(')
|
||
nobound=FALSE;
|
||
else if (cc->token=='[')
|
||
nobound=TRUE;
|
||
else
|
||
LexExcept(cc,"Expecting '(' or '[' at ");
|
||
Lex(cc);
|
||
QueInit(&head);
|
||
|
||
head.last->lb_break=COCMiscNew(cc,CMT_LABEL);
|
||
head.last->lb_break->use_cnt++;
|
||
lb_dft=COCMiscNew(cc,CMT_LABEL);
|
||
lb_dft->use_cnt++;
|
||
mc_jt=COCMiscNew(cc,CMT_JMP_TABLE);
|
||
mc_jt->begin=COCMiscNew(cc,CMT_LABEL);
|
||
mc_jt->begin->use_cnt++;
|
||
if (!PrsExpression(cc,NULL,FALSE))
|
||
throw('Compiler');
|
||
tmpi_sub=ICAdd(cc,IC_IMM_I64,0,cmp.internal_types[RT_I64]);
|
||
ICAdd(cc,IC_SUB,0,cmp.internal_types[RT_I64]);
|
||
tmpi_cmp=ICAdd(cc,IC_IMM_I64,0,cmp.internal_types[RT_I64]);
|
||
if (nobound) {
|
||
ICAdd(cc,IC_NOBOUND_SWITCH,mc_jt,0);
|
||
if (cc->token!=']')
|
||
LexExcept(cc,"Missing ']' at ");
|
||
} else {
|
||
ICAdd(cc,IC_SWITCH,mc_jt,0);
|
||
if (cc->token!=')')
|
||
LexExcept(cc,"Missing ')' at ");
|
||
}
|
||
if (Lex(cc)!='{')
|
||
LexExcept(cc,"Expecting '{' at ");
|
||
Lex(cc);
|
||
ICAdd(cc,IC_LABEL,mc_jt->begin,0);
|
||
while (TRUE) {
|
||
while (cc->token && cc->token!='}') {
|
||
sw_cont:
|
||
switch (PrsKeyWord(cc)) {
|
||
case KW_END:
|
||
goto sw_sub_end;
|
||
case KW_START:
|
||
if (Lex(cc)==':')
|
||
Lex(cc);
|
||
else
|
||
LexExcept(cc,"Expecting ':' at ");
|
||
tmpss=MAlloc(sizeof(CSubSwitch));
|
||
QueIns(tmpss,head.last);
|
||
head.last->lb_break=COCMiscNew(cc,CMT_LABEL);
|
||
head.last->lb_break->use_cnt++;
|
||
lb_fwd_case=COCMiscNew(cc,CMT_LABEL);
|
||
tmpi_jmp=ICAdd(cc,IC_JMP,lb_fwd_case,0);
|
||
|
||
tmpss->lb_start=COCMiscNew(cc,CMT_LABEL);
|
||
tmpi_start=ICAdd(cc,IC_LABEL,tmpss->lb_start,0);
|
||
while (cc->token && cc->token!='}') {
|
||
switch (PrsKeyWord(cc)) {
|
||
case KW_END:
|
||
OptFree(tmpi_jmp);
|
||
goto sw_sub_end;
|
||
case KW_START:
|
||
case KW_CASE:
|
||
case KW_DFT:
|
||
if (cc->coc.coc_head.last==tmpi_start) {
|
||
OptFree(tmpi_jmp);
|
||
tmpss->lb_start=NULL;
|
||
} else {
|
||
ICAdd(cc,IC_RET,0,0);
|
||
ICAdd(cc,IC_LABEL,lb_fwd_case,0);
|
||
ICAdd(cc,IC_SUB_CALL,tmpss->lb_start,0);//In case fall-thru
|
||
}
|
||
goto sw_cont;
|
||
default:
|
||
PrsStmt(cc,try_cnt);
|
||
}
|
||
}
|
||
break;
|
||
case KW_CASE:
|
||
if (head.next!=&head) {
|
||
lb_fwd_case=COCMiscNew(cc,CMT_LABEL);
|
||
tmpi_jmp=ICAdd(cc,IC_JMP,lb_fwd_case,0);//In case fall-thru
|
||
}
|
||
Lex(cc);
|
||
lb_entry=COCMiscNew(cc,CMT_LABEL);
|
||
ICAdd(cc,IC_LABEL,lb_entry,0);
|
||
lb_entry->use_cnt++;
|
||
if (head.next!=&head) {
|
||
tmpss=head.next;
|
||
while (tmpss!=&head) {
|
||
if (tmpss->lb_start)
|
||
ICAdd(cc,IC_SUB_CALL,tmpss->lb_start,0);
|
||
tmpss=tmpss->next;
|
||
}
|
||
ICAdd(cc,IC_LABEL,lb_fwd_case,0);
|
||
}
|
||
if (cc->token==':') {
|
||
if (k_start==I64_MIN)
|
||
k_start=0;
|
||
else
|
||
k_start++;
|
||
} else
|
||
k_start=LexExpressionI64(cc);
|
||
if (k_start<lo) lo=k_start;
|
||
if (k_start>hi) hi=k_start;
|
||
if (cc->token==':') {
|
||
Lex(cc);
|
||
tmps=MAlloc(sizeof(CSwitchCase));
|
||
tmps->label=lb_entry;
|
||
tmps->val=k_start;
|
||
tmps->next=header;
|
||
header=tmps;
|
||
} else if (cc->token==TK_ELLIPSIS) {
|
||
Lex(cc);
|
||
k_end=LexExpressionI64(cc);
|
||
if (cc->token==':') {
|
||
Lex(cc);
|
||
if (k_end<lo) lo=k_end;
|
||
if (k_end>hi) hi=k_end;
|
||
if (k_start>k_end)
|
||
SwapI64(&k_start,&k_end);
|
||
for (i=k_start;i<=k_end;i++) {
|
||
tmps=MAlloc(sizeof(CSwitchCase));
|
||
tmps->label=lb_entry;
|
||
tmps->val=i;
|
||
tmps->next=header;
|
||
header=tmps;
|
||
}
|
||
k_start=k_end;
|
||
} else
|
||
LexExcept(cc,"Expecting ':' at ");
|
||
} else
|
||
LexExcept(cc,"Expecting ':' at ");
|
||
break;
|
||
case KW_DFT:
|
||
if (head.next!=&head) {
|
||
lb_fwd_case=COCMiscNew(cc,CMT_LABEL);
|
||
tmpi_jmp=ICAdd(cc,IC_JMP,lb_fwd_case,0);//In case fall-thru
|
||
}
|
||
Lex(cc);
|
||
ICAdd(cc,IC_LABEL,lb_dft,0);
|
||
if (cc->token==':')
|
||
Lex(cc);
|
||
else
|
||
LexExcept(cc,"Expecting ':' at ");
|
||
if (head.next!=&head) {
|
||
tmpss=head.next;
|
||
while (tmpss!=&head) {
|
||
if (tmpss->lb_start)
|
||
ICAdd(cc,IC_SUB_CALL,tmpss->lb_start,0);
|
||
tmpss=tmpss->next;
|
||
}
|
||
ICAdd(cc,IC_LABEL,lb_fwd_case,0);
|
||
}
|
||
dft_found=TRUE;
|
||
break;
|
||
default:
|
||
PrsStmt(cc,try_cnt,head.last->lb_break);
|
||
}
|
||
}
|
||
sw_sub_end:
|
||
tmpss=head.last;
|
||
ICAdd(cc,IC_LABEL,tmpss->lb_break,0);
|
||
if (tmpss==&head) {
|
||
if (cc->token!='}')
|
||
LexExcept(cc,"Missing '}' at ");
|
||
Lex(cc);
|
||
break;
|
||
} else {
|
||
QueRem(tmpss);
|
||
Free(tmpss);
|
||
if (PrsKeyWord(cc)!=KW_END)
|
||
LexExcept(cc,"Missing 'end' at ");
|
||
if (Lex(cc)==':')
|
||
Lex(cc);
|
||
else
|
||
LexExcept(cc,"Expecting ':' at ");
|
||
}
|
||
}
|
||
if (!dft_found)
|
||
ICAdd(cc,IC_LABEL,lb_dft,0);
|
||
|
||
if (0<lo<=16)
|
||
lo=0;
|
||
range=hi-lo+1;
|
||
if (lo>hi || !(0<range<=0xFFFF))
|
||
LexExcept(cc,"switch range error at ");
|
||
jmp_table=MAlloc((sizeof(CCodeMisc *)*range+0x1FF)&~0x1FF);
|
||
MemSetI64(jmp_table,lb_dft,range);
|
||
tmpi_sub->ic_data=lo;
|
||
tmpi_cmp->ic_data=range;
|
||
tmps=header;
|
||
while (tmps) {
|
||
tmps1=tmps->next;
|
||
if (jmp_table[tmps->val-lo]!=lb_dft)
|
||
LexExcept(cc,"Duplicate case at ");
|
||
else
|
||
jmp_table[tmps->val-lo]=tmps->label;
|
||
Free(tmps);
|
||
tmps=tmps1;
|
||
}
|
||
mc_jt->dft=lb_dft;
|
||
mc_jt->jmp_table=jmp_table;
|
||
mc_jt->range=range;
|
||
}
|
||
|
||
U0 PrsNoWarn(CCmpCtrl *cc)
|
||
{
|
||
CMemberLst *tmpm;
|
||
while (cc->token==TK_IDENT) {
|
||
if (!(tmpm=cc->local_var_entry))
|
||
LexExcept(cc,"Expecting local var at ");
|
||
tmpm->flags|=MLF_NO_UNUSED_WARN;
|
||
if (Lex(cc)==',')
|
||
Lex(cc);
|
||
else if (cc->token!=';')
|
||
LexExcept(cc,"Expecting ',' at ");
|
||
}
|
||
}
|
||
|
||
U0 PrsStreamBlk(CCmpCtrl *cc)
|
||
{
|
||
CLexHashTableContext *htc=MAlloc(sizeof(CLexHashTableContext));
|
||
CStreamBlk *tmpe=MAlloc(sizeof(CStreamBlk));
|
||
tmpe->body=StrNew("");
|
||
QueIns(tmpe,cc->last_stream_blk);
|
||
COCPush(cc);
|
||
QueInit(&cc->coc.coc_next_misc);
|
||
|
||
MemCpy(htc,&cc->htc,sizeof(CLexHashTableContext));
|
||
htc->old_flags=cc->flags;
|
||
cc->htc.next=htc;
|
||
cc->htc.fun=cc->htc.local_var_lst=NULL;
|
||
cc->htc.define_hash_table=cc->htc.hash_table_lst=
|
||
cc->htc.glbl_hash_table=cc->htc.local_hash_table=Fs->hash_table;
|
||
cc->flags=cc->flags & ~(CCF_ASM_EXPRESSIONS|CCF_AOT_COMPILE) | CCF_EXE_BLK;
|
||
if (cc->token=='{')
|
||
Lex(cc);
|
||
else
|
||
LexExcept(cc,"Missing '}' at ");
|
||
while (cc->token && cc->token!='}')
|
||
ExeCmdLine(cc);
|
||
|
||
MemCpy(&cc->htc,htc,sizeof(CLexHashTableContext));
|
||
cc->flags=cc->flags&~CCF_EXE_BLK |
|
||
htc->old_flags & (CCF_ASM_EXPRESSIONS|CCF_EXE_BLK|CCF_AOT_COMPILE);
|
||
Free(htc);
|
||
COCPop(cc);
|
||
QueRem(tmpe);
|
||
if (*tmpe->body)
|
||
LexIncludeStr(cc,"StreamBlk",tmpe->body,FALSE);
|
||
else
|
||
Free(tmpe->body);
|
||
Free(tmpe);
|
||
Lex(cc); //Skip '}'
|
||
}
|
||
|
||
U0 PrsTryBlk(CCmpCtrl *cc,I64 try_cnt)
|
||
{
|
||
CCodeMisc *lb_catch,*lb_done,*lb_untry;
|
||
CHashClass *tmpc=cmp.internal_types[RT_PTR];
|
||
CHashFun *tmp_try=HashFind("SysTry",cc->htc.hash_table_lst,HTT_FUN),
|
||
*tmp_untry=HashFind("SysUntry",cc->htc.hash_table_lst,HTT_FUN);
|
||
|
||
if (!tmp_try || !tmp_untry)
|
||
LexExcept(cc,"Missing header for SysTry() and SysUntry() at ");
|
||
|
||
cc->flags|=CCF_NO_REG_OPT; //TODO:Currently no reg vars in funs with try/catch
|
||
|
||
lb_catch=COCMiscNew(cc,CMT_LABEL);
|
||
lb_done =COCMiscNew(cc,CMT_LABEL);
|
||
lb_untry=COCMiscNew(cc,CMT_LABEL);
|
||
|
||
ICAdd(cc,IC_CALL_START,0,0);
|
||
ICAdd(cc,IC_GET_LABEL,lb_untry,tmpc,ICF_PUSH_RES);
|
||
ICAdd(cc,IC_GET_LABEL,lb_catch,tmpc,ICF_PUSH_RES);
|
||
if (Bt(&tmp_try->flags,Cf_EXTERN)) {
|
||
cc->abs_cnts.externs++;
|
||
if (cc->flags&CCF_AOT_COMPILE)
|
||
ICAdd(cc,IC_CALL_IMPORT,tmp_try,tmpc);
|
||
else
|
||
ICAdd(cc,IC_CALL_INDIRECT2,&tmp_try->exe_addr,tmpc);
|
||
} else
|
||
ICAdd(cc,IC_CALL,tmp_try->exe_addr,tmpc);
|
||
if ((Bt(&tmp_try->flags,Ff_RET1) ||
|
||
Bt(&tmp_try->flags,Ff_ARGPOP)) && !Bt(&tmp_try->flags,Ff_NOARGPOP))
|
||
ICAdd(cc,IC_ADD_RSP1,16,tmpc);
|
||
else
|
||
ICAdd(cc,IC_ADD_RSP,16,tmpc);
|
||
ICAdd(cc,IC_CALL_END,0,tmpc);
|
||
ICAdd(cc,IC_END_EXP,0,0,ICF_RES_NOT_USED);
|
||
|
||
PrsStmt(cc,try_cnt+1);
|
||
|
||
ICAdd(cc,IC_LABEL,lb_untry,0);
|
||
ICAdd(cc,IC_CALL_START,0,0);
|
||
if (Bt(&tmp_untry->flags,Cf_EXTERN)) {
|
||
cc->abs_cnts.externs++;
|
||
if (cc->flags&CCF_AOT_COMPILE)
|
||
ICAdd(cc,IC_CALL_IMPORT,tmp_untry,tmpc);
|
||
else
|
||
ICAdd(cc,IC_CALL_INDIRECT2,&tmp_untry->exe_addr,tmpc);
|
||
} else
|
||
ICAdd(cc,IC_CALL,tmp_untry->exe_addr,tmpc);
|
||
ICAdd(cc,IC_CALL_END,0,tmpc);
|
||
ICAdd(cc,IC_END_EXP,0,0,ICF_RES_NOT_USED);
|
||
|
||
ICAdd(cc,IC_JMP,lb_done,0);
|
||
|
||
if (PrsKeyWord(cc)!=KW_CATCH)
|
||
LexExcept(cc,"Missing 'catch' at");
|
||
|
||
Lex(cc);
|
||
ICAdd(cc,IC_LABEL,lb_catch,0);
|
||
PrsStmt(cc,try_cnt+1);
|
||
ICAdd(cc,IC_RET,0,tmpc);
|
||
ICAdd(cc,IC_LABEL,lb_done,0);
|
||
}
|
||
|
||
Bool PrsStmt(CCmpCtrl *cc,I64 try_cnt=0,
|
||
CCodeMisc *lb_break=NULL,I64 cmp_flags=CMPF_PRS_SEMICOLON)
|
||
{
|
||
I64 i,fsp_flags=0;
|
||
CHashExport *tmpex;
|
||
CCodeMisc *g_lb;
|
||
U8 *import_name;
|
||
CHashFun *tmp_untry;
|
||
CAOT *tmpaot;
|
||
if (cmp_flags&CMPF_ONE_ASM_INS) {
|
||
if (cc->flags&CCF_AOT_COMPILE || cc->aot_depth)
|
||
PrsAsmBlk(cc,CMPF_ONE_ASM_INS);
|
||
else if (tmpaot=CmpJoin(cc,CMPF_ASM_BLK|CMPF_ONE_ASM_INS))
|
||
CmpFixUpJITAsm(cc,tmpaot);
|
||
fsp_flags=FSF_ASM;
|
||
} else
|
||
while (TRUE) {
|
||
while (cc->token==',')
|
||
Lex(cc);
|
||
if (cc->token=='{') {
|
||
Lex(cc);
|
||
while (cc->token!='}' && cc->token!=TK_EOF)
|
||
PrsStmt(cc,try_cnt,lb_break);
|
||
if (cc->lex_include_stk==cc->fun_lex_file)
|
||
cc->max_line=cc->lex_include_stk->line_num;
|
||
if (Lex(cc)!=',') goto sm_done;
|
||
} else if (cc->token==';') {
|
||
if (cmp_flags&CMPF_PRS_SEMICOLON)
|
||
Lex(cc);
|
||
if (cc->token!=',') goto sm_done;
|
||
} else {
|
||
if (cc->token==TK_IDENT) {
|
||
if (tmpex=cc->hash_entry) {
|
||
if (tmpex->type & HTT_KEYWORD) {
|
||
i=tmpex(CHashGeneric *)->user_data0;
|
||
switch [i] {
|
||
case KW_KWS_NUM-1: //nobound switch
|
||
default: //A keyword that is not valid here is just a symbol.
|
||
goto sm_not_keyword_afterall;
|
||
start:
|
||
case KW_ASM:
|
||
if (cc->htc.fun) {
|
||
if (tmpaot=CmpJoin(cc,CMPF_ASM_BLK))
|
||
ICAdd(cc,IC_ASM,tmpaot,0);
|
||
Lex(cc); //Skip '}' of asm{}
|
||
} else {
|
||
if (cc->flags&CCF_AOT_COMPILE || cc->aot_depth) {
|
||
Lex(cc);
|
||
PrsAsmBlk(cc,0);
|
||
if (cc->flags&CCF_AOT_COMPILE && cc->aot_depth==1)
|
||
Lex(cc); //Skip '}' of asm{}
|
||
} else {
|
||
if (tmpaot=CmpJoin(cc,CMPF_ASM_BLK))
|
||
CmpFixUpJITAsm(cc,tmpaot);
|
||
Lex(cc); //Skip '}' of asm{}
|
||
}
|
||
fsp_flags=FSF_ASM;
|
||
}
|
||
break;
|
||
start:
|
||
Lex(cc);
|
||
case KW_LOCK:
|
||
cc->lock_cnt++;
|
||
PrsStmt(cc,try_cnt);
|
||
cc->lock_cnt--;
|
||
break;
|
||
case KW_TRY:
|
||
PrsTryBlk(cc,try_cnt);
|
||
break;
|
||
case KW_IF:
|
||
PrsIf(cc,try_cnt,lb_break);
|
||
break;
|
||
case KW_FOR:
|
||
PrsFor(cc,try_cnt);
|
||
break;
|
||
case KW_WHILE:
|
||
PrsWhile(cc,try_cnt);
|
||
break;
|
||
case KW_DO:
|
||
PrsDoWhile(cc,try_cnt);
|
||
break;
|
||
case KW_SWITCH:
|
||
PrsSwitch(cc,try_cnt);
|
||
break;
|
||
end:
|
||
end:
|
||
if (cc->token!=',') goto sm_done;
|
||
break;
|
||
start:
|
||
if (cc->htc.fun)
|
||
LexExcept(cc,"Not allowed in fun");
|
||
Lex(cc);
|
||
case KW__EXTERN:
|
||
if (Bt(&cc->opts,OPTf_EXTERNS_TO_IMPORTS))
|
||
goto sm_underscore_import;
|
||
if (cc->token!=TK_IDENT || !(tmpex=cc->hash_entry) ||
|
||
!(tmpex->type & HTT_EXPORT_SYS_SYM))
|
||
LexExcept(cc,"Expecting system sym at ");
|
||
if (*cc->cur_str=='_')
|
||
fsp_flags|=FSF__;
|
||
i=tmpex->val;
|
||
Lex(cc);
|
||
if (cc->token!=TK_IDENT || !(tmpex=cc->hash_entry) ||
|
||
!(tmpex->type & (HTT_CLASS|HTT_INTERNAL_TYPE)))
|
||
LexExcept(cc,"Expecting type at ");
|
||
Lex(cc);
|
||
PrsGlblVarLst(cc,PRS0__EXTERN|PRS1_NULL,tmpex,i,fsp_flags);
|
||
break;
|
||
case KW__IMPORT:
|
||
sm_underscore_import:
|
||
if (cc->token!=TK_IDENT)
|
||
LexExcept(cc,"Expecting system sym at ");
|
||
if (*cc->cur_str=='_')
|
||
fsp_flags|=FSF__;
|
||
import_name=cc->cur_str;
|
||
cc->cur_str=0;
|
||
if (Lex(cc)!=TK_IDENT || !(tmpex=cc->hash_entry) ||
|
||
!(tmpex->type & (HTT_CLASS|HTT_INTERNAL_TYPE)))
|
||
LexExcept(cc,"Expecting type at ");
|
||
Lex(cc);
|
||
PrsGlblVarLst(cc,PRS0__IMPORT|PRS1_NULL,tmpex,
|
||
import_name,fsp_flags);
|
||
Free(import_name);
|
||
break;
|
||
case KW_EXTERN:
|
||
if (cc->token!=TK_IDENT)
|
||
LexExcept(cc,"Expecting type at ");
|
||
tmpex=cc->hash_entry;
|
||
i=PrsKeyWord(cc);
|
||
if (i==KW_CLASS||i==KW_UNION) {
|
||
Lex(cc);
|
||
PrsClass(cc,i,fsp_flags,TRUE);
|
||
fsp_flags&=FSF_ASM;
|
||
goto sm_semicolon;
|
||
}
|
||
if (!tmpex ||
|
||
!(tmpex->type & (HTT_CLASS|HTT_INTERNAL_TYPE)))
|
||
LexExcept(cc,"Expecting type at ");
|
||
if (Bt(&cc->opts,OPTf_EXTERNS_TO_IMPORTS))
|
||
goto sm_import;
|
||
Lex(cc);
|
||
PrsGlblVarLst(cc,PRS0_EXTERN|PRS1_NULL,tmpex,0,fsp_flags);
|
||
break;
|
||
case KW_IMPORT:
|
||
if (cc->token!=TK_IDENT || !(tmpex=cc->hash_entry) ||
|
||
!(tmpex->type & (HTT_CLASS|HTT_INTERNAL_TYPE)))
|
||
LexExcept(cc,"Expecting type at ");
|
||
sm_import:
|
||
Lex(cc);
|
||
PrsGlblVarLst(cc,PRS0_IMPORT|PRS1_NULL,tmpex,0,fsp_flags);
|
||
break;
|
||
case KW__INTERN:
|
||
i=LexExpressionI64(cc);
|
||
if (cc->token!=TK_IDENT || !(tmpex=cc->hash_entry) ||
|
||
!(tmpex->type & (HTT_CLASS|HTT_INTERNAL_TYPE)))
|
||
LexExcept(cc,"Expecting type at ");
|
||
Lex(cc);
|
||
PrsGlblVarLst(cc,PRS0__INTERN|PRS1_NULL,tmpex,i,fsp_flags);
|
||
break;
|
||
end:
|
||
fsp_flags&=FSF_ASM;
|
||
break;
|
||
start:
|
||
case KW_STATIC:
|
||
fsp_flags=FSF_STATIC|fsp_flags&FSF_ASM;
|
||
break;
|
||
case KW_INTERRUPT:
|
||
fsp_flags=FSF_INTERRUPT|FSF_NOARGPOP|
|
||
fsp_flags&(FSG_FUN_FLAGS2|FSF_ASM);
|
||
break;
|
||
case KW_HASERRCODE:
|
||
fsp_flags=FSF_HASERRCODE|fsp_flags&(FSG_FUN_FLAGS2|FSF_ASM);
|
||
break;
|
||
case KW_ARGPOP:
|
||
fsp_flags=FSF_ARGPOP|fsp_flags&(FSG_FUN_FLAGS2|FSF_ASM);
|
||
break;
|
||
case KW_NOARGPOP:
|
||
fsp_flags=FSF_NOARGPOP|fsp_flags&(FSG_FUN_FLAGS2|FSF_ASM);
|
||
break;
|
||
case KW_PUBLIC:
|
||
fsp_flags=FSF_PUBLIC|fsp_flags&(FSG_FUN_FLAGS2|FSF_ASM);
|
||
break;
|
||
end:
|
||
Lex(cc);
|
||
break;
|
||
case KW_RETURN:
|
||
if (!cc->htc.fun)
|
||
LexExcept(cc,"Not in fun. Can't return a val ");
|
||
if (try_cnt) {
|
||
tmp_untry=HashFind("SysUntry",
|
||
cc->htc.hash_table_lst,HTT_FUN);
|
||
for (i=0;i<try_cnt;i++) {
|
||
if (Bt(&tmp_untry->flags,Cf_EXTERN)) {
|
||
cc->abs_cnts.externs++;
|
||
if (cc->flags&CCF_AOT_COMPILE)
|
||
ICAdd(cc,IC_CALL_IMPORT,
|
||
tmp_untry,cmp.internal_types[RT_PTR]);
|
||
else
|
||
ICAdd(cc,IC_CALL_INDIRECT2,
|
||
&tmp_untry->exe_addr,
|
||
cmp.internal_types[RT_PTR]);
|
||
} else
|
||
ICAdd(cc,IC_CALL,tmp_untry->exe_addr,
|
||
cmp.internal_types[RT_PTR]);
|
||
}
|
||
}
|
||
if (Lex(cc)!=';') {
|
||
if (!cc->htc.fun->return_class->size)
|
||
LexWarn(cc,"Function should NOT return val ");
|
||
if (!PrsExpression(cc,NULL,FALSE))
|
||
throw('Compiler');
|
||
ICAdd(cc,IC_RETURN_VAL,0,cc->htc.fun->return_class);
|
||
cc->flags|=CCF_HAS_RETURN;
|
||
} else if (cc->htc.fun->return_class->size)
|
||
LexWarn(cc,"Function should return val ");
|
||
ICAdd(cc,IC_JMP,cc->lb_leave,0);
|
||
goto sm_semicolon;
|
||
case KW_GOTO:
|
||
if (Lex(cc)!=TK_IDENT)
|
||
LexExcept(cc,"Expecting identifier at ");
|
||
if (!(g_lb=COCGoToLabelFind(cc,cc->cur_str))) {
|
||
g_lb=COCMiscNew(cc,CMT_GOTO_LABEL);
|
||
g_lb->str=cc->cur_str;
|
||
cc->cur_str=NULL;
|
||
}
|
||
g_lb->use_cnt++;
|
||
ICAdd(cc,IC_JMP,g_lb,0);
|
||
Lex(cc);
|
||
goto sm_semicolon;
|
||
case KW_BREAK:
|
||
Lex(cc);
|
||
if (!lb_break)
|
||
LexExcept(cc,"'break' not allowed\n");
|
||
ICAdd(cc,IC_JMP,lb_break,0);
|
||
goto sm_semicolon;
|
||
case KW_NO_WARN:
|
||
Lex(cc);
|
||
PrsNoWarn(cc);
|
||
goto sm_semicolon;
|
||
case KW_UNION:
|
||
case KW_CLASS:
|
||
Lex(cc);
|
||
tmpex=PrsClass(cc,i,fsp_flags,FALSE);
|
||
if (!cc->htc.fun && cc->token!=';') {
|
||
PrsGlblVarLst(cc,PRS0_NULL|PRS1_NULL,tmpex,0,fsp_flags);
|
||
fsp_flags&=FSF_ASM;
|
||
break;
|
||
} else {
|
||
fsp_flags&=FSF_ASM;
|
||
goto sm_semicolon;
|
||
}
|
||
}
|
||
} else {//Ident, found in hash table, not keyword
|
||
sm_not_keyword_afterall:
|
||
if (tmpex->type & (HTT_CLASS|HTT_INTERNAL_TYPE)) {
|
||
if (cc->htc.fun) {
|
||
if (fsp_flags&FSF_STATIC)
|
||
PrsVarLst(cc,cc->htc.fun,PRS0_NULL|PRS1_STATIC_LOCAL_VAR);
|
||
else
|
||
PrsVarLst(cc,cc->htc.fun,PRS0_NULL|PRS1_LOCAL_VAR);
|
||
if (cc->token=='}') goto sm_done;
|
||
} else {
|
||
Lex(cc);
|
||
PrsGlblVarLst(cc,PRS0_NULL|PRS1_NULL,tmpex,0,fsp_flags);
|
||
}
|
||
} else {
|
||
if (tmpex->type & (HTT_OPCODE|HTT_ASM_KEYWORD)) {
|
||
if (cc->htc.fun) {
|
||
if (tmpaot=CmpJoin(cc,CMPF_ASM_BLK|CMPF_ONE_ASM_INS))
|
||
ICAdd(cc,IC_ASM,tmpaot,0);
|
||
} else
|
||
LexExcept(cc,"Use Asm Blk at ");
|
||
if (cc->token!=',') goto sm_done;
|
||
} else
|
||
goto sm_prs_exp;
|
||
}
|
||
fsp_flags&=FSF_ASM;
|
||
}
|
||
} else {//Ident, not in hash table
|
||
if (cc->local_var_entry)
|
||
goto sm_prs_exp;
|
||
if (!(g_lb=COCGoToLabelFind(cc,cc->cur_str))) {
|
||
g_lb=COCMiscNew(cc,CMT_GOTO_LABEL);
|
||
g_lb->str=cc->cur_str;
|
||
cc->cur_str=NULL;
|
||
} else if (g_lb->flags&CMF_DEFINED)
|
||
LexExcept(cc,"Duplicate goto label at ");
|
||
g_lb->flags|=CMF_DEFINED;
|
||
ICAdd(cc,IC_LABEL,g_lb,0);
|
||
if (Lex(cc)==':') //skip cur_str
|
||
Lex(cc); //skip colon
|
||
else
|
||
LexExcept(cc,"Undefined identifier at ");
|
||
if (!cc->htc.fun)
|
||
LexExcept(cc,"No global labels at ");
|
||
if (cc->token!=',') goto sm_done;
|
||
}
|
||
} else if (cc->token==TK_STR||cc->token==TK_CHAR_CONST) {
|
||
PrsFunCall(cc,NULL,FALSE,NULL);
|
||
goto sm_semicolon;
|
||
} else if (cc->token!=TK_EOF) {//Non-cur_str symbol, num or something
|
||
sm_prs_exp:
|
||
if (!PrsExpression(cc,NULL,TRUE))
|
||
throw('Compiler');
|
||
sm_semicolon:
|
||
if (cmp_flags&CMPF_PRS_SEMICOLON) {
|
||
if (cc->token==';')
|
||
Lex(cc);
|
||
else if (cc->token!=',')
|
||
LexExcept(cc,"Missing ';' at");
|
||
}
|
||
if (cc->token!=',') goto sm_done;
|
||
} else
|
||
goto sm_done; //TK_EOF
|
||
}
|
||
}
|
||
sm_done:
|
||
return fsp_flags&FSF_ASM;
|
||
}
|