Commit 386c0e65 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

cmd/compile: give ChanDir a type

Change-Id: I03621db79637b04982e1f0e7b4268c4ed2db6d22
Reviewed-on: https://go-review.googlesource.com/21484Reviewed-by: 's avatarJosh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 73edd7b2
...@@ -316,7 +316,7 @@ func (p *importer) typ() *Type { ...@@ -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 { ...@@ -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 { ...@@ -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 ( ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) { ...@@ -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 { ...@@ -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 ( ...@@ -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 { ...@@ -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) { ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment