t = funcnext(&list);
}
+ t = structfirst(&list, getoutarg(curfn->type));
+ while(t != T) {
+ if(t->nname != N && t->nname->sym->name[0] != '_') {
+ if(d == D)
+ fatal("allocparams: this nil");
+ if(d->op != ONAME) {
+ d = d->forw;
+ continue;
+ }
+
+ n = d->dnode;
+ if(n->class != PPARAM)
+ fatal("allocparams: this class");
+
+ n->xoffset = t->width;
+ d = d->forw;
+ }
+ t = structnext(&list);
+ }
+
/*
* allocate (set xoffset) the stack
* slots for all automatics.
fatal("funchdr: dclcontext");
dclcontext = PAUTO;
- markdcl("func");
+ markdcl();
funcargs(n->type);
if(n->type->thistuple > 0) {
{
Type *n1;
Iter save;
+ int all;
- // declare the this argument
+ // declare the this/in arguments
n1 = funcfirst(&save, t);
while(n1 != T) {
if(n1->nname != N)
}
// declare the outgoing arguments
-// n1 = structfirst(&save, getoutarg(t));
-// while(n1 != T) {
-// n1->left = newname(n1->sym);
-// if(n1->nname != N)
-// addvar(n1->nname, n1->type, PPARAM);
-// n1 = structnext(&save);
-// }
+ all = 0;
+ n1 = structfirst(&save, getoutarg(t));
+ while(n1 != T) {
+ if(n1->nname != N && n1->nname->sym->name[0] != '_') {
+ addvar(n1->nname, n1->type, PPARAM);
+ all |= 1;
+ } else
+ all |= 2;
+ n1 = structnext(&save);
+ }
+ if(all == 3)
+ yyerror("output parameters are all named or not named");
+
+ t->outnamed = 0;
+ if(all == 1)
+ t->outnamed = 1;
}
/*
// change the declaration context from auto to extern
if(dclcontext != PAUTO)
fatal("funcbody: dclcontext");
- popdcl("func");
+ popdcl();
dclcontext = PEXTERN;
}
}
void
-popdcl(char *why)
+popdcl(void)
{
Sym *d, *s;
}
if(d == S)
fatal("popdcl: no mark");
- if(strcmp(why, d->package) != 0)
- fatal("popdcl: pushed as %s popped as %s", d->package, why);
dclstack = d->link;
block = d->vblock;
}
}
void
-markdcl(char *why)
+markdcl(void)
{
Sym *d;
d = push();
d->name = nil; // used as a mark in fifo
- d->package = why; // diagnostic for unmatched
d->vblock = block;
blockgen++;
block = blockgen;
+
// if(dflag())
// print("markdcl\n");
}
{
Sym *d, *s;
- markdcl("fnlit");
+ markdcl();
// copy the entire pop of the stack
// all the way back to block0.
gen = 0;
}
- if(s->vblock == block)
- yyerror("var %S redeclared in this block %d", s, block);
+ if(s->vblock == block) {
+ if(s->oname != N) {
+ yyerror("var %S redeclared in this block"
+ "\n previous declaration at %L",
+ s, s->oname->lineno);
+ } else
+ yyerror("var %S redeclared in this block", s);
+ }
if(ctxt != PEXTERN)
pushdcl(s);
uchar thistuple;
uchar outtuple;
uchar intuple;
+ uchar outnamed;
Sym* sym;
long vargen; // unique name for OTYPE/ONAME
Sym* psym; // import
Sym* sym; // various
long vargen; // unique name for OTYPE/ONAME
- ulong lineno;
+ long lineno;
vlong xoffset;
};
#define N ((Node*)0)
Type* dostruct(Node*, int);
Type** stotype(Node*, Type**);
Type* sortinter(Type*);
-void markdcl(char*);
-void popdcl(char*);
+void markdcl(void);
+void popdcl(void);
void poptodcl(void);
void markdclstack(void);
void testdclstack(void);
*/
void walk(Node*);
void walktype(Node*, int);
+void walkbool(Node*);
Type* walkswitch(Node*, Type*(*)(Node*, Type*));
int casebody(Node*);
int whatis(Node*);
%type <node> export_list_r export
%type <node> hidden_importsym_list_r ohidden_importsym_list hidden_importsym isym
%type <node> hidden_importfield_list_r ohidden_importfield_list hidden_importfield
-%type <node> fnbody
-%type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl
+%type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl fnbody
%type <node> keyval_list_r keyval
%type <node> typedcl Atypedcl Btypedcl
{
$$ = N;
}
-| error '}'
+| error xdcl
{
- $$ = N;
- }
-| error ';'
- {
- $$ = N;
+ $$ = $2;
}
common_dcl:
complex_stmt:
LFOR for_stmt
{
- /* FOR and WHILE are the same keyword */
- popdcl("for/while");
+ popdcl();
$$ = $2;
}
| LSWITCH if_stmt
{
- popdcl("if/switch");
+ popdcl();
if(!casebody($2->nbody))
yyerror("switch statement must have case labels");
$$ = $2;
}
| LIF if_stmt
{
- popdcl("if/switch");
+ popdcl();
$$ = $2;
//if($$->ninit != N && $$->ntest == N)
// yyerror("if conditional should not be missing");
}
| LIF if_stmt LELSE else_stmt1
{
- popdcl("if/switch");
+ popdcl();
$$ = $2;
$$->nelse = $4;
//if($$->ninit != N && $$->ntest == N)
}
| LRANGE range_stmt
{
- popdcl("range");
+ popdcl();
$$ = $2;
}
| LCASE expr_list ':'
}
| LIF if_stmt LELSE else_stmt2
{
- popdcl("if/switch");
+ popdcl();
$$ = $2;
$$->nelse = $4;
//if($$->ninit != N && $$->ntest == N)
compound_stmt:
'{'
{
- markdcl("compound");
+ markdcl();
} ostmt_list '}'
{
$$ = $3;
if($$ == N)
$$ = nod(OEMPTY, N, N);
- popdcl("compound");
+ popdcl();
}
for_header:
for_stmt:
{
- markdcl("for/while");
+ markdcl();
} for_body
{
$$ = $2;
if_stmt:
{
- markdcl("if/switch");
+ markdcl();
} if_body
{
$$ = $2;
range_stmt:
{
- markdcl("range");
+ markdcl();
} range_body
{
$$ = $2;
fnliteral:
fnlitdcl '{' ostmt_list '}'
{
- popdcl("fnlit");
+ popdcl();
vargen++;
snprint(namebuf, sizeof(namebuf), "_f%.3ld", vargen);
}
fnbody:
- compound_stmt
+ '{' ostmt_list '}'
{
- $$ = $1;
- if($$->op == OEMPTY)
+ $$ = $2;
+ if($$ == N)
$$ = nod(ORETURN, N, N);
}
| ';'
{
$$ = N;
}
+
fnres:
Afnres
| Bfnres
{
$$ = N;
}
-| error ';'
- {
- $$ = N;
- }
-| error '}'
+| error Astmt
{
$$ = N;
}
Bstmt:
semi_stmt
| Bcommon_dcl
+| error Bstmt
+ {
+ $$ = N;
+ }
/*
* need semi in front YES
}
*cp++ = c;
c = getc();
- if(c == 'x' || c == 'X')
+ if(c == 'x' || c == 'X') {
for(;;) {
*cp++ = c;
c = getc();
yyerror("malformed hex constant");
goto ncu;
}
- if(c < '0' || c > '7')
- goto dc;
+ }
+
+ c1 = 0;
for(;;) {
- if(c >= '0' && c <= '7') {
- *cp++ = c;
- c = getc();
- continue;
- }
- goto ncu;
+ if(!isdigit(c))
+ break;
+ if(c < '0' || c > '7')
+ c1 = 1; // not octal
+ *cp++ = c;
+ c = getc();
}
+ if(c == '.')
+ goto casedot;
+ if(c == 'e' || c == 'E')
+ goto casee;
+ if(c1)
+ yyerror("malformed octal constant");
+ goto ncu;
dc:
if(c == '.')
if(top != Etop)
goto nottop;
walktype(n->ninit, Etop);
- walktype(n->ntest, Erv);
+ walkbool(n->ntest);
walktype(n->nincr, Etop);
n = n->nbody;
goto loop;
if(top != Etop)
goto nottop;
walktype(n->ninit, Etop);
- walktype(n->ntest, Erv);
+ walkbool(n->ntest);
walktype(n->nelse, Etop);
n = n->nbody;
goto loop;
if(top != Etop)
goto nottop;
walktype(n->left, Erv);
+ if(curfn->type->outnamed && n->left == N) {
+ // print("special return\n");
+ goto ret;
+ }
l = ascompatte(n->op, getoutarg(curfn->type), &n->left, 1);
if(l != N)
n->left = reorder4(l);
lineno = lno;
}
+void
+walkbool(Node *n)
+{
+ walktype(n, Erv);
+ if(n != N && n->type != T)
+ if(!eqtype(n->type, types[TBOOL], 0))
+ yyerror("IF and FOR require a boolean type");
+}
+
/*
* return the first type
*/