mirror of
https://github.com/golang/go
synced 2024-11-19 05:04:43 -07:00
cmd/compile: give ChanDir a type
Change-Id: I03621db79637b04982e1f0e7b4268c4ed2db6d22 Reviewed-on: https://go-review.googlesource.com/21484 Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
73edd7b208
commit
386c0e6598
@ -316,7 +316,7 @@ func (p *importer) typ() *Type {
|
||||
|
||||
case chanTag:
|
||||
t = p.newtyp(TCHAN)
|
||||
t.Chan = uint8(p.int())
|
||||
t.Chan = ChanDir(p.int())
|
||||
t.Type = p.typ()
|
||||
|
||||
default:
|
||||
|
@ -1154,7 +1154,7 @@ func exprfmt(n *Node, prec int) string {
|
||||
return fmt.Sprintf("map[%v]%v", n.Left, n.Right)
|
||||
|
||||
case OTCHAN:
|
||||
switch n.Etype {
|
||||
switch ChanDir(n.Etype) {
|
||||
case Crecv:
|
||||
return fmt.Sprintf("<-chan %v", n.Left)
|
||||
|
||||
@ -1162,7 +1162,7 @@ func exprfmt(n *Node, prec int) string {
|
||||
return fmt.Sprintf("chan<- %v", n.Left)
|
||||
|
||||
default:
|
||||
if n.Left != nil && n.Left.Op == OTCHAN && n.Left.Sym == nil && n.Left.Etype == Crecv {
|
||||
if n.Left != nil && n.Left.Op == OTCHAN && n.Left.Sym == nil && ChanDir(n.Left.Etype) == Crecv {
|
||||
return fmt.Sprintf("chan (%v)", n.Left)
|
||||
} else {
|
||||
return fmt.Sprintf("chan %v", n.Left)
|
||||
|
@ -128,12 +128,18 @@ const (
|
||||
CTNIL
|
||||
)
|
||||
|
||||
// ChanDir is whether a channel can send, receive, or both.
|
||||
type ChanDir uint8
|
||||
|
||||
func (c ChanDir) CanRecv() bool { return c&Crecv != 0 }
|
||||
func (c ChanDir) CanSend() bool { return c&Csend != 0 }
|
||||
|
||||
const (
|
||||
// types of channel
|
||||
// must match ../../../../reflect/type.go:/ChanDir
|
||||
Crecv = 1 << 0
|
||||
Csend = 1 << 1
|
||||
Cboth = Crecv | Csend
|
||||
Crecv ChanDir = 1 << 0
|
||||
Csend ChanDir = 1 << 1
|
||||
Cboth ChanDir = Crecv | Csend
|
||||
)
|
||||
|
||||
// The Class of a variable/function describes the "storage class"
|
||||
|
@ -1187,17 +1187,17 @@ func (p *parser) uexpr() *Node {
|
||||
|
||||
if x.Op == OTCHAN {
|
||||
// x is a channel type => re-associate <-
|
||||
dir := EType(Csend)
|
||||
dir := Csend
|
||||
t := x
|
||||
for ; t.Op == OTCHAN && dir == Csend; t = t.Left {
|
||||
dir = t.Etype
|
||||
dir = ChanDir(t.Etype)
|
||||
if dir == Crecv {
|
||||
// t is type <-chan E but <-<-chan E is not permitted
|
||||
// (report same error as for "type _ <-<-chan E")
|
||||
p.syntax_error("unexpected <-, expecting chan")
|
||||
// already progressed, no need to advance
|
||||
}
|
||||
t.Etype = Crecv
|
||||
t.Etype = EType(Crecv)
|
||||
}
|
||||
if dir == Csend {
|
||||
// channel dir is <- but channel element E is not a channel
|
||||
@ -1697,7 +1697,7 @@ func (p *parser) try_ntype() *Node {
|
||||
p.next()
|
||||
p.want(LCHAN)
|
||||
t := Nod(OTCHAN, p.chan_elem(), nil)
|
||||
t.Etype = Crecv
|
||||
t.Etype = EType(Crecv)
|
||||
return t
|
||||
|
||||
case LFUNC:
|
||||
@ -1726,9 +1726,9 @@ func (p *parser) try_ntype() *Node {
|
||||
// LCHAN non_recvchantype
|
||||
// LCHAN LCOMM ntype
|
||||
p.next()
|
||||
var dir EType = Cboth
|
||||
var dir = EType(Cboth)
|
||||
if p.got(LCOMM) {
|
||||
dir = Csend
|
||||
dir = EType(Csend)
|
||||
}
|
||||
t := Nod(OTCHAN, p.chan_elem(), nil)
|
||||
t.Etype = dir
|
||||
|
@ -58,7 +58,7 @@ func typecheckrange(n *Node) {
|
||||
t2 = t.Val()
|
||||
|
||||
case TCHAN:
|
||||
if t.ChanDir()&Crecv == 0 {
|
||||
if !t.ChanDir().CanRecv() {
|
||||
Yyerror("invalid operation: range %v (receive from send-only type %v)", n.Right, n.Right.Type)
|
||||
goto out
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ type Node struct {
|
||||
Op Op
|
||||
Ullman uint8 // sethi/ullman number
|
||||
Addable bool // addressable
|
||||
Etype EType // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg
|
||||
Etype EType // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg, ChanDir for OTCHAN
|
||||
Bounded bool // bounds check unnecessary
|
||||
Class Class // PPARAM, PAUTO, PEXTERN, etc
|
||||
Embedded uint8 // ODCLFIELD embedded type
|
||||
|
@ -110,7 +110,7 @@ var (
|
||||
type Type struct {
|
||||
Etype EType
|
||||
Noalg bool
|
||||
Chan uint8
|
||||
Chan ChanDir
|
||||
Trecur uint8 // to detect loops
|
||||
Printed bool
|
||||
Funarg bool // on TSTRUCT and TFIELD
|
||||
@ -266,7 +266,7 @@ func typDDDArray(elem *Type) *Type {
|
||||
}
|
||||
|
||||
// typChan returns a new chan Type with direction dir.
|
||||
func typChan(elem *Type, dir uint8) *Type {
|
||||
func typChan(elem *Type, dir ChanDir) *Type {
|
||||
t := typ(TCHAN)
|
||||
t.Type = elem
|
||||
t.Chan = dir
|
||||
@ -957,7 +957,7 @@ func (t *Type) SetNumElem(n int64) {
|
||||
|
||||
// ChanDir returns the direction of a channel type t.
|
||||
// The direction will be one of Crecv, Csend, or Cboth.
|
||||
func (t *Type) ChanDir() uint8 {
|
||||
func (t *Type) ChanDir() ChanDir {
|
||||
t.wantEtype(TCHAN)
|
||||
return t.Chan
|
||||
}
|
||||
|
@ -414,7 +414,7 @@ OpSwitch:
|
||||
n.Type = nil
|
||||
return n
|
||||
}
|
||||
t := typChan(l.Type, uint8(n.Etype)) // TODO(marvin): Fix Node.EType type union.
|
||||
t := typChan(l.Type, ChanDir(n.Etype)) // TODO(marvin): Fix Node.EType type union.
|
||||
n.Op = OTYPE
|
||||
n.Type = t
|
||||
n.Left = nil
|
||||
@ -1048,7 +1048,7 @@ OpSwitch:
|
||||
return n
|
||||
}
|
||||
|
||||
if t.ChanDir()&Crecv == 0 {
|
||||
if !t.ChanDir().CanRecv() {
|
||||
Yyerror("invalid operation: %v (receive from send-only type %v)", n, t)
|
||||
n.Type = nil
|
||||
return n
|
||||
@ -1075,7 +1075,7 @@ OpSwitch:
|
||||
return n
|
||||
}
|
||||
|
||||
if t.ChanDir()&Csend == 0 {
|
||||
if !t.ChanDir().CanSend() {
|
||||
Yyerror("invalid operation: %v (send to receive-only type %v)", n, t)
|
||||
n.Type = nil
|
||||
return n
|
||||
@ -1528,7 +1528,7 @@ OpSwitch:
|
||||
return n
|
||||
}
|
||||
|
||||
if t.ChanDir()&Csend == 0 {
|
||||
if !t.ChanDir().CanSend() {
|
||||
Yyerror("invalid operation: %v (cannot close receive-only channel)", n)
|
||||
n.Type = nil
|
||||
return n
|
||||
|
Loading…
Reference in New Issue
Block a user