ruby-next-core 0.14.0 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 55cb050984d91ee15965b5629bd998d7300af1051e7ad721f1dfed77fc6df7c7
4
- data.tar.gz: ac68a6f7da2b826b11a40be72948601f2d12ce8b1cd27ab9953977238c1e488d
3
+ metadata.gz: c8f084701e3c87e432518f6367d883b9524dbc002d77352793b912504a63e8d0
4
+ data.tar.gz: bc44011f4183dd2133f259f07dc7a40c4be5dbd4cf2f85e35efb525463011ace
5
5
  SHA512:
6
- metadata.gz: 7cd0de569637973ff61866733a6a3d59dac4e317bf5e522b23a88fc5af8941e4a072ae1dfbf26163a661c71911f7801545cad00134cd826d4913f684b03473e8
7
- data.tar.gz: 2ebf8f0a42bd0771cfbc2f2240a3844436d3f108e5cec292ec2cd7e3bebef0a332088357a892cf3cd2b0c6835e9f39679cc472cd6a0ac4d120850194d8f2e783
6
+ metadata.gz: eabbb2bc0ccfa86f033eabce8001d208638a3995c7f112c29ed0e5f3142597bc60d87112899e7d383b09739c7c4cbe2eff06d10c58df7577cf12f80d4cb19c4d
7
+ data.tar.gz: 000c76da160d8dba1231121b7e71b335da2d9775240bfc7a9fb2201ca55d6ac366f47f1c918a3c5ebb46abdcc90857b0c3a9d221455ed6eff68965f5b8f905e9
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.14.1 (2022-01-21)
6
+
7
+ - Fix nested find patterns transpiling. ([@palkan][])
8
+
5
9
  ## 0.14.0 🎄
6
10
 
7
11
  - Add `Integer.try_convert`. ([@palkan][])
@@ -243,6 +243,7 @@ module RubyNext
243
243
 
244
244
  @deconstructed_keys = {}
245
245
  @predicates = Predicates::CaseIn.new
246
+ @lvars = []
246
247
 
247
248
  matchee_ast =
248
249
  s(:begin, s(:lvasgn, MATCHEE, node.children[0]))
@@ -272,6 +273,7 @@ module RubyNext
272
273
 
273
274
  @deconstructed_keys = {}
274
275
  @predicates = Predicates::Noop.new
276
+ @lvars = []
275
277
 
276
278
  matchee =
277
279
  s(:begin, s(:lvasgn, MATCHEE, node.children[0]))
@@ -282,10 +284,12 @@ module RubyNext
282
284
  arr: MATCHEE_ARR,
283
285
  hash: MATCHEE_HASH
284
286
  ) do
285
- send(
286
- :"#{node.children[1].type}_clause",
287
- node.children[1]
288
- ).then do |node|
287
+ with_declared_locals do
288
+ send(
289
+ :"#{node.children[1].type}_clause",
290
+ node.children[1]
291
+ )
292
+ end.then do |node|
289
293
  s(:begin,
290
294
  s(:or,
291
295
  node,
@@ -311,6 +315,7 @@ module RubyNext
311
315
 
312
316
  @deconstructed_keys = {}
313
317
  @predicates = Predicates::Noop.new
318
+ @lvars = []
314
319
 
315
320
  matchee =
316
321
  s(:begin, s(:lvasgn, MATCHEE, node.children[0]))
@@ -321,10 +326,12 @@ module RubyNext
321
326
  arr: MATCHEE_ARR,
322
327
  hash: MATCHEE_HASH
323
328
  ) do
324
- send(
325
- :"#{node.children[1].type}_clause",
326
- node.children[1]
327
- )
329
+ with_declared_locals do
330
+ send(
331
+ :"#{node.children[1].type}_clause",
332
+ node.children[1]
333
+ )
334
+ end
328
335
  end
329
336
 
330
337
  node.updated(
@@ -395,13 +402,15 @@ module RubyNext
395
402
  def build_when_clause(clause)
396
403
  predicates.reset!
397
404
  [
398
- with_guard(
399
- send(
400
- :"#{clause.children[0].type}_clause",
401
- clause.children[0]
402
- ),
403
- clause.children[1] # guard
404
- ),
405
+ with_declared_locals do
406
+ with_guard(
407
+ send(
408
+ :"#{clause.children[0].type}_clause",
409
+ clause.children[0]
410
+ ),
411
+ clause.children[1] # guard
412
+ )
413
+ end,
405
414
  process(clause.children[2] || s(:nil)) # expression
406
415
  ].then do |children|
407
416
  s(:when, *children)
@@ -442,7 +451,7 @@ module RubyNext
442
451
  var = node.children[0]
443
452
  return s(:true) if var == :_
444
453
 
445
- check_match_var_alternation!(var) unless var.is_a?(::Parser::AST::Node)
454
+ check_match_var_alternation!(var)
446
455
 
447
456
  s(:begin,
448
457
  s(:or,
@@ -541,11 +550,10 @@ module RubyNext
541
550
  def array_find(head, *nodes, tail)
542
551
  index = s(:lvar, :__i__)
543
552
 
544
- match_vars = []
545
-
546
553
  head_match =
547
554
  unless head.children.empty?
548
- match_vars << build_var_assignment(head.children[0].children[0])
555
+ # we only need to call this to track the lvar usage
556
+ build_var_assignment(head.children[0].children[0])
549
557
 
550
558
  arr_take = s(:send,
551
559
  s(:lvar, locals[:arr]),
@@ -557,16 +565,19 @@ module RubyNext
557
565
 
558
566
  tail_match =
559
567
  unless tail.children.empty?
560
- match_vars << build_var_assignment(tail.children[0].children[0])
568
+ # we only need to call this to track the lvar usage
569
+ build_var_assignment(tail.children[0].children[0])
561
570
 
562
571
  match_var_clause(tail.children[0], arr_slice(index + nodes.size, -1))
563
572
  end
564
573
 
565
574
  nodes.each do |node|
566
575
  if node.type == :match_var
567
- match_vars << build_var_assignment(node.children[0])
576
+ # we only need to call this to track the lvar usage
577
+ build_var_assignment(node.children[0])
568
578
  elsif node.type == :match_as
569
- match_vars << build_var_assignment(node.children[1].children[0])
579
+ # we only need to call this to track the lvar usage
580
+ build_var_assignment(node.children[1].children[0])
570
581
  end
571
582
  end
572
583
 
@@ -594,19 +605,7 @@ module RubyNext
594
605
  s(:args,
595
606
  s(:arg, :_),
596
607
  s(:arg, :__i__)),
597
- pattern).then do |block|
598
- next block if match_vars.empty?
599
-
600
- # We need to declare match vars outside of `find` block
601
- locals_declare = s(:begin, s(:masgn,
602
- s(:mlhs, *match_vars),
603
- s(:nil)))
604
-
605
- s(:begin,
606
- s(:or,
607
- locals_declare,
608
- block))
609
- end
608
+ pattern)
610
609
  end
611
610
 
612
611
  def array_match_rest(index, node, *tail)
@@ -649,6 +648,14 @@ module RubyNext
649
648
  end
650
649
  end
651
650
 
651
+ def find_pattern_array_element(node, index)
652
+ element = arr_item_at(index)
653
+ locals.with(arr: locals[:arr, index]) do
654
+ predicates.push :"i#{index}"
655
+ find_pattern_clause(node, element).tap { predicates.pop }
656
+ end
657
+ end
658
+
652
659
  def hash_pattern_array_element(node, index)
653
660
  element = arr_item_at(index)
654
661
  locals.with(hash: locals[:arr, index]) do
@@ -829,6 +836,15 @@ module RubyNext
829
836
  end
830
837
  end
831
838
 
839
+ def find_pattern_hash_element(node, key)
840
+ element = hash_value_at(key)
841
+ key_index = deconstructed_key(key)
842
+ locals.with(arr: locals[:hash, key_index]) do
843
+ predicates.push :"k#{key_index}"
844
+ find_pattern_clause(node, element).tap { predicates.pop }
845
+ end
846
+ end
847
+
832
848
  def hash_element(head, *tail)
833
849
  send("#{head.type}_hash_element", head).then do |node|
834
850
  next node if tail.empty?
@@ -948,6 +964,24 @@ module RubyNext
948
964
  end
949
965
  end
950
966
 
967
+ def with_declared_locals
968
+ lvars.clear
969
+ node = yield
970
+
971
+ return node if lvars.empty?
972
+
973
+ # We need to declare match lvars outside of the outer `find` block,
974
+ # so we do that for that whole pattern
975
+ locals_declare = s(:begin, s(:masgn,
976
+ s(:mlhs, *lvars.uniq.map { |_1| s(:lvasgn, _1) }),
977
+ s(:nil)))
978
+
979
+ s(:begin,
980
+ s(:or,
981
+ locals_declare,
982
+ node))
983
+ end
984
+
951
985
  def no_matching_pattern
952
986
  raise_error(
953
987
  :NoMatchingPatternError,
@@ -982,13 +1016,17 @@ module RubyNext
982
1016
 
983
1017
  private
984
1018
 
985
- attr_reader :deconstructed_keys, :predicates
1019
+ attr_reader :deconstructed_keys, :predicates, :lvars
986
1020
 
987
1021
  # Raise SyntaxError if match-var is used within alternation
988
1022
  # https://github.com/ruby/ruby/blob/672213ef1ca2b71312084057e27580b340438796/compile.c#L5900
989
1023
  def check_match_var_alternation!(name)
990
1024
  return unless locals.key?(ALTERNATION_MARKER)
991
1025
 
1026
+ if name.is_a?(::Parser::AST::Node)
1027
+ raise ::SyntaxError, "illegal variable in alternative pattern (#{name.children.first})"
1028
+ end
1029
+
992
1030
  return if name.start_with?("_")
993
1031
 
994
1032
  raise ::SyntaxError, "illegal variable in alternative pattern (#{name})"
@@ -1008,7 +1046,10 @@ module RubyNext
1008
1046
 
1009
1047
  # Value could be omitted for mass assignment
1010
1048
  def build_var_assignment(var, value = nil)
1011
- return s(:lvasgn, *[var, value].compact) unless var.is_a?(::Parser::AST::Node)
1049
+ unless var.is_a?(::Parser::AST::Node)
1050
+ lvars << var
1051
+ return s(:lvasgn, *[var, value].compact)
1052
+ end
1012
1053
 
1013
1054
  asign_type = :"#{var.type.to_s[0]}vasgn"
1014
1055