code-ruby 3.1.1 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4fb3de0080323ce38f0bc61db99084820616f9b437d94fbf973a4a0736da7a0b
4
- data.tar.gz: 476a64d5bcd78add94f15f25c3d1d086c3263aa66dd4af73443e8ad5e126fc9e
3
+ metadata.gz: 2495002bb8e1d284386f2a90ff600370cfe0490a356688426682ec106727fbb3
4
+ data.tar.gz: e8dffdf7d8d0c0e62a091d2a7d305eae48dc74d024aa26c5a8dc393763147f13
5
5
  SHA512:
6
- metadata.gz: 9851fd43383c19e34984f2124980f788beb59b22e2fd6cd5871a4e3107f62b908770c0b1575b58e1f84cefef574740877f9de9d18bb41ac22eaac531a85136bb
7
- data.tar.gz: b620dc0c1eb65e83fe5d8ade6047fc712a1149f258a1275fc46163f4852a7efd2e5107fc979396daaa95672bb2216c43b3796176abf27d6c0f7bd35c9fba1cf4
6
+ metadata.gz: 55ceb13028c588110d3adec5539995ddd1f2dc4fd7173fd067a8e009a8093610adb150de78be46dfc57e605dbad0f03dd89e5693820be31c6d61c3440fb129ea
7
+ data.tar.gz: 6ae82061c1a129f1607eb348e18917e75c7d23accf7dca589da00ed3ae34eccf76af79826e430f5267b4a2011ce7c9df8a1709069f95f660c8dff22d16c0c37a
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- code-ruby (3.1.1)
4
+ code-ruby (3.1.2)
5
5
  activesupport
6
6
  base64
7
7
  bigdecimal
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.1
1
+ 3.1.2
data/lib/code/format.rb CHANGED
@@ -706,7 +706,13 @@ class Code
706
706
 
707
707
  if operator == "loop"
708
708
  body = format_code(while_statement[:body], indent: indent + 1)
709
- return "#{INDENT * indent}loop {\n#{body}\n#{INDENT * indent}}"
709
+ parameters =
710
+ Array(while_statement[:parameters]).map do |parameter|
711
+ format_parameter(parameter, indent: indent)
712
+ end
713
+ header = parameters.empty? ? "loop {" : "loop { |#{parameters.join(", ")}|"
714
+
715
+ return "#{INDENT * indent}#{header}\n#{body}\n#{INDENT * indent}}"
710
716
  end
711
717
 
712
718
  statement =
@@ -14,6 +14,8 @@ class Code
14
14
  @statement = Statement.new(parsed.delete(:statement)) if parsed.key?(
15
15
  :statement
16
16
  )
17
+ @parameters = parsed.delete(:parameters) { [] }.presence || []
18
+ @parameters.map! { |parameter| FunctionParameter.new(parameter) }
17
19
  @body = Code.new(parsed.delete(:body).presence)
18
20
  end
19
21
 
@@ -53,11 +55,15 @@ class Code
53
55
 
54
56
  def evaluate_infinite_loop(**args)
55
57
  last = Object::Nothing.new
58
+ index = 0
56
59
 
57
60
  loop do
61
+ bind_loop_parameters(index, **args)
58
62
  last = @body&.evaluate(**args) || Object::Nothing.new
63
+ index += 1
59
64
  rescue Error::Next, Error::Continue => e
60
65
  last = e.code_value
66
+ index += 1
61
67
  next
62
68
  rescue Error::Retry
63
69
  retry
@@ -74,6 +80,21 @@ class Code
74
80
 
75
81
  condition_truthy ? condition : !condition
76
82
  end
83
+
84
+ def bind_loop_parameters(index, **args)
85
+ return if @parameters.blank?
86
+
87
+ @parameters.each.with_index do |parameter, parameter_index|
88
+ value =
89
+ if parameter_index.zero?
90
+ Object::Integer.new(index)
91
+ else
92
+ Object::Nothing.new
93
+ end
94
+
95
+ args.fetch(:context).code_set(parameter.name, value)
96
+ end
97
+ end
77
98
  end
78
99
  end
79
100
  end
@@ -576,9 +576,13 @@ class Code
576
576
  )
577
577
  .truthy?
578
578
  .tap { index += 1 }
579
+ rescue Error::Next => e
580
+ e.code_value.truthy?.tap { index += 1 }
579
581
  end
580
582
  )
581
583
  end
584
+ rescue Error::Break => e
585
+ e.code_value
582
586
  end
583
587
 
584
588
  def code_clear
@@ -605,6 +609,8 @@ class Code
605
609
  e.code_value.truthy?
606
610
  end
607
611
  )
612
+ rescue Error::Break => e
613
+ e.code_value
608
614
  end
609
615
 
610
616
  def code_compact!(argument = nil, **globals)
@@ -626,6 +632,8 @@ class Code
626
632
  end
627
633
 
628
634
  self
635
+ rescue Error::Break => e
636
+ e.code_value
629
637
  end
630
638
 
631
639
  def code_delete(*arguments, index: 0, **globals)
@@ -650,6 +658,8 @@ class Code
650
658
  **globals
651
659
  )
652
660
  end
661
+ rescue Error::Next => e
662
+ e.code_value
653
663
  end
654
664
  else
655
665
  Dictionary.new(
@@ -676,6 +686,8 @@ class Code
676
686
  .to_h
677
687
  )
678
688
  end
689
+ rescue Error::Break => e
690
+ e.code_value
679
691
  end
680
692
 
681
693
  def code_delete_if(argument, **globals)
@@ -690,10 +702,14 @@ class Code
690
702
  List.new([code_key, code_value, Integer.new(index), self]),
691
703
  **globals
692
704
  ).truthy?
705
+ rescue Error::Next => e
706
+ e.code_value.truthy?
693
707
  end
694
708
  end
695
709
 
696
710
  self
711
+ rescue Error::Break => e
712
+ e.code_value
697
713
  end
698
714
 
699
715
  def code_delete_unless(argument, **globals)
@@ -707,10 +723,14 @@ class Code
707
723
  arguments: List.new([key, value, Integer.new(index), self]),
708
724
  **globals
709
725
  ).falsy?
726
+ rescue Error::Next => e
727
+ e.code_value.falsy?
710
728
  end
711
729
  end
712
730
 
713
731
  self
732
+ rescue Error::Break => e
733
+ e.code_value
714
734
  end
715
735
 
716
736
  def code_dig(*arguments)
@@ -735,9 +755,13 @@ class Code
735
755
  arguments: List.new([key, value, Integer.new(index), self]),
736
756
  **globals
737
757
  )
758
+ rescue Error::Next => e
759
+ e.code_value
738
760
  end
739
761
 
740
762
  self
763
+ rescue Error::Break => e
764
+ e.code_value
741
765
  end
742
766
 
743
767
  def code_empty?
@@ -771,6 +795,8 @@ class Code
771
795
  **globals
772
796
  )
773
797
  end
798
+ rescue Error::Next => e
799
+ e.code_value
774
800
  end
775
801
  else
776
802
  Dictionary.new(
@@ -797,6 +823,8 @@ class Code
797
823
  .to_h
798
824
  )
799
825
  end
826
+ rescue Error::Break => e
827
+ e.code_value
800
828
  end
801
829
 
802
830
  def code_fetch_values(*arguments)
@@ -841,10 +869,14 @@ class Code
841
869
  arguments: List.new([key, value, Integer.new(index), self]),
842
870
  **globals
843
871
  ).truthy?
872
+ rescue Error::Next => e
873
+ e.code_value.truthy?
844
874
  end
845
875
  end
846
876
 
847
877
  self
878
+ rescue Error::Break => e
879
+ e.code_value
848
880
  end
849
881
 
850
882
  def code_keep_unless(argument, **globals)
@@ -864,6 +896,8 @@ class Code
864
896
  end
865
897
 
866
898
  self
899
+ rescue Error::Break => e
900
+ e.code_value
867
901
  end
868
902
 
869
903
  def code_key(value, function = nil, **globals)
@@ -876,7 +910,7 @@ class Code
876
910
  raw.key(code_value) ||
877
911
  function.call(arguments: List.new([code_value, self]), **globals)
878
912
  end
879
- rescue Error::Next => e
913
+ rescue Error::Next, Error::Break => e
880
914
  e.code_value
881
915
  end
882
916
 
@@ -921,6 +955,8 @@ class Code
921
955
  e.code_value.tap { index += 1 }
922
956
  end
923
957
  )
958
+ rescue Error::Break => e
959
+ e.code_value
924
960
  end
925
961
 
926
962
  def code_merge!(*arguments, **globals)
@@ -960,6 +996,8 @@ class Code
960
996
  end
961
997
 
962
998
  self
999
+ rescue Error::Break => e
1000
+ e.code_value
963
1001
  end
964
1002
 
965
1003
  def code_select!(argument, **globals)
@@ -980,6 +1018,8 @@ class Code
980
1018
  end
981
1019
 
982
1020
  self
1021
+ rescue Error::Break => e
1022
+ e.code_value
983
1023
  end
984
1024
 
985
1025
  def code_select(argument, **globals)
@@ -1002,6 +1042,8 @@ class Code
1002
1042
  end
1003
1043
  )
1004
1044
  end
1045
+ rescue Error::Break => e
1046
+ e.code_value
1005
1047
  end
1006
1048
 
1007
1049
  def code_set(key, value)
@@ -1045,6 +1087,8 @@ class Code
1045
1087
  end
1046
1088
  .to_h
1047
1089
  )
1090
+ rescue Error::Break => e
1091
+ e.code_value
1048
1092
  end
1049
1093
 
1050
1094
  def code_values
@@ -188,10 +188,14 @@ class Code
188
188
 
189
189
  if code_function.something?
190
190
  code_content =
191
- code_function.call(
192
- arguments: List.new([code_name, code_attributes]),
193
- **globals
194
- )
191
+ begin
192
+ code_function.call(
193
+ arguments: List.new([code_name, code_attributes]),
194
+ **globals
195
+ )
196
+ rescue Error::Next => e
197
+ e.code_value
198
+ end
195
199
 
196
200
  content =
197
201
  if code_content.is_an?(Html)
@@ -206,33 +210,52 @@ class Code
206
210
  fragment.add_child(node)
207
211
 
208
212
  Html.new(fragment)
213
+ rescue Error::Break => e
214
+ e.code_value
209
215
  end
210
216
 
211
217
  def self.code_escape(value_or_function = nil, **globals)
212
218
  code_value =
213
219
  if value_or_function.is_a?(Function)
214
- value_or_function.to_code.call(**globals)
220
+ begin
221
+ value_or_function.to_code.call(**globals)
222
+ rescue Error::Next => e
223
+ e.code_value
224
+ end
215
225
  else
216
226
  value_or_function.to_code
217
227
  end
218
228
 
219
229
  String.new(CGI.escapeHTML(code_value.to_s))
230
+ rescue Error::Break => e
231
+ e.code_value
220
232
  end
221
233
 
222
234
  def self.code_unescape(value_or_function = nil, **globals)
223
235
  code_value =
224
236
  if value_or_function.is_a?(Function)
225
- value_or_function.to_code.call(**globals)
237
+ begin
238
+ value_or_function.to_code.call(**globals)
239
+ rescue Error::Next => e
240
+ e.code_value
241
+ end
226
242
  else
227
243
  value_or_function.to_code
228
244
  end
229
245
 
230
246
  String.new(Nokogiri::HTML.fragment(code_value.to_s).text)
247
+ rescue Error::Break => e
248
+ e.code_value
231
249
  end
232
250
 
233
251
  def self.code_join(first = nil, second = nil, **globals)
234
252
  if second.is_a?(Function)
235
- code_contents = second.to_code.call(**globals)
253
+ code_contents =
254
+ begin
255
+ second.to_code.call(**globals)
256
+ rescue Error::Next => e
257
+ e.code_value
258
+ end
236
259
  code_separator = first.to_code
237
260
  else
238
261
  code_contents = first.to_code
@@ -264,12 +287,18 @@ class Code
264
287
  end
265
288
 
266
289
  Html.new(fragment)
290
+ rescue Error::Break => e
291
+ e.code_value
267
292
  end
268
293
 
269
294
  def self.code_text(value_or_function = nil, **globals)
270
295
  code_value =
271
296
  if value_or_function.is_a?(Function)
272
- value_or_function.to_code.call(**globals)
297
+ begin
298
+ value_or_function.to_code.call(**globals)
299
+ rescue Error::Next => e
300
+ e.code_value
301
+ end
273
302
  else
274
303
  value_or_function.to_code
275
304
  end
@@ -280,12 +309,18 @@ class Code
280
309
  )
281
310
 
282
311
  Html.new(fragment)
312
+ rescue Error::Break => e
313
+ e.code_value
283
314
  end
284
315
 
285
316
  def self.code_raw(value_or_function = nil, **globals)
286
317
  code_value =
287
318
  if value_or_function.is_a?(Function)
288
- value_or_function.to_code.call(**globals)
319
+ begin
320
+ value_or_function.to_code.call(**globals)
321
+ rescue Error::Next => e
322
+ e.code_value
323
+ end
289
324
  else
290
325
  value_or_function.to_code
291
326
  end
@@ -295,6 +330,8 @@ class Code
295
330
  else
296
331
  Html.new(Nokogiri::HTML::DocumentFragment.parse(code_value.to_s))
297
332
  end
333
+ rescue Error::Break => e
334
+ e.code_value
298
335
  end
299
336
 
300
337
  def call(**args)
@@ -352,6 +389,8 @@ class Code
352
389
  e.code_value
353
390
  end
354
391
  )
392
+ rescue Error::Break => e
393
+ e.code_value
355
394
  end
356
395
 
357
396
  def to_s
@@ -584,9 +584,13 @@ class Code
584
584
  arguments: List.new([Integer.new(element), self]),
585
585
  **globals
586
586
  )
587
+ rescue Error::Next => e
588
+ e.code_value
587
589
  end
588
590
 
589
591
  self
592
+ rescue Error::Break => e
593
+ e.code_value
590
594
  end
591
595
 
592
596
  def code_truncate(n = nil)
@@ -870,6 +870,8 @@ class Code
870
870
  e.code_value.tap { index += 1 }
871
871
  end
872
872
  )
873
+ rescue Error::Break => e
874
+ e.code_value
873
875
  end
874
876
 
875
877
  def code_append(other)
@@ -909,6 +911,8 @@ class Code
909
911
  rescue Error::Next => e
910
912
  e.code_value
911
913
  end || Nothing.new
914
+ rescue Error::Break => e
915
+ e.code_value
912
916
  end
913
917
 
914
918
  def code_each(argument = nil, **globals)
@@ -928,6 +932,8 @@ class Code
928
932
  end
929
933
 
930
934
  self
935
+ rescue Error::Break => e
936
+ e.code_value
931
937
  end
932
938
 
933
939
  def code_first(value = nil)
@@ -1424,6 +1430,8 @@ class Code
1424
1430
  e.code_value
1425
1431
  end
1426
1432
  )
1433
+ rescue Error::Break => e
1434
+ e.code_value
1427
1435
  end
1428
1436
 
1429
1437
  def code_map!(argument = nil, **globals)
@@ -1445,6 +1453,8 @@ class Code
1445
1453
  end
1446
1454
 
1447
1455
  self
1456
+ rescue Error::Break => e
1457
+ e.code_value
1448
1458
  end
1449
1459
 
1450
1460
  def code_max(argument = nil, **globals)
@@ -1462,6 +1472,8 @@ class Code
1462
1472
  rescue Error::Next => e
1463
1473
  e.code_value
1464
1474
  end || Nothing.new
1475
+ rescue Error::Break => e
1476
+ e.code_value
1465
1477
  end
1466
1478
 
1467
1479
  def code_none?(argument = nil, **globals)
@@ -1488,6 +1500,8 @@ class Code
1488
1500
  e.code_value.truthy?.tap { index += 1 }
1489
1501
  end
1490
1502
  )
1503
+ rescue Error::Break => e
1504
+ e.code_value
1491
1505
  end
1492
1506
 
1493
1507
  def code_all?(argument = nil, **globals)
@@ -1514,6 +1528,8 @@ class Code
1514
1528
  e.code_value.truthy?.tap { index += 1 }
1515
1529
  end
1516
1530
  )
1531
+ rescue Error::Break => e
1532
+ e.code_value
1517
1533
  end
1518
1534
 
1519
1535
  def code_reduce(argument = nil, **globals)
@@ -1536,6 +1552,8 @@ class Code
1536
1552
  rescue Error::Next => e
1537
1553
  e.code_value.tap { index += 1 }
1538
1554
  end || Nothing.new
1555
+ rescue Error::Break => e
1556
+ e.code_value
1539
1557
  end
1540
1558
 
1541
1559
  def code_reverse
@@ -1563,6 +1581,8 @@ class Code
1563
1581
  e.code_value.truthy?
1564
1582
  end
1565
1583
  )
1584
+ rescue Error::Break => e
1585
+ e.code_value
1566
1586
  end
1567
1587
 
1568
1588
  def code_compact!(argument = nil, **globals)
@@ -1586,6 +1606,8 @@ class Code
1586
1606
  end
1587
1607
 
1588
1608
  self
1609
+ rescue Error::Break => e
1610
+ e.code_value
1589
1611
  end
1590
1612
 
1591
1613
  def code_select(argument = nil, **globals)
@@ -1607,6 +1629,8 @@ class Code
1607
1629
  e.code_value.truthy?
1608
1630
  end
1609
1631
  )
1632
+ rescue Error::Break => e
1633
+ e.code_value
1610
1634
  end
1611
1635
 
1612
1636
  def code_select!(argument = nil, **globals)
@@ -1628,6 +1652,8 @@ class Code
1628
1652
  end
1629
1653
 
1630
1654
  self
1655
+ rescue Error::Break => e
1656
+ e.code_value
1631
1657
  end
1632
1658
 
1633
1659
  def code_reject(argument = nil, **globals)
@@ -1649,6 +1675,8 @@ class Code
1649
1675
  e.code_value.truthy?
1650
1676
  end
1651
1677
  )
1678
+ rescue Error::Break => e
1679
+ e.code_value
1652
1680
  end
1653
1681
 
1654
1682
  def code_reject!(argument = nil, **globals)
@@ -1670,6 +1698,8 @@ class Code
1670
1698
  end
1671
1699
 
1672
1700
  self
1701
+ rescue Error::Break => e
1702
+ e.code_value
1673
1703
  end
1674
1704
 
1675
1705
  def code_join(separator = nil)
@@ -1695,6 +1725,8 @@ class Code
1695
1725
  e.code_value
1696
1726
  end
1697
1727
  )
1728
+ rescue Error::Break => e
1729
+ e.code_value
1698
1730
  end
1699
1731
 
1700
1732
  def code_size
@@ -1730,6 +1762,8 @@ class Code
1730
1762
  e.code_value.tap { index += 1 }
1731
1763
  end
1732
1764
  )
1765
+ rescue Error::Break => e
1766
+ e.code_value
1733
1767
  end
1734
1768
 
1735
1769
  def code_sum
@@ -90,8 +90,12 @@ class Code
90
90
  )
91
91
  .truthy?
92
92
  .tap { index += 1 }
93
+ rescue Error::Next => e
94
+ e.code_value.truthy?.tap { index += 1 }
93
95
  end
94
96
  )
97
+ rescue Error::Break => e
98
+ e.code_value
95
99
  end
96
100
 
97
101
  def code_any?(argument, **globals)
@@ -108,8 +112,12 @@ class Code
108
112
  )
109
113
  .truthy?
110
114
  .tap { index += 1 }
115
+ rescue Error::Next => e
116
+ e.code_value.truthy?.tap { index += 1 }
111
117
  end
112
118
  )
119
+ rescue Error::Break => e
120
+ e.code_value
113
121
  end
114
122
 
115
123
  def code_each(argument, **globals)
@@ -120,9 +128,13 @@ class Code
120
128
  arguments: List.new([code_element, Integer.new(index), self]),
121
129
  **globals
122
130
  )
131
+ rescue Error::Next => e
132
+ e.code_value
123
133
  end
124
134
 
125
135
  self
136
+ rescue Error::Break => e
137
+ e.code_value
126
138
  end
127
139
 
128
140
  def code_first
@@ -142,8 +154,12 @@ class Code
142
154
  arguments: List.new([code_element, Integer.new(index), self]),
143
155
  **globals
144
156
  )
157
+ rescue Error::Next => e
158
+ e.code_value
145
159
  end
146
160
  )
161
+ rescue Error::Break => e
162
+ e.code_value
147
163
  end
148
164
 
149
165
  def code_select(argument, **globals)
@@ -155,8 +171,12 @@ class Code
155
171
  arguments: List.new([code_element, Integer.new(index), self]),
156
172
  **globals
157
173
  ).truthy?
174
+ rescue Error::Next => e
175
+ e.code_value.truthy?
158
176
  end
159
177
  )
178
+ rescue Error::Break => e
179
+ e.code_value
160
180
  end
161
181
 
162
182
  def exclude_end?
data/lib/code/parser.rb CHANGED
@@ -407,12 +407,26 @@ class Code
407
407
  skip_newlines
408
408
 
409
409
  statement = parse_expression unless operator == "loop"
410
- body = parse_body(%w[end])
410
+
411
+ if operator == "loop" &&
412
+ (match?(:punctuation, "{") || match?(:keyword, "do"))
413
+ block = parse_block(current.value)
414
+ body = block[:body]
415
+ parameters = block[:parameters]
416
+ else
417
+ body = parse_body(%w[end])
418
+ end
419
+
411
420
  skip_newlines
412
421
  advance if match?(:keyword, "end")
413
422
 
414
423
  {
415
- while: { operator: operator, statement: statement, body: body }.compact
424
+ while: {
425
+ operator: operator,
426
+ statement: statement,
427
+ parameters: parameters,
428
+ body: body
429
+ }.compact
416
430
  }
417
431
  end
418
432
 
data/spec/code_spec.rb CHANGED
@@ -13,6 +13,74 @@ RSpec.describe Code do
13
13
  [result, output.string]
14
14
  end
15
15
 
16
+ def control_flow_block_calls
17
+ [
18
+ "[1].each { CONTROL }",
19
+ "[1, 2].any? { CONTROL }",
20
+ "[1].detect { CONTROL }",
21
+ "[1].map { CONTROL }",
22
+ "xs = [1] xs.map! { CONTROL }",
23
+ "[1].max { CONTROL }",
24
+ "[1].none? { CONTROL }",
25
+ "[1].all? { CONTROL }",
26
+ "[1, 2].reduce { |acc, item| CONTROL }",
27
+ "[nothing].compact { CONTROL }",
28
+ "xs = [nothing] xs.compact! { CONTROL }",
29
+ "[1].select { CONTROL }",
30
+ "xs = [1] xs.select! { CONTROL }",
31
+ "[1].reject { CONTROL }",
32
+ "xs = [1] xs.reject! { CONTROL }",
33
+ "[1].sort { CONTROL }",
34
+ "[1].uniq { CONTROL }",
35
+ "(1..1).all? { CONTROL }",
36
+ "(1..1).any? { CONTROL }",
37
+ "(1..1).each { CONTROL }",
38
+ "(1..1).map { CONTROL }",
39
+ "(1..1).select { CONTROL }",
40
+ "{a: 1}.any? { CONTROL }",
41
+ "{a: 1}.compact { CONTROL }",
42
+ "hash = {a: 1} hash.compact! { CONTROL }",
43
+ "{a: 1}.delete(:b) { CONTROL }",
44
+ "hash = {a: 1} hash.delete_if { CONTROL }",
45
+ "hash = {a: 1} hash.delete_unless { CONTROL }",
46
+ "{a: 1}.each { CONTROL }",
47
+ "{a: 1}.fetch(:b) { CONTROL }",
48
+ "hash = {a: 1} hash.keep_if { CONTROL }",
49
+ "hash = {a: 1} hash.keep_unless { CONTROL }",
50
+ "{a: 1}.key(2) { CONTROL }",
51
+ "{a: 1}.merge({a: 2}) { CONTROL }",
52
+ "hash = {a: 1} hash.merge!({a: 2}) { CONTROL }",
53
+ "{a: 1}.select { CONTROL }",
54
+ "hash = {a: 1} hash.select! { CONTROL }",
55
+ "{a: 1}.transform_values { CONTROL }",
56
+ "1.times { CONTROL }",
57
+ "Html.p { CONTROL }",
58
+ "Html.escape { CONTROL }",
59
+ "Html.unescape { CONTROL }",
60
+ "Html.join(Html.br) { CONTROL }",
61
+ "Html.text { CONTROL }",
62
+ "Html.raw { CONTROL }",
63
+ "Html.raw(\"<p>a</p>\").css(\"p\").map { CONTROL }"
64
+ ]
65
+ end
66
+
67
+ %w[return break next continue].each do |control_flow|
68
+ it "continues after #{control_flow} in block methods" do
69
+ aggregate_failures do
70
+ control_flow_block_calls.each do |block_call|
71
+ input = "#{block_call.sub("CONTROL", control_flow)} puts(:end)"
72
+ formatted = format_input(input)
73
+
74
+ _result, output = evaluate_with_output(input)
75
+ _formatted_result, formatted_output = evaluate_with_output(formatted)
76
+
77
+ expect(output).to eq("end\n"), input
78
+ expect(formatted_output).to eq("end\n"), formatted
79
+ end
80
+ end
81
+ end
82
+ end
83
+
16
84
  (
17
85
  [
18
86
  "{ a: 1, b: 2 }.transform_values { |key| key.upcase }",
@@ -352,6 +420,7 @@ RSpec.describe Code do
352
420
  ["[1, 2].map(&:to_string)", '["1", "2"]'],
353
421
  ["[1, 2].map(&:to_string)", '["1", "2"]'],
354
422
  ["[1].each do end", "[1]"],
423
+ ["x = [1].each { break(42) } x", "42"],
355
424
  ["[[true]]", "[[true]]"],
356
425
  ["[]", "[]"],
357
426
  ["\r\n", "nothing"],
@@ -362,6 +431,8 @@ RSpec.describe Code do
362
431
  ],
363
432
  ["a = 0 loop a += 1 break end a", "1"],
364
433
  ["x = loop break(42) end x", "42"],
434
+ ["x = loop { |index| break(index) if index > 3 } x", "4"],
435
+ ["x = loop do |index| break(index) if index > 3 end x", "4"],
365
436
  ["a = 0\nuntil a > 10 a += 1 end a", "11"],
366
437
  ["a = 0\nwhile a < 10 a += 1 end a", "10"],
367
438
  ["a = 1 3.times { a += 1 } a", "4"],
@@ -541,7 +612,11 @@ RSpec.describe Code do
541
612
  end
542
613
  end
543
614
 
544
- [["puts(true)", "true\n"], %w[print(false) false]].each do |input, expected|
615
+ [
616
+ ["puts(true)", "true\n"],
617
+ %w[print(false) false],
618
+ ["[1].each { break } puts(:end)", "end\n"]
619
+ ].each do |input, expected|
545
620
  it "#{input} prints #{expected}" do
546
621
  formatted = format_input(input)
547
622
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Marié