Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Commit

Permalink
spec/explainer: Forbid other assignment-level expressions as pipe hea…
Browse files Browse the repository at this point in the history
…ds/bodies

See #11 and #12.
  • Loading branch information
js-choi committed Aug 17, 2021
1 parent dbe4cb1 commit 9eee84f
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 28 deletions.
48 changes: 25 additions & 23 deletions README.md
Expand Up @@ -491,13 +491,15 @@ Likewise, a topic reference **must** be contained in a pipe body.
Using a topic reference outside of a pipe body
is also **invalid syntax**.

Because `yield` is a very loose operator,
a **`yield`** expression acting as a pipe’s body **must have parentheses**.
This is to prevent `v |> yield % |> % + 1` from being valid,
which would confusingly parse as `v |> (yield % |> % + 1)`.
(However, other expressions such as assignment and arrow functions
are valid pipe bodies. Note that they, too, group with right associativity,
so `v |> x => y |> z` is `v |> (x => y |> z`).)
To prevent confusing grouping,
it is **invalid** syntax to use **other** operators that have the **same precedence**
(the function arrow `=>`, the assignment operators, and the yield operators)
as a **pipe head or body**.
When using, we must use **parentheses**
to explicitly indicate which precedence is correct.
For example, `a |> b ? % : c |> %.d` is invalid syntax;
it should be corrected to either `a |> (b ? % : c) |> %.d`
or `a |> (b ? % : c |> %.d)`.

Lastly, topic bindings **inside dynamically compiled** code
(e.g., with `eval` or `new Function`)
Expand Down Expand Up @@ -787,9 +789,9 @@ From [jquery/src/core/init.js][].
```js
match
|> context[%]
|> isFunction(this[match])
|> (isFunction(this[match])
? this[match](%);
: this.attr(match, %);
: this.attr(match, %));
```
<tr>
Expand All @@ -807,7 +809,7 @@ From [underscore.js][].
```js
return self
|> srcFn.apply(%, args)
|> _.isObject(%) ? % : self;
|> (_.isObject(%) ? % : self);
```
<tr>
Expand All @@ -827,9 +829,9 @@ From [ramda.js][].

```js
return fn
|> typeof % === 'function'
|> (typeof % === 'function'
? _xwrap(%)
: %
: %)
|> xf(%)
|> _reduce(%, acc, list);
```
Expand All @@ -839,21 +841,21 @@ return fn

```js
if (obj == null) return 0;
return isArrayLike(obj)
return (isArrayLike(obj)
? obj.length
: _.keys(obj).length;
: _.keys(obj).length);
```
From [underscore.js][].

<td>

```js
return obj
|> % == null
? 0
: isArrayLike(%)
? %.length
: _.keys(%).length;
|> (% == null
? 0
: isArrayLike(%)
? %.length
: _.keys(%).length);
```

<tr>
Expand All @@ -874,9 +876,9 @@ From [jquery/src/core/init.js][].

```js
context
|> % && %.nodeType
|> (% && %.nodeType
? %.ownerDocument || %
: document
: document)
|> jQuery.parseHTML(match[1], %, true)
|> jQuery.merge(%);
```
Expand All @@ -899,11 +901,11 @@ From [jquery/src/core/init.js][].

```js
return context
|> !% || %.jquery
|> (!% || %.jquery
// Handle $(expr, $(...))
? % || root
// Handle $(expr, context)
: this.constructor(%)
: this.constructor(%))
|> %.find(selector);
```

Expand Down
23 changes: 18 additions & 5 deletions spec.html
Expand Up @@ -861,15 +861,28 @@ <h1>Static Semantics: Early Errors</h1>

<emu-grammar>PipeBody : PipeExpression</emu-grammar>
<emu-alg>
1. It is a Syntax Error if |YieldExpression| is covering |PipeBody|.
1. It is a Syntax Error if one of the following productions is covering |PipeBody|:
* |ConditionalExpression|
* |YieldExpression|
* |ArrowFunction|
* |AsyncArrowFunction|
* |LeftHandSideExpression| `=` |AssignmentExpression|
* |LeftHandSideExpression| |AssignmentOperator| |AssignmentExpression|
* |LeftHandSideExpression| `&&=` |AssignmentExpression|
* |LeftHandSideExpression| `||=` |AssignmentExpression|
* |LeftHandSideExpression| `??=` |AssignmentExpression|
</emu-alg>

<emu-note>
<p>A |PipeBody| must not be a |YieldExpression| without parentheses.
This is to prevent the confusing expression from being valid:
`x |> yield % |> % + 1`.
This expression would otherwise be unexpectedly equivalent to
<p>A |PipeBody| must not be an expression without parentheses that is formed from any other operator with identical precedence, such as |YieldExpression| or |ArrowFunction|.</p>
<p>This is to prevent confusing expressions from being valid, such as
`x |> yield % |> % + 1`.<br>
That expression would otherwise be unexpectedly equivalent to
`x |> (yield % |> f(%)).`</p>
<p>Likewise, the confusing expression
`x |> y ? % : z |> f(%)`.<br>
would otherwise be unexpectedly equivalent to
`x |> (y ? % : z |> f(%)).`</p>
</emu-note>
</emu-clause>

Expand Down

0 comments on commit 9eee84f

Please sign in to comment.