mirror of
https://github.com/golang/go
synced 2024-11-22 07:34:40 -07:00
- fixed another export bug
- more self-verification code R=r OCL=13894 CL=13894
This commit is contained in:
parent
f7f6329e26
commit
28547615ce
@ -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";
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -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?";
|
||||
// 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;
|
||||
}
|
||||
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;
|
||||
|
||||
// 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();
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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 VerifyType(typ *Globals.Type) {
|
||||
func (V *Verifier) VerifyObject(obj *Globals.Object, pnolev int);
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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++ {
|
||||
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) {
|
||||
for i := 0; i < comp.pkg_ref; i++ {
|
||||
VerifyPackage(comp.pkg_list[i], i);
|
||||
}
|
||||
V := new(Verifier);
|
||||
V.Verify(comp);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user