mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00: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
8 changed files with 27 additions and 21 deletions
|
|
@ -316,7 +316,7 @@ func (p *importer) typ() *Type {
|
||||||
|
|
||||||
case chanTag:
|
case chanTag:
|
||||||
t = p.newtyp(TCHAN)
|
t = p.newtyp(TCHAN)
|
||||||
t.Chan = uint8(p.int())
|
t.Chan = ChanDir(p.int())
|
||||||
t.Type = p.typ()
|
t.Type = p.typ()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -1154,7 +1154,7 @@ func exprfmt(n *Node, prec int) string {
|
||||||
return fmt.Sprintf("map[%v]%v", n.Left, n.Right)
|
return fmt.Sprintf("map[%v]%v", n.Left, n.Right)
|
||||||
|
|
||||||
case OTCHAN:
|
case OTCHAN:
|
||||||
switch n.Etype {
|
switch ChanDir(n.Etype) {
|
||||||
case Crecv:
|
case Crecv:
|
||||||
return fmt.Sprintf("<-chan %v", n.Left)
|
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)
|
return fmt.Sprintf("chan<- %v", n.Left)
|
||||||
|
|
||||||
default:
|
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)
|
return fmt.Sprintf("chan (%v)", n.Left)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf("chan %v", n.Left)
|
return fmt.Sprintf("chan %v", n.Left)
|
||||||
|
|
|
||||||
|
|
@ -128,12 +128,18 @@ const (
|
||||||
CTNIL
|
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 (
|
const (
|
||||||
// types of channel
|
// types of channel
|
||||||
// must match ../../../../reflect/type.go:/ChanDir
|
// must match ../../../../reflect/type.go:/ChanDir
|
||||||
Crecv = 1 << 0
|
Crecv ChanDir = 1 << 0
|
||||||
Csend = 1 << 1
|
Csend ChanDir = 1 << 1
|
||||||
Cboth = Crecv | Csend
|
Cboth ChanDir = Crecv | Csend
|
||||||
)
|
)
|
||||||
|
|
||||||
// The Class of a variable/function describes the "storage class"
|
// The Class of a variable/function describes the "storage class"
|
||||||
|
|
|
||||||
|
|
@ -1187,17 +1187,17 @@ func (p *parser) uexpr() *Node {
|
||||||
|
|
||||||
if x.Op == OTCHAN {
|
if x.Op == OTCHAN {
|
||||||
// x is a channel type => re-associate <-
|
// x is a channel type => re-associate <-
|
||||||
dir := EType(Csend)
|
dir := Csend
|
||||||
t := x
|
t := x
|
||||||
for ; t.Op == OTCHAN && dir == Csend; t = t.Left {
|
for ; t.Op == OTCHAN && dir == Csend; t = t.Left {
|
||||||
dir = t.Etype
|
dir = ChanDir(t.Etype)
|
||||||
if dir == Crecv {
|
if dir == Crecv {
|
||||||
// t is type <-chan E but <-<-chan E is not permitted
|
// t is type <-chan E but <-<-chan E is not permitted
|
||||||
// (report same error as for "type _ <-<-chan E")
|
// (report same error as for "type _ <-<-chan E")
|
||||||
p.syntax_error("unexpected <-, expecting chan")
|
p.syntax_error("unexpected <-, expecting chan")
|
||||||
// already progressed, no need to advance
|
// already progressed, no need to advance
|
||||||
}
|
}
|
||||||
t.Etype = Crecv
|
t.Etype = EType(Crecv)
|
||||||
}
|
}
|
||||||
if dir == Csend {
|
if dir == Csend {
|
||||||
// channel dir is <- but channel element E is not a channel
|
// channel dir is <- but channel element E is not a channel
|
||||||
|
|
@ -1697,7 +1697,7 @@ func (p *parser) try_ntype() *Node {
|
||||||
p.next()
|
p.next()
|
||||||
p.want(LCHAN)
|
p.want(LCHAN)
|
||||||
t := Nod(OTCHAN, p.chan_elem(), nil)
|
t := Nod(OTCHAN, p.chan_elem(), nil)
|
||||||
t.Etype = Crecv
|
t.Etype = EType(Crecv)
|
||||||
return t
|
return t
|
||||||
|
|
||||||
case LFUNC:
|
case LFUNC:
|
||||||
|
|
@ -1726,9 +1726,9 @@ func (p *parser) try_ntype() *Node {
|
||||||
// LCHAN non_recvchantype
|
// LCHAN non_recvchantype
|
||||||
// LCHAN LCOMM ntype
|
// LCHAN LCOMM ntype
|
||||||
p.next()
|
p.next()
|
||||||
var dir EType = Cboth
|
var dir = EType(Cboth)
|
||||||
if p.got(LCOMM) {
|
if p.got(LCOMM) {
|
||||||
dir = Csend
|
dir = EType(Csend)
|
||||||
}
|
}
|
||||||
t := Nod(OTCHAN, p.chan_elem(), nil)
|
t := Nod(OTCHAN, p.chan_elem(), nil)
|
||||||
t.Etype = dir
|
t.Etype = dir
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ func typecheckrange(n *Node) {
|
||||||
t2 = t.Val()
|
t2 = t.Val()
|
||||||
|
|
||||||
case TCHAN:
|
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)
|
Yyerror("invalid operation: range %v (receive from send-only type %v)", n.Right, n.Right.Type)
|
||||||
goto out
|
goto out
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ type Node struct {
|
||||||
Op Op
|
Op Op
|
||||||
Ullman uint8 // sethi/ullman number
|
Ullman uint8 // sethi/ullman number
|
||||||
Addable bool // addressable
|
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
|
Bounded bool // bounds check unnecessary
|
||||||
Class Class // PPARAM, PAUTO, PEXTERN, etc
|
Class Class // PPARAM, PAUTO, PEXTERN, etc
|
||||||
Embedded uint8 // ODCLFIELD embedded type
|
Embedded uint8 // ODCLFIELD embedded type
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ var (
|
||||||
type Type struct {
|
type Type struct {
|
||||||
Etype EType
|
Etype EType
|
||||||
Noalg bool
|
Noalg bool
|
||||||
Chan uint8
|
Chan ChanDir
|
||||||
Trecur uint8 // to detect loops
|
Trecur uint8 // to detect loops
|
||||||
Printed bool
|
Printed bool
|
||||||
Funarg bool // on TSTRUCT and TFIELD
|
Funarg bool // on TSTRUCT and TFIELD
|
||||||
|
|
@ -266,7 +266,7 @@ func typDDDArray(elem *Type) *Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
// typChan returns a new chan Type with direction dir.
|
// 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 := typ(TCHAN)
|
||||||
t.Type = elem
|
t.Type = elem
|
||||||
t.Chan = dir
|
t.Chan = dir
|
||||||
|
|
@ -957,7 +957,7 @@ func (t *Type) SetNumElem(n int64) {
|
||||||
|
|
||||||
// ChanDir returns the direction of a channel type t.
|
// ChanDir returns the direction of a channel type t.
|
||||||
// The direction will be one of Crecv, Csend, or Cboth.
|
// The direction will be one of Crecv, Csend, or Cboth.
|
||||||
func (t *Type) ChanDir() uint8 {
|
func (t *Type) ChanDir() ChanDir {
|
||||||
t.wantEtype(TCHAN)
|
t.wantEtype(TCHAN)
|
||||||
return t.Chan
|
return t.Chan
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -414,7 +414,7 @@ OpSwitch:
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return n
|
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.Op = OTYPE
|
||||||
n.Type = t
|
n.Type = t
|
||||||
n.Left = nil
|
n.Left = nil
|
||||||
|
|
@ -1048,7 +1048,7 @@ OpSwitch:
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.ChanDir()&Crecv == 0 {
|
if !t.ChanDir().CanRecv() {
|
||||||
Yyerror("invalid operation: %v (receive from send-only type %v)", n, t)
|
Yyerror("invalid operation: %v (receive from send-only type %v)", n, t)
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return n
|
return n
|
||||||
|
|
@ -1075,7 +1075,7 @@ OpSwitch:
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.ChanDir()&Csend == 0 {
|
if !t.ChanDir().CanSend() {
|
||||||
Yyerror("invalid operation: %v (send to receive-only type %v)", n, t)
|
Yyerror("invalid operation: %v (send to receive-only type %v)", n, t)
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return n
|
return n
|
||||||
|
|
@ -1528,7 +1528,7 @@ OpSwitch:
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.ChanDir()&Csend == 0 {
|
if !t.ChanDir().CanSend() {
|
||||||
Yyerror("invalid operation: %v (cannot close receive-only channel)", n)
|
Yyerror("invalid operation: %v (cannot close receive-only channel)", n)
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return n
|
return n
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue