Specifying the Existential Operator using Abrupt Completion

Andreas Rossberg rossberg at google.com
Wed May 21 05:56:33 PDT 2014


On 21 May 2014 14:33, Claude Pache <claude.pache at gmail.com> wrote:
>
> I have thought about the right semantics (and the issues) of the existential operator.
>
>     user.getPlan?().value?.score;
>
> The intended semantics of `?` is that, whenever its LHS evaluates to `null` or `undefined`,
> the evaluation of the whole expression (or subexpression) is interrupted and return immediately `undefined`.
> In other word, it may be seen as an abrupt completion, as demonstrated by the following expansion:
>
>     (do {
>         let result = user           // user
>         result = result.getPlan // _.getPlan
>         if (result == null)         // _?
>             break                   // abrupt completion

Drive-by comment: This would break the switch or loop statement
surrounding the do-expression (or be an error if there isn't any). You
need to wrap the statements into a labelled block and break that.

/Andreas


>         result = result.call(user)  // _()
>         result = result.value       // _.value
>         if (result == null)         // _?
>             break                   // abrupt completion
>         result = result.score       // _.score
>     })
>
> Now, it should be determined, whenever such an abrupt completion is encountered during evaluation,
> in which cases it should propagate, and in which case it should be transformed into a normal completion of value `undefined`.
> Roughly, property accesses and function calls should propagate it when it is found on their LHS,
> and in all other cases it should be mutated it to NormalCompletion(undefined). E.g.:
>
>     (user.getPlan?().value?.score || 0).toFixed(2) // the `||` operator interrupts the abrupt completion propagation
>
>
> Here is a simple strawman that illustrates how that idea could be implemented in the spec.
> It has some known (and unknown) issues, but I think it gives a good idea of the mechanism.
> And it resolves quite naturally the non-compositional issue of the original strawman (see the remark at the end of the message).
>
> The specification is patched as follows:
>
> 6.2.2 The Completion Record Specification Type
>
>     An additional value is allowed for the [[type]] field, besides normal, break, continue, return, or throw; namely: failsoft.
>
> 6.2.3.1 GetValue(V)
>
> An additional parameter is added to that abstract operation:
>
>     GetValue(V, propagateFailsoft = false)
>
> If the second argument is absent, it is presumed to be false. An additional step is prepended to the algorithm:
>
> 0. If V is an abrupt completion of [[type]] failsoft and if propagateFailsoft is false,
>     a. Let V be NormalCompletion(undefined).
>
>
> 12.3 Left-Hand-Side Expressions
>
> The production of MemberExpression is expanded as follows:
>
> FailsoftMark:
>     "?"
>
> MemberExpression:
>     (...)
>     MemberExpression FailsoftMark
>
> The runtime semantics is the following:
>
> MemberExpression: MemberExpression FailsoftMark
>
>     1. Let ref be the result of evaluating MemberExpression.
>     2. Let val be GetValue(ref, true).
>     3. ReturnIfAbrupt(val).
>     3. If val is null or undefined,
>         a. Return Completion([[type]]: failsoft, [[value]]: undefined, [[target]]: empty).
>     4. Return val.
>
> Here, there is an issue in expressions like `a.b?(c)`, because the correct `this` value of the method call won't be able to be determined.
> This can be resolved by further suitable refinements.
>
> Finally, in the algorithms involving LeftHandSideExpression's (section 12.3), some calls to GetValue(...) are replaced by GetValue(..., true).
> They are:
>
> Property Accessors
> 12.3.2.. Runtime Semantics: Evaluation
> MemberExpression : MemberExpression [ Expression ]
> Step 2. Let baseValue be GetValue(baseReference, true).
>
> The new operator
> 12.3.3.1 Runtime Semantics: Evaluation
> NewExpression : new NewExpression
> Step 2. Let constructor be GetValue(ref, true).
>
> ibid.
> MemberExpression : new MemberExpression Arguments
> Step 2. Let constructor be GetValue(ref, true).
>
> Function Calls
> 12.3.4.2 Runtime Semantics: EvaluateCall
> Step 1. Let func be GetValue(ref, true).
>
> In all other cases, a call to GetValue(...) will intercept a failsoft abrupt completion and return `undefined`.
>
>
> A notable fact of that strawman is that the two following expressions are equivalent:
>
>     (a?.b).c
>     a?.b.c
>
> because evaluating a ParenthesizedExpression does not apply GetValue(...) (Section 12.2.10.4).
>
> —Claude
>
>
>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss


More information about the es-discuss mailing list