diff --git a/usr/gri/pretty/ast.go b/usr/gri/pretty/ast.go index 0a6d3485c5b..3b6c79322ce 100644 --- a/usr/gri/pretty/ast.go +++ b/usr/gri/pretty/ast.go @@ -17,6 +17,7 @@ type ( Type struct; Block struct; + Lit struct; Expr struct; Stat struct; Decl struct; @@ -88,6 +89,18 @@ func (obj *Object) IsExported() bool { } +func (obj* Object) String() string { + if obj != nil { + return + "Object(" + + KindStr(obj.Kind) + ", " + + obj.Ident + + ")"; + } + return "nil"; +} + + var Universe_void_typ *Type // initialized by Universe to Universe.void_typ var objectId int; @@ -99,13 +112,42 @@ func NewObject(pos, kind int, ident string) *Object { obj.Pos = pos; obj.Kind = kind; obj.Ident = ident; - obj.Typ = Universe_void_typ; + obj.Typ = Universe_void_typ; // TODO would it be better to use nil instead? obj.Pnolev = 0; return obj; } +// ---------------------------------------------------------------------------- +// All nodes have a source position and a token. + +type Node struct { + Pos int; // source position (< 0 => unknown position) + Tok int; // identifying token +} + + +// ---------------------------------------------------------------------------- +// Literals + +type Lit struct { + Node; + + // Identifiers + Obj *Object; + + // Constant literals + + // Type literals + Len *Expr; // array length + Dir int; // channel direction + Key *Type; // receiver or map key type + Elt *Type; // array, map, channel, pointer element, or function result type + List *array.Array; End int; // struct fields, interface methods, function parameters +} + + // ---------------------------------------------------------------------------- // Scopes @@ -176,15 +218,6 @@ func (scope *Scope) Print() { } -// ---------------------------------------------------------------------------- -// All nodes have a source position and and token. - -type Node struct { - Pos int; // source position (< 0 => unknown position) - Tok int; // identifying token -} - - // ---------------------------------------------------------------------------- // Blocks // @@ -258,7 +291,7 @@ func NewExpr(pos, tok int, x, y *Expr) *Expr { // TODO probably don't need the tok parameter eventually func NewLit(tok int, obj *Object) *Expr { e := new(Expr); - e.Pos, e.Tok, e.Obj = obj.Pos, tok, obj; + e.Pos, e.Tok, e.Obj, e.Typ = obj.Pos, tok, obj, obj.Typ; return e; } @@ -350,7 +383,7 @@ type Type struct { Ref int; // for exporting only: >= 0 means already exported Form int; // type form Size int; // size in bytes - Obj *Object; // primary type object or NULL + Obj *Object; // primary type object or nil Scope *Scope; // locals, fields & methods // syntactic components @@ -358,7 +391,7 @@ type Type struct { Expr *Expr; // type name, array length Mode int; // channel mode Key *Type; // receiver type or map key - Elt *Type; // array, map, channel or pointer element type, function result type + Elt *Type; // type name type, array, map, channel or pointer element type, function result type List *array.Array; End int; // struct fields, interface methods, function parameters } @@ -397,6 +430,17 @@ func (t *Type) Nfields() int { } +func (typ* Type) String() string { + if typ != nil { + return + "Type(" + + FormStr(typ.Form) + + ")"; + } + return "nil"; +} + + // requires complete Type.Pos access func NewTypeExpr(typ *Type) *Expr { e := new(Expr); @@ -405,6 +449,22 @@ func NewTypeExpr(typ *Type) *Expr { } +// requires complete Type.String access +func (x *Expr) String() string { + if x != nil { + return + "Expr(" + + Scanner.TokenString(x.Tok) + ", " + + x.X.String() + ", " + + x.Y.String() + ", " + + x.Obj.String() + ", " + + x.Typ.String() + + ")"; + } + return "nil"; +} + + var BadType = NewType(0, Scanner.ILLEGAL); @@ -416,7 +476,7 @@ type Stat struct { Init, Post *Stat; Expr *Expr; Body *Block; // composite statement body - Decl *Decl; + Decl *Decl; // declaration statement } diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go index fbea1fcdab5..fc20c2fbea0 100644 --- a/usr/gri/pretty/parser.go +++ b/usr/gri/pretty/parser.go @@ -5,6 +5,7 @@ package Parser import ( + "fmt"; "array"; Scanner "scanner"; AST "ast"; @@ -170,7 +171,7 @@ func (P *Parser) CloseScope() { } -func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int) { +func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int, typ *AST.Type) { if P.scope_lev < 0 { panic("cannot declare objects in other packages"); } @@ -178,10 +179,16 @@ func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int) { assert(x.Tok == Scanner.IDENT); obj := x.Obj; obj.Kind = kind; + obj.Typ = typ; obj.Pnolev = P.scope_lev; - if scope.LookupLocal(obj.Ident) == nil { + switch { + case scope.LookupLocal(obj.Ident) == nil: scope.Insert(obj); - } else { + case kind == AST.TYPE: + // possibly a forward declaration + case kind == AST.FUNC: + // possibly a forward declaration + default: P.Error(obj.Pos, `"` + obj.Ident + `" is declared already`); } } @@ -189,12 +196,12 @@ func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int) { // Declare a comma-separated list of idents or a single ident. -func (P *Parser) Declare(p *AST.Expr, kind int) { +func (P *Parser) Declare(p *AST.Expr, kind int, typ *AST.Type) { for p.Tok == Scanner.COMMA { - P.DeclareInScope(P.top_scope, p.X, kind); + P.DeclareInScope(P.top_scope, p.X, kind, typ); p = p.Y; } - P.DeclareInScope(P.top_scope, p, kind); + P.DeclareInScope(P.top_scope, p, kind, typ); } @@ -344,6 +351,7 @@ func (P *Parser) ParseTypeName() *AST.Type { t := AST.NewType(P.pos, AST.TYPENAME); t.Expr = P.ParseQualifiedIdent(); + t.Elt = t.Expr.Typ; P.Ecart(); return t; @@ -652,7 +660,7 @@ func (P *Parser) ParseStructType() *AST.Type { for i, n := 0, t.List.Len(); i < n; i++ { x := t.List.At(i).(*AST.Expr); if x.Tok == Scanner.IDENT { - P.DeclareInScope(t.Scope, x, AST.FIELD); + P.DeclareInScope(t.Scope, x, AST.FIELD, nil); } } } @@ -741,7 +749,7 @@ func (P *Parser) ParseBlock(ftyp *AST.Type, tok int) *AST.Block { for i, n := 0, ftyp.List.Len(); i < n; i++ { x := ftyp.List.At(i).(*AST.Expr); if x.Tok == Scanner.IDENT { - P.DeclareInScope(P.top_scope, x, AST.VAR); + P.DeclareInScope(P.top_scope, x, AST.VAR, nil); } } } @@ -858,8 +866,8 @@ func (P *Parser) ParseSelectorOrTypeGuard(x *AST.Expr) *AST.Expr { if P.tok == Scanner.IDENT { // TODO should always guarantee x.Typ != nil var scope *AST.Scope; - if x.Typ != nil { - scope = x.Typ.Scope; + if x.X.Typ != nil { + scope = x.X.Typ.Scope; } x.Y = P.ParseIdent(scope); x.Typ = x.Y.Obj.Typ; @@ -1478,10 +1486,6 @@ func (P *Parser) ParseImportSpec(d *AST.Decl) { P.Expect(Scanner.STRING); // use Expect() error handling } - if d.Ident != nil { - P.Declare(d.Ident, AST.PACKAGE); - } - P.Ecart(); } @@ -1496,8 +1500,6 @@ func (P *Parser) ParseConstSpec(d *AST.Decl) { d.Val = P.ParseExpressionList(); } - P.Declare(d.Ident, AST.CONST); - P.Ecart(); } @@ -1528,28 +1530,28 @@ func (P *Parser) ParseVarSpec(d *AST.Decl) { } } - P.Declare(d.Ident, AST.VAR); - P.Ecart(); } func (P *Parser) ParseSpec(d *AST.Decl) { + kind := AST.NONE; + switch d.Tok { - case Scanner.IMPORT: P.ParseImportSpec(d); - case Scanner.CONST: P.ParseConstSpec(d); - case Scanner.TYPE: P.ParseTypeSpec(d); - case Scanner.VAR: P.ParseVarSpec(d); + case Scanner.IMPORT: P.ParseImportSpec(d); kind = AST.PACKAGE; + case Scanner.CONST: P.ParseConstSpec(d); kind = AST.CONST; + case Scanner.TYPE: P.ParseTypeSpec(d); kind = AST.TYPE; + case Scanner.VAR: P.ParseVarSpec(d); kind = AST.VAR; default: unreachable(); } - + // semantic checks if d.Tok == Scanner.IMPORT { - // TODO - } else { - if d.Typ != nil { - // apply type to all variables + if d.Ident != nil { + P.Declare(d.Ident, kind, nil); } + } else { + P.Declare(d.Ident, kind, d.Typ); if d.Val != nil { // initialization/assignment llen := d.Ident.Len();