2016-03-04 17:09:08 -08:00
|
|
|
// Copyright 2016 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 syntax
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
// Nodes
|
|
|
|
|
|
|
|
|
|
type Node interface {
|
2016-08-16 13:33:29 -07:00
|
|
|
Line() uint32
|
2016-03-04 17:09:08 -08:00
|
|
|
aNode()
|
2016-08-30 16:31:53 -07:00
|
|
|
init(p *parser)
|
2016-03-04 17:09:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type node struct {
|
2016-11-29 10:18:06 -08:00
|
|
|
// commented out for now since not yet used
|
|
|
|
|
// doc *Comment // nil means no comment(s) attached
|
2016-03-04 17:09:08 -08:00
|
|
|
pos uint32
|
|
|
|
|
line uint32
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (*node) aNode() {}
|
|
|
|
|
|
2016-08-16 13:33:29 -07:00
|
|
|
func (n *node) Line() uint32 {
|
|
|
|
|
return n.line
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-04 17:09:08 -08:00
|
|
|
func (n *node) init(p *parser) {
|
|
|
|
|
n.pos = uint32(p.pos)
|
|
|
|
|
n.line = uint32(p.line)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
// Files
|
|
|
|
|
|
2016-11-04 16:37:24 -07:00
|
|
|
// package PkgName; DeclList[0], DeclList[1], ...
|
2016-03-04 17:09:08 -08:00
|
|
|
type File struct {
|
|
|
|
|
PkgName *Name
|
|
|
|
|
DeclList []Decl
|
|
|
|
|
Lines int
|
|
|
|
|
node
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
// Declarations
|
|
|
|
|
|
|
|
|
|
type (
|
|
|
|
|
Decl interface {
|
|
|
|
|
Node
|
|
|
|
|
aDecl()
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-04 16:37:24 -07:00
|
|
|
// Path
|
|
|
|
|
// LocalPkgName Path
|
2016-03-04 17:09:08 -08:00
|
|
|
ImportDecl struct {
|
|
|
|
|
LocalPkgName *Name // including "."; nil means no rename present
|
|
|
|
|
Path *BasicLit
|
|
|
|
|
Group *Group // nil means not part of a group
|
|
|
|
|
decl
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-04 16:37:24 -07:00
|
|
|
// NameList
|
|
|
|
|
// NameList = Values
|
|
|
|
|
// NameList Type = Values
|
2016-03-04 17:09:08 -08:00
|
|
|
ConstDecl struct {
|
|
|
|
|
NameList []*Name
|
|
|
|
|
Type Expr // nil means no type
|
|
|
|
|
Values Expr // nil means no values
|
|
|
|
|
Group *Group // nil means not part of a group
|
|
|
|
|
decl
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-04 16:37:24 -07:00
|
|
|
// Name Type
|
2016-03-04 17:09:08 -08:00
|
|
|
TypeDecl struct {
|
cmd/compile: add go:notinheap type pragma
This adds a //go:notinheap pragma for declarations of types that must
not be heap allocated. We ensure these rules by disallowing new(T),
make([]T), append([]T), or implicit allocation of T, by disallowing
conversions to notinheap types, and by propagating notinheap to any
struct or array that contains notinheap elements.
The utility of this pragma is that we can eliminate write barriers for
writes to pointers to go:notinheap types, since the write barrier is
guaranteed to be a no-op. This will let us mark several scheduler and
memory allocator structures as go:notinheap, which will let us
disallow write barriers in the scheduler and memory allocator much
more thoroughly and also eliminate some problematic hybrid write
barriers.
This also makes go:nowritebarrierrec and go:yeswritebarrierrec much
more powerful. Currently we use go:nowritebarrier all over the place,
but it's almost never what you actually want: when write barriers are
illegal, they're typically illegal for a whole dynamic scope. Partly
this is because go:nowritebarrier has been around longer, but it's
also because go:nowritebarrierrec couldn't be used in situations that
had no-op write barriers or where some nested scope did allow write
barriers. go:notinheap eliminates many no-op write barriers and
go:yeswritebarrierrec makes it possible to opt back in to write
barriers, so these two changes will let us use go:nowritebarrierrec
far more liberally.
This updates #13386, which is about controlling pointers from non-GC'd
memory to GC'd memory. That would require some additional pragma (or
pragmas), but could build on this pragma.
Change-Id: I6314f8f4181535dd166887c9ec239977b54940bd
Reviewed-on: https://go-review.googlesource.com/30939
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-10-11 22:53:27 -04:00
|
|
|
Name *Name
|
2016-12-16 16:28:30 -08:00
|
|
|
Alias bool
|
cmd/compile: add go:notinheap type pragma
This adds a //go:notinheap pragma for declarations of types that must
not be heap allocated. We ensure these rules by disallowing new(T),
make([]T), append([]T), or implicit allocation of T, by disallowing
conversions to notinheap types, and by propagating notinheap to any
struct or array that contains notinheap elements.
The utility of this pragma is that we can eliminate write barriers for
writes to pointers to go:notinheap types, since the write barrier is
guaranteed to be a no-op. This will let us mark several scheduler and
memory allocator structures as go:notinheap, which will let us
disallow write barriers in the scheduler and memory allocator much
more thoroughly and also eliminate some problematic hybrid write
barriers.
This also makes go:nowritebarrierrec and go:yeswritebarrierrec much
more powerful. Currently we use go:nowritebarrier all over the place,
but it's almost never what you actually want: when write barriers are
illegal, they're typically illegal for a whole dynamic scope. Partly
this is because go:nowritebarrier has been around longer, but it's
also because go:nowritebarrierrec couldn't be used in situations that
had no-op write barriers or where some nested scope did allow write
barriers. go:notinheap eliminates many no-op write barriers and
go:yeswritebarrierrec makes it possible to opt back in to write
barriers, so these two changes will let us use go:nowritebarrierrec
far more liberally.
This updates #13386, which is about controlling pointers from non-GC'd
memory to GC'd memory. That would require some additional pragma (or
pragmas), but could build on this pragma.
Change-Id: I6314f8f4181535dd166887c9ec239977b54940bd
Reviewed-on: https://go-review.googlesource.com/30939
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-10-11 22:53:27 -04:00
|
|
|
Type Expr
|
|
|
|
|
Group *Group // nil means not part of a group
|
|
|
|
|
Pragma Pragma
|
2016-03-04 17:09:08 -08:00
|
|
|
decl
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-04 16:37:24 -07:00
|
|
|
// NameList Type
|
|
|
|
|
// NameList Type = Values
|
|
|
|
|
// NameList = Values
|
2016-03-04 17:09:08 -08:00
|
|
|
VarDecl struct {
|
|
|
|
|
NameList []*Name
|
|
|
|
|
Type Expr // nil means no type
|
|
|
|
|
Values Expr // nil means no values
|
|
|
|
|
Group *Group // nil means not part of a group
|
|
|
|
|
decl
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-04 16:37:24 -07:00
|
|
|
// func Name Type { Body }
|
|
|
|
|
// func Name Type
|
|
|
|
|
// func Receiver Name Type { Body }
|
|
|
|
|
// func Receiver Name Type
|
2016-03-04 17:09:08 -08:00
|
|
|
FuncDecl struct {
|
2016-08-16 13:33:29 -07:00
|
|
|
Attr map[string]bool // go:attr map
|
|
|
|
|
Recv *Field // nil means regular function
|
|
|
|
|
Name *Name
|
|
|
|
|
Type *FuncType
|
|
|
|
|
Body []Stmt // nil means no body (forward declaration)
|
2016-08-30 16:31:53 -07:00
|
|
|
Pragma Pragma // TODO(mdempsky): Cleaner solution.
|
2016-08-16 13:33:29 -07:00
|
|
|
EndLine uint32 // TODO(mdempsky): Cleaner solution.
|
2016-03-04 17:09:08 -08:00
|
|
|
decl
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type decl struct{ node }
|
|
|
|
|
|
|
|
|
|
func (*decl) aDecl() {}
|
|
|
|
|
|
|
|
|
|
// All declarations belonging to the same group point to the same Group node.
|
|
|
|
|
type Group struct {
|
|
|
|
|
dummy int // not empty so we are guaranteed different Group instances
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
// Expressions
|
|
|
|
|
|
|
|
|
|
type (
|
|
|
|
|
Expr interface {
|
|
|
|
|
Node
|
|
|
|
|
aExpr()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Value
|
|
|
|
|
Name struct {
|
|
|
|
|
Value string
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Value
|
|
|
|
|
BasicLit struct {
|
|
|
|
|
Value string
|
|
|
|
|
Kind LitKind
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type { ElemList[0], ElemList[1], ... }
|
|
|
|
|
CompositeLit struct {
|
|
|
|
|
Type Expr // nil means no literal type
|
|
|
|
|
ElemList []Expr
|
2016-08-30 16:31:53 -07:00
|
|
|
NKeys int // number of elements with keys
|
|
|
|
|
EndLine uint32 // TODO(mdempsky): Cleaner solution.
|
2016-03-04 17:09:08 -08:00
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Key: Value
|
|
|
|
|
KeyValueExpr struct {
|
|
|
|
|
Key, Value Expr
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// func Type { Body }
|
|
|
|
|
FuncLit struct {
|
2016-08-16 13:33:29 -07:00
|
|
|
Type *FuncType
|
|
|
|
|
Body []Stmt
|
|
|
|
|
EndLine uint32 // TODO(mdempsky): Cleaner solution.
|
2016-03-04 17:09:08 -08:00
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// (X)
|
|
|
|
|
ParenExpr struct {
|
|
|
|
|
X Expr
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// X.Sel
|
|
|
|
|
SelectorExpr struct {
|
|
|
|
|
X Expr
|
|
|
|
|
Sel *Name
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// X[Index]
|
|
|
|
|
IndexExpr struct {
|
|
|
|
|
X Expr
|
|
|
|
|
Index Expr
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// X[Index[0] : Index[1] : Index[2]]
|
|
|
|
|
SliceExpr struct {
|
|
|
|
|
X Expr
|
|
|
|
|
Index [3]Expr
|
2016-08-16 13:33:29 -07:00
|
|
|
// Full indicates whether this is a simple or full slice expression.
|
|
|
|
|
// In a valid AST, this is equivalent to Index[2] != nil.
|
|
|
|
|
// TODO(mdempsky): This is only needed to report the "3-index
|
|
|
|
|
// slice of string" error when Index[2] is missing.
|
|
|
|
|
Full bool
|
2016-03-04 17:09:08 -08:00
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// X.(Type)
|
|
|
|
|
AssertExpr struct {
|
|
|
|
|
X Expr
|
|
|
|
|
// TODO(gri) consider using Name{"..."} instead of nil (permits attaching of comments)
|
|
|
|
|
Type Expr
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Operation struct {
|
|
|
|
|
Op Operator
|
|
|
|
|
X, Y Expr // Y == nil means unary expression
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fun(ArgList[0], ArgList[1], ...)
|
|
|
|
|
CallExpr struct {
|
|
|
|
|
Fun Expr
|
|
|
|
|
ArgList []Expr
|
|
|
|
|
HasDots bool // last argument is followed by ...
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ElemList[0], ElemList[1], ...
|
|
|
|
|
ListExpr struct {
|
|
|
|
|
ElemList []Expr
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// [Len]Elem
|
|
|
|
|
ArrayType struct {
|
|
|
|
|
// TODO(gri) consider using Name{"..."} instead of nil (permits attaching of comments)
|
|
|
|
|
Len Expr // nil means Len is ...
|
|
|
|
|
Elem Expr
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// []Elem
|
|
|
|
|
SliceType struct {
|
|
|
|
|
Elem Expr
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ...Elem
|
|
|
|
|
DotsType struct {
|
|
|
|
|
Elem Expr
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// struct { FieldList[0] TagList[0]; FieldList[1] TagList[1]; ... }
|
|
|
|
|
StructType struct {
|
|
|
|
|
FieldList []*Field
|
|
|
|
|
TagList []*BasicLit // i >= len(TagList) || TagList[i] == nil means no tag for field i
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Name Type
|
|
|
|
|
// Type
|
|
|
|
|
Field struct {
|
|
|
|
|
Name *Name // nil means anonymous field/parameter (structs/parameters), or embedded interface (interfaces)
|
|
|
|
|
Type Expr // field names declared in a list share the same Type (identical pointers)
|
|
|
|
|
node
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// interface { MethodList[0]; MethodList[1]; ... }
|
|
|
|
|
InterfaceType struct {
|
|
|
|
|
MethodList []*Field
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FuncType struct {
|
|
|
|
|
ParamList []*Field
|
|
|
|
|
ResultList []*Field
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// map[Key]Value
|
|
|
|
|
MapType struct {
|
|
|
|
|
Key Expr
|
|
|
|
|
Value Expr
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// chan Elem
|
|
|
|
|
// <-chan Elem
|
|
|
|
|
// chan<- Elem
|
|
|
|
|
ChanType struct {
|
|
|
|
|
Dir ChanDir // 0 means no direction
|
|
|
|
|
Elem Expr
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type expr struct{ node }
|
|
|
|
|
|
|
|
|
|
func (*expr) aExpr() {}
|
|
|
|
|
|
|
|
|
|
type ChanDir uint
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
_ ChanDir = iota
|
|
|
|
|
SendOnly
|
|
|
|
|
RecvOnly
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
// Statements
|
|
|
|
|
|
|
|
|
|
type (
|
|
|
|
|
Stmt interface {
|
|
|
|
|
Node
|
|
|
|
|
aStmt()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SimpleStmt interface {
|
|
|
|
|
Stmt
|
|
|
|
|
aSimpleStmt()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EmptyStmt struct {
|
|
|
|
|
simpleStmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LabeledStmt struct {
|
|
|
|
|
Label *Name
|
|
|
|
|
Stmt Stmt
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BlockStmt struct {
|
|
|
|
|
Body []Stmt
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExprStmt struct {
|
|
|
|
|
X Expr
|
|
|
|
|
simpleStmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SendStmt struct {
|
|
|
|
|
Chan, Value Expr // Chan <- Value
|
|
|
|
|
simpleStmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeclStmt struct {
|
|
|
|
|
DeclList []Decl
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AssignStmt struct {
|
|
|
|
|
Op Operator // 0 means no operation
|
|
|
|
|
Lhs, Rhs Expr // Rhs == ImplicitOne means Lhs++ (Op == Add) or Lhs-- (Op == Sub)
|
|
|
|
|
simpleStmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BranchStmt struct {
|
|
|
|
|
Tok token // Break, Continue, Fallthrough, or Goto
|
|
|
|
|
Label *Name
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CallStmt struct {
|
|
|
|
|
Tok token // Go or Defer
|
|
|
|
|
Call *CallExpr
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReturnStmt struct {
|
|
|
|
|
Results Expr // nil means no explicit return values
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IfStmt struct {
|
|
|
|
|
Init SimpleStmt
|
|
|
|
|
Cond Expr
|
|
|
|
|
Then []Stmt
|
|
|
|
|
Else Stmt // either *IfStmt or *BlockStmt
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ForStmt struct {
|
|
|
|
|
Init SimpleStmt // incl. *RangeClause
|
|
|
|
|
Cond Expr
|
|
|
|
|
Post SimpleStmt
|
|
|
|
|
Body []Stmt
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SwitchStmt struct {
|
|
|
|
|
Init SimpleStmt
|
|
|
|
|
Tag Expr
|
|
|
|
|
Body []*CaseClause
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SelectStmt struct {
|
|
|
|
|
Body []*CommClause
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type (
|
|
|
|
|
RangeClause struct {
|
|
|
|
|
Lhs Expr // nil means no Lhs = or Lhs :=
|
|
|
|
|
Def bool // means :=
|
|
|
|
|
X Expr // range X
|
|
|
|
|
simpleStmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TypeSwitchGuard struct {
|
|
|
|
|
// TODO(gri) consider using Name{"..."} instead of nil (permits attaching of comments)
|
|
|
|
|
Lhs *Name // nil means no Lhs :=
|
|
|
|
|
X Expr // X.(type)
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CaseClause struct {
|
|
|
|
|
Cases Expr // nil means default clause
|
|
|
|
|
Body []Stmt
|
|
|
|
|
node
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CommClause struct {
|
|
|
|
|
Comm SimpleStmt // send or receive stmt; nil means default clause
|
|
|
|
|
Body []Stmt
|
|
|
|
|
node
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type stmt struct{ node }
|
|
|
|
|
|
|
|
|
|
func (stmt) aStmt() {}
|
|
|
|
|
|
|
|
|
|
type simpleStmt struct {
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (simpleStmt) aSimpleStmt() {}
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
// Comments
|
|
|
|
|
|
2016-11-04 16:37:24 -07:00
|
|
|
// TODO(gri) Consider renaming to CommentPos, CommentPlacement, etc.
|
|
|
|
|
// Kind = Above doesn't make much sense.
|
2016-03-04 17:09:08 -08:00
|
|
|
type CommentKind uint
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
Above CommentKind = iota
|
|
|
|
|
Below
|
|
|
|
|
Left
|
|
|
|
|
Right
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Comment struct {
|
|
|
|
|
Kind CommentKind
|
|
|
|
|
Text string
|
|
|
|
|
Next *Comment
|
|
|
|
|
}
|