1
0
mirror of https://github.com/golang/go synced 2024-11-25 04:57:56 -07:00

go spec: follow-up cleanups after communication operator changes

These are syntactical changes to better reflect the communication
operator's new status in the language.

- sending to a channel is now done via a send statement
- there is no binary communication operation anymore which
  leads to a reduction of the number of precedence levels
  from 6 to 5 (yeah!)
- small semantic change: since a send operation is not part
  of the expression syntax anymore, a <- send operator is
  binding weaker than any other operator now
- receiving from a channel is done as before via the unary
  receive expression
- communication clauses in select statement now can contain
  send statements or receive expressions

R=rsc, r, iant, ken2, gri1
CC=golang-dev
https://golang.org/cl/3973051
This commit is contained in:
Robert Griesemer 2011-02-01 12:02:49 -08:00
parent dc9a02fa66
commit b50ed022f5

View File

@ -1,5 +1,5 @@
<!-- title The Go Programming Language Specification --> <!-- title The Go Programming Language Specification -->
<!-- subtitle Version of January 27, 2011 --> <!-- subtitle Version of February 1, 2011 -->
<!-- <!--
TODO TODO
@ -2667,9 +2667,7 @@ Operators combine operands into expressions.
Expression = UnaryExpr | Expression binary_op UnaryExpr . Expression = UnaryExpr | Expression binary_op UnaryExpr .
UnaryExpr = PrimaryExpr | unary_op UnaryExpr . UnaryExpr = PrimaryExpr | unary_op UnaryExpr .
binary_op = log_op | com_op | rel_op | add_op | mul_op . binary_op = "||" | "&amp;&amp;" | rel_op | add_op | mul_op .
log_op = "||" | "&amp;&amp;" .
com_op = "&lt;-" .
rel_op = "==" | "!=" | "&lt;" | "&lt;=" | ">" | ">=" . rel_op = "==" | "!=" | "&lt;" | "&lt;=" | ">" | ">=" .
add_op = "+" | "-" | "|" | "^" . add_op = "+" | "-" | "|" | "^" .
mul_op = "*" | "/" | "%" | "&lt;&lt;" | "&gt;&gt;" | "&amp;" | "&amp;^" . mul_op = "*" | "/" | "%" | "&lt;&lt;" | "&gt;&gt;" | "&amp;" | "&amp;^" .
@ -2726,18 +2724,17 @@ statements, not expressions, they fall
outside the operator hierarchy. outside the operator hierarchy.
As a consequence, statement <code>*p++</code> is the same as <code>(*p)++</code>. As a consequence, statement <code>*p++</code> is the same as <code>(*p)++</code>.
<p> <p>
There are six precedence levels for binary operators. There are five precedence levels for binary operators.
Multiplication operators bind strongest, followed by addition Multiplication operators bind strongest, followed by addition
operators, comparison operators, <code>&lt;-</code> (channel send), operators, comparison operators, <code>&amp;&amp;</code> (logical and),
<code>&amp;&amp;</code> (logical and), and finally <code>||</code> (logical or): and finally <code>||</code> (logical or):
</p> </p>
<pre class="grammar"> <pre class="grammar">
Precedence Operator Precedence Operator
6 * / % &lt;&lt; &gt;&gt; &amp; &amp;^ 5 * / % &lt;&lt; &gt;&gt; &amp; &amp;^
5 + - | ^ 4 + - | ^
4 == != &lt; &lt;= > >= 3 == != &lt; &lt;= > >=
3 &lt;-
2 &amp;&amp; 2 &amp;&amp;
1 || 1 ||
</pre> </pre>
@ -3005,51 +3002,21 @@ to by <code>x</code>.
*pf(x) *pf(x)
</pre> </pre>
<h3 id="Communication_operators">Communication operators</h3>
<h3 id="Receive_operator">Receive operator</h3>
<p> <p>
The term <i>channel</i> means "value of <a href="#Channel_types">channel type</a>". For an operand <code>ch</code> of <a href="#Channel_types">channel type</a>,
</p> the value of the receive operation <code>&lt;-ch</code> is the value received
<p> from the channel <code>ch</code>. The type of the value is the element type of
The send operation uses the binary operator "&lt;-", which operates on the channel. The expression blocks until a value is available.
a channel and a value (expression):
</p>
<pre>
ch &lt;- 3
</pre>
<p>
The send operation sends the value on the channel. Both the channel
and the expression are evaluated before communication begins.
Communication blocks until the send can proceed, at which point the
value is transmitted on the channel.
A send on an unbuffered channel can proceed if a receiver is ready.
A send on a buffered channel can proceed if there is room in the buffer.
</p>
<p>
The receive operation uses the prefix unary operator "&lt;-".
The value of the expression is the value received, whose type
is the element type of the channel.
</p>
<pre>
&lt;-ch
</pre>
<p>
The expression blocks until a value is available, which then can
be assigned to a variable or used like any other expression.
If the receive expression does not save the value, the value is
discarded.
</p> </p>
<pre> <pre>
v1 := &lt;-ch v1 := &lt;-ch
v2 = &lt;-ch v2 = &lt;-ch
f(&lt;-ch) f(&lt;-ch)
&lt;-strobe // wait until clock pulse &lt;-strobe // wait until clock pulse and discard received value
</pre> </pre>
<!-- <!--
@ -3075,8 +3042,7 @@ because the channel is closed and empty (<code>false</code>).
--> -->
<p> <p>
Except in a communications clause of a <a href="#Select_statements">select statement</a>, Receiving from a <code>nil</code> channel causes a
sending or receiving from a <code>nil</code> channel causes a
<a href="#Run_time_panics">run-time panic</a>. <a href="#Run_time_panics">run-time panic</a>.
</p> </p>
@ -3087,6 +3053,7 @@ need to be presented regarding send, receive, select, and goroutines.</span>
</p> </p>
---> --->
<h3 id="Method_expressions">Method expressions</h3> <h3 id="Method_expressions">Method expressions</h3>
<p> <p>
@ -3508,7 +3475,7 @@ Statement =
FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt | FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
DeferStmt . DeferStmt .
SimpleStmt = EmptyStmt | ExpressionStmt | IncDecStmt | Assignment | ShortVarDecl . SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .
</pre> </pre>
@ -3543,7 +3510,7 @@ Error: log.Crash("error encountered")
<h3 id="Expression_statements">Expression statements</h3> <h3 id="Expression_statements">Expression statements</h3>
<p> <p>
Function calls, method calls, and channel operations Function calls, method calls, and receive operations
can appear in statement context. can appear in statement context.
</p> </p>
@ -3553,11 +3520,44 @@ ExpressionStmt = Expression .
</pre> </pre>
<pre> <pre>
f(x+y) h(x+y)
f.Close()
&lt;-ch &lt;-ch
</pre> </pre>
<h3 id="Send_statements">Send statements</h3>
<p>
A send statement sends a value on a channel.
The channel expression must be of <a href="#Channel_types">channel type</a>
and the type of the value must be <a href="#Assignability">assignable</a>
to the channel's element type.
</p>
<pre class="ebnf">
SendStmt = Channel "&lt;-" Expression .
Channel = Expression .
</pre>
<p>
Both the channel and the value expression are evaluated before communication
begins. Communication blocks until the send can proceed, at which point the
value is transmitted on the channel.
A send on an unbuffered channel can proceed if a receiver is ready.
A send on a buffered channel can proceed if there is room in the buffer.
</p>
<pre>
ch &lt;- 3
</pre>
<p>
Sending to a <code>nil</code> channel causes a
<a href="#Run_time_panics">run-time panic</a>.
</p>
<h3 id="IncDec_statements">IncDec statements</h3> <h3 id="IncDec_statements">IncDec statements</h3>
<p> <p>
@ -4076,18 +4076,19 @@ cases all referring to communication operations.
<pre class="ebnf"> <pre class="ebnf">
SelectStmt = "select" "{" { CommClause } "}" . SelectStmt = "select" "{" { CommClause } "}" .
CommClause = CommCase ":" { Statement ";" } . CommClause = CommCase ":" { Statement ";" } .
CommCase = "case" ( SendExpr | RecvExpr) | "default" . CommCase = "case" ( SendStmt | RecvStmt ) | "default" .
SendExpr = Expression "&lt;-" Expression . RecvStmt = [ Expression ( "=" | ":=" ) ] RecvExpr .
RecvExpr = [ Expression ( "=" | ":=" ) ] "&lt;-" Expression . RecvExpr = Expression .
</pre> </pre>
<!-- TODO(rsc): <!-- TODO(rsc):
RecvExpr = [ Expression [ "," Expression ] ( "=" | ":=" ) ] "&lt;-" Expression . RecvStmt = [ Expression [ "," Expression ] ( "=" | ":=" ) ] RecvExpr .
--> -->
<p> <p>
For all the send and receive expressions in the "select" RecvExpr must be a <a href="#Receive_operator">receive operation</a>.
For all the cases in the "select"
statement, the channel expressions are evaluated in top-to-bottom order, along with statement, the channel expressions are evaluated in top-to-bottom order, along with
any expressions that appear on the right hand side of send expressions. any expressions that appear on the right hand side of send statements.
A channel may be <code>nil</code>, A channel may be <code>nil</code>,
which is equivalent to that case not which is equivalent to that case not
being present in the select statement being present in the select statement
@ -4398,7 +4399,7 @@ sent values have been received, receive operations will return
the zero value for the channel's type without blocking. the zero value for the channel's type without blocking.
<!-- TODO(rsc): delete next sentence, replace with <!-- TODO(rsc): delete next sentence, replace with
The multi-valued <a href="#Communication_operators">receive operation</a> The multi-valued <a href="#Receive_operator">receive operation</a>
returns a received value along with an indication of whether the channel is closed. returns a received value along with an indication of whether the channel is closed.
--> -->
After at least one such zero value has been After at least one such zero value has been