break;
case OCONV:
- if(!eqtype(n->type, nl->type))
+ if(!cvttype(n->type, nl->type))
fatal("agen: non-trivial OCONV");
agen(nl, res);
return;
if(n->method) {
if(n->type != T)
if(n->type->sym != S)
- if(n->type->sym->opackage != nil)
- a->sym = pkglookup(a->sym->name, n->type->sym->opackage);
+ if(n->type->sym->package != nil)
+ a->sym = pkglookup(a->sym->name, n->type->sym->package);
}
switch(n->class) {
Bputc(b, t); /* type */
Bputc(b, s->sym); /* sym */
- for(n=s->opackage; *n; n++)
+ for(n=s->package; *n; n++)
Bputc(b, *n);
Bputdot(b);
for(n=s->name; *n; n++)
}
// avoided repeated calculations, errors
- if(eqtype(n->type, t)) {
+ if(cvttype(n->type, t)) {
n->type = t;
return;
}
}
// if already has non-ideal type, cannot change implicitly
- if(n->type->etype != TIDEAL && n->type->etype != TNIL && !explicit)
- goto bad;
+ if(!explicit) {
+ switch(n->type->etype) {
+ case TIDEAL:
+ case TNIL:
+ break;
+ case TSTRING:
+ if(n->type == idealstring)
+ break;
+ // fall through
+ default:
+ goto bad;
+ }
+ }
switch(ct) {
default:
switch(TUP(n->op, v.ctype)) {
default:
- yyerror("illegal constant expression %O %T %d", n->op, nl->type, v.ctype);
+ yyerror("illegal constant expression %O %T", n->op, nl->type);
return;
case TUP(OPLUS, CTINT):
*n = *nl;
n->val = v;
- // lose type name if any:
- // type T int
- // const A T = 1;
- // A+0 has type int, not T.
- n->type = types[n->type->etype];
-
// check range.
lno = lineno;
lineno = n->lineno;
snprint(buf, sizeof(buf), "%#hT·%s", t0, nsym->name);
//print("methodname %s\n", buf);
- return pkglookup(buf, s->opackage);
+ return pkglookup(buf, s->package);
bad:
yyerror("illegal <this> type: %T", t);
a->otype = b->otype;
a->oconst = b->oconst;
a->package = b->package;
- a->opackage = b->opackage;
a->lexical = b->lexical;
a->undef = b->undef;
a->vargen = b->vargen;
s = l->sym;
if(s == S)
goto no;
- if(strcmp(s->opackage, "unsafe") != 0)
+ if(strcmp(s->package, "unsafe") != 0)
goto no;
if(strcmp(s->name, "Sizeof") == 0) {
{
Sym *s;
- renamepkg(ss);
-
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 */
- s->opackage = ss->osym->name;
if(exportname(ss->sym->name))
s->export = 1;
else
n = nod(OIMPORT, N, N);
n->sym = lookup(name);
n->psym = lookup(pkg);
- n->osym = n->psym;
- renamepkg(n);
s = importsym(n, LATYPE);
if(s->otype == T) {
s = importsym(ss, LNAME);
if(s->oname != N) {
- if(eqtype(t, s->oname->type))
+ if(cvttype(t, s->oname->type))
return;
warn("redeclare import var %S from %T to %T",
s, s->oname->type, t);
s = importsym(ss, LATYPE);
if(s->otype != T) {
- if(eqtype(t, s->otype))
+ if(cvttype(t, s->otype))
return;
if(s->otype->etype != TFORW) {
- warn("redeclare import type %S from %T to %T",
+ warn("redeclare import type %S from %lT to %lT",
s, s->otype, t);
s->otype = typ(0);
}
}
}
-
-
-void
-renamepkg(Node *n)
-{
- if(n->psym == pkgimportname)
- if(pkgmyname != S)
- n->psym = pkgmyname;
-}
Node* outer; // outer PPARAMREF in nested closure
Node* closure; // ONAME/PHEAP <-> ONAME/PPARAMREF
- Sym* osym; // import
Sym* psym; // import
Sym* sym; // various
int32 vargen; // unique name for OTYPE/ONAME
uchar uniq; // imbedded field name first found
uchar siggen; // signature generated
- char* opackage; // original package name
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
vlong offset; // stack location if automatic
int32 lexical;
int32 vargen; // unique variable number
EXTERN uchar okforeq[NTYPE];
EXTERN uchar okforadd[NTYPE];
EXTERN uchar okforand[NTYPE];
+EXTERN Type* idealstring;
EXTERN Mpint* minintval[NTYPE];
EXTERN Mpint* maxintval[NTYPE];
uint32 stringhash(char*);
Sym* lookup(char*);
Sym* pkglookup(char*, char*);
+Sym* opkglookup(char*, char*);
+void importdot(Sym*);
void yyerror(char*, ...);
void warn(char*, ...);
void fatal(char*, ...);
Type* methtype(Type*);
Sym* signame(Type*);
int eqtype(Type*, Type*);
+int cvttype(Type*, Type*);
int eqtypenoname(Type*, Type*);
void argtype(Node*, Type*);
int eqargs(Type*, Type*);
/*
* export.c
*/
-void renamepkg(Node*);
+void renameimports(void);
void autoexport(Sym*);
int exportname(char*);
void exportsym(Sym*);
%%
file:
- package import_there imports oxdcl_list
+ loadsys
+ package
+ imports
+ oxdcl_list
{
if(debug['f'])
frame(1);
{
yyerror("package statement must be first");
mkpackage("main");
- cannedimports("sys.6", sysimport);
}
| LPACKAGE sym
{
mkpackage($2->name);
+ }
+
+/*
+ * this loads the definitions for the sys functions,
+ * so that the compiler can generate calls to them,
+ * but does not make the name "sys" visible as a package.
+ */
+loadsys:
+ {
cannedimports("sys.6", sysimport);
}
+ import_package
+ import_there
+ {
+ pkgimportname = S;
+ }
imports:
| imports import
| LIMPORT '(' ')'
import_stmt:
- import_here import_package import_there
+ import_here import_package import_there import_done
import_here:
LLITERAL
{
// import with original name
+ pkgimportname = S;
pkgmyname = S;
importfile(&$1);
}
| sym LLITERAL
{
// import with given name
+ pkgimportname = S;
pkgmyname = $1;
- pkgmyname->lexical = LPACK;
importfile(&$2);
}
| '.' LLITERAL
{
- // import with my name
- pkgmyname = lookup(package);
+ // import into my name space
+ pkgmyname = lookup(".");
importfile(&$2);
}
LPACKAGE sym
{
pkgimportname = $2;
-
if(strcmp($2->name, "main") == 0)
yyerror("cannot import package main");
-
- // if we are not remapping the package name
- // then the imported package name is LPACK
- if(pkgmyname == S)
- pkgimportname->lexical = LPACK;
}
import_there:
{
checkimports();
unimportfile();
- pkgimportname = S;
}
| LIMPORT '$' '$' hidden_import_list '$' '$'
{
checkimports();
}
+import_done:
+ {
+ Sym *import, *my;
+
+ import = pkgimportname;
+ my = pkgmyname;
+ pkgmyname = S;
+ pkgimportname = S;
+
+ if(import == S)
+ break;
+ if(my == S)
+ my = import;
+ if(my->name[0] == '.') {
+ importdot(import);
+ break;
+ }
+
+ // In order to allow multifile packages to use type names
+ // that are the same as the package name (i.e. go/parser
+ // is package parser and has a type called parser), we have
+ // to not bother trying to declare the package if it is our package.
+ // TODO(rsc): Is there a better way to tell if the package is ours?
+ if(my == import && strcmp(import->name, package) == 0)
+ break;
+
+ if(my->lexical != LNAME || my->oname != N || my->otype != T) {
+ // 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)
+ yyerror("redeclaration of %S by import", my);
+ }
+ my->lexical = LPACK;
+ my->opack = import->name;
+ }
+
hidden_import_list:
{
defercheckwidth();
lpack:
LPACK
{
- context = $1->name;
+ context = $1->opack;
+ }
+/*
+ * adding this would enable gri's nested package idea
+ *
+| lpack '.' LPACK
+ {
+ context = $3->opack;
}
+ */
laconst:
LACONST
sym1 '.' sym2
{
$$ = nod(OIMPORT, N, N);
- $$->osym = $1;
$$->psym = $1;
$$->sym = $3;
}
s = pkglookup(s->name, context);
if(s->lexical == LIGNORE)
goto l0;
- if(!exportname(s->name) && strcmp(package, s->opackage) != 0)
+ if(!exportname(s->name) && strcmp(package, s->package) != 0)
s = pkglookup(s->name, ".private");
}
"string", LBASETYPE, TSTRING,
"any", LBASETYPE, TANY,
- "sys", LPACK, Txxx,
"break", LBREAK, Txxx,
"case", LCASE, Txxx,
lex = syms[i].lexical;
s = lookup(syms[i].name);
s->lexical = lex;
+ s->package = package;
if(lex != LBASETYPE)
continue;
types[etype] = t;
s->otype = t;
}
+
+ // 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").
+ // this is the ideal form
+ // (the type of x in const x = "hello").
+ // TODO(rsc): this may need some more thought.
+ idealstring = typ(TSTRING);
}
struct
}
// redefine all names to be this package
- package = pkg;
for(h=0; h<NHASH; h++)
- for(s = hash[h]; s != S; s = s->link) {
- s->package = package;
- s->opackage = package;
- }
+ for(s = hash[h]; s != S; s = s->link)
+ if(s->package == package)
+ s->package = pkg;
+ package = pkg;
// declare this name as a package
- lookup(package)->lexical = LPACK;
+ s = lookup(package);
+ s->lexical = LPACK;
+ s->opack = s->name;
if(outfile == nil) {
p = strrchr(infile, '/');
if(s->name[0] != c)
continue;
if(strcmp(s->name, p) == 0)
- if(strcmp(s->package, package) == 0)
+ if(s->package && strcmp(s->package, package) == 0)
return s;
}
s = mal(sizeof(*s));
s->lexical = LNAME;
s->name = mal(strlen(p)+1);
- s->opackage = package;
s->package = package;
strcpy(s->name, p);
if(s->name[0] != c)
continue;
if(strcmp(s->name, p) == 0)
- if(strcmp(s->package, k) == 0)
+ if(s->package && strcmp(s->package, k) == 0)
return s;
}
// botch - should probably try to reuse the pkg string
s->package = mal(strlen(k)+1);
- s->opackage = s->package;
strcpy(s->package, k);
s->link = hash[h];
return s;
}
+// find all the symbols in package opkg
+// and make them available in the current package
+void
+importdot(Sym *opkg)
+{
+ Sym *s, *s1;
+ uint32 h;
+ int c;
+
+ if(strcmp(opkg->name, package) == 0)
+ return;
+
+ c = opkg->name[0];
+ for(h=0; h<NHASH; h++) {
+ for(s = hash[h]; s != S; s = s->link) {
+ if(s->package[0] != c)
+ continue;
+ if(strcmp(s->package, opkg->name) != 0)
+ continue;
+ s1 = lookup(s->name);
+ if(s1->oname != N || s1->otype != T) {
+ yyerror("redeclaration of %S during import", s1);
+ continue;
+ }
+ s1->lexical = s->lexical;
+ s1->oname = s->oname;
+ s1->otype = s->otype;
+ }
+ }
+}
+
void
gethunk(void)
{
Sconv(Fmt *fp)
{
Sym *s;
- char *opk, *pkg, *nam;
+ char *pkg, *nam;
s = va_arg(fp->args, Sym*);
if(s == S) {
pkg = "<nil>";
nam = pkg;
- opk = pkg;
- if(s->opackage != nil)
- opk = s->opackage;
if(s->package != nil)
pkg = s->package;
if(s->name != nil)
nam = s->name;
if(!(fp->flags & FmtShort))
- if(strcmp(opk, package) != 0 || (fp->flags & FmtLong)) {
- fmtprint(fp, "%s.%s", opk, nam);
+ if(strcmp(pkg, package) != 0 || (fp->flags & FmtLong)) {
+ fmtprint(fp, "%s.%s", pkg, nam);
return 0;
}
fmtstrcpy(fp, nam);
fmtprint(fp, "%hS", s);
else
fmtprint(fp, "%lS", s);
- if(strcmp(s->opackage, package) == 0)
+ if(strcmp(s->package, package) == 0)
if(s->otype != t || (!s->export && !s->imported)) {
fmtprint(fp, "·%s", filename);
if(t->vargen)
}
int
-eqtype1(Type *t1, Type *t2, int d)
+eqtype1(Type *t1, Type *t2, int d, int names)
{
if(d >= 10)
return 1;
return 0;
if(t1->etype != t2->etype)
return 0;
+ if(names && t1->etype != TFIELD && t1->sym && t2->sym && t1 != t2)
+ return 0;
switch(t1->etype) {
case TINTER:
case TSTRUCT:
t1 = t1->type;
t2 = t2->type;
for(;;) {
- if(!eqtype1(t1, t2, d+1))
+ if(!eqtype1(t1, t2, d+1, names))
return 0;
if(t1 == T)
return 1;
return 0;
if(ta->etype != TFIELD || tb->etype != TFIELD)
return 0;
- if(!eqtype1(ta->type, tb->type, d+1))
+ if(!eqtype1(ta->type, tb->type, d+1, names))
return 0;
ta = ta->down;
tb = tb->down;
break;
return 0;
}
- return eqtype1(t1->type, t2->type, d+1);
+ return eqtype1(t1->type, t2->type, d+1, names);
}
int
eqtype(Type *t1, Type *t2)
{
- return eqtype1(t1, t2, 0);
+ return eqtype1(t1, t2, 0, 1);
+}
+
+int
+cvttype(Type *t1, Type *t2)
+{
+ return eqtype1(t1, t2, 0, 0);
}
int
if(t1 == T || t2 == T || t1->etype != TSTRUCT || t2->etype != TSTRUCT)
return eqtype(t1, t2);
-
t1 = t1->type;
t2 = t2->type;
for(;;) {
if(u->etype == TINTER) {
for(f=u->type; f!=T; f=f->down) {
- if(!exportname(f->sym->name) && strcmp(f->sym->opackage, package) != 0)
+ if(!exportname(f->sym->name) && strcmp(f->sym->package, package) != 0)
continue;
if(f->sym->uniq)
continue;
u = methtype(t);
if(u != T) {
for(f=u->method; f!=T; f=f->down) {
- if(!exportname(f->sym->name) && strcmp(f->sym->opackage, package) != 0)
+ if(!exportname(f->sym->name) && strcmp(f->sym->package, package) != 0)
continue;
if(f->sym->uniq)
continue;
break;
}
- if(t == T) {
+ if(t == T)
t = n->left->type;
- // throw away name:
- // type MyInt int
- // var x MyInt = 0;
- // -x has type int, not MyInt.
- if(t != T)
- t = types[t->etype];
- }
n->type = t;
goto ret;
return;
// nil conversion
- if(eqtype(t, l->type)) {
+ if(cvttype(t, l->type)) {
if(l->op != ONAME) {
indir(n, l);
n->type = t;