InterpolationPatternMatches
waldemarhorwat opened this issue · 4 comments
I don't understand what ${Expression}
and ${Expression} with MatchPattern
are supposed to do with the expression's value.
The semantics of the former is:
- Let exprRef be evaluating the Expression.
- Let exprVal be ? GetValue(exprRef).
- Let result be ? InvokeCustomMatcher(exprVal, matchable).
- If result is an ECMAScript language value, return true.
- Return result.
Given that InvokeCustomMatcher is specified to always return either an ECMAScript language value or an abrupt completion, this will either exit with an abrupt completion in step 3 or return true in step 4. Step 5 is dead code.
Similar problem in the other variant:
-
Let exprRef be evaluating the Expression.
-
Let exprVal be ? GetValue(exprRef).
-
Let result be ? InvokeCustomMatcher(exprVal, matchable).
-
If result is false, return false.
-
If result is an ECMAScript language value, then
a. Return ? MatchPatternMatches of MatchPattern with arguments result and cacheGroup.
-
Return ? MatchPatternMatches of MatchPattern with arguments matchable and cacheGroup.
Looks like this part of the spec isn't perfect yet :-)
The intention is that ${expression}
invokes a custom matcher if present and the expression is an object, to do SameValueZero if it's a primitive, else to throw.
If a custom matcher is used, and it did match, the value
is used with with
to apply the MatchPattern, which may or may not match, and may or may not create bindings.
Tips on how to specify this correctly would be greatly appreciated!
Oh, so false
is both a spec value and an ECMAScript language value?
By design, InvokeCustomMatcher
should return this: a Boolean (true
means a simple match) or an ECMAScript language value (means the further matchable in the with
pattern should be replaced with this value).
For example:
const x = 1
match (1) { when (${x}): void 0 };
// ^ InvokeCustomMatcher: *true* (spec value)
match (2) { when (${x}): void 0 };
// ^ InvokeCustomMatcher: *false* (spec value)
const y = { [Symbol.matcher](val) { return { matched: val === 1, value: val + 1 } } }
match (1) { when (${y}): void 0 };
// ^ InvokeCustomMatcher: 2 (ECMAScript language value)
match (2) { when (${y}): void 0 };
// ^ InvokeCustomMatcher: *false* (spec value)
I agree this is very subtle. I changed to use ~not-matched~ or ECMAScript language value
to represent that in #277.
The fix is incorrect: InvokeCustomMatcher is still specified to always return either an ECMAScript language value or an abrupt completion.