parser := new(Parser.Parser);
parser.Open(comp, scanner);
- print "parsing ", file_name, "\n";
parser.ParseProgram();
if parser.S.nerrors > 0 {
return;
Verifier.Verify(comp);
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);
E.WriteString(obj.ident);
E.WriteType(obj.typ);
- E.WritePackage(obj.pnolev);
switch obj.kind {
case Object.CONST:
if -typ.form >= 0 {
panic "-typ.form >= 0"; // conflict with ref numbers
}
-
E.WriteTypeTag(-typ.form);
typ.ref = E.type_ref;
E.type_ref++;
+ // if we have a primary type, export the type identifier and package
+ ident := "";
if typ.obj != nil {
+ // primary type
if typ.obj.typ != typ {
- panic "typ.obj.type() != typ"; // primary type
+ panic "inconsistent primary type";
+ }
+ 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(typ.obj.ident);
+ }
+
+ E.WriteString(ident);
+ if len(ident) > 0 {
+ // primary type
E.WritePackage(typ.obj.pnolev);
- } else {
- E.WriteString("");
}
-
+
switch typ.form {
case Type.ALIAS:
E.WriteType(typ.elt);
if pno < 0 {
pno = 0;
}
- pkg := E.comp.pkgs[pno];
+ pkg := E.comp.pkg_list[pno];
if pkg.ref >= 0 {
E.WritePackageTag(pkg.ref); // package already exported
return;
}
E.type_ref = Universe.types.len_;
- pkg := comp.pkgs[0];
+ pkg := comp.pkg_list[0];
E.WritePackage(0);
E.WriteScope(pkg.scope, false);
// ----------------------------------------------------------------------------
-export Object
-type Object struct {
+export type Object struct {
exported bool;
pos int; // source position (< 0 if unknown position)
kind int;
ident string;
- typ *Type;
- pnolev int; // >= 0: package no., <= 0: level, 0: global level of compilation
- scope *Scope; // which contains the object
+ typ *Type; // nil for packages
+ pnolev int; // >= 0: package no., <= 0: function nesting level, 0: global level
}
-export Type
-type Type struct {
+export type Type struct {
ref int; // for exporting only: >= 0 means already exported
form int;
flags int; // channels, functions
}
-export Package
-type Package struct {
+export type Package struct {
ref int; // for exporting only: >= 0 means already exported
file_name string;
key string;
obj *Object;
- scope *Scope;
+ scope *Scope; // holds the (global) objects in this package
}
}
-export List
-type List struct {
+export type List struct {
len_ int;
first, last *Elem;
};
-export Scope
-type Scope struct {
+export type Scope struct {
parent *Scope;
entries *List;
// entries *map[string] *Object; // doesn't work properly
}
-export Flags;
-type Flags struct {
+export type Flags struct {
debug bool;
print_export bool;
semantic_checks bool;
}
-export Compilation
-type Compilation struct {
+export type Compilation struct {
flags *Flags;
// TODO use open arrays eventually
- pkgs [256] *Package; // pkgs[0] is the current package
- npkgs int;
+ pkg_list [256] *Package; // pkg_list[0] is the current package
+ pkg_ref int;
}
-export Expr
-type Expr interface {
+export type Expr interface {
typ() *Type;
// ... more to come here
}
-export Stat
-type Stat interface {
+export type Stat interface {
// ... more to come here
}
// ----------------------------------------------------------------------------
// Creation
-export Universe_undef_t
-var Universe_undef_t *Type // initialized by Universe to Universe.undef_t
+export var Universe_undef_t *Type // initialized by Universe to Universe.undef_t
export NewObject
func NewObject(pos, kind int, ident string) *Object {
obj.ident = ident;
obj.typ = Universe_undef_t;
obj.pnolev = 0;
- obj.scope = nil;
return obj;
}
export NewPackage;
-func NewPackage(file_name string) *Package {
+func NewPackage(file_name string, obj *Object) *Package {
pkg := new(Package);
pkg.ref = -1; // not yet exported
pkg.file_name = file_name;
pkg.key = "<the package key>"; // TODO fix this
+ pkg.obj = obj;
return pkg;
}
copy.ident = obj.ident;
copy.typ = obj.typ;
copy.pnolev = obj.pnolev;
- copy.scope = nil; // cannot be in the same scope (same ident!)
return copy;
}
func (scope *Scope) Lookup(ident string) *Object {
for p := scope.entries.first; p != nil; p = p.next {
if p.obj.ident == ident {
- if p.obj.scope != scope {
- panic "incorrect scope for object";
- }
return p.obj;
}
}
if scope.Lookup(obj.ident) != nil {
panic "obj already inserted";
}
- if obj.scope != nil {
- panic "obj already in a scope";
- }
scope.entries.AddObj(obj);
- obj.scope = scope;
}
// Compilation methods
func (C *Compilation) Lookup(file_name string) *Package {
- for i := 0; i < C.npkgs; i++ {
- pkg := C.pkgs[i];
+ for i := 0; i < C.pkg_ref; i++ {
+ pkg := C.pkg_list[i];
if pkg.file_name == file_name {
return pkg;
}
if C.Lookup(pkg.file_name) != nil {
panic "package already inserted";
}
- pkg.obj.pnolev = C.npkgs;
- C.pkgs[C.npkgs] = pkg;
- C.npkgs++;
+ pkg.obj.pnolev = C.pkg_ref;
+ C.pkg_list[C.pkg_ref] = pkg;
+ C.pkg_ref++;
}
debug bool;
buf string;
buf_pos int;
- pkgs [256] *Globals.Package;
+ pkg_list [256] *Globals.Package;
pkg_ref int;
- types [1024] *Globals.Type;
+ type_list [1024] *Globals.Type;
type_ref int;
};
scope := Globals.NewScope(nil);
obj := I.ReadObject();
for obj != nil {
- // InsertImport only needed for package scopes
- // but ok to use always
scope.InsertImport(obj);
obj = I.ReadObject();
}
ident := I.ReadString();
obj := Globals.NewObject(0, tag, ident);
obj.typ = I.ReadType();
- obj.pnolev = I.ReadPackage().obj.pnolev;
switch (tag) {
case Object.CONST:
func (I *Importer) ReadType() *Globals.Type {
tag := I.ReadTypeTag();
if tag >= 0 {
- return I.types[tag]; // type already imported
+ return I.type_list[tag]; // type already imported
}
typ := Globals.NewType(-tag);
ptyp := typ; // primary type
+
ident := I.ReadString();
if len(ident) > 0 {
// primary type
+ pkg := I.ReadPackage();
+
+ // create corresponding type object
obj := Globals.NewObject(0, Object.TYPE, ident);
+ obj.exported = true;
obj.typ = typ;
+ obj.pnolev = pkg.obj.pnolev;
typ.obj = obj;
// canonicalize type
- pkg := I.ReadPackage();
- obj.pnolev = pkg.obj.pnolev;
- obj = pkg.scope.InsertImport(obj);
-
- ptyp = obj.typ;
+ // (if the type was seen before, use primary instance!)
+ ptyp = pkg.scope.InsertImport(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++;
switch (typ.form) {
func (I *Importer) ReadPackage() *Globals.Package {
tag := I.ReadPackageTag();
if tag >= 0 {
- return I.pkgs[tag]; // package already imported
+ return I.pkg_list[tag]; // package already imported
}
ident := I.ReadString();
if pkg == nil {
// new package
- pkg = Globals.NewPackage(file_name);
- pkg.obj = Globals.NewObject(-1, Object.PACKAGE, ident);
+ obj := Globals.NewObject(-1, Object.PACKAGE, ident);
+ pkg = Globals.NewPackage(file_name, obj);
pkg.scope = Globals.NewScope(nil);
pkg = I.comp.InsertImport(pkg);
// package inconsistency
panic "package key inconsistency";
}
- I.pkgs[I.pkg_ref] = pkg;
+ I.pkg_list[I.pkg_ref] = pkg;
I.pkg_ref++;
return pkg;
if p.typ.ref != I.type_ref {
panic "incorrect ref for predeclared type";
}
- I.types[I.type_ref] = p.typ;
+ I.type_list[I.type_ref] = p.typ;
I.type_ref++;
}
import Globals "globals"
-export BAD, CONST, TYPE, VAR, FUNC, PACKAGE, LABEL, END
-const /* kind */ (
+export const /* kind */ (
BAD = iota; // error handling
CONST; TYPE; VAR; FUNC; PACKAGE; LABEL;
END; // end of scope (import/export only)
if 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 {
// panic "pkg.obj.ident != ident";
//}
P.OpenScope();
P.Expect(Scanner.PACKAGE);
- pkg := Globals.NewPackage(P.S.filename);
- pkg.obj = P.ParseIdentDecl(Object.PACKAGE);
+ obj := P.ParseIdentDecl(Object.PACKAGE);
+ pkg := Globals.NewPackage(P.S.filename, obj);
P.comp.Insert(pkg);
- if P.comp.npkgs != 1 {
+ if P.comp.pkg_ref != 1 {
panic "should have exactly one package now";
}
P.Optional(Scanner.SEMICOLON);
print "package ";
P.PrintObject(obj);
print " ";
- P.PrintScope(P.comp.pkgs[obj.pnolev].scope, 0);
+ P.PrintScope(P.comp.pkg_list[obj.pnolev].scope, 0);
default:
panic "UNREACHABLE";
func (P *Printer) PrintObject(obj *Globals.Object) {
if obj.pnolev > 0 {
- print P.comp.pkgs[obj.pnolev].obj.ident, ".";
+ print P.comp.pkg_list[obj.pnolev].obj.ident, ".";
}
print obj.ident;
}
import Utils "utils"
-
-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 (
+export const (
ILLEGAL = iota;
EOF;
IDENT;
}
-export Scanner
-type Scanner struct {
+export type Scanner struct {
filename string; // error reporting only
nerrors int; // number of errors
errpos int; // last error position
package Type
-export
- UNDEF, BAD, NIL,
- BOOL, UINT, INT, FLOAT, STRING,
- ANY,
- ALIAS, ARRAY, STRUCT, INTERFACE, MAP, CHANNEL, FUNCTION, POINTER, REFERENCE
-
-const /* form */ (
+export const /* form */ (
// internal types
UNDEF = iota; BAD; NIL;
// basic types
)
-export
- SEND, RECV
-
-const /* flag */ (
+export const /* flag */ (
SEND = 1 << iota; // chan>
RECV; // chan< or method
)
export Verify
func Verify(comp *Globals.Compilation) {
- for i := 0; i < comp.npkgs; i++ {
- VerifyPackage(comp.pkgs[i], i);
+ for i := 0; i < comp.pkg_ref; i++ {
+ VerifyPackage(comp.pkg_list[i], i);
}
}