Re: Another statement expression-related proposal

2016-11-02 Thread Isiah Meadows
Inline.

On Wed, Nov 2, 2016, 01:01 Bob Myers  wrote:

> Just a random thought, but would `{= =}` work for expression blocks?
>
> ```js
> // plain block
> const foo = {= let a = 1; a =};
>
> assert.equal(foo, 1)
>
> // if-else
> let cond = false
> const bar = {= if (cond) "hi" else "bye" =};
>
> assert.equal(bar, "bye")
>
> // try-catch
> let e = new Error()
> const error = {= try { throw e } catch (e) { e } =};
> assert.equal(error, e)
> ```
>

In theory, yes, but it doesn't exactly look very pretty (too many equals
signs and curly braces).


>
> I don't know about the loop idea. It seems like it's trying to do too much.
>

The loop thing is a bit extra, complicating things some, but I feel it's
merited by the ability to avoid a lot of the confusion when using loops
with the current `do` expression proposal (loops currently act like
`reduce`, which is incredibly unintuitive).


> On Wed, Nov 2, 2016 at 10:13 AM, Isiah Meadows 
> wrote:
>
> Yes, there's been a bit of talk about modifying the `do` proposal in
> various ways (like allowing more than a block, using `=` to
> differentiate, etc.), but each of these have potential ambiguities
> (like conflicting with `do-while` or object literal syntax,
> respectively), and give unintuitive results with loops.
>
> Here's my idea: prepend a `::` to any non-expression statement, and it
> becomes an expression. The last statement's value (as if through
> `eval`) is used as the return value, with exception of loops, which
> return an array generated from their loop body. Here's a few examples
> to clarify:
>
> ```js
> // plain block
> const foo = :: { let a = 1; a }
> assert.equal(foo, 1)
>
> // if-else
> let cond = false
> const bar = :: if (cond) "hi" else "bye"
> assert.equal(bar, "bye")
>
> // try-catch
> let e = new Error()
> const error = :: try { throw e } catch (e) { e }
> assert.equal(error, e)
>
> // while loop
> let i = 0
> const range = :: while (i < 10) i++
> assert.deepEqual(range, [
>   0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
> ])
>
> // for + nested if-else
> const fizzBuzz = :: for (let i = 0; i < 100; i++) {
>   if (i % 15) "FizzBuzz"
>   else if (i % 3) "Fizz"
>   else if (i % 5) "Buzz"
>   // If no expression is evaluated in the body, then no value
>   // is pushed.
> }
> assert.deepEqual(fizzBuzz, [
>   // 100 lines of the classic "Fizz", "Buzz", and "FizzBuzz"
> ])
> ```
>
> What do you all think of this?
>
> ---
>
> To clarify, here's some more detailed semantics:
>
> ### Grammar
>
> - `:: ExpressionStatement`
> - `:: Declaration`
> - `:: VariableStatement`
>
> These are early errors, and they are all redundant, anyways, since you
> already have a value you could use.
>
> - `:: ContinueStatement`
> - `:: BreakStatement`
> - `:: ReturnStatement`
> - `:: DebuggerStatement`
> - `:: ThrowStatement`
> - `:: EmptyStatement`
>
> These are also early errors, since there's no real value you can
> associate with them.
>
> - `:: BlockStatement`
> - `:: IfStatement`
> - `:: SwitchStatement`
> - `:: WithStatement`
> - `:: TryStatement`
>
> 1. Let `completion` be ? ExecuteStatement(`statement`), where
> `statement` is one of the statements above.
> 2. If `completion` is *none*, return `undefined`
> 3. Otherwise, return `completion`.
>
> - `:: IterationStatement`
>
> 1. Return ? ExecuteIterationStatement(`statement`), where `statement`
> is one of the statements above.
>
> - `:: LabelledStatement`
>
> This works similarly, but has an outer label instead. The same above
> statements are also similarly banned as `LabelledItem` entries.
> Additionally, the Annex B extension for FunctionDeclaraions are also
> early errors.
>
> (Should these even be allowed? I'm open to making this an early error
> instead.)
>
> ### Abstract Operation ExecuteStatement(`statement`)
>
> 1. If `statement` is an IterationStatement:
>   1. Let `list` be a new empty list.
>   2. Evaluate `statement`, but for each `child` statement:
> 1. Let `result` be ? ExecuteStatement(`child`).
> 2. If `result` is not *empty*, then append `result` to `list`.
>   3. Return `list`.
> 2. If `statement` is an ExpressionStatement:
>   1. Return the result of evaluating the expression within.
> 3. If `statement` is a `BreakStatement` or `ContinueStatement`:
>   1. Evaluate `statement`
>   2. Return *empty*.
> 4. If `statement` is a `Declaration`:
>   1. Evaluate `statement`.
>   2. Return the value of the resulting declaration
> 5. Otherwise:
>   1. Let `last` be *empty*
>   2. Evaluate `statement`. For each `child` statement:
> 1. Let `last` be ? ExecuteStatement(`child`).
>   3. Note: `last` is the final expression's value, or `empty` if there
> was no final expression.
>   4. Return `last`.
>
> (I probably missed several edge cases, but this is just a mailing list
> strawman.)
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
>

Re: Another statement expression-related proposal

2016-11-01 Thread Bob Myers
Just a random thought, but would `{= =}` work for expression blocks?

```js
// plain block
const foo = {= let a = 1; a =};
assert.equal(foo, 1)

// if-else
let cond = false
const bar = {= if (cond) "hi" else "bye" =};
assert.equal(bar, "bye")

// try-catch
let e = new Error()
const error = {= try { throw e } catch (e) { e } =};
assert.equal(error, e)
```

I don't know about the loop idea. It seems like it's trying to do too much.

On Wed, Nov 2, 2016 at 10:13 AM, Isiah Meadows 
wrote:

> Yes, there's been a bit of talk about modifying the `do` proposal in
> various ways (like allowing more than a block, using `=` to
> differentiate, etc.), but each of these have potential ambiguities
> (like conflicting with `do-while` or object literal syntax,
> respectively), and give unintuitive results with loops.
>
> Here's my idea: prepend a `::` to any non-expression statement, and it
> becomes an expression. The last statement's value (as if through
> `eval`) is used as the return value, with exception of loops, which
> return an array generated from their loop body. Here's a few examples
> to clarify:
>
> ```js
> // plain block
> const foo = :: { let a = 1; a }
> assert.equal(foo, 1)
>
> // if-else
> let cond = false
> const bar = :: if (cond) "hi" else "bye"
> assert.equal(bar, "bye")
>
> // try-catch
> let e = new Error()
> const error = :: try { throw e } catch (e) { e }
> assert.equal(error, e)
>
> // while loop
> let i = 0
> const range = :: while (i < 10) i++
> assert.deepEqual(range, [
>   0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
> ])
>
> // for + nested if-else
> const fizzBuzz = :: for (let i = 0; i < 100; i++) {
>   if (i % 15) "FizzBuzz"
>   else if (i % 3) "Fizz"
>   else if (i % 5) "Buzz"
>   // If no expression is evaluated in the body, then no value
>   // is pushed.
> }
> assert.deepEqual(fizzBuzz, [
>   // 100 lines of the classic "Fizz", "Buzz", and "FizzBuzz"
> ])
> ```
>
> What do you all think of this?
>
> ---
>
> To clarify, here's some more detailed semantics:
>
> ### Grammar
>
> - `:: ExpressionStatement`
> - `:: Declaration`
> - `:: VariableStatement`
>
> These are early errors, and they are all redundant, anyways, since you
> already have a value you could use.
>
> - `:: ContinueStatement`
> - `:: BreakStatement`
> - `:: ReturnStatement`
> - `:: DebuggerStatement`
> - `:: ThrowStatement`
> - `:: EmptyStatement`
>
> These are also early errors, since there's no real value you can
> associate with them.
>
> - `:: BlockStatement`
> - `:: IfStatement`
> - `:: SwitchStatement`
> - `:: WithStatement`
> - `:: TryStatement`
>
> 1. Let `completion` be ? ExecuteStatement(`statement`), where
> `statement` is one of the statements above.
> 2. If `completion` is *none*, return `undefined`
> 3. Otherwise, return `completion`.
>
> - `:: IterationStatement`
>
> 1. Return ? ExecuteIterationStatement(`statement`), where `statement`
> is one of the statements above.
>
> - `:: LabelledStatement`
>
> This works similarly, but has an outer label instead. The same above
> statements are also similarly banned as `LabelledItem` entries.
> Additionally, the Annex B extension for FunctionDeclaraions are also
> early errors.
>
> (Should these even be allowed? I'm open to making this an early error
> instead.)
>
> ### Abstract Operation ExecuteStatement(`statement`)
>
> 1. If `statement` is an IterationStatement:
>   1. Let `list` be a new empty list.
>   2. Evaluate `statement`, but for each `child` statement:
> 1. Let `result` be ? ExecuteStatement(`child`).
> 2. If `result` is not *empty*, then append `result` to `list`.
>   3. Return `list`.
> 2. If `statement` is an ExpressionStatement:
>   1. Return the result of evaluating the expression within.
> 3. If `statement` is a `BreakStatement` or `ContinueStatement`:
>   1. Evaluate `statement`
>   2. Return *empty*.
> 4. If `statement` is a `Declaration`:
>   1. Evaluate `statement`.
>   2. Return the value of the resulting declaration
> 5. Otherwise:
>   1. Let `last` be *empty*
>   2. Evaluate `statement`. For each `child` statement:
> 1. Let `last` be ? ExecuteStatement(`child`).
>   3. Note: `last` is the final expression's value, or `empty` if there
> was no final expression.
>   4. Return `last`.
>
> (I probably missed several edge cases, but this is just a mailing list
> strawman.)
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Another statement expression-related proposal

2016-11-01 Thread Isiah Meadows
Yes, there's been a bit of talk about modifying the `do` proposal in
various ways (like allowing more than a block, using `=` to
differentiate, etc.), but each of these have potential ambiguities
(like conflicting with `do-while` or object literal syntax,
respectively), and give unintuitive results with loops.

Here's my idea: prepend a `::` to any non-expression statement, and it
becomes an expression. The last statement's value (as if through
`eval`) is used as the return value, with exception of loops, which
return an array generated from their loop body. Here's a few examples
to clarify:

```js
// plain block
const foo = :: { let a = 1; a }
assert.equal(foo, 1)

// if-else
let cond = false
const bar = :: if (cond) "hi" else "bye"
assert.equal(bar, "bye")

// try-catch
let e = new Error()
const error = :: try { throw e } catch (e) { e }
assert.equal(error, e)

// while loop
let i = 0
const range = :: while (i < 10) i++
assert.deepEqual(range, [
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
])

// for + nested if-else
const fizzBuzz = :: for (let i = 0; i < 100; i++) {
  if (i % 15) "FizzBuzz"
  else if (i % 3) "Fizz"
  else if (i % 5) "Buzz"
  // If no expression is evaluated in the body, then no value
  // is pushed.
}
assert.deepEqual(fizzBuzz, [
  // 100 lines of the classic "Fizz", "Buzz", and "FizzBuzz"
])
```

What do you all think of this?

---

To clarify, here's some more detailed semantics:

### Grammar

- `:: ExpressionStatement`
- `:: Declaration`
- `:: VariableStatement`

These are early errors, and they are all redundant, anyways, since you
already have a value you could use.

- `:: ContinueStatement`
- `:: BreakStatement`
- `:: ReturnStatement`
- `:: DebuggerStatement`
- `:: ThrowStatement`
- `:: EmptyStatement`

These are also early errors, since there's no real value you can
associate with them.

- `:: BlockStatement`
- `:: IfStatement`
- `:: SwitchStatement`
- `:: WithStatement`
- `:: TryStatement`

1. Let `completion` be ? ExecuteStatement(`statement`), where
`statement` is one of the statements above.
2. If `completion` is *none*, return `undefined`
3. Otherwise, return `completion`.

- `:: IterationStatement`

1. Return ? ExecuteIterationStatement(`statement`), where `statement`
is one of the statements above.

- `:: LabelledStatement`

This works similarly, but has an outer label instead. The same above
statements are also similarly banned as `LabelledItem` entries.
Additionally, the Annex B extension for FunctionDeclaraions are also
early errors.

(Should these even be allowed? I'm open to making this an early error instead.)

### Abstract Operation ExecuteStatement(`statement`)

1. If `statement` is an IterationStatement:
  1. Let `list` be a new empty list.
  2. Evaluate `statement`, but for each `child` statement:
1. Let `result` be ? ExecuteStatement(`child`).
2. If `result` is not *empty*, then append `result` to `list`.
  3. Return `list`.
2. If `statement` is an ExpressionStatement:
  1. Return the result of evaluating the expression within.
3. If `statement` is a `BreakStatement` or `ContinueStatement`:
  1. Evaluate `statement`
  2. Return *empty*.
4. If `statement` is a `Declaration`:
  1. Evaluate `statement`.
  2. Return the value of the resulting declaration
5. Otherwise:
  1. Let `last` be *empty*
  2. Evaluate `statement`. For each `child` statement:
1. Let `last` be ? ExecuteStatement(`child`).
  3. Note: `last` is the final expression's value, or `empty` if there
was no final expression.
  4. Return `last`.

(I probably missed several edge cases, but this is just a mailing list
strawman.)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss