Skip to content

Commit

Permalink
- ruby*.y: fixed context inside lambda args and module. (#709)
Browse files Browse the repository at this point in the history
Previously we didn't push context for module and lambda arguments and so we didn't reject some code (or we rejected what's allowed).
However, examples that should've raised errors are complicated and it's very unlikely that any code was affected. At least no related issues were reported.

Examples of code that is accepted/rejected differently after this change:

1. `->(a) { module M; _1; end }`
We didn't push context for module M, and so argument a conflicted with implicit parameter `_1`. In Ruby module opens a new scope and so `_1` is just a regular local variable.

2. `class A; ->(a = (return; 1)) {}; end`
This code is valid, because return is a part of the lambda. But we didn't store this fact internally, and so it was rejected before.

Both examples described above (and all similar variations) are fixed in this commit.

Also, slightly improved assertions related to context (`assert_context`). Instead of checking state of the half-reduced AST (which is impossible for lambda args for example) we use a special get_context macro-like node that grabs snapshot of the `parser.context`.
  • Loading branch information
iliabylich committed Jun 11, 2020
1 parent b5c1fb4 commit bc20734
Show file tree
Hide file tree
Showing 18 changed files with 273 additions and 78 deletions.
1 change: 1 addition & 0 deletions lib/parser/context.rb
Expand Up @@ -5,6 +5,7 @@ module Parser
#
# Supported states:
# + :class - in the class body (class A; end)
# + :module - in the module body (module M; end)
# + :sclass - in the singleton class body (class << obj; end)
# + :def - in the method body (def m; end)
# + :defs - in the singleton method body (def self.m; end)
Expand Down
18 changes: 14 additions & 4 deletions lib/parser/macruby.y
Expand Up @@ -1042,11 +1042,15 @@ rule
result = @builder.block(val[0],
begin_t, args, body, end_t)
}
| tLAMBDA lambda
| tLAMBDA
{
@context.push(:lambda)
}
lambda
{
lambda_call = @builder.call_lambda(val[0])

args, (begin_t, body, end_t) = val[1]
args, (begin_t, body, end_t) = val[2]
result = @builder.block(lambda_call,
begin_t, args, body, end_t)
}
Expand Down Expand Up @@ -1160,6 +1164,7 @@ rule
{
@static_env.extend_static
@lexer.push_cmdarg
@context.push(:module)
}
bodystmt kEND
{
Expand All @@ -1172,6 +1177,7 @@ rule

@lexer.pop_cmdarg
@static_env.unextend
@context.pop
}
| kDEF fname
{
Expand Down Expand Up @@ -1453,9 +1459,13 @@ rule
lambda: {
@static_env.extend_dynamic
}
f_larglist lambda_body
f_larglist
{
@context.pop
}
lambda_body
{
result = [ val[1], val[2] ]
result = [ val[1], val[3] ]

@static_env.unextend
}
Expand Down
2 changes: 2 additions & 0 deletions lib/parser/ruby18.y
Expand Up @@ -1156,6 +1156,7 @@ rule
| kMODULE cpath
{
@static_env.extend_static
@context.push(:module)
}
bodystmt kEND
{
Expand All @@ -1167,6 +1168,7 @@ rule
val[3], val[4])

@static_env.unextend
@context.pop
}
| kDEF fname
{
Expand Down
18 changes: 14 additions & 4 deletions lib/parser/ruby19.y
Expand Up @@ -1009,11 +1009,15 @@ rule
result = @builder.block(val[0],
begin_t, args, body, end_t)
}
| tLAMBDA lambda
| tLAMBDA
{
@context.push(:lambda)
}
lambda
{
lambda_call = @builder.call_lambda(val[0])

args, (begin_t, body, end_t) = val[1]
args, (begin_t, body, end_t) = val[2]
result = @builder.block(lambda_call,
begin_t, args, body, end_t)
}
Expand Down Expand Up @@ -1127,6 +1131,7 @@ rule
{
@static_env.extend_static
@lexer.push_cmdarg
@context.push(:module)
}
bodystmt kEND
{
Expand All @@ -1139,6 +1144,7 @@ rule

@lexer.pop_cmdarg
@static_env.unextend
@context.pop
}
| kDEF fname
{
Expand Down Expand Up @@ -1433,9 +1439,13 @@ rule
lambda: {
@static_env.extend_dynamic
}
f_larglist lambda_body
f_larglist
{
@context.pop
}
lambda_body
{
result = [ val[1], val[2] ]
result = [ val[1], val[3] ]

@static_env.unextend
}
Expand Down
18 changes: 14 additions & 4 deletions lib/parser/ruby20.y
Expand Up @@ -1039,11 +1039,15 @@ rule
result = @builder.block(val[0],
begin_t, args, body, end_t)
}
| tLAMBDA lambda
| tLAMBDA
{
@context.push(:lambda)
}
lambda
{
lambda_call = @builder.call_lambda(val[0])

args, (begin_t, body, end_t) = val[1]
args, (begin_t, body, end_t) = val[2]
result = @builder.block(lambda_call,
begin_t, args, body, end_t)
}
Expand Down Expand Up @@ -1157,6 +1161,7 @@ rule
{
@static_env.extend_static
@lexer.push_cmdarg
@context.push(:module)
}
bodystmt kEND
{
Expand All @@ -1169,6 +1174,7 @@ rule

@lexer.pop_cmdarg
@static_env.unextend
@context.pop
}
| kDEF fname
{
Expand Down Expand Up @@ -1487,9 +1493,13 @@ opt_block_args_tail:
lambda: {
@static_env.extend_dynamic
}
f_larglist lambda_body
f_larglist
{
@context.pop
}
lambda_body
{
result = [ val[1], val[2] ]
result = [ val[1], val[3] ]

@static_env.unextend
}
Expand Down
11 changes: 9 additions & 2 deletions lib/parser/ruby21.y
Expand Up @@ -1029,11 +1029,15 @@ rule
result = @builder.block(val[0],
begin_t, args, body, end_t)
}
| tLAMBDA lambda
| tLAMBDA
{
@context.push(:lambda)
}
lambda
{
lambda_call = @builder.call_lambda(val[0])

args, (begin_t, body, end_t) = val[1]
args, (begin_t, body, end_t) = val[2]
result = @builder.block(lambda_call,
begin_t, args, body, end_t)
}
Expand Down Expand Up @@ -1147,6 +1151,7 @@ rule
{
@static_env.extend_static
@lexer.push_cmdarg
@context.push(:module)
}
bodystmt kEND
{
Expand All @@ -1159,6 +1164,7 @@ rule

@lexer.pop_cmdarg
@static_env.unextend
@context.pop
}
| kDEF fname
{
Expand Down Expand Up @@ -1471,6 +1477,7 @@ opt_block_args_tail:
{
result = @lexer.cmdarg.dup
@lexer.cmdarg.clear
@context.pop
}
lambda_body
{
Expand Down
11 changes: 9 additions & 2 deletions lib/parser/ruby22.y
Expand Up @@ -1028,11 +1028,15 @@ rule
result = @builder.block(val[0],
begin_t, args, body, end_t)
}
| tLAMBDA lambda
| tLAMBDA
{
@context.push(:lambda)
}
lambda
{
lambda_call = @builder.call_lambda(val[0])

args, (begin_t, body, end_t) = val[1]
args, (begin_t, body, end_t) = val[2]
result = @builder.block(lambda_call,
begin_t, args, body, end_t)
}
Expand Down Expand Up @@ -1146,6 +1150,7 @@ rule
{
@static_env.extend_static
@lexer.push_cmdarg
@context.push(:module)
}
bodystmt kEND
{
Expand All @@ -1158,6 +1163,7 @@ rule

@lexer.pop_cmdarg
@static_env.unextend
@context.pop
}
| kDEF fname
{
Expand Down Expand Up @@ -1470,6 +1476,7 @@ opt_block_args_tail:
{
result = @lexer.cmdarg.dup
@lexer.cmdarg.clear
@context.pop
}
lambda_body
{
Expand Down
11 changes: 9 additions & 2 deletions lib/parser/ruby23.y
Expand Up @@ -1028,11 +1028,15 @@ rule
result = @builder.block(val[0],
begin_t, args, body, end_t)
}
| tLAMBDA lambda
| tLAMBDA
{
@context.push(:lambda)
}
lambda
{
lambda_call = @builder.call_lambda(val[0])

args, (begin_t, body, end_t) = val[1]
args, (begin_t, body, end_t) = val[2]
result = @builder.block(lambda_call,
begin_t, args, body, end_t)
}
Expand Down Expand Up @@ -1146,6 +1150,7 @@ rule
{
@static_env.extend_static
@lexer.push_cmdarg
@context.push(:module)
}
bodystmt kEND
{
Expand All @@ -1158,6 +1163,7 @@ rule

@lexer.pop_cmdarg
@static_env.unextend
@context.pop
}
| kDEF fname
{
Expand Down Expand Up @@ -1470,6 +1476,7 @@ opt_block_args_tail:
{
result = @lexer.cmdarg.dup
@lexer.cmdarg.clear
@context.pop
}
lambda_body
{
Expand Down
11 changes: 9 additions & 2 deletions lib/parser/ruby24.y
Expand Up @@ -1047,11 +1047,15 @@ rule
result = @builder.block(val[0],
begin_t, args, body, end_t)
}
| tLAMBDA lambda
| tLAMBDA
{
@context.push(:lambda)
}
lambda
{
lambda_call = @builder.call_lambda(val[0])
args, (begin_t, body, end_t) = val[1]
args, (begin_t, body, end_t) = val[2]
result = @builder.block(lambda_call,
begin_t, args, body, end_t)
}
Expand Down Expand Up @@ -1165,6 +1169,7 @@ rule
{
@static_env.extend_static
@lexer.cmdarg.push(false)
@context.push(:module)
}
bodystmt kEND
{
Expand All @@ -1177,6 +1182,7 @@ rule
@lexer.cmdarg.pop
@static_env.unextend
@context.pop
}
| kDEF fname
{
Expand Down Expand Up @@ -1487,6 +1493,7 @@ opt_block_args_tail:
}
f_larglist
{
@context.pop
@lexer.cmdarg.push(false)
}
lambda_body
Expand Down
11 changes: 9 additions & 2 deletions lib/parser/ruby25.y
Expand Up @@ -1057,11 +1057,15 @@ rule
result = @builder.block(val[0],
begin_t, args, body, end_t)
}
| tLAMBDA lambda
| tLAMBDA
{
@context.push(:lambda)
}
lambda
{
lambda_call = @builder.call_lambda(val[0])
args, (begin_t, body, end_t) = val[1]
args, (begin_t, body, end_t) = val[2]
result = @builder.block(lambda_call,
begin_t, args, body, end_t)
}
Expand Down Expand Up @@ -1151,6 +1155,7 @@ rule
{
@static_env.extend_static
@lexer.cmdarg.push(false)
@context.push(:module)
}
bodystmt kEND
{
Expand All @@ -1163,6 +1168,7 @@ rule
@lexer.cmdarg.pop
@static_env.unextend
@context.pop
}
| kDEF fname
{
Expand Down Expand Up @@ -1484,6 +1490,7 @@ opt_block_args_tail:
}
f_larglist
{
@context.pop
@lexer.cmdarg.push(false)
}
lambda_body
Expand Down

0 comments on commit bc20734

Please sign in to comment.