1
0
mirror of https://github.com/golang/go synced 2024-11-23 00:50:05 -07:00

- more import/export stuff

- use new export syntax

R=r
OCL=13807
CL=13807
This commit is contained in:
Robert Griesemer 2008-08-04 10:19:36 -07:00
parent 0cc772cbc0
commit 71d50b8bf9
10 changed files with 75 additions and 114 deletions

View File

@ -31,7 +31,6 @@ func Compile(comp *Globals.Compilation, file_name string) {
parser := new(Parser.Parser); parser := new(Parser.Parser);
parser.Open(comp, scanner); parser.Open(comp, scanner);
print "parsing ", file_name, "\n";
parser.ParseProgram(); parser.ParseProgram();
if parser.S.nerrors > 0 { if parser.S.nerrors > 0 {
return; return;
@ -44,7 +43,7 @@ func Compile(comp *Globals.Compilation, file_name string) {
Verifier.Verify(comp); Verifier.Verify(comp);
if comp.flags.print_export { if comp.flags.print_export {
Printer.PrintObject(comp, comp.pkgs[0].obj, false); Printer.PrintObject(comp, comp.pkg_list[0].obj, false);
} }
Export.Export(comp, file_name); Export.Export(comp, file_name);

View File

@ -137,7 +137,6 @@ func (E *Exporter) WriteObject(obj *Globals.Object) {
E.WriteString(obj.ident); E.WriteString(obj.ident);
E.WriteType(obj.typ); E.WriteType(obj.typ);
E.WritePackage(obj.pnolev);
switch obj.kind { switch obj.kind {
case Object.CONST: case Object.CONST:
@ -164,19 +163,30 @@ func (E *Exporter) WriteType(typ *Globals.Type) {
if -typ.form >= 0 { if -typ.form >= 0 {
panic "-typ.form >= 0"; // conflict with ref numbers panic "-typ.form >= 0"; // conflict with ref numbers
} }
E.WriteTypeTag(-typ.form); E.WriteTypeTag(-typ.form);
typ.ref = E.type_ref; typ.ref = E.type_ref;
E.type_ref++; E.type_ref++;
// if we have a primary type, export the type identifier and package
ident := "";
if typ.obj != nil { if typ.obj != nil {
// primary type
if typ.obj.typ != typ { if typ.obj.typ != typ {
panic "typ.obj.type() != typ"; // primary type panic "inconsistent primary type";
} }
E.WriteString(typ.obj.ident); ident = typ.obj.ident;
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
ident = "." + ident;
}
}
E.WriteString(ident);
if len(ident) > 0 {
// primary type
E.WritePackage(typ.obj.pnolev); E.WritePackage(typ.obj.pnolev);
} else {
E.WriteString("");
} }
switch typ.form { switch typ.form {
@ -215,7 +225,7 @@ func (E *Exporter) WritePackage(pno int) {
if pno < 0 { if pno < 0 {
pno = 0; pno = 0;
} }
pkg := E.comp.pkgs[pno]; pkg := E.comp.pkg_list[pno];
if pkg.ref >= 0 { if pkg.ref >= 0 {
E.WritePackageTag(pkg.ref); // package already exported E.WritePackageTag(pkg.ref); // package already exported
return; return;
@ -254,7 +264,7 @@ func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
} }
E.type_ref = Universe.types.len_; E.type_ref = Universe.types.len_;
pkg := comp.pkgs[0]; pkg := comp.pkg_list[0];
E.WritePackage(0); E.WritePackage(0);
E.WriteScope(pkg.scope, false); E.WriteScope(pkg.scope, false);

View File

@ -13,20 +13,17 @@ package Globals
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
export Object export type Object struct {
type Object struct {
exported bool; exported bool;
pos int; // source position (< 0 if unknown position) pos int; // source position (< 0 if unknown position)
kind int; kind int;
ident string; ident string;
typ *Type; typ *Type; // nil for packages
pnolev int; // >= 0: package no., <= 0: level, 0: global level of compilation pnolev int; // >= 0: package no., <= 0: function nesting level, 0: global level
scope *Scope; // which contains the object
} }
export Type export type Type struct {
type Type struct {
ref int; // for exporting only: >= 0 means already exported ref int; // for exporting only: >= 0 means already exported
form int; form int;
flags int; // channels, functions flags int; // channels, functions
@ -39,13 +36,12 @@ type Type struct {
} }
export Package export type Package struct {
type Package struct {
ref int; // for exporting only: >= 0 means already exported ref int; // for exporting only: >= 0 means already exported
file_name string; file_name string;
key string; key string;
obj *Object; obj *Object;
scope *Scope; scope *Scope; // holds the (global) objects in this package
} }
@ -61,23 +57,20 @@ type Elem struct {
} }
export List export type List struct {
type List struct {
len_ int; len_ int;
first, last *Elem; first, last *Elem;
}; };
export Scope export type Scope struct {
type Scope struct {
parent *Scope; parent *Scope;
entries *List; entries *List;
// entries *map[string] *Object; // doesn't work properly // entries *map[string] *Object; // doesn't work properly
} }
export Flags; export type Flags struct {
type Flags struct {
debug bool; debug bool;
print_export bool; print_export bool;
semantic_checks bool; semantic_checks bool;
@ -86,24 +79,21 @@ type Flags struct {
} }
export Compilation export type Compilation struct {
type Compilation struct {
flags *Flags; flags *Flags;
// TODO use open arrays eventually // TODO use open arrays eventually
pkgs [256] *Package; // pkgs[0] is the current package pkg_list [256] *Package; // pkg_list[0] is the current package
npkgs int; pkg_ref int;
} }
export Expr export type Expr interface {
type Expr interface {
typ() *Type; typ() *Type;
// ... more to come here // ... more to come here
} }
export Stat export type Stat interface {
type Stat interface {
// ... more to come here // ... more to come here
} }
@ -111,8 +101,7 @@ type Stat interface {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Creation // Creation
export Universe_undef_t export var Universe_undef_t *Type // initialized by Universe to Universe.undef_t
var Universe_undef_t *Type // initialized by Universe to Universe.undef_t
export NewObject export NewObject
func NewObject(pos, kind int, ident string) *Object { func NewObject(pos, kind int, ident string) *Object {
@ -123,7 +112,6 @@ func NewObject(pos, kind int, ident string) *Object {
obj.ident = ident; obj.ident = ident;
obj.typ = Universe_undef_t; obj.typ = Universe_undef_t;
obj.pnolev = 0; obj.pnolev = 0;
obj.scope = nil;
return obj; return obj;
} }
@ -138,11 +126,12 @@ func NewType(form int) *Type {
export NewPackage; export NewPackage;
func NewPackage(file_name string) *Package { func NewPackage(file_name string, obj *Object) *Package {
pkg := new(Package); pkg := new(Package);
pkg.ref = -1; // not yet exported pkg.ref = -1; // not yet exported
pkg.file_name = file_name; pkg.file_name = file_name;
pkg.key = "<the package key>"; // TODO fix this pkg.key = "<the package key>"; // TODO fix this
pkg.obj = obj;
return pkg; return pkg;
} }
@ -181,7 +170,6 @@ func (obj *Object) Copy() *Object {
copy.ident = obj.ident; copy.ident = obj.ident;
copy.typ = obj.typ; copy.typ = obj.typ;
copy.pnolev = obj.pnolev; copy.pnolev = obj.pnolev;
copy.scope = nil; // cannot be in the same scope (same ident!)
return copy; return copy;
} }
@ -272,9 +260,6 @@ func (L *List) AddTyp(typ *Type) {
func (scope *Scope) Lookup(ident string) *Object { func (scope *Scope) Lookup(ident string) *Object {
for p := scope.entries.first; p != nil; p = p.next { for p := scope.entries.first; p != nil; p = p.next {
if p.obj.ident == ident { if p.obj.ident == ident {
if p.obj.scope != scope {
panic "incorrect scope for object";
}
return p.obj; return p.obj;
} }
} }
@ -286,11 +271,7 @@ func (scope *Scope) Insert(obj *Object) {
if scope.Lookup(obj.ident) != nil { if scope.Lookup(obj.ident) != nil {
panic "obj already inserted"; panic "obj already inserted";
} }
if obj.scope != nil {
panic "obj already in a scope";
}
scope.entries.AddObj(obj); scope.entries.AddObj(obj);
obj.scope = scope;
} }
@ -317,8 +298,8 @@ func (scope *Scope) Print() {
// Compilation methods // Compilation methods
func (C *Compilation) Lookup(file_name string) *Package { func (C *Compilation) Lookup(file_name string) *Package {
for i := 0; i < C.npkgs; i++ { for i := 0; i < C.pkg_ref; i++ {
pkg := C.pkgs[i]; pkg := C.pkg_list[i];
if pkg.file_name == file_name { if pkg.file_name == file_name {
return pkg; return pkg;
} }
@ -331,9 +312,9 @@ func (C *Compilation) Insert(pkg *Package) {
if C.Lookup(pkg.file_name) != nil { if C.Lookup(pkg.file_name) != nil {
panic "package already inserted"; panic "package already inserted";
} }
pkg.obj.pnolev = C.npkgs; pkg.obj.pnolev = C.pkg_ref;
C.pkgs[C.npkgs] = pkg; C.pkg_list[C.pkg_ref] = pkg;
C.npkgs++; C.pkg_ref++;
} }

View File

@ -16,9 +16,9 @@ type Importer struct {
debug bool; debug bool;
buf string; buf string;
buf_pos int; buf_pos int;
pkgs [256] *Globals.Package; pkg_list [256] *Globals.Package;
pkg_ref int; pkg_ref int;
types [1024] *Globals.Type; type_list [1024] *Globals.Type;
type_ref int; type_ref int;
}; };
@ -120,8 +120,6 @@ func (I *Importer) ReadScope() *Globals.Scope {
scope := Globals.NewScope(nil); scope := Globals.NewScope(nil);
obj := I.ReadObject(); obj := I.ReadObject();
for obj != nil { for obj != nil {
// InsertImport only needed for package scopes
// but ok to use always
scope.InsertImport(obj); scope.InsertImport(obj);
obj = I.ReadObject(); obj = I.ReadObject();
} }
@ -153,7 +151,6 @@ 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.typ = I.ReadType(); obj.typ = I.ReadType();
obj.pnolev = I.ReadPackage().obj.pnolev;
switch (tag) { switch (tag) {
case Object.CONST: case Object.CONST:
@ -176,26 +173,31 @@ func (I *Importer) ReadObject() *Globals.Object {
func (I *Importer) ReadType() *Globals.Type { func (I *Importer) ReadType() *Globals.Type {
tag := I.ReadTypeTag(); tag := I.ReadTypeTag();
if tag >= 0 { if tag >= 0 {
return I.types[tag]; // type already imported return I.type_list[tag]; // type already imported
} }
typ := Globals.NewType(-tag); typ := Globals.NewType(-tag);
ptyp := typ; // primary type ptyp := typ; // primary type
ident := I.ReadString(); ident := I.ReadString();
if len(ident) > 0 { if len(ident) > 0 {
// primary type // primary type
pkg := I.ReadPackage();
// create corresponding type object
obj := Globals.NewObject(0, Object.TYPE, ident); obj := Globals.NewObject(0, Object.TYPE, ident);
obj.exported = true;
obj.typ = typ; obj.typ = typ;
obj.pnolev = pkg.obj.pnolev;
typ.obj = obj; typ.obj = obj;
// canonicalize type // canonicalize type
pkg := I.ReadPackage(); // (if the type was seen before, use primary instance!)
obj.pnolev = pkg.obj.pnolev; ptyp = pkg.scope.InsertImport(obj).typ;
obj = pkg.scope.InsertImport(obj);
ptyp = obj.typ;
} }
I.types[I.type_ref] = ptyp; // insert the primary type into the type table but
// keep filling in the current type fields
I.type_list[I.type_ref] = ptyp;
I.type_ref++; I.type_ref++;
switch (typ.form) { switch (typ.form) {
@ -235,7 +237,7 @@ func (I *Importer) ReadType() *Globals.Type {
func (I *Importer) ReadPackage() *Globals.Package { func (I *Importer) ReadPackage() *Globals.Package {
tag := I.ReadPackageTag(); tag := I.ReadPackageTag();
if tag >= 0 { if tag >= 0 {
return I.pkgs[tag]; // package already imported return I.pkg_list[tag]; // package already imported
} }
ident := I.ReadString(); ident := I.ReadString();
@ -245,8 +247,8 @@ func (I *Importer) ReadPackage() *Globals.Package {
if pkg == nil { if pkg == nil {
// new package // new package
pkg = Globals.NewPackage(file_name); obj := Globals.NewObject(-1, Object.PACKAGE, ident);
pkg.obj = Globals.NewObject(-1, Object.PACKAGE, ident); pkg = Globals.NewPackage(file_name, obj);
pkg.scope = Globals.NewScope(nil); pkg.scope = Globals.NewScope(nil);
pkg = I.comp.InsertImport(pkg); pkg = I.comp.InsertImport(pkg);
@ -254,7 +256,7 @@ func (I *Importer) ReadPackage() *Globals.Package {
// package inconsistency // package inconsistency
panic "package key inconsistency"; panic "package key inconsistency";
} }
I.pkgs[I.pkg_ref] = pkg; I.pkg_list[I.pkg_ref] = pkg;
I.pkg_ref++; I.pkg_ref++;
return pkg; return pkg;
@ -284,7 +286,7 @@ func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.
if p.typ.ref != I.type_ref { if p.typ.ref != I.type_ref {
panic "incorrect ref for predeclared type"; panic "incorrect ref for predeclared type";
} }
I.types[I.type_ref] = p.typ; I.type_list[I.type_ref] = p.typ;
I.type_ref++; I.type_ref++;
} }

View File

@ -7,8 +7,7 @@ package Object
import Globals "globals" import Globals "globals"
export BAD, CONST, TYPE, VAR, FUNC, PACKAGE, LABEL, END export const /* kind */ (
const /* kind */ (
BAD = iota; // error handling BAD = iota; // error handling
CONST; TYPE; VAR; FUNC; PACKAGE; LABEL; CONST; TYPE; VAR; FUNC; PACKAGE; LABEL;
END; // end of scope (import/export only) END; // end of scope (import/export only)

View File

@ -306,7 +306,7 @@ func (P *Parser) ParseQualifiedIdent(pos int, ident string) *Globals.Object {
if obj.pnolev < 0 { if obj.pnolev < 0 {
panic "obj.pnolev < 0"; panic "obj.pnolev < 0";
} }
pkg := P.comp.pkgs[obj.pnolev]; pkg := P.comp.pkg_list[obj.pnolev];
//if pkg.obj.ident != ident { //if pkg.obj.ident != ident {
// panic "pkg.obj.ident != ident"; // panic "pkg.obj.ident != ident";
//} //}
@ -1916,10 +1916,10 @@ func (P *Parser) ParseProgram() {
P.OpenScope(); P.OpenScope();
P.Expect(Scanner.PACKAGE); P.Expect(Scanner.PACKAGE);
pkg := Globals.NewPackage(P.S.filename); obj := P.ParseIdentDecl(Object.PACKAGE);
pkg.obj = P.ParseIdentDecl(Object.PACKAGE); pkg := Globals.NewPackage(P.S.filename, obj);
P.comp.Insert(pkg); P.comp.Insert(pkg);
if P.comp.npkgs != 1 { if P.comp.pkg_ref != 1 {
panic "should have exactly one package now"; panic "should have exactly one package now";
} }
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);

View File

@ -164,7 +164,7 @@ func (P *Printer) PrintObjectStruct(obj *Globals.Object) {
print "package "; print "package ";
P.PrintObject(obj); P.PrintObject(obj);
print " "; print " ";
P.PrintScope(P.comp.pkgs[obj.pnolev].scope, 0); P.PrintScope(P.comp.pkg_list[obj.pnolev].scope, 0);
default: default:
panic "UNREACHABLE"; panic "UNREACHABLE";
@ -178,7 +178,7 @@ func (P *Printer) PrintObjectStruct(obj *Globals.Object) {
func (P *Printer) PrintObject(obj *Globals.Object) { func (P *Printer) PrintObject(obj *Globals.Object) {
if obj.pnolev > 0 { if obj.pnolev > 0 {
print P.comp.pkgs[obj.pnolev].obj.ident, "."; print P.comp.pkg_list[obj.pnolev].obj.ident, ".";
} }
print obj.ident; print obj.ident;
} }

View File

@ -6,27 +6,7 @@ package Scanner
import Utils "utils" import Utils "utils"
export const (
export
ILLEGAL, EOF, IDENT, STRING, NUMBER,
COMMA, COLON, SEMICOLON, PERIOD,
LPAREN, RPAREN, LBRACK, RBRACK, LBRACE, RBRACE,
ASSIGN, DEFINE,
INC, DEC, NOT,
AND, OR, XOR,
ADD, SUB, MUL, QUO, REM,
EQL, NEQ, LSS, LEQ, GTR, GEQ,
SHL, SHR,
SEND, RECV,
ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN,
AND_ASSIGN, OR_ASSIGN, XOR_ASSIGN, SHL_ASSIGN, SHR_ASSIGN,
LAND, LOR,
BREAK, CASE, CHAN, CONST, CONTINUE, DEFAULT, ELSE, EXPORT, FALLTHROUGH, FALSE,
FOR, FUNC, GO, GOTO, IF, IMPORT, INTERFACE, IOTA, MAP, NEW, NIL, PACKAGE, RANGE,
RETURN, SELECT, STRUCT, SWITCH, TRUE, TYPE, VAR
const (
ILLEGAL = iota; ILLEGAL = iota;
EOF; EOF;
IDENT; IDENT;
@ -270,8 +250,7 @@ func digit_val(ch int) int {
} }
export Scanner export type Scanner struct {
type Scanner struct {
filename string; // error reporting only filename string; // error reporting only
nerrors int; // number of errors nerrors int; // number of errors
errpos int; // last error position errpos int; // last error position

View File

@ -4,13 +4,7 @@
package Type package Type
export export const /* form */ (
UNDEF, BAD, NIL,
BOOL, UINT, INT, FLOAT, STRING,
ANY,
ALIAS, ARRAY, STRUCT, INTERFACE, MAP, CHANNEL, FUNCTION, POINTER, REFERENCE
const /* form */ (
// internal types // internal types
UNDEF = iota; BAD; NIL; UNDEF = iota; BAD; NIL;
// basic types // basic types
@ -22,10 +16,7 @@ const /* form */ (
) )
export export const /* flag */ (
SEND, RECV
const /* flag */ (
SEND = 1 << iota; // chan> SEND = 1 << iota; // chan>
RECV; // chan< or method RECV; // chan< or method
) )

View File

@ -106,7 +106,7 @@ func VerifyPackage(pkg *Globals.Package, pno int) {
export Verify export Verify
func Verify(comp *Globals.Compilation) { func Verify(comp *Globals.Compilation) {
for i := 0; i < comp.npkgs; i++ { for i := 0; i < comp.pkg_ref; i++ {
VerifyPackage(comp.pkgs[i], i); VerifyPackage(comp.pkg_list[i], i);
} }
} }