Guards redux

Gavin Bierman gavin.bierman at oracle.com
Wed Mar 10 14:47:30 UTC 2021


Okay, so it seems like our initial stab at guards and a pattern conjunction
operator needs some finessing. 

Here's another take, inspired by Guy's emails. 

Step 1. Let's use `p && e` as the way to guard a pattern p with a boolean
expression e. 

Step 2. [Now or later] Let's use `&` (and `|`) as the conjunction and
disjunction operators on patterns.

There are a couple of immediate parsing puzzlers:

* e instanceof String s && s.length() > 2

This parses as `(e instanceof String s) && s.length() > 2` today. We need to be
careful that our grammar continues to make this the case (see below). We will
also introduce a parenthesized pattern, which you can use if you want the
dangling `&& s.length() > 2` to parse as a guard for the `String s` type
pattern. (It is extremely fortuitous that the functional behavior of both
expressions is the same, but either way I think this is a simple rule.)

* case p && b -> c -> b

Now we have some ambiguity from the `->` in a lambda expression and in a switch
rule. Fortunately, again I think we can just lean into the grammar to get what
we want. At the moment, the grammar for expressions is:

    Expression:
        LambdaExpression
        AssignmentExpression

As a lambda expression can never be a boolean expression it can never
meaningfully serve as a guard for a pattern. Great!

So, I'd like to suggest this grammar for patterns (including pattern conjunction
and pattern disjunction operators for completeness but we can drop them from the
first release): 

Pattern:
: ConditionalOrPattern
: ConditionalOrPattern `&&` Guard

ConditionalOrPattern:
: ConditionalAndPattern
: ConditionalOrPattern `|` ConditionalAndPattern

ConditionalAndPattern:
: PrimaryPattern
: ConditionalAndPattern `&` PrimaryPattern

PrimaryPattern:
: TypePattern
: RecordPattern
: ArrayPattern
: `(` Pattern `)`

Guard:
: AssignmentExpression

Along with the following change to the grammar for instanceof:

InstanceofExpression:
: RelationalExpression `instanceof` ReferenceType 
: RelationalExpression `instanceof` PrimaryPattern      <-- Note!

Some consequences:

p1 & p2 & p3 && g1 && g2 parses as ((p1 & p2) & p3) && (g1 && g2), yay!

p1 && g1 & p2 && g2 needs to be bracketed as (p1 && g1) & (p2 && g2) to parse
properly. But that's okay, as I think the second is much clearer.

Let me know what you think.

Gavin


More information about the amber-spec-experts mailing list