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 Interval < Abstract
15 define_class_method(
16 :meth_make_empty,
17 :empty, [],
18 [], VCM::List::Abstract
19 )
20 def self.meth_make_empty(loc, env, _event)
21 VC.make_nil
22 end
23
24
25 define_class_method(
26 :meth_from_to_by,
27 :'from-to', [:'from:to:'],
28 [VCAN::Int, VCAN::Int], self
29 )
30 define_class_method(
31 :meth_from_to_by,
32 :'from-to-by', [:'from:to:by:'],
33 [VCAN::Int, VCAN::Int, VCAN::Int], self
34 )
35 def self.meth_from_to_by(
36 _loc, _env, _event,
37 start_value,
38 stop_value,
39 step_value = VC.make_integer_one
40 )
41 ASSERT.kind_of start_value, VCAN::Int
42 ASSERT.kind_of stop_value, VCAN::Int
43 ASSERT.kind_of step_value, VCAN::Int
44
45 VC.make_interval start_value, stop_value, step_value
46 end
47
48
49 attr_reader :current_value, :stop_value, :step_value
50
51
52 def initialize(current_value, stop_value, step_value)
53 ASSERT.kind_of current_value, VCAN::Int
54 ASSERT.kind_of stop_value, VCAN::Int
55 ASSERT.kind_of step_value, VCAN::Int
56
57 @current_value = current_value
58 @stop_value = stop_value
59 @step_value = step_value
60 end
61
62
63 def to_s
64 step = self.step_value.val
65
66 format("[%s .. %s (%s%s)]",
67 self.current_value.to_s,
68 self.stop_value.to_s,
69 step.positive? ? '+' : '',
70 step.to_s
71 )
72 end
73
74
75 INDEX_BY_LABELS = {current: 0, stop: 1, step: 2}
76
77 define_instance_method(
78 :meth_contents,
79 :contents, [],
80 [], VCP::Named
81 )
82 def meth_contents(_loc, _env, _event)
83 VC.make_named_tuple(
84 INDEX_BY_LABELS,
85 self.current_value,
86 self.stop_value,
87 self.step_value
88 )
89 end
90
91
92 define_instance_method(
93 :meth_susp,
94 :susp, [],
95 [], VCM::Stream::Entry::Interval
96 )
97 def meth_susp(_loc, env, _event)
98 VC.make_interval_stream(
99 self.current_value,
100 self.stop_value,
101 self.step_value,
102 env.va_context
103 )
104 end
105
106
107 define_instance_method(
108 :meth_cons,
109 :cons, [],
110 [VC::Top], VCM::List::Abstract
111 )
112 def meth_cons(loc, env, event, value)
113 ASSERT.kind_of value, VC::Top
114
115 self.meth_to_list(loc, env, event)
116 .meth_cons(loc, env, event, value)
117 end
118
119
120 def meth_dest(_loc, _env, _event)
121 if (
122 if self.step_value.val.positive?
123 self.current_value.val > self.stop_value.val
124 else
125 self.current_value.val < self.stop_value.val
126 end
127 )
128 VC.make_none
129 else
130 VC.make_some(
131 VC.make_tuple(
132 self.current_value,
133
134 VC.make_interval(
135 self.current_value + self.step_value,
136 self.stop_value,
137 self.step_value
138 )
139 )
140 )
141 end
142 end
143 end
144 Interval.freeze
145
146
147 end # Umu::Value::Core::Morph
148
149
150 module_function
151
152 def make_interval(
153 start_value,
154 stop_value,
155 step_value = VC.make_integer_one
156 )
157 ASSERT.kind_of start_value, VCAN::Int
158 ASSERT.kind_of stop_value, VCAN::Int
159 ASSERT.kind_of step_value, VCAN::Int
160
161 Morph::Interval.new(
162 start_value, stop_value, step_value
163 ).freeze
164 end
165
166 end # Umu::Value::Core
167
168 end # Umu::Value
169
170 end # Umu