mirror of https://github.com/golang/go.git
parent
866b272336
commit
66bb399fdd
|
|
@ -649,16 +649,9 @@ funchdr(Node *n)
|
|||
Node *nt;
|
||||
|
||||
if(n->nname != N) {
|
||||
// TODO(rsc): remove once forward declarations are gone
|
||||
if(n->nname->sym->def && n->nname->sym->def->class == PFUNC) {
|
||||
nt = n->nname->ntype;
|
||||
n->nname = n->nname->sym->def;
|
||||
n->nname->ntype = nt;
|
||||
n->nname->type = T;
|
||||
} else {
|
||||
n->nname->op = ONAME;
|
||||
declare(n->nname, PFUNC);
|
||||
}
|
||||
n->nname->op = ONAME;
|
||||
declare(n->nname, PFUNC);
|
||||
n->nname->defn = n;
|
||||
}
|
||||
|
||||
// change the declaration context from extern to auto
|
||||
|
|
|
|||
|
|
@ -299,6 +299,8 @@ pkgtype(Sym *s)
|
|||
t->sym = s;
|
||||
s->def = typenod(t);
|
||||
}
|
||||
if(s->def->type == T)
|
||||
yyerror("pkgtype %lS", s);
|
||||
return s->def->type;
|
||||
}
|
||||
|
||||
|
|
@ -314,6 +316,8 @@ mypackage(Sym *s)
|
|||
void
|
||||
importconst(Sym *s, Type *t, Node *n)
|
||||
{
|
||||
Node *n1;
|
||||
|
||||
if(!exportname(s->name) && !mypackage(s))
|
||||
return;
|
||||
importsym(s, OLITERAL);
|
||||
|
|
@ -327,6 +331,11 @@ importconst(Sym *s, Type *t, Node *n)
|
|||
yyerror("expression must be a constant");
|
||||
return;
|
||||
}
|
||||
if(n->sym != S) {
|
||||
n1 = nod(OXXX, N, N);
|
||||
*n1 = *n;
|
||||
n = n1;
|
||||
}
|
||||
n->sym = s;
|
||||
declare(n, PEXTERN);
|
||||
|
||||
|
|
@ -360,7 +369,8 @@ importvar(Sym *s, Type *t, int ctxt)
|
|||
void
|
||||
importtype(Type *pt, Type *t)
|
||||
{
|
||||
typedcl2(pt, t);
|
||||
if(pt != T && t != T)
|
||||
typedcl2(pt, t);
|
||||
|
||||
if(debug['E'])
|
||||
print("import type %T %lT\n", pt, t);
|
||||
|
|
|
|||
|
|
@ -198,6 +198,7 @@ struct Node
|
|||
uchar walkdef;
|
||||
uchar typecheck;
|
||||
uchar local;
|
||||
uchar initorder;
|
||||
|
||||
// most nodes
|
||||
Node* left;
|
||||
|
|
@ -649,6 +650,7 @@ EXTERN Mpint* maxintval[NTYPE];
|
|||
EXTERN Mpflt* minfltval[NTYPE];
|
||||
EXTERN Mpflt* maxfltval[NTYPE];
|
||||
|
||||
EXTERN NodeList* xtop;
|
||||
EXTERN NodeList* externdcl;
|
||||
EXTERN NodeList* closures;
|
||||
EXTERN NodeList* exportlist;
|
||||
|
|
|
|||
|
|
@ -120,29 +120,7 @@ file:
|
|||
imports
|
||||
xdcl_list
|
||||
{
|
||||
NodeList *l;
|
||||
|
||||
if(nsyntaxerrors == 0)
|
||||
testdclstack();
|
||||
|
||||
typecheckok = 1;
|
||||
if(debug['f'])
|
||||
frame(1);
|
||||
defercheckwidth();
|
||||
typechecklist($4, Etop);
|
||||
resumecheckwidth();
|
||||
for(l=$4; l; l=l->next)
|
||||
if(l->n->op == ODCLFUNC)
|
||||
funccompile(l->n);
|
||||
if(nerrors == 0)
|
||||
fninit($4);
|
||||
while(closures) {
|
||||
l = closures;
|
||||
closures = nil;
|
||||
for(; l; l=l->next)
|
||||
funccompile(l->n);
|
||||
}
|
||||
dclchecks();
|
||||
xtop = concat(xtop, $4);
|
||||
}
|
||||
|
||||
package:
|
||||
|
|
@ -262,15 +240,17 @@ import_done:
|
|||
if(my == import && strcmp(import->name, package) == 0)
|
||||
break;
|
||||
|
||||
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->def->op != OPACK || strcmp(my->name, import->name) != 0)
|
||||
yyerror("redeclaration of %S by import", my);
|
||||
}
|
||||
// TODO(rsc): this line is needed for a package
|
||||
// which does bytes := in a function, which creates
|
||||
// an ONONAME for bytes, but then a different file
|
||||
// imports "bytes". more generally we need to figure out
|
||||
// what it means if one file imports "bytes" and another
|
||||
// declares a top-level name.
|
||||
if(my->def && my->def->op == ONONAME)
|
||||
my->def = N;
|
||||
|
||||
if(my->def)
|
||||
yyerror("redeclaration of %S by import\n\t%N", my, my->def);
|
||||
my->def = nod(OPACK, N, N);
|
||||
my->def->sym = import;
|
||||
import->block = -1; // above top level
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ Node*
|
|||
renameinit(Node *n)
|
||||
{
|
||||
Sym *s;
|
||||
static int initgen;
|
||||
|
||||
s = n->sym;
|
||||
if(s == S)
|
||||
|
|
@ -22,7 +23,7 @@ renameinit(Node *n)
|
|||
if(strcmp(s->name, "init") != 0)
|
||||
return n;
|
||||
|
||||
snprint(namebuf, sizeof(namebuf), "init·%s", filename);
|
||||
snprint(namebuf, sizeof(namebuf), "init·%d", ++initgen);
|
||||
s = lookup(namebuf);
|
||||
return newname(s);
|
||||
}
|
||||
|
|
@ -70,7 +71,7 @@ anyinit(NodeList *n)
|
|||
return 1;
|
||||
|
||||
// is there an explicit init function
|
||||
snprint(namebuf, sizeof(namebuf), "init·%s", filename);
|
||||
snprint(namebuf, sizeof(namebuf), "init·1");
|
||||
s = lookup(namebuf);
|
||||
if(s->def != N)
|
||||
return 1;
|
||||
|
|
@ -92,6 +93,7 @@ anyinit(NodeList *n)
|
|||
void
|
||||
fninit(NodeList *n)
|
||||
{
|
||||
int i;
|
||||
Node *gatevar;
|
||||
Node *a, *b, *fn;
|
||||
NodeList *r;
|
||||
|
|
@ -110,7 +112,7 @@ fninit(NodeList *n)
|
|||
r = nil;
|
||||
|
||||
// (1)
|
||||
snprint(namebuf, sizeof(namebuf), "initdone·%s", filename);
|
||||
snprint(namebuf, sizeof(namebuf), "initdone·");
|
||||
gatevar = newname(lookup(namebuf));
|
||||
addvar(gatevar, types[TUINT8], PEXTERN);
|
||||
|
||||
|
|
@ -118,7 +120,7 @@ fninit(NodeList *n)
|
|||
|
||||
maxarg = 0;
|
||||
|
||||
snprint(namebuf, sizeof(namebuf), "Init·%s", filename);
|
||||
snprint(namebuf, sizeof(namebuf), "Init·");
|
||||
|
||||
// this is a botch since we need a known name to
|
||||
// call the top level init function out of rt0
|
||||
|
|
@ -168,13 +170,15 @@ fninit(NodeList *n)
|
|||
}
|
||||
|
||||
// (8)
|
||||
r = concat(r, initfix(n));
|
||||
r = concat(r, n);
|
||||
|
||||
// (9)
|
||||
// could check that it is fn of no args/returns
|
||||
snprint(namebuf, sizeof(namebuf), "init·%s", filename);
|
||||
s = lookup(namebuf);
|
||||
if(s->def != N) {
|
||||
for(i=1;; i++) {
|
||||
snprint(namebuf, sizeof(namebuf), "init·%d", i);
|
||||
s = lookup(namebuf);
|
||||
if(s->def == N)
|
||||
break;
|
||||
a = nod(OCALL, s->def, N);
|
||||
r = list(r, a);
|
||||
}
|
||||
|
|
|
|||
128
src/cmd/gc/lex.c
128
src/cmd/gc/lex.c
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
extern int yychar;
|
||||
Sym *anysym;
|
||||
char nopackage[] = "____";
|
||||
|
||||
#define DBG if(!debug['x']);else print
|
||||
enum
|
||||
|
|
@ -20,10 +21,11 @@ enum
|
|||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
int i, c;
|
||||
NodeList *l;
|
||||
|
||||
outfile = nil;
|
||||
package = "____";
|
||||
package = nopackage;
|
||||
ARGBEGIN {
|
||||
default:
|
||||
c = ARGC();
|
||||
|
|
@ -44,7 +46,7 @@ main(int argc, char *argv[])
|
|||
break;
|
||||
} ARGEND
|
||||
|
||||
if(argc != 1)
|
||||
if(argc < 1)
|
||||
goto usage;
|
||||
|
||||
pathname = mal(100);
|
||||
|
|
@ -69,31 +71,57 @@ main(int argc, char *argv[])
|
|||
lexinit();
|
||||
typeinit();
|
||||
|
||||
lineno = 1;
|
||||
block = 1;
|
||||
blockgen = 1;
|
||||
|
||||
setfilename(argv[0]);
|
||||
infile = argv[0];
|
||||
linehist(infile, 0, 0);
|
||||
|
||||
curio.infile = infile;
|
||||
curio.bin = Bopen(infile, OREAD);
|
||||
if(curio.bin == nil)
|
||||
fatal("cant open: %s", infile);
|
||||
curio.peekc = 0;
|
||||
curio.peekc1 = 0;
|
||||
|
||||
dclcontext = PEXTERN;
|
||||
|
||||
nerrors = 0;
|
||||
yyparse();
|
||||
lineno = 1;
|
||||
|
||||
for(i=0; i<argc; i++) {
|
||||
if(i == 0)
|
||||
setfilename(argv[i]);
|
||||
infile = argv[i];
|
||||
linehist(infile, 0, 0);
|
||||
|
||||
curio.infile = infile;
|
||||
curio.bin = Bopen(infile, OREAD);
|
||||
if(curio.bin == nil)
|
||||
fatal("open%s: %r", infile);
|
||||
curio.peekc = 0;
|
||||
curio.peekc1 = 0;
|
||||
|
||||
block = 1;
|
||||
|
||||
yyparse();
|
||||
if(nsyntaxerrors != 0)
|
||||
errorexit();
|
||||
|
||||
linehist(nil, 0, 0);
|
||||
if(curio.bin != nil)
|
||||
Bterm(curio.bin);
|
||||
}
|
||||
|
||||
testdclstack();
|
||||
|
||||
typecheckok = 1;
|
||||
if(debug['f'])
|
||||
frame(1);
|
||||
defercheckwidth();
|
||||
typechecklist(xtop, Etop);
|
||||
resumecheckwidth();
|
||||
for(l=xtop; l; l=l->next)
|
||||
if(l->n->op == ODCLFUNC)
|
||||
funccompile(l->n);
|
||||
if(nerrors == 0)
|
||||
fninit(xtop);
|
||||
while(closures) {
|
||||
l = closures;
|
||||
closures = nil;
|
||||
for(; l; l=l->next)
|
||||
funccompile(l->n);
|
||||
}
|
||||
dclchecks();
|
||||
|
||||
runifacechecks();
|
||||
|
||||
linehist(nil, 0, 0);
|
||||
if(curio.bin != nil)
|
||||
Bterm(curio.bin);
|
||||
|
||||
if(nerrors)
|
||||
errorexit();
|
||||
|
||||
|
|
@ -264,6 +292,8 @@ importfile(Val *f)
|
|||
int32 c;
|
||||
int len;
|
||||
|
||||
// TODO: don't bother reloading imports more than once
|
||||
|
||||
if(f->ctype != CTSTR) {
|
||||
yyerror("import statement not a string");
|
||||
return;
|
||||
|
|
@ -1427,6 +1457,16 @@ lexname(int lex)
|
|||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
specialsym(Sym *s)
|
||||
{
|
||||
if(strcmp(s->name, "byte") == 0 && s->def->sym == lookup("uint8"))
|
||||
return 1;
|
||||
if(strcmp(s->name, "iota") == 0 && s->def->sym == S)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
mkpackage(char* pkg)
|
||||
{
|
||||
|
|
@ -1434,23 +1474,43 @@ mkpackage(char* pkg)
|
|||
int32 h;
|
||||
char *p;
|
||||
|
||||
if(bout != nil) {
|
||||
yyerror("mkpackage: called again %s %s", pkg, package);
|
||||
return;
|
||||
if(package == nopackage) {
|
||||
// redefine all names to be this package.
|
||||
for(h=0; h<NHASH; h++)
|
||||
for(s = hash[h]; s != S; s = s->link)
|
||||
if(s->package == nopackage)
|
||||
s->package = pkg;
|
||||
package = pkg;
|
||||
} else {
|
||||
if(strcmp(pkg, package) != 0)
|
||||
yyerror("package %s; expected %s", pkg, package);
|
||||
for(h=0; h<NHASH; h++) {
|
||||
for(s = hash[h]; s != S; s = s->link) {
|
||||
if(s->def == N || s->package != package)
|
||||
continue;
|
||||
if(s->def->op == OPACK) {
|
||||
// throw away top-level package name leftover
|
||||
// from previous file.
|
||||
s->def = N;
|
||||
continue;
|
||||
}
|
||||
if(s->def->sym != s && !specialsym(s)) {
|
||||
// throw away top-level name left over
|
||||
// from previous import . "x"
|
||||
s->def = N;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// redefine all names to be this package
|
||||
for(h=0; h<NHASH; h++)
|
||||
for(s = hash[h]; s != S; s = s->link)
|
||||
if(s->package == package)
|
||||
s->package = pkg;
|
||||
package = pkg;
|
||||
|
||||
/*
|
||||
// declare this name as a package
|
||||
s = lookup(package);
|
||||
s->def = nod(OPACK, N, N);
|
||||
s->def->sym = s;
|
||||
s->block = -1; // above top level
|
||||
*/
|
||||
|
||||
if(outfile == nil) {
|
||||
p = strrchr(infile, '/');
|
||||
|
|
|
|||
|
|
@ -457,13 +457,85 @@ return;
|
|||
|
||||
}
|
||||
|
||||
static void
|
||||
init1(Node *n, NodeList **out)
|
||||
{
|
||||
NodeList *l;
|
||||
|
||||
if(n == N)
|
||||
return;
|
||||
init1(n->left, out);
|
||||
init1(n->right, out);
|
||||
for(l=n->list; l; l=l->next)
|
||||
init1(l->n, out);
|
||||
|
||||
if(n->op != ONAME)
|
||||
return;
|
||||
switch(n->class) {
|
||||
case PEXTERN:
|
||||
case PFUNC:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if(n->initorder == 1)
|
||||
return;
|
||||
if(n->initorder == 2)
|
||||
fatal("init loop");
|
||||
|
||||
// make sure that everything n depends on is initialized.
|
||||
// n->defn is an assignment to n
|
||||
n->initorder = 2;
|
||||
if(n->defn != N) {
|
||||
switch(n->defn->op) {
|
||||
case ODCLFUNC:
|
||||
for(l=n->defn->nbody; l; l=l->next)
|
||||
init1(l->n, out);
|
||||
break;
|
||||
case OAS:
|
||||
if(n->defn->left != n) {
|
||||
default:
|
||||
dump("defn", n->defn);
|
||||
fatal("bad defn");
|
||||
}
|
||||
init1(n->defn->right, out);
|
||||
if(debug['j'])
|
||||
print("%S\n", n->sym);
|
||||
*out = list(*out, n->defn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
n->initorder = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
initreorder(NodeList *l, NodeList **out)
|
||||
{
|
||||
Node *n;
|
||||
|
||||
for(; l; l=l->next) {
|
||||
n = l->n;
|
||||
switch(n->op) {
|
||||
case ODCLFUNC:
|
||||
case ODCLCONST:
|
||||
case ODCLTYPE:
|
||||
continue;
|
||||
}
|
||||
initreorder(n->ninit, out);
|
||||
n->ninit = nil;
|
||||
init1(n, out);
|
||||
}
|
||||
}
|
||||
|
||||
NodeList*
|
||||
initfix(NodeList *l)
|
||||
{
|
||||
Node *r;
|
||||
|
||||
xxx.list = nil;
|
||||
initlin(l);
|
||||
initreorder(l, &xxx.list);
|
||||
|
||||
if(0)
|
||||
return xxx.list;
|
||||
|
|
|
|||
Loading…
Reference in New Issue