// see if it just works
data, ok = Platform.ReadSourceFile(filename);
if ok {
- comp.env.Compile(comp.flags, comp.env, filename + Platform.src_file_ext);
+ comp.env.Compile(comp, filename + Platform.src_file_ext);
data, ok = ReadImport(comp, filename, false);
if ok {
return data, ok;
}
-export func Export(comp *Globals.Compilation) string {
- panic "UNIMPLEMENTED";
- return "";
+export func Export(comp *Globals.Compilation, pkg_file string) {
+ data := Exporter.Export(comp);
+ ok := Platform.WriteObjectFile(pkg_file, data);
+ if !ok {
+ panic "export failed";
+ }
}
-export func Compile(flags *Globals.Flags, env* Globals.Environment, filename string) {
- // setup compilation
- comp := new(Globals.Compilation);
- comp.flags = flags;
- comp.env = env;
-
- src, ok := sys.readfile(filename);
+export func Compile(comp *Globals.Compilation, src_file string) {
+ src, ok := Platform.ReadSourceFile(src_file);
if !ok {
- print "cannot open ", filename, "\n"
+ print "cannot open ", src_file, "\n"
return;
}
- if flags.verbosity > 0 {
- print filename, "\n";
+ if comp.flags.verbosity > 0 {
+ print src_file, "\n";
}
scanner := new(Scanner.Scanner);
- scanner.Open(filename, src);
+ scanner.Open(src_file, src);
var tstream *chan *Scanner.Token;
if comp.flags.token_chan {
Printer.PrintObject(comp, comp.pkg_list[0].obj, false);
}
- Exporter.Export(comp, filename);
+ Export(comp, src_file);
}
}
switch typ.form {
+ case Type.FORWARD:
+ // corresponding package must be forward-declared too
+ if typ.obj == nil || E.comp.pkg_list[typ.obj.pnolev].key != "" {
+ panic "inconsistency in package.type forward declaration";
+ }
+
case Type.ALIAS, Type.MAP:
E.WriteType(typ.aux);
E.WriteType(typ.elt);
}
-func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
- E.comp = comp;
- E.debug = comp.flags.debug;
- E.buf_pos = 0;
- E.pkg_ref = 0;
- E.type_ref = 0;
-
- if E.debug {
- print "exporting to ", file_name, "\n";
- }
-
- // write magic bits
- magic := Platform.MAGIC_obj_file; // TODO remove once len(constant) works
- for i := 0; i < len(magic); i++ {
- E.WriteByte(magic[i]);
- }
-
- // Predeclared types are "pre-exported".
- // TODO run the loop below only in debug mode
- { i := 0;
- for p := Universe.types.first; p != nil; p = p.next {
- if p.typ.ref != i {
- panic "incorrect ref for predeclared type";
- }
- i++;
- }
- }
- E.type_ref = Universe.types.len_;
-
- // export package 0
- pkg := comp.pkg_list[0];
- E.WritePackage(pkg);
- E.WriteScope(pkg.scope);
-
- if E.debug {
- print "\n(", E.buf_pos, " bytes)\n";
- }
-
- data := string(E.buf)[0 : E.buf_pos];
- ok := sys.writefile(file_name, data);
-
- if !ok {
- panic "export failed";
- }
-}
-
-
-func (E *Exporter) Export2(comp* Globals.Compilation) string {
+func (E *Exporter) Export(comp* Globals.Compilation) string {
E.comp = comp;
E.debug = comp.flags.debug;
E.buf_pos = 0;
}
-export func Export(comp* Globals.Compilation, pkg_name string) {
- var E Exporter;
- (&E).Export(comp, Utils.TrimExt(Utils.BaseName(pkg_name), Platform.src_file_ext) + Platform.obj_file_ext);
-}
-
-
-export func Export2(comp* Globals.Compilation) string {
+export func Export(comp* Globals.Compilation) string {
var E Exporter;
- return (&E).Export2(comp);
+ return (&E).Export(comp);
}
export type Environment struct {
Error *func(comp *Compilation); // TODO complete this
Import *func(comp *Compilation, pkg_file string) *Package;
- Export *func(comp *Compilation) string;
- Compile *func(flags *Flags, env* Environment, file string);
+ Export *func(comp *Compilation, pkg_file string);
+ Compile *func(comp *Compilation, src_file string);
}
pkg := new(Package);
pkg.ref = -1; // not yet exported
pkg.file_name = file_name;
- pkg.key = "<the package key>"; // TODO fix this
+ pkg.key = "<the package key>"; // empty key means package forward declaration
pkg.obj = obj;
pkg.scope = scope;
return pkg;
// compile files
for p := files.first; p != nil; p = p.next {
- Compilation.Compile(flags, env, p.str);
+ // setup compilation
+ comp := new(Globals.Compilation);
+ comp.flags = flags;
+ comp.env = env;
+
+ // compile
+ Compilation.Compile(comp, p.str);
}
}
if I.comp.flags.verbosity > 1 {
print `import: implicitly adding package `, ident, ` "`, file_name, `" (pno = `, obj.pnolev, ")\n";
}
- } else if key != pkg.key {
+ } else if key != "" && key != pkg.key {
// the package was imported before but the package
- // key has changed
+ // key has changed (a "" key indicates a forward-
+ // declared package - it's key is consistent with
+ // any actual package of the same name)
panic "package key inconsistency";
}
I.pkg_list[I.pkg_ref] = pkg;
I.type_ref++;
switch (typ.form) {
+ case Type.FORWARD:
+ typ.scope = Globals.NewScope(nil);
+ break;
+
case Type.ALIAS, Type.MAP:
typ.aux = I.ReadType();
typ.elt = I.ReadType();
typ := Globals.NewType(Type.POINTER);
var elt *Globals.Type;
- if P.semantic_checks && P.tok == Scanner.IDENT {
- if P.Lookup(P.val) == nil {
- // implicit forward declaration
- // create a named forward type
+ if P.semantic_checks {
+ if P.tok == Scanner.STRING && !P.comp.flags.sixg {
+ // implicit package.type forward declaration
+ // TODO eventually the scanner should strip the quotes
+ pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes
+ pkg := P.comp.Lookup(pkg_name);
+ if pkg == nil {
+ // package doesn't exist yet - add it to the package list
+ obj := Globals.NewObject(P.pos, Object.PACKAGE, ".pkg");
+ pkg = Globals.NewPackage(pkg_name, obj, Globals.NewScope(nil));
+ pkg.key = ""; // mark as forward-declared package
+ P.comp.Insert(pkg);
+ } else {
+ // package exists already - must be forward declaration
+ if pkg.key != "" {
+ P.Error(P.pos, `cannot use implicit package forward declaration for imported package "` + P.val + `"`);
+ panic "wrong package forward decl";
+ // TODO introduce dummy package so we can continue safely
+ }
+ }
+
+ P.Next(); // consume package name
+ P.Expect(Scanner.PERIOD);
pos, ident := P.ParseIdent();
- obj := Globals.NewObject(pos, Object.TYPE, ident);
- elt = Globals.NewType(Type.FORWARD);
- obj.typ = elt;
- elt.obj = obj; // primary type object;
- // remember the current scope - resolving the forward
- // type must find a matching declaration in this or a less nested scope
- elt.scope = P.top_scope;
+ obj := pkg.scope.Lookup(ident);
+ if obj == nil {
+ elt = Globals.NewType(Type.FORWARD);
+ elt.scope = P.top_scope; // not really needed here, but for consistency
+ obj = Globals.NewObject(pos, Object.TYPE, ident);
+ obj.exported = true; // the type name must be visible
+ obj.typ = elt;
+ elt.obj = obj; // primary type object;
+ pkg.scope.Insert(obj);
+ obj.pnolev = pkg.obj.pnolev;
+ } else {
+ if obj.kind != Object.TYPE || obj.typ.form != Type.FORWARD {
+ panic "inconsistency in package.type forward declaration";
+ }
+ elt = obj.typ;
+ }
- } else {
- // type name
- // (ParseType() (via TryType()) checks for forward types and complains,
- // so call ParseTypeName() directly)
- // we can only have a foward type here if we refer to the name of a
- // yet incomplete type (i.e. if we are in the middle of a type's declaration)
- elt = P.ParseTypeName();
- }
+ } else if P.tok == Scanner.IDENT {
+ if P.Lookup(P.val) == nil {
+ // implicit type forward declaration
+ // create a named forward type
+ pos, ident := P.ParseIdent();
+ obj := Globals.NewObject(pos, Object.TYPE, ident);
+ elt = Globals.NewType(Type.FORWARD);
+ obj.typ = elt;
+ elt.obj = obj; // primary type object;
+ // remember the current scope - resolving the forward
+ // type must find a matching declaration in this or a less nested scope
+ elt.scope = P.top_scope;
+
+ } else {
+ // type name
+ // (ParseType() (via TryType()) checks for forward types and complains,
+ // so call ParseTypeName() directly)
+ // we can only have a foward type here if we refer to the name of a
+ // yet incomplete type (i.e. if we are in the middle of a type's declaration)
+ elt = P.ParseTypeName();
+ }
- // collect uses of pointer types referring to forward types
- if elt.form == Type.FORWARD {
- P.forward_types.AddTyp(typ);
+ // collect uses of pointer types referring to forward types
+ if elt.form == Type.FORWARD {
+ P.forward_types.AddTyp(typ);
+ }
+
+ } else {
+ elt = P.ParseType();
}
-
+
} else {
elt = P.ParseType();
}
}
-func (P *Parser) ParseCaseList() {
- P.Trace("CaseList");
-
- P.ParseCase();
- for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
- P.ParseCase();
- }
-
- P.Ecart();
-}
-
-
func (P *Parser) ParseCaseClause() {
P.Trace("CaseClause");
- P.ParseCaseList();
+ P.ParseCase();
if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
P.ParseStatementList();
P.Optional(Scanner.SEMICOLON);
func (P *Parser) ParseTypeSpec(exported bool) {
P.Trace("TypeSpec");
- // Immediately after declaration of the type name, the type is
- // considered forward-declared. It may be referred to from inside
- // the type specification only via a pointer type.
- typ := Globals.NewType(Type.FORWARD);
- typ.scope = P.top_scope; // not really needed here, but for consistency
+ var typ *Globals.Type;
pos, ident := P.ParseIdent();
- obj := Globals.NewObject(pos, Object.TYPE, ident);
- obj.exported = exported;
- obj.typ = typ;
- typ.obj = obj; // primary type object
- P.Declare(obj);
+ obj := P.Lookup(ident);
+ if !P.comp.flags.sixg && obj != nil {
+ if obj.typ.form == Type.FORWARD {
+ // imported forward-declared type
+ if !exported {
+ panic "foo";
+ }
+ } else {
+ panic "bar";
+ }
+
+ } else {
+ // Immediately after declaration of the type name, the type is
+ // considered forward-declared. It may be referred to from inside
+ // the type specification only via a pointer type.
+ typ = Globals.NewType(Type.FORWARD);
+ typ.scope = P.top_scope; // not really needed here, but for consistency
+
+ obj = Globals.NewObject(pos, Object.TYPE, ident);
+ obj.exported = exported;
+ obj.typ = typ;
+ typ.obj = obj; // primary type object
+ P.Declare(obj);
+ }
+
// If the next token is an identifier and we have a legal program,
// it must be a typename. In that case this declaration introduces
// an alias type.
package Platform
+import Utils "utils"
+
+
// ----------------------------------------------------------------------------
// Environment
}
-export func ReadSourceFile(filename string) (data string, ok bool) {
- data, ok = sys.readfile(filename + src_file_ext);
+export func ReadSourceFile(name string) (data string, ok bool) {
+ name = Utils.TrimExt(name, src_file_ext) + src_file_ext;
+ data, ok = sys.readfile(name);
return data, ok;
}
+
+
+export func WriteObjectFile(name string, data string) bool {
+ name = Utils.TrimExt(Utils.BaseName(name), src_file_ext) + obj_file_ext;
+ return sys.writefile(name, data);
+}
func (P *Printer) PrintObject(obj *Globals.Object) {
if obj.pnolev > 0 {
- print P.comp.pkg_list[obj.pnolev].obj.ident, ".";
+ pkg := P.comp.pkg_list[obj.pnolev];
+ if pkg.key == "" {
+ // forward-declared package
+ print `"`, pkg.file_name, `"`;
+ } else {
+ // imported package
+ print pkg.obj.ident;
+ }
+ print "."
}
print obj.ident;
}
Bit3 = 4;
Bit4 = 3;
- // TODO 6g constant evaluation incomplete
- T1 = 0x00; // (1 << (Bit1 + 1) - 1) ^ 0xFF; // 0000 0000
- Tx = 0x80; // (1 << (Bitx + 1) - 1) ^ 0xFF; // 1000 0000
- T2 = 0xC0; // (1 << (Bit2 + 1) - 1) ^ 0xFF; // 1100 0000
- T3 = 0xE0; // (1 << (Bit3 + 1) - 1) ^ 0xFF; // 1110 0000
- T4 = 0xF0; // (1 << (Bit4 + 1) - 1) ^ 0xFF; // 1111 0000
+ T1 = (1 << (Bit1 + 1) - 1) ^ 0xFF; // 0000 0000
+ Tx = (1 << (Bitx + 1) - 1) ^ 0xFF; // 1000 0000
+ T2 = (1 << (Bit2 + 1) - 1) ^ 0xFF; // 1100 0000
+ T3 = (1 << (Bit3 + 1) - 1) ^ 0xFF; // 1110 0000
+ T4 = (1 << (Bit4 + 1) - 1) ^ 0xFF; // 1111 0000
Rune1 = 1 << (Bit1 + 0*Bitx) - 1; // 0000 0000 0111 1111
Rune2 = 1 << (Bit2 + 1*Bitx) - 1; // 0000 0111 1111 1111