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
|
|
|
|
|
|
2016-12-09 17:15:05 -08:00
|
|
|
import "cmd/internal/src"
|
|
|
|
|
|
2016-03-04 17:09:08 -08:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
// Nodes
|
|
|
|
|
|
|
|
|
|
type Node interface {
|
cmd/compile/internal/syntax: establish principled position information
Until now, the parser set the position for each Node to the position of
the first token belonging to that node. For compatibility with the now
defunct gc parser, in many places that position information was modified
when the gcCompat flag was set (which it was, by default). Furthermore,
in some places, position information was not set at all.
This change removes the gcCompat flag and all associated code, and sets
position information for all nodes in a more principled way, as proposed
by mdempsky (see #16943 for details). Specifically, the position of a
node may not be at the very beginning of the respective production. For
instance for an Operation `a + b`, the position associated with the node
is the position of the `+`. Thus, for `a + b + c` we now get different
positions for the two additions.
This change does not pass toolstash -cmp because position information
recorded in export data and pcline tables is different. There are no
other functional changes.
Added test suite testing the position of all nodes.
Fixes #16943.
Change-Id: I3fc02bf096bc3b3d7d2fa655dfd4714a1a0eb90c
Reviewed-on: https://go-review.googlesource.com/37017
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-02-13 16:00:53 -08:00
|
|
|
// Pos() returns the position associated with the node as follows:
|
|
|
|
|
// 1) The position of a node representing a terminal syntax production
|
|
|
|
|
// (Name, BasicLit, etc.) is the position of the respective production
|
|
|
|
|
// in the source.
|
|
|
|
|
// 2) The position of a node representing a non-terminal production
|
|
|
|
|
// (IndexExpr, IfStmt, etc.) is the position of a token uniquely
|
|
|
|
|
// associated with that production; usually the left-most one
|
|
|
|
|
// ('[' for IndexExpr, 'if' for IfStmt, etc.)
|
2016-12-09 17:15:05 -08:00
|
|
|
Pos() src.Pos
|
2016-03-04 17:09:08 -08:00
|
|
|
aNode()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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-12-09 17:15:05 -08:00
|
|
|
pos src.Pos
|
2016-03-04 17:09:08 -08:00
|
|
|
}
|
|
|
|
|
|
2017-03-21 15:22:13 -07:00
|
|
|
func (n *node) Pos() src.Pos { return n.pos }
|
|
|
|
|
func (*node) aNode() {}
|
2016-11-29 16:13:09 -08:00
|
|
|
|
2016-03-04 17:09:08 -08:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
// 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
|
2016-11-29 16:13:09 -08:00
|
|
|
Lines uint
|
2016-03-04 17:09:08 -08:00
|
|
|
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 {
|
2017-03-21 22:23:15 -07:00
|
|
|
Attr map[string]bool // go:attr map
|
|
|
|
|
Recv *Field // nil means regular function
|
|
|
|
|
Name *Name
|
|
|
|
|
Type *FuncType
|
|
|
|
|
Body *BlockStmt // nil means no body (forward declaration)
|
|
|
|
|
Pragma Pragma // 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()
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-24 16:23:21 -07:00
|
|
|
// Placeholder for an expression that failed to parse
|
|
|
|
|
// correctly and where we can't provide a better node.
|
|
|
|
|
BadExpr struct {
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-04 17:09:08 -08:00
|
|
|
// Value
|
|
|
|
|
Name struct {
|
|
|
|
|
Value string
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Value
|
|
|
|
|
BasicLit struct {
|
|
|
|
|
Value string
|
|
|
|
|
Kind LitKind
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type { ElemList[0], ElemList[1], ... }
|
|
|
|
|
CompositeLit struct {
|
2017-03-21 22:23:15 -07:00
|
|
|
Type Expr // nil means no literal type
|
|
|
|
|
ElemList []Expr
|
|
|
|
|
NKeys int // number of elements with keys
|
|
|
|
|
Rbrace src.Pos
|
2016-03-04 17:09:08 -08:00
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Key: Value
|
|
|
|
|
KeyValueExpr struct {
|
|
|
|
|
Key, Value Expr
|
|
|
|
|
expr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// func Type { Body }
|
|
|
|
|
FuncLit struct {
|
2017-03-21 22:23:15 -07:00
|
|
|
Type *FuncType
|
|
|
|
|
Body *BlockStmt
|
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 {
|
2017-03-21 22:23:15 -07:00
|
|
|
List []Stmt
|
2017-03-21 15:22:13 -07:00
|
|
|
Rbrace src.Pos
|
2016-03-04 17:09:08 -08:00
|
|
|
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
|
2017-04-18 20:44:54 -07:00
|
|
|
// Target is the continuation of the control flow after executing
|
|
|
|
|
// the branch; it is computed by the parser if CheckBranches is set.
|
|
|
|
|
// Target is a *LabeledStmt for gotos, and a *SwitchStmt, *SelectStmt,
|
|
|
|
|
// or *ForStmt for breaks and continues, depending on the context of
|
|
|
|
|
// the branch. Target is not set for fallthroughs.
|
|
|
|
|
Target Stmt
|
2016-03-04 17:09:08 -08:00
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CallStmt struct {
|
|
|
|
|
Tok token // Go or Defer
|
|
|
|
|
Call *CallExpr
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReturnStmt struct {
|
|
|
|
|
Results Expr // nil means no explicit return values
|
|
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IfStmt struct {
|
2017-03-21 22:23:15 -07:00
|
|
|
Init SimpleStmt
|
|
|
|
|
Cond Expr
|
|
|
|
|
Then *BlockStmt
|
|
|
|
|
Else Stmt // either *IfStmt or *BlockStmt
|
2016-03-04 17:09:08 -08:00
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ForStmt struct {
|
2017-03-21 22:23:15 -07:00
|
|
|
Init SimpleStmt // incl. *RangeClause
|
|
|
|
|
Cond Expr
|
|
|
|
|
Post SimpleStmt
|
|
|
|
|
Body *BlockStmt
|
2016-03-04 17:09:08 -08:00
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SwitchStmt struct {
|
2017-03-21 15:22:13 -07:00
|
|
|
Init SimpleStmt
|
|
|
|
|
Tag Expr
|
|
|
|
|
Body []*CaseClause
|
|
|
|
|
Rbrace src.Pos
|
2016-03-04 17:09:08 -08:00
|
|
|
stmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SelectStmt struct {
|
2017-03-21 15:22:13 -07:00
|
|
|
Body []*CommClause
|
|
|
|
|
Rbrace src.Pos
|
2016-03-04 17:09:08 -08:00
|
|
|
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
|
2017-03-21 15:22:13 -07:00
|
|
|
Colon src.Pos
|
2016-03-04 17:09:08 -08:00
|
|
|
node
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CommClause struct {
|
2017-03-21 15:22:13 -07:00
|
|
|
Comm SimpleStmt // send or receive stmt; nil means default clause
|
|
|
|
|
Body []Stmt
|
|
|
|
|
Colon src.Pos
|
2016-03-04 17:09:08 -08:00
|
|
|
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
|
|
|
|
|
}
|