1 # frozen_string_literal: true
2
3 require "test_helper"
4
5
6 module Umu
7
8 module Test
9
10 module Grammar
11
12 module CoreLanguage
13
14 module Expression
15
16 module Atomic
17
18 module Stream
19 =begin
20 <stream-expression> ::=
21 <cell-stream-expression>
22 | <memo-stream-expression>
23 | <interval-stream-expression>
24 | <stream-comprehension>
25 ;
26 =end
27
28 class CellStreamTest < Minitest::Test
29 =begin
30 <cell-stream-expression> ::=
31 "&[" "]"
32 | "&[" <expression> { "," <expression> } [ "|" <expression> ] "]"
33 ;
34 =end
35
36 def setup
37 @interp = Api.setup_interpreter
38 end
39
40
41 def test_empty_stream
42 interp_1 = Api.eval_decls @interp, "val it = &[]"
43 value = Api.eval_expr interp_1, "it"
44 assert_instance_of VCM::Stream::Entry::Cell, value
45 assert_instance_of VCM::Stream::Cell::Nil, value.cell
46
47 forced_value = Api.eval_expr interp_1, "it.force"
48 assert_instance_of VCU::Option::None, forced_value
49 end
50
51
52 def test_singleton_stream
53 interp_1 = Api.eval_decls @interp, "val it = &[3]"
54 value = Api.eval_expr interp_1, "it"
55 assert_instance_of VCM::Stream::Entry::Cell, value
56 assert_instance_of VCM::Stream::Cell::Cons, value.cell
57
58 interp_2 = Api.eval_decls interp_1, "val it = it.force"
59 forced_value_1 = Api.eval_expr interp_2, "it"
60 assert_instance_of VCU::Option::Some, forced_value_1
61 assert_instance_of VCP::Tuple, forced_value_1.contents
62
63 interp_3 = Api.eval_decls interp_2, "val (hd, tl) = it.contents"
64 head_value = Api.eval_expr interp_3, "hd"
65 tail_value = Api.eval_expr interp_3, "tl"
66
67 assert_instance_of VCAN::Int, head_value
68 assert_equal 3, head_value.val
69 assert_instance_of VCM::Stream::Entry::Cell, tail_value
70 assert_instance_of VCM::Stream::Cell::Nil, tail_value.cell
71 end
72
73
74 def test_some_stream
75 interp_1 = Api.eval_decls @interp, "val it = &[3, 4]"
76 value_1 = Api.eval_expr interp_1, "it"
77 assert_instance_of VCM::Stream::Entry::Cell, value_1
78 assert_instance_of VCM::Stream::Cell::Cons, value_1.cell
79
80 interp_2 = Api.eval_decls interp_1, "val it = it.force"
81 forced_value_1 = Api.eval_expr interp_2, "it"
82 assert_instance_of VCU::Option::Some, forced_value_1
83
84 interp_3 = Api.eval_decls interp_2, "val (hd, tl) = it.contents"
85 head_value_1 = Api.eval_expr interp_3, "hd"
86 tail_value_1 = Api.eval_expr interp_3, "tl"
87
88 assert_instance_of VCAN::Int, head_value_1
89 assert_equal 3, head_value_1.val
90 assert_instance_of VCM::Stream::Entry::Cell, tail_value_1
91 assert_instance_of VCM::Stream::Cell::Cons, tail_value_1.cell
92
93 interp_4 = Api.eval_decls interp_3, "val it = tl.force"
94 forced_value_2 = Api.eval_expr interp_4, "it"
95 assert_instance_of VCU::Option::Some, forced_value_2
96
97 interp_5 = Api.eval_decls interp_4, "val (hd, tl) = it.contents"
98 head_value_2 = Api.eval_expr interp_5, "hd"
99 tail_value_2 = Api.eval_expr interp_5, "tl"
100
101 assert_instance_of VCAN::Int, head_value_2
102 assert_equal 4, head_value_2.val
103 assert_instance_of VCM::Stream::Entry::Cell, tail_value_2
104 assert_instance_of VCM::Stream::Cell::Nil, tail_value_2.cell
105 end
106
107
108 def test_singleton_stream_with_last_expression
109 interp_1 = Api.eval_decls @interp, "val it = &[3 | &[]]"
110 value = Api.eval_expr interp_1, "it"
111 assert_instance_of VCM::Stream::Entry::Cell, value
112 assert_instance_of VCM::Stream::Cell::Cons, value.cell
113
114 forced_value = Api.eval_expr interp_1, "it.force"
115 assert_instance_of VCU::Option::Some, forced_value
116
117 pair_value = forced_value.contents
118 assert_instance_of VCP::Tuple, pair_value
119 assert_equal 2, pair_value.arity
120
121 head_value, tail_value = pair_value.values
122 assert_instance_of VCAN::Int, head_value
123 assert_equal 3, head_value.val
124 assert_instance_of VCM::Stream::Entry::Cell, tail_value
125 assert_instance_of VCM::Stream::Cell::Nil, tail_value.cell
126 end
127
128
129 def test_some_stream_with_last_expression
130 interp_1 = Api.eval_decls @interp, "val it = &[3 | &[4]]"
131 value_1 = Api.eval_expr interp_1, "it"
132 assert_instance_of VCM::Stream::Entry::Cell, value_1
133 assert_instance_of VCM::Stream::Cell::Cons, value_1.cell
134
135 interp_2 = Api.eval_decls interp_1, "val it = it.force"
136 forced_value_1 = Api.eval_expr interp_2, "it"
137 assert_instance_of VCU::Option::Some, forced_value_1
138
139 interp_3 = Api.eval_decls interp_2, "val (hd, tl) = it.contents"
140 head_value_1 = Api.eval_expr interp_3, "hd"
141 tail_value_1 = Api.eval_expr interp_3, "tl"
142
143 assert_instance_of VCAN::Int, head_value_1
144 assert_equal 3, head_value_1.val
145 assert_instance_of VCM::Stream::Entry::Cell, tail_value_1
146 assert_instance_of VCM::Stream::Cell::Cons, tail_value_1.cell
147
148 interp_4 = Api.eval_decls interp_3, "val it = tl.force"
149 forced_value_2 = Api.eval_expr interp_4, "it"
150 assert_instance_of VCU::Option::Some, forced_value_2
151
152 interp_5 = Api.eval_decls interp_4, "val (hd, tl) = it.contents"
153 head_value_2 = Api.eval_expr interp_5, "hd"
154 tail_value_2 = Api.eval_expr interp_5, "tl"
155
156 assert_instance_of VCAN::Int, head_value_2
157 assert_equal 4, head_value_2.val
158 assert_instance_of VCM::Stream::Entry::Cell, tail_value_2
159 assert_instance_of VCM::Stream::Cell::Nil, tail_value_2.cell
160 end
161
162
163 def test_infinite_stream_generator
164 interp_1 = Api.eval_decls @interp, <<-EOS
165 fun rec g = n -> &[ n | g (n + 1) ]
166 EOS
167 interp_2 = Api.eval_decls interp_1, "val it = g 3"
168 value_1 = Api.eval_expr interp_2, "it"
169 assert_instance_of VCM::Stream::Entry::Cell, value_1
170
171 actual_list_value = Api.eval_expr interp_2, "it.take-to-list 4"
172 assert_instance_of VCM::List::Cons, actual_list_value
173
174 [3, 4, 5, 6].zip(actual_list_value).each do |expected, actual_value|
175 assert_instance_of VCAN::Int, actual_value
176 assert_equal expected, actual_value.val
177 end
178 end
179 end
180
181
182
183 class MemoStreamTest < Minitest::Test
184 =begin
185 <memo-stream-expression> ::=
186 "&{" "}"
187 | "&{" <expression> "|" <expression> "}"
188 ;
189 =end
190
191 def setup
192 @interp = Api.setup_interpreter
193 end
194
195
196 def test_empty_stream
197 interp_1 = Api.eval_decls @interp, "val it = &{}"
198 value = Api.eval_expr interp_1, "it"
199 assert_instance_of VCM::Stream::Entry::Memorization, value
200
201 forced_value = Api.eval_expr interp_1, "it.force"
202 assert_instance_of VCU::Option::None, forced_value
203 end
204
205
206 def test_singleton_stream
207 interp_1 = Api.eval_decls @interp, "val it = &{3 | &{}}"
208 value = Api.eval_expr interp_1, "it"
209 assert_instance_of VCM::Stream::Entry::Memorization, value
210
211 interp_2 = Api.eval_decls interp_1, "val it = it.force"
212 forced_value_1 = Api.eval_expr interp_2, "it"
213 assert_instance_of VCU::Option::Some, forced_value_1
214
215 interp_3 = Api.eval_decls interp_2, "val (hd, tl) = it.contents"
216 head_value = Api.eval_expr interp_3, "hd"
217 tail_value = Api.eval_expr interp_3, "tl"
218
219 assert_instance_of VCAN::Int, head_value
220 assert_equal 3, head_value.val
221 assert_instance_of VCM::Stream::Entry::Memorization, tail_value
222
223 forced_value_2 = Api.eval_expr interp_3, "tl.force"
224 assert_instance_of VCU::Option::None, forced_value_2
225 end
226
227
228 def test_some_stream_with
229 interp_1 = Api.eval_decls @interp, "val it = &{3 | &{4 | &{}}}"
230 value_1 = Api.eval_expr interp_1, "it"
231 assert_instance_of VCM::Stream::Entry::Memorization, value_1
232
233 interp_2 = Api.eval_decls interp_1, "val it = it.force"
234 forced_value_1 = Api.eval_expr interp_2, "it"
235 assert_instance_of VCU::Option::Some, forced_value_1
236
237 interp_3 = Api.eval_decls interp_2, "val (hd, tl) = it.contents"
238 head_value_1 = Api.eval_expr interp_3, "hd"
239 tail_value_1 = Api.eval_expr interp_3, "tl"
240
241 assert_instance_of VCAN::Int, head_value_1
242 assert_equal 3, head_value_1.val
243 assert_instance_of VCM::Stream::Entry::Memorization, tail_value_1
244
245 interp_4 = Api.eval_decls interp_3, "val it = tl.force"
246 forced_value_2 = Api.eval_expr interp_4, "it"
247 assert_instance_of VCU::Option::Some, forced_value_2
248
249 interp_5 = Api.eval_decls interp_4, "val (hd, tl) = it.contents"
250 head_value_2 = Api.eval_expr interp_5, "hd"
251 tail_value_2 = Api.eval_expr interp_5, "tl"
252
253 assert_instance_of VCAN::Int, head_value_2
254 assert_equal 4, head_value_2.val
255 assert_instance_of VCM::Stream::Entry::Memorization, tail_value_2
256
257 forced_value_3 = Api.eval_expr interp_5, "tl.force"
258 assert_instance_of VCU::Option::None, forced_value_3
259 end
260
261
262 def test_infinite_stream_generator
263 interp_1 = Api.eval_decls @interp, <<-EOS
264 fun rec g = n -> &{ n | g (n + 1) }
265 EOS
266 interp_2 = Api.eval_decls interp_1, "val it = g 3"
267 value_1 = Api.eval_expr interp_2, "it"
268 assert_instance_of VCM::Stream::Entry::Memorization, value_1
269
270 actual_list_value = Api.eval_expr interp_2, "it.take-to-list 4"
271 assert_instance_of VCM::List::Cons, actual_list_value
272
273 [3, 4, 5, 6].zip(actual_list_value).each do |expected, actual_value|
274 assert_instance_of VCAN::Int, actual_value
275 assert_equal expected, actual_value.val
276 end
277 end
278 end
279
280
281
282 class IntervalStreamTest < Minitest::Test
283 =begin
284 <list-interval> ::=
285 "[" <expression> { "," <expression> } ".." [ <expression> ] "]" ;
286 =end
287
288 def setup
289 @interp = Api.setup_interpreter
290 end
291
292
293 def test_finite_interval
294 value = Api.eval_expr @interp, "&[3 .. 7]"
295 assert_instance_of VCM::Stream::Entry::Interval, value
296 assert_instance_of VCAN::Int, value.current_value
297 assert_equal 3, value.current_value.val
298 assert_instance_of VCAN::Int, value.step_value
299 assert_equal 1, value.step_value.val
300 assert_instance_of VCAN::Int, value.opt_stop_value
301 assert_equal 7, value.opt_stop_value.val
302
303 list_value = Api.eval_expr @interp, "&[3 .. 7].to-list"
304 assert_instance_of VCM::List::Cons, list_value
305
306 expected_list = (3 .. 7).to_a
307 assert_equal expected_list.count, list_value.count
308
309 expected_list.zip(list_value).each do |expected, actual_value|
310 assert_instance_of VCAN::Int, actual_value
311 assert_equal expected, actual_value.val
312 end
313 end
314
315
316 def test_finite_interval_with_second_expression
317 value = Api.eval_expr @interp, "&[3, 5 .. 10]"
318 assert_instance_of VCM::Stream::Entry::Interval, value
319 assert_instance_of VCAN::Int, value.current_value
320 assert_equal 3, value.current_value.val
321 assert_instance_of VCAN::Int, value.step_value
322 assert_equal 2, value.step_value.val
323 assert_instance_of VCAN::Int, value.opt_stop_value
324 assert_equal 10, value.opt_stop_value.val
325
326 list_value = Api.eval_expr @interp, "[3, 5 .. 10].to-list"
327 assert_instance_of VCM::List::Cons, list_value
328
329 expected_list = [3, 5, 7, 9]
330 assert_equal expected_list.count, list_value.count
331
332 expected_list.zip(list_value).each do |expected, actual_value|
333 assert_instance_of VCAN::Int, actual_value
334 assert_equal expected, actual_value.val
335 end
336 end
337
338
339 def test_infinite_interval
340 value = Api.eval_expr @interp, "&[3 ..]"
341 assert_instance_of VCM::Stream::Entry::Interval, value
342 assert_instance_of VCAN::Int, value.current_value
343 assert_equal 3, value.current_value.val
344 assert_instance_of VCAN::Int, value.step_value
345 assert_equal 1, value.step_value.val
346 assert_nil value.opt_stop_value
347
348 list_value = Api.eval_expr @interp, "&[3 ..].take-to-list 5"
349 assert_instance_of VCM::List::Cons, list_value
350
351 expected_list = (3 .. 7).to_a
352 assert_equal expected_list.count, list_value.count
353
354 expected_list.zip(list_value).each do |expected, actual_value|
355 assert_instance_of VCAN::Int, actual_value
356 assert_equal expected, actual_value.val
357 end
358 end
359
360
361 def test_infinite_interval_with_second_expression
362 value = Api.eval_expr @interp, "&[3, 5 ..]"
363 assert_instance_of VCM::Stream::Entry::Interval, value
364 assert_instance_of VCAN::Int, value.current_value
365 assert_equal 3, value.current_value.val
366 assert_instance_of VCAN::Int, value.step_value
367 assert_equal 2, value.step_value.val
368 assert_nil value.opt_stop_value
369
370 list_value = Api.eval_expr @interp, "&[3, 5 ..].take-to-list 4"
371 assert_instance_of VCM::List::Cons, list_value
372
373 expected_list = [3, 5, 7, 9]
374 assert_equal expected_list.count, list_value.count
375
376 expected_list.zip(list_value).each do |expected, actual_value|
377 assert_instance_of VCAN::Int, actual_value
378 assert_equal expected, actual_value.val
379 end
380 end
381 end
382
383
384
385 class StreamComprehensionTest < Minitest::Test
386 =begin
387 <stream-comprehension> ::=
388 | "&[" "|" <expression> { "," <expression> } "|"
389 { <qualifier> }
390 "]"
391 | "&[" "|" <named-field> <<named-field> { <named-field> } "|"
392 { <qualifier> }
393 "]"
394 ;
395
396
397 /* <qualifier> ::= ... ; See ListComprehensionTest */
398
399 /* <named-field> ::= ... ; See NamedTupleTest */
400 =end
401
402 def setup
403 @interp = Api.setup_interpreter
404 end
405
406
407 def test_singleton_comprehension
408 interp_1 = Api.eval_decls @interp, "val it = &[|3|]"
409 value = Api.eval_expr interp_1, "it"
410 assert_instance_of VCM::Stream::Entry::Cell, value
411 assert_instance_of VCM::Stream::Cell::Cons, value.cell
412
413 interp_2 = Api.eval_decls interp_1, "val it = it.force"
414 forced_value_1 = Api.eval_expr interp_2, "it"
415 assert_instance_of VCU::Option::Some, forced_value_1
416
417 interp_3 = Api.eval_decls interp_2, "val (hd, tl) = it.contents"
418 head_value = Api.eval_expr interp_3, "hd"
419 tail_value = Api.eval_expr interp_3, "tl"
420
421 assert_instance_of VCAN::Int, head_value
422 assert_equal 3, head_value.val
423 assert_instance_of VCM::Stream::Entry::Cell, tail_value
424 assert_instance_of VCM::Stream::Cell::Nil, tail_value.cell
425 end
426
427
428 def test_comprehension_with_generator
429 list_value = Api.eval_expr @interp, <<-EOS
430 &[|x| val x <- &[3..]].take-to-list 4
431 EOS
432 assert_instance_of VCM::List::Cons, list_value
433
434 expected_list = [3, 4, 5, 6]
435 assert_equal expected_list.count, list_value.count
436
437 expected_list.zip(list_value).each do |expected, actual_value|
438 assert_instance_of VCAN::Int, actual_value
439 assert_equal expected, actual_value.val
440 end
441 end
442
443
444 def test_comprehension_with_guard
445 list_value = Api.eval_expr @interp, <<-EOS
446 &[|x| val x <- &[1..] if odd? x].take-to-list 3
447 EOS
448 assert_instance_of VCM::List::Cons, list_value
449
450 expected_list = [1, 3, 5]
451 assert_equal expected_list.count, list_value.count
452
453 expected_list.zip(list_value).each do |expected, actual_value|
454 assert_instance_of VCAN::Int, actual_value
455 assert_equal expected, actual_value.val
456 end
457 end
458
459
460 def test_comprehension_returned_tuple
461 list_value = Api.eval_expr @interp, <<-EOS
462 &[|i, n|
463 val i <- &[1 ..]
464 val n <- [@Apple, @Banana]
465 ].take-to-list 6
466 EOS
467 assert_instance_of VCM::List::Cons, list_value
468
469 expected_list = [
470 [1, :Apple], [1, :Banana],
471 [2, :Apple], [2, :Banana],
472 [3, :Apple], [3, :Banana]
473 ]
474 assert_equal expected_list.count, list_value.count
475
476 expected_list.zip(list_value).each do |expected, actual_value|
477 assert_instance_of VCP::Tuple, actual_value
478 assert_equal 2, actual_value.arity
479
480 assert_instance_of VCAN::Int, actual_value.values[0]
481 assert_equal expected[0], actual_value.values[0].val
482
483 assert_instance_of VCA::Symbol, actual_value.values[1]
484 assert_equal expected[1], actual_value.values[1].val
485 end
486 end
487
488
489 def test_comprehension_returned_named_tuple
490 list_value = Api.eval_expr @interp, <<-EOS
491 &[|index:i name:n|
492 val i <- &[1 ..]
493 val n <- [@Apple, @Banana]
494 ].take-to-list 6
495 EOS
496 assert_instance_of VCM::List::Cons, list_value
497
498 expected_list = [
499 [1, :Apple], [1, :Banana],
500 [2, :Apple], [2, :Banana],
501 [3, :Apple], [3, :Banana]
502 ]
503 assert_equal expected_list.count, list_value.count
504
505 expected_list.zip(list_value).each do |expected, actual_value|
506 assert_instance_of VCP::Named, actual_value
507 assert_equal 2, actual_value.arity
508
509 assert_instance_of VCAN::Int, actual_value.values[0]
510 assert_equal expected[0], actual_value.values[0].val
511
512 assert_instance_of VCA::Symbol, actual_value.values[1]
513 assert_equal expected[1], actual_value.values[1].val
514 end
515 end
516 end
517
518 end # Umu::Test::Grammar::CoreLanguage::Expression::Atomic::SquareBracket
519
520 end # Umu::Test::Grammar::CoreLanguage::Expression::Atomic
521
522 end # Umu::Test::Grammar::CoreLanguage::Expression
523
524 end # Umu::Test::Grammar::CoreLanguage
525
526 end # Umu::Test::Grammar
527
528 end # Umu::Test
529
530 end # Umu