Previously checking for a command write was the same concept as
checking for a command call, but in reality (and since 4.0) they
are different things.
https://github.com/ruby/prism/commit/e9cdac6b98
There are times when we don't need explicit order in a list of
constants, namely when looking at names of captures in a pattern
match and names of captures in a regular expression. In these cases
it's better to be linear with respect to the number of names, so
using a hash makes a little more sense.
https://github.com/ruby/prism/commit/d1c23d4956
When a variable is captured anywhere in a pattern, the operands of each
alternation are visited to report captures inside them. That visitor
treated every local variable target as a capture, including
underscore-prefixed names and targets that belong to a lambda, a string
interpolation, or a pinned expression:
case foo
in [bar, 1 | _baz] # error
in [bar, "#{case 1; in baz; end}" | 2] # error
end
Without `bar` both are accepted. Skip underscore-prefixed names, like
parse_pattern_capture does, and only descend into the nodes that make up
the pattern itself. Nested alternations are skipped too, their operands
were already checked when they were parsed. Before this, a capture like
`1 => [x, (1 | y) | 2]` was reported twice.
The new fixture is excluded from the tests that compare against parse.y,
which currently rejects these forms because of the capture of `bar`:
https://bugs.ruby-lang.org/issues/22310https://github.com/ruby/prism/commit/33ef692741
(https://github.com/ruby/prism/pull/4221)
Ref https://bugs.ruby-lang.org/issues/22294
pm_check_value_expression descended the left operand of every and/or
node it visited. Because pm_and_node_create and pm_or_node_create
already assert the value of their left operand when the node is built,
walking a left-associative chain such as `a && a && ... && a`
re-checked the whole left spine once per operator, which is quadratic
in the length of the chain: 16k operators took seconds.
The left operand of an existing and/or node was therefore already
checked, so stop at the node instead of descending. This makes the
check linear. The only observable change is that a void value on the
left spine of a chain is now reported once, at the innermost node
where it is created, rather than once per enclosing operator; the
errors fixture that pinned the duplicate is updated to match.
https://github.com/ruby/prism/commit/b19a0a5bc0
This reverts commit 0017dea395,
5e36630fc0, and
f3ec056c9f.
We are trying to bump to latest IRB, which has "Accomodate new prism
tokens", but that runs into another CI failure. While we figure out a
path forward at <https://github.com/ruby/ruby/pull/18207>, let's get
back to a green CI.
This was previously an allow-list of the various tokens that were
considered the start of a pattern expression. Instead, use our
existing expression checking stuff and avoid having to list out
each token.
https://github.com/ruby/prism/commit/a139586ca0
Co-authored-by: kai-matsudate <kai.matsudate@techouse.jp>
A couple more deviations from the parse.y grammar with the
command_call and arg productions.
* pm_block_call_p — allow parens on chain links (meth 1 do end.fun(x))
* pm_command_call_value_p — recognize const-path brace commands (Foo::Bar { })
* super with do/end as a block_call (chaining: super 1 do end.baz)
* foo(Foo::Bar { } => v)
https://github.com/ruby/prism/commit/2c2a463021
The value of a `rescue` modifier is a full `stmt` in the grammar in
three of its six productions, but we parsed it as a plain expression
in every case. This rejected valid syntax such as `a rescue b, c = 1`
and accepted invalid syntax such as `a = 1 rescue not b`.
These are the relevant grammar rules:
stmt : stmt modifier_rescue stmt
| mlhs '=' mrhs_arg modifier_rescue stmt
command_rhs : command_call_value modifier_rescue stmt
arg_rhs : arg modifier_rescue arg
endless_arg : endless_arg modifier_rescue arg
endless_command : endless_command modifier_rescue arg
parse_rescue_modifier_value will now parse either a stmt or an arg
depending on the caller.
https://github.com/ruby/prism/commit/07e63f707f
Alphanumerics are correctly handled in the check below
by simply discarding the `%`.
The same was not true for the other types, which caused some assumption to no longer hold.
https://github.com/ruby/prism/commit/69a9a36a6a
Prism accepted a modifier conditional as the predicate of an `if`/`unless`
(and `elsif`), while parse.y rejects it:
if a if b then end # parse.y: SyntaxError, prism: accepted
unless a unless b then end
The `if`/`unless`/`elsif` predicate was parsed with a floor of
`PM_BINDING_POWER_MODIFIER`, which is inclusive of the modifier
conditionals (`if`/`unless`/`while`/`until`, left binding power
`PM_BINDING_POWER_MODIFIER`), so they were absorbed into the predicate.
`while`/`until` predicates already use `PM_BINDING_POWER_COMPOSITION` and
reject these correctly.
Raise the floor to `PM_BINDING_POWER_MODIFIER + 1` so the predicate still
absorbs `and`/`or` (and tighter operators) but excludes the modifier
conditionals, matching parse.y and aligning `if`/`unless` with
`while`/`until`.
https://github.com/ruby/prism/commit/0fa8d8f8d8
Introduce PM_TOKEN_KEYWORD_DO_BLOCK to distinguish do-blocks on
command-style calls from regular `do` keywords. Add
parse_command_do_block to attach these blocks to call nodes. Track
in_endless_def_body to prevent do-block consumption inside endless
method definitions, allowing blocks to correctly bubble up to outer
contexts like `private def f = puts "Hello" do end`.
https://github.com/ruby/prism/commit/7d17fd254b
They currently complain that the parent method is not forwarding.
But the actual problem is that these types of arguments simply don't
accept `...`
Fixes [Bug #21927]
https://github.com/ruby/prism/commit/0aa2363331
When we hit EOF and still have lex modes left, it means some content was unterminated.
Heredocs specifically have logic that needs to happen when the body finished lexing.
If we don't reset the mode back to how it was before, it will not continue lexing at the correct place.
Followup to https://github.com/ruby/prism/pull/3918.
We can't call into `parser_lex` since it resets token locations.
https://github.com/ruby/prism/commit/27c24fdc0d
When we hit EOF and still have lex modes left, it means some content was unterminated.
Heredocs specifically have logic that needs to happen when the body finished lexing.
If we don't reset the mode back to how it was before, it will not continue lexing at the correct place.
https://github.com/ruby/prism/commit/8f35e8ef25
This commit adds an `expect1_opening` function that expects a token and
attaches the error to the opening token location rather than the current
position. This is useful for errors about missing closing tokens, where
we want to point to the line with the opening token rather than the end
of the file.
For example:
```ruby
def foo
def bar
def baz
^ expected an `end` to close the `def` statement
^ expected an `end` to close the `def` statement
^ expected an `end` to close the `def` statement
```
This would previously produce three identical errors at the end of the
file. After this commit, they would be reported at the opening token
location:
```ruby
def foo
^~~ expected an `end` to close the `def` statement
def bar
^~~ expected an `end` to close the `def` statement
def baz
^~~ expected an `end` to close the `def` statement
```
I considered using the end of the line where the opening token is
located, but in some cases that would be less useful than the opening
token location itself. For example:
```ruby
def foo def bar def baz
```
Here the end of the line where the opening token is located would be the
same for each of the unclosed `def` nodes.
https://github.com/ruby/prism/commit/2d7829f060