Commit 28547615 authored by Robert Griesemer's avatar Robert Griesemer

- fixed another export bug

- more self-verification code

R=r
OCL=13894
CL=13894
parent f7f6329e
...@@ -124,7 +124,9 @@ func (E *Exporter) WriteScope(scope *Globals.Scope) { ...@@ -124,7 +124,9 @@ func (E *Exporter) WriteScope(scope *Globals.Scope) {
} }
for p := scope.entries.first; p != nil; p = p.next { 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); E.WriteObject(nil);
...@@ -158,7 +160,8 @@ func (E *Exporter) WriteType(typ *Globals.Type) { ...@@ -158,7 +160,8 @@ func (E *Exporter) WriteType(typ *Globals.Type) {
if !typ.obj.exported { if !typ.obj.exported {
// the type is invisible (it's identifier is not exported) // the type is invisible (it's identifier is not exported)
// prepend "." to the identifier to make it an illegal // 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; ident = "." + ident;
} }
} }
...@@ -170,17 +173,14 @@ func (E *Exporter) WriteType(typ *Globals.Type) { ...@@ -170,17 +173,14 @@ func (E *Exporter) WriteType(typ *Globals.Type) {
} }
switch typ.form { switch typ.form {
case Type.ALIAS: case Type.ALIAS, Type.MAP:
E.WriteType(typ.aux);
E.WriteType(typ.elt); E.WriteType(typ.elt);
case Type.ARRAY: case Type.ARRAY:
E.WriteInt(typ.len_); E.WriteInt(typ.len_);
E.WriteType(typ.elt); E.WriteType(typ.elt);
case Type.MAP:
E.WriteType(typ.key);
E.WriteType(typ.elt);
case Type.CHANNEL: case Type.CHANNEL:
E.WriteInt(typ.flags); E.WriteInt(typ.flags);
E.WriteType(typ.elt); E.WriteType(typ.elt);
...@@ -262,12 +262,7 @@ func (E *Exporter) Export(comp* Globals.Compilation, file_name string) { ...@@ -262,12 +262,7 @@ func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
// export package 0 // export package 0
pkg := comp.pkg_list[0]; pkg := comp.pkg_list[0];
E.WritePackage(pkg); E.WritePackage(pkg);
for p := pkg.scope.entries.first; p != nil; p = p.next { E.WriteScope(pkg.scope);
if p.obj.exported {
E.WriteObject(p.obj);
}
}
E.WriteObject(nil);
if E.debug { if E.debug {
print "\n(", E.buf_pos, " bytes)\n"; print "\n(", E.buf_pos, " bytes)\n";
......
...@@ -30,7 +30,7 @@ export type Type struct { ...@@ -30,7 +30,7 @@ export type Type struct {
size int; // in bytes size int; // in bytes
len_ int; // array length, no. of parameters (w/o recv) len_ int; // array length, no. of parameters (w/o recv)
obj *Object; // primary type object or NULL 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 elt *Type; // aliases, arrays, maps, channels, pointers
scope *Scope; // structs, interfaces, functions scope *Scope; // structs, interfaces, functions
} }
......
...@@ -140,23 +140,26 @@ func (I *Importer) ReadPackage() *Globals.Package { ...@@ -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 { if I.debug {
print " {"; print " {";
} }
scope := Globals.NewScope(nil);
obj := I.ReadObject(); obj := I.ReadObject();
for obj != nil { 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(); obj = I.ReadObject();
} }
if I.debug { if I.debug {
print " }"; print " }";
} }
return scope;
} }
...@@ -191,27 +194,26 @@ func (I *Importer) ReadType() *Globals.Type { ...@@ -191,27 +194,26 @@ func (I *Importer) ReadType() *Globals.Type {
I.type_ref++; I.type_ref++;
switch (typ.form) { switch (typ.form) {
case Type.ALIAS: case Type.ALIAS, Type.MAP:
typ.aux = I.ReadType();
typ.elt = I.ReadType(); typ.elt = I.ReadType();
case Type.ARRAY: case Type.ARRAY:
typ.len_ = I.ReadInt(); typ.len_ = I.ReadInt();
typ.elt = I.ReadType(); typ.elt = I.ReadType();
case Type.MAP:
typ.key = I.ReadType();
typ.elt = I.ReadType();
case Type.CHANNEL: case Type.CHANNEL:
typ.flags = I.ReadInt(); typ.flags = I.ReadInt();
typ.elt = I.ReadType(); typ.elt = I.ReadType();
case Type.FUNCTION: case Type.FUNCTION:
typ.flags = I.ReadInt(); typ.flags = I.ReadInt();
typ.scope = I.ReadScope(); typ.scope = Globals.NewScope(nil);
I.ReadScope(typ.scope, false);
case Type.STRUCT, Type.INTERFACE: case Type.STRUCT, Type.INTERFACE:
typ.scope = I.ReadScope(); typ.scope = Globals.NewScope(nil);
I.ReadScope(typ.scope, false);
case Type.POINTER, Type.REFERENCE: case Type.POINTER, Type.REFERENCE:
typ.elt = I.ReadType(); typ.elt = I.ReadType();
...@@ -241,6 +243,7 @@ func (I *Importer) ReadObject() *Globals.Object { ...@@ -241,6 +243,7 @@ func (I *Importer) ReadObject() *Globals.Object {
ident := I.ReadString(); ident := I.ReadString();
obj := Globals.NewObject(0, tag, ident); obj := Globals.NewObject(0, tag, ident);
obj.exported = true;
obj.typ = I.ReadType(); obj.typ = I.ReadType();
switch (tag) { switch (tag) {
...@@ -290,13 +293,7 @@ func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals. ...@@ -290,13 +293,7 @@ func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.
// import package // import package
pkg := I.ReadPackage(); pkg := I.ReadPackage();
{ obj := I.ReadObject(); I.ReadScope(pkg.scope, true);
for obj != nil {
obj.pnolev = pkg.obj.pnolev;
pkg.scope.InsertImport(obj);
obj = I.ReadObject();
}
}
if I.debug { if I.debug {
print "\n(", I.buf_pos, " bytes)\n"; print "\n(", I.buf_pos, " bytes)\n";
......
...@@ -147,74 +147,82 @@ func (P *Parser) Declare(obj *Globals.Object) { ...@@ -147,74 +147,82 @@ func (P *Parser) Declare(obj *Globals.Object) {
func MakeFunctionType(sig *Globals.Scope, p0, r0 int, check_recv bool) *Globals.Type { func MakeFunctionType(sig *Globals.Scope, p0, r0 int, check_recv bool) *Globals.Type {
// Determine if we have a receiver or not. // Determine if we have a receiver or not.
// TODO do we still need this? // TODO do we still need this?
if p0 > 0 && check_recv { if p0 > 0 && check_recv {
// method // method
if p0 != 1 { if p0 != 1 {
panic "p0 != 1"; panic "p0 != 1";
}
} }
}
typ := Globals.NewType(Type.FUNCTION); typ := Globals.NewType(Type.FUNCTION);
if p0 == 0 { if p0 == 0 {
typ.flags = 0; typ.flags = 0;
} else { } else {
typ.flags = Type.RECV; typ.flags = Type.RECV;
} }
typ.len_ = r0 - p0; typ.len_ = r0 - p0;
typ.scope = sig; typ.scope = sig;
return typ;
// 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 { func (P *Parser) DeclareFunc(ident string, typ *Globals.Type) *Globals.Object {
// determine scope // determine scope
scope := P.top_scope; scope := P.top_scope;
if typ.flags & Type.RECV != 0 { if typ.flags & Type.RECV != 0 {
// method - declare in corresponding struct // method - declare in corresponding struct
if typ.scope.entries.len_ < 1 { if typ.scope.entries.len_ < 1 {
panic "no recv in signature?"; panic "no recv in signature?";
} }
recv_typ := typ.scope.entries.first.obj.typ; recv_typ := typ.scope.entries.first.obj.typ;
if recv_typ.form == Type.POINTER { if recv_typ.form == Type.POINTER {
recv_typ = recv_typ.elt; recv_typ = recv_typ.elt;
} }
scope = recv_typ.scope; scope = recv_typ.scope;
} }
// declare the function // declare the function
obj := scope.Lookup(ident); obj := scope.Lookup(ident);
if obj == nil { if obj == nil {
obj = Globals.NewObject(-1, Object.FUNC, ident); obj = Globals.NewObject(-1, Object.FUNC, ident);
obj.typ = typ; obj.typ = typ;
// TODO do we need to set the primary type? probably... // TODO do we need to set the primary type? probably...
P.DeclareInScope(scope, obj); P.DeclareInScope(scope, obj);
return obj; return obj;
} }
// obj != NULL: possibly a forward declaration. // obj != NULL: possibly a forward declaration.
if (obj.kind != Object.FUNC) { if obj.kind != Object.FUNC {
P.Error(-1, `"` + ident + `" is declared already`); P.Error(-1, `"` + ident + `" is declared already`);
// Continue but do not insert this function into the scope. // Continue but do not insert this function into the scope.
obj = Globals.NewObject(-1, Object.FUNC, ident); obj = Globals.NewObject(-1, Object.FUNC, ident);
obj.typ = typ; obj.typ = typ;
// TODO do we need to set the prymary type? probably... // TODO do we need to set the primary type? probably...
return obj; return obj;
} }
// We have a function with the same name. // We have a function with the same name.
/* /*
if (!EqualTypes(type, obj->type())) { if !EqualTypes(type, obj->type()) {
this->Error("type of \"%s\" does not match its forward declaration", name.cstr()); this->Error("type of \"%s\" does not match its forward declaration", name.cstr());
// Continue but do not insert this function into the scope. // Continue but do not insert this function into the scope.
NewObject(Object::FUNC, name); NewObject(Object::FUNC, name);
obj->set_type(type); obj->set_type(type);
return obj; return obj;
} }
*/ */
// We have a matching forward declaration. Use it. // We have a matching forward declaration. Use it.
return obj; return obj;
} }
...@@ -521,7 +529,7 @@ func (P *Parser) ParseAnonymousSignature() *Globals.Type { ...@@ -521,7 +529,7 @@ func (P *Parser) ParseAnonymousSignature() *Globals.Type {
if P.tok == Scanner.PERIOD { if P.tok == Scanner.PERIOD {
p0 = sig.entries.len_; 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") P.Error(recv_pos, "must have exactly one receiver")
panic "UNIMPLEMENTED (ParseAnonymousSignature)"; panic "UNIMPLEMENTED (ParseAnonymousSignature)";
// TODO do something useful here // TODO do something useful here
...@@ -561,7 +569,7 @@ func (P *Parser) ParseNamedSignature() (name string, typ *Globals.Type) { ...@@ -561,7 +569,7 @@ func (P *Parser) ParseNamedSignature() (name string, typ *Globals.Type) {
recv_pos := P.pos; recv_pos := P.pos;
P.ParseParameters(); P.ParseParameters();
p0 = sig.entries.len_; p0 = sig.entries.len_;
if (P.semantic_checks && p0 != 1) { if P.semantic_checks && p0 != 1 {
print "p0 = ", p0, "\n"; print "p0 = ", p0, "\n";
P.Error(recv_pos, "must have exactly one receiver") P.Error(recv_pos, "must have exactly one receiver")
panic "UNIMPLEMENTED (ParseNamedSignature)"; panic "UNIMPLEMENTED (ParseNamedSignature)";
...@@ -651,7 +659,7 @@ func (P *Parser) ParseMapType() *Globals.Type { ...@@ -651,7 +659,7 @@ func (P *Parser) ParseMapType() *Globals.Type {
P.Expect(Scanner.MAP); P.Expect(Scanner.MAP);
P.Expect(Scanner.LBRACK); P.Expect(Scanner.LBRACK);
typ := Globals.NewType(Type.MAP); typ := Globals.NewType(Type.MAP);
typ.key = P.ParseVarType(); typ.aux = P.ParseVarType();
P.Expect(Scanner.RBRACK); P.Expect(Scanner.RBRACK);
typ.elt = P.ParseVarType(); typ.elt = P.ParseVarType();
P.Ecart(); P.Ecart();
...@@ -1617,7 +1625,7 @@ func (P *Parser) ParseImportSpec() { ...@@ -1617,7 +1625,7 @@ func (P *Parser) ParseImportSpec() {
obj = P.ParseIdentDecl(Object.PACKAGE); 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 // TODO eventually the scanner should strip the quotes
pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes
pkg := Import.Import(P.comp, pkg_name); pkg := Import.Import(P.comp, pkg_name);
...@@ -1699,6 +1707,11 @@ func (P *Parser) ParseTypeSpec(exported bool) { ...@@ -1699,6 +1707,11 @@ func (P *Parser) ParseTypeSpec(exported bool) {
if typ != nil { if typ != nil {
if make_alias { if make_alias {
alias := Globals.NewType(Type.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; alias.elt = typ;
typ = alias; typ = alias;
} }
...@@ -1706,6 +1719,14 @@ func (P *Parser) ParseTypeSpec(exported bool) { ...@@ -1706,6 +1719,14 @@ func (P *Parser) ParseTypeSpec(exported bool) {
if typ.obj == nil { if typ.obj == nil {
typ.obj = obj; // primary type object 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(); P.Ecart();
......
...@@ -109,7 +109,7 @@ func (P *Printer) PrintScope(scope *Globals.Scope, delta int) { ...@@ -109,7 +109,7 @@ func (P *Printer) PrintScope(scope *Globals.Scope, delta int) {
} else { } else {
n = 0; n = 0;
for p := scope.entries.first; p != nil; p = p.next { for p := scope.entries.first; p != nil; p = p.next {
if p.obj.exported { if p.obj.exported && !IsAnonymous(p.obj.ident) {
n++; n++;
} }
} }
...@@ -120,7 +120,7 @@ func (P *Printer) PrintScope(scope *Globals.Scope, delta int) { ...@@ -120,7 +120,7 @@ func (P *Printer) PrintScope(scope *Globals.Scope, delta int) {
if n > 0 { if n > 0 {
P.level += delta; P.level += delta;
for p := scope.entries.first; p != nil; p = p.next { 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.PrintIndent();
P.PrintObjectStruct(p.obj); P.PrintObjectStruct(p.obj);
} }
...@@ -200,7 +200,12 @@ func (P *Printer) PrintTypeStruct(typ *Globals.Type) { ...@@ -200,7 +200,12 @@ func (P *Printer) PrintTypeStruct(typ *Globals.Type) {
case Type.ALIAS: case Type.ALIAS:
P.PrintType(typ.elt); P.PrintType(typ.elt);
if typ.aux != typ.elt {
print " /* ";
P.PrintType(typ.aux);
print " */";
}
case Type.ARRAY: case Type.ARRAY:
print "[]"; print "[]";
P.PrintType(typ.elt); P.PrintType(typ.elt);
...@@ -217,7 +222,7 @@ func (P *Printer) PrintTypeStruct(typ *Globals.Type) { ...@@ -217,7 +222,7 @@ func (P *Printer) PrintTypeStruct(typ *Globals.Type) {
case Type.MAP: case Type.MAP:
print "map ["; print "map [";
P.PrintType(typ.key); P.PrintType(typ.aux);
print "] "; print "] ";
P.PrintType(typ.elt); P.PrintType(typ.elt);
...@@ -263,4 +268,5 @@ export func PrintObject(comp *Globals.Compilation, obj *Globals.Object, print_al ...@@ -263,4 +268,5 @@ export func PrintObject(comp *Globals.Compilation, obj *Globals.Object, print_al
var P Printer; var P Printer;
(&P).Init(comp, print_all); (&P).Init(comp, print_all);
(&P).PrintObjectStruct(obj); (&P).PrintObjectStruct(obj);
print "\n";
} }
...@@ -13,3 +13,7 @@ export type T2 struct { ...@@ -13,3 +13,7 @@ export type T2 struct {
export func (obj *T2) M1(u, v float) { 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
...@@ -71,6 +71,7 @@ func DeclType(form int, ident string, size int) *Globals.Type { ...@@ -71,6 +71,7 @@ func DeclType(form int, ident string, size int) *Globals.Type {
func DeclAlias(ident string, typ *Globals.Type) *Globals.Type { func DeclAlias(ident string, typ *Globals.Type) *Globals.Type {
alias := Globals.NewType(Type.ALIAS); alias := Globals.NewType(Type.ALIAS);
alias.aux = typ;
alias.elt = typ; alias.elt = typ;
return DeclObj(Object.TYPE, ident, alias).typ; return DeclObj(Object.TYPE, ident, alias).typ;
} }
......
...@@ -21,12 +21,27 @@ func Error(msg string) { ...@@ -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 { if typ.obj != nil {
VerifyObject(typ.obj, 0); V.VerifyObject(typ.obj, 0);
} }
switch typ.form { switch typ.form {
...@@ -70,8 +85,14 @@ func VerifyType(typ *Globals.Type) { ...@@ -70,8 +85,14 @@ func VerifyType(typ *Globals.Type) {
} }
func VerifyObject(obj *Globals.Object, pnolev int) { func (V *Verifier) VerifyObject(obj *Globals.Object, pnolev int) {
VerifyType(obj.typ); 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 { switch obj.kind {
case Object.CONST: case Object.CONST:
...@@ -92,20 +113,46 @@ func VerifyObject(obj *Globals.Object, pnolev int) { ...@@ -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 { 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) { func (V *Verifier) VerifyPackage(pkg *Globals.Package, pno int) {
VerifyObject(pkg.obj, 0); 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++ { 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);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment