1 # coding: utf-8
2 # frozen_string_literal: true
3
4
5
6 module Umu
7
8 module Value
9
10 module Core
11
12 module Morph
13
14 class Abstract < Object
15 =begin
16 The subclasses of this class must be implemented the following methods:
17 * .meth_make_empty(loc, env, event) -> Morph::Abstract
18 * #meth_cons(loc, env, event, value : VC::Top) -> Morph::Abstract
19 * #meth_dest(loc, env, event) -> VCU::Option::Abstract
20 =end
21
22
23 define_class_method(
24 :meth_make_empty,
25 :empty, [],
26 [], self
27 )
28 def self.meth_make_empty(_loc, _env, _event)
29 # List is default morph
30 VC.make_nil
31 end
32
33
34 define_class_method(
35 :meth_make_cons,
36 :cons, [:'head:tail:'],
37 [VC::Top, self], self
38 )
39 def self.meth_make_cons(loc, env, event, x, xs)
40 ASSERT.kind_of x, VC::Top
41 ASSERT.kind_of xs, VCM::Abstract
42
43 xs.meth_cons loc, env, event, x
44 end
45
46
47 =begin
48 HOW TO USE: unfoldr
49
50 * Same to: [1 .. 5].to-list
51
52 > &List.unfold 1 { x ->
53 * if x <= 5 then Some ([x], x + 1) else NONE
54 * }
55 val it : Cons = [1, 2, 3, 4, 5]
56
57 * Same to: [1, 2, 3].map to-s
58
59 > &List.unfold [1, 2, 3] { xs ->
60 * case xs of {
61 * [x|xs'] -> Some ([x.to-s], xs')
62 * else -> NONE
63 * }
64 * }
65 val it : Cons = ["1", "2", "3"]
66
67 * Same to: [1, 2, 3].select odd?
68
69 > &List.unfold [1, 2, 3] { xs ->
70 * case xs of {
71 * [x|xs'] -> Some (if odd? x then [x] else [], xs')
72 * else -> NONE
73 * }
74 * }
75 val it : Cons = [1, 3]
76
77 * Same to: STDIN.each-line.to-list
78
79 > &List.unfold STDIN { io ->
80 * case io.gets of {
81 * &Some s -> Some ([s], io)
82 * else -> NONE
83 * }
84 * }
85 a
86 b
87 c
88 [Ctrl]+[D]
89 val it : Cons = ["a", "b", "c"]
90 =end
91 define_class_method(
92 :meth_unfold,
93 :unfold, [],
94 [VC::Top, VC::Fun], self
95 )
96 def self.meth_unfold(loc, env, event, x, func)
97 ASSERT.kind_of x, VC::Top
98 ASSERT.kind_of func, VC::Fun
99
100 new_env = env.enter event
101
102 _, result = loop.inject(
103 [x, self.meth_make_empty(loc, new_env, event)]
104 ) { |(x1, yss ), _|
105 value = func.apply x1, [], loc, new_env
106 ASSERT.kind_of value, VC::Top
107
108 VC.validate_option value, 'unfoldl', loc, new_env
109
110 case value
111 when VCU::Option::None
112 break [x1, yss]
113 when VCU::Option::Some
114 tuple = value.contents
115 ys, next_x = VC.validate_pair tuple, "unfoldl", loc, env
116
117 VC.validate_morph ys, 'unfoldl', loc, new_env
118
119 [next_x, yss.meth_append(loc, new_env, event, ys)]
120 else
121 ASSERT.abort "No case"
122 end
123 }
124
125 ASSERT.kind_of result, VC::Top
126 end
127
128
129 def abstract_class
130 VCM::Abstract
131 end
132
133
134 define_instance_method(
135 :meth_cons,
136 :cons, [],
137 [VC::Top], self
138 )
139 def meth_cons(_loc, _env, _event, value)
140 ASSERT.kind_of value, VC::Top
141
142 raise X::InternalSubclassResponsibility
143 end
144
145
146 define_instance_method(
147 :meth_make_empty,
148 :empty, [],
149 [], self
150 )
151 def meth_make_empty(loc, env, event)
152 self.class.meth_make_empty loc, env, event
153 end
154
155
156 define_instance_method(
157 :meth_is_empty,
158 :empty?, [],
159 [], VCA::Bool
160 )
161 def meth_is_empty(_loc, _env, _event)
162 val_opt = self.meth_dest loc, env, event
163
164 VC.validate_option val_opt, 'empty?', loc, env
165
166 VC.make_bool val_opt.none?
167 end
168
169
170 define_instance_method(
171 :meth_is_exists,
172 :exists?, [],
173 [], VCA::Bool
174 )
175 def meth_is_exists(loc, env, event)
176 val_opt = self.meth_dest loc, env, event
177
178 VC.validate_option val_opt, 'exists?', loc, env
179
180 VC.make_bool val_opt.some?
181 end
182
183
184 define_instance_method(
185 :meth_dest!,
186 :dest!, [],
187 [], VCP::Tuple
188 )
189 def meth_dest!(loc, env, event)
190 val_opt = self.meth_dest loc, env, event
191
192 VC.validate_option val_opt, 'dest!', loc, env
193
194 unless val_opt.some?
195 raise X::EmptyError.new loc, env, "dest!: Empty morph"
196 end
197
198 pair = val_opt.contents
199 VC.validate_pair pair, "dest!", loc, env
200
201 ASSERT.kind_of pair, VCP::Tuple
202 end
203
204
205 define_instance_method(
206 :meth_dest,
207 :dest, [],
208 [], VCU::Option::Abstract
209 )
210 def meth_dest(_loc, _env, _event)
211 raise X::InternalSubclassResponsibility
212 end
213
214
215 define_instance_method(
216 :meth_head,
217 :head, [],
218 [], VC::Top
219 )
220 def meth_head(loc, env, event)
221 val_opt = self.meth_dest loc, env, event
222
223 VC.validate_option val_opt, 'head', loc, env
224 unless val_opt.some?
225 raise X::EmptyError.new loc, env, "head: Empty morph"
226 end
227
228 result, _ = VC.validate_pair val_opt.contents, "head", loc, env
229
230 result
231 end
232
233
234 define_instance_method(
235 :meth_tail,
236 :tail, [],
237 [], self
238 )
239 def meth_tail(loc, env, event)
240 val_opt = self.meth_dest loc, env, event
241
242 VC.validate_option val_opt, 'tail', loc, env
243 unless val_opt.some?
244 raise X::EmptyError.new loc, env, "tail: Empty morph"
245 end
246
247 _, result = VC.validate_pair val_opt.contents, "tail", loc, env
248
249 result
250 end
251
252
253 define_instance_method(
254 :meth_to_list,
255 :'to-list', [],
256 [], VCM::List::Abstract
257 )
258 def meth_to_list(loc, env, event)
259 zs = loop.inject(
260 [VC.make_nil, self]
261 ) { |(ys, xs), _|
262 val_of_opt = xs.meth_dest(loc, env, event)
263 case val_of_opt
264 when VCU::Option::None
265 break ys
266 when VCU::Option::Some
267 pair = val_of_opt.contents
268 ASSERT.kind_of pair, VCP::Tuple
269 x, xs1 = pair.values
270
271 [ys.meth_cons(loc, env, event, x), xs1]
272 else
273 ASSERT.abort "No case: ", val_of_opt.inspect
274 end
275 }
276
277 result = zs.meth_reverse(loc, env, event)
278
279 ASSERT.kind_of result, VCM::List::Abstract
280 end
281
282
283 =begin
284 HOW TO USE Morph#susp
285
286 * If not exists 'susp', then ...
287
288 > STDIN.each-line.map { s -> "- " ^ s }.for-each print
289 aaa [Enter]
290 bbb [Enter]
291 ccc [Enter]
292 [Ctrl]+[d]
293 - aaa
294 - bbb
295 - ccc
296 val it : Unit = ()
297 >
298
299 * Use 'susp'
300
301 > STDIN.each-line.susp.map { s -> "- " ^ s }.for-each print
302 aaa [Enter]
303 - aaa
304 bbb [Enter]
305 - bbb
306 ccc [Enter]
307 - ccc
308 [Ctrl]+[d]
309 val it : Unit = ()
310 >
311 =end
312 define_instance_method(
313 :meth_susp,
314 :susp, [],
315 [], VCM::Stream::Entry::Abstract
316 )
317 def meth_susp(loc, env, event)
318 sym_this = :this
319
320 new_env = env.va_extend_value sym_this, self
321
322 expr = ASCE.make_send(
323 loc,
324 ASCE.make_identifier(loc, sym_this),
325 ASCE.make_message(loc, :'%susp')
326 )
327
328 VC.make_suspended_stream(expr, new_env.va_context)
329 end
330
331
332 define_instance_method(
333 :meth_susp_,
334 :'%susp', [],
335 [], VCM::Stream::Entry::Abstract
336 )
337 def meth_susp_(loc, env, event)
338 val_opt = self.meth_dest loc, env, event
339
340 VC.validate_option val_opt, 'susp', loc, env
341
342 result = (
343 if val_opt.none?
344 VC.make_cell_stream_nil env.va_context
345 else
346 sym_x = :'%x'
347 sym_xs = :'%xs'
348
349 x, xs = VC.validate_pair val_opt.contents, 'susp', loc, env
350
351 VC.validate_morph xs, 'susp', loc, env
352 new_env = env.va_extend_values(
353 sym_x => x,
354 sym_xs => xs
355 )
356
357 VC.make_cell_stream_cons(
358 ASCE.make_identifier(loc, sym_x),
359
360 VC.make_expr_stream_entry(
361 ASCE.make_send(
362 loc,
363 ASCE.make_identifier(loc, sym_xs),
364 ASCE.make_message(loc, :susp)
365 ),
366
367 new_env.va_context
368 ),
369
370 new_env.va_context
371 )
372 end
373 )
374
375 ASSERT.kind_of result, VCM::Stream::Entry::Abstract
376 end
377
378
379 def foldr(loc, env, event, init, &block)
380 ASSERT.kind_of init, VC::Top
381 ASSERT.kind_of block, ::Proc
382
383 result = self.foldl(
384 loc, env, event, self.meth_make_empty(loc, env, event)
385 ) { |new_loc, new_env, x, xs|
386
387 xs.meth_cons new_loc, new_env, event, x
388 }.foldl(
389 loc, env, event, init, &block
390 )
391
392 ASSERT.kind_of result, VC::Top
393 end
394
395
396 define_instance_method(
397 :meth_foldr,
398 :foldr, [],
399 [VC::Top, VC::Fun], VC::Top
400 )
401 def meth_foldr(loc, env, event, init, func)
402 ASSERT.kind_of init, VC::Top
403 ASSERT.kind_of func, VC::Fun
404
405 result = self.foldr(
406 loc, env, event, init
407 ) { |new_loc, new_env, x, y|
408
409 func.apply x, [y], new_loc, new_env
410 }
411
412 ASSERT.kind_of result, VC::Top
413 end
414
415
416 def foldl(loc, env, event, init, &block)
417 ASSERT.kind_of init, VC::Top
418 ASSERT.kind_of block, ::Proc
419
420 mut_y = init.dup
421 mut_xs = self.dup
422 loop do
423 val_opt = mut_xs.meth_dest loc, env, event
424 break if val_opt.none?
425
426 pair = val_opt.contents
427 x, mut_xs = VC.validate_pair pair, "foldl", loc, env
428 VC.validate_morph mut_xs, 'foldl', loc, env
429
430 mut_y = yield loc, env, x, mut_y
431 end
432
433 ASSERT.kind_of mut_y, VC::Top
434 end
435
436
437 define_instance_method(
438 :meth_foldl,
439 :foldl, [],
440 [VC::Top, VC::Fun], VC::Top
441 )
442 def meth_foldl(loc, env, event, init, func)
443 ASSERT.kind_of init, VC::Top
444 ASSERT.kind_of func, VC::Fun
445
446 result = self.foldl(
447 loc, env, event, init
448 ) { |new_loc, new_env, x, y|
449
450 func.apply x, [y], new_loc, new_env
451 }
452
453 ASSERT.kind_of result, VC::Top
454 end
455
456
457 define_instance_method(
458 :meth_reverse,
459 :reverse, [],
460 [], self
461 )
462 def meth_reverse(loc, env, event)
463 result = self.foldl(
464 loc, env, event, self.meth_make_empty(loc, env, event)
465 ) { |new_loc, new_env, x, xs|
466
467 xs.meth_cons new_loc, new_env, event, x
468 }
469
470 ASSERT.kind_of result, VC::Top
471 end
472
473
474 define_instance_method(
475 :meth_at,
476 :at, [],
477 [VCAN::Int], VCU::Option::Abstract
478 )
479 def meth_at(loc, env, event, target_index)
480 ASSERT.opt_kind_of target_index, VCAN::Int
481
482 target_index_val = target_index.val
483 unless target_index_val >= 0
484 raise X::ArgumentError.new(
485 loc,
486 env,
487 "at: Expected zero or positive integer, but: %d",
488 target_index_val
489 )
490 end
491
492 result = self.foldl(
493 loc, env, event, VC.make_opaque([0, VC.make_none])
494 ) { |new_loc, new_event, x, opaque|
495
496 index_val, opt = opaque.obj
497 if index_val == target_index_val
498 break VC.make_opaque [index_val, VC.make_some(x)]
499 end
500
501 VC.make_opaque [index_val + 1, opt]
502 }
503
504 ASSERT.kind_of result.obj[1], VCU::Option::Abstract
505 end
506
507
508 define_instance_method(
509 :meth_at!,
510 :'at!', [:apply],
511 [VCAN::Int], VC::Top
512 )
513 def meth_at!(loc, env, event, target_index)
514 ASSERT.opt_kind_of target_index, VCAN::Int
515
516 target_index_val = target_index.val
517 unless target_index_val >= 0
518 raise X::ArgumentError.new(
519 loc,
520 env,
521 "at!: Expected zero or positive integer, but: %d",
522 target_index_val
523 )
524 end
525
526 self.foldl(
527 loc, env, event, VC.make_opaque(0)
528 ) do |new_loc, new_event, x, opaque|
529
530 index_val = opaque.obj
531 if index_val == target_index_val
532 return x
533 end
534
535 VC.make_opaque(index_val + 1)
536 end
537
538 raise X::IndexError.new(
539 loc,
540 env,
541 "at!: Out of range index: %d",
542 target_index_val
543 )
544 end
545
546
547 define_instance_method(
548 :meth_count,
549 :count, [],
550 [], VCAN::Int
551 )
552 def meth_count(loc, env, event)
553 result = self.foldl(
554 loc, env, event, VC.make_integer_zero
555 ) { |new_loc, new_env, _, n|
556
557 n.meth_succ new_loc, new_env, event
558 }
559
560 ASSERT.kind_of result, VCAN::Int
561 end
562
563
564 define_instance_method(
565 :meth_sum,
566 :sum, [],
567 [], VCAN::Abstract
568 )
569 def meth_sum(loc, env, event)
570 val_opt = self.meth_dest loc, env, event
571
572 VC.validate_option val_opt, 'sum', loc, env
573 unless val_opt.some?
574 raise X::EmptyError.new loc, env, "sum: Empty morph"
575 end
576
577 head, _ = VC.validate_pair val_opt.contents, 'sum', loc, env
578 VC.validate_number head, 'sum', loc, env
579
580 zero = head.meth_zero loc, env, event
581 zero_class_signat = env.ty_class_signat_of zero
582
583 result = self.foldl(
584 loc, env, event, zero
585 ) { |new_loc, new_env, x, sum|
586
587 unless env.ty_kind_of?(x, zero_class_signat)
588 raise X::TypeError.new(
589 new_loc,
590 new_env,
591 "sum: Expected a %s, but %s : %s",
592 zero_class_signat.symbol.to_s,
593 x.to_s,
594 x.type_sym.to_s
595 )
596 end
597
598 sum.meth_add new_loc, new_env, event, x
599 }
600
601 ASSERT.kind_of result, VCAN::Abstract
602 end
603
604
605 define_instance_method(
606 :meth_avg,
607 :avg, [],
608 [], VCAN::Abstract
609 )
610 def meth_avg(loc, env, event)
611 val_opt = self.meth_dest loc, env, event
612
613 VC.validate_option val_opt, 'avg', loc, env
614 unless val_opt.some?
615 raise X::EmptyError.new loc, env, "avg: Empty morph"
616 end
617
618 head, _ = VC.validate_pair val_opt.contents, 'avg', loc, env
619 VC.validate_number head, 'avg', loc, env
620
621 zero = head.meth_zero loc, env, event
622 zero_class_signat = env.ty_class_signat_of zero
623
624 result_opaque = self.foldl(
625 loc, env, event, VC.make_opaque([zero, zero])
626 ) { |new_loc, new_env, x, opaque|
627
628 unless env.ty_kind_of?(x, zero_class_signat)
629 raise X::TypeError.new(
630 new_loc,
631 new_env,
632 "avg: Expected a %s, but %s : %s",
633 zero_class_signat.symbol.to_s,
634 x.to_s,
635 x.type_sym.to_s
636 )
637 end
638
639 va_sum, va_count = opaque.obj
640
641 VC.make_opaque(
642 [
643 va_sum.meth_add(loc, env, event, x),
644 va_count.meth_succ(loc, env, event)
645 ]
646 )
647 }
648
649 res_sum, res_count = result_opaque.obj
650
651 res_sum.meth_divide(loc, env, event, res_count)
652 end
653
654
655 define_instance_method(
656 :meth_max,
657 :max, [],
658 [], VCAN::Abstract
659 )
660 def meth_max(loc, env, event)
661 val_opt = self.meth_dest loc, env, event
662
663 VC.validate_option val_opt, 'max', loc, env
664 unless val_opt.some?
665 raise X::EmptyError.new loc, env, "max: Empty morph"
666 end
667
668 head, _ = VC.validate_pair val_opt.contents, 'max', loc, env
669 VC.validate_number head, 'max', loc, env
670
671 head_class_signat = env.ty_class_signat_of head
672
673 self.meth_tail(loc, env, event).foldl(
674 loc, env, event, head
675 ) { |new_loc, new_event, x, y|
676
677 unless env.ty_kind_of?(y, head_class_signat)
678 raise X::TypeError.new(
679 new_loc,
680 new_env,
681 "max: Expected a %s, but %s : %s",
682 head_class_signat.symbol.to_s,
683 y.to_s,
684 y.type_sym.to_s
685 )
686 end
687
688 if y.meth_is_less_than(loc, env, event, x).true?
689 x
690 else
691 y
692 end
693 }
694 end
695
696
697 define_instance_method(
698 :meth_min,
699 :min, [],
700 [], VCAN::Abstract
701 )
702 def meth_min(loc, env, event)
703 val_opt = self.meth_dest loc, env, event
704
705 VC.validate_option val_opt, 'max', loc, env
706 unless val_opt.some?
707 raise X::EmptyError.new loc, env, "max: Empty morph"
708 end
709
710 head, _ = VC.validate_pair val_opt.contents, 'max', loc, env
711 VC.validate_number head, 'min', loc, env
712
713 head_class_signat = env.ty_class_signat_of head
714
715 self.meth_tail(loc, env, event).foldl(
716 loc, env, event, head
717 ) { |new_loc, new_event, x, y|
718
719 unless env.ty_kind_of?(y, head_class_signat)
720 raise X::TypeError.new(
721 new_loc,
722 new_env,
723 "min: Expected a %s, but %s : %s",
724 head_class_signat.symbol.to_s,
725 y.to_s,
726 y.type_sym.to_s
727 )
728 end
729
730 if x.meth_is_less_than(loc, env, event, y).true?
731 x
732 else
733 y
734 end
735 }
736 end
737
738
739 define_instance_method(
740 :meth_is_all,
741 :all?, [],
742 [VC::Fun], VCA::Bool
743 )
744 def meth_is_all(loc, env, event, func)
745 ASSERT.kind_of func, VC::Fun
746
747 result = self.foldl(
748 loc, env, event, VC.make_true
749 ) { |new_loc, new_env, x, bool|
750
751 value = func.apply x, [], new_loc, new_env
752 VC.validate_bool value, 'all?', loc, env
753
754 break VC.make_false if value.false?
755
756 bool
757 }
758
759 ASSERT.kind_of result, VCA::Bool
760 end
761
762
763 define_instance_method(
764 :meth_is_any,
765 :any?, [],
766 [VC::Fun], VCA::Bool
767 )
768 def meth_is_any(loc, env, event, func)
769 ASSERT.kind_of func, VC::Fun
770
771 result = self.foldl(
772 loc, env, event, VC.make_false
773 ) { |new_loc, new_env, x, bool|
774
775 value = func.apply x, [], new_loc, new_env
776 VC.validate_bool value, 'any?', loc, env
777
778 break VC.make_true if value.true?
779
780 bool
781 }
782
783 ASSERT.kind_of result, VCA::Bool
784 end
785
786
787 define_instance_method(
788 :meth_is_include,
789 :include?, [],
790 [VC::Top], VCA::Bool
791 )
792 def meth_is_include(loc, env, event, member)
793 ASSERT.kind_of member, VC::Top
794
795 result = self.foldl(
796 loc, env, event, VC.make_false
797 ) { |new_loc, new_env, x, bool|
798
799 value = x.meth_is_equal loc, new_env, event, member
800 VC.validate_bool value, 'include?', loc, env
801
802 break VC.make_true if value.true?
803
804 bool
805 }
806
807 ASSERT.kind_of result, VCA::Bool
808 end
809
810
811 define_instance_method(
812 :meth_for_each,
813 :'for-each', [],
814 [VC::Fun], VC::Unit
815 )
816 def meth_for_each(loc, env, event, func)
817 ASSERT.kind_of func, VC::Fun
818
819 self.foldl(
820 loc, env, event, VC.make_unit
821 ) do |new_loc, new_env, x, _|
822
823 func.apply x, [], loc, new_env
824 end
825
826 VC.make_unit
827 end
828
829
830 define_instance_method(
831 :meth_map,
832 :map, [],
833 [VC::Fun], self
834 )
835 def meth_map(loc, env, event, func)
836 ASSERT.kind_of func, VC::Fun
837
838 result = self.foldr(
839 loc, env, event, self.meth_make_empty(loc, env, event)
840 ) { |new_loc, new_env, x, ys|
841
842 ys.meth_cons(
843 new_loc, new_env, event,
844 func.apply(x, [], new_loc, new_env)
845 )
846 }
847
848 ASSERT.kind_of result, self.abstract_class
849 end
850
851
852 define_instance_method(
853 :meth_select,
854 :select, [],
855 [VC::Fun], self
856 )
857 def meth_select(loc, env, event, func)
858 ASSERT.kind_of func, VC::Fun
859
860 result = self.foldr(
861 loc, env, event, self.meth_make_empty(loc, env, event)
862 ) { |new_loc, new_env, x, ys|
863
864 value = func.apply x, [], new_loc, new_env
865 VC.validate_bool value, 'select', new_loc, new_env
866
867 if value.true?
868 ys.meth_cons new_loc, new_env, event, x
869 else
870 ys
871 end
872 }
873
874 ASSERT.kind_of result, self.abstract_class
875 end
876
877
878 define_instance_method(
879 :meth_reject,
880 :reject, [],
881 [VC::Fun], self
882 )
883 def meth_reject(loc, env, event, func)
884 ASSERT.kind_of func, VC::Fun
885
886 result = self.foldr(
887 loc, env, event, self.meth_make_empty(loc, env, event)
888 ) { |new_loc, new_env, x, ys|
889
890 value = func.apply x, [], new_loc, new_env
891 VC.validate_bool value, 'reject', new_loc, new_env
892
893 if value.false?
894 ys.meth_cons new_loc, new_env, event, x
895 else
896 ys
897 end
898 }
899
900 ASSERT.kind_of result, self.abstract_class
901 end
902
903
904 define_instance_method(
905 :meth_append,
906 :'++', [],
907 [self], self
908 )
909 def meth_append(loc, env, event, ys)
910 ASSERT.kind_of ys, Abstract
911
912 result = self.foldr(
913 loc, env, event, ys
914 ) { |new_loc, new_env, x, ys1|
915
916 ys1.meth_cons new_loc, new_env, event, x
917 }
918
919 ASSERT.kind_of result, VCM::Abstract
920 end
921
922
923 define_instance_method(
924 :meth_concat,
925 :concat, [],
926 [], self
927 )
928 def meth_concat(loc, env, event)
929 result = self.foldl(
930 loc, env, event, self.meth_make_empty(loc, env, event)
931 ) { |new_loc, new_env, xs, xss|
932
933 xss.meth_append new_loc, new_env, event, xs
934 }
935
936 ASSERT.kind_of result, self.abstract_class
937 end
938
939
940 define_instance_method(
941 :meth_concat_map,
942 :'concat-map', [],
943 [VC::Fun], self
944 )
945 def meth_concat_map(loc, env, event, func)
946 ASSERT.kind_of func, VC::Fun
947
948 result = self.foldl(
949 loc, env, event, self.meth_make_empty(loc, env, event)
950 ) { |new_loc, new_env, x, yss|
951
952 xs = func.apply x, [], new_loc, new_env
953 VC.validate_morph xs, 'concat-map', new_loc, new_env
954
955 yss.meth_append new_loc, new_env, event, xs
956 }
957
958 ASSERT.kind_of result, self.abstract_class
959 end
960
961
962 define_instance_method(
963 :meth_join,
964 :join, [],
965 [], VCA::String
966 )
967 define_instance_method(
968 :meth_join,
969 :'join-by', [:'join:'],
970 [VCA::String], VCA::String
971 )
972 def meth_join(loc, env, event, sep_value = nil)
973 ASSERT.opt_kind_of sep_value, VCA::String
974
975 result = self.foldl(
976 loc, env, event, VC.make_opaque(["", true])
977 ) { |new_loc, new_env, x, opaque|
978
979 VC.validate_string x, 'join', new_loc, new_env
980
981 s, is_first = opaque.obj
982
983 VC.make_opaque(
984 [
985 s + (
986 if sep_value && ! is_first
987 sep_value.val
988 else
989 ""
990 end
991 ) + x.val,
992
993 false
994 ]
995 )
996 }
997
998 VC.make_string (result.obj)[0]
999 end
1000
1001
1002 define_instance_method(
1003 :meth_zip,
1004 :zip, [],
1005 [self], self
1006 )
1007 def meth_zip(loc, env, event, ys)
1008 ASSERT.kind_of ys, Abstract
1009
1010 _, _, zs = loop.inject(
1011 [self, ys, self.meth_make_empty(loc, env, event)]
1012 ) { |(xs1, ys1, zs1 ), _|
1013
1014 xs_opt = xs1.meth_dest loc, env, event
1015 ys_opt = ys1.meth_dest loc, env, event
1016
1017 if xs_opt.none? || ys_opt.none?
1018 break [xs1, ys1, zs1]
1019 else
1020 xs_pair = xs_opt.contents
1021 x, xs2 = VC.validate_pair xs_pair, "zip", loc, env
1022
1023 ys_pair = ys_opt.contents
1024 y, ys2 = VC.validate_pair ys_pair, "zip", loc, env
1025
1026 [
1027 xs2,
1028 ys2,
1029 zs1.meth_cons(loc, env, event,
1030 VC.make_tuple(x, y)
1031 )
1032 ]
1033 end
1034 }
1035
1036 result = zs.meth_reverse loc, env, event
1037
1038 ASSERT.kind_of result, self.abstract_class
1039 end
1040
1041
1042 define_instance_method(
1043 :meth_unzip,
1044 :unzip, [],
1045 [], VCP::Tuple
1046 )
1047 def meth_unzip(loc, env, event)
1048 result = self.foldr(
1049 loc, env, event,
1050 VC.make_tuple(
1051 self.meth_make_empty(loc, env, event),
1052 self.meth_make_empty(loc, env, event)
1053 )
1054 ) { |new_loc, new_env, y_z, ys_zs|
1055
1056 y, z = VC.validate_pair y_z, "unzip", new_loc, new_env
1057 ys, zs = VC.validate_pair ys_zs, "unzip", new_loc, new_env
1058 ys, zs = ys_zs.values
1059
1060 VC.make_tuple(
1061 ys.meth_cons(loc, env, event, y),
1062 zs.meth_cons(loc, env, event, z)
1063 )
1064 }
1065
1066 ASSERT.kind_of result, VCP::Tuple
1067 end
1068
1069
1070 define_instance_method(
1071 :meth_uniq,
1072 :uniq, [],
1073 [], self
1074 )
1075 def meth_uniq(loc, env, event)
1076 val_opt = self.meth_dest loc, env, event
1077 VC.validate_option val_opt, 'uniq', loc, env
1078
1079 if val_opt.none?
1080 self
1081 else
1082 x, xs = VC.validate_pair val_opt.contents, "uniq", loc, env
1083
1084 xs_opt = xs.meth_dest loc, env, event
1085 VC.validate_option xs_opt, 'uniq', loc, env
1086
1087 if xs_opt.none?
1088 self
1089 else
1090 result_opaque = xs.foldl(
1091 loc, env, event,
1092 VC.make_opaque([x, VC.make_list([x])])
1093 ) { |new_loc, new_env, x1, opaque|
1094
1095 before, ys = opaque.obj
1096
1097 VC.make_opaque(
1098 [
1099 x1,
1100
1101 if x1.meth_is_equal(
1102 loc, env, event, before
1103 ).true?
1104 ys
1105 else
1106 ys.meth_cons loc, env, event, x1
1107 end
1108 ]
1109 )
1110 }
1111
1112 (result_opaque.obj)[1].meth_reverse loc, env, event
1113 end
1114 end
1115 end
1116
1117
1118 define_instance_method(
1119 :meth_partition,
1120 :partition, [],
1121 [VC::Fun], VCP::Tuple
1122 )
1123 def meth_partition(loc, env, event, func)
1124 ASSERT.kind_of func, VC::Fun
1125
1126 init_opaque = VC.make_opaque [
1127 self.meth_make_empty(loc, env, event),
1128 self.meth_make_empty(loc, env, event)
1129 ]
1130
1131 result_opaque = self.foldr(
1132 loc, env, event, init_opaque
1133 ) { |new_loc, new_env, x, opaque|
1134
1135 value = func.apply(x, [], loc, new_env)
1136 VC.validate_bool value, 'partition', new_loc, new_env
1137
1138 ys, zs = opaque.obj
1139
1140 if value.true?
1141 VC.make_opaque([
1142 ys.meth_cons(loc, env, event, x),
1143 zs
1144 ])
1145 else
1146 VC.make_opaque([
1147 ys,
1148 zs.meth_cons(loc, env, event, x)
1149 ])
1150 end
1151 }
1152
1153 VC.make_tuple result_opaque.obj[0], result_opaque.obj[1]
1154 end
1155
1156
1157 define_instance_method(
1158 :meth_sort,
1159 :sort, [],
1160 [], self
1161 )
1162 define_instance_method(
1163 :meth_sort,
1164 :'sort-with', [],
1165 [VC::Fun], self
1166 )
1167 def meth_sort(loc, env, event, opt_func = nil)
1168 ASSERT.opt_kind_of opt_func, VC::Fun
1169
1170 val_opt = self.meth_dest loc, env, event
1171
1172 VC.validate_option val_opt, 'head', loc, env
1173 unless val_opt.none?
1174 return self
1175 end
1176
1177 pivot, xs = VC.validate_pair val_opt.contents, "sort", loc, env
1178
1179 init_opaque = VC.make_opaque [
1180 self.meth_make_empty(loc, env, event),
1181 self.meth_make_empty(loc, env, event)
1182 ]
1183
1184 result_opaque = xs.foldr(
1185 loc, env, event, init_opaque
1186 ) { |new_loc, new_env, x, opaque|
1187
1188 compare_result = if opt_func
1189 func = opt_func
1190
1191 value = func.apply x, [pivot], new_loc, new_env
1192 VC.validate_int value, 'sort', new_loc, new_env
1193
1194 value.val
1195 else
1196 if x.meth_is_less_than(
1197 new_loc, new_env, event, pivot
1198 ).true?
1199 -1
1200 else
1201 1
1202 end
1203 end
1204
1205 ys, zs = opaque.obj
1206
1207 if compare_result < 0
1208 VC.make_opaque([
1209 ys.meth_cons(loc, env, event, x),
1210 zs
1211 ])
1212 else
1213 VC.make_opaque([
1214 ys,
1215 zs.meth_cons(loc, env, event, x)
1216 ])
1217 end
1218 }
1219 littles, bigs = result_opaque.obj
1220
1221 littles1 = littles.meth_sort loc, env, event, opt_func
1222 bigs1 = bigs .meth_sort loc, env, event, opt_func
1223
1224 result = littles1.meth_append(loc, env, event,
1225 bigs1.meth_cons(loc, env, event, pivot)
1226 )
1227
1228 ASSERT.kind_of result, self.abstract_class
1229 end
1230 end
1231 Abstract.freeze
1232
1233 end # Umu::Value::Core::Morph
1234
1235 end # Umu::Value::Core
1236
1237 end # Umu::Value
1238
1239 end # Umu