[e-lang] Atomic expansion of MatchBindExpr to trinary-define
Kevin Reid
kpreid at attglobal.net
Mon May 1 08:09:15 EDT 2006
On May 1, 2006, at 1:46, Mark S. Miller wrote:
> Dean points out that if we give the trinary-define a syntax with a
> left-to-right order that matches its execution order, (e1, e2, p),
> then we can
> allow it to follow E's normal left-to-right scoping rules without
> restriction.
> At that point, we should be able to express MatchBindExpr as an
> expansion to
> trinary-define.
>
> ...For purposes of discussion, we're using the syntax
>
> e ::= keyword (e1, e2) =~ p
Two issues are being confused here.
/Trinary/-define, while it has its own syntactic issues, already
exists and works. The new idea is a left-to-right-order definition
expression, which (other than syntactically) is orthogonal to trinarity.
The =~ expansion below does require trinarity, but not left-to-right-
order, since (for MatchBindExpr) the kernel-define which contains the
user's pattern does not also contain the user's specimen expression.
> Given this form of trinary-define, Kevin proposes that, for example,
>
> left =~ [rA, &rB, [rC]]
>
> should expand to
>
> def specimen__1 := left
> keyword(escape ej {
> keyword(specimen__1, ej) =~ [rA, &rB, [rC]]
> [true, rA, &rB, rC]
> } catch ex__1 {
> def b__1 := Ref.broken(ex__1)
> [false, b__1, b__1, b__1]
> },
> null) =~ [result__1, rA, &rB, rC]
> result__1
>
> In this expansion, if 'rA' succeeds but '[rC]' fails, the inner
> 'rA' stays
> bound and the outer 'rA' is bound to a broken reference. They are
> explicitly
> different variables, as the semantics of atomic binding demands.
There are only three uses of MatchBindExpr in E-on-CL's expander:
- MismatchExpr (!~). This is trivial - it expands to
<MatchBindExpr>.not().
- MapPattern. This use will go away when 'via' is added.
- ConditionalExpr (my lousy name for || and &&).
In the interest of readable full-expansions, the third case should be
expanded directly to kernel-defines.
Our current expansion of e`(def a := b) || (def c := d)` is:
if (def a := b) {
null =~ [&c]
__makeList.run(&c, &a)
} else {
if (def c := d) {
null =~ [&a]
__makeList.run(&c, &a)
} else {
null
}
} =~ [&c, &a]
The expansion using LTR defines rather than =~ is:
# (def a := b) || (def c := d)
keyword if (def a := b) {
keyword __brokenFromBooleanFlow =~ &c
[true, &c, &a]
} else {
if (def c := d) {
keyword __brokenFromBooleanFlow =~ &a
[true, &c, &a]
} else {
__makeBooleanFlowFailure(2)
}
} =~ [res__1, &c, &a]
res__1
Note that no trinary-defines of either type are involved here.
(The occurrences of __brokenFromBooleanFlow and
__makeBooleanFlowFailure are where the existing expansion just does
"null =~ [...]", which gives the irrelevant and confusing result <ref
broken by problem: <NullPointerException: must be an EList rather
than null>>.)
--
Kevin Reid <http://homepage.mac.com/kpreid/>
More information about the e-lang
mailing list