diff options
-rw-r--r-- | NEWS.md | 8 | ||||
-rw-r--r-- | compile.c | 3 | ||||
-rw-r--r-- | doc/syntax/pattern_matching.rdoc | 32 | ||||
-rw-r--r-- | parse.y | 14 | ||||
-rw-r--r-- | test/ruby/test_pattern_matching.rb | 24 |
5 files changed, 79 insertions, 2 deletions
@@ -14,6 +14,13 @@ Note that each entry is kept to a minimum, see links for details. #=> [[3, 5], [5, 7], [11, 13]] ``` +* Pin operator now supports instance, class, and global variables. + [[Feature #17724]] + + @n = 5 + Prime.each_cons(2).lazy.find{_1 in [n, ^@n]} + #=> [3, 5] + * Multiple assignment evaluation order has been made consistent with single assignment evaluation order. With single assignment, Ruby uses a left-to-right evaluation order. With this code: @@ -190,6 +197,7 @@ Excluding feature bug fixes. [Bug #17423]: https://bugs.ruby-lang.org/issues/17423 [Feature #17479]: https://bugs.ruby-lang.org/issues/17479 [Feature #17490]: https://bugs.ruby-lang.org/issues/17490 +[Feature #17724]: https://bugs.ruby-lang.org/issues/17724 [Feature #17744]: https://bugs.ruby-lang.org/issues/17744 [Feature #17762]: https://bugs.ruby-lang.org/issues/17762 [Bug #18003]: https://bugs.ruby-lang.org/issues/18003 @@ -6462,6 +6462,9 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c case NODE_CONST: case NODE_LVAR: case NODE_DVAR: + case NODE_IVAR: + case NODE_CVAR: + case NODE_GVAR: case NODE_TRUE: case NODE_FALSE: case NODE_SELF: diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc index 69756369fb..49835def22 100644 --- a/doc/syntax/pattern_matching.rdoc +++ b/doc/syntax/pattern_matching.rdoc @@ -312,6 +312,33 @@ One important usage of variable pinning is specifying that the same value should end #=> "not matched" +In addition to pinning local variables, you can also pin instance, global, and class variables: + + $gvar = 1 + class A + @ivar = 2 + @@cvar = 3 + case [1, 2, 3] + in ^$gvar, ^@ivar, ^@@cvar + "matched" + else + "not matched" + end + #=> "matched" + end + +You can also pin the result of arbitrary expressions using parentheses: + + a = 1 + b = 2 + case 3 + in ^(a + b) + "matched" + else + "not matched" + end + #=> "matched" + == Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ As already mentioned above, array, find, and hash patterns besides literal arrays and hashes will try to match any object implementing +deconstruct+ (for array/find patterns) or +deconstruct_keys+ (for hash patterns). @@ -449,7 +476,10 @@ Approximate syntax is: value_pattern: literal | Constant - | ^variable + | ^local_variable + | ^instance_variable + | ^class_variable + | ^global_variable | ^(expression) variable_pattern: variable @@ -1203,7 +1203,7 @@ static int looking_at_eol_p(struct parser_params *p); %type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg %type <id> f_kwrest f_label f_arg_asgn call_op call_op2 reswords relop dot_or_colon %type <id> p_rest p_kwrest p_kwnorest p_any_kwrest p_kw_label -%type <id> f_no_kwarg f_any_kwrest args_forward excessed_comma +%type <id> f_no_kwarg f_any_kwrest args_forward excessed_comma nonlocal_var %type <ctxt> lex_ctxt /* keep <ctxt> in ripper */ %token END_OF_INPUT 0 "end-of-input" %token <id> '.' @@ -4517,6 +4517,13 @@ p_var_ref : '^' tIDENTIFIER /*% %*/ /*% ripper: var_ref!($2) %*/ } + | '^' nonlocal_var + { + /*%%%*/ + if (!($$ = gettable(p, $2, &@$))) $$ = NEW_BEGIN(0, &@$); + /*% %*/ + /*% ripper: var_ref!($2) %*/ + } ; p_expr_ref : '^' tLPAREN expr_value ')' @@ -4993,6 +5000,11 @@ simple_numeric : tINTEGER | tIMAGINARY ; +nonlocal_var : tIVAR + | tGVAR + | tCVAR + ; + user_variable : tIDENTIFIER | tIVAR | tGVAR diff --git a/test/ruby/test_pattern_matching.rb b/test/ruby/test_pattern_matching.rb index c494550574..320c2c00c7 100644 --- a/test/ruby/test_pattern_matching.rb +++ b/test/ruby/test_pattern_matching.rb @@ -400,6 +400,30 @@ END a == 0 end end + + assert_block do + @a = /a/ + case 'abc' + in ^@a + true + end + end + + assert_block do + @@TestPatternMatching = /a/ + case 'abc' + in ^@@TestPatternMatching + true + end + end + + assert_block do + $TestPatternMatching = /a/ + case 'abc' + in ^$TestPatternMatching + true + end + end end def test_pin_operator_expr_pattern |