mirror of
https://github.com/golang/go
synced 2024-11-22 06:24:38 -07:00
- snapshot before making larger change
R=r OCL=23403 CL=23403
This commit is contained in:
parent
1b3299ed0b
commit
88da39feea
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user