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 Binary
15
16 module Send
17
18 module Message
19
20 class Abstract < Expression::Abstract; end
21
22
23
24 class BasicMessage < Abstract
25 attr_reader :sym, :exprs
26
27
28 def initialize(loc, sym, exprs)
29 ASSERT.kind_of sym, ::Symbol
30 ASSERT.kind_of exprs, ::Array
31
32 super(loc)
33
34 @sym = sym
35 @exprs = exprs
36 end
37
38
39 def to_s
40 format(".%s",
41 if self.exprs.empty?
42 self.sym.to_s
43 else
44 format "(%s %s)",
45 self.sym.to_s,
46 self.exprs.map(&:to_s).join(' ')
47 end
48 )
49 end
50
51
52 def pretty_print(q)
53 PRT.group_for_enum(
54 q,
55
56 self.exprs,
57
58 bb: format(self.exprs.empty? ? ".%s" : ".(%s ", self.sym.to_s),
59
60 eb: self.exprs.empty? ? '' : ')',
61
62 join: ' '
63 )
64 end
65
66
67 private
68
69 def __desugar__(env, event)
70 new_env = env.enter event
71
72 ASCE.make_message(
73 self.loc,
74 self.sym,
75 self.exprs.map { |expr| expr.desugar(new_env) },
76 )
77 end
78 end
79
80
81
82 class ApplyMessage < Abstract
83 attr_reader :head_expr, :tail_exprs
84
85
86 def initialize(loc, head_expr, tail_exprs)
87 ASSERT.kind_of head_expr, CSCE::Abstract
88 ASSERT.kind_of tail_exprs, ::Array
89
90 super(loc)
91
92 @head_expr = head_expr
93 @tail_exprs = tail_exprs
94 end
95
96
97 def to_s
98 format(".[%s]",
99 ([self.head_expr.to_s] + self.tail_exprs).map(&:to_s).join(', ')
100 )
101 end
102
103
104 def pretty_print(q)
105 PRT.group_for_enum(
106 q,
107 [self.head_expr] + self.tail_exprs,
108 bb: '.[',
109 eb: ']',
110 join: ', '
111 )
112 end
113
114
115 private
116
117 def __desugar__(env, event)
118 new_env = env.enter event
119
120 message = case self.tail_exprs.size
121 when 0
122 expr = [self.head_expr.desugar(new_env)]
123
124 ASCE.make_message self.loc, :apply, expr
125 when 1
126 exprs = [
127 self.head_expr.desugar(new_env),
128 self.tail_exprs[0].desugar(new_env)
129 ]
130
131 ASCE.make_message self.loc, :'apply-binary', exprs
132 else
133 second_expr, *tail_exprs = self.tail_exprs
134 exprs = [
135 self.head_expr.desugar(new_env),
136
137 second_expr.desugar(new_env),
138
139 ASCE.make_list(
140 tail_exprs[0].loc,
141 tail_exprs.map { |expr| expr.desugar new_env }
142 )
143 ]
144
145 ASCE.make_message self.loc, :'apply-nary', exprs
146 end
147
148 ASSERT.kind_of message, ASCE::Binary::Send::Message
149 end
150 end
151
152
153
154 class KeywordMessage < Abstract
155 attr_reader :head_field, :tail_fields
156
157
158 def initialize(loc, head_field, tail_fields)
159 ASSERT.tuple_of head_field, [
160 CSCEU::Container::Named::Label, ::Object
161 ]
162 ASSERT.opt_kind_of head_field[1], CSCE::Abstract
163 ASSERT.kind_of tail_fields, ::Array
164 tail_fields.each do |lab, expr|
165 ASSERT.kind_of lab, CSCEU::Container::Named::Label
166 ASSERT.opt_kind_of expr, CSCE::Abstract
167 end
168
169 super(loc)
170
171 @head_field = head_field
172 @tail_fields = tail_fields
173 end
174
175
176 def to_s
177 format(".(%s)",
178 ([self.head_field] + self.tail_fields).map { |lab, opt_expr|
179 lab.to_s + (opt_expr ? opt_expr.to_s : '')
180 }.join(' ')
181 )
182 end
183
184
185 def pretty_print(q)
186 PRT.group_for_enum(
187 q,
188 [self.head_field] + self.tail_fields,
189 bb: '.(',
190 eb: ')',
191 join: ' '
192 ) do |lab, opt_expr|
193 q.text lab.to_s
194 q.text opt_expr.to_s if opt_expr
195 end
196 end
197
198
199 private
200
201 def __desugar__(env, event)
202 new_env = env.enter event
203
204 labels, exprs = (
205 [self.head_field] + self.tail_fields
206 ).inject([[], []]) { |(ls, es), fld|
207 lab, opt_expr = fld
208 expr = if opt_expr
209 opt_expr.desugar new_env
210 else
211 ASCE.make_identifier lab.loc, lab.sym
212 end
213
214 [ls + [lab], es + [expr]]
215 }
216 sym = labels.map { |lab| lab.sym.to_s + ':' }.join.to_sym
217
218 ASCE.make_message self.loc, sym, exprs
219 end
220 end
221
222 end # Umu::ConcreteSyntax::Core::Expression::Binary::Send::Message
223
224
225
226 class Entry < Binary::Abstract
227 alias lhs_expr lhs
228 alias rhs_head_message rhs
229 attr_reader :rhs_tail_messages
230
231
232 def initialize(loc, lhs_expr, rhs_head_message, rhs_tail_messages)
233 ASSERT.kind_of lhs_expr, CSCE::Abstract
234 ASSERT.kind_of rhs_head_message, Message::Abstract
235 ASSERT.kind_of rhs_tail_messages, ::Array
236
237 super(loc, lhs_expr, rhs_head_message)
238
239 @rhs_tail_messages = rhs_tail_messages
240 end
241
242
243 def to_s
244 format("(%s)%s",
245 self.lhs_expr.to_s,
246 self.rhs_messages.map(&:to_s).join
247 )
248 end
249
250
251 def pretty_print(q)
252 PRT.group q, bb:'(', eb:')' do
253 q.pp self.lhs_expr
254 end
255
256 PRT.group_for_enum q, self.rhs_messages
257 end
258
259
260 def rhs_messages
261 [self.rhs_head_message] + self.rhs_tail_messages
262 end
263
264
265 private
266
267 def __desugar__(env, event)
268 new_env = env.enter event
269
270 ASCE.make_send(
271 self.loc,
272 self.lhs_expr.desugar(new_env),
273 self.rhs_head_message.desugar(new_env),
274 self.rhs_tail_messages.map { |mess|
275 ASSERT.kind_of mess, Message::Abstract
276
277 mess.desugar(new_env)
278 }
279 )
280 end
281 end
282
283 end # Umu::ConcreteSyntax::Core::Expression::Binary::Send
284
285 end # Umu::ConcreteSyntax::Core::Expression::Binary
286
287
288 module_function
289
290 def make_message(loc, sym, exprs = [])
291 ASSERT.kind_of loc, LOC::Entry
292 ASSERT.kind_of sym, ::Symbol
293 ASSERT.kind_of exprs, ::Array
294
295 Binary::Send::Message::BasicMessage.new(
296 loc, sym, exprs.freeze
297 ).freeze
298 end
299
300
301 def make_apply_message(loc, expr, exprs = [])
302 ASSERT.kind_of loc, LOC::Entry
303 ASSERT.kind_of expr, CSCE::Abstract
304 ASSERT.kind_of exprs, ::Array
305
306 Binary::Send::Message::ApplyMessage.new(
307 loc, expr, exprs.freeze
308 ).freeze
309 end
310
311
312 def make_keyword_message(loc, field, fields = [])
313 ASSERT.kind_of loc, LOC::Entry
314 ASSERT.tuple_of field, [CSCEU::Container::Named::Label, ::Object]
315 ASSERT.kind_of fields, ::Array
316
317 Binary::Send::Message::KeywordMessage.new(
318 loc, field, fields.freeze
319 ).freeze
320 end
321
322
323 def make_send(loc, lhs_expr, rhs_head_message, rhs_tail_messages = [])
324 ASSERT.kind_of loc, LOC::Entry
325 ASSERT.kind_of lhs_expr, CSCE::Abstract
326 ASSERT.kind_of rhs_head_message, Binary::Send::Message::Abstract
327 ASSERT.kind_of rhs_tail_messages, ::Array
328
329 Binary::Send::Entry.new(
330 loc, lhs_expr, rhs_head_message, rhs_tail_messages.freeze
331 ).freeze
332 end
333
334 end # Umu::ConcreteSyntax::Core::Expression
335
336 end # Umu::ConcreteSyntax::Core
337
338 end # Umu::ConcreteSyntax
339
340 end # Umu