From a6f87794ffcadb0adec683b5a6f38685d209998a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 15 Jul 2008 15:37:14 -0700 Subject: [PATCH] - added more code (package, export, compilation) - first cut at semantic checks (disabled) SVN=127348 --- usr/gri/gosrc/compilation.go | 52 ++++++ usr/gri/gosrc/export.go | 302 +++++++++++++++++++++++++++++++++++ usr/gri/gosrc/globals.go | 4 +- usr/gri/gosrc/object.go | 2 +- usr/gri/gosrc/package.go | 23 +++ usr/gri/gosrc/parser.go | 277 +++++++++++++++++++++++++------- usr/gri/gosrc/universe.go | 2 +- 7 files changed, 597 insertions(+), 65 deletions(-) create mode 100644 usr/gri/gosrc/compilation.go create mode 100755 usr/gri/gosrc/export.go create mode 100644 usr/gri/gosrc/package.go diff --git a/usr/gri/gosrc/compilation.go b/usr/gri/gosrc/compilation.go new file mode 100644 index 00000000000..c520d00fe1c --- /dev/null +++ b/usr/gri/gosrc/compilation.go @@ -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 index 00000000000..9cc2a030192 --- /dev/null +++ b/usr/gri/gosrc/export.go @@ -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); + */ +} diff --git a/usr/gri/gosrc/globals.go b/usr/gri/gosrc/globals.go index a689eaa945b..1518fc1ad97 100644 --- a/usr/gri/gosrc/globals.go +++ b/usr/gri/gosrc/globals.go @@ -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; diff --git a/usr/gri/gosrc/object.go b/usr/gri/gosrc/object.go index 1f3c04180d0..fba2b3cf226 100755 --- a/usr/gri/gosrc/object.go +++ b/usr/gri/gosrc/object.go @@ -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 index 00000000000..fa2578b9634 --- /dev/null +++ b/usr/gri/gosrc/package.go @@ -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; +} diff --git a/usr/gri/gosrc/parser.go b/usr/gri/gosrc/parser.go index 24b0c7c3882..dc80cb87872 100644 --- a/usr/gri/gosrc/parser.go +++ b/usr/gri/gosrc/parser.go @@ -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(); } diff --git a/usr/gri/gosrc/universe.go b/usr/gri/gosrc/universe.go index 0e545eb9ef7..8fa8953bc44 100755 --- a/usr/gri/gosrc/universe.go +++ b/usr/gri/gosrc/universe.go @@ -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