]> Cypherpunks repositories - gostls13.git/commitdiff
- fixed another export bug
authorRobert Griesemer <gri@golang.org>
Tue, 5 Aug 2008 22:20:58 +0000 (15:20 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 5 Aug 2008 22:20:58 +0000 (15:20 -0700)
- more self-verification code

R=r
OCL=13894
CL=13894

usr/gri/gosrc/export.go
usr/gri/gosrc/globals.go
usr/gri/gosrc/import.go
usr/gri/gosrc/parser.go
usr/gri/gosrc/printer.go
usr/gri/gosrc/test/d.go
usr/gri/gosrc/universe.go
usr/gri/gosrc/verifier.go

index 3a0a6bfa862e51ea5b88120a9e256247196b8e2e..cccb33bcbfc758a90d15b69e8a2bf9b010085f06 100755 (executable)
@@ -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";
index 81e24aace4026dbe9149b65ef20d8cbafaafc7de..3624ede13a6b7363cb64238219c8e662f67e8311 100644 (file)
@@ -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
 }
index 920b98be77f203dd17e6c4dec5b68439dcba7e3d..101b51416bb49805405a4fcd103d017bb4a3917d 100755 (executable)
@@ -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";
index 10a0563c59605fa303fd0ede4bebff497cc3edbb..503a4cf51ec638de9d281b66281dad9412163db4 100644 (file)
@@ -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();
index d4b3779c234e33bac898599cfb1eb3af02544800..54c510c37abe4fe879ab02cb82797fb5618709a7 100755 (executable)
@@ -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";
 }
index 540a03d71e83b79f70216b1dc11494038c6488d2..e9d87e837475d99ab4d66ad3290ace3cad44a028 100644 (file)
@@ -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
index 0de2c69ea649c9282a45abb83587dc75f24be529..c167e67d07abbd0f7495c4d54d3e5334e404781e 100755 (executable)
@@ -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;
 }
index af4eca116b098c6a6d947146eb3304552b902110..daadc627338118200d01a6e77264bef935956cd6 100644 (file)
@@ -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);
+}