]> Cypherpunks repositories - gostls13.git/commitdiff
- added more code (package, export, compilation)
authorRobert Griesemer <gri@golang.org>
Tue, 15 Jul 2008 22:37:14 +0000 (15:37 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 15 Jul 2008 22:37:14 +0000 (15:37 -0700)
- first cut at semantic checks (disabled)

SVN=127348

usr/gri/gosrc/compilation.go [new file with mode: 0644]
usr/gri/gosrc/export.go [new file with mode: 0755]
usr/gri/gosrc/globals.go
usr/gri/gosrc/object.go
usr/gri/gosrc/package.go [new file with mode: 0644]
usr/gri/gosrc/parser.go
usr/gri/gosrc/universe.go

diff --git a/usr/gri/gosrc/compilation.go b/usr/gri/gosrc/compilation.go
new file mode 100644 (file)
index 0000000..c520d00
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package Compilation
+
+import Globals "globals"
+import Object "object"
+import Type "type"
+import Package "package"
+import Scanner "scanner"
+import Parser "parser"
+
+
+export Compilation
+type Compilation struct {
+  src_name string;
+  pkg *Globals.Object;
+  imports *Globals.List;  // a list of *Globals.Package
+}
+
+
+func (C *Compilation) Lookup(pkg_name string) *Package.Package {
+       panic "UNIMPLEMENTED";
+       return nil;
+}
+
+
+func (C *Compilation) Insert(pkg *Package.Package) {
+       panic "UNIMPLEMENTED";
+}
+
+
+func (C *Compilation) InsertImport(pkg *Package.Package) *Package.Package {
+       panic "UNIMPLEMENTED";
+       return nil;
+}
+
+
+func (C *Compilation) Import(pkg_name string) (pno int) {
+       panic "UNIMPLEMENTED";
+}
+
+
+func (C *Compilation) Export() {
+       panic "UNIMPLEMENTED";
+}
+
+
+export Compile
+func Compile() {
+}
diff --git a/usr/gri/gosrc/export.go b/usr/gri/gosrc/export.go
new file mode 100755 (executable)
index 0000000..9cc2a03
--- /dev/null
@@ -0,0 +1,302 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package Exporter
+
+import Globals "globals"
+import Object "object"
+import Type "type"
+import Package "package"
+
+
+type Exporter struct {
+       /*
+       Compilation* comp;
+       */
+       debug bool;
+       buf [4*1024] byte;
+       pos int;
+       pkg_ref int;
+       type_ref int;
+};
+
+
+func (E *Exporter) WriteType(typ *Globals.Type);
+func (E *Exporter) WriteObject(obj *Globals.Object);
+func (E *Exporter) WritePackage(pkg *Package.Package) ;
+
+
+func (E *Exporter) WriteByte(x byte) {
+       E.buf[E.pos] = x;
+       E.pos++;
+       if E.debug {
+               print " ", x;
+       }
+}
+
+
+func (E *Exporter) WriteInt(x int) {
+       if E.debug {
+               print " #", x;
+       }
+       for x < -64 || x >= 64 {
+               E.WriteByte(byte(x & 127));
+               x = int(uint(x >> 7));  // arithmetic shift
+       }
+       // -64 <= x && x < 64
+       E.WriteByte(byte(x + 192));
+}
+
+
+func (E *Exporter) WriteString(s string) {
+       if E.debug {
+               print `"`, s, `"`;
+       }
+       n := len(s);
+       E.WriteInt(n);
+       for i := 0; i < n; i++ {
+               E.WriteByte(s[i]);
+       }
+}
+
+
+func (E *Exporter) WriteObjTag(tag int) {
+       if tag < 0 {
+               panic "tag < 0";
+       }
+       if E.debug {
+               print "\nO: ", tag;  // obj kind
+       }
+       E.WriteInt(tag);
+}
+
+
+func (E *Exporter) WriteTypeTag(tag int) {
+       if E.debug {
+               if tag > 0 {
+                       print "\nT", E.type_ref, ": ", tag;  // type form
+               } else {
+                       print " [T", -tag, "]";  // type ref
+               }
+       }
+       E.WriteInt(tag);
+}
+
+
+func (E *Exporter) WritePackageTag(tag int) {
+       if E.debug {
+               if tag > 0 {
+                       print "\nP", E.pkg_ref, ": ", tag;  // package no
+               } else {
+                       print " [P", -tag, "]";  // package ref
+               }
+       }
+       E.WriteInt(tag);
+}
+
+
+func (E *Exporter) WriteTypeField(fld *Globals.Object) {
+       if fld.kind != Object.VAR {
+               panic "fld.kind != Object.VAR";
+       }
+       E.WriteType(fld.typ);
+}
+
+
+func (E *Exporter) WriteScope(scope *Globals.Scope) {
+       if E.debug {
+               print " {";
+       }
+
+       // determine number of objects to export
+       n := 0;
+       for p := scope.entries.first; p != nil; p = p.next {
+               if p.obj.mark {
+                       n++;
+               }                       
+       }
+       
+       // export the objects, if any
+       if n > 0 {
+               for p := scope.entries.first; p != nil; p = p.next {
+                       if p.obj.mark {
+                               E.WriteObject(p.obj);
+                       }                       
+               }
+       }
+
+       if E.debug {
+               print " }";
+       }
+}
+
+
+func (E *Exporter) WriteObject(obj *Globals.Object) {
+       if obj == nil || !obj.mark {
+               panic "obj == nil || !obj.mark";
+       }
+
+       if obj.kind == Object.TYPE && obj.typ.obj == obj {
+               // primary type object - handled entirely by WriteType()
+               E.WriteObjTag(Object.PTYPE);
+               E.WriteType(obj.typ);
+
+       } else {
+               E.WriteObjTag(obj.kind);
+               E.WriteString(obj.ident);
+               E.WriteType(obj.typ);
+               panic "UNIMPLEMENTED";
+               //E.WritePackage(E.comp.packages[obj.pnolev]);
+
+               switch obj.kind {
+               case Object.BAD: fallthrough;
+               case Object.PACKAGE: fallthrough;
+               case Object.PTYPE:
+                       panic "UNREACHABLE";
+               case Object.CONST:
+                       E.WriteInt(0);  // should be the correct value
+                       break;
+               case Object.TYPE:
+                       // nothing to do
+               case Object.VAR:
+                       E.WriteInt(0);  // should be the correct address/offset
+               case Object.FUNC:
+                       E.WriteInt(0);  // should be the correct address/offset
+               default:
+                       panic "UNREACHABLE";
+               }
+       }
+}
+
+
+func (E *Exporter) WriteType(typ *Globals.Type) {
+       if typ == nil {
+               panic "typ == nil";
+       }
+
+       if typ.ref >= 0 {
+               E.WriteTypeTag(-typ.ref);  // type already exported
+               return;
+       }
+
+       if typ.form <= 0 {
+               panic "typ.form <= 0";
+       }
+       E.WriteTypeTag(typ.form);
+       typ.ref = E.type_ref;
+       E.type_ref++;
+
+       if typ.obj != nil {
+               if typ.obj.typ != typ {
+                       panic "typ.obj.type() != typ";  // primary type
+               }
+               E.WriteString(typ.obj.ident);
+               panic "UNIMPLEMENTED";
+               //WritePackage(E.comp.packages[typ.obj.pnolev]);
+       } else {
+               E.WriteString("");
+       }
+
+       switch typ.form {
+       case Type.UNDEF: fallthrough;
+       case Type.BAD: fallthrough;
+       case Type.NIL: fallthrough;
+       case Type.BOOL: fallthrough;
+       case Type.UINT: fallthrough;
+       case Type.INT: fallthrough;
+       case Type.FLOAT: fallthrough;
+       case Type.STRING: fallthrough;
+       case Type.ANY:
+               panic "UNREACHABLE";
+
+       case Type.ARRAY:
+               E.WriteInt(typ.len_);
+               E.WriteTypeField(typ.elt);
+
+       case Type.MAP:
+               E.WriteTypeField(typ.key);
+               E.WriteTypeField(typ.elt);
+
+       case Type.CHANNEL:
+               E.WriteInt(typ.flags);
+               E.WriteTypeField(typ.elt);
+
+       case Type.FUNCTION:
+               E.WriteInt(typ.flags);
+               fallthrough;
+       case Type.STRUCT: fallthrough;
+       case Type.INTERFACE:
+               E.WriteScope(typ.scope);
+
+       case Type.POINTER: fallthrough;
+       case Type.REFERENCE:
+               E.WriteTypeField(typ.elt);
+
+       default:
+               panic "UNREACHABLE";
+       }
+}
+
+
+func (E *Exporter) WritePackage(pkg *Package.Package) {
+       if pkg.ref >= 0 {
+               E.WritePackageTag(-pkg.ref);  // package already exported
+               return;
+       }
+
+       if Object.PACKAGE <= 0 {
+               panic "Object.PACKAGE <= 0";
+       }
+       E.WritePackageTag(Object.PACKAGE);
+       pkg.ref = E.pkg_ref;
+       E.pkg_ref++;
+
+       E.WriteString(pkg.ident);
+       E.WriteString(pkg.path);
+       E.WriteString(pkg.key);
+}
+
+
+func (E *Exporter) Export(/*Compilation* comp, BBuffer* buf*/) {
+       panic "UNIMPLEMENTED";
+       
+       /*
+       E.comp = comp;
+       E.buf = buf;
+       E.pak_ref = 0;
+       E.nbytes = 0;
+       */
+
+       // Predeclared types are "pre-exported".
+       /*
+       #ifdef DEBUG
+       for (int i = 0; i < Universe.types.len(); i++) {
+       ASSERT(Universe.types[i].ref == i);
+       }
+       #endif
+       E.type_ref = Universe.types.len();
+       */
+       
+       var pkg *Package.Package = nil; // comp.packages[0];
+       E.WritePackage(pkg);
+       for p := pkg.scope.entries.first; p != nil; p = p.next {
+               if p.obj.mark {
+                       E.WriteObject(p.obj);
+               }
+       }
+       E.WriteObjTag(0);
+
+       if E.debug {
+               print "\n(", E.pos, ")\n";
+       }
+}
+
+
+export Export
+func Export(/*Compilation* comp, BBuffer* buf*/) {
+       /*
+       Exporter exp;
+       exp.Export(comp, buf);
+       */
+}
index a689eaa945bbade29bede4a906e60194211bd0da..1518fc1ad97210958915462d5b6d2e13c33707e9 100644 (file)
@@ -16,6 +16,7 @@ package Globals
 export Object
 type Object struct {
        mark bool;  // mark => object marked for export
+       pos int;  // source position
        kind int;
        ident string;
        typ *Type;
@@ -67,9 +68,10 @@ type Scope struct {
 // Creation
 
 export NewObject
-func NewObject(kind int, ident string) *Object {
+func NewObject(pos, kind int, ident string) *Object {
        obj := new(Object);
        obj.mark = false;
+       obj.pos = pos;
        obj.kind = kind;
        obj.ident = ident;
        obj.typ = nil;  // Universe::undef_t;
index 1f3c04180d099a6e604f182254037940dd22ccd2..fba2b3cf2266e1fb9d08f1a8f347627db8689219 100755 (executable)
@@ -7,7 +7,7 @@ package Object
 import Globals "globals"
 
 
-export BAD, CONST, TYPE, VAR, FUNC, PACKAGE
+export BAD, CONST, TYPE, VAR, FUNC, PACKAGE, PTYPE
 const /* kind */ (
        BAD = iota;  // error handling
        CONST; TYPE; VAR; FUNC; PACKAGE;
diff --git a/usr/gri/gosrc/package.go b/usr/gri/gosrc/package.go
new file mode 100644 (file)
index 0000000..fa2578b
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package Package
+
+import Globals "globals"
+
+export Package
+type Package struct {
+       ref int;
+       ident string;
+       path string;
+       key string;
+       scope *Globals.Scope;
+}
+
+
+export NewPackage;
+func NewPackage() *Package {
+       pkg := new(Package);
+       return pkg;
+}
index 24b0c7c38822079206ee49afa72ebfcae7f29b43..dc80cb878726cd1bfa03e686c1b93537604b1d54 100644 (file)
@@ -6,9 +6,15 @@ package Parser
 
 import Scanner "scanner"
 import Globals "globals"
+import Object "object"
+import Type "type"
 import Universe "universe"
 
 
+// So I can submit and have a running parser for now...
+const EnableSemanticTests = false;
+
+
 export Parser
 type Parser struct {
        verbose, indent int;
@@ -20,6 +26,9 @@ type Parser struct {
 }
 
 
+// ----------------------------------------------------------------------------
+// Support functions
+
 func (P *Parser) PrintIndent() {
        for i := P.indent; i > 0; i-- {
                print ". ";
@@ -52,7 +61,7 @@ func (P *Parser) Next() {
        }
        if P.verbose > 1 {
                P.PrintIndent();
-               print Scanner.TokenName(P.tok), "\n";
+               print "[", P.beg, "] ", Scanner.TokenName(P.tok), "\n";
        }
 }
 
@@ -68,16 +77,14 @@ func (P *Parser) Open(S *Scanner.Scanner, verbose int) {
 
 func (P *Parser) Error(pos int, msg string) {
        P.S.Error(pos, msg);
-       P.Next();  // make progress
 }
 
 
 func (P *Parser) Expect(tok int) {
-       if P.tok == tok {
-               P.Next()
-       } else {
+       if P.tok != tok {
                P.Error(P.beg, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'");
        }
+       P.Next();  // make progress in any case
 }
 
 
@@ -89,6 +96,7 @@ func (P *Parser) Optional(tok int) {
 
 
 // ----------------------------------------------------------------------------
+// Scopes
 
 func (P *Parser) OpenScope() {
        P.top_scope = Globals.NewScope(P.top_scope);
@@ -112,9 +120,13 @@ func (P *Parser) Lookup(ident string) *Globals.Object {
 
 
 func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) {
+       if !EnableSemanticTests {
+               return;
+       }
+       
        if scope.Lookup(obj.ident) != nil {
                // TODO is this the correct error position?
-               P.Error(P.beg, `"` + obj.ident + `" is declared already`);
+               P.Error(obj.pos, `"` + obj.ident + `" is declared already`);
                return;  // don't insert it into the scope
        }
        scope.Insert(obj);
@@ -130,18 +142,56 @@ func (P *Parser) Declare(obj *Globals.Object) {
 // Common productions
 
 
-func (P *Parser) TryType() bool;
+func (P *Parser) TryType() *Globals.Type;
 func (P *Parser) ParseExpression();
 func (P *Parser) TryStatement() bool;
 func (P *Parser) ParseDeclaration();
 
 
-func (P *Parser) ParseIdent() {
-       if P.verbose > 0 {
-               P.PrintIndent();
-               print "Ident = \"", P.ident, "\"\n";
+func (P *Parser) ParseIdent() string {
+       P.Trace("Ident");
+
+       ident := "";
+       if P.tok == Scanner.IDENT {
+               ident = P.ident;
+               if P.verbose > 0 {
+                       P.PrintIndent();
+                       print "Ident = \"", ident, "\"\n";
+               }
+               P.Next();
+       } else {
+               P.Expect(Scanner.IDENT);  // use Expect() error handling
        }
-       P.Expect(Scanner.IDENT);
+       
+       P.Ecart();
+       return ident;
+}
+
+
+func (P *Parser) ParseIdentDecl(kind int) *Globals.Object {
+       P.Trace("IdentDecl");
+       
+       pos := P.beg;
+       obj := Globals.NewObject(pos, kind, P.ParseIdent());
+       P.Declare(obj);
+       
+       P.Ecart();
+       return obj;
+}
+
+
+func (P *Parser) ParseIdentDeclList(kind int) *Globals.List {
+       P.Trace("IdentDeclList");
+       
+       list := Globals.NewList();
+       list.AddObj(P.ParseIdentDecl(kind));
+       for P.tok == Scanner.COMMA {
+               P.Next();
+               list.AddObj(P.ParseIdentDecl(kind));
+       }
+       
+       P.Ecart();
+       return list;
 }
 
 
@@ -156,37 +206,76 @@ func (P *Parser) ParseIdentList() {
 }
 
 
-func (P *Parser) ParseQualifiedIdent() {
+func (P *Parser) ParseQualifiedIdent() *Globals.Object {
        P.Trace("QualifiedIdent");
-       P.ParseIdent();
-       if P.tok == Scanner.PERIOD {
-               P.Next();
+
+       if EnableSemanticTests {
+               pos := P.beg;
+               ident := P.ParseIdent();
+               obj := P.Lookup(ident);
+               if obj == nil {
+                       P.Error(pos, `"` + ident + `" is not declared`);
+                       obj = Globals.NewObject(pos, Object.BAD, ident);
+               }
+
+               if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD {
+                       panic "Qualified ident not complete yet";
+                       P.Next();
+                       P.ParseIdent();
+               }
+               P.Ecart();
+               return obj;
+               
+       } else {
                P.ParseIdent();
+               if P.tok == Scanner.PERIOD {
+                       P.Next();
+                       P.ParseIdent();
+               }
+               P.Ecart();
+               return nil;
        }
-       P.Ecart();
 }
 
 
 // ----------------------------------------------------------------------------
 // Types
 
-func (P *Parser) ParseType() {
+func (P *Parser) ParseType() *Globals.Type{
        P.Trace("Type");
-       if !P.TryType() {
+       
+       typ := P.TryType();
+       if typ == nil {
                P.Error(P.beg, "type expected");
+               typ = Universe.bad_t;
        }
+       
        P.Ecart();
+       return typ;
 }
 
 
-func (P *Parser) ParseTypeName() {
+func (P *Parser) ParseTypeName() *Globals.Type {
        P.Trace("TypeName");
-       P.ParseQualifiedIdent();
-       P.Ecart();
+       
+       if EnableSemanticTests {
+               obj := P.ParseQualifiedIdent();
+               typ := obj.typ;
+               if obj.kind != Object.TYPE {
+                       P.Error(obj.pos, `"` + obj.ident + `" is not a type`);
+                       typ = Universe.bad_t;
+               }
+               P.Ecart();
+               return typ;
+       } else {
+               P.ParseQualifiedIdent();
+               P.Ecart();
+               return Universe.bad_t;
+       }
 }
 
 
-func (P *Parser) ParseArrayType() {
+func (P *Parser) ParseArrayType() *Globals.Type {
        P.Trace("ArrayType");
        P.Expect(Scanner.LBRACK);
        if P.tok != Scanner.RBRACK {
@@ -195,10 +284,11 @@ func (P *Parser) ParseArrayType() {
        P.Expect(Scanner.RBRACK);
        P.ParseType();
        P.Ecart();
+       return Universe.bad_t;
 }
 
 
-func (P *Parser) ParseChannelType() {
+func (P *Parser) ParseChannelType() *Globals.Type {
        P.Trace("ChannelType");
        P.Expect(Scanner.CHAN);
        switch P.tok {
@@ -208,6 +298,7 @@ func (P *Parser) ParseChannelType() {
        }
        P.ParseType();
        P.Ecart();
+       return Universe.bad_t;
 }
 
 
@@ -249,7 +340,7 @@ func (P *Parser) TryResult() bool {
                P.ParseParameters();
                res = true;
        } else {
-               res = P.TryType();
+               res = P.TryType() != nil;
        }
        P.Ecart();
        return res;
@@ -302,11 +393,12 @@ func (P *Parser) ParseNamedSignature() {
 }
 
 
-func (P *Parser) ParseFunctionType() {
+func (P *Parser) ParseFunctionType() *Globals.Type {
        P.Trace("FunctionType");
        P.Expect(Scanner.FUNC);
        P.ParseAnonymousSignature();
        P.Ecart();
+       return Universe.bad_t;
 }
 
 
@@ -320,7 +412,7 @@ func (P *Parser) ParseMethodDecl() {
 }
 
 
-func (P *Parser) ParseInterfaceType() {
+func (P *Parser) ParseInterfaceType() *Globals.Type {
        P.Trace("InterfaceType");
        P.Expect(Scanner.INTERFACE);
        P.Expect(Scanner.LBRACE);
@@ -331,10 +423,11 @@ func (P *Parser) ParseInterfaceType() {
        P.CloseScope();
        P.Next();
        P.Ecart();
+       return Universe.bad_t;
 }
 
 
-func (P *Parser) ParseMapType() {
+func (P *Parser) ParseMapType() *Globals.Type {
        P.Trace("MapType");
        P.Expect(Scanner.MAP);
        P.Expect(Scanner.LBRACK);
@@ -342,23 +435,32 @@ func (P *Parser) ParseMapType() {
        P.Expect(Scanner.RBRACK);
        P.ParseType();
        P.Ecart();
+       return Universe.bad_t;
 }
 
 
 func (P *Parser) ParseFieldDecl() {
        P.Trace("FieldDecl");
-       P.ParseIdentList();
-       P.ParseType();
+       
+       list := P.ParseIdentDeclList(Object.VAR);
+       typ := P.ParseType();  // TODO should check completeness of types
+       for p := list.first; p != nil; p = p.next {
+               p.obj.typ = typ;  // TODO should use/have set_type()
+       }
+       
        P.Ecart();
 }
 
 
-func (P *Parser) ParseStructType() {
+func (P *Parser) ParseStructType() *Globals.Type {
        P.Trace("StructType");
+       
        P.Expect(Scanner.STRUCT);
        P.Expect(Scanner.LBRACE);
        P.OpenScope();
-       for P.tok != Scanner.RBRACE {
+       typ := Globals.NewType(Type.STRUCT);
+       typ.scope = P.top_scope;
+       for P.tok == Scanner.IDENT {
                P.ParseFieldDecl();
                if P.tok != Scanner.RBRACE {
                        P.Expect(Scanner.SEMICOLON);
@@ -367,43 +469,39 @@ func (P *Parser) ParseStructType() {
        P.Optional(Scanner.SEMICOLON);
        P.CloseScope();
        P.Expect(Scanner.RBRACE);
+       
        P.Ecart();
+       return typ;
 }
 
 
-func (P *Parser) ParsePointerType() {
+func (P *Parser) ParsePointerType() *Globals.Type {
        P.Trace("PointerType");
        P.Expect(Scanner.MUL);
        P.ParseType();
        P.Ecart();
+       return Universe.bad_t;
 }
 
 
-func (P *Parser) TryType() bool {
+// Returns nil if no type was found.
+func (P *Parser) TryType() *Globals.Type {
        P.Trace("Type (try)");
+       
+       var typ *Globals.Type = nil;
        switch P.tok {
-       case Scanner.IDENT:
-               P.ParseTypeName();
-       case Scanner.LBRACK:
-               P.ParseArrayType();
-       case Scanner.CHAN:
-               P.ParseChannelType();
-       case Scanner.INTERFACE:
-               P.ParseInterfaceType();
-       case Scanner.FUNC:
-               P.ParseFunctionType();
-       case Scanner.MAP:
-               P.ParseMapType();
-       case Scanner.STRUCT:
-               P.ParseStructType();
-       case Scanner.MUL:
-               P.ParsePointerType();
-       default:
-               P.Ecart();
-               return false;
+       case Scanner.IDENT: typ = P.ParseTypeName();
+       case Scanner.LBRACK: typ = P.ParseArrayType();
+       case Scanner.CHAN: typ = P.ParseChannelType();
+       case Scanner.INTERFACE: typ = P.ParseInterfaceType();
+       case Scanner.FUNC: typ = P.ParseFunctionType();
+       case Scanner.MAP: typ = P.ParseMapType();
+       case Scanner.STRUCT: typ = P.ParseStructType();
+       case Scanner.MUL: typ = P.ParsePointerType();
        }
+
        P.Ecart();
-       return true;
+       return typ;
 }
 
 
@@ -414,6 +512,7 @@ func (P *Parser) ParseStatement() {
        P.Trace("Statement");
        if !P.TryStatement() {
                P.Error(P.beg, "statement expected");
+               P.Next();  // make progress
        }
        P.Ecart();
 }
@@ -500,6 +599,7 @@ func (P *Parser) ParseOperand() {
                P.ParseNew();
        default:
                P.Error(P.beg, "operand expected");
+               P.Next();  // make progress
        }
        P.Ecart();
 }
@@ -903,8 +1003,9 @@ func (P *Parser) TryStatement() bool {
        case Scanner.FUNC:
                // for now we do not allow local function declarations
                fallthrough;
+       case Scanner.LSS: fallthrough;
        case Scanner.GTR:
-               P.ParseSimpleStat();  // send
+               P.ParseSimpleStat();  // send or receive
        case Scanner.IDENT:
                switch P.ident {
                case "print", "panic":
@@ -947,18 +1048,21 @@ func (P *Parser) TryStatement() bool {
 
 func (P *Parser) ParseImportSpec() {
        P.Trace("ImportSpec");
+       
        if P.tok == Scanner.PERIOD {
                P.Next();
        } else if P.tok == Scanner.IDENT {
                P.Next();
        }
        P.Expect(Scanner.STRING);
+       
        P.Ecart();
 }
 
 
 func (P *Parser) ParseImportDecl() {
        P.Trace("ImportDecl");
+       
        P.Expect(Scanner.IMPORT);
        if P.tok == Scanner.LPAREN {
                P.Next();
@@ -970,24 +1074,33 @@ func (P *Parser) ParseImportDecl() {
        } else {
                P.ParseImportSpec();
        }
+       
        P.Ecart();
 }
 
 
 func (P *Parser) ParseConstSpec() {
        P.Trace("ConstSpec");
-       P.ParseIdent();
-       P.TryType();
+       
+       list := P.ParseIdentDeclList(Object.CONST);
+       typ := P.TryType();
+       if typ != nil {
+               for p := list.first; p != nil; p = p.next {
+                       p.obj.typ = typ;  // TODO should use/have set_type()!
+               }
+       }
        if P.tok == Scanner.ASSIGN {
                P.Next();
-               P.ParseExpression();
+               P.ParseExpressionList();
        }
+       
        P.Ecart();
 }
 
 
 func (P *Parser) ParseConstDecl() {
        P.Trace("ConstDecl");
+       
        P.Expect(Scanner.CONST);
        if P.tok == Scanner.LPAREN {
                P.Next();
@@ -1001,20 +1114,45 @@ func (P *Parser) ParseConstDecl() {
        } else {
                P.ParseConstSpec();
        }
+       
        P.Ecart();
 }
 
 
 func (P *Parser) ParseTypeSpec() {
        P.Trace("TypeSpec");
-       P.ParseIdent();
-       P.TryType();
+       
+       pos := P.beg;
+       ident := P.ParseIdent();
+       obj := P.top_scope.Lookup(ident);  // only lookup in top scope!
+       if obj != nil {
+               // ok if forward declared type
+               if obj.kind != Object.TYPE || obj.typ.form != Type.UNDEF {
+                       // TODO use obj.pos to refer to decl pos in error msg!
+                       P.Error(pos, `"` + ident + `" is declared already`);
+               }
+       } else {
+               obj = Globals.NewObject(pos, Object.TYPE, ident);
+               obj.typ = Universe.undef_t;  // TODO fix this
+               P.top_scope.Insert(obj);
+       }
+       
+       typ := P.TryType();  // no type if we have a forward decl
+       if typ != nil {
+               // TODO what about the name of incomplete types?
+               obj.typ = typ;  // TODO should use/have set_typ()!
+               if typ.obj == nil {
+                       typ.obj = obj;  // primary type object
+               }
+       }
+       
        P.Ecart();
 }
 
 
 func (P *Parser) ParseTypeDecl() {
        P.Trace("TypeDecl");
+       
        P.Expect(Scanner.TYPE);
        if P.tok == Scanner.LPAREN {
                P.Next();
@@ -1028,29 +1166,36 @@ func (P *Parser) ParseTypeDecl() {
        } else {
                P.ParseTypeSpec();
        }
+       
        P.Ecart();
 }
 
 
 func (P *Parser) ParseVarSpec() {
        P.Trace("VarSpec");
-       P.ParseIdentList();
+       
+       list := P.ParseIdentDeclList(Object.VAR);
        if P.tok == Scanner.ASSIGN {
                P.Next();
                P.ParseExpressionList();
        } else {
-               P.ParseType();
+               typ := P.ParseType();
+               for p := list.first; p != nil; p = p.next {
+                       p.obj.typ = typ;  // TODO should use/have set_type()!
+               }
                if P.tok == Scanner.ASSIGN {
                        P.Next();
                        P.ParseExpressionList();
                }
        }
+       
        P.Ecart();
 }
 
 
 func (P *Parser) ParseVarDecl() {
        P.Trace("VarDecl");
+       
        P.Expect(Scanner.VAR);
        if P.tok == Scanner.LPAREN {
                P.Next();
@@ -1064,12 +1209,14 @@ func (P *Parser) ParseVarDecl() {
        } else {
                P.ParseVarSpec();
        }
+       
        P.Ecart();
 }
 
 
 func (P *Parser) ParseFuncDecl() {
        P.Trace("FuncDecl");
+       
        P.Expect(Scanner.FUNC);
        P.ParseNamedSignature();
        if P.tok == Scanner.SEMICOLON {
@@ -1078,12 +1225,14 @@ func (P *Parser) ParseFuncDecl() {
        } else {
                P.ParseBlock();
        }
+       
        P.Ecart();
 }
 
 
 func (P *Parser) ParseExportDecl() {
        P.Trace("ExportDecl");
+       
        P.Expect(Scanner.EXPORT);
        if P.tok == Scanner.LPAREN {
                P.Next();
@@ -1099,12 +1248,14 @@ func (P *Parser) ParseExportDecl() {
                        P.ParseIdent();
                }
        }
+       
        P.Ecart();
 }
 
 
 func (P *Parser) ParseDeclaration() {
        P.Trace("Declaration");
+       
        indent := P.indent;
        switch P.tok {
        case Scanner.CONST:
@@ -1119,10 +1270,12 @@ func (P *Parser) ParseDeclaration() {
                P.ParseExportDecl();
        default:
                P.Error(P.beg, "declaration expected");
+               P.Next();  // make progress
        }
        if indent != P.indent {
                panic "imbalanced tracing code"
        }
+       
        P.Ecart();
 }
 
index 0e545eb9ef72a869ea6c3ebd56dde5cf565af9e0..8fa8953bc44aef3050a3229e07ae05c4ee0856b6 100755 (executable)
@@ -67,7 +67,7 @@ var (
 
 
 func DeclObj(kind int, ident string, typ *Globals.Type) *Globals.Object {
-       obj := Globals.NewObject(kind, ident);
+       obj := Globals.NewObject(-1 /* no source pos */, kind, ident);
        obj.typ = typ;
        if kind == Object.TYPE && typ.obj == nil {
                typ.obj = obj;  // set primary type object