From 1d3b2319fd2be5975873f26b7eeb65a36d38313a Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Sat, 14 Sep 2019 12:42:47 +0700 Subject: [PATCH] Implement operator '__addressof' --- source/compiler/sc.h | 5 +++ source/compiler/sc2.c | 10 ++--- source/compiler/sc3.c | 97 +++++++++++++++++++++++++++++++++++++++++++ source/compiler/sc5.c | 3 +- 4 files changed, 109 insertions(+), 6 deletions(-) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index 3398784..df4285b 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -356,6 +356,7 @@ enum { tMIDDLE = tDBLDOT, /* value of last multi-character operator */ /* reserved words (statements) */ + t__ADDRESSOF, tASSERT, tBEGIN, tBREAK, @@ -542,6 +543,10 @@ enum { /* search types for error_suggest() when the identifier type is "estSYMB /* find symbols of any type but labels */ esfNONLABEL = esfANY & ~esfLABEL, + /* find symbols of any type except constants and native functions + * (for the "__addressof" operator) */ + esfADDRESSOF = esfANY & ~(esfCONST | esfNATIVE), + /* find an array, a single variable, or a named constant */ esfVARCONST = esfCONST | esfVARIABLE | esfARRAY }; diff --git a/source/compiler/sc2.c b/source/compiler/sc2.c index bd12249..846f2ba 100644 --- a/source/compiler/sc2.c +++ b/source/compiler/sc2.c @@ -2170,11 +2170,11 @@ char *sc_tokens[] = { "*=", "/=", "%=", "+=", "-=", "<<=", ">>>=", ">>=", "&=", "^=", "|=", "||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--", "...", "..", - "assert", "*begin", "break", "case", "char", "const", "continue", "default", - "defined", "do", "else", "emit", "__emit", "*end", "enum", "exit", "for", - "forward", "goto", "if", "native", "new", "operator", "public", "return", - "sizeof", "sleep", "state", "static", "stock", "switch", "tagof", "*then", - "while", + "__addressof", "assert", "*begin", "break", "case", "char", "const", "continue", + "default", "defined", "do", "else", "emit", "__emit", "*end", "enum", "exit", + "for", "forward", "goto", "if", "native", "new", "operator", "public", + "return", "sizeof", "sleep", "state", "static", "stock", "switch", "tagof", + "*then", "while", "#assert", "#define", "#else", "#elseif", "#emit", "#endif", "#endinput", "#endscript", "#error", "#file", "#if", "#include", "#line", "#pragma", "#tryinclude", "#undef", "#warning", diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index 993e358..39e6a57 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -1315,6 +1315,103 @@ static int hier2(value *lval) lvalue=hier2(lval); lval->tag=tag; return lvalue; + case t__ADDRESSOF: { + extern char *sc_tokens[]; + static const char allowed_sym_types[]="-variable, array, array cell, label or function-"; + paranthese=0; + while (matchtoken('(')) + paranthese++; + tok=lex(&val,&st); + if (tok!=tSYMBOL) + return error_suggest(20,st,NULL,estNONSYMBOL,tok); /* invalid symbol name */ + sym=findloc(st); + if (sym==NULL) + sym=findglb(st,sSTATEVAR); + if (sym==NULL) { + return error_suggest(17,st,NULL,estSYMBOL,esfADDRESSOF); /* undefined symbol */ + } else if ((sym->usage & uDEFINE)==0) { + /* the symbol is defined after the point of its use, + so the compiler can't know its address yet + */ + return error(17,st); /* undefined symbol (don't suggest other symbols) */ + } /* if */ + /* Mark the symbol as read, so the compiler won't throw it away + * if it's only indirectly used from "__addressof" */ + markusage(sym,uREAD); + clear_value(lval); + lval->ident=iCONSTEXPR; + switch (sym->ident) { + case iVARIABLE: + case iREFERENCE: + case iARRAY: + case iREFARRAY: + if (sym->vclass==sLOCAL) { + lval->ident=iEXPRESSION; + address(sym,sPRI); + break; + } /* if */ + /* fallthrough */ + case iFUNCTN: + case iLABEL: + lval->constval=sym->addr; + if (sym->ident==iFUNCTN) { + if ((sym->usage & uNATIVE)!=0) + error(1,allowed_sym_types,sc_tokens[teNATIVE-tFIRST]); + break; + } else if (sym->ident==iARRAY || sym->ident==iREFARRAY) { + cell arrayidx=0,numoffsets=0,offsmul=1; + int level; + symbol *subsym=sym; + for (level=0; matchtoken('['); level++) { + if (subsym!=NULL) { + if (level==subsym->dim.array.level && matchtoken(tSYMBOL)) { + char *idxname; + int cmptag=subsym->x.tags.index; + tokeninfo(&val,&idxname); + if (findconst(idxname,&cmptag)==NULL) + error_suggest(80,idxname,NULL,estSYMBOL,esfCONST); /* unknown symbol, or non-constant */ + else if (cmptag>1) + error(91,idxname); /* ambiguous constant */ + } else { + int index,ident; + cell cidx; + stgget(&index,&cidx); /* mark position in code generator */ + ident=expression(&val,&tag,NULL,TRUE); + stgdel(index,cidx); /* scratch generated code */ + if (ident!=iCONSTEXPR) + error(8); /* must be constant expression */ + } /* if */ + numoffsets+=offsmul; + offsmul*=subsym->dim.array.length; + arrayidx=(arrayidx*subsym->dim.array.length)+val; + subsym=finddepend(subsym); + } + needtoken(']'); + } /* for */ + if (level>sym->dim.array.level+1) + error(28,sym->name); /* invalid subscript */ + while (subsym!=NULL) { + numoffsets+=offsmul; + offsmul*=subsym->dim.array.length; + arrayidx*=arrayidx*subsym->dim.array.length; + subsym=finddepend(subsym); + } /* if */ + lval->constval+=(numoffsets-1+arrayidx)*(cell)sizeof(cell); + ldconst(lval->constval,sPRI); + } /* if */ + break; + case iCONSTEXPR: + error(1,allowed_sym_types,sc_tokens[teNUMERIC-tFIRST]); + break; + default: + assert(0); + } /* switch */ + while (paranthese--) + needtoken(')'); + if (strchr((char*)pline,PREPROC_TERM)!=NULL) + return error(93); /* "__addressof" operator is invalid in preprocessor directives */ + return FALSE; + } /* case */ case tDEFINED: paranthese=0; while (matchtoken('(')) diff --git a/source/compiler/sc5.c b/source/compiler/sc5.c index d528bde..ae37e35 100644 --- a/source/compiler/sc5.c +++ b/source/compiler/sc5.c @@ -131,7 +131,8 @@ static char *errmsg[] = { /*089*/ "state variables may not be initialized (symbol \"%s\")\n", /*090*/ "public functions may not return arrays (symbol \"%s\")\n", /*091*/ "ambiguous constant; tag override is required (symbol \"%s\")\n", -/*092*/ "functions may not return arrays of unknown size (symbol \"%s\")\n" +/*092*/ "functions may not return arrays of unknown size (symbol \"%s\")\n", +/*093*/ "\"__addressof\" operator is invalid in preprocessor expressions\n" }; static char *fatalmsg[] = {