Commit 88da39fe authored by Robert Griesemer's avatar Robert Griesemer

- snapshot before making larger change

R=r
OCL=23403
CL=23403
parent 1b3299ed
......@@ -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
}
......
......@@ -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();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment