Implement operator '__addressof'

This commit is contained in:
Daniel_Cortez 2019-09-14 12:42:47 +07:00
parent 65070b6563
commit 1d3b2319fd
4 changed files with 109 additions and 6 deletions

View File

@ -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
};

View File

@ -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",

View File

@ -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('('))

View File

@ -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[] = {