Spawn proposal strawman

David-Sarah Hopwood david-sarah at jacaranda.org
Sat May 9 14:32:34 PDT 2009


Brendan Eich wrote:
> With some successful experiments, perhaps we can converge quickly on a
> standardizable high-level AST.
> 
> Suggestions welcome on any issues that crop up. Here's one: && and ||
> want to group to the right, for short-circuiting evaluation, yet the
> ES1-5 grammars use standard left-recursive bottom-up-style productions:
> 
> LogicalORExpression: See 11.11
>      LogicalANDExpression
>      LogicalORExpression || LogicalANDExpression
> 
> This will produce a tree for X || Y || Z shaped like this initializer
> (skipping tedious quoting of property names):
> 
>  {op: "||",
>   left: {op: "||",
>          left: {op: "Id", value: "X"},
>          right: {op: "Id", value: "Y"}},
>   right: {op: "Id", value: "Z"}}

I would mildly prefer to use an S-expression-style AST, like this:

  ["||",
    ["||",
      ["Id", "X"],
      ["Id", "Y"]],
    ["Id", "Z"]]

which is more concise, does not lose any useful information, and
is easier to remember. This is the same style as used in JsonML
(www.jsonml.org).

> A definitional interpreter the recursively evaluates nodes can handle
> this easily enough, although the right-recursive AST alternative, which
> is equivalent AFAIK, would be better for avoiding recursion. A simple
> code generator, on the other hand, definitely wants the right-recursive
> tree:
> 
>  {op: "||",
>   left: {op: "Id", value: "Z"},
>   right: {op: "||",
>           left: {op: "Id", value: "X"},
>           right: {op: "Id", value: "Y"}}}
> 
> so that, at each recursion level, branches to the next bytecode after
> the expression can be emitted and fixed up using local variables only.
> Of course backpatching could be used (and must be used for other control
> structures in the language), but all else equal, || and && want to be
> right-associated in the AST.

I'm not convinced about this. '||' and '&&' are defined in ES5 to
be left-associative; that is, "a || b || c" is defined to mean
"(a || b) || c", and that is how its evaluation is specified.

It so happens that this is *semantically* equivalent to "a || (b || c)",
but that is not an equivalence of abstract syntax. It's trivial for a
code generator (even a very naïve one) to convert between these if it
needs to, but the AST should preserve the associativity defined in the
language spec.

> I'm in favor of right association for these logical connective ops,
> since they short-circuit evaluation based on truthiness (||) or
> falsiness (&&) of the left operand. Thoughts?

Evaluating "a || b || c" always evaluates the left operand of the
outer '||', which is "a || b". This in turn always evaluates "a". But
the left operand of the outer expression is not "a", unless we also
want to change how '||' and '&&' are specified.

-- 
David-Sarah Hopwood ⚥




More information about the es-discuss mailing list