1 # coding: utf-8
2 # frozen_string_literal: true
3
4
5
6 module Umu
7
8 module ConcreteSyntax
9
10 module Core
11
12 module Expression
13
14 module Unary
15
16 module Container
17
18 module Comprehension
19
20 module Qualifier
21
22 class Abstract < Umu::Abstraction::Model
23 attr_reader :expr
24
25
26 def initialize(loc, expr)
27 ASSERT.kind_of expr, CSCE::Abstract
28
29 super(loc)
30
31 @expr = expr
32 end
33
34
35 def pretty_print(_q)
36 raise X::InternalSubclassResponsibility
37 end
38 end
39
40
41
42 class Generator < Abstract
43 attr_reader :pat
44
45
46 def initialize(loc, pat, expr)
47 ASSERT.kind_of pat, CSCP::Abstract
48 ASSERT.kind_of expr, CSCE::Abstract
49
50 super(loc, expr)
51
52 @pat = pat
53 end
54
55
56 def to_s
57 format "%%VAL %s <- %s", self.pat.to_s, self.expr.to_s
58 end
59
60
61 def pretty_print(q)
62 q.text '%VAL '
63 q.pp self.pat
64 q.text ' <- '
65 q.pp self.expr
66 end
67
68
69 def desugar_qualifier(
70 env, elem_expr, tail_qualifiers, type_coercion_sym,
71 make_comprehension, _make_morph
72 )
73 ASSERT.kind_of env, E::Entry
74 ASSERT.kind_of elem_expr, CSCE::Abstract
75 ASSERT.kind_of tail_qualifiers, ::Array
76 ASSERT.kind_of type_coercion_sym, ::Symbol
77 ASSERT.kind_of make_comprehension, ::Proc
78 ASSERT.kind_of _make_morph, ::Proc
79
80 body_expr = make_comprehension.call(
81 self.loc, elem_expr, tail_qualifiers
82 )
83
84 ASCE.make_send(
85 self.loc,
86
87 self.expr.desugar(env),
88
89 ASCE.make_message(self.loc, type_coercion_sym),
90
91 [
92 ASCE.make_message(
93 self.loc,
94
95 :'concat-map',
96
97 [
98 CSCE.make_lambda(
99 self.loc, [self.pat], body_expr
100 ).desugar(env)
101 ]
102 )
103 ]
104 )
105 end
106 end
107
108
109
110 class Guard < Abstract
111 def to_s
112 format "%%IF %s", self.expr.to_s
113 end
114
115
116 def pretty_print(q)
117 q.text '%IF '
118 q.pp self.expr
119 end
120
121
122 def desugar_qualifier(
123 env, elem_expr, tail_qualifiers, _type_coercion_sym,
124 make_comprehension, make_morph
125 )
126 ASSERT.kind_of env, E::Entry
127 ASSERT.kind_of elem_expr, CSCE::Abstract
128 ASSERT.kind_of tail_qualifiers, ::Array
129 ASSERT.kind_of _type_coercion_sym, ::Symbol
130 ASSERT.kind_of make_comprehension, ::Proc
131 ASSERT.kind_of make_morph, ::Proc
132
133 then_expr = make_comprehension.call(
134 self.loc, elem_expr, tail_qualifiers
135 )
136
137 ASCE.make_if(
138 self.loc,
139
140 [
141 ASCE.make_rule(
142 elem_expr.loc,
143 self.expr.desugar(env),
144 then_expr.desugar(env)
145 )
146 ],
147
148 make_morph.call(self.loc, [])
149 )
150 end
151 end
152
153 end # Umu::ConcreteSyntax::Core::Expression::Unary::Container::Comprehension::Qualifier
154
155
156
157 module Entry
158
159 class Abstract < Container::Abstract
160 alias qualifiers exprs
161 attr_reader :expr
162
163
164 def initialize(loc, expr, qualifiers)
165 ASSERT.kind_of expr, CSCE::Abstract
166 ASSERT.kind_of qualifiers, ::Array
167
168 super(loc, qualifiers)
169
170 @expr = expr
171 end
172
173
174 def to_s
175 format("%s%s|%s]",
176 __bb__,
177
178 self.expr.to_s,
179
180 if self.qualifiers.empty?
181 ''
182 else
183 ' ' + self.qualifiers.map(&:to_s).join(' ')
184 end
185 )
186 end
187
188
189 def pretty_print(q)
190 PRT.group q, bb:__bb__, eb:'|' do
191 q.pp self.expr
192 end
193
194 PRT.group_for_enum q, self.qualifiers, eb:']', sep:' ', join:' '
195 end
196
197
198 private
199
200 def __desugar__(env, event)
201 new_env = env.enter event
202
203 if self.qualifiers.empty?
204 __make_morph__ self.loc, [self.expr.desugar(new_env)]
205 else
206 hd_qualifier, *tl_qualifiers = qualifiers
207 ASSERT.kind_of hd_qualifier, Qualifier::Abstract
208
209 hd_qualifier.desugar_qualifier(
210 new_env, self.expr, tl_qualifiers, __type_coercion_sym__,
211
212 lambda { |loc, expr, qualifiers|
213 __make_comprehension__ loc, expr, qualifiers
214 },
215
216 lambda { |loc, exprs|
217 __make_morph__ loc, exprs
218 }
219 )
220 end
221 end
222 end
223
224
225
226 class List < Abstract
227
228 private
229
230 def __bb__
231 '[|'
232 end
233
234
235 def __type_coercion_sym__
236 :'to-list'
237 end
238
239
240 def __make_comprehension__(loc, expr, qualifiers)
241 CSCE.make_list_comprehension loc, expr, qualifiers
242 end
243
244
245 def __make_morph__(loc, exprs)
246 ASCE.make_list loc, exprs
247 end
248 end
249
250
251
252 class Stream < Abstract
253
254 private
255
256 def __bb__
257 '&[|'
258 end
259
260
261 def __type_coercion_sym__
262 :'susp'
263 end
264
265
266 def __make_comprehension__(loc, expr, qualifiers)
267 CSCE.make_stream_comprehension loc, expr, qualifiers
268 end
269
270
271 def __make_morph__(loc, exprs)
272 ASCE.make_stream loc, exprs
273 end
274 end
275
276 end # Umu::ConcreteSyntax::Core::Expression::Unary::Container::Comprehension::Entry
277
278 end # Umu::ConcreteSyntax::Core::Expression::Unary::Container::Comprehension
279
280 end # Umu::ConcreteSyntax::Core::Expression::Unary::Container
281
282 end # Umu::ConcreteSyntax::Core::Expression::Unary
283
284
285 module_function
286
287 def make_generator(loc, pat, expr)
288 ASSERT.kind_of loc, LOC::Entry
289 ASSERT.kind_of pat, CSCP::Abstract
290 ASSERT.kind_of expr, CSCE::Abstract
291
292 Unary::Container::Comprehension::Qualifier::Generator.new(
293 loc, pat, expr
294 ).freeze
295 end
296
297
298 def make_guard(loc, expr)
299 ASSERT.kind_of loc, LOC::Entry
300 ASSERT.kind_of expr, CSCE::Abstract
301
302 Unary::Container::Comprehension::Qualifier::Guard.new(
303 loc, expr
304 ).freeze
305 end
306
307
308 def make_list_comprehension(loc, expr, qualifiers)
309 ASSERT.kind_of loc, LOC::Entry
310 ASSERT.kind_of expr, CSCE::Abstract
311 ASSERT.kind_of qualifiers, ::Array
312
313 Unary::Container::Comprehension::Entry::List.new(
314 loc, expr, qualifiers.freeze
315 ).freeze
316 end
317
318
319 def make_stream_comprehension(loc, expr, qualifiers)
320 ASSERT.kind_of loc, LOC::Entry
321 ASSERT.kind_of expr, CSCE::Abstract
322 ASSERT.kind_of qualifiers, ::Array
323
324 Unary::Container::Comprehension::Entry::Stream.new(
325 loc, expr, qualifiers.freeze
326 ).freeze
327 end
328
329 end # Umu::ConcreteSyntax::Core::Expression
330
331 end # Umu::ConcreteSyntax::Core
332
333 end # Umu::ConcreteSyntax
334
335 end # Umu