Commit 8f4af6d2 authored by Russ Cox's avatar Russ Cox

gc: grammar cleanup:

  * no longer distinguishes const, var, type, package names.
  * all the predefined names are not tokens anymore.

R=ken
OCL=29326
CL=29985
parent ea33ff40
...@@ -208,7 +208,7 @@ dowidth(Type *t) ...@@ -208,7 +208,7 @@ dowidth(Type *t)
} }
void void
typeinit(int lex) typeinit(void)
{ {
int i, etype, sameas; int i, etype, sameas;
Type *t; Type *t;
...@@ -306,7 +306,7 @@ typeinit(int lex) ...@@ -306,7 +306,7 @@ typeinit(int lex)
types[TFUNC] = functype(N, N, N); types[TFUNC] = functype(N, N, N);
/* types used in front end */ /* types used in front end */
types[TNIL] = typ(TNIL); // types[TNIL] got set early in lexinit
types[TIDEAL] = typ(TIDEAL); types[TIDEAL] = typ(TIDEAL);
/* simple aliases */ /* simple aliases */
...@@ -317,7 +317,6 @@ typeinit(int lex) ...@@ -317,7 +317,6 @@ typeinit(int lex)
/* pick up the backend typedefs */ /* pick up the backend typedefs */
for(i=0; typedefs[i].name; i++) { for(i=0; typedefs[i].name; i++) {
s = lookup(typedefs[i].name); s = lookup(typedefs[i].name);
s->lexical = lex;
etype = typedefs[i].etype; etype = typedefs[i].etype;
if(etype < 0 || etype >= nelem(types)) if(etype < 0 || etype >= nelem(types))
...@@ -340,7 +339,7 @@ typeinit(int lex) ...@@ -340,7 +339,7 @@ typeinit(int lex)
dowidth(t); dowidth(t);
types[etype] = t; types[etype] = t;
s->otype = t; s->def = typenod(t);
} }
Array_array = rnd(0, widthptr); Array_array = rnd(0, widthptr);
......
...@@ -67,11 +67,11 @@ dodcltype(Type *n) ...@@ -67,11 +67,11 @@ dodcltype(Type *n)
// if n has been forward declared, // if n has been forward declared,
// use the Type* created then // use the Type* created then
s = n->sym; s = n->sym;
if(s->block == block && s->otype != T) { if(s->block == block && s->def != N && s->def->op == OTYPE) {
switch(s->otype->etype) { switch(s->def->type->etype) {
case TFORWSTRUCT: case TFORWSTRUCT:
case TFORWINTER: case TFORWINTER:
n = s->otype; n = s->def->type;
goto found; goto found;
} }
} }
...@@ -95,7 +95,7 @@ updatetype(Type *n, Type *t) ...@@ -95,7 +95,7 @@ updatetype(Type *n, Type *t)
int local; int local;
s = n->sym; s = n->sym;
if(s == S || s->otype != n) if(s == S || s->def == N || s->def->op != OTYPE || s->def->type != n)
fatal("updatetype %T = %T", n, t); fatal("updatetype %T = %T", n, t);
switch(n->etype) { switch(n->etype) {
...@@ -132,7 +132,7 @@ updatetype(Type *n, Type *t) ...@@ -132,7 +132,7 @@ updatetype(Type *n, Type *t)
n->printed = 0; n->printed = 0;
n->method = nil; n->method = nil;
n->vargen = 0; n->vargen = 0;
n->nod = N;
// catch declaration of incomplete type // catch declaration of incomplete type
switch(n->etype) { switch(n->etype) {
case TFORWSTRUCT: case TFORWSTRUCT:
...@@ -306,7 +306,7 @@ addmethod(Node *n, Type *t, int local) ...@@ -306,7 +306,7 @@ addmethod(Node *n, Type *t, int local)
goto bad; goto bad;
if(local && !f->local) { if(local && !f->local) {
yyerror("cannot define methods on non-local type %T", t); yyerror("cannot define methods on non-local type %T", f);
return; return;
} }
...@@ -383,7 +383,9 @@ funchdr(Node *n) ...@@ -383,7 +383,9 @@ funchdr(Node *n)
Sym *s; Sym *s;
s = n->nname->sym; s = n->nname->sym;
on = s->oname; on = s->def;
if(on != N && (on->op != ONAME || on->builtin))
on = N;
// check for same types // check for same types
if(on != N) { if(on != N) {
...@@ -748,7 +750,7 @@ loop: ...@@ -748,7 +750,7 @@ loop:
f->embedded = n->embedded; f->embedded = n->embedded;
f->sym = f->nname->sym; f->sym = f->nname->sym;
if(pkgimportname != S && !exportname(f->sym->name)) if(pkgimportname != S && !exportname(f->sym->name))
f->sym = pkglookup(f->sym->name, pkgcontext); f->sym = pkglookup(f->sym->name, structpkg);
} }
*t = f; *t = f;
...@@ -793,11 +795,8 @@ void ...@@ -793,11 +795,8 @@ void
dcopy(Sym *a, Sym *b) dcopy(Sym *a, Sym *b)
{ {
a->name = b->name; a->name = b->name;
a->oname = b->oname; a->def = b->def;
a->otype = b->otype;
a->oconst = b->oconst;
a->package = b->package; a->package = b->package;
a->lexical = b->lexical;
a->undef = b->undef; a->undef = b->undef;
a->vargen = b->vargen; a->vargen = b->vargen;
a->block = b->block; a->block = b->block;
...@@ -954,11 +953,8 @@ addvar(Node *n, Type *t, int ctxt) ...@@ -954,11 +953,8 @@ addvar(Node *n, Type *t, int ctxt)
redeclare("variable", s); redeclare("variable", s);
s->vargen = gen; s->vargen = gen;
s->oname = n; s->def = n;
s->offset = 0; s->offset = 0;
s->oconst = nil;
s->otype = nil;
s->lexical = LNAME;
n->funcdepth = funcdepth; n->funcdepth = funcdepth;
n->type = t; n->type = t;
...@@ -1004,10 +1000,7 @@ addtyp(Type *n, int ctxt) ...@@ -1004,10 +1000,7 @@ addtyp(Type *n, int ctxt)
} }
redeclare("type", s); redeclare("type", s);
s->otype = n; s->def = typenod(n);
s->oconst = nil;
s->oname = nil;
s->lexical = LATYPE;
d = dcl(); d = dcl();
d->dsym = s; d->dsym = s;
...@@ -1041,7 +1034,7 @@ addconst(Node *n, Node *e, int ctxt) ...@@ -1041,7 +1034,7 @@ addconst(Node *n, Node *e, int ctxt)
Sym *s; Sym *s;
Dcl *r, *d; Dcl *r, *d;
if(n->op != ONAME) if(n->op != ONAME && n->op != ONONAME)
fatal("addconst: not a name"); fatal("addconst: not a name");
if(e->op != OLITERAL) { if(e->op != OLITERAL) {
...@@ -1059,10 +1052,8 @@ addconst(Node *n, Node *e, int ctxt) ...@@ -1059,10 +1052,8 @@ addconst(Node *n, Node *e, int ctxt)
} }
redeclare("constant", s); redeclare("constant", s);
s->oconst = e; s->def = e;
s->otype = nil; e->sym = s;
s->oname = nil;
s->lexical = LNAME;
d = dcl(); d = dcl();
d->dsym = s; d->dsym = s;
...@@ -1073,7 +1064,7 @@ addconst(Node *n, Node *e, int ctxt) ...@@ -1073,7 +1064,7 @@ addconst(Node *n, Node *e, int ctxt)
r->back = d; r->back = d;
if(dflag()) if(dflag())
print("const-dcl %S %N\n", n->sym, n->sym->oconst); print("const-dcl %S %N\n", n->sym, n->sym->def);
} }
Node* Node*
...@@ -1130,6 +1121,18 @@ newname(Sym *s) ...@@ -1130,6 +1121,18 @@ newname(Sym *s)
return n; return n;
} }
Node*
typenod(Type *t)
{
if(t->nod == N) {
t->nod = nod(OTYPE, N, N);
t->nod->type = t;
t->nod->sym = t->sym;
}
return t->nod;
}
/* /*
* this will return an old name * this will return an old name
* that has already been pushed on the * that has already been pushed on the
...@@ -1142,15 +1145,7 @@ oldname(Sym *s) ...@@ -1142,15 +1145,7 @@ oldname(Sym *s)
Node *n; Node *n;
Node *c; Node *c;
if(s->oconst) { n = s->def;
n = nod(OLITERAL, N, N);
n->sym = s;
n->val = s->oconst->val;
n->type = s->oconst->type;
return n;
}
n = s->oname;
if(n == N) { if(n == N) {
n = nod(ONONAME, N, N); n = nod(ONONAME, N, N);
n->sym = s; n->sym = s;
...@@ -1158,7 +1153,15 @@ oldname(Sym *s) ...@@ -1158,7 +1153,15 @@ oldname(Sym *s)
n->addable = 1; n->addable = 1;
n->ullman = 1; n->ullman = 1;
} }
if(n->funcdepth > 0 && n->funcdepth != funcdepth) { if(n->op == OLITERAL) {
c = nod(OLITERAL, N, N);
c->sym = s;
c->val = n->val;
c->type = n->type;
c->iota = n->iota;
return c;
}
if(n->funcdepth > 0 && n->funcdepth != funcdepth && n->op == ONAME) {
// inner func is referring to var // inner func is referring to var
// in outer func. // in outer func.
if(n->closure == N || n->closure->funcdepth != funcdepth) { if(n->closure == N || n->closure->funcdepth != funcdepth) {
...@@ -1200,9 +1203,19 @@ oldtype(Sym *s) ...@@ -1200,9 +1203,19 @@ oldtype(Sym *s)
{ {
Type *t; Type *t;
t = s->otype; if(s->def == N || s->def->op != OTYPE) {
if(t == T) yyerror("%S is not a type", s);
fatal("%S not a type", s); // cant happen return T;
}
t = s->def->type;
/*
* If t is lowercase and not in our package
* and this isn't a reference during the parsing
* of import data, complain.
*/
if(pkgimportname == S && !exportname(s->name) && strcmp(s->package, package) != 0)
yyerror("cannot use type %T", t);
return t; return t;
} }
...@@ -1219,9 +1232,9 @@ nametoanondcl(Node *na) ...@@ -1219,9 +1232,9 @@ nametoanondcl(Node *na)
for(l=&na; (n=*l)->op == OLIST; l=&n->left) for(l=&na; (n=*l)->op == OLIST; l=&n->left)
n->right = nametoanondcl(n->right); n->right = nametoanondcl(n->right);
t = n->sym->otype; n = n->sym->def;
if(t == T) { if(n == N || n->op != OTYPE || (t = n->type) == T) {
yyerror("%s is not a type", n->sym->name); yyerror("%S is not a type", n->sym);
t = typ(TINT32); t = typ(TINT32);
} }
n = nod(ODCLFIELD, N, N); n = nod(ODCLFIELD, N, N);
...@@ -1261,33 +1274,95 @@ anondcl(Type *t) ...@@ -1261,33 +1274,95 @@ anondcl(Type *t)
return n; return n;
} }
static Node*
findtype(Node *n)
{
Node *r;
for(r=n; r->op==OLIST; r=r->right)
if(r->left->op == OKEY)
return r->left->right;
if(r->op == OKEY)
return r->right;
if(n->op == OLIST)
n = n->left;
return N;
}
static Node*
xanondcl(Node *nt, int dddok)
{
Node *n;
Type *t;
t = nt->type;
if(nt->op != OTYPE) {
yyerror("%N is not a type", nt);
t = types[TINT32];
}
n = nod(ODCLFIELD, N, N);
n->type = t;
if(!dddok && t->etype == TDDD)
yyerror("only last argument can have type ...");
return n;
}
static Node*
namedcl(Node *nn, Node *nt, int dddok)
{
Node *n;
Type *t;
if(nn->op == OKEY)
nn = nn->left;
if(nn->op == OTYPE && nn->sym == S) {
yyerror("cannot mix anonymous %T with named arguments", nn->type);
return xanondcl(nn, dddok);
}
t = types[TINT32];
if(nt == N)
yyerror("missing type for argument %S", nn->sym);
else if(nt->op != OTYPE)
yyerror("%S is not a type", nt->sym);
else
t = nt->type;
n = nod(ODCLFIELD, newname(nn->sym), N);
n->type = t;
if(!dddok && t->etype == TDDD)
yyerror("only last argument can have type ...");
return n;
}
/* /*
* check that the list of declarations is either all anonymous or all named * check that the list of declarations is either all anonymous or all named
*/ */
void Node*
checkarglist(Node *n) checkarglist(Node *n)
{ {
if(n->op != OLIST) Node *r;
return; Node **l;
if(n->left->op != ODCLFIELD)
fatal("checkarglist"); // check for all anonymous
if(n->left->left != N) { for(r=n; r->op==OLIST; r=r->right)
for(n=n->right; n->op == OLIST; n=n->right) if(r->left->op == OKEY)
if(n->left->left == N) goto named;
goto mixed; if(r->op == OKEY)
if(n->left == N) goto named;
goto mixed;
} else { // all anonymous - add names
for(n=n->right; n->op == OLIST; n=n->right) for(l=&n; (r=*l)->op==OLIST; l=&r->right)
if(n->left->left != N) r->left = xanondcl(r->left, 0);
goto mixed; *l = xanondcl(r, 1);
if(n->left != N) return n;
goto mixed;
}
return;
mixed: named:
yyerror("cannot mix anonymous and named function arguments"); // otherwise, each run of names ends in a type.
// add a type to each one that needs one.
for(l=&n; (r=*l)->op==OLIST; l=&r->right)
r->left = namedcl(r->left, findtype(r), 0);
*l = namedcl(r, findtype(r), 1);
return n;
} }
/* /*
...@@ -1296,7 +1371,7 @@ mixed: ...@@ -1296,7 +1371,7 @@ mixed:
* func Init·<file>() (2) * func Init·<file>() (2)
* if initdone·<file> { (3) * if initdone·<file> { (3)
* if initdone·<file> == 2 (4) * if initdone·<file> == 2 (4)
* return * return
* throw(); (5) * throw(); (5)
* } * }
* initdone.<file>++; (6) * initdone.<file>++; (6)
...@@ -1325,7 +1400,7 @@ anyinit(Node *n) ...@@ -1325,7 +1400,7 @@ anyinit(Node *n)
// is there an explicit init function // is there an explicit init function
snprint(namebuf, sizeof(namebuf), "init·%s", filename); snprint(namebuf, sizeof(namebuf), "init·%s", filename);
s = lookup(namebuf); s = lookup(namebuf);
if(s->oname != N) if(s->def != N)
return 1; return 1;
// are there any imported init functions // are there any imported init functions
...@@ -1333,7 +1408,7 @@ anyinit(Node *n) ...@@ -1333,7 +1408,7 @@ anyinit(Node *n)
for(s = hash[h]; s != S; s = s->link) { for(s = hash[h]; s != S; s = s->link) {
if(s->name[0] != 'I' || strncmp(s->name, "Init·", 6) != 0) if(s->name[0] != 'I' || strncmp(s->name, "Init·", 6) != 0)
continue; continue;
if(s->oname == N) if(s->def == N)
continue; continue;
return 1; return 1;
} }
...@@ -1409,13 +1484,13 @@ fninit(Node *n) ...@@ -1409,13 +1484,13 @@ fninit(Node *n)
for(s = hash[h]; s != S; s = s->link) { for(s = hash[h]; s != S; s = s->link) {
if(s->name[0] != 'I' || strncmp(s->name, "Init·", 6) != 0) if(s->name[0] != 'I' || strncmp(s->name, "Init·", 6) != 0)
continue; continue;
if(s->oname == N) if(s->def == N)
continue; continue;
if(s == initsym) if(s == initsym)
continue; continue;
// could check that it is fn of no args/returns // could check that it is fn of no args/returns
a = nod(OCALL, s->oname, N); a = nod(OCALL, s->def, N);
r = list(r, a); r = list(r, a);
} }
...@@ -1426,8 +1501,8 @@ fninit(Node *n) ...@@ -1426,8 +1501,8 @@ fninit(Node *n)
// could check that it is fn of no args/returns // could check that it is fn of no args/returns
snprint(namebuf, sizeof(namebuf), "init·%s", filename); snprint(namebuf, sizeof(namebuf), "init·%s", filename);
s = lookup(namebuf); s = lookup(namebuf);
if(s->oname != N) { if(s->def != N) {
a = nod(OCALL, s->oname, N); a = nod(OCALL, s->def, N);
r = list(r, a); r = list(r, a);
} }
......
...@@ -100,7 +100,7 @@ dumpexportconst(Sym *s) ...@@ -100,7 +100,7 @@ dumpexportconst(Sym *s)
Node *n; Node *n;
Type *t; Type *t;
n = s->oconst; n = s->def;
if(n == N || n->op != OLITERAL) if(n == N || n->op != OLITERAL)
fatal("dumpexportconst: oconst nil: %S", s); fatal("dumpexportconst: oconst nil: %S", s);
...@@ -141,7 +141,7 @@ dumpexportvar(Sym *s) ...@@ -141,7 +141,7 @@ dumpexportvar(Sym *s)
Node *n; Node *n;
Type *t; Type *t;
n = s->oname; n = s->def;
if(n == N || n->type == T) { if(n == N || n->type == T) {
yyerror("variable exported but not defined: %S", s); yyerror("variable exported but not defined: %S", s);
return; return;
...@@ -161,49 +161,54 @@ dumpexportvar(Sym *s) ...@@ -161,49 +161,54 @@ dumpexportvar(Sym *s)
void void
dumpexporttype(Sym *s) dumpexporttype(Sym *s)
{ {
dumpprereq(s->otype); Type *t;
t = s->def->type;
dumpprereq(t);
Bprint(bout, "\t"); Bprint(bout, "\t");
switch (s->otype->etype) { switch (t->etype) {
case TFORW: case TFORW:
case TFORWSTRUCT: case TFORWSTRUCT:
case TFORWINTER: case TFORWINTER:
yyerror("export of incomplete type %T", s->otype); yyerror("export of incomplete type %T", t);
return; return;
} }
Bprint(bout, "type %#T %l#T\n", s->otype, s->otype); Bprint(bout, "type %#T %l#T\n", t, t);
} }
void void
dumpsym(Sym *s) dumpsym(Sym *s)
{ {
Type *f; Type *f, *t;
if(s->exported != 0) if(s->exported != 0)
return; return;
s->exported = 1; s->exported = 1;
switch(s->lexical) { if(s->def == N) {
default:
yyerror("unknown export symbol: %S", s); yyerror("unknown export symbol: %S", s);
return;
}
switch(s->def->op) {
default:
yyerror("unexpected export symbol: %O %S", s->def->op, s);
break; break;
case LPACK: case OLITERAL:
yyerror("package export symbol: %S", s); dumpexportconst(s);
break; break;
case LATYPE: case OTYPE:
t = s->def->type;
// TODO(rsc): sort methods by name // TODO(rsc): sort methods by name
for(f=s->otype->method; f!=T; f=f->down) for(f=t->method; f!=T; f=f->down)
dumpprereq(f); dumpprereq(f);
dumpexporttype(s); dumpexporttype(s);
for(f=s->otype->method; f!=T; f=f->down) for(f=t->method; f!=T; f=f->down)
Bprint(bout, "\tfunc (%#T) %hS %#hhT\n", Bprint(bout, "\tfunc (%#T) %hS %#hhT\n",
f->type->type->type, f->sym, f->type); f->type->type->type, f->sym, f->type);
break; break;
case LNAME: case ONAME:
if(s->oconst) dumpexportvar(s);
dumpexportconst(s);
else
dumpexportvar(s);
break; break;
} }
} }
...@@ -216,7 +221,7 @@ dumptype(Type *t) ...@@ -216,7 +221,7 @@ dumptype(Type *t)
return; return;
// no need to dump type if it's not ours (was imported) // no need to dump type if it's not ours (was imported)
if(t->sym != S && t->sym->otype == t && !t->local) if(t->sym != S && t->sym->def == typenod(t) && !t->local)
return; return;
Bprint(bout, "type %#T %l#T\n", t, t); Bprint(bout, "type %#T %l#T\n", t, t);
...@@ -256,43 +261,22 @@ dumpexport(void) ...@@ -256,43 +261,22 @@ dumpexport(void)
* import * import
*/ */
/*
* look up and maybe declare pkg.name, which should match lexical
*/
Sym*
pkgsym(char *name, char *pkg, int lexical)
{
Sym *s;
s = pkglookup(name, pkg);
switch(lexical) {
case LATYPE:
if(s->oname)
yyerror("%s.%s is not a type", name, pkg);
break;
case LNAME:
if(s->otype)
yyerror("%s.%s is not a name", name, pkg);
break;
}
s->lexical = lexical;
return s;
}
/* /*
* return the sym for ss, which should match lexical * return the sym for ss, which should match lexical
*/ */
Sym* Sym*
importsym(Node *ss, int lexical) importsym(Sym *s, int op)
{ {
Sym *s; if(s->def != N && s->def->op != op) {
// Clumsy hack for
if(ss->op != OIMPORT) // package parser
fatal("importsym: oops1 %N", ss); // import "go/parser" // defines type parser
if(s == lookup(package))
s = pkgsym(ss->sym->name, ss->psym->name, lexical); s->def = N;
/* TODO botch - need some diagnostic checking for the following assignment */ else
if(exportname(ss->sym->name)) yyerror("redeclaration of %lS during import", s, s->def->op, op);
}
if(exportname(s->name))
s->export = 1; s->export = 1;
else else
s->export = 2; // package scope s->export = 2; // package scope
...@@ -304,47 +288,36 @@ importsym(Node *ss, int lexical) ...@@ -304,47 +288,36 @@ importsym(Node *ss, int lexical)
* return the type pkg.name, forward declaring if needed * return the type pkg.name, forward declaring if needed
*/ */
Type* Type*
pkgtype(char *name, char *pkg) pkgtype(Sym *s)
{ {
Sym *s;
Type *t; Type *t;
// botch importsym(s, OTYPE);
// s = pkgsym(name, pkg, LATYPE); if(s->def == N || s->def->op != OTYPE) {
Node *n;
n = nod(OIMPORT, N, N);
n->sym = lookup(name);
n->psym = lookup(pkg);
s = importsym(n, LATYPE);
if(s->otype == T) {
t = typ(TFORW); t = typ(TFORW);
t->sym = s; t->sym = s;
s->otype = t; s->def = typenod(t);
} }
return s->otype; return s->def->type;
} }
static int static int
mypackage(Node *ss) mypackage(Sym *s)
{ {
// we import all definitions for sys. // we import all definitions for sys.
// lowercase ones can only be used by the compiler. // lowercase ones can only be used by the compiler.
return strcmp(ss->psym->name, package) == 0 return strcmp(s->package, package) == 0
|| strcmp(ss->psym->name, "sys") == 0; || strcmp(s->package, "sys") == 0;
} }
void void
importconst(Node *ss, Type *t, Node *n) importconst(Sym *s, Type *t, Node *n)
{ {
Sym *s; if(!exportname(s->name) && !mypackage(s))
if(!exportname(ss->sym->name) && !mypackage(ss))
return; return;
importsym(s, OLITERAL);
convlit(n, t); convlit(n, t);
s = importsym(ss, LNAME); if(s->def != N) {
if(s->oconst != N) {
// TODO: check if already the same. // TODO: check if already the same.
return; return;
} }
...@@ -356,19 +329,17 @@ importconst(Node *ss, Type *t, Node *n) ...@@ -356,19 +329,17 @@ importconst(Node *ss, Type *t, Node *n)
} }
void void
importvar(Node *ss, Type *t, int ctxt) importvar(Sym *s, Type *t, int ctxt)
{ {
Sym *s; if(!exportname(s->name) && !mypackage(s))
if(!exportname(ss->sym->name) && !mypackage(ss))
return; return;
s = importsym(ss, LNAME); importsym(s, ONAME);
if(s->oname != N) { if(s->def != N && s->def->op == ONAME) {
if(cvttype(t, s->oname->type)) if(cvttype(t, s->def->type))
return; return;
warn("redeclare import var %S from %T to %T", warn("redeclare import var %S from %T to %T",
s, s->oname->type, t); s, s->def->type, t);
} }
checkwidth(t); checkwidth(t);
addvar(newname(s), t, ctxt); addvar(newname(s), t, ctxt);
...@@ -378,25 +349,34 @@ importvar(Node *ss, Type *t, int ctxt) ...@@ -378,25 +349,34 @@ importvar(Node *ss, Type *t, int ctxt)
} }
void void
importtype(Node *ss, Type *t) importtype(Sym *s, Type *t)
{ {
Sym *s; Node *n;
Type *tt;
s = importsym(ss, LATYPE); importsym(s, OTYPE);
if(s->otype != T) { n = s->def;
if(cvttype(t, s->otype)) if(n != N && n->op == OTYPE) {
if(cvttype(t, n->type))
return; return;
if(s->otype->etype != TFORW) { if(n->type->etype != TFORW) {
warn("redeclare import type %S from %lT to %lT", warn("redeclare import type %S from %lT to %lT",
s, s->otype, t); s, n->type, t);
s->otype = typ(0); n = s->def = typenod(typ(0));
} }
} }
if(s->otype == T) if(n == N || n->op != OTYPE) {
s->otype = typ(0); tt = typ(0);
*s->otype = *t; tt->sym = s;
s->otype->sym = s; n = typenod(tt);
checkwidth(s->otype); s->def = n;
}
if(n->type == T)
n->type = typ(0);
*n->type = *t;
n->type->sym = s;
n->type->nod = n;
checkwidth(n->type);
if(debug['E']) if(debug['E'])
print("import type %S %lT\n", s, t); print("import type %S %lT\n", s, t);
...@@ -425,7 +405,9 @@ return; ...@@ -425,7 +405,9 @@ return;
for(h=0; h<NHASH; h++) for(h=0; h<NHASH; h++)
for(s = hash[h]; s != S; s = s->link) { for(s = hash[h]; s != S; s = s->link) {
t = s->otype; if(s->def == N || s->def->op != OTYPE)
continue;
t = s->def->type;
if(t == T) if(t == T)
continue; continue;
......
...@@ -145,6 +145,8 @@ struct Type ...@@ -145,6 +145,8 @@ struct Type
uchar copyany; uchar copyany;
uchar local; // created in this file uchar local; // created in this file
Node* nod; // canonical OTYPE node
// TFUNCT // TFUNCT
uchar thistuple; uchar thistuple;
uchar outtuple; uchar outtuple;
...@@ -187,6 +189,7 @@ struct Node ...@@ -187,6 +189,7 @@ struct Node
uchar diag; // already printed error about this uchar diag; // already printed error about this
uchar noescape; // ONAME never move to heap uchar noescape; // ONAME never move to heap
uchar funcdepth; uchar funcdepth;
uchar builtin; // built-in name, like len or close
// most nodes // most nodes
Node* left; Node* left;
...@@ -247,10 +250,7 @@ struct Sym ...@@ -247,10 +250,7 @@ struct Sym
char* package; // package name char* package; // package name
char* name; // variable name char* name; // variable name
Node* oname; // ONAME node if a var Node* def; // definition: ONAME OTYPE OPACK or OLITERAL
Type* otype; // TYPE node if a type
Node* oconst; // OLITERAL node if a const
char* opack; // package reference if lexical == LPACK
vlong offset; // stack location if automatic vlong offset; // stack location if automatic
int32 lexical; int32 lexical;
int32 vargen; // unique variable number int32 vargen; // unique variable number
...@@ -298,9 +298,8 @@ enum ...@@ -298,9 +298,8 @@ enum
{ {
OXXX, OXXX,
OTYPE, OVAR, OIMPORT, ONAME, ONONAME, OTYPE, OPACK, OLITERAL,
ODCL,
ONAME, ONONAME, ODCL,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
ODCLFUNC, ODCLFIELD, ODCLARG, ODCLFUNC, ODCLFIELD, ODCLARG,
OLIST, OCMP, OPTR, OARRAY, ORANGE, OLIST, OCMP, OPTR, OARRAY, ORANGE,
...@@ -325,7 +324,7 @@ enum ...@@ -325,7 +324,7 @@ enum
OCALL, OCALLMETH, OCALLINTER, OCALL, OCALLMETH, OCALLINTER,
OINDEX, OSLICE, OINDEX, OSLICE,
ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV, ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
OLITERAL, OREGISTER, OINDREG, OREGISTER, OINDREG,
OKEY, OPARAM, OKEY, OPARAM,
OCOMPOS, OCOMPSLICE, OCOMPMAP, OCOMPOS, OCOMPSLICE, OCOMPMAP,
OCONV, OCONV,
...@@ -573,6 +572,7 @@ EXTERN int importflag; ...@@ -573,6 +572,7 @@ EXTERN int importflag;
EXTERN int inimportsys; EXTERN int inimportsys;
EXTERN int initflag; // compiling the init fn EXTERN int initflag; // compiling the init fn
EXTERN int statuniqgen; // name generator for static temps EXTERN int statuniqgen; // name generator for static temps
EXTERN int loophack;
EXTERN uint32 iota; EXTERN uint32 iota;
EXTERN Node* lastconst; EXTERN Node* lastconst;
...@@ -595,8 +595,7 @@ EXTERN Node* fskel; ...@@ -595,8 +595,7 @@ EXTERN Node* fskel;
EXTERN Node* addtop; EXTERN Node* addtop;
EXTERN Node* typeswvar; EXTERN Node* typeswvar;
EXTERN char* context; EXTERN char* structpkg;
EXTERN char* pkgcontext;
extern int thechar; extern int thechar;
extern char* thestring; extern char* thestring;
EXTERN char* hunk; EXTERN char* hunk;
...@@ -623,7 +622,7 @@ void importfile(Val*); ...@@ -623,7 +622,7 @@ void importfile(Val*);
void cannedimports(char*, char*); void cannedimports(char*, char*);
void unimportfile(); void unimportfile();
int32 yylex(void); int32 yylex(void);
void typeinit(int lex); void typeinit(void);
void lexinit(void); void lexinit(void);
char* lexname(int); char* lexname(int);
int32 getr(void); int32 getr(void);
...@@ -731,7 +730,7 @@ int isnilinter(Type*); ...@@ -731,7 +730,7 @@ int isnilinter(Type*);
int isddd(Type*); int isddd(Type*);
Type* maptype(Type*, Type*); Type* maptype(Type*, Type*);
Type* methtype(Type*); Type* methtype(Type*);
Sym* signame(Type*); Node* signame(Type*);
int eqtype(Type*, Type*); int eqtype(Type*, Type*);
int cvttype(Type*, Type*); int cvttype(Type*, Type*);
int eqtypenoname(Type*, Type*); int eqtypenoname(Type*, Type*);
...@@ -821,6 +820,7 @@ Node* renameinit(Node*); ...@@ -821,6 +820,7 @@ Node* renameinit(Node*);
void funchdr(Node*); void funchdr(Node*);
void funcargs(Type*); void funcargs(Type*);
void funcbody(Node*); void funcbody(Node*);
Node* typenod(Type*);
Type* dostruct(Node*, int); Type* dostruct(Node*, int);
Type** stotype(Node*, int, Type**); Type** stotype(Node*, int, Type**);
Type* sortinter(Type*); Type* sortinter(Type*);
...@@ -844,7 +844,7 @@ void fninit(Node*); ...@@ -844,7 +844,7 @@ void fninit(Node*);
Node* nametoanondcl(Node*); Node* nametoanondcl(Node*);
Node* nametodcl(Node*, Type*); Node* nametodcl(Node*, Type*);
Node* anondcl(Type*); Node* anondcl(Type*);
void checkarglist(Node*); Node* checkarglist(Node*);
void checkwidth(Type*); void checkwidth(Type*);
void defercheckwidth(void); void defercheckwidth(void);
void resumecheckwidth(void); void resumecheckwidth(void);
...@@ -887,12 +887,12 @@ void doimport6(Node*, Node*); ...@@ -887,12 +887,12 @@ void doimport6(Node*, Node*);
void doimport7(Node*, Node*); void doimport7(Node*, Node*);
void doimport8(Node*, Val*, Node*); void doimport8(Node*, Val*, Node*);
void doimport9(Sym*, Node*); void doimport9(Sym*, Node*);
void importconst(Node *ss, Type *t, Node *v); void importconst(Sym *s, Type *t, Node *v);
void importmethod(Sym *s, Type *t); void importmethod(Sym *s, Type *t);
void importtype(Node *ss, Type *t); void importtype(Sym *s, Type *t);
void importvar(Node *ss, Type *t, int ctxt); void importvar(Sym *s, Type *t, int ctxt);
void checkimports(void); void checkimports(void);
Type* pkgtype(char*, char*); Type* pkgtype(Sym*);
/* /*
* walk.c * walk.c
......
...@@ -2,6 +2,30 @@ ...@@ -2,6 +2,30 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
/*
* Go language grammar.
*
* The grammar has 6 reduce/reduce conflicts, caused by
* input that can be parsed as either a type or an expression
* depending on context, like the t in t(1). The expressions
* have the more general syntax, so the grammar arranges
* that such input gets parsed as expressions and then is
* fixed up as a type later. In return for this extra work,
* the lexer need not distinguish type names from variable names.
*
* The Go semicolon rules are:
*
* 1. all statements and declarations are terminated by semicolons
* 2. semicolons can be omitted at top level.
* 3. semicolons can be omitted before and after the closing ) or }
* on a list of statements or declarations.
*
* Thus the grammar must distinguish productions that
* can omit the semicolon terminator and those that can't.
* Names like Astmt, Avardcl, etc. can drop the semicolon.
* Names like Bstmt, Bvardcl, etc. can't.
*/
%{ %{
#include "go.h" #include "go.h"
%} %}
...@@ -12,106 +36,90 @@ ...@@ -12,106 +36,90 @@
struct Val val; struct Val val;
int lint; int lint;
} }
%token <val> LLITERAL
%token <lint> LASOP
%token <sym> LNAME LATYPE LPACK
%token <sym> LPACKAGE LIMPORT LDEFER LCLOSE LCLOSED
%token <sym> LMAP LCHAN LINTERFACE LFUNC LSTRUCT
%token <sym> LCOLAS LFALL LRETURN LDDD
%token <sym> LLEN LCAP LPANIC LPANICN LPRINT LPRINTN
%token <sym> LVAR LTYPE LCONST LSELECT LMAKE LNEW
%token <sym> LFOR LIF LELSE LSWITCH LCASE LDEFAULT
%token <sym> LBREAK LCONTINUE LGO LGOTO LRANGE
%token <sym> LNIL LTRUE LFALSE LIOTA
%token LOROR LANDAND LEQ LNE LLE LLT LGE LGT
%token LLSH LRSH LINC LDEC LCOMM LANDNOT
%token LIGNORE
/* // |sed 's/.* //' |9 fmt -l1 |sort |9 fmt -l50 | sed 's/^/%xxx /'
* the go semicolon rules are:
* %token <val> LLITERAL
* 1. all statements and declarations are terminated by semicolons %token <lint> LASOP
* 2. semicolons can be omitted at top level. %token <sym> LBREAK LCASE LCHAN LCOLAS LCONST LCONTINUE LDDD
* 3. semicolons can be omitted before and after the closing ) or } %token <sym> LDEFAULT LDEFER LELSE LFALL LFOR LFUNC LGO LGOTO
* on a list of statements or declarations. %token <sym> LIF LIMPORT LINTERFACE LMAKE LMAP LNAME LNEW
* %token <sym> LPACKAGE LRANGE LRETURN LSELECT LSTRUCT LSWITCH
* thus the grammar must distinguish productions that %token <sym> LTYPE LVAR
* can omit the semicolon terminator and those that can't.
* names like Astmt, Avardcl, etc. can drop the semicolon. %token LANDAND LANDNOT LBODY LCOMM LDEC LEQ LGE LGT
* names like Bstmt, Bvardcl, etc. can't. %token LIGNORE LINC LLE LLSH LLT LNE LOROR LRSH
*/
%type <lint> lbrace
%type <sym> sym sym1 sym2 sym3 keyword lname latype lpackatype %type <sym> sym packname
%type <node> xdcl xdcl_list_r oxdcl_list %type <val> oliteral
%type <node> common_dcl Acommon_dcl Bcommon_dcl
%type <node> oarg_type_list arg_type_list_r arg_chunk arg_chunk_list_r arg_type_list %type <node> Acommon_dcl Aelse_stmt Afnres Astmt Astmt_list_r
%type <node> Aelse_stmt Belse_stmt %type <node> Avardcl Bcommon_dcl Belse_stmt Bfnres Bstmt
%type <node> complex_stmt compound_stmt switch_body ocaseblock_list ostmt_list %type <node> Bstmt_list_r Bvardcl arg_type arg_type_list
%type <node> caseblock_list_r stmt_list_r Astmt_list_r Bstmt_list_r %type <node> arg_type_list_r braced_keyexpr_list case caseblock
%type <node> Astmt Bstmt %type <node> caseblock_list_r common_dcl complex_stmt
%type <node> for_stmt for_body for_header %type <node> compound_stmt dotname embed expr expr_list
%type <node> if_stmt if_header select_stmt switch_stmt condition case caseblock %type <node> expr_list_r expr_or_type expr_or_type_list
%type <node> simple_stmt osimple_stmt range_stmt semi_stmt %type <node> expr_or_type_list_r fnbody fndcl fnliteral fnres
%type <node> expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r %type <node> for_body for_header for_stmt if_header if_stmt
%type <node> exprsym3_list_r exprsym3 pseudocall %type <node> interfacedcl interfacedcl1 interfacedcl_list_r
%type <node> name labelname onew_name new_name new_name_list_r new_field %type <node> keyval keyval_list_r labelname loop_body name
%type <node> vardcl_list_r vardcl Avardcl Bvardcl %type <node> name_list name_list_r name_or_type new_field
%type <node> interfacedcl_list_r interfacedcl interfacedcl1 %type <node> new_name oarg_type_list ocaseblock_list oexpr
%type <node> structdcl_list_r structdcl embed %type <node> oexpr_list oexpr_or_type_list onew_name
%type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl fnbody %type <node> osimple_stmt ostmt_list oxdcl_list pexpr
%type <node> braced_keyexpr_list keyval_list_r keyval %type <node> pseudocall range_stmt select_stmt semi_stmt
%type <node> simple_stmt stmt_list_r structdcl structdcl_list_r
%type <type> typedclname new_type %type <node> switch_body switch_stmt uexpr vardcl vardcl_list_r
%type <type> type Atype Btype %type <node> xdcl xdcl_list_r xfndcl
%type <type> othertype Aothertype Bothertype
%type <type> chantype Achantype Bchantype %type <type> Achantype Afntype Anon_chan_type Anon_fn_type
%type <type> fntype Afntype Bfntype %type <type> Aothertype Atype Bchantype Bfntype Bnon_chan_type
%type <type> nametype structtype interfacetype convtype %type <type> Bnon_fn_type Bothertype Btype convtype dotdotdot
%type <type> non_name_type Anon_fn_type Bnon_fn_type %type <type> fnlitdcl fntype indcl interfacetype nametype
%type <type> Anon_chan_type Bnon_chan_type %type <type> new_type structtype type typedclname
%type <type> indcl fnlitdcl dotdotdot
%type <val> oliteral %type <sym> hidden_importsym hidden_pkg_importsym
%type <node> hidden_constant %type <node> hidden_constant hidden_dcl hidden_funarg_list
%type <node> hidden_dcl hidden_structdcl %type <node> hidden_funarg_list_r hidden_funres
%type <type> hidden_type hidden_type1 hidden_type2 %type <node> hidden_interfacedcl hidden_interfacedcl_list
%type <node> hidden_structdcl_list ohidden_structdcl_list hidden_structdcl_list_r %type <node> hidden_interfacedcl_list_r hidden_structdcl
%type <node> hidden_interfacedcl_list ohidden_interfacedcl_list hidden_interfacedcl_list_r %type <node> hidden_structdcl_list hidden_structdcl_list_r
%type <node> hidden_interfacedcl %type <node> ohidden_funarg_list ohidden_funres
%type <node> hidden_funarg_list ohidden_funarg_list hidden_funarg_list_r %type <node> ohidden_interfacedcl_list ohidden_structdcl_list
%type <node> hidden_funres ohidden_funres hidden_importsym hidden_pkg_importsym
%type <type> hidden_type hidden_type1 hidden_type2
%left LOROR
%left LANDAND %left LOROR
%left LCOMM %left LANDAND
%left LEQ LNE LLE LGE LLT LGT %left LCOMM
%left '+' '-' '|' '^' %left LEQ LNE LLE LGE LLT LGT
%left '*' '/' '%' '&' LLSH LRSH LANDNOT %left '+' '-' '|' '^'
%left '*' '/' '%' '&' LLSH LRSH LANDNOT
/* /*
* resolve { vs condition in favor of condition * manual override of shift/reduce conflicts.
* the general form is that we assign a precedence
* to the token being shifted and then introduce
* NotToken with lower precedence or PreferToToken with higher
* and annotate the reducing rule accordingly.
*/ */
%left '{' %left NotPackage
%left Condition %left LPACKAGE
/* %left NotParen
* resolve LPACKAGE vs not in favor of LPACKAGE %left '('
*/
%left NotPackage
%left LPACKAGE
/* %left ')'
* resolve '.' vs not in favor of '.' %left PreferToRightParen
*/
%left NotDot
%left '.'
/* %left NotDot
* resolve '(' vs not in favor of '(' %left '.'
*/
%left NotParen %left NotBrace
%left '(' %left '{'
%% %%
file: file:
...@@ -230,17 +238,17 @@ import_done: ...@@ -230,17 +238,17 @@ import_done:
if(my == import && strcmp(import->name, package) == 0) if(my == import && strcmp(import->name, package) == 0)
break; break;
if(my->lexical != LNAME || my->oname != N || my->otype != T) { if(my->def != N) {
// TODO(rsc): this line is only needed because of the // TODO(rsc): this line is only needed because of the
// package net // package net
// import "net" // import "net"
// convention; if we get rid of it, the check can go away // convention; if we get rid of it, the check can go away
// and we can just always print the error // and we can just always print the error
if(my->lexical != LPACK || strcmp(my->opack, import->name) != 0) if(my->def->op != OPACK || strcmp(my->name, import->name) != 0)
yyerror("redeclaration of %S by import", my); yyerror("redeclaration of %S by import", my);
} }
my->lexical = LPACK; my->def = nod(OPACK, N, N);
my->opack = import->name; my->def->sym = import;
} }
hidden_import_list: hidden_import_list:
...@@ -343,9 +351,8 @@ vardcl: ...@@ -343,9 +351,8 @@ vardcl:
| Bvardcl | Bvardcl
Avardcl: Avardcl:
new_name_list_r Atype name_list Atype
{ {
$$ = rev($1);
dodclvar($$, $2); dodclvar($$, $2);
if(funcdepth == 0) { if(funcdepth == 0) {
...@@ -357,9 +364,8 @@ Avardcl: ...@@ -357,9 +364,8 @@ Avardcl:
} }
Bvardcl: Bvardcl:
new_name_list_r Btype name_list Btype
{ {
$$ = rev($1);
dodclvar($$, $2); dodclvar($$, $2);
if(funcdepth == 0) { if(funcdepth == 0) {
...@@ -369,7 +375,7 @@ Bvardcl: ...@@ -369,7 +375,7 @@ Bvardcl:
addtotop($$); addtotop($$);
} }
} }
| new_name_list_r type '=' expr_list | name_list type '=' expr_list
{ {
if(addtop != N) if(addtop != N)
fatal("new_name_list_r type '=' expr_list"); fatal("new_name_list_r type '=' expr_list");
...@@ -377,7 +383,7 @@ Bvardcl: ...@@ -377,7 +383,7 @@ Bvardcl:
$$ = variter($1, $2, $4); $$ = variter($1, $2, $4);
addtotop($$); addtotop($$);
} }
| new_name_list_r '=' expr_list | name_list '=' expr_list
{ {
if(addtop != N) if(addtop != N)
fatal("new_name_list_r '=' expr_list"); fatal("new_name_list_r '=' expr_list");
...@@ -387,22 +393,22 @@ Bvardcl: ...@@ -387,22 +393,22 @@ Bvardcl:
} }
constdcl: constdcl:
new_name_list_r type '=' expr_list name_list type '=' expr_list
{ {
constiter($1, $2, $4); constiter($1, $2, $4);
} }
| new_name_list_r '=' expr_list | name_list '=' expr_list
{ {
constiter($1, T, $3); constiter($1, T, $3);
} }
constdcl1: constdcl1:
constdcl constdcl
| new_name_list_r type | name_list type
{ {
constiter($1, $2, N); constiter($1, $2, N);
} }
| new_name_list_r | name_list
{ {
constiter($1, T, N); constiter($1, T, N);
} }
...@@ -464,41 +470,23 @@ simple_stmt: ...@@ -464,41 +470,23 @@ simple_stmt:
$$ = nod(OASOP, $1, $3); $$ = nod(OASOP, $1, $3);
$$->etype = $2; // rathole to pass opcode $$->etype = $2; // rathole to pass opcode
} }
| exprsym3_list_r '=' expr_list | expr_list '=' expr_list
{ {
$$ = rev($1);
$$ = nod(OAS, $$, $3); $$ = nod(OAS, $$, $3);
} }
| exprsym3_list_r LCOLAS expr_list | expr_list LCOLAS expr_list
{ {
if(addtop != N) if(addtop != N)
fatal("exprsym3_list_r LCOLAS expr_list"); fatal("expr_list LCOLAS expr_list");
if($3->op == OTYPESW) { if($3->op == OTYPESW) {
$$ = nod(OTYPESW, $1, $3->left); $$ = nod(OTYPESW, $1, $3->left);
break; break;
} }
$$ = rev($1);
$$ = colas($$, $3); $$ = colas($$, $3);
$$ = nod(OAS, $$, $3); $$ = nod(OAS, $$, $3);
$$->colas = 1; $$->colas = 1;
addtotop($$); addtotop($$);
} }
| LPRINT '(' oexpr_list ')'
{
$$ = nod(OPRINT, $3, N);
}
| LPRINTN '(' oexpr_list ')'
{
$$ = nod(OPRINTN, $3, N);
}
| LPANIC '(' oexpr_list ')'
{
$$ = nod(OPANIC, $3, N);
}
| LPANICN '(' oexpr_list ')'
{
$$ = nod(OPANICN, $3, N);
}
| expr LINC | expr LINC
{ {
$$ = nod(OASOP, $1, nodintconst(1)); $$ = nod(OASOP, $1, nodintconst(1));
...@@ -533,15 +521,36 @@ case: ...@@ -533,15 +521,36 @@ case:
// right will point to next case // right will point to next case
// done in casebody() // done in casebody()
poptodcl(); poptodcl();
if(typeswvar != N && typeswvar->right != N) if(typeswvar != N && typeswvar->right != N) {
if($2->op == OLITERAL && $2->val.ctype == CTNIL) { if($2->op == OLITERAL && $2->val.ctype == CTNIL) {
// this version in type switch case nil // this version in type switch case nil
$$ = nod(OTYPESW, N, N); $$ = nod(OTYPESW, N, N);
$$ = nod(OXCASE, $$, N); $$ = nod(OXCASE, $$, N);
break; break;
}
if($2->op == OTYPE) {
$$ = old2new(typeswvar->right, $2->type);
$$ = nod(OTYPESW, $$, N);
$$ = nod(OXCASE, $$, N);
addtotop($$);
break;
}
yyerror("non-type case in type switch");
} }
$$ = nod(OXCASE, $2, N); $$ = nod(OXCASE, $2, N);
} }
| LCASE type ':'
{
poptodcl();
if(typeswvar == N || typeswvar->right == N) {
yyerror("type case not in a type switch");
$$ = N;
} else
$$ = old2new(typeswvar->right, $2);
$$ = nod(OTYPESW, $$, N);
$$ = nod(OXCASE, $$, N);
addtotop($$);
}
| LCASE name '=' expr ':' | LCASE name '=' expr ':'
{ {
// will be converted to OCASE // will be converted to OCASE
...@@ -561,18 +570,6 @@ case: ...@@ -561,18 +570,6 @@ case:
$$ = nod(OXCASE, $$, N); $$ = nod(OXCASE, $$, N);
addtotop($$); addtotop($$);
} }
| LCASE type ':'
{
poptodcl();
if(typeswvar == N || typeswvar->right == N) {
yyerror("type case not in a type switch");
$$ = N;
} else
$$ = old2new(typeswvar->right, $2);
$$ = nod(OTYPESW, $$, N);
$$ = nod(OXCASE, $$, N);
addtotop($$);
}
| LDEFAULT ':' | LDEFAULT ':'
{ {
poptodcl(); poptodcl();
...@@ -620,7 +617,8 @@ compound_stmt: ...@@ -620,7 +617,8 @@ compound_stmt:
'{' '{'
{ {
markdcl(); markdcl();
} ostmt_list '}' }
ostmt_list '}'
{ {
$$ = $3; $$ = $3;
if($$ == N) if($$ == N)
...@@ -629,7 +627,7 @@ compound_stmt: ...@@ -629,7 +627,7 @@ compound_stmt:
} }
switch_body: switch_body:
'{' LBODY
{ {
markdcl(); markdcl();
} }
...@@ -655,13 +653,26 @@ caseblock_list_r: ...@@ -655,13 +653,26 @@ caseblock_list_r:
$$ = nod(OLIST, $1, $2); $$ = nod(OLIST, $1, $2);
} }
loop_body:
LBODY
{
markdcl();
}
ostmt_list '}'
{
$$ = $3;
if($$ == N)
$$ = nod(OEMPTY, N, N);
popdcl();
}
range_stmt: range_stmt:
exprsym3_list_r '=' LRANGE expr expr_list '=' LRANGE expr
{ {
$$ = nod(ORANGE, $1, $4); $$ = nod(ORANGE, $1, $4);
$$->etype = 0; // := flag $$->etype = 0; // := flag
} }
| exprsym3_list_r LCOLAS LRANGE expr | expr_list LCOLAS LRANGE expr
{ {
$$ = nod(ORANGE, $1, $4); $$ = nod(ORANGE, $1, $4);
$$->etype = 1; $$->etype = 1;
...@@ -678,7 +689,7 @@ for_header: ...@@ -678,7 +689,7 @@ for_header:
$$->ntest = $3; $$->ntest = $3;
$$->nincr = $5; $$->nincr = $5;
} }
| condition | osimple_stmt
{ {
// normal test // normal test
$$ = nod(OFOR, N, N); $$ = nod(OFOR, N, N);
...@@ -693,7 +704,7 @@ for_header: ...@@ -693,7 +704,7 @@ for_header:
} }
for_body: for_body:
for_header compound_stmt for_header loop_body
{ {
$$ = $1; $$ = $1;
$$->nbody = list($$->nbody, $2); $$->nbody = list($$->nbody, $2);
...@@ -710,30 +721,15 @@ for_stmt: ...@@ -710,30 +721,15 @@ for_stmt:
popdcl(); popdcl();
} }
/*
* using cond instead of osimple_stmt creates
* a shift/reduce conflict on an input like
*
* if x == []int { true } { true }
*
* at the first {, giving us an opportunity
* to resolve it by reduce, which implements
* the rule about { } inside if conditions
* needing parens.
*/
condition:
osimple_stmt %prec Condition
if_header: if_header:
condition osimple_stmt
{ {
// test // test
$$ = nod(OIF, N, N); $$ = nod(OIF, N, N);
$$->ninit = N; $$->ninit = N;
$$->ntest = $1; $$->ntest = $1;
} }
| osimple_stmt ';' condition | osimple_stmt ';' osimple_stmt
{ {
// init ; test // init ; test
$$ = nod(OIF, N, N); $$ = nod(OIF, N, N);
...@@ -746,7 +742,7 @@ if_stmt: ...@@ -746,7 +742,7 @@ if_stmt:
{ {
markdcl(); markdcl();
} }
if_header compound_stmt if_header loop_body
{ {
$$ = $3; $$ = $3;
$$->nbody = $4; $$->nbody = $4;
...@@ -878,6 +874,10 @@ uexpr: ...@@ -878,6 +874,10 @@ uexpr:
pexpr pexpr
| '*' uexpr | '*' uexpr
{ {
if($2->op == OTYPE) {
$$ = typenod(ptrto($2->type));
break;
}
$$ = nod(OIND, $2, N); $$ = nod(OIND, $2, N);
} }
| '&' uexpr | '&' uexpr
...@@ -915,15 +915,26 @@ uexpr: ...@@ -915,15 +915,26 @@ uexpr:
* can be preceeded by 'defer' and 'go' * can be preceeded by 'defer' and 'go'
*/ */
pseudocall: pseudocall:
pexpr '(' oexpr_list ')' pexpr '(' oexpr_or_type_list ')'
{ {
$$ = unsafenmagic($1, $3); $$ = unsafenmagic($1, $3);
if($$ == N) if($$)
$$ = nod(OCALL, $1, $3); break;
} if($1->op == OTYPE) {
| LCLOSE '(' expr ')' // type conversion
{ if($3 == N)
$$ = nod(OCLOSE, $3, N); yyerror("conversion to %T missing expr", $1->type);
else if($3->op == OLIST)
yyerror("conversion to %T has too many exprs", $1->type);
$$ = nod(OCONV, $3, N);
$$->type = $1->type;
break;
}
if($1->op == ONAME && $1->etype != 0) { // builtin OLEN, OCAP, etc
$$ = nod($1->etype, $3, N);
break;
}
$$ = nod(OCALL, $1, $3);
} }
pexpr: pexpr:
...@@ -931,39 +942,28 @@ pexpr: ...@@ -931,39 +942,28 @@ pexpr:
{ {
$$ = nodlit($1); $$ = nodlit($1);
} }
| LNIL | name %prec NotBrace
| pexpr '.' sym
{ {
Val v; if($1->op == OPACK) {
v.ctype = CTNIL; Sym *s;
$$ = nodlit(v); s = pkglookup($3->name, $1->sym->name);
} $$ = oldname(s);
| LTRUE break;
{ }
$$ = nodbool(1); $$ = nod(ODOT, $1, newname($3));
} $$ = adddot($$);
| LFALSE
{
$$ = nodbool(0);
}
| LIOTA
{
$$ = nodintconst(iota);
$$->iota = 1; // flag to reevaluate on copy
} }
| name | '(' expr_or_type ')'
| '(' expr ')'
{ {
$$ = $2; $$ = $2;
} }
| pexpr '.' sym2 | pexpr '.' '(' expr_or_type ')'
{
$$ = nod(ODOT, $1, newname($3));
$$ = adddot($$);
}
| pexpr '.' '(' type ')'
{ {
$$ = nod(ODOTTYPE, $1, N); $$ = nod(ODOTTYPE, $1, N);
$$->type = $4; if($4->op != OTYPE)
yyerror("expected type got %O", $4->op);
$$->type = $4->type;
} }
| pexpr '.' '(' LTYPE ')' | pexpr '.' '(' LTYPE ')'
{ {
...@@ -978,93 +978,63 @@ pexpr: ...@@ -978,93 +978,63 @@ pexpr:
$$ = nod(OSLICE, $1, $3); $$ = nod(OSLICE, $1, $3);
} }
| pseudocall | pseudocall
| LLEN '(' expr ')'
{
$$ = nod(OLEN, $3, N);
}
| LCLOSED '(' expr ')'
{
$$ = nod(OCLOSED, $3, N);
}
| LCAP '(' expr ')'
{
$$ = nod(OCAP, $3, N);
}
| LNEW '(' type ')'
{
$$ = nod(ONEW, N, N);
$$->type = $3;
}
| LNEW '(' type ',' expr_list ')'
{
$$ = nod(ONEW, $5, N);
$$->type = $3;
}
| LMAKE '(' type ')'
{
$$ = nod(OMAKE, N, N);
$$->type = $3;
}
| LMAKE '(' type ',' expr_list ')'
{
$$ = nod(OMAKE, $5, N);
$$->type = $3;
}
| convtype '(' expr ')' | convtype '(' expr ')'
{ {
// conversion // conversion
$$ = nod(OCONV, $3, N);
$$->type = $1;
}
| convtype lbrace braced_keyexpr_list '}'
{
// composite expression
$$ = rev($3); $$ = rev($3);
if($$ == N) if($$ == N)
$$ = nod(OEMPTY, N, N); $$ = nod(OEMPTY, N, N);
$$ = nod(OCONV, $$, N); $$ = nod(OCOMPOS, $$, N);
$$->type = $1; $$->type = $1;
// If the opening brace was an LBODY,
// set up for another one now that we're done.
// See comment in lex.c about loophack.
if($2 == LBODY)
loophack = 1;
} }
| convtype '{' braced_keyexpr_list '}' | pexpr '{' braced_keyexpr_list '}'
{ {
// composite expression // composite expression
$$ = rev($3); $$ = rev($3);
if($$ == N) if($$ == N)
$$ = nod(OEMPTY, N, N); $$ = nod(OEMPTY, N, N);
$$ = nod(OCOMPOS, $$, N); $$ = nod(OCOMPOS, $$, N);
$$->type = $1; if($1->op != OTYPE)
yyerror("expected type in composite literal");
else
$$->type = $1->type;
} }
| fnliteral | fnliteral
/* expr_or_type:
* lexical symbols that can be expr
* from other packages | type %prec PreferToRightParen
*/
lpack:
LPACK
{ {
context = $1->opack; $$ = typenod($1);
} }
/*
* adding this would enable gri's nested package idea name_or_type:
* dotname
| lpack '.' LPACK | type
{ {
context = $3->opack; $$ = typenod($1);
} }
*/
lname: lbrace:
LNAME LBODY
| lpack '.' LNAME
{ {
$$ = $3; $$ = LBODY;
context = nil;
} }
| '{'
latype:
LATYPE
| lpackatype
lpackatype:
lpack '.' LATYPE
{ {
$$ = $3; $$ = '{';
context = nil;
} }
/* /*
...@@ -1073,19 +1043,19 @@ lpackatype: ...@@ -1073,19 +1043,19 @@ lpackatype:
* oldname is used after declared * oldname is used after declared
*/ */
new_name: new_name:
sym1 sym
{ {
$$ = newname($1); $$ = newname($1);
} }
new_field: new_field:
sym2 sym
{ {
$$ = newname($1); $$ = newname($1);
} }
new_type: new_type:
sym1 sym
{ {
$$ = newtype($1); $$ = newtype($1);
} }
...@@ -1097,84 +1067,19 @@ onew_name: ...@@ -1097,84 +1067,19 @@ onew_name:
| new_name | new_name
sym: sym:
LATYPE LNAME
| LNAME
| LPACK
sym1:
sym
| keyword
/*
* keywords that can be field names
* pretty much any name can be allowed
* limited only by good taste
*/
sym2:
sym1
/*
* keywords that can be variables
* but are not already legal expressions
*/
sym3:
LLEN
| LCAP
| LCLOSE
| LCLOSED
| LPANIC
| LPANICN
| LPRINT
| LPRINTN
| LNEW
| LMAKE
/*
* keywords that we can
* use as variable/type names
*/
keyword:
sym3
| LNIL
| LTRUE
| LFALSE
| LIOTA
name: name:
lname sym %prec NotDot
{
$$ = oldname($1);
}
/*
* this rule introduces 1 reduce/reduce conflict
* with the rule lpack: LPACK above.
* the reduce/reduce conflict is only with
* lookahead '.', in which case the correct
* resolution is the lpack rule. (and it wins
* because it is above.)
*/
| LPACK %prec NotDot
{ {
$$ = oldname($1); $$ = oldname($1);
} }
labelname: labelname:
name name
| LATYPE
{
$$ = oldname($1);
}
| keyword
{
$$ = oldname($1);
}
convtype: convtype:
latype '[' oexpr ']' type
{
$$ = oldtype($1);
}
| '[' oexpr ']' type
{ {
// array literal // array literal
$$ = aindex($2, $4); $$ = aindex($2, $4);
...@@ -1191,10 +1096,6 @@ convtype: ...@@ -1191,10 +1096,6 @@ convtype:
$$ = maptype($3, $5); $$ = maptype($3, $5);
} }
| structtype | structtype
| '(' type ')'
{
$$ = $2;
}
/* /*
* to avoid parsing conflicts, type is split into * to avoid parsing conflicts, type is split into
...@@ -1227,12 +1128,6 @@ Btype: ...@@ -1227,12 +1128,6 @@ Btype:
$$ = $2; $$ = $2;
} }
non_name_type:
chantype
| fntype
| othertype
| dotdotdot
dotdotdot: dotdotdot:
LDDD LDDD
{ {
...@@ -1262,17 +1157,28 @@ Bnon_fn_type: ...@@ -1262,17 +1157,28 @@ Bnon_fn_type:
| Bothertype | Bothertype
nametype: nametype:
LATYPE dotname
{ {
if($1->otype != T && $1->otype->etype == TANY) if($1->op == OTYPE)
if($1->type->etype == TANY)
if(strcmp(package, "PACKAGE") != 0) if(strcmp(package, "PACKAGE") != 0)
yyerror("the any type is restricted"); yyerror("the any type is restricted");
$$ = oldtype($1); $$ = oldtype($1->sym);
} }
othertype: dotname:
Aothertype name %prec NotDot
| Bothertype | name '.' sym
{
if($1->op == OPACK) {
Sym *s;
s = pkglookup($3->name, $1->sym->name);
$$ = oldname(s);
break;
}
$$ = nod(ODOT, $1, newname($3));
$$ = adddot($$);
}
Aothertype: Aothertype:
'[' oexpr ']' Atype '[' oexpr ']' Atype
...@@ -1303,11 +1209,7 @@ Aothertype: ...@@ -1303,11 +1209,7 @@ Aothertype:
| interfacetype | interfacetype
Bothertype: Bothertype:
lpackatype '[' oexpr ']' Btype
{
$$ = oldtype($1);
}
| '[' oexpr ']' Btype
{ {
$$ = aindex($2, $4); $$ = aindex($2, $4);
} }
...@@ -1332,10 +1234,6 @@ Bothertype: ...@@ -1332,10 +1234,6 @@ Bothertype:
$$ = ptrto($2); $$ = ptrto($2);
} }
chantype:
Achantype
| Bchantype
Achantype: Achantype:
LCHAN Atype LCHAN Atype
{ {
...@@ -1378,10 +1276,6 @@ keyval: ...@@ -1378,10 +1276,6 @@ keyval:
{ {
$$ = nod(OKEY, $1, $3); $$ = nod(OKEY, $1, $3);
} }
| LATYPE ':' expr
{
$$ = nod(OKEY, newname($1), $3);
}
/* /*
...@@ -1574,15 +1468,24 @@ structdcl: ...@@ -1574,15 +1468,24 @@ structdcl:
$$->val = $3; $$->val = $3;
} }
embed: packname:
LATYPE LNAME
| LNAME '.' sym
{ {
$$ = embedded($1); char *pkg;
if($1->def == N || $1->def->op != OPACK) {
yyerror("%S is not a package", $1);
pkg = $1->name;
} else
pkg = $1->def->sym->name;
$$ = pkglookup($3->name, pkg);
} }
| lpack '.' LATYPE
embed:
packname
{ {
$$ = embedded($3); $$ = embedded($1);
context = nil;
} }
interfacedcl1: interfacedcl1:
...@@ -1599,7 +1502,7 @@ interfacedcl1: ...@@ -1599,7 +1502,7 @@ interfacedcl1:
interfacedcl: interfacedcl:
interfacedcl1 interfacedcl1
| latype | packname
{ {
$$ = nod(ODCLFIELD, N, N); $$ = nod(ODCLFIELD, N, N);
$$->type = oldtype($1); $$->type = oldtype($1);
...@@ -1614,65 +1517,44 @@ indcl: ...@@ -1614,65 +1517,44 @@ indcl:
/* /*
* function arguments. * function arguments.
*
* the hard part is that when we're reading a list of names,
* we don't know if they are going to be the names of
* parameters (like "a,b,c int") or the types of anonymous
* parameters (like "int, string, bool").
*
* an arg_chunk is a comma-separated list of arguments
* that ends in an obvious type, either "a, b, c x" or "a, b, c, *x".
* in the first case, a, b, c are parameters of type x.
* in the second case, a, b, c, and *x are types of anonymous parameters.
*/ */
arg_chunk: arg_type:
new_name_list_r type name_or_type
{ | sym name_or_type
$$ = nametodcl($1, $2); {
} $$ = $1->def;
| new_name_list_r dotdotdot if($$ == N) {
{ $$ = nod(ONONAME, N, N);
$$ = nametodcl($1, $2); $$->sym = $1;
} }
| non_name_type $$ = nod(OKEY, $$, $2);
{
$$ = anondcl($1);
} }
| new_name_list_r ',' non_name_type | sym dotdotdot
{ {
$1 = nametoanondcl($1); $$ = $1->def;
$$ = appendr($1, anondcl($3)); if($$ == N) {
$$ = nod(ONONAME, N, N);
$$->sym = $1;
}
$$ = nod(OKEY, $$, typenod($2));
} }
| dotdotdot
arg_chunk_list_r:
arg_chunk
| arg_chunk_list_r ',' arg_chunk
{ {
$$ = appendr($1, $3); $$ = typenod($1);
} }
/*
* an arg type list is a sequence of arg chunks,
* possibly ending in a list of names (plain "a,b,c"),
* which must be the types of anonymous parameters.
*/
arg_type_list_r: arg_type_list_r:
arg_chunk_list_r arg_type
| arg_chunk_list_r ',' new_name_list_r | arg_type_list_r ',' arg_type
{ {
$3 = nametoanondcl($3); $$ = nod(OLIST, $1, $3);
$$ = appendr($1, $3);
}
| new_name_list_r
{
$$ = nametoanondcl($1);
} }
arg_type_list: arg_type_list:
arg_type_list_r arg_type_list_r
{ {
$$ = rev($1); $$ = rev($1);
checkarglist($$); $$ = checkarglist($$);
} }
/* /*
...@@ -1728,34 +1610,26 @@ stmt_list_r: ...@@ -1728,34 +1610,26 @@ stmt_list_r:
Astmt_list_r Astmt_list_r
| Bstmt_list_r | Bstmt_list_r
expr_list_r: name_list_r:
expr name
| expr_list_r ',' expr
{ {
$$ = nod(OLIST, $1, $3); $$ = newname($1->sym);
} }
| name_list_r ',' name
new_name_list_r:
new_name
| new_name_list_r ',' new_name
{ {
$$ = nod(OLIST, $1, $3); $$ = nod(OLIST, $1, newname($3->sym));
} }
exprsym3: expr_list_r:
expr expr
| sym3 | expr_list_r ',' expr
{
$$ = newname($1);
}
| LATYPE
{ {
$$ = newname($1); $$ = nod(OLIST, $1, $3);
} }
exprsym3_list_r: expr_or_type_list_r:
exprsym3 expr_or_type
| exprsym3_list_r ',' exprsym3 | expr_or_type_list_r ',' expr_or_type
{ {
$$ = nod(OLIST, $1, $3); $$ = nod(OLIST, $1, $3);
} }
...@@ -1844,6 +1718,18 @@ expr_list: ...@@ -1844,6 +1718,18 @@ expr_list:
$$ = rev($1); $$ = rev($1);
} }
expr_or_type_list:
expr_or_type_list_r
{
$$ = rev($1);
}
name_list:
name_list_r
{
$$ = rev($1);
}
/* /*
* optional things * optional things
...@@ -1866,6 +1752,12 @@ oexpr_list: ...@@ -1866,6 +1752,12 @@ oexpr_list:
} }
| expr_list | expr_list
oexpr_or_type_list:
{
$$ = N;
}
| expr_or_type_list
osimple_stmt: osimple_stmt:
{ {
$$ = N; $$ = N;
...@@ -1934,7 +1826,7 @@ oliteral: ...@@ -1934,7 +1826,7 @@ oliteral:
* an output package * an output package
*/ */
hidden_import: hidden_import:
LPACKAGE sym1 LPACKAGE sym
/* variables */ /* variables */
| LVAR hidden_pkg_importsym hidden_type | LVAR hidden_pkg_importsym hidden_type
{ {
...@@ -1956,7 +1848,7 @@ hidden_import: ...@@ -1956,7 +1848,7 @@ hidden_import:
{ {
importvar($2, functype(N, $4, $6), PFUNC); importvar($2, functype(N, $4, $6), PFUNC);
} }
| LFUNC '(' hidden_funarg_list ')' sym1 '(' ohidden_funarg_list ')' ohidden_funres | LFUNC '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres
{ {
if($3->op != ODCLFIELD) { if($3->op != ODCLFIELD) {
yyerror("bad receiver in method"); yyerror("bad receiver in method");
...@@ -1972,9 +1864,9 @@ hidden_type: ...@@ -1972,9 +1864,9 @@ hidden_type:
hidden_type1: hidden_type1:
hidden_importsym hidden_importsym
{ {
$$ = pkgtype($1->sym->name, $1->psym->name); $$ = pkgtype($1);
} }
| LATYPE | LNAME
{ {
$$ = oldtype($1); $$ = oldtype($1);
} }
...@@ -2034,7 +1926,7 @@ hidden_type2: ...@@ -2034,7 +1926,7 @@ hidden_type2:
} }
hidden_dcl: hidden_dcl:
sym1 hidden_type sym hidden_type
{ {
$$ = nod(ODCLFIELD, newname($1), N); $$ = nod(ODCLFIELD, newname($1), N);
$$->type = $2; $$->type = $2;
...@@ -2046,7 +1938,7 @@ hidden_dcl: ...@@ -2046,7 +1938,7 @@ hidden_dcl:
} }
hidden_structdcl: hidden_structdcl:
sym1 hidden_type oliteral sym hidden_type oliteral
{ {
$$ = nod(ODCLFIELD, newname($1), N); $$ = nod(ODCLFIELD, newname($1), N);
$$->type = $2; $$->type = $2;
...@@ -2063,7 +1955,7 @@ hidden_structdcl: ...@@ -2063,7 +1955,7 @@ hidden_structdcl:
} }
hidden_interfacedcl: hidden_interfacedcl:
sym1 '(' ohidden_funarg_list ')' ohidden_funres sym '(' ohidden_funarg_list ')' ohidden_funres
{ {
$$ = nod(ODCLFIELD, newname($1), N); $$ = nod(ODCLFIELD, newname($1), N);
$$->type = functype(fakethis(), $3, $5); $$->type = functype(fakethis(), $3, $5);
...@@ -2105,72 +1997,24 @@ hidden_constant: ...@@ -2105,72 +1997,24 @@ hidden_constant:
yyerror("bad negated constant"); yyerror("bad negated constant");
} }
} }
| LTRUE | name
{
$$ = nodbool(1);
}
| LFALSE
{ {
$$ = nodbool(0); $$ = $1;
if($$->op != OLITERAL)
yyerror("bad constant %S", $$->sym);
} }
hidden_importsym: hidden_importsym:
sym1 '.' sym2 sym '.' sym
{ {
$$ = nod(OIMPORT, N, N); $$ = pkglookup($3->name, $1->name);
$$->psym = $1;
$$->sym = $3;
} }
hidden_pkg_importsym: hidden_pkg_importsym:
hidden_importsym hidden_importsym
{ {
$$ = $1; $$ = $1;
pkgcontext = $$->psym->name; structpkg = $$->package;
}
/*
* helpful error messages.
* THIS SECTION MUST BE AT THE END OF THE FILE.
*
* these rules trigger reduce/reduce conflicts in the grammar.
* they are safe because reduce/reduce conflicts are resolved
* in favor of rules appearing earlier in the grammar, and these
* are at the end of the file.
*
* to check whether the rest of the grammar is free of
* reduce/reduce conflicts, comment this section out by
* removing the slash on the next line.
*
* there should be exactly 1 reduce/reduce conflict
* when this block is commented out.
*/
lpack:
LATYPE
{
yyerror("%s is type, not package", $1->name);
YYERROR;
}
latype:
LPACK
{
yyerror("%s is package, not type", $1->name);
YYERROR;
}
| LNAME
{
yyerror("no type %s", $1->name);
YYERROR;
}
nametype:
LNAME
{
yyerror("no type %s", $1->name);
YYERROR;
} }
/**/
...@@ -64,7 +64,7 @@ main(int argc, char *argv[]) ...@@ -64,7 +64,7 @@ main(int argc, char *argv[])
fatal("betypeinit failed"); fatal("betypeinit failed");
lexinit(); lexinit();
typeinit(LATYPE); typeinit();
lineno = 1; lineno = 1;
block = 1; block = 1;
...@@ -711,6 +711,40 @@ l0: ...@@ -711,6 +711,40 @@ l0:
} }
break; break;
/*
* clumsy dance:
* to implement rule that disallows
* if T{1}[0] { ... }
* but allows
* if (T{1}[0]) { ... }
* the block bodies for if/for/switch/select
* begin with an LBODY token, not '{'.
*
* when we see the keyword, the next
* non-parenthesized '{' becomes an LBODY.
* loophack is normally 0.
* a keyword makes it go up to 1.
* parens increment and decrement when loophack > 0.
* a '{' with loophack == 1 becomes LBODY and disables loophack.
*
* i said it was clumsy.
*/
case '(':
if(loophack > 0)
loophack++;
goto lx;
case ')':
if(loophack > 0)
loophack--;
goto lx;
case '{':
if(loophack == 1) {
DBG("%L lex: LBODY\n", lineno);
loophack = 0;
return LBODY;
}
goto lx;
default: default:
goto lx; goto lx;
} }
...@@ -764,15 +798,16 @@ talph: ...@@ -764,15 +798,16 @@ talph:
ungetc(c); ungetc(c);
s = lookup(lexbuf); s = lookup(lexbuf);
if(s->lexical == LIGNORE) switch(s->lexical) {
case LIGNORE:
goto l0; goto l0;
if(context != nil) { case LFOR:
s = pkglookup(s->name, context); case LIF:
if(s->lexical == LIGNORE) case LSWITCH:
goto l0; case LSELECT:
if(!exportname(s->name) && strcmp(package, s->package) != 0) loophack = 1; // see comment about loophack above
s = pkglookup(s->name, ".private"); break;
} }
DBG("lex: %S %s\n", s, lexname(s->lexical)); DBG("lex: %S %s\n", s, lexname(s->lexical));
...@@ -1109,77 +1144,74 @@ static struct ...@@ -1109,77 +1144,74 @@ static struct
char* name; char* name;
int lexical; int lexical;
int etype; int etype;
int op;
} syms[] = } syms[] =
{ {
/* name lexical etype /* name lexical etype op
*/ */
/* basic types */ /* basic types */
"int8", LATYPE, TINT8, "int8", LNAME, TINT8, OXXX,
"int16", LATYPE, TINT16, "int16", LNAME, TINT16, OXXX,
"int32", LATYPE, TINT32, "int32", LNAME, TINT32, OXXX,
"int64", LATYPE, TINT64, "int64", LNAME, TINT64, OXXX,
"uint8", LATYPE, TUINT8, "uint8", LNAME, TUINT8, OXXX,
"uint16", LATYPE, TUINT16, "uint16", LNAME, TUINT16, OXXX,
"uint32", LATYPE, TUINT32, "uint32", LNAME, TUINT32, OXXX,
"uint64", LATYPE, TUINT64, "uint64", LNAME, TUINT64, OXXX,
"float32", LATYPE, TFLOAT32, "float32", LNAME, TFLOAT32, OXXX,
"float64", LATYPE, TFLOAT64, "float64", LNAME, TFLOAT64, OXXX,
"float80", LATYPE, TFLOAT80, "float80", LNAME, TFLOAT80, OXXX,
"bool", LATYPE, TBOOL, "bool", LNAME, TBOOL, OXXX,
"byte", LATYPE, TUINT8, "byte", LNAME, TUINT8, OXXX,
"string", LATYPE, TSTRING, "string", LNAME, TSTRING, OXXX,
"any", LATYPE, TANY, "any", LNAME, TANY, OXXX,
"break", LBREAK, Txxx, "break", LBREAK, Txxx, OXXX,
"case", LCASE, Txxx, "case", LCASE, Txxx, OXXX,
"chan", LCHAN, Txxx, "chan", LCHAN, Txxx, OXXX,
"const", LCONST, Txxx, "const", LCONST, Txxx, OXXX,
"continue", LCONTINUE, Txxx, "continue", LCONTINUE, Txxx, OXXX,
"default", LDEFAULT, Txxx, "default", LDEFAULT, Txxx, OXXX,
"else", LELSE, Txxx, "else", LELSE, Txxx, OXXX,
"defer", LDEFER, Txxx, "defer", LDEFER, Txxx, OXXX,
"fallthrough", LFALL, Txxx, "fallthrough", LFALL, Txxx, OXXX,
"false", LFALSE, Txxx, "for", LFOR, Txxx, OXXX,
"for", LFOR, Txxx, "func", LFUNC, Txxx, OXXX,
"func", LFUNC, Txxx, "go", LGO, Txxx, OXXX,
"go", LGO, Txxx, "goto", LGOTO, Txxx, OXXX,
"goto", LGOTO, Txxx, "if", LIF, Txxx, OXXX,
"if", LIF, Txxx, "import", LIMPORT, Txxx, OXXX,
"import", LIMPORT, Txxx, "interface", LINTERFACE, Txxx, OXXX,
"interface", LINTERFACE, Txxx, "map", LMAP, Txxx, OXXX,
"iota", LIOTA, Txxx, "package", LPACKAGE, Txxx, OXXX,
"make", LMAKE, Txxx, "range", LRANGE, Txxx, OXXX,
"map", LMAP, Txxx, "return", LRETURN, Txxx, OXXX,
"new", LNEW, Txxx, "select", LSELECT, Txxx, OXXX,
"len", LLEN, Txxx, "struct", LSTRUCT, Txxx, OXXX,
"cap", LCAP, Txxx, "switch", LSWITCH, Txxx, OXXX,
"nil", LNIL, Txxx, "type", LTYPE, Txxx, OXXX,
"package", LPACKAGE, Txxx, "var", LVAR, Txxx, OXXX,
"panic", LPANIC, Txxx,
"panicln", LPANICN, Txxx, "cap", LNAME, Txxx, OCAP,
"print", LPRINT, Txxx, "close", LNAME, Txxx, OCLOSE,
"println", LPRINTN, Txxx, "closed", LNAME, Txxx, OCLOSED,
"range", LRANGE, Txxx, "len", LNAME, Txxx, OLEN,
"return", LRETURN, Txxx, "make", LNAME, Txxx, OMAKE,
"select", LSELECT, Txxx, "new", LNAME, Txxx, ONEW,
"struct", LSTRUCT, Txxx, "panic", LNAME, Txxx, OPANIC,
"switch", LSWITCH, Txxx, "panicln", LNAME, Txxx, OPANICN,
"true", LTRUE, Txxx, "print", LNAME, Txxx, OPRINT,
"type", LTYPE, Txxx, "println", LNAME, Txxx, OPRINTN,
"var", LVAR, Txxx,
"notwithstanding", LIGNORE, Txxx, OXXX,
"close", LCLOSE, Txxx, "thetruthofthematter", LIGNORE, Txxx, OXXX,
"closed", LCLOSED, Txxx, "despiteallobjections", LIGNORE, Txxx, OXXX,
"whereas", LIGNORE, Txxx, OXXX,
"notwithstanding", LIGNORE, Txxx, "insofaras", LIGNORE, Txxx, OXXX,
"thetruthofthematter", LIGNORE, Txxx,
"despiteallobjections", LIGNORE, Txxx,
"whereas", LIGNORE, Txxx,
"insofaras", LIGNORE, Txxx,
}; };
void void
...@@ -1189,6 +1221,7 @@ lexinit(void) ...@@ -1189,6 +1221,7 @@ lexinit(void)
Sym *s; Sym *s;
Type *t; Type *t;
int etype; int etype;
Val v;
/* /*
* initialize basic types array * initialize basic types array
...@@ -1201,25 +1234,51 @@ lexinit(void) ...@@ -1201,25 +1234,51 @@ lexinit(void)
s->package = package; s->package = package;
etype = syms[i].etype; etype = syms[i].etype;
if(etype == Txxx) if(etype != Txxx) {
if(etype < 0 || etype >= nelem(types))
fatal("lexinit: %s bad etype", s->name);
t = types[etype];
if(t == T) {
t = typ(etype);
t->sym = s;
dowidth(t);
types[etype] = t;
}
s->def = typenod(t);
continue; continue;
}
if(etype < 0 || etype >= nelem(types)) etype = syms[i].op;
fatal("lexinit: %s bad etype", s->name); if(etype != OXXX) {
s->def = nod(ONAME, N, N);
t = types[etype]; s->def->sym = s;
if(t != T) { s->def->etype = etype;
s->otype = t; s->def->builtin = 1;
continue; continue;
} }
t = typ(etype);
t->sym = s;
dowidth(t);
types[etype] = t;
s->otype = t;
} }
// there's only so much table-driven we can handle.
// these are special cases.
types[TNIL] = typ(TNIL);
s = lookup("nil");
v.ctype = CTNIL;
s->def = nodlit(v);
s->def->sym = s;
s = lookup("true");
s->def = nodbool(1);
s->def->sym = s;
s = lookup("false");
s->def = nodbool(0);
s->def->sym = s;
s = lookup("iota");
s->def = nodintconst(iota);
s->def->iota = 1; // flag to reevaluate on copy
// logically, the type of a string literal. // logically, the type of a string literal.
// types[TSTRING] is the named type string // types[TSTRING] is the named type string
// (the type of x in var x string or var x = "hello"). // (the type of x in var x string or var x = "hello").
...@@ -1244,14 +1303,18 @@ struct ...@@ -1244,14 +1303,18 @@ struct
LCONST, "CONST", LCONST, "CONST",
LCONTINUE, "CONTINUE", LCONTINUE, "CONTINUE",
LDEC, "DEC", LDEC, "DEC",
LDEFER, "DEFER",
LELSE, "ELSE", LELSE, "ELSE",
LEQ, "EQ", LEQ, "EQ",
LFALL, "FALL",
LFOR, "FOR",
LFUNC, "FUNC", LFUNC, "FUNC",
LGE, "GE", LGE, "GE",
LGO, "GO", LGO, "GO",
LGOTO, "GOTO", LGOTO, "GOTO",
LGT, "GT", LGT, "GT",
LIF, "IF", LIF, "IF",
LIMPORT, "IMPORT",
LINC, "INC", LINC, "INC",
LINTERFACE, "INTERFACE", LINTERFACE, "INTERFACE",
LLE, "LE", LLE, "LE",
...@@ -1262,7 +1325,7 @@ struct ...@@ -1262,7 +1325,7 @@ struct
LNAME, "NAME", LNAME, "NAME",
LNE, "NE", LNE, "NE",
LOROR, "OROR", LOROR, "OROR",
LPACK, "PACK", LPACKAGE, "PACKAGE",
LRANGE, "RANGE", LRANGE, "RANGE",
LRETURN, "RETURN", LRETURN, "RETURN",
LRSH, "RSH", LRSH, "RSH",
...@@ -1270,16 +1333,6 @@ struct ...@@ -1270,16 +1333,6 @@ struct
LSWITCH, "SWITCH", LSWITCH, "SWITCH",
LTYPE, "TYPE", LTYPE, "TYPE",
LVAR, "VAR", LVAR, "VAR",
LFOR, "FOR",
LNEW, "NEW",
LLEN, "LEN",
LFALL, "FALL",
LIOTA, "IOTA",
LPRINT, "PRINT",
LPACKAGE, "PACKAGE",
LIMPORT, "IMPORT",
LDEFER, "DEFER",
LPANIC, "PANIC",
}; };
char* char*
...@@ -1316,8 +1369,8 @@ mkpackage(char* pkg) ...@@ -1316,8 +1369,8 @@ mkpackage(char* pkg)
// declare this name as a package // declare this name as a package
s = lookup(package); s = lookup(package);
s->lexical = LPACK; s->def = nod(OPACK, N, N);
s->opack = s->name; s->def->sym = s;
if(outfile == nil) { if(outfile == nil) {
p = strrchr(infile, '/'); p = strrchr(infile, '/');
......
...@@ -58,7 +58,7 @@ dumpglobls(void) ...@@ -58,7 +58,7 @@ dumpglobls(void)
continue; continue;
dowidth(n->type); dowidth(n->type);
ggloblnod(s->oname, n->type->width); ggloblnod(s->def, n->type->width);
} }
} }
...@@ -393,6 +393,7 @@ dumpsignatures(void) ...@@ -393,6 +393,7 @@ dumpsignatures(void)
Dcl *d, *x; Dcl *d, *x;
Type *t, *progt, *methodt, *ifacet, *rcvrt; Type *t, *progt, *methodt, *ifacet, *rcvrt;
Sym *s; Sym *s;
Node *n;
// copy externdcl list to signatlist // copy externdcl list to signatlist
for(d=externdcl; d!=D; d=d->forw) { for(d=externdcl; d!=D; d=d->forw) {
...@@ -403,9 +404,10 @@ dumpsignatures(void) ...@@ -403,9 +404,10 @@ dumpsignatures(void)
if(t == T) if(t == T)
continue; continue;
s = signame(t); n = signame(t);
if(s == S) if(n == N || n->sym == S)
continue; continue;
s = n->sym;
x = mal(sizeof(*d)); x = mal(sizeof(*d));
x->op = OTYPE; x->op = OTYPE;
...@@ -425,10 +427,11 @@ dumpsignatures(void) ...@@ -425,10 +427,11 @@ dumpsignatures(void)
continue; continue;
t = d->dtype; t = d->dtype;
et = t->etype; et = t->etype;
s = signame(t); n = signame(t);
//print("signame %S for %T\n", s, t); //print("signame %S for %T\n", s, t);
if(s == S) if(n == N || n->sym == S)
continue; continue;
s = n->sym;
// only emit one // only emit one
if(s->siggen) if(s->siggen)
......
...@@ -156,9 +156,9 @@ lookup(char *p) ...@@ -156,9 +156,9 @@ lookup(char *p)
} }
s = mal(sizeof(*s)); s = mal(sizeof(*s));
s->lexical = LNAME;
s->name = mal(strlen(p)+1); s->name = mal(strlen(p)+1);
s->package = package; s->package = package;
s->lexical = LNAME;
strcpy(s->name, p); strcpy(s->name, p);
...@@ -186,7 +186,6 @@ pkglookup(char *p, char *k) ...@@ -186,7 +186,6 @@ pkglookup(char *p, char *k)
} }
s = mal(sizeof(*s)); s = mal(sizeof(*s));
s->lexical = LNAME;
s->name = mal(strlen(p)+1); s->name = mal(strlen(p)+1);
strcpy(s->name, p); strcpy(s->name, p);
...@@ -220,13 +219,11 @@ importdot(Sym *opkg) ...@@ -220,13 +219,11 @@ importdot(Sym *opkg)
if(strcmp(s->package, opkg->name) != 0) if(strcmp(s->package, opkg->name) != 0)
continue; continue;
s1 = lookup(s->name); s1 = lookup(s->name);
if(s1->oname != N || s1->otype != T) { if(s1->def != N) {
yyerror("redeclaration of %S during import", s1); yyerror("redeclaration of %S during import", s1);
continue; continue;
} }
s1->lexical = s->lexical; s1->def = s->def;
s1->oname = s->oname;
s1->otype = s->otype;
} }
} }
} }
...@@ -571,7 +568,7 @@ loop: ...@@ -571,7 +568,7 @@ loop:
break; break;
case OTYPE: case OTYPE:
print("%O-%E %lT\n", n->op, n->etype, n); print("%O %T\n", n->op, n->type);
break; break;
case OIF: case OIF:
...@@ -696,7 +693,6 @@ opnames[] = ...@@ -696,7 +693,6 @@ opnames[] =
[OGOTO] = "GOTO", [OGOTO] = "GOTO",
[OGT] = "GT", [OGT] = "GT",
[OIF] = "IF", [OIF] = "IF",
[OIMPORT] = "IMPORT",
[OINC] = "INC", [OINC] = "INC",
[OINDEX] = "INDEX", [OINDEX] = "INDEX",
[OINDREG] = "INDREG", [OINDREG] = "INDREG",
...@@ -722,6 +718,7 @@ opnames[] = ...@@ -722,6 +718,7 @@ opnames[] =
[OOR] = "OR", [OOR] = "OR",
[OPANICN] = "PANICN", [OPANICN] = "PANICN",
[OPANIC] = "PANIC", [OPANIC] = "PANIC",
[OPACK] = "PACK",
[OPARAM] = "PARAM", [OPARAM] = "PARAM",
[OPLUS] = "PLUS", [OPLUS] = "PLUS",
[OPRINTN] = "PRINTN", [OPRINTN] = "PRINTN",
...@@ -741,7 +738,6 @@ opnames[] = ...@@ -741,7 +738,6 @@ opnames[] =
[OTYPEOF] = "TYPEOF", [OTYPEOF] = "TYPEOF",
[OTYPESW] = "TYPESW", [OTYPESW] = "TYPESW",
[OTYPE] = "TYPE", [OTYPE] = "TYPE",
[OVAR] = "VAR",
[OXCASE] = "XCASE", [OXCASE] = "XCASE",
[OXFALL] = "XFALL", [OXFALL] = "XFALL",
[OXOR] = "XOR", [OXOR] = "XOR",
...@@ -1044,8 +1040,11 @@ Tpretty(Fmt *fp, Type *t) ...@@ -1044,8 +1040,11 @@ Tpretty(Fmt *fp, Type *t)
fmtprint(fp, "%hS", s); fmtprint(fp, "%hS", s);
else else
fmtprint(fp, "%lS", s); fmtprint(fp, "%lS", s);
if(strcmp(s->package, package) == 0) if(strcmp(s->package, package) != 0)
if((s->otype != t || !s->export) && !s->imported) { return 0;
if(s->imported)
return 0;
if(s->def == N || s->def->op != OTYPE || s->def->type != t || !s->export) {
fmtprint(fp, "·%s", filename); fmtprint(fp, "·%s", filename);
if(t->vargen) if(t->vargen)
fmtprint(fp, "·%d", t->vargen); fmtprint(fp, "·%d", t->vargen);
...@@ -1339,7 +1338,7 @@ Nconv(Fmt *fp) ...@@ -1339,7 +1338,7 @@ Nconv(Fmt *fp)
break; break;
case OTYPE: case OTYPE:
snprint(buf, sizeof(buf), "%O-%E%J", n->op, n->etype, n); snprint(buf, sizeof(buf), "%O %T", n->op, n->type);
break; break;
} }
if(n->sym != S) { if(n->sym != S) {
...@@ -1581,7 +1580,7 @@ iscomposite(Type *t) ...@@ -1581,7 +1580,7 @@ iscomposite(Type *t)
return 0; return 0;
} }
Sym* Node*
signame(Type *t) signame(Type *t)
{ {
Sym *ss; Sym *ss;
...@@ -1611,10 +1610,10 @@ signame(Type *t) ...@@ -1611,10 +1610,10 @@ signame(Type *t)
strcpy(buf, "dotdotdot"); strcpy(buf, "dotdotdot");
ss = pkglookup(buf, e); ss = pkglookup(buf, e);
if(ss->oname == N) { if(ss->def == N) {
ss->oname = newname(ss); ss->def = newname(ss);
ss->oname->type = types[TUINT8]; ss->def->type = types[TUINT8];
ss->oname->class = PEXTERN; ss->def->class = PEXTERN;
} }
//print("siggen %T %d\n", t, t->siggen); //print("siggen %T %d\n", t, t->siggen);
...@@ -1633,10 +1632,10 @@ signame(Type *t) ...@@ -1633,10 +1632,10 @@ signame(Type *t)
} }
out: out:
return ss; return ss->def;
bad: bad:
return S; return N;
} }
int int
...@@ -1942,15 +1941,15 @@ syslook(char *name, int copy) ...@@ -1942,15 +1941,15 @@ syslook(char *name, int copy)
Node *n; Node *n;
s = pkglookup(name, "sys"); s = pkglookup(name, "sys");
if(s == S || s->oname == N) if(s == S || s->def == N)
fatal("looksys: cant find sys.%s", name); fatal("looksys: cant find sys.%s", name);
if(!copy) if(!copy)
return s->oname; return s->def;
n = nod(0, N, N); n = nod(0, N, N);
*n = *s->oname; *n = *s->def;
n->type = deep(s->oname->type); n->type = deep(s->def->type);
return n; return n;
} }
...@@ -2073,7 +2072,7 @@ frame(int context) ...@@ -2073,7 +2072,7 @@ frame(int context)
case OTYPE: case OTYPE:
if(flag) if(flag)
print("--- %s frame ---\n", p); print("--- %s frame ---\n", p);
print("%O %lT\n", d->op, d->dnode); print("%O %T\n", d->op, d->dnode);
flag = 0; flag = 0;
break; break;
} }
......
...@@ -123,8 +123,16 @@ loop: ...@@ -123,8 +123,16 @@ loop:
return; return;
more = N; more = N;
if(n->op != ONAME) switch(n->op) {
case ONAME: // one only; lineno isn't right for right now
case OPACK:
case OTYPE:
case OLITERAL:
break;
default:
lineno = n->lineno; lineno = n->lineno;
}
switch(n->op) { switch(n->op) {
case OLIST: case OLIST:
...@@ -248,6 +256,7 @@ loop: ...@@ -248,6 +256,7 @@ loop:
switch(n->op) { switch(n->op) {
default: default:
dump("walk", n);
fatal("walktype: switch 1 unknown op %N", n); fatal("walktype: switch 1 unknown op %N", n);
goto ret; goto ret;
...@@ -313,7 +322,10 @@ loop: ...@@ -313,7 +322,10 @@ loop:
if(n->type == T) { if(n->type == T) {
s = n->sym; s = n->sym;
if(s->undef == 0) { if(s->undef == 0) {
yyerror("walktype: %S undeclared", s); if(n->etype != 0)
yyerror("walktype: %S must be called", s);
else
yyerror("walktype: %S undeclared", s);
s->undef = 1; s->undef = 1;
} }
} }
...@@ -1030,20 +1042,28 @@ loop: ...@@ -1030,20 +1042,28 @@ loop:
case OMAKE: case OMAKE:
if(top != Erv) if(top != Erv)
goto nottop; goto nottop;
l = n->left;
if(l == N) {
yyerror("missing argument to make");
goto ret;
}
indir(n, makecompat(n)); indir(n, makecompat(n));
goto ret; goto ret;
case ONEW: case ONEW:
if(top != Erv) if(top != Erv)
goto nottop; goto nottop;
if(n->left != N) { l = n->left;
yyerror("cannot new(%T, expr)", t); if(l == N)
goto ret; yyerror("missing argument to new");
} else if(n->right != N)
t = n->type; yyerror("too many arguments to new");
if(t == T) else if(l->op != OTYPE)
goto ret; yyerror("argument to new must be type");
indir(n, callnew(t)); else if((t = l->type) == T)
;
else
indir(n, callnew(t));
goto ret; goto ret;
} }
...@@ -1927,12 +1947,12 @@ sigtype(Type *st) ...@@ -1927,12 +1947,12 @@ sigtype(Type *st)
x = mal(sizeof(*x)); x = mal(sizeof(*x));
x->op = OTYPE; x->op = OTYPE;
x->dsym = s; x->dsym = s;
x->dtype = s->otype; x->dtype = t;
x->forw = signatlist; x->forw = signatlist;
x->block = block; x->block = block;
signatlist = x; signatlist = x;
return s->otype; return t;
} }
/* /*
...@@ -2350,8 +2370,22 @@ Node* ...@@ -2350,8 +2370,22 @@ Node*
makecompat(Node *n) makecompat(Node *n)
{ {
Type *t; Type *t;
Node *l, *r;
t = n->type; l = n->left;
r = N;
if(l->op == OLIST) {
r = l->right;
l = l->left;
}
if(l->op != OTYPE) {
yyerror("cannot make(expr)");
return n;
}
t = l->type;
n->type = t;
n->left = r;
n->right = N;
if(t != T) if(t != T)
switch(t->etype) { switch(t->etype) {
...@@ -3045,9 +3079,8 @@ arrayop(Node *n, int top) ...@@ -3045,9 +3079,8 @@ arrayop(Node *n, int top)
a = listfirst(&save, &n->left); // nel a = listfirst(&save, &n->left); // nel
if(a == N) { if(a == N) {
if(t->bound < 0) yyerror("new slice must have size");
yyerror("new open array must have size"); a = nodintconst(1);
a = nodintconst(t->bound);
} }
a = nod(OCONV, a, N); a = nod(OCONV, a, N);
a->type = types[TINT]; a->type = types[TINT];
...@@ -3193,7 +3226,6 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3193,7 +3226,6 @@ ifacecvt(Type *tl, Node *n, int et)
{ {
Type *tr; Type *tr;
Node *r, *a, *on; Node *r, *a, *on;
Sym *s;
tr = n->type; tr = n->type;
...@@ -3207,19 +3239,10 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3207,19 +3239,10 @@ ifacecvt(Type *tl, Node *n, int et)
a = n; // elem a = n; // elem
r = a; r = a;
s = signame(tr); // sigt a = nod(OADDR, signame(tr), N); // sigt
if(s == S)
fatal("ifacecvt: signame-1 T2I: %lT", tr);
a = s->oname;
a = nod(OADDR, a, N);
r = list(a, r); r = list(a, r);
s = signame(tl); // sigi a = nod(OADDR, signame(tl), N); // sigi
if(s == S) {
fatal("ifacecvt: signame-2 T2I: %lT", tl);
}
a = s->oname;
a = nod(OADDR, a, N);
r = list(a, r); r = list(a, r);
on = syslook("ifaceT2I", 1); on = syslook("ifaceT2I", 1);
...@@ -3240,11 +3263,7 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3240,11 +3263,7 @@ ifacecvt(Type *tl, Node *n, int et)
a = n; // interface a = n; // interface
r = a; r = a;
s = signame(tl); // sigi or sigt a = nod(OADDR, signame(tl), N); // sigi or sigt
if(s == S)
fatal("ifacecvt: signame %d", et);
a = s->oname;
a = nod(OADDR, a, N);
r = list(a, r); r = list(a, r);
on = syslook(ifacename[et], 1); on = syslook(ifacename[et], 1);
...@@ -3268,11 +3287,7 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3268,11 +3287,7 @@ ifacecvt(Type *tl, Node *n, int et)
a = n; // elem a = n; // elem
r = a; r = a;
s = signame(tr); // sigt a = nod(OADDR, signame(tr), N); // sigt
if(s == S)
fatal("ifacecvt: signame-1 T2E: %lT", tr);
a = s->oname;
a = nod(OADDR, a, N);
r = list(a, r); r = list(a, r);
on = syslook("ifaceT2E", 1); on = syslook("ifaceT2E", 1);
...@@ -3394,7 +3409,9 @@ colasname(Node *n) ...@@ -3394,7 +3409,9 @@ colasname(Node *n)
switch(n->op) { switch(n->op) {
case ONAME: case ONAME:
case ONONAME: case ONONAME:
case OPACK:
break; break;
case OTYPE:
case OLITERAL: case OLITERAL:
if(n->sym != S) if(n->sym != S)
break; break;
...@@ -4248,9 +4265,7 @@ arraylit(Node *n, Node *var) ...@@ -4248,9 +4265,7 @@ arraylit(Node *n, Node *var)
if(b < 0) { if(b < 0) {
// slice // slice
a = nod(OMAKE, N, N); a = nod(OMAKE, nod(OLIST, typenod(t), nodintconst(ninit)), N);
a->type = t;
a->left = nodintconst(ninit);
a = nod(OAS, var, a); a = nod(OAS, var, a);
addtop = list(addtop, a); addtop = list(addtop, a);
} else { } else {
...@@ -4377,8 +4392,7 @@ maplit(Node *n, Node *var) ...@@ -4377,8 +4392,7 @@ maplit(Node *n, Node *var)
tempname(var, t); tempname(var, t);
} }
a = nod(OMAKE, N, N); a = nod(OMAKE, typenod(t), N);
a->type = t;
a = nod(OAS, var, a); a = nod(OAS, var, a);
addtop = list(addtop, a); addtop = list(addtop, a);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment