2008-10-20 16:03:40 -06:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
2008-10-14 19:14:01 -06:00
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2008-10-20 16:03:40 -06:00
|
|
|
package AST
|
2008-10-14 19:14:01 -06:00
|
|
|
|
|
|
|
import Scanner "scanner"
|
|
|
|
|
|
|
|
|
|
|
|
type (
|
2008-10-23 18:56:54 -06:00
|
|
|
Any interface {};
|
2008-10-14 19:14:01 -06:00
|
|
|
Type struct;
|
|
|
|
Expr struct;
|
|
|
|
Stat struct;
|
|
|
|
Decl struct;
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Lists
|
|
|
|
//
|
|
|
|
// If p is a list and p == nil, then p.len() == 0.
|
|
|
|
// Thus, empty lists can be represented by nil.
|
|
|
|
|
|
|
|
export type List struct {
|
2008-10-23 18:56:54 -06:00
|
|
|
a *[] Any;
|
2008-10-14 19:14:01 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (p *List) len() int {
|
|
|
|
if p == nil { return 0; }
|
|
|
|
return len(p.a);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-23 18:56:54 -06:00
|
|
|
func (p *List) at(i int) Any {
|
2008-10-14 19:14:01 -06:00
|
|
|
return p.a[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-23 18:56:54 -06:00
|
|
|
func (p *List) set(i int, x Any) {
|
2008-10-15 18:06:28 -06:00
|
|
|
p.a[i] = x;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-26 22:32:30 -06:00
|
|
|
func (p *List) Add(x Any) {
|
2008-10-14 19:14:01 -06:00
|
|
|
a := p.a;
|
|
|
|
n := len(a);
|
|
|
|
|
|
|
|
if n == cap(a) {
|
2008-10-23 18:56:54 -06:00
|
|
|
b := new([] Any, 2*n);
|
2008-10-14 19:14:01 -06:00
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
b[i] = a[i];
|
|
|
|
}
|
|
|
|
a = b;
|
|
|
|
}
|
|
|
|
|
|
|
|
a = a[0 : n + 1];
|
|
|
|
a[n] = x;
|
|
|
|
p.a = a;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-26 22:32:30 -06:00
|
|
|
func (p *List) Pop() Any {
|
|
|
|
a := p.a;
|
|
|
|
n := len(a);
|
|
|
|
|
|
|
|
var x Any;
|
|
|
|
if n > 0 {
|
|
|
|
x = a[n - 1];
|
|
|
|
a = a[0 : n - 1];
|
|
|
|
p.a = a;
|
|
|
|
} else {
|
|
|
|
panic("pop from empty list");
|
|
|
|
}
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-14 19:14:01 -06:00
|
|
|
export func NewList() *List {
|
|
|
|
p := new(List);
|
2008-10-23 18:56:54 -06:00
|
|
|
p.a = new([] Any, 10) [0 : 0];
|
2008-10-14 19:14:01 -06:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-23 18:56:54 -06:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// All nodes have a source position and and token.
|
|
|
|
|
|
|
|
export type Node struct {
|
|
|
|
pos, tok int;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-14 19:14:01 -06:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Expressions
|
|
|
|
|
|
|
|
export type Expr struct {
|
2008-10-23 18:56:54 -06:00
|
|
|
Node;
|
2008-10-14 19:14:01 -06:00
|
|
|
x, y *Expr; // binary (x, y) and unary (y) expressions
|
2008-10-17 17:19:31 -06:00
|
|
|
// TODO find a more space efficient way to hold these
|
2008-10-15 12:48:18 -06:00
|
|
|
s string; // identifiers and literals
|
2008-10-17 17:19:31 -06:00
|
|
|
t *Type; // type expressions, function literal types
|
|
|
|
block *List; // stats for function literals
|
2008-10-14 19:14:01 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (x *Expr) len() int {
|
|
|
|
if x == nil {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
n := 1;
|
|
|
|
for ; x.tok == Scanner.COMMA; x = x.y {
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export func NewExpr(pos, tok int, x, y *Expr) *Expr {
|
2008-10-17 00:30:42 -06:00
|
|
|
if x != nil && x.tok == Scanner.TYPE || y != nil && y.tok == Scanner.TYPE {
|
|
|
|
panic("no type expression allowed");
|
|
|
|
}
|
2008-10-14 19:14:01 -06:00
|
|
|
e := new(Expr);
|
|
|
|
e.pos, e.tok, e.x, e.y = pos, tok, x, y;
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-15 12:48:18 -06:00
|
|
|
export func NewLit(pos, tok int, s string) *Expr {
|
2008-10-14 19:14:01 -06:00
|
|
|
e := new(Expr);
|
2008-10-15 12:48:18 -06:00
|
|
|
e.pos, e.tok, e.s = pos, tok, s;
|
2008-10-14 19:14:01 -06:00
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-17 17:19:31 -06:00
|
|
|
export var BadExpr = NewExpr(0, Scanner.ILLEGAL, nil, nil);
|
|
|
|
|
|
|
|
|
2008-10-16 13:16:50 -06:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Types
|
|
|
|
|
|
|
|
export const /* channel mode */ (
|
|
|
|
FULL = iota;
|
|
|
|
SEND;
|
|
|
|
RECV;
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
export type Type struct {
|
2008-10-23 18:56:54 -06:00
|
|
|
Node;
|
2008-10-16 13:16:50 -06:00
|
|
|
expr *Expr; // type name, array length
|
|
|
|
mode int; // channel mode
|
|
|
|
key *Type; // receiver type, map key
|
|
|
|
elt *Type; // array element, map or channel value, or pointer base type, result type
|
|
|
|
list *List; // struct fields, interface methods, function parameters
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (t *Type) nfields() int {
|
|
|
|
nx, nt := 0, 0;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export func NewType(pos, tok int) *Type {
|
|
|
|
t := new(Type);
|
|
|
|
t.pos, t.tok = pos, tok;
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// requires complete Type type
|
|
|
|
export func NewTypeExpr(t *Type) *Expr {
|
2008-10-15 18:06:28 -06:00
|
|
|
e := new(Expr);
|
2008-10-16 13:16:50 -06:00
|
|
|
e.pos, e.tok, e.t = t.pos, Scanner.TYPE, t;
|
2008-10-15 18:06:28 -06:00
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-17 17:19:31 -06:00
|
|
|
export var BadType = NewType(0, Scanner.ILLEGAL);
|
|
|
|
|
|
|
|
|
2008-10-14 19:14:01 -06:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Statements
|
|
|
|
|
|
|
|
export type Stat struct {
|
2008-10-23 18:56:54 -06:00
|
|
|
Node;
|
2008-10-15 12:48:18 -06:00
|
|
|
init, post *Stat;
|
2008-10-20 11:01:34 -06:00
|
|
|
expr *Expr;
|
2008-10-14 19:14:01 -06:00
|
|
|
block *List;
|
|
|
|
decl *Decl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export func NewStat(pos, tok int) *Stat {
|
|
|
|
s := new(Stat);
|
|
|
|
s.pos, s.tok = pos, tok;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-17 17:19:31 -06:00
|
|
|
export var BadStat = NewStat(0, Scanner.ILLEGAL);
|
|
|
|
|
|
|
|
|
2008-10-14 19:14:01 -06:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Declarations
|
|
|
|
|
|
|
|
export type Decl struct {
|
2008-10-23 18:56:54 -06:00
|
|
|
Node;
|
2008-10-14 19:14:01 -06:00
|
|
|
exported bool;
|
|
|
|
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)
|
|
|
|
list *List;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export func NewDecl(pos, tok int, exported bool) *Decl {
|
|
|
|
d := new(Decl);
|
|
|
|
d.pos, d.tok, d.exported = pos, tok, exported;
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-17 17:19:31 -06:00
|
|
|
export var BadDecl = NewDecl(0, Scanner.ILLEGAL, false);
|
|
|
|
|
|
|
|
|
2008-10-14 19:14:01 -06:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Program
|
|
|
|
|
2008-10-17 00:30:42 -06:00
|
|
|
export type Comment struct {
|
|
|
|
pos int;
|
|
|
|
text string;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export func NewComment(pos int, text string) *Comment {
|
|
|
|
c := new(Comment);
|
|
|
|
c.pos, c.text = pos, text;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-14 19:14:01 -06:00
|
|
|
export type Program struct {
|
|
|
|
pos int; // tok is Scanner.PACKAGE
|
|
|
|
ident *Expr;
|
|
|
|
decls *List;
|
2008-10-17 00:30:42 -06:00
|
|
|
comments *List;
|
2008-10-14 19:14:01 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export func NewProgram(pos int) *Program {
|
|
|
|
p := new(Program);
|
|
|
|
p.pos = pos;
|
|
|
|
return p;
|
|
|
|
}
|