- 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
diff --git a/usr/gri/gosrc/parser.go b/usr/gri/gosrc/parser.go
index 2e2e6fa..2ca3a0f 100644
--- a/usr/gri/gosrc/parser.go
+++ b/usr/gri/gosrc/parser.go
@@ -715,33 +715,78 @@
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 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);
+ }
} 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();
+ elt = P.ParseType();
}
-
- // collect uses of pointer types referring to forward types
- if elt.form == Type.FORWARD {
- P.forward_types.AddTyp(typ);
- }
-
+
} else {
elt = P.ParseType();
}
@@ -1556,22 +1601,10 @@
}
-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);
@@ -1796,19 +1829,35 @@
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.