1 # coding: utf-8
2 # frozen_string_literal: true
3
4
5
6 module Umu
7
8 module AbstractSyntax
9
10 module Core
11
12 module Expression
13
14 module Nary
15
16 module Interval
17
18 class Abstract < Expression::Abstract
19 attr_reader :fst_expr, :opt_snd_expr, :opt_lst_expr
20
21
22 def initialize(loc, fst_expr, opt_snd_expr, opt_lst_expr)
23 ASSERT.kind_of fst_expr, ASCE::Abstract
24 ASSERT.opt_kind_of opt_snd_expr, ASCE::Abstract
25 ASSERT.opt_kind_of opt_lst_expr, ASCE::Abstract
26
27 super(loc)
28
29 @fst_expr = fst_expr
30 @opt_snd_expr = opt_snd_expr
31 @opt_lst_expr = opt_lst_expr
32 end
33
34
35 def to_s
36 format("%s%s%s ..%s]",
37 __bb__,
38
39 self.fst_expr.to_s,
40
41 if self.opt_snd_expr
42 format ", %s", self.opt_snd_expr.to_s
43 else
44 ''
45 end,
46
47 if self.opt_lst_expr
48 format " %s", self.opt_lst_expr.to_s
49 else
50 ''
51 end
52 )
53 end
54
55
56 private
57
58 def __bb__
59 raise X::InternalSubclassResponsibility
60 end
61
62
63 def __evaluate__(env, event)
64 ASSERT.kind_of env, E::Entry
65 ASSERT.kind_of event, E::Tracer::Event
66
67 new_env = env.enter event
68
69 fst_result = self.fst_expr.evaluate new_env
70 ASSERT.kind_of fst_result, ASR::Value
71 fst_value = fst_result.value
72 ASSERT.kind_of fst_value, VC::Top
73 unless fst_value.kind_of? VCAN::Int
74 raise X::TypeError.new(
75 self.loc,
76 env,
77 "Type error in interval-expression, " +
78 "expected a Int as first value, but %s : %s",
79 fst_value.to_s,
80 fst_value.type_sym.to_s
81 )
82 end
83
84 opt_snd_value = (
85 if self.opt_snd_expr
86 snd_result = self.opt_snd_expr.evaluate new_env
87 ASSERT.kind_of snd_result, ASR::Value
88 snd_value = snd_result.value
89 ASSERT.kind_of snd_value, VC::Top
90 unless snd_value.kind_of? VCAN::Int
91 raise X::TypeError.new(
92 self.loc,
93 env,
94 "Type error in interval-expression, " +
95 "expected a Int as second value, but %s : %s",
96 snd_value.to_s,
97 snd_value.type_sym.to_s
98 )
99 end
100
101 snd_value
102 else
103 nil
104 end
105 )
106
107 opt_lst_value = (
108 if self.opt_lst_expr
109 lst_result = self.opt_lst_expr.evaluate new_env
110 ASSERT.kind_of lst_result, ASR::Value
111
112 lst_val = lst_result.value
113 ASSERT.kind_of lst_val, VC::Top
114 unless lst_val.kind_of? VCAN::Int
115 raise X::TypeError.new(
116 self.loc,
117 env,
118 "Type error in interval-expression, " +
119 "expected a Int as last value, but %s : %s",
120 lst_val.to_s,
121 lst_val.type_sym.to_s
122 )
123 end
124
125 lst_val
126 else
127 nil
128 end
129 )
130
131 step_value = VC.make_integer(
132 if opt_lst_value
133 lst_value = opt_lst_value
134
135 if fst_value.val <= lst_value.val
136 if opt_snd_value
137 snd_value = opt_snd_value
138 unless (fst_value.val < snd_value.val &&
139 snd_value.val < lst_value.val)
140 raise X::ValueError.new(
141 self.loc,
142 env,
143 "The second value must be between " +
144 "the first and last value, but %s : %s",
145 snd_value.to_s,
146 snd_value.type_sym.to_s
147 )
148 end
149
150 snd_value.val - fst_value.val
151 else
152 1
153 end
154 else
155 if opt_snd_value
156 snd_value = opt_snd_value
157 unless (fst_value.val > snd_value.val &&
158 snd_value.val > lst_value.val)
159 raise X::ValueError.new(
160 self.loc,
161 env,
162 "The second value must be between " +
163 "the first and last value, but %s : %s",
164 snd_value.to_s,
165 snd_value.type_sym.to_s
166 )
167 end
168
169 snd_value.val - fst_value.val
170 else
171 -1
172 end
173 end
174 else
175 if opt_snd_value
176 snd_value = opt_snd_value
177
178 if fst_value.val == snd_value.val
179 raise X::ValueError.new(
180 self.loc,
181 env,
182 "The first value and second value " +
183 "must be not equal, but %s : %s",
184 snd_value.to_s,
185 snd_value.type_sym.to_s
186 )
187 else
188 snd_value.val - fst_value.val
189 end
190 else
191 1
192 end
193 end
194 )
195
196 __make__ fst_value, lst_value, step_value, env.va_context
197 end
198
199
200 private
201
202 def __make__(_fst_value, _lst_value, _step_value, _va_context)
203 raise X::InternalSubclassResponsibility
204 end
205
206
207 def __validate_second_value__(loc, env, fst_value, snd_value)
208 end
209 end
210
211
212
213 class Basic < Abstract
214 def initialize(loc, fst_expr, opt_snd_expr, lst_expr)
215 ASSERT.kind_of fst_expr, ASCE::Abstract
216 ASSERT.opt_kind_of opt_snd_expr, ASCE::Abstract
217 ASSERT.kind_of lst_expr, ASCE::Abstract
218
219 super
220 end
221
222
223 private
224
225 def __bb__
226 '['
227 end
228
229
230 def __make__(fst_value, lst_value, step_value, _va_context)
231 VC.make_interval fst_value, lst_value, step_value
232 end
233 end
234
235
236
237 class Stream < Abstract
238
239 private
240
241 def __bb__
242 '&['
243 end
244
245
246 def __make__(fst_value, lst_value, step_value, va_context)
247 VC.make_interval_stream fst_value, lst_value, step_value, va_context
248 end
249 end
250
251 end # Umu::AbstractSyntax::Core::Expression::Nary::Interval
252
253 end # Umu::AbstractSyntax::Core::Expression::Nary
254
255
256 module_function
257
258 def make_interval(loc, fst_expr, opt_snd_expr, lst_expr)
259 ASSERT.kind_of loc, LOC::Entry
260 ASSERT.kind_of fst_expr, ASCE::Abstract
261 ASSERT.opt_kind_of opt_snd_expr, ASCE::Abstract
262 ASSERT.kind_of lst_expr, ASCE::Abstract
263
264 Nary::Interval::Basic.new(
265 loc, fst_expr, opt_snd_expr, lst_expr
266 ).freeze
267 end
268
269
270 def make_interval_stream(loc, fst_expr, opt_snd_expr, opt_lst_expr)
271 ASSERT.kind_of loc, LOC::Entry
272 ASSERT.kind_of fst_expr, ASCE::Abstract
273 ASSERT.opt_kind_of opt_snd_expr, ASCE::Abstract
274 ASSERT.opt_kind_of opt_lst_expr, ASCE::Abstract
275
276 Nary::Interval::Stream.new(
277 loc, fst_expr, opt_snd_expr, opt_lst_expr
278 ).freeze
279 end
280
281 end # Umu::AbstractSyntax::Core::Expression
282
283 end # Umu::AbstractSyntax::Core
284
285 end # Umu::AbstractSyntax
286
287 end # Umu