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 +4 -4
- data/Gemfile.lock +1 -1
- data/VERSION +1 -1
- data/lib/code/format.rb +7 -1
- data/lib/code/node/while.rb +21 -0
- data/lib/code/object/dictionary.rb +45 -1
- data/lib/code/object/html.rb +48 -9
- data/lib/code/object/integer.rb +4 -0
- data/lib/code/object/list.rb +34 -0
- data/lib/code/object/range.rb +20 -0
- data/lib/code/parser.rb +16 -2
- data/spec/code_spec.rb +76 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2495002bb8e1d284386f2a90ff600370cfe0490a356688426682ec106727fbb3
|
|
4
|
+
data.tar.gz: e8dffdf7d8d0c0e62a091d2a7d305eae48dc74d024aa26c5a8dc393763147f13
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 55ceb13028c588110d3adec5539995ddd1f2dc4fd7173fd067a8e009a8093610adb150de78be46dfc57e605dbad0f03dd89e5693820be31c6d61c3440fb129ea
|
|
7
|
+
data.tar.gz: 6ae82061c1a129f1607eb348e18917e75c7d23accf7dca589da00ed3ae34eccf76af79826e430f5267b4a2011ce7c9df8a1709069f95f660c8dff22d16c0c37a
|
data/Gemfile.lock
CHANGED
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.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
|
-
|
|
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 =
|
data/lib/code/node/while.rb
CHANGED
|
@@ -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
|
data/lib/code/object/html.rb
CHANGED
|
@@ -188,10 +188,14 @@ class Code
|
|
|
188
188
|
|
|
189
189
|
if code_function.something?
|
|
190
190
|
code_content =
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
data/lib/code/object/integer.rb
CHANGED
|
@@ -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)
|
data/lib/code/object/list.rb
CHANGED
|
@@ -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
|
data/lib/code/object/range.rb
CHANGED
|
@@ -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
|
-
|
|
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: {
|
|
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
|
-
[
|
|
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
|
|