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