go/usr/gri/pretty/ast.go

438 lines
8.4 KiB
Go
Raw Normal View History

// 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 AST
import (
"array";
"utf8";
"unicode";
Scanner "scanner";
)
2009-01-20 22:40:40 +00:00
type (
Object struct;
Type struct;
Expr struct;
Stat struct;
Decl struct;
)
// ----------------------------------------------------------------------------
// Objects
// Object represents a language object, such as a constant, variable, type, etc.
2009-01-20 22:40:40 +00:00
const /* kind */ (
BADOBJ = iota; // error handling
NONE; // kind unknown
CONST; TYPE; VAR; FIELD; FUNC; BUILTIN; PACKAGE; LABEL;
END; // end of scope (import/export only)
)
2009-01-20 22:40:40 +00:00
func KindStr(kind int) string {
switch kind {
case BADOBJ: return "BADOBJ";
case NONE: return "NONE";
case CONST: return "CONST";
case TYPE: return "TYPE";
case VAR: return "VAR";
case FIELD: return "FIELD";
case FUNC: return "FUNC";
case BUILTIN: return "BUILTIN";
case PACKAGE: return "PACKAGE";
case LABEL: return "LABEL";
case END: return "END";
}
return "<unknown Object kind>";
}
2009-01-20 22:40:40 +00:00
type Object struct {
2009-01-16 01:16:41 +00:00
Id int; // unique id
2009-01-16 01:16:41 +00:00
Pos int; // source position (< 0 if unknown position)
Kind int; // object kind
Ident string;
Typ *Type; // nil for packages
Pnolev int; // >= 0: package no., <= 0: function nesting level, 0: global level
2009-01-20 22:40:40 +00:00
// attached values
2009-01-16 01:16:41 +00:00
Block *array.Array; End int; // stats for function literals; end of block pos
}
func (obj *Object) IsExported() bool {
2009-01-16 01:16:41 +00:00
switch obj.Kind {
case NONE /* FUNC for now */, CONST, TYPE, VAR, FUNC:
2009-01-16 01:16:41 +00:00
ch, size := utf8.DecodeRuneInString(obj.Ident, 0);
return unicode.IsUpper(ch);
}
return false;
}
2009-01-20 22:40:40 +00:00
var Universe_void_typ *Type // initialized by Universe to Universe.void_typ
2009-01-16 01:16:41 +00:00
var objectId int;
2009-01-20 22:40:40 +00:00
func NewObject(pos, kind int, ident string) *Object {
obj := new(Object);
2009-01-16 01:16:41 +00:00
obj.Id = objectId;
objectId++;
2009-01-20 22:40:40 +00:00
2009-01-16 01:16:41 +00:00
obj.Pos = pos;
obj.Kind = kind;
obj.Ident = ident;
obj.Typ = Universe_void_typ;
obj.Pnolev = 0;
return obj;
}
// ----------------------------------------------------------------------------
// Scopes
2009-01-20 22:40:40 +00:00
type Scope struct {
Parent *Scope;
entries map[string] *Object;
}
2009-01-20 22:40:40 +00:00
func NewScope(parent *Scope) *Scope {
scope := new(Scope);
scope.Parent = parent;
scope.entries = make(map[string]*Object, 8);
return scope;
}
func (scope *Scope) LookupLocal(ident string) *Object {
obj, found := scope.entries[ident];
if found {
return obj;
}
return nil;
}
func (scope *Scope) Lookup(ident string) *Object {
for scope != nil {
obj := scope.LookupLocal(ident);
if obj != nil {
return obj;
}
scope = scope.Parent;
}
return nil;
}
2009-01-16 01:16:41 +00:00
func (scope *Scope) add(obj* Object) {
scope.entries[obj.Ident] = obj;
}
func (scope *Scope) Insert(obj *Object) {
2009-01-16 01:16:41 +00:00
if scope.LookupLocal(obj.Ident) != nil {
panic("obj already inserted");
}
2009-01-16 01:16:41 +00:00
scope.add(obj);
}
func (scope *Scope) InsertImport(obj *Object) *Object {
2009-01-16 01:16:41 +00:00
p := scope.LookupLocal(obj.Ident);
if p == nil {
2009-01-16 01:16:41 +00:00
scope.add(obj);
p = obj;
}
return p;
}
func (scope *Scope) Print() {
print("scope {");
for key := range scope.entries {
print("\n ", key);
}
print("\n}\n");
}
// ----------------------------------------------------------------------------
// All nodes have a source position and and token.
2009-01-20 22:40:40 +00:00
type Node struct {
2009-01-16 01:16:41 +00:00
Pos int; // source position (< 0 => unknown position)
Tok int; // identifying token
}
// ----------------------------------------------------------------------------
// Expressions
2009-01-20 22:40:40 +00:00
type Expr struct {
Node;
2009-01-16 01:16:41 +00:00
X, Y *Expr; // binary (X, Y) and unary (Y) expressions
Obj *Object;
}
func (x *Expr) Len() int {
if x == nil {
return 0;
}
n := 1;
2009-01-16 01:16:41 +00:00
for ; x.Tok == Scanner.COMMA; x = x.Y {
n++;
}
return n;
}
2009-01-20 22:40:40 +00:00
func NewExpr(pos, tok int, x, y *Expr) *Expr {
2009-01-16 01:16:41 +00:00
if x != nil && x.Tok == Scanner.TYPE || y != nil && y.Tok == Scanner.TYPE {
panic("no type expression allowed");
}
e := new(Expr);
2009-01-16 01:16:41 +00:00
e.Pos, e.Tok, e.X, e.Y = pos, tok, x, y;
return e;
}
// TODO probably don't need the tok parameter eventually
2009-01-20 22:40:40 +00:00
func NewLit(tok int, obj *Object) *Expr {
e := new(Expr);
2009-01-16 01:16:41 +00:00
e.Pos, e.Tok, e.Obj = obj.Pos, tok, obj;
return e;
}
2009-01-20 22:40:40 +00:00
var BadExpr = NewExpr(0, Scanner.ILLEGAL, nil, nil);
// ----------------------------------------------------------------------------
// Types
2009-01-20 22:40:40 +00:00
const /* form */ (
// internal types
// We should never see one of these.
UNDEF = iota;
2009-01-20 22:40:40 +00:00
// VOID types are used when we don't have a type. Never exported.
// (exported type forms must be > 0)
VOID;
2009-01-20 22:40:40 +00:00
// BADTYPE types are compatible with any type and don't cause further errors.
// They are introduced only as a result of an error in the source code. A
// correct program cannot have BAD types.
BADTYPE;
2009-01-20 22:40:40 +00:00
// FORWARD types are forward-declared (incomplete) types. They can only
// be used as element types of pointer types and must be resolved before
// their internals are accessible.
FORWARD;
// TUPLE types represent multi-valued result types of functions and
// methods.
TUPLE;
2009-01-20 22:40:40 +00:00
// The type of nil.
NIL;
// A type name
TYPENAME;
// basic types
BOOL; UINT; INT; FLOAT; STRING; INTEGER;
2009-01-20 22:40:40 +00:00
// composite types
ALIAS; ARRAY; STRUCT; INTERFACE; MAP; CHANNEL; FUNCTION; METHOD; POINTER;
2009-01-20 22:40:40 +00:00
// open-ended parameter type
ELLIPSIS
)
2009-01-20 22:40:40 +00:00
func FormStr(form int) string {
switch form {
case VOID: return "VOID";
case BADTYPE: return "BADTYPE";
case FORWARD: return "FORWARD";
case TUPLE: return "TUPLE";
case NIL: return "NIL";
case TYPENAME: return "TYPENAME";
case BOOL: return "BOOL";
case UINT: return "UINT";
case INT: return "INT";
case FLOAT: return "FLOAT";
case STRING: return "STRING";
case ALIAS: return "ALIAS";
case ARRAY: return "ARRAY";
case STRUCT: return "STRUCT";
case INTERFACE: return "INTERFACE";
case MAP: return "MAP";
case CHANNEL: return "CHANNEL";
case FUNCTION: return "FUNCTION";
case METHOD: return "METHOD";
case POINTER: return "POINTER";
case ELLIPSIS: return "ELLIPSIS";
}
return "<unknown Type form>";
}
2009-01-20 22:40:40 +00:00
const /* channel mode */ (
FULL = iota;
SEND;
RECV;
)
2009-01-20 22:40:40 +00:00
type Type struct {
2009-01-16 01:16:41 +00:00
Id int; // unique id
2009-01-16 01:16:41 +00:00
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
Scope *Scope; // forwards, structs, interfaces, functions
// syntactic components
2009-01-16 01:16:41 +00:00
Pos int; // source position (< 0 if unknown position)
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
List *array.Array; End int; // struct fields, interface methods, function parameters
Scope *Scope; // struct fields, methods
}
2009-01-16 01:16:41 +00:00
var typeId int;
2009-01-20 22:40:40 +00:00
func NewType(pos, form int) *Type {
typ := new(Type);
2009-01-16 01:16:41 +00:00
typ.Id = typeId;
typeId++;
2009-01-16 01:16:41 +00:00
typ.Ref = -1; // not yet exported
typ.Pos = pos;
typ.Form = form;
return typ;
}
2009-01-16 01:16:41 +00:00
func (t *Type) Nfields() int {
if t.List == nil {
return 0;
}
nx, nt := 0, 0;
2009-01-16 01:16:41 +00:00
for i, n := 0, t.List.Len(); i < n; i++ {
if t.List.At(i).(*Expr).Tok == Scanner.TYPE {
nt++;
} else {
nx++;
}
}
if nx == 0 {
return nt;
}
return nx;
}
2009-01-16 01:16:41 +00:00
// requires complete Type.Pos access
2009-01-20 22:40:40 +00:00
func NewTypeExpr(typ *Type) *Expr {
2009-01-16 01:16:41 +00:00
obj := NewObject(typ.Pos, TYPE, "");
obj.Typ = typ;
return NewLit(Scanner.TYPE, obj);
}
2009-01-20 22:40:40 +00:00
var BadType = NewType(0, Scanner.ILLEGAL);
// ----------------------------------------------------------------------------
// Statements
2009-01-20 22:40:40 +00:00
type Stat struct {
Node;
2009-01-16 01:16:41 +00:00
Init, Post *Stat;
Expr *Expr;
Block *array.Array; End int; // block end position
Decl *Decl;
}
2009-01-20 22:40:40 +00:00
func NewStat(pos, tok int) *Stat {
s := new(Stat);
2009-01-16 01:16:41 +00:00
s.Pos, s.Tok = pos, tok;
return s;
}
2009-01-20 22:40:40 +00:00
var BadStat = NewStat(0, Scanner.ILLEGAL);
// ----------------------------------------------------------------------------
// Declarations
2009-01-20 22:40:40 +00:00
type Decl struct {
Node;
2009-01-16 01:16:41 +00:00
Ident *Expr; // nil for ()-style declarations
Typ *Type;
Val *Expr;
// list of *Decl for ()-style declarations
// list of *Stat for func declarations (or nil for forward decl)
2009-01-16 01:16:41 +00:00
List *array.Array; End int;
}
func NewDecl(pos, tok int) *Decl {
d := new(Decl);
d.Pos, d.Tok = pos, tok;
return d;
}
var BadDecl = NewDecl(0, Scanner.ILLEGAL);
// ----------------------------------------------------------------------------
// Program
2009-01-20 22:40:40 +00:00
type Comment struct {
2009-01-16 01:16:41 +00:00
Pos int;
Text string;
}
2009-01-20 22:40:40 +00:00
func NewComment(pos int, text string) *Comment {
c := new(Comment);
2009-01-16 01:16:41 +00:00
c.Pos, c.Text = pos, text;
return c;
}
2009-01-20 22:40:40 +00:00
type Program struct {
2009-01-16 01:16:41 +00:00
Pos int; // tok is Scanner.PACKAGE
Ident *Expr;
Decls *array.Array;
Comments *array.Array;
}
2009-01-20 22:40:40 +00:00
func NewProgram(pos int) *Program {
p := new(Program);
2009-01-16 01:16:41 +00:00
p.Pos = pos;
return p;
}