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
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index 739851a..bf9fb16 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -208,7 +208,7 @@
}
void
-typeinit(int lex)
+typeinit(void)
{
int i, etype, sameas;
Type *t;
@@ -306,7 +306,7 @@
types[TFUNC] = functype(N, N, N);
/* types used in front end */
- types[TNIL] = typ(TNIL);
+ // types[TNIL] got set early in lexinit
types[TIDEAL] = typ(TIDEAL);
/* simple aliases */
@@ -317,7 +317,6 @@
/* pick up the backend typedefs */
for(i=0; typedefs[i].name; i++) {
s = lookup(typedefs[i].name);
- s->lexical = lex;
etype = typedefs[i].etype;
if(etype < 0 || etype >= nelem(types))
@@ -340,7 +339,7 @@
dowidth(t);
types[etype] = t;
- s->otype = t;
+ s->def = typenod(t);
}
Array_array = rnd(0, widthptr);
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index c5359dc..122df1d 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -67,11 +67,11 @@
// if n has been forward declared,
// use the Type* created then
s = n->sym;
- if(s->block == block && s->otype != T) {
- switch(s->otype->etype) {
+ if(s->block == block && s->def != N && s->def->op == OTYPE) {
+ switch(s->def->type->etype) {
case TFORWSTRUCT:
case TFORWINTER:
- n = s->otype;
+ n = s->def->type;
goto found;
}
}
@@ -95,7 +95,7 @@
int local;
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);
switch(n->etype) {
@@ -132,7 +132,7 @@
n->printed = 0;
n->method = nil;
n->vargen = 0;
-
+ n->nod = N;
// catch declaration of incomplete type
switch(n->etype) {
case TFORWSTRUCT:
@@ -306,7 +306,7 @@
goto bad;
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;
}
@@ -383,7 +383,9 @@
Sym *s;
s = n->nname->sym;
- on = s->oname;
+ on = s->def;
+ if(on != N && (on->op != ONAME || on->builtin))
+ on = N;
// check for same types
if(on != N) {
@@ -748,7 +750,7 @@
f->embedded = n->embedded;
f->sym = f->nname->sym;
if(pkgimportname != S && !exportname(f->sym->name))
- f->sym = pkglookup(f->sym->name, pkgcontext);
+ f->sym = pkglookup(f->sym->name, structpkg);
}
*t = f;
@@ -793,11 +795,8 @@
dcopy(Sym *a, Sym *b)
{
a->name = b->name;
- a->oname = b->oname;
- a->otype = b->otype;
- a->oconst = b->oconst;
+ a->def = b->def;
a->package = b->package;
- a->lexical = b->lexical;
a->undef = b->undef;
a->vargen = b->vargen;
a->block = b->block;
@@ -954,11 +953,8 @@
redeclare("variable", s);
s->vargen = gen;
- s->oname = n;
+ s->def = n;
s->offset = 0;
- s->oconst = nil;
- s->otype = nil;
- s->lexical = LNAME;
n->funcdepth = funcdepth;
n->type = t;
@@ -1004,10 +1000,7 @@
}
redeclare("type", s);
- s->otype = n;
- s->oconst = nil;
- s->oname = nil;
- s->lexical = LATYPE;
+ s->def = typenod(n);
d = dcl();
d->dsym = s;
@@ -1041,7 +1034,7 @@
Sym *s;
Dcl *r, *d;
- if(n->op != ONAME)
+ if(n->op != ONAME && n->op != ONONAME)
fatal("addconst: not a name");
if(e->op != OLITERAL) {
@@ -1059,10 +1052,8 @@
}
redeclare("constant", s);
- s->oconst = e;
- s->otype = nil;
- s->oname = nil;
- s->lexical = LNAME;
+ s->def = e;
+ e->sym = s;
d = dcl();
d->dsym = s;
@@ -1073,7 +1064,7 @@
r->back = d;
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*
@@ -1130,6 +1121,18 @@
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
* that has already been pushed on the
@@ -1142,15 +1145,7 @@
Node *n;
Node *c;
- if(s->oconst) {
- n = nod(OLITERAL, N, N);
- n->sym = s;
- n->val = s->oconst->val;
- n->type = s->oconst->type;
- return n;
- }
-
- n = s->oname;
+ n = s->def;
if(n == N) {
n = nod(ONONAME, N, N);
n->sym = s;
@@ -1158,7 +1153,15 @@
n->addable = 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
// in outer func.
if(n->closure == N || n->closure->funcdepth != funcdepth) {
@@ -1200,9 +1203,19 @@
{
Type *t;
- t = s->otype;
- if(t == T)
- fatal("%S not a type", s); // cant happen
+ if(s->def == N || s->def->op != OTYPE) {
+ yyerror("%S is not a type", s);
+ 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;
}
@@ -1219,9 +1232,9 @@
for(l=&na; (n=*l)->op == OLIST; l=&n->left)
n->right = nametoanondcl(n->right);
- t = n->sym->otype;
- if(t == T) {
- yyerror("%s is not a type", n->sym->name);
+ n = n->sym->def;
+ if(n == N || n->op != OTYPE || (t = n->type) == T) {
+ yyerror("%S is not a type", n->sym);
t = typ(TINT32);
}
n = nod(ODCLFIELD, N, N);
@@ -1261,33 +1274,95 @@
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
*/
-void
+Node*
checkarglist(Node *n)
{
- if(n->op != OLIST)
- return;
- if(n->left->op != ODCLFIELD)
- fatal("checkarglist");
- if(n->left->left != N) {
- for(n=n->right; n->op == OLIST; n=n->right)
- if(n->left->left == N)
- goto mixed;
- if(n->left == N)
- goto mixed;
- } else {
- for(n=n->right; n->op == OLIST; n=n->right)
- if(n->left->left != N)
- goto mixed;
- if(n->left != N)
- goto mixed;
- }
- return;
+ Node *r;
+ Node **l;
-mixed:
- yyerror("cannot mix anonymous and named function arguments");
+ // check for all anonymous
+ for(r=n; r->op==OLIST; r=r->right)
+ if(r->left->op == OKEY)
+ goto named;
+ if(r->op == OKEY)
+ goto named;
+
+ // all anonymous - add names
+ for(l=&n; (r=*l)->op==OLIST; l=&r->right)
+ r->left = xanondcl(r->left, 0);
+ *l = xanondcl(r, 1);
+ return n;
+
+
+named:
+ // 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 @@
* func Init·<file>() (2)
* if initdone·<file> { (3)
* if initdone·<file> == 2 (4)
- * return
+ * return
* throw(); (5)
* }
* initdone.<file>++; (6)
@@ -1325,7 +1400,7 @@
// is there an explicit init function
snprint(namebuf, sizeof(namebuf), "init·%s", filename);
s = lookup(namebuf);
- if(s->oname != N)
+ if(s->def != N)
return 1;
// are there any imported init functions
@@ -1333,7 +1408,7 @@
for(s = hash[h]; s != S; s = s->link) {
if(s->name[0] != 'I' || strncmp(s->name, "Init·", 6) != 0)
continue;
- if(s->oname == N)
+ if(s->def == N)
continue;
return 1;
}
@@ -1409,13 +1484,13 @@
for(s = hash[h]; s != S; s = s->link) {
if(s->name[0] != 'I' || strncmp(s->name, "Init·", 6) != 0)
continue;
- if(s->oname == N)
+ if(s->def == N)
continue;
if(s == initsym)
continue;
// 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);
}
@@ -1426,8 +1501,8 @@
// could check that it is fn of no args/returns
snprint(namebuf, sizeof(namebuf), "init·%s", filename);
s = lookup(namebuf);
- if(s->oname != N) {
- a = nod(OCALL, s->oname, N);
+ if(s->def != N) {
+ a = nod(OCALL, s->def, N);
r = list(r, a);
}
diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c
index e9bb438..8653cb5 100644
--- a/src/cmd/gc/export.c
+++ b/src/cmd/gc/export.c
@@ -100,7 +100,7 @@
Node *n;
Type *t;
- n = s->oconst;
+ n = s->def;
if(n == N || n->op != OLITERAL)
fatal("dumpexportconst: oconst nil: %S", s);
@@ -141,7 +141,7 @@
Node *n;
Type *t;
- n = s->oname;
+ n = s->def;
if(n == N || n->type == T) {
yyerror("variable exported but not defined: %S", s);
return;
@@ -161,49 +161,54 @@
void
dumpexporttype(Sym *s)
{
- dumpprereq(s->otype);
+ Type *t;
+
+ t = s->def->type;
+ dumpprereq(t);
Bprint(bout, "\t");
- switch (s->otype->etype) {
+ switch (t->etype) {
case TFORW:
case TFORWSTRUCT:
case TFORWINTER:
- yyerror("export of incomplete type %T", s->otype);
+ yyerror("export of incomplete type %T", t);
return;
}
- Bprint(bout, "type %#T %l#T\n", s->otype, s->otype);
+ Bprint(bout, "type %#T %l#T\n", t, t);
}
void
dumpsym(Sym *s)
{
- Type *f;
+ Type *f, *t;
if(s->exported != 0)
return;
s->exported = 1;
- switch(s->lexical) {
- default:
+ if(s->def == N) {
yyerror("unknown export symbol: %S", s);
+ return;
+ }
+ switch(s->def->op) {
+ default:
+ yyerror("unexpected export symbol: %O %S", s->def->op, s);
break;
- case LPACK:
- yyerror("package export symbol: %S", s);
+ case OLITERAL:
+ dumpexportconst(s);
break;
- case LATYPE:
+ case OTYPE:
+ t = s->def->type;
// 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);
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",
f->type->type->type, f->sym, f->type);
break;
- case LNAME:
- if(s->oconst)
- dumpexportconst(s);
- else
- dumpexportvar(s);
+ case ONAME:
+ dumpexportvar(s);
break;
}
}
@@ -216,7 +221,7 @@
return;
// 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;
Bprint(bout, "type %#T %l#T\n", t, t);
@@ -257,42 +262,21 @@
*/
/*
- * 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
*/
Sym*
-importsym(Node *ss, int lexical)
+importsym(Sym *s, int op)
{
- Sym *s;
-
- if(ss->op != OIMPORT)
- fatal("importsym: oops1 %N", ss);
-
- s = pkgsym(ss->sym->name, ss->psym->name, lexical);
- /* TODO botch - need some diagnostic checking for the following assignment */
- if(exportname(ss->sym->name))
+ if(s->def != N && s->def->op != op) {
+ // Clumsy hack for
+ // package parser
+ // import "go/parser" // defines type parser
+ if(s == lookup(package))
+ s->def = N;
+ else
+ yyerror("redeclaration of %lS during import", s, s->def->op, op);
+ }
+ if(exportname(s->name))
s->export = 1;
else
s->export = 2; // package scope
@@ -304,47 +288,36 @@
* return the type pkg.name, forward declaring if needed
*/
Type*
-pkgtype(char *name, char *pkg)
+pkgtype(Sym *s)
{
- Sym *s;
Type *t;
- // botch
- // s = pkgsym(name, pkg, LATYPE);
- Node *n;
- n = nod(OIMPORT, N, N);
- n->sym = lookup(name);
- n->psym = lookup(pkg);
- s = importsym(n, LATYPE);
-
- if(s->otype == T) {
+ importsym(s, OTYPE);
+ if(s->def == N || s->def->op != OTYPE) {
t = typ(TFORW);
t->sym = s;
- s->otype = t;
+ s->def = typenod(t);
}
- return s->otype;
+ return s->def->type;
}
static int
-mypackage(Node *ss)
+mypackage(Sym *s)
{
// we import all definitions for sys.
// lowercase ones can only be used by the compiler.
- return strcmp(ss->psym->name, package) == 0
- || strcmp(ss->psym->name, "sys") == 0;
+ return strcmp(s->package, package) == 0
+ || strcmp(s->package, "sys") == 0;
}
void
-importconst(Node *ss, Type *t, Node *n)
+importconst(Sym *s, Type *t, Node *n)
{
- Sym *s;
-
- if(!exportname(ss->sym->name) && !mypackage(ss))
+ if(!exportname(s->name) && !mypackage(s))
return;
-
+ importsym(s, OLITERAL);
convlit(n, t);
- s = importsym(ss, LNAME);
- if(s->oconst != N) {
+ if(s->def != N) {
// TODO: check if already the same.
return;
}
@@ -356,19 +329,17 @@
}
void
-importvar(Node *ss, Type *t, int ctxt)
+importvar(Sym *s, Type *t, int ctxt)
{
- Sym *s;
-
- if(!exportname(ss->sym->name) && !mypackage(ss))
+ if(!exportname(s->name) && !mypackage(s))
return;
- s = importsym(ss, LNAME);
- if(s->oname != N) {
- if(cvttype(t, s->oname->type))
+ importsym(s, ONAME);
+ if(s->def != N && s->def->op == ONAME) {
+ if(cvttype(t, s->def->type))
return;
warn("redeclare import var %S from %T to %T",
- s, s->oname->type, t);
+ s, s->def->type, t);
}
checkwidth(t);
addvar(newname(s), t, ctxt);
@@ -378,25 +349,34 @@
}
void
-importtype(Node *ss, Type *t)
+importtype(Sym *s, Type *t)
{
- Sym *s;
+ Node *n;
+ Type *tt;
- s = importsym(ss, LATYPE);
- if(s->otype != T) {
- if(cvttype(t, s->otype))
+ importsym(s, OTYPE);
+ n = s->def;
+ if(n != N && n->op == OTYPE) {
+ if(cvttype(t, n->type))
return;
- if(s->otype->etype != TFORW) {
+ if(n->type->etype != TFORW) {
warn("redeclare import type %S from %lT to %lT",
- s, s->otype, t);
- s->otype = typ(0);
+ s, n->type, t);
+ n = s->def = typenod(typ(0));
}
}
- if(s->otype == T)
- s->otype = typ(0);
- *s->otype = *t;
- s->otype->sym = s;
- checkwidth(s->otype);
+ if(n == N || n->op != OTYPE) {
+ tt = typ(0);
+ tt->sym = s;
+ n = typenod(tt);
+ 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'])
print("import type %S %lT\n", s, t);
@@ -425,7 +405,9 @@
for(h=0; h<NHASH; h++)
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)
continue;
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index e35721e..c8d6107 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -145,6 +145,8 @@
uchar copyany;
uchar local; // created in this file
+ Node* nod; // canonical OTYPE node
+
// TFUNCT
uchar thistuple;
uchar outtuple;
@@ -187,6 +189,7 @@
uchar diag; // already printed error about this
uchar noescape; // ONAME never move to heap
uchar funcdepth;
+ uchar builtin; // built-in name, like len or close
// most nodes
Node* left;
@@ -247,10 +250,7 @@
char* package; // package name
char* name; // variable name
- Node* oname; // ONAME node if a var
- Type* otype; // TYPE node if a type
- Node* oconst; // OLITERAL node if a const
- char* opack; // package reference if lexical == LPACK
+ Node* def; // definition: ONAME OTYPE OPACK or OLITERAL
vlong offset; // stack location if automatic
int32 lexical;
int32 vargen; // unique variable number
@@ -298,9 +298,8 @@
{
OXXX,
- OTYPE, OVAR, OIMPORT,
-
- ONAME, ONONAME, ODCL,
+ ONAME, ONONAME, OTYPE, OPACK, OLITERAL,
+ ODCL,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
ODCLFUNC, ODCLFIELD, ODCLARG,
OLIST, OCMP, OPTR, OARRAY, ORANGE,
@@ -325,7 +324,7 @@
OCALL, OCALLMETH, OCALLINTER,
OINDEX, OSLICE,
ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
- OLITERAL, OREGISTER, OINDREG,
+ OREGISTER, OINDREG,
OKEY, OPARAM,
OCOMPOS, OCOMPSLICE, OCOMPMAP,
OCONV,
@@ -573,6 +572,7 @@
EXTERN int inimportsys;
EXTERN int initflag; // compiling the init fn
EXTERN int statuniqgen; // name generator for static temps
+EXTERN int loophack;
EXTERN uint32 iota;
EXTERN Node* lastconst;
@@ -595,8 +595,7 @@
EXTERN Node* addtop;
EXTERN Node* typeswvar;
-EXTERN char* context;
-EXTERN char* pkgcontext;
+EXTERN char* structpkg;
extern int thechar;
extern char* thestring;
EXTERN char* hunk;
@@ -623,7 +622,7 @@
void cannedimports(char*, char*);
void unimportfile();
int32 yylex(void);
-void typeinit(int lex);
+void typeinit(void);
void lexinit(void);
char* lexname(int);
int32 getr(void);
@@ -731,7 +730,7 @@
int isddd(Type*);
Type* maptype(Type*, Type*);
Type* methtype(Type*);
-Sym* signame(Type*);
+Node* signame(Type*);
int eqtype(Type*, Type*);
int cvttype(Type*, Type*);
int eqtypenoname(Type*, Type*);
@@ -821,6 +820,7 @@
void funchdr(Node*);
void funcargs(Type*);
void funcbody(Node*);
+Node* typenod(Type*);
Type* dostruct(Node*, int);
Type** stotype(Node*, int, Type**);
Type* sortinter(Type*);
@@ -844,7 +844,7 @@
Node* nametoanondcl(Node*);
Node* nametodcl(Node*, Type*);
Node* anondcl(Type*);
-void checkarglist(Node*);
+Node* checkarglist(Node*);
void checkwidth(Type*);
void defercheckwidth(void);
void resumecheckwidth(void);
@@ -887,12 +887,12 @@
void doimport7(Node*, Node*);
void doimport8(Node*, Val*, 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 importtype(Node *ss, Type *t);
-void importvar(Node *ss, Type *t, int ctxt);
+void importtype(Sym *s, Type *t);
+void importvar(Sym *s, Type *t, int ctxt);
void checkimports(void);
-Type* pkgtype(char*, char*);
+Type* pkgtype(Sym*);
/*
* walk.c
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index cc9caf9..f774df2 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -2,6 +2,30 @@
// Use of this source code is governed by a BSD-style
// 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"
%}
@@ -12,106 +36,90 @@
struct Val val;
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 /'
+
+%token <val> LLITERAL
+%token <lint> LASOP
+%token <sym> LBREAK LCASE LCHAN LCOLAS LCONST LCONTINUE LDDD
+%token <sym> LDEFAULT LDEFER LELSE LFALL LFOR LFUNC LGO LGOTO
+%token <sym> LIF LIMPORT LINTERFACE LMAKE LMAP LNAME LNEW
+%token <sym> LPACKAGE LRANGE LRETURN LSELECT LSTRUCT LSWITCH
+%token <sym> LTYPE LVAR
+
+%token LANDAND LANDNOT LBODY LCOMM LDEC LEQ LGE LGT
+%token LIGNORE LINC LLE LLSH LLT LNE LOROR LRSH
+
+%type <lint> lbrace
+%type <sym> sym packname
+%type <val> oliteral
+
+%type <node> Acommon_dcl Aelse_stmt Afnres Astmt Astmt_list_r
+%type <node> Avardcl Bcommon_dcl Belse_stmt Bfnres Bstmt
+%type <node> Bstmt_list_r Bvardcl arg_type arg_type_list
+%type <node> arg_type_list_r braced_keyexpr_list case caseblock
+%type <node> caseblock_list_r common_dcl complex_stmt
+%type <node> compound_stmt dotname embed expr expr_list
+%type <node> expr_list_r expr_or_type expr_or_type_list
+%type <node> expr_or_type_list_r fnbody fndcl fnliteral fnres
+%type <node> for_body for_header for_stmt if_header if_stmt
+%type <node> interfacedcl interfacedcl1 interfacedcl_list_r
+%type <node> keyval keyval_list_r labelname loop_body name
+%type <node> name_list name_list_r name_or_type new_field
+%type <node> new_name oarg_type_list ocaseblock_list oexpr
+%type <node> oexpr_list oexpr_or_type_list onew_name
+%type <node> osimple_stmt ostmt_list oxdcl_list pexpr
+%type <node> pseudocall range_stmt select_stmt semi_stmt
+%type <node> simple_stmt stmt_list_r structdcl structdcl_list_r
+%type <node> switch_body switch_stmt uexpr vardcl vardcl_list_r
+%type <node> xdcl xdcl_list_r xfndcl
+
+%type <type> Achantype Afntype Anon_chan_type Anon_fn_type
+%type <type> Aothertype Atype Bchantype Bfntype Bnon_chan_type
+%type <type> Bnon_fn_type Bothertype Btype convtype dotdotdot
+%type <type> fnlitdcl fntype indcl interfacetype nametype
+%type <type> new_type structtype type typedclname
+
+%type <sym> hidden_importsym hidden_pkg_importsym
+
+%type <node> hidden_constant hidden_dcl hidden_funarg_list
+%type <node> hidden_funarg_list_r hidden_funres
+%type <node> hidden_interfacedcl hidden_interfacedcl_list
+%type <node> hidden_interfacedcl_list_r hidden_structdcl
+%type <node> hidden_structdcl_list hidden_structdcl_list_r
+%type <node> ohidden_funarg_list ohidden_funres
+%type <node> ohidden_interfacedcl_list ohidden_structdcl_list
+
+%type <type> hidden_type hidden_type1 hidden_type2
+
+%left LOROR
+%left LANDAND
+%left LCOMM
+%left LEQ LNE LLE LGE LLT LGT
+%left '+' '-' '|' '^'
+%left '*' '/' '%' '&' LLSH LRSH LANDNOT
/*
- * 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.
+ * 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 NotPackage
+%left LPACKAGE
-%type <sym> sym sym1 sym2 sym3 keyword lname latype lpackatype
-%type <node> xdcl xdcl_list_r oxdcl_list
-%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> Aelse_stmt Belse_stmt
-%type <node> complex_stmt compound_stmt switch_body ocaseblock_list ostmt_list
-%type <node> caseblock_list_r stmt_list_r Astmt_list_r Bstmt_list_r
-%type <node> Astmt Bstmt
-%type <node> for_stmt for_body for_header
-%type <node> if_stmt if_header select_stmt switch_stmt condition case caseblock
-%type <node> simple_stmt osimple_stmt range_stmt semi_stmt
-%type <node> expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r
-%type <node> exprsym3_list_r exprsym3 pseudocall
-%type <node> name labelname onew_name new_name new_name_list_r new_field
-%type <node> vardcl_list_r vardcl Avardcl Bvardcl
-%type <node> interfacedcl_list_r interfacedcl interfacedcl1
-%type <node> structdcl_list_r structdcl embed
-%type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl fnbody
-%type <node> braced_keyexpr_list keyval_list_r keyval
+%left NotParen
+%left '('
-%type <type> typedclname new_type
-%type <type> type Atype Btype
-%type <type> othertype Aothertype Bothertype
-%type <type> chantype Achantype Bchantype
-%type <type> fntype Afntype Bfntype
-%type <type> nametype structtype interfacetype convtype
-%type <type> non_name_type Anon_fn_type Bnon_fn_type
-%type <type> Anon_chan_type Bnon_chan_type
-%type <type> indcl fnlitdcl dotdotdot
-%type <val> oliteral
+%left ')'
+%left PreferToRightParen
-%type <node> hidden_constant
-%type <node> hidden_dcl hidden_structdcl
-%type <type> hidden_type hidden_type1 hidden_type2
-%type <node> hidden_structdcl_list ohidden_structdcl_list hidden_structdcl_list_r
-%type <node> hidden_interfacedcl_list ohidden_interfacedcl_list hidden_interfacedcl_list_r
-%type <node> hidden_interfacedcl
-%type <node> hidden_funarg_list ohidden_funarg_list hidden_funarg_list_r
-%type <node> hidden_funres ohidden_funres hidden_importsym hidden_pkg_importsym
+%left NotDot
+%left '.'
-%left LOROR
-%left LANDAND
-%left LCOMM
-%left LEQ LNE LLE LGE LLT LGT
-%left '+' '-' '|' '^'
-%left '*' '/' '%' '&' LLSH LRSH LANDNOT
-
-/*
- * resolve { vs condition in favor of condition
- */
-%left '{'
-%left Condition
-
-/*
- * resolve LPACKAGE vs not in favor of LPACKAGE
- */
-%left NotPackage
-%left LPACKAGE
-
-/*
- * resolve '.' vs not in favor of '.'
- */
-%left NotDot
-%left '.'
-
-/*
- * resolve '(' vs not in favor of '('
- */
-%left NotParen
-%left '('
+%left NotBrace
+%left '{'
%%
file:
@@ -230,17 +238,17 @@
if(my == import && strcmp(import->name, package) == 0)
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
// package net
// import "net"
// convention; if we get rid of it, the check can go away
// 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);
}
- my->lexical = LPACK;
- my->opack = import->name;
+ my->def = nod(OPACK, N, N);
+ my->def->sym = import;
}
hidden_import_list:
@@ -343,9 +351,8 @@
| Bvardcl
Avardcl:
- new_name_list_r Atype
+ name_list Atype
{
- $$ = rev($1);
dodclvar($$, $2);
if(funcdepth == 0) {
@@ -357,9 +364,8 @@
}
Bvardcl:
- new_name_list_r Btype
+ name_list Btype
{
- $$ = rev($1);
dodclvar($$, $2);
if(funcdepth == 0) {
@@ -369,7 +375,7 @@
addtotop($$);
}
}
-| new_name_list_r type '=' expr_list
+| name_list type '=' expr_list
{
if(addtop != N)
fatal("new_name_list_r type '=' expr_list");
@@ -377,7 +383,7 @@
$$ = variter($1, $2, $4);
addtotop($$);
}
-| new_name_list_r '=' expr_list
+| name_list '=' expr_list
{
if(addtop != N)
fatal("new_name_list_r '=' expr_list");
@@ -387,22 +393,22 @@
}
constdcl:
- new_name_list_r type '=' expr_list
+ name_list type '=' expr_list
{
constiter($1, $2, $4);
}
-| new_name_list_r '=' expr_list
+| name_list '=' expr_list
{
constiter($1, T, $3);
}
constdcl1:
constdcl
-| new_name_list_r type
+| name_list type
{
constiter($1, $2, N);
}
-| new_name_list_r
+| name_list
{
constiter($1, T, N);
}
@@ -464,41 +470,23 @@
$$ = nod(OASOP, $1, $3);
$$->etype = $2; // rathole to pass opcode
}
-| exprsym3_list_r '=' expr_list
+| expr_list '=' expr_list
{
- $$ = rev($1);
$$ = nod(OAS, $$, $3);
}
-| exprsym3_list_r LCOLAS expr_list
+| expr_list LCOLAS expr_list
{
if(addtop != N)
- fatal("exprsym3_list_r LCOLAS expr_list");
+ fatal("expr_list LCOLAS expr_list");
if($3->op == OTYPESW) {
$$ = nod(OTYPESW, $1, $3->left);
break;
}
- $$ = rev($1);
$$ = colas($$, $3);
$$ = nod(OAS, $$, $3);
$$->colas = 1;
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
{
$$ = nod(OASOP, $1, nodintconst(1));
@@ -533,15 +521,36 @@
// right will point to next case
// done in casebody()
poptodcl();
- if(typeswvar != N && typeswvar->right != N)
- if($2->op == OLITERAL && $2->val.ctype == CTNIL) {
- // this version in type switch case nil
- $$ = nod(OTYPESW, N, N);
- $$ = nod(OXCASE, $$, N);
- break;
+ if(typeswvar != N && typeswvar->right != N) {
+ if($2->op == OLITERAL && $2->val.ctype == CTNIL) {
+ // this version in type switch case nil
+ $$ = nod(OTYPESW, N, N);
+ $$ = nod(OXCASE, $$, N);
+ 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);
}
+| 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 ':'
{
// will be converted to OCASE
@@ -561,18 +570,6 @@
$$ = nod(OXCASE, $$, N);
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 ':'
{
poptodcl();
@@ -620,7 +617,8 @@
'{'
{
markdcl();
- } ostmt_list '}'
+ }
+ ostmt_list '}'
{
$$ = $3;
if($$ == N)
@@ -629,7 +627,7 @@
}
switch_body:
- '{'
+ LBODY
{
markdcl();
}
@@ -655,13 +653,26 @@
$$ = nod(OLIST, $1, $2);
}
+loop_body:
+ LBODY
+ {
+ markdcl();
+ }
+ ostmt_list '}'
+ {
+ $$ = $3;
+ if($$ == N)
+ $$ = nod(OEMPTY, N, N);
+ popdcl();
+ }
+
range_stmt:
- exprsym3_list_r '=' LRANGE expr
+ expr_list '=' LRANGE expr
{
$$ = nod(ORANGE, $1, $4);
$$->etype = 0; // := flag
}
-| exprsym3_list_r LCOLAS LRANGE expr
+| expr_list LCOLAS LRANGE expr
{
$$ = nod(ORANGE, $1, $4);
$$->etype = 1;
@@ -678,7 +689,7 @@
$$->ntest = $3;
$$->nincr = $5;
}
-| condition
+| osimple_stmt
{
// normal test
$$ = nod(OFOR, N, N);
@@ -693,7 +704,7 @@
}
for_body:
- for_header compound_stmt
+ for_header loop_body
{
$$ = $1;
$$->nbody = list($$->nbody, $2);
@@ -710,30 +721,15 @@
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:
- condition
+ osimple_stmt
{
// test
$$ = nod(OIF, N, N);
$$->ninit = N;
$$->ntest = $1;
}
-| osimple_stmt ';' condition
+| osimple_stmt ';' osimple_stmt
{
// init ; test
$$ = nod(OIF, N, N);
@@ -746,7 +742,7 @@
{
markdcl();
}
- if_header compound_stmt
+ if_header loop_body
{
$$ = $3;
$$->nbody = $4;
@@ -878,6 +874,10 @@
pexpr
| '*' uexpr
{
+ if($2->op == OTYPE) {
+ $$ = typenod(ptrto($2->type));
+ break;
+ }
$$ = nod(OIND, $2, N);
}
| '&' uexpr
@@ -915,15 +915,26 @@
* can be preceeded by 'defer' and 'go'
*/
pseudocall:
- pexpr '(' oexpr_list ')'
+ pexpr '(' oexpr_or_type_list ')'
{
$$ = unsafenmagic($1, $3);
- if($$ == N)
- $$ = nod(OCALL, $1, $3);
- }
-| LCLOSE '(' expr ')'
- {
- $$ = nod(OCLOSE, $3, N);
+ if($$)
+ break;
+ if($1->op == OTYPE) {
+ // type conversion
+ if($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:
@@ -931,39 +942,28 @@
{
$$ = nodlit($1);
}
-| LNIL
+| name %prec NotBrace
+| pexpr '.' sym
{
- Val v;
- v.ctype = CTNIL;
- $$ = nodlit(v);
- }
-| LTRUE
- {
- $$ = nodbool(1);
- }
-| LFALSE
- {
- $$ = nodbool(0);
- }
-| LIOTA
- {
- $$ = nodintconst(iota);
- $$->iota = 1; // flag to reevaluate on copy
- }
-| name
-| '(' expr ')'
- {
- $$ = $2;
- }
-| pexpr '.' sym2
- {
+ if($1->op == OPACK) {
+ Sym *s;
+ s = pkglookup($3->name, $1->sym->name);
+ $$ = oldname(s);
+ break;
+ }
$$ = nod(ODOT, $1, newname($3));
$$ = adddot($$);
}
-| pexpr '.' '(' type ')'
+| '(' expr_or_type ')'
+ {
+ $$ = $2;
+ }
+| pexpr '.' '(' expr_or_type ')'
{
$$ = nod(ODOTTYPE, $1, N);
- $$->type = $4;
+ if($4->op != OTYPE)
+ yyerror("expected type got %O", $4->op);
+ $$->type = $4->type;
}
| pexpr '.' '(' LTYPE ')'
{
@@ -978,48 +978,13 @@
$$ = nod(OSLICE, $1, $3);
}
| 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 ')'
{
// conversion
- $$ = rev($3);
- if($$ == N)
- $$ = nod(OEMPTY, N, N);
- $$ = nod(OCONV, $$, N);
+ $$ = nod(OCONV, $3, N);
$$->type = $1;
}
-| convtype '{' braced_keyexpr_list '}'
+| convtype lbrace braced_keyexpr_list '}'
{
// composite expression
$$ = rev($3);
@@ -1027,44 +992,49 @@
$$ = nod(OEMPTY, N, N);
$$ = nod(OCOMPOS, $$, N);
$$->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;
+ }
+| pexpr '{' braced_keyexpr_list '}'
+ {
+ // composite expression
+ $$ = rev($3);
+ if($$ == N)
+ $$ = nod(OEMPTY, N, N);
+ $$ = nod(OCOMPOS, $$, N);
+ if($1->op != OTYPE)
+ yyerror("expected type in composite literal");
+ else
+ $$->type = $1->type;
}
| fnliteral
-/*
- * lexical symbols that can be
- * from other packages
- */
-lpack:
- LPACK
+expr_or_type:
+ expr
+| type %prec PreferToRightParen
{
- context = $1->opack;
- }
-/*
- * adding this would enable gri's nested package idea
- *
-| lpack '.' LPACK
- {
- context = $3->opack;
- }
- */
-
-lname:
- LNAME
-| lpack '.' LNAME
- {
- $$ = $3;
- context = nil;
+ $$ = typenod($1);
}
-latype:
- LATYPE
-| lpackatype
-
-lpackatype:
- lpack '.' LATYPE
+name_or_type:
+ dotname
+| type
{
- $$ = $3;
- context = nil;
+ $$ = typenod($1);
+ }
+
+lbrace:
+ LBODY
+ {
+ $$ = LBODY;
+ }
+| '{'
+ {
+ $$ = '{';
}
/*
@@ -1073,19 +1043,19 @@
* oldname is used after declared
*/
new_name:
- sym1
+ sym
{
$$ = newname($1);
}
new_field:
- sym2
+ sym
{
$$ = newname($1);
}
new_type:
- sym1
+ sym
{
$$ = newtype($1);
}
@@ -1097,84 +1067,19 @@
| new_name
sym:
- LATYPE
-| 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
+ LNAME
name:
- lname
- {
- $$ = 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
+ sym %prec NotDot
{
$$ = oldname($1);
}
labelname:
name
-| LATYPE
- {
- $$ = oldname($1);
- }
-| keyword
- {
- $$ = oldname($1);
- }
convtype:
- latype
- {
- $$ = oldtype($1);
- }
-| '[' oexpr ']' type
+ '[' oexpr ']' type
{
// array literal
$$ = aindex($2, $4);
@@ -1191,10 +1096,6 @@
$$ = maptype($3, $5);
}
| structtype
-| '(' type ')'
- {
- $$ = $2;
- }
/*
* to avoid parsing conflicts, type is split into
@@ -1227,12 +1128,6 @@
$$ = $2;
}
-non_name_type:
- chantype
-| fntype
-| othertype
-| dotdotdot
-
dotdotdot:
LDDD
{
@@ -1262,17 +1157,28 @@
| Bothertype
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)
yyerror("the any type is restricted");
- $$ = oldtype($1);
+ $$ = oldtype($1->sym);
}
-othertype:
- Aothertype
-| Bothertype
+dotname:
+ name %prec NotDot
+| 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:
'[' oexpr ']' Atype
@@ -1303,11 +1209,7 @@
| interfacetype
Bothertype:
- lpackatype
- {
- $$ = oldtype($1);
- }
-| '[' oexpr ']' Btype
+ '[' oexpr ']' Btype
{
$$ = aindex($2, $4);
}
@@ -1332,10 +1234,6 @@
$$ = ptrto($2);
}
-chantype:
- Achantype
-| Bchantype
-
Achantype:
LCHAN Atype
{
@@ -1378,10 +1276,6 @@
{
$$ = nod(OKEY, $1, $3);
}
-| LATYPE ':' expr
- {
- $$ = nod(OKEY, newname($1), $3);
- }
/*
@@ -1574,16 +1468,25 @@
$$->val = $3;
}
+packname:
+ LNAME
+| LNAME '.' sym
+ {
+ 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);
+ }
+
embed:
- LATYPE
+ packname
{
$$ = embedded($1);
}
-| lpack '.' LATYPE
- {
- $$ = embedded($3);
- context = nil;
- }
interfacedcl1:
new_name ',' interfacedcl1
@@ -1599,7 +1502,7 @@
interfacedcl:
interfacedcl1
-| latype
+| packname
{
$$ = nod(ODCLFIELD, N, N);
$$->type = oldtype($1);
@@ -1614,65 +1517,44 @@
/*
* 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:
- new_name_list_r type
+arg_type:
+ name_or_type
+| sym name_or_type
{
- $$ = nametodcl($1, $2);
+ $$ = $1->def;
+ if($$ == N) {
+ $$ = nod(ONONAME, N, N);
+ $$->sym = $1;
+ }
+ $$ = nod(OKEY, $$, $2);
}
-| new_name_list_r dotdotdot
+| sym dotdotdot
{
- $$ = nametodcl($1, $2);
+ $$ = $1->def;
+ if($$ == N) {
+ $$ = nod(ONONAME, N, N);
+ $$->sym = $1;
+ }
+ $$ = nod(OKEY, $$, typenod($2));
}
-| non_name_type
+| dotdotdot
{
- $$ = anondcl($1);
- }
-| new_name_list_r ',' non_name_type
- {
- $1 = nametoanondcl($1);
- $$ = appendr($1, anondcl($3));
+ $$ = typenod($1);
}
-arg_chunk_list_r:
- arg_chunk
-| arg_chunk_list_r ',' arg_chunk
- {
- $$ = appendr($1, $3);
- }
-
-/*
- * 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_chunk_list_r
-| arg_chunk_list_r ',' new_name_list_r
+ arg_type
+| arg_type_list_r ',' arg_type
{
- $3 = nametoanondcl($3);
- $$ = appendr($1, $3);
- }
-| new_name_list_r
- {
- $$ = nametoanondcl($1);
+ $$ = nod(OLIST, $1, $3);
}
arg_type_list:
arg_type_list_r
{
$$ = rev($1);
- checkarglist($$);
+ $$ = checkarglist($$);
}
/*
@@ -1728,6 +1610,16 @@
Astmt_list_r
| Bstmt_list_r
+name_list_r:
+ name
+ {
+ $$ = newname($1->sym);
+ }
+| name_list_r ',' name
+ {
+ $$ = nod(OLIST, $1, newname($3->sym));
+ }
+
expr_list_r:
expr
| expr_list_r ',' expr
@@ -1735,27 +1627,9 @@
$$ = nod(OLIST, $1, $3);
}
-new_name_list_r:
- new_name
-| new_name_list_r ',' new_name
- {
- $$ = nod(OLIST, $1, $3);
- }
-
-exprsym3:
- expr
-| sym3
- {
- $$ = newname($1);
- }
-| LATYPE
- {
- $$ = newname($1);
- }
-
-exprsym3_list_r:
- exprsym3
-| exprsym3_list_r ',' exprsym3
+expr_or_type_list_r:
+ expr_or_type
+| expr_or_type_list_r ',' expr_or_type
{
$$ = nod(OLIST, $1, $3);
}
@@ -1844,6 +1718,18 @@
$$ = rev($1);
}
+expr_or_type_list:
+ expr_or_type_list_r
+ {
+ $$ = rev($1);
+ }
+
+name_list:
+ name_list_r
+ {
+ $$ = rev($1);
+ }
+
/*
* optional things
@@ -1866,6 +1752,12 @@
}
| expr_list
+oexpr_or_type_list:
+ {
+ $$ = N;
+ }
+| expr_or_type_list
+
osimple_stmt:
{
$$ = N;
@@ -1934,7 +1826,7 @@
* an output package
*/
hidden_import:
- LPACKAGE sym1
+ LPACKAGE sym
/* variables */
| LVAR hidden_pkg_importsym hidden_type
{
@@ -1956,7 +1848,7 @@
{
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) {
yyerror("bad receiver in method");
@@ -1972,9 +1864,9 @@
hidden_type1:
hidden_importsym
{
- $$ = pkgtype($1->sym->name, $1->psym->name);
+ $$ = pkgtype($1);
}
-| LATYPE
+| LNAME
{
$$ = oldtype($1);
}
@@ -2034,7 +1926,7 @@
}
hidden_dcl:
- sym1 hidden_type
+ sym hidden_type
{
$$ = nod(ODCLFIELD, newname($1), N);
$$->type = $2;
@@ -2046,7 +1938,7 @@
}
hidden_structdcl:
- sym1 hidden_type oliteral
+ sym hidden_type oliteral
{
$$ = nod(ODCLFIELD, newname($1), N);
$$->type = $2;
@@ -2063,7 +1955,7 @@
}
hidden_interfacedcl:
- sym1 '(' ohidden_funarg_list ')' ohidden_funres
+ sym '(' ohidden_funarg_list ')' ohidden_funres
{
$$ = nod(ODCLFIELD, newname($1), N);
$$->type = functype(fakethis(), $3, $5);
@@ -2105,72 +1997,24 @@
yyerror("bad negated constant");
}
}
-| LTRUE
+| name
{
- $$ = nodbool(1);
- }
-| LFALSE
- {
- $$ = nodbool(0);
+ $$ = $1;
+ if($$->op != OLITERAL)
+ yyerror("bad constant %S", $$->sym);
}
hidden_importsym:
- sym1 '.' sym2
+ sym '.' sym
{
- $$ = nod(OIMPORT, N, N);
- $$->psym = $1;
- $$->sym = $3;
+ $$ = pkglookup($3->name, $1->name);
}
hidden_pkg_importsym:
hidden_importsym
{
$$ = $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;
- }
-
-/**/
-
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 8e4f350..58e3ba6 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -64,7 +64,7 @@
fatal("betypeinit failed");
lexinit();
- typeinit(LATYPE);
+ typeinit();
lineno = 1;
block = 1;
@@ -711,6 +711,40 @@
}
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:
goto lx;
}
@@ -764,15 +798,16 @@
ungetc(c);
s = lookup(lexbuf);
- if(s->lexical == LIGNORE)
+ switch(s->lexical) {
+ case LIGNORE:
goto l0;
- if(context != nil) {
- s = pkglookup(s->name, context);
- if(s->lexical == LIGNORE)
- goto l0;
- if(!exportname(s->name) && strcmp(package, s->package) != 0)
- s = pkglookup(s->name, ".private");
+ case LFOR:
+ case LIF:
+ case LSWITCH:
+ case LSELECT:
+ loophack = 1; // see comment about loophack above
+ break;
}
DBG("lex: %S %s\n", s, lexname(s->lexical));
@@ -1109,77 +1144,74 @@
char* name;
int lexical;
int etype;
+ int op;
} syms[] =
{
-/* name lexical etype
+/* name lexical etype op
*/
/* basic types */
- "int8", LATYPE, TINT8,
- "int16", LATYPE, TINT16,
- "int32", LATYPE, TINT32,
- "int64", LATYPE, TINT64,
+ "int8", LNAME, TINT8, OXXX,
+ "int16", LNAME, TINT16, OXXX,
+ "int32", LNAME, TINT32, OXXX,
+ "int64", LNAME, TINT64, OXXX,
- "uint8", LATYPE, TUINT8,
- "uint16", LATYPE, TUINT16,
- "uint32", LATYPE, TUINT32,
- "uint64", LATYPE, TUINT64,
+ "uint8", LNAME, TUINT8, OXXX,
+ "uint16", LNAME, TUINT16, OXXX,
+ "uint32", LNAME, TUINT32, OXXX,
+ "uint64", LNAME, TUINT64, OXXX,
- "float32", LATYPE, TFLOAT32,
- "float64", LATYPE, TFLOAT64,
- "float80", LATYPE, TFLOAT80,
+ "float32", LNAME, TFLOAT32, OXXX,
+ "float64", LNAME, TFLOAT64, OXXX,
+ "float80", LNAME, TFLOAT80, OXXX,
- "bool", LATYPE, TBOOL,
- "byte", LATYPE, TUINT8,
- "string", LATYPE, TSTRING,
+ "bool", LNAME, TBOOL, OXXX,
+ "byte", LNAME, TUINT8, OXXX,
+ "string", LNAME, TSTRING, OXXX,
- "any", LATYPE, TANY,
+ "any", LNAME, TANY, OXXX,
- "break", LBREAK, Txxx,
- "case", LCASE, Txxx,
- "chan", LCHAN, Txxx,
- "const", LCONST, Txxx,
- "continue", LCONTINUE, Txxx,
- "default", LDEFAULT, Txxx,
- "else", LELSE, Txxx,
- "defer", LDEFER, Txxx,
- "fallthrough", LFALL, Txxx,
- "false", LFALSE, Txxx,
- "for", LFOR, Txxx,
- "func", LFUNC, Txxx,
- "go", LGO, Txxx,
- "goto", LGOTO, Txxx,
- "if", LIF, Txxx,
- "import", LIMPORT, Txxx,
- "interface", LINTERFACE, Txxx,
- "iota", LIOTA, Txxx,
- "make", LMAKE, Txxx,
- "map", LMAP, Txxx,
- "new", LNEW, Txxx,
- "len", LLEN, Txxx,
- "cap", LCAP, Txxx,
- "nil", LNIL, Txxx,
- "package", LPACKAGE, Txxx,
- "panic", LPANIC, Txxx,
- "panicln", LPANICN, Txxx,
- "print", LPRINT, Txxx,
- "println", LPRINTN, Txxx,
- "range", LRANGE, Txxx,
- "return", LRETURN, Txxx,
- "select", LSELECT, Txxx,
- "struct", LSTRUCT, Txxx,
- "switch", LSWITCH, Txxx,
- "true", LTRUE, Txxx,
- "type", LTYPE, Txxx,
- "var", LVAR, Txxx,
+ "break", LBREAK, Txxx, OXXX,
+ "case", LCASE, Txxx, OXXX,
+ "chan", LCHAN, Txxx, OXXX,
+ "const", LCONST, Txxx, OXXX,
+ "continue", LCONTINUE, Txxx, OXXX,
+ "default", LDEFAULT, Txxx, OXXX,
+ "else", LELSE, Txxx, OXXX,
+ "defer", LDEFER, Txxx, OXXX,
+ "fallthrough", LFALL, Txxx, OXXX,
+ "for", LFOR, Txxx, OXXX,
+ "func", LFUNC, Txxx, OXXX,
+ "go", LGO, Txxx, OXXX,
+ "goto", LGOTO, Txxx, OXXX,
+ "if", LIF, Txxx, OXXX,
+ "import", LIMPORT, Txxx, OXXX,
+ "interface", LINTERFACE, Txxx, OXXX,
+ "map", LMAP, Txxx, OXXX,
+ "package", LPACKAGE, Txxx, OXXX,
+ "range", LRANGE, Txxx, OXXX,
+ "return", LRETURN, Txxx, OXXX,
+ "select", LSELECT, Txxx, OXXX,
+ "struct", LSTRUCT, Txxx, OXXX,
+ "switch", LSWITCH, Txxx, OXXX,
+ "type", LTYPE, Txxx, OXXX,
+ "var", LVAR, Txxx, OXXX,
- "close", LCLOSE, Txxx,
- "closed", LCLOSED, Txxx,
+ "cap", LNAME, Txxx, OCAP,
+ "close", LNAME, Txxx, OCLOSE,
+ "closed", LNAME, Txxx, OCLOSED,
+ "len", LNAME, Txxx, OLEN,
+ "make", LNAME, Txxx, OMAKE,
+ "new", LNAME, Txxx, ONEW,
+ "panic", LNAME, Txxx, OPANIC,
+ "panicln", LNAME, Txxx, OPANICN,
+ "print", LNAME, Txxx, OPRINT,
+ "println", LNAME, Txxx, OPRINTN,
- "notwithstanding", LIGNORE, Txxx,
- "thetruthofthematter", LIGNORE, Txxx,
- "despiteallobjections", LIGNORE, Txxx,
- "whereas", LIGNORE, Txxx,
- "insofaras", LIGNORE, Txxx,
+ "notwithstanding", LIGNORE, Txxx, OXXX,
+ "thetruthofthematter", LIGNORE, Txxx, OXXX,
+ "despiteallobjections", LIGNORE, Txxx, OXXX,
+ "whereas", LIGNORE, Txxx, OXXX,
+ "insofaras", LIGNORE, Txxx, OXXX,
};
void
@@ -1189,6 +1221,7 @@
Sym *s;
Type *t;
int etype;
+ Val v;
/*
* initialize basic types array
@@ -1201,25 +1234,51 @@
s->package = package;
etype = syms[i].etype;
- if(etype == Txxx)
- continue;
+ 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;
- if(etype < 0 || etype >= nelem(types))
- fatal("lexinit: %s bad etype", s->name);
-
- t = types[etype];
- if(t != T) {
- s->otype = t;
+ dowidth(t);
+ types[etype] = t;
+ }
+ s->def = typenod(t);
continue;
}
- t = typ(etype);
- t->sym = s;
- dowidth(t);
- types[etype] = t;
- s->otype = t;
+ etype = syms[i].op;
+ if(etype != OXXX) {
+ s->def = nod(ONAME, N, N);
+ s->def->sym = s;
+ s->def->etype = etype;
+ s->def->builtin = 1;
+ continue;
+ }
}
+ // 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.
// types[TSTRING] is the named type string
// (the type of x in var x string or var x = "hello").
@@ -1244,14 +1303,18 @@
LCONST, "CONST",
LCONTINUE, "CONTINUE",
LDEC, "DEC",
+ LDEFER, "DEFER",
LELSE, "ELSE",
LEQ, "EQ",
+ LFALL, "FALL",
+ LFOR, "FOR",
LFUNC, "FUNC",
LGE, "GE",
LGO, "GO",
LGOTO, "GOTO",
LGT, "GT",
LIF, "IF",
+ LIMPORT, "IMPORT",
LINC, "INC",
LINTERFACE, "INTERFACE",
LLE, "LE",
@@ -1262,7 +1325,7 @@
LNAME, "NAME",
LNE, "NE",
LOROR, "OROR",
- LPACK, "PACK",
+ LPACKAGE, "PACKAGE",
LRANGE, "RANGE",
LRETURN, "RETURN",
LRSH, "RSH",
@@ -1270,16 +1333,6 @@
LSWITCH, "SWITCH",
LTYPE, "TYPE",
LVAR, "VAR",
- LFOR, "FOR",
- LNEW, "NEW",
- LLEN, "LEN",
- LFALL, "FALL",
- LIOTA, "IOTA",
- LPRINT, "PRINT",
- LPACKAGE, "PACKAGE",
- LIMPORT, "IMPORT",
- LDEFER, "DEFER",
- LPANIC, "PANIC",
};
char*
@@ -1316,8 +1369,8 @@
// declare this name as a package
s = lookup(package);
- s->lexical = LPACK;
- s->opack = s->name;
+ s->def = nod(OPACK, N, N);
+ s->def->sym = s;
if(outfile == nil) {
p = strrchr(infile, '/');
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index e540106..64d1898 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -58,7 +58,7 @@
continue;
dowidth(n->type);
- ggloblnod(s->oname, n->type->width);
+ ggloblnod(s->def, n->type->width);
}
}
@@ -393,6 +393,7 @@
Dcl *d, *x;
Type *t, *progt, *methodt, *ifacet, *rcvrt;
Sym *s;
+ Node *n;
// copy externdcl list to signatlist
for(d=externdcl; d!=D; d=d->forw) {
@@ -403,9 +404,10 @@
if(t == T)
continue;
- s = signame(t);
- if(s == S)
+ n = signame(t);
+ if(n == N || n->sym == S)
continue;
+ s = n->sym;
x = mal(sizeof(*d));
x->op = OTYPE;
@@ -425,10 +427,11 @@
continue;
t = d->dtype;
et = t->etype;
- s = signame(t);
+ n = signame(t);
//print("signame %S for %T\n", s, t);
- if(s == S)
+ if(n == N || n->sym == S)
continue;
+ s = n->sym;
// only emit one
if(s->siggen)
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 0e02507..0ff7524 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -156,9 +156,9 @@
}
s = mal(sizeof(*s));
- s->lexical = LNAME;
s->name = mal(strlen(p)+1);
s->package = package;
+ s->lexical = LNAME;
strcpy(s->name, p);
@@ -186,7 +186,6 @@
}
s = mal(sizeof(*s));
- s->lexical = LNAME;
s->name = mal(strlen(p)+1);
strcpy(s->name, p);
@@ -220,13 +219,11 @@
if(strcmp(s->package, opkg->name) != 0)
continue;
s1 = lookup(s->name);
- if(s1->oname != N || s1->otype != T) {
+ if(s1->def != N) {
yyerror("redeclaration of %S during import", s1);
continue;
}
- s1->lexical = s->lexical;
- s1->oname = s->oname;
- s1->otype = s->otype;
+ s1->def = s->def;
}
}
}
@@ -571,7 +568,7 @@
break;
case OTYPE:
- print("%O-%E %lT\n", n->op, n->etype, n);
+ print("%O %T\n", n->op, n->type);
break;
case OIF:
@@ -696,7 +693,6 @@
[OGOTO] = "GOTO",
[OGT] = "GT",
[OIF] = "IF",
- [OIMPORT] = "IMPORT",
[OINC] = "INC",
[OINDEX] = "INDEX",
[OINDREG] = "INDREG",
@@ -722,6 +718,7 @@
[OOR] = "OR",
[OPANICN] = "PANICN",
[OPANIC] = "PANIC",
+ [OPACK] = "PACK",
[OPARAM] = "PARAM",
[OPLUS] = "PLUS",
[OPRINTN] = "PRINTN",
@@ -741,7 +738,6 @@
[OTYPEOF] = "TYPEOF",
[OTYPESW] = "TYPESW",
[OTYPE] = "TYPE",
- [OVAR] = "VAR",
[OXCASE] = "XCASE",
[OXFALL] = "XFALL",
[OXOR] = "XOR",
@@ -1044,8 +1040,11 @@
fmtprint(fp, "%hS", s);
else
fmtprint(fp, "%lS", s);
- if(strcmp(s->package, package) == 0)
- if((s->otype != t || !s->export) && !s->imported) {
+ if(strcmp(s->package, package) != 0)
+ 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);
if(t->vargen)
fmtprint(fp, "·%d", t->vargen);
@@ -1339,7 +1338,7 @@
break;
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;
}
if(n->sym != S) {
@@ -1581,7 +1580,7 @@
return 0;
}
-Sym*
+Node*
signame(Type *t)
{
Sym *ss;
@@ -1611,10 +1610,10 @@
strcpy(buf, "dotdotdot");
ss = pkglookup(buf, e);
- if(ss->oname == N) {
- ss->oname = newname(ss);
- ss->oname->type = types[TUINT8];
- ss->oname->class = PEXTERN;
+ if(ss->def == N) {
+ ss->def = newname(ss);
+ ss->def->type = types[TUINT8];
+ ss->def->class = PEXTERN;
}
//print("siggen %T %d\n", t, t->siggen);
@@ -1633,10 +1632,10 @@
}
out:
- return ss;
+ return ss->def;
bad:
- return S;
+ return N;
}
int
@@ -1942,15 +1941,15 @@
Node *n;
s = pkglookup(name, "sys");
- if(s == S || s->oname == N)
+ if(s == S || s->def == N)
fatal("looksys: cant find sys.%s", name);
if(!copy)
- return s->oname;
+ return s->def;
n = nod(0, N, N);
- *n = *s->oname;
- n->type = deep(s->oname->type);
+ *n = *s->def;
+ n->type = deep(s->def->type);
return n;
}
@@ -2073,7 +2072,7 @@
case OTYPE:
if(flag)
print("--- %s frame ---\n", p);
- print("%O %lT\n", d->op, d->dnode);
+ print("%O %T\n", d->op, d->dnode);
flag = 0;
break;
}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 03ca8db..e29d608 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -123,8 +123,16 @@
return;
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;
+ }
+
switch(n->op) {
case OLIST:
@@ -248,6 +256,7 @@
switch(n->op) {
default:
+ dump("walk", n);
fatal("walktype: switch 1 unknown op %N", n);
goto ret;
@@ -313,7 +322,10 @@
if(n->type == T) {
s = n->sym;
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;
}
}
@@ -1030,20 +1042,28 @@
case OMAKE:
if(top != Erv)
goto nottop;
+ l = n->left;
+ if(l == N) {
+ yyerror("missing argument to make");
+ goto ret;
+ }
indir(n, makecompat(n));
goto ret;
case ONEW:
if(top != Erv)
goto nottop;
- if(n->left != N) {
- yyerror("cannot new(%T, expr)", t);
- goto ret;
- }
- t = n->type;
- if(t == T)
- goto ret;
- indir(n, callnew(t));
+ l = n->left;
+ if(l == N)
+ yyerror("missing argument to new");
+ else if(n->right != N)
+ yyerror("too many arguments to new");
+ else if(l->op != OTYPE)
+ yyerror("argument to new must be type");
+ else if((t = l->type) == T)
+ ;
+ else
+ indir(n, callnew(t));
goto ret;
}
@@ -1927,12 +1947,12 @@
x = mal(sizeof(*x));
x->op = OTYPE;
x->dsym = s;
- x->dtype = s->otype;
+ x->dtype = t;
x->forw = signatlist;
x->block = block;
signatlist = x;
- return s->otype;
+ return t;
}
/*
@@ -2350,8 +2370,22 @@
makecompat(Node *n)
{
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)
switch(t->etype) {
@@ -3045,9 +3079,8 @@
a = listfirst(&save, &n->left); // nel
if(a == N) {
- if(t->bound < 0)
- yyerror("new open array must have size");
- a = nodintconst(t->bound);
+ yyerror("new slice must have size");
+ a = nodintconst(1);
}
a = nod(OCONV, a, N);
a->type = types[TINT];
@@ -3193,7 +3226,6 @@
{
Type *tr;
Node *r, *a, *on;
- Sym *s;
tr = n->type;
@@ -3207,19 +3239,10 @@
a = n; // elem
r = a;
- s = signame(tr); // sigt
- if(s == S)
- fatal("ifacecvt: signame-1 T2I: %lT", tr);
- a = s->oname;
- a = nod(OADDR, a, N);
+ a = nod(OADDR, signame(tr), N); // sigt
r = list(a, r);
- s = signame(tl); // sigi
- if(s == S) {
- fatal("ifacecvt: signame-2 T2I: %lT", tl);
- }
- a = s->oname;
- a = nod(OADDR, a, N);
+ a = nod(OADDR, signame(tl), N); // sigi
r = list(a, r);
on = syslook("ifaceT2I", 1);
@@ -3240,11 +3263,7 @@
a = n; // interface
r = a;
- s = signame(tl); // sigi or sigt
- if(s == S)
- fatal("ifacecvt: signame %d", et);
- a = s->oname;
- a = nod(OADDR, a, N);
+ a = nod(OADDR, signame(tl), N); // sigi or sigt
r = list(a, r);
on = syslook(ifacename[et], 1);
@@ -3268,11 +3287,7 @@
a = n; // elem
r = a;
- s = signame(tr); // sigt
- if(s == S)
- fatal("ifacecvt: signame-1 T2E: %lT", tr);
- a = s->oname;
- a = nod(OADDR, a, N);
+ a = nod(OADDR, signame(tr), N); // sigt
r = list(a, r);
on = syslook("ifaceT2E", 1);
@@ -3394,7 +3409,9 @@
switch(n->op) {
case ONAME:
case ONONAME:
+ case OPACK:
break;
+ case OTYPE:
case OLITERAL:
if(n->sym != S)
break;
@@ -4248,9 +4265,7 @@
if(b < 0) {
// slice
- a = nod(OMAKE, N, N);
- a->type = t;
- a->left = nodintconst(ninit);
+ a = nod(OMAKE, nod(OLIST, typenod(t), nodintconst(ninit)), N);
a = nod(OAS, var, a);
addtop = list(addtop, a);
} else {
@@ -4377,8 +4392,7 @@
tempname(var, t);
}
- a = nod(OMAKE, N, N);
- a->type = t;
+ a = nod(OMAKE, typenod(t), N);
a = nod(OAS, var, a);
addtop = list(addtop, a);