mirror of
https://github.com/golang/go
synced 2024-11-26 02:37:58 -07:00
- experiments with forward-declaring types of non-imported packages
- adjusted switch syntax (no repeated case: case: anymore) - enabled some constant expressions that work now R=r OCL=14098 CL=14098
This commit is contained in:
parent
fe582137f4
commit
40c93a5238
@ -52,7 +52,7 @@ func ReadImport(comp* Globals.Compilation, filename string, update bool) (data s
|
|||||||
// see if it just works
|
// see if it just works
|
||||||
data, ok = Platform.ReadSourceFile(filename);
|
data, ok = Platform.ReadSourceFile(filename);
|
||||||
if ok {
|
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);
|
data, ok = ReadImport(comp, filename, false);
|
||||||
if ok {
|
if ok {
|
||||||
return data, ok;
|
return data, ok;
|
||||||
@ -73,30 +73,28 @@ export func Import(comp *Globals.Compilation, pkg_file string) *Globals.Package
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export func Export(comp *Globals.Compilation) string {
|
export func Export(comp *Globals.Compilation, pkg_file string) {
|
||||||
panic "UNIMPLEMENTED";
|
data := Exporter.Export(comp);
|
||||||
return "";
|
ok := Platform.WriteObjectFile(pkg_file, data);
|
||||||
|
if !ok {
|
||||||
|
panic "export failed";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export func Compile(flags *Globals.Flags, env* Globals.Environment, filename string) {
|
export func Compile(comp *Globals.Compilation, src_file string) {
|
||||||
// setup compilation
|
src, ok := Platform.ReadSourceFile(src_file);
|
||||||
comp := new(Globals.Compilation);
|
|
||||||
comp.flags = flags;
|
|
||||||
comp.env = env;
|
|
||||||
|
|
||||||
src, ok := sys.readfile(filename);
|
|
||||||
if !ok {
|
if !ok {
|
||||||
print "cannot open ", filename, "\n"
|
print "cannot open ", src_file, "\n"
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.verbosity > 0 {
|
if comp.flags.verbosity > 0 {
|
||||||
print filename, "\n";
|
print src_file, "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
scanner := new(Scanner.Scanner);
|
scanner := new(Scanner.Scanner);
|
||||||
scanner.Open(filename, src);
|
scanner.Open(src_file, src);
|
||||||
|
|
||||||
var tstream *chan *Scanner.Token;
|
var tstream *chan *Scanner.Token;
|
||||||
if comp.flags.token_chan {
|
if comp.flags.token_chan {
|
||||||
@ -122,5 +120,5 @@ export func Compile(flags *Globals.Flags, env* Globals.Environment, filename str
|
|||||||
Printer.PrintObject(comp, comp.pkg_list[0].obj, false);
|
Printer.PrintObject(comp, comp.pkg_list[0].obj, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Exporter.Export(comp, filename);
|
Export(comp, src_file);
|
||||||
}
|
}
|
||||||
|
@ -174,6 +174,12 @@ func (E *Exporter) WriteType(typ *Globals.Type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch typ.form {
|
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:
|
case Type.ALIAS, Type.MAP:
|
||||||
E.WriteType(typ.aux);
|
E.WriteType(typ.aux);
|
||||||
E.WriteType(typ.elt);
|
E.WriteType(typ.elt);
|
||||||
@ -237,54 +243,7 @@ func (E *Exporter) WriteObject(obj *Globals.Object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
|
func (E *Exporter) Export(comp* Globals.Compilation) 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 {
|
|
||||||
E.comp = comp;
|
E.comp = comp;
|
||||||
E.debug = comp.flags.debug;
|
E.debug = comp.flags.debug;
|
||||||
E.buf_pos = 0;
|
E.buf_pos = 0;
|
||||||
@ -322,13 +281,7 @@ func (E *Exporter) Export2(comp* Globals.Compilation) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export func Export(comp* Globals.Compilation, pkg_name string) {
|
export func Export(comp* Globals.Compilation) string {
|
||||||
var E Exporter;
|
var E Exporter;
|
||||||
(&E).Export(comp, Utils.TrimExt(Utils.BaseName(pkg_name), Platform.src_file_ext) + Platform.obj_file_ext);
|
return (&E).Export(comp);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export func Export2(comp* Globals.Compilation) string {
|
|
||||||
var E Exporter;
|
|
||||||
return (&E).Export2(comp);
|
|
||||||
}
|
}
|
||||||
|
@ -77,8 +77,8 @@ export type Flags struct {
|
|||||||
export type Environment struct {
|
export type Environment struct {
|
||||||
Error *func(comp *Compilation); // TODO complete this
|
Error *func(comp *Compilation); // TODO complete this
|
||||||
Import *func(comp *Compilation, pkg_file string) *Package;
|
Import *func(comp *Compilation, pkg_file string) *Package;
|
||||||
Export *func(comp *Compilation) string;
|
Export *func(comp *Compilation, pkg_file string);
|
||||||
Compile *func(flags *Flags, env* Environment, file string);
|
Compile *func(comp *Compilation, src_file string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ export func NewPackage(file_name string, obj *Object, scope *Scope) *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>"; // empty key means package forward declaration
|
||||||
pkg.obj = obj;
|
pkg.obj = obj;
|
||||||
pkg.scope = scope;
|
pkg.scope = scope;
|
||||||
return pkg;
|
return pkg;
|
||||||
|
@ -89,6 +89,12 @@ func main() {
|
|||||||
|
|
||||||
// compile files
|
// compile files
|
||||||
for p := files.first; p != nil; p = p.next {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,9 +132,11 @@ func (I *Importer) ReadPackage() *Globals.Package {
|
|||||||
if I.comp.flags.verbosity > 1 {
|
if I.comp.flags.verbosity > 1 {
|
||||||
print `import: implicitly adding package `, ident, ` "`, file_name, `" (pno = `, obj.pnolev, ")\n";
|
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
|
// 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";
|
panic "package key inconsistency";
|
||||||
}
|
}
|
||||||
I.pkg_list[I.pkg_ref] = pkg;
|
I.pkg_list[I.pkg_ref] = pkg;
|
||||||
@ -198,6 +200,10 @@ func (I *Importer) ReadType() *Globals.Type {
|
|||||||
I.type_ref++;
|
I.type_ref++;
|
||||||
|
|
||||||
switch (typ.form) {
|
switch (typ.form) {
|
||||||
|
case Type.FORWARD:
|
||||||
|
typ.scope = Globals.NewScope(nil);
|
||||||
|
break;
|
||||||
|
|
||||||
case Type.ALIAS, Type.MAP:
|
case Type.ALIAS, Type.MAP:
|
||||||
typ.aux = I.ReadType();
|
typ.aux = I.ReadType();
|
||||||
typ.elt = I.ReadType();
|
typ.elt = I.ReadType();
|
||||||
|
@ -715,9 +715,50 @@ func (P *Parser) ParsePointerType() *Globals.Type {
|
|||||||
typ := Globals.NewType(Type.POINTER);
|
typ := Globals.NewType(Type.POINTER);
|
||||||
|
|
||||||
var elt *Globals.Type;
|
var elt *Globals.Type;
|
||||||
if P.semantic_checks && P.tok == Scanner.IDENT {
|
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 := 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 if P.tok == Scanner.IDENT {
|
||||||
if P.Lookup(P.val) == nil {
|
if P.Lookup(P.val) == nil {
|
||||||
// implicit forward declaration
|
// implicit type forward declaration
|
||||||
// create a named forward type
|
// create a named forward type
|
||||||
pos, ident := P.ParseIdent();
|
pos, ident := P.ParseIdent();
|
||||||
obj := Globals.NewObject(pos, Object.TYPE, ident);
|
obj := Globals.NewObject(pos, Object.TYPE, ident);
|
||||||
@ -746,6 +787,10 @@ func (P *Parser) ParsePointerType() *Globals.Type {
|
|||||||
elt = P.ParseType();
|
elt = P.ParseType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
elt = P.ParseType();
|
||||||
|
}
|
||||||
|
|
||||||
typ.elt = elt;
|
typ.elt = elt;
|
||||||
|
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
@ -1556,22 +1601,10 @@ func (P *Parser) ParseCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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() {
|
func (P *Parser) ParseCaseClause() {
|
||||||
P.Trace("CaseClause");
|
P.Trace("CaseClause");
|
||||||
|
|
||||||
P.ParseCaseList();
|
P.ParseCase();
|
||||||
if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
|
if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
|
||||||
P.ParseStatementList();
|
P.ParseStatementList();
|
||||||
P.Optional(Scanner.SEMICOLON);
|
P.Optional(Scanner.SEMICOLON);
|
||||||
@ -1796,18 +1829,34 @@ func (P *Parser) ParseConstSpec(exported bool) {
|
|||||||
func (P *Parser) ParseTypeSpec(exported bool) {
|
func (P *Parser) ParseTypeSpec(exported bool) {
|
||||||
P.Trace("TypeSpec");
|
P.Trace("TypeSpec");
|
||||||
|
|
||||||
|
var typ *Globals.Type;
|
||||||
|
|
||||||
|
pos, ident := P.ParseIdent();
|
||||||
|
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
|
// Immediately after declaration of the type name, the type is
|
||||||
// considered forward-declared. It may be referred to from inside
|
// considered forward-declared. It may be referred to from inside
|
||||||
// the type specification only via a pointer type.
|
// the type specification only via a pointer type.
|
||||||
typ := Globals.NewType(Type.FORWARD);
|
typ = Globals.NewType(Type.FORWARD);
|
||||||
typ.scope = P.top_scope; // not really needed here, but for consistency
|
typ.scope = P.top_scope; // not really needed here, but for consistency
|
||||||
|
|
||||||
pos, ident := P.ParseIdent();
|
obj = Globals.NewObject(pos, Object.TYPE, ident);
|
||||||
obj := Globals.NewObject(pos, Object.TYPE, ident);
|
|
||||||
obj.exported = exported;
|
obj.exported = exported;
|
||||||
obj.typ = typ;
|
obj.typ = typ;
|
||||||
typ.obj = obj; // primary type object
|
typ.obj = obj; // primary type object
|
||||||
P.Declare(obj);
|
P.Declare(obj);
|
||||||
|
}
|
||||||
|
|
||||||
// If the next token is an identifier and we have a legal program,
|
// If the next token is an identifier and we have a legal program,
|
||||||
// it must be a typename. In that case this declaration introduces
|
// it must be a typename. In that case this declaration introduces
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
package Platform
|
package Platform
|
||||||
|
|
||||||
|
import Utils "utils"
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Environment
|
// Environment
|
||||||
|
|
||||||
@ -54,7 +57,14 @@ export func ReadObjectFile(filename string) (data string, ok bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export func ReadSourceFile(filename string) (data string, ok bool) {
|
export func ReadSourceFile(name string) (data string, ok bool) {
|
||||||
data, ok = sys.readfile(filename + src_file_ext);
|
name = Utils.TrimExt(name, src_file_ext) + src_file_ext;
|
||||||
|
data, ok = sys.readfile(name);
|
||||||
return data, ok;
|
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);
|
||||||
|
}
|
||||||
|
@ -178,7 +178,15 @@ 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.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;
|
print obj.ident;
|
||||||
}
|
}
|
||||||
|
@ -276,12 +276,11 @@ func (S *Scanner) Next() {
|
|||||||
Bit3 = 4;
|
Bit3 = 4;
|
||||||
Bit4 = 3;
|
Bit4 = 3;
|
||||||
|
|
||||||
// TODO 6g constant evaluation incomplete
|
T1 = (1 << (Bit1 + 1) - 1) ^ 0xFF; // 0000 0000
|
||||||
T1 = 0x00; // (1 << (Bit1 + 1) - 1) ^ 0xFF; // 0000 0000
|
Tx = (1 << (Bitx + 1) - 1) ^ 0xFF; // 1000 0000
|
||||||
Tx = 0x80; // (1 << (Bitx + 1) - 1) ^ 0xFF; // 1000 0000
|
T2 = (1 << (Bit2 + 1) - 1) ^ 0xFF; // 1100 0000
|
||||||
T2 = 0xC0; // (1 << (Bit2 + 1) - 1) ^ 0xFF; // 1100 0000
|
T3 = (1 << (Bit3 + 1) - 1) ^ 0xFF; // 1110 0000
|
||||||
T3 = 0xE0; // (1 << (Bit3 + 1) - 1) ^ 0xFF; // 1110 0000
|
T4 = (1 << (Bit4 + 1) - 1) ^ 0xFF; // 1111 0000
|
||||||
T4 = 0xF0; // (1 << (Bit4 + 1) - 1) ^ 0xFF; // 1111 0000
|
|
||||||
|
|
||||||
Rune1 = 1 << (Bit1 + 0*Bitx) - 1; // 0000 0000 0111 1111
|
Rune1 = 1 << (Bit1 + 0*Bitx) - 1; // 0000 0000 0111 1111
|
||||||
Rune2 = 1 << (Bit2 + 1*Bitx) - 1; // 0000 0111 1111 1111
|
Rune2 = 1 << (Bit2 + 1*Bitx) - 1; // 0000 0111 1111 1111
|
||||||
|
Loading…
Reference in New Issue
Block a user