summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2008-08-05 15:20:58 -0700
committerRobert Griesemer <gri@golang.org>2008-08-05 15:20:58 -0700
commit21c8ae4c9e25eb4992e62592c1e32fbd6146891d (patch)
treed3e83cf9c11b6941e195e50abe999beea11ef568
parent0c981e17f35a565ee51ea3f32a249bb62d4a474e (diff)
downloadgolang-21c8ae4c9e25eb4992e62592c1e32fbd6146891d.tar.gz
- fixed another export bug
- more self-verification code R=r OCL=13894 CL=13894
-rwxr-xr-xusr/gri/gosrc/export.go21
-rw-r--r--usr/gri/gosrc/globals.go2
-rwxr-xr-xusr/gri/gosrc/import.go35
-rw-r--r--usr/gri/gosrc/parser.go155
-rwxr-xr-xusr/gri/gosrc/printer.go14
-rw-r--r--usr/gri/gosrc/test/d.go4
-rwxr-xr-xusr/gri/gosrc/universe.go1
-rw-r--r--usr/gri/gosrc/verifier.go69
8 files changed, 186 insertions, 115 deletions
diff --git a/usr/gri/gosrc/export.go b/usr/gri/gosrc/export.go
index 3a0a6bfa8..cccb33bcb 100755
--- a/usr/gri/gosrc/export.go
+++ b/usr/gri/gosrc/export.go
@@ -124,7 +124,9 @@ func (E *Exporter) WriteScope(scope *Globals.Scope) {
}
for p := scope.entries.first; p != nil; p = p.next {
- E.WriteObject(p.obj);
+ if p.obj.exported {
+ E.WriteObject(p.obj);
+ }
}
E.WriteObject(nil);
@@ -158,7 +160,8 @@ func (E *Exporter) WriteType(typ *Globals.Type) {
if !typ.obj.exported {
// the type is invisible (it's identifier is not exported)
// prepend "." to the identifier to make it an illegal
- // identifier and thus invisible in Go source code
+ // identifier for importing packages and thus inaccessible
+ // from those package's source code
ident = "." + ident;
}
}
@@ -170,17 +173,14 @@ func (E *Exporter) WriteType(typ *Globals.Type) {
}
switch typ.form {
- case Type.ALIAS:
+ case Type.ALIAS, Type.MAP:
+ E.WriteType(typ.aux);
E.WriteType(typ.elt);
case Type.ARRAY:
E.WriteInt(typ.len_);
E.WriteType(typ.elt);
- case Type.MAP:
- E.WriteType(typ.key);
- E.WriteType(typ.elt);
-
case Type.CHANNEL:
E.WriteInt(typ.flags);
E.WriteType(typ.elt);
@@ -262,12 +262,7 @@ func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
// export package 0
pkg := comp.pkg_list[0];
E.WritePackage(pkg);
- for p := pkg.scope.entries.first; p != nil; p = p.next {
- if p.obj.exported {
- E.WriteObject(p.obj);
- }
- }
- E.WriteObject(nil);
+ E.WriteScope(pkg.scope);
if E.debug {
print "\n(", E.buf_pos, " bytes)\n";
diff --git a/usr/gri/gosrc/globals.go b/usr/gri/gosrc/globals.go
index 81e24aace..3624ede13 100644
--- a/usr/gri/gosrc/globals.go
+++ b/usr/gri/gosrc/globals.go
@@ -30,7 +30,7 @@ export type Type struct {
size int; // in bytes
len_ int; // array length, no. of parameters (w/o recv)
obj *Object; // primary type object or NULL
- key *Type; // maps
+ aux *Type; // alias base type or map key
elt *Type; // aliases, arrays, maps, channels, pointers
scope *Scope; // structs, interfaces, functions
}
diff --git a/usr/gri/gosrc/import.go b/usr/gri/gosrc/import.go
index 920b98be7..101b51416 100755
--- a/usr/gri/gosrc/import.go
+++ b/usr/gri/gosrc/import.go
@@ -140,23 +140,26 @@ func (I *Importer) ReadPackage() *Globals.Package {
}
-func (I *Importer) ReadScope() *Globals.Scope {
+func (I *Importer) ReadScope(scope *Globals.Scope, allow_multiples bool) {
if I.debug {
print " {";
}
- scope := Globals.NewScope(nil);
obj := I.ReadObject();
for obj != nil {
- scope.Insert(obj);
+ // allow_multiples is for debugging only - we should never
+ // have multiple imports where we don't expect them
+ if allow_multiples {
+ scope.InsertImport(obj);
+ } else {
+ scope.Insert(obj);
+ }
obj = I.ReadObject();
}
if I.debug {
print " }";
}
-
- return scope;
}
@@ -191,27 +194,26 @@ func (I *Importer) ReadType() *Globals.Type {
I.type_ref++;
switch (typ.form) {
- case Type.ALIAS:
+ case Type.ALIAS, Type.MAP:
+ typ.aux = I.ReadType();
typ.elt = I.ReadType();
case Type.ARRAY:
typ.len_ = I.ReadInt();
typ.elt = I.ReadType();
- case Type.MAP:
- typ.key = I.ReadType();
- typ.elt = I.ReadType();
-
case Type.CHANNEL:
typ.flags = I.ReadInt();
typ.elt = I.ReadType();
case Type.FUNCTION:
typ.flags = I.ReadInt();
- typ.scope = I.ReadScope();
+ typ.scope = Globals.NewScope(nil);
+ I.ReadScope(typ.scope, false);
case Type.STRUCT, Type.INTERFACE:
- typ.scope = I.ReadScope();
+ typ.scope = Globals.NewScope(nil);
+ I.ReadScope(typ.scope, false);
case Type.POINTER, Type.REFERENCE:
typ.elt = I.ReadType();
@@ -241,6 +243,7 @@ func (I *Importer) ReadObject() *Globals.Object {
ident := I.ReadString();
obj := Globals.NewObject(0, tag, ident);
+ obj.exported = true;
obj.typ = I.ReadType();
switch (tag) {
@@ -290,13 +293,7 @@ func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.
// import package
pkg := I.ReadPackage();
- { obj := I.ReadObject();
- for obj != nil {
- obj.pnolev = pkg.obj.pnolev;
- pkg.scope.InsertImport(obj);
- obj = I.ReadObject();
- }
- }
+ I.ReadScope(pkg.scope, true);
if I.debug {
print "\n(", I.buf_pos, " bytes)\n";
diff --git a/usr/gri/gosrc/parser.go b/usr/gri/gosrc/parser.go
index 10a0563c5..503a4cf51 100644
--- a/usr/gri/gosrc/parser.go
+++ b/usr/gri/gosrc/parser.go
@@ -147,74 +147,82 @@ func (P *Parser) Declare(obj *Globals.Object) {
func MakeFunctionType(sig *Globals.Scope, p0, r0 int, check_recv bool) *Globals.Type {
- // Determine if we have a receiver or not.
- // TODO do we still need this?
- if p0 > 0 && check_recv {
- // method
- if p0 != 1 {
- panic "p0 != 1";
+ // Determine if we have a receiver or not.
+ // TODO do we still need this?
+ if p0 > 0 && check_recv {
+ // method
+ if p0 != 1 {
+ panic "p0 != 1";
+ }
}
- }
- typ := Globals.NewType(Type.FUNCTION);
- if p0 == 0 {
- typ.flags = 0;
- } else {
- typ.flags = Type.RECV;
- }
- typ.len_ = r0 - p0;
- typ.scope = sig;
- return typ;
+
+ typ := Globals.NewType(Type.FUNCTION);
+ if p0 == 0 {
+ typ.flags = 0;
+ } else {
+ typ.flags = Type.RECV;
+ }
+ typ.len_ = r0 - p0;
+ typ.scope = sig;
+
+ // parameters are always exported (they can't be accessed w/o the function
+ // or function type being exported)
+ for p := sig.entries.first; p != nil; p = p.next {
+ p.obj.exported = true;
+ }
+
+ return typ;
}
func (P *Parser) DeclareFunc(ident string, typ *Globals.Type) *Globals.Object {
- // determine scope
- scope := P.top_scope;
- if typ.flags & Type.RECV != 0 {
- // method - declare in corresponding struct
- if typ.scope.entries.len_ < 1 {
- panic "no recv in signature?";
- }
- recv_typ := typ.scope.entries.first.obj.typ;
- if recv_typ.form == Type.POINTER {
- recv_typ = recv_typ.elt;
- }
- scope = recv_typ.scope;
- }
-
- // declare the function
- obj := scope.Lookup(ident);
- if obj == nil {
- obj = Globals.NewObject(-1, Object.FUNC, ident);
- obj.typ = typ;
- // TODO do we need to set the primary type? probably...
- P.DeclareInScope(scope, obj);
- return obj;
- }
-
- // obj != NULL: possibly a forward declaration.
- if (obj.kind != Object.FUNC) {
- P.Error(-1, `"` + ident + `" is declared already`);
- // Continue but do not insert this function into the scope.
- obj = Globals.NewObject(-1, Object.FUNC, ident);
- obj.typ = typ;
- // TODO do we need to set the prymary type? probably...
- return obj;
- }
-
- // We have a function with the same name.
- /*
- if (!EqualTypes(type, obj->type())) {
- this->Error("type of \"%s\" does not match its forward declaration", name.cstr());
- // Continue but do not insert this function into the scope.
- NewObject(Object::FUNC, name);
- obj->set_type(type);
- return obj;
- }
- */
-
- // We have a matching forward declaration. Use it.
- return obj;
+ // determine scope
+ scope := P.top_scope;
+ if typ.flags & Type.RECV != 0 {
+ // method - declare in corresponding struct
+ if typ.scope.entries.len_ < 1 {
+ panic "no recv in signature?";
+ }
+ recv_typ := typ.scope.entries.first.obj.typ;
+ if recv_typ.form == Type.POINTER {
+ recv_typ = recv_typ.elt;
+ }
+ scope = recv_typ.scope;
+ }
+
+ // declare the function
+ obj := scope.Lookup(ident);
+ if obj == nil {
+ obj = Globals.NewObject(-1, Object.FUNC, ident);
+ obj.typ = typ;
+ // TODO do we need to set the primary type? probably...
+ P.DeclareInScope(scope, obj);
+ return obj;
+ }
+
+ // obj != NULL: possibly a forward declaration.
+ if obj.kind != Object.FUNC {
+ P.Error(-1, `"` + ident + `" is declared already`);
+ // Continue but do not insert this function into the scope.
+ obj = Globals.NewObject(-1, Object.FUNC, ident);
+ obj.typ = typ;
+ // TODO do we need to set the primary type? probably...
+ return obj;
+ }
+
+ // We have a function with the same name.
+ /*
+ if !EqualTypes(type, obj->type()) {
+ this->Error("type of \"%s\" does not match its forward declaration", name.cstr());
+ // Continue but do not insert this function into the scope.
+ NewObject(Object::FUNC, name);
+ obj->set_type(type);
+ return obj;
+ }
+ */
+
+ // We have a matching forward declaration. Use it.
+ return obj;
}
@@ -521,7 +529,7 @@ func (P *Parser) ParseAnonymousSignature() *Globals.Type {
if P.tok == Scanner.PERIOD {
p0 = sig.entries.len_;
- if (P.semantic_checks && p0 != 1) {
+ if P.semantic_checks && p0 != 1 {
P.Error(recv_pos, "must have exactly one receiver")
panic "UNIMPLEMENTED (ParseAnonymousSignature)";
// TODO do something useful here
@@ -561,7 +569,7 @@ func (P *Parser) ParseNamedSignature() (name string, typ *Globals.Type) {
recv_pos := P.pos;
P.ParseParameters();
p0 = sig.entries.len_;
- if (P.semantic_checks && p0 != 1) {
+ if P.semantic_checks && p0 != 1 {
print "p0 = ", p0, "\n";
P.Error(recv_pos, "must have exactly one receiver")
panic "UNIMPLEMENTED (ParseNamedSignature)";
@@ -651,7 +659,7 @@ func (P *Parser) ParseMapType() *Globals.Type {
P.Expect(Scanner.MAP);
P.Expect(Scanner.LBRACK);
typ := Globals.NewType(Type.MAP);
- typ.key = P.ParseVarType();
+ typ.aux = P.ParseVarType();
P.Expect(Scanner.RBRACK);
typ.elt = P.ParseVarType();
P.Ecart();
@@ -1617,7 +1625,7 @@ func (P *Parser) ParseImportSpec() {
obj = P.ParseIdentDecl(Object.PACKAGE);
}
- if (P.semantic_checks && P.tok == Scanner.STRING) {
+ if P.semantic_checks && P.tok == Scanner.STRING {
// TODO eventually the scanner should strip the quotes
pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes
pkg := Import.Import(P.comp, pkg_name);
@@ -1699,6 +1707,11 @@ func (P *Parser) ParseTypeSpec(exported bool) {
if typ != nil {
if make_alias {
alias := Globals.NewType(Type.ALIAS);
+ if typ.form == Type.ALIAS {
+ alias.aux = typ.aux; // the base type
+ } else {
+ alias.aux = typ;
+ }
alias.elt = typ;
typ = alias;
}
@@ -1706,6 +1719,14 @@ func (P *Parser) ParseTypeSpec(exported bool) {
if typ.obj == nil {
typ.obj = obj; // primary type object
}
+ // if the type is exported, for now we export all fields
+ // of structs and interfaces by default
+ // TODO this needs to change eventually
+ if exported && (typ.form == Type.STRUCT || typ.form == Type.INTERFACE) {
+ for p := typ.scope.entries.first; p != nil; p = p.next {
+ p.obj.exported = true;
+ }
+ }
}
P.Ecart();
diff --git a/usr/gri/gosrc/printer.go b/usr/gri/gosrc/printer.go
index d4b3779c2..54c510c37 100755
--- a/usr/gri/gosrc/printer.go
+++ b/usr/gri/gosrc/printer.go
@@ -109,7 +109,7 @@ func (P *Printer) PrintScope(scope *Globals.Scope, delta int) {
} else {
n = 0;
for p := scope.entries.first; p != nil; p = p.next {
- if p.obj.exported {
+ if p.obj.exported && !IsAnonymous(p.obj.ident) {
n++;
}
}
@@ -120,7 +120,7 @@ func (P *Printer) PrintScope(scope *Globals.Scope, delta int) {
if n > 0 {
P.level += delta;
for p := scope.entries.first; p != nil; p = p.next {
- if P.print_all || p.obj.exported {
+ if P.print_all || p.obj.exported && !IsAnonymous(p.obj.ident) {
P.PrintIndent();
P.PrintObjectStruct(p.obj);
}
@@ -200,7 +200,12 @@ func (P *Printer) PrintTypeStruct(typ *Globals.Type) {
case Type.ALIAS:
P.PrintType(typ.elt);
-
+ if typ.aux != typ.elt {
+ print " /* ";
+ P.PrintType(typ.aux);
+ print " */";
+ }
+
case Type.ARRAY:
print "[]";
P.PrintType(typ.elt);
@@ -217,7 +222,7 @@ func (P *Printer) PrintTypeStruct(typ *Globals.Type) {
case Type.MAP:
print "map [";
- P.PrintType(typ.key);
+ P.PrintType(typ.aux);
print "] ";
P.PrintType(typ.elt);
@@ -263,4 +268,5 @@ export func PrintObject(comp *Globals.Compilation, obj *Globals.Object, print_al
var P Printer;
(&P).Init(comp, print_all);
(&P).PrintObjectStruct(obj);
+ print "\n";
}
diff --git a/usr/gri/gosrc/test/d.go b/usr/gri/gosrc/test/d.go
index 540a03d71..e9d87e837 100644
--- a/usr/gri/gosrc/test/d.go
+++ b/usr/gri/gosrc/test/d.go
@@ -13,3 +13,7 @@ export type T2 struct {
export func (obj *T2) M1(u, v float) {
}
+
+export func F0(a int, b T0) int {
+ return a + b;
+} \ No newline at end of file
diff --git a/usr/gri/gosrc/universe.go b/usr/gri/gosrc/universe.go
index 0de2c69ea..c167e67d0 100755
--- a/usr/gri/gosrc/universe.go
+++ b/usr/gri/gosrc/universe.go
@@ -71,6 +71,7 @@ func DeclType(form int, ident string, size int) *Globals.Type {
func DeclAlias(ident string, typ *Globals.Type) *Globals.Type {
alias := Globals.NewType(Type.ALIAS);
+ alias.aux = typ;
alias.elt = typ;
return DeclObj(Object.TYPE, ident, alias).typ;
}
diff --git a/usr/gri/gosrc/verifier.go b/usr/gri/gosrc/verifier.go
index af4eca116..daadc6273 100644
--- a/usr/gri/gosrc/verifier.go
+++ b/usr/gri/gosrc/verifier.go
@@ -21,12 +21,27 @@ func Error(msg string) {
}
-func VerifyObject(obj *Globals.Object, pnolev int);
+type Verifier struct {
+ comp *Globals.Compilation;
+
+ // various sets for marking the graph (and thus avoid cycles)
+ objs *map[*Globals.Object] bool;
+ typs *map[*Globals.Type] bool;
+ pkgs *map[*Globals.Package] bool;
+}
+
+
+func (V *Verifier) VerifyObject(obj *Globals.Object, pnolev int);
-func VerifyType(typ *Globals.Type) {
+func (V *Verifier) VerifyType(typ *Globals.Type) {
+ if V.typs[typ] {
+ return; // already verified
+ }
+ V.typs[typ] = true;
+
if typ.obj != nil {
- VerifyObject(typ.obj, 0);
+ V.VerifyObject(typ.obj, 0);
}
switch typ.form {
@@ -70,8 +85,14 @@ func VerifyType(typ *Globals.Type) {
}
-func VerifyObject(obj *Globals.Object, pnolev int) {
- VerifyType(obj.typ);
+func (V *Verifier) VerifyObject(obj *Globals.Object, pnolev int) {
+ if V.objs[obj] {
+ return; // already verified
+ }
+ V.objs[obj] = true;
+
+ // all objects have a non-nil type
+ V.VerifyType(obj.typ);
switch obj.kind {
case Object.CONST:
@@ -92,20 +113,46 @@ func VerifyObject(obj *Globals.Object, pnolev int) {
}
-func VerifyScope(scope *Globals.Scope) {
+func (V *Verifier) VerifyScope(scope *Globals.Scope) {
for p := scope.entries.first; p != nil; p = p.next {
- VerifyObject(p.obj, 0);
+ V.VerifyObject(p.obj, 0);
}
}
-func VerifyPackage(pkg *Globals.Package, pno int) {
- VerifyObject(pkg.obj, 0);
+func (V *Verifier) VerifyPackage(pkg *Globals.Package, pno int) {
+ if V.pkgs[pkg] {
+ return; // already verified
+ }
+ V.pkgs[pkg] = true;
+
+ V.VerifyObject(pkg.obj, pno);
+ V.VerifyScope(pkg.scope);
}
-export func Verify(comp *Globals.Compilation) {
+func (V *Verifier) Verify(comp *Globals.Compilation) {
+ // initialize Verifier
+ V.comp = comp;
+ V.objs = new(map[*Globals.Object] bool);
+ V.typs = new(map[*Globals.Type] bool);
+ V.pkgs = new(map[*Globals.Package] bool);
+
+ // verify all packages
+ filenames := new(map[string] bool);
for i := 0; i < comp.pkg_ref; i++ {
- VerifyPackage(comp.pkg_list[i], i);
+ pkg := comp.pkg_list[i];
+ // each pkg filename must appear only once
+ if filenames[pkg.file_name] {
+ Error("package filename present more then once");
+ }
+ filenames[pkg.file_name] = true;
+ V.VerifyPackage(pkg, i);
}
}
+
+
+export func Verify(comp *Globals.Compilation) {
+ V := new(Verifier);
+ V.Verify(comp);
+}