Skip to content

[RFC] Implement block expressions #5403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

iluuu1994
Copy link
Member

@nikic

This implementation replaces the statement list ('{' inner_statement_list '}') by a block expression that CAN contain an expression. After implementing it this way I don't think it's the right approach.

Two things to note:

$x = {
    // Doesn't work because the expression belongs to the statement list instead of the terminating expression
    { 1 }
};

The reason for this is that the semicolon is optional with expression statements that only contain a single block expression to maintain backwards compatibility. Additionally the semicolon won't be enforced here:

// No error or warning
function foo() {
    {
        echo 'Foo';
        'Bar'
    } // Should require a semicolon IMO
}

Alternative approach

Instead of replacing the statement list completely we add the new block expression as '{' inner_statement_list expr '}'. This avoids the ambiguity with the existing statement list.

To support blocks in arrow functions without returning a value we accept statement lists in the arrow functions body and transform it to a block with a null return value ({ ...; null }). This would solve the two cases above and require much fewer changes in the grammar.

WDYT?

I'll create a PR for this alternative approach to demonstrate what I mean. The whole terminology here can be very confusing.

Side note: This breaks the optimizer in the same way the throw expression does (see 005.phpt).

@iluuu1994
Copy link
Member Author

It's also worth noting that neither of those approaches fix the issue of having to differentiate between match expressions that allow blocks vs those that don't. Instead now we have to differentiate between blocks that require a return value vs those that don't. Pretty much the same thing.

match ($x) {
    // This is fine
    1 => {},
}

$x = match($y) {
    // This isn't
    1 => {},
};

expr_without_block:
expr_not_starting_with_expr
{ $$ = $1; }
| expr_without_block T_BOOLEAN_OR expr
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expect this to break precedence annotations.

@iluuu1994
Copy link
Member Author

Closing in favor of #5407.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants