1 # coding: utf-8
2 # frozen_string_literal: true
3
4
5
6 module Umu
7
8 module ConcreteSyntax
9
10 module Module
11
12 module Declaration
13
14 class Abstract < Module::Abstract
15 def exported_vars
16 raise X::InternalSubclassResponsibility
17 end
18 end
19
20
21
22 class Structure < Abstract
23 attr_reader :pat, :expr, :local_decls
24
25
26 def initialize(loc, pat, expr, local_decls)
27 ASSERT.kind_of pat, CSMP::Abstract
28 ASSERT.kind_of expr, CSME::Abstract
29 ASSERT.kind_of local_decls, ::Array
30
31 super(loc)
32
33 @pat = pat
34 @expr = expr
35 @local_decls = local_decls
36 end
37
38
39 def to_s
40 format("%%STRUCTURE %s = %s%s",
41 self.pat.to_s,
42
43 self.expr.to_s,
44
45 if self.local_decls.empty?
46 ''
47 else
48 format(" %%WHERE {%s}",
49 self.local_decls.map(&:to_s).join(' ')
50 )
51 end
52 )
53 end
54
55
56 def pretty_print(q)
57 PRT.group q, bb:format("%%STRUCTURE %s = ", self.pat.to_s) do
58 q.pp self.expr
59 end
60
61 unless self.local_decls.empty?
62 q.breakable
63
64 PRT.group_for_enum(
65 q, self.local_decls, bb:'%WHERE {', eb:'}', sep:' '
66 )
67 end
68 end
69
70
71 def exported_vars
72 self.pat.exported_vars
73 end
74
75
76 private
77
78 def __desugar__(env, event)
79 new_env = env.enter event
80
81 expr = if self.local_decls.empty?
82 self.expr.desugar new_env
83 else
84 ASCE.make_let(
85 self.loc,
86
87 ASCD.make_seq_of_declaration(
88 self.loc,
89 self.local_decls.map { |decl| decl.desugar new_env }
90 ),
91
92 self.expr.desugar(new_env)
93 )
94 end
95
96 self.pat.desugar_value expr, new_env
97 end
98 end
99
100
101
102 module Import
103
104 module Fields
105
106 class Abstract < Abstraction::Model
107 attr_reader :fields
108
109
110 def initialize(loc, fields)
111 ASSERT.kind_of fields, ::Array
112
113 super(loc)
114
115 @fields = fields
116 end
117
118
119 def to_s
120 self.fields.map { |target_id, opt_type_sym, opt_source_id|
121 ASSERT.kind_of target_id, CSME::Identifier::Short
122 ASSERT.opt_kind_of opt_type_sym, ::Symbol
123 ASSERT.opt_kind_of opt_source_id, CSME::Identifier::Abstract
124
125 __format_field__ target_id, opt_type_sym, opt_source_id
126 }.join(' ')
127 end
128
129
130 def pretty_print(q)
131 return if self.fields.empty?
132
133 fst_field, *not_fst_fields = self.fields
134 q.text __format_field__(*fst_field)
135
136 not_fst_fields.each do |field|
137 q.breakable
138
139 q.text __format_field__(*field)
140 end
141 end
142
143
144 def desugar_field(env, souce_dir_id)
145 ASSERT.kind_of souce_dir_id, CSME::Identifier::Abstract
146
147 self.fields.map { |target_id, opt_type_sym, opt_source_id|
148 ASSERT.kind_of target_id, CSME::Identifier::Short
149 ASSERT.opt_kind_of opt_type_sym, ::Symbol
150 ASSERT.opt_kind_of opt_source_id, CSME::Identifier::Abstract
151
152 expr = ASCE.make_long_identifier(
153 souce_dir_id.loc,
154
155 souce_dir_id.head.desugar(env),
156
157 (
158 souce_dir_id.tail + (
159 opt_source_id ? opt_source_id : target_id
160 ).to_a
161 ).map { |id| id.desugar env }
162 )
163
164 ASCD.make_value(
165 target_id.loc,
166 target_id.sym,
167 expr,
168 __opt_type_sym__(opt_type_sym)
169 )
170 }
171 end
172
173
174 private
175
176 def __reserved_word__
177 raise X::InternalSubclassResponsibility
178 end
179
180
181 def __opt_type_sym__
182 raise X::InternalSubclassResponsibility
183 end
184
185
186 def __format_field__(target_id, opt_type_sym, opt_source_id)
187 format("%%%s %s%s%s",
188 __reserved_word__,
189
190 target_id.to_s,
191
192 if opt_type_sym
193 format " : %s", opt_type_sym.to_s
194 else
195 ''
196 end,
197
198 if opt_source_id
199 format " = %s", opt_source_id.to_s
200 else
201 ''
202 end
203 )
204 end
205 end
206
207
208
209 class Value < Abstract
210
211 private
212
213 def __reserved_word__
214 'VAL'
215 end
216
217 def __opt_type_sym__(opt_type_sym)
218 opt_type_sym
219 end
220 end
221
222
223
224 class Function < Abstract
225
226 private
227
228 def __reserved_word__
229 'FUN'
230 end
231
232 def __opt_type_sym__(opt_type_sym)
233 opt_type_sym || :Fun
234 end
235 end
236
237
238
239 class Structure < Abstract
240
241 private
242
243 def __reserved_word__
244 'STRUCTURE'
245 end
246
247 def __opt_type_sym__(opt_type_sym)
248 opt_type_sym || :Struct
249 end
250 end
251
252 end # Umu::ConcreteSyntax::Module::Declaration::Import::Fields
253
254 class Entry < Declaration::Abstract
255 attr_reader :id, :opt_fields
256
257
258 def initialize(loc, id, opt_fields)
259 ASSERT.kind_of id, CSME::Identifier::Abstract
260 ASSERT.opt_kind_of opt_fields, ::Array
261
262 super(loc)
263
264 @id = id
265 @opt_fields = opt_fields
266 end
267
268
269 def to_s
270 body = if self.opt_fields
271 fields = self.opt_fields
272
273 format " { %s }", fields.map(&:to_s).join(' ')
274 else
275 ''
276 end
277
278 format "%%IMPORT %s%s", self.id.to_s, body
279 end
280
281
282 def pretty_print(q)
283 q.text '%IMPORT '
284 q.text self.id.to_s
285
286 if self.opt_fields
287 PRT.group_for_enum(
288 q, self.opt_fields, bb:' {', eb:'}', sep:' '
289 ) do |field| q.pp field end
290 end
291 end
292
293
294 def exported_vars
295 [].freeze
296 end
297
298
299 private
300
301 def __desugar__(env, event)
302 new_env = env.enter event
303
304 result = if self.opt_fields
305 fields = self.opt_fields
306
307 decls = fields.inject([]) { |array, field|
308 ASSERT.kind_of field, Fields::Abstract
309
310 array + field.desugar_field(new_env, self.id)
311 }
312
313 ASCD.make_seq_of_declaration self.loc, decls
314 else
315 ASCD.make_import self.loc, self.id.desugar(new_env)
316 end
317
318 ASSERT.kind_of result, ASCD::Abstract
319 end
320 end
321
322 end # Umu::ConcreteSyntax::Module::Declaration::Import
323
324
325
326 class Core < Abstract
327 attr_reader :core_decl
328
329
330 def initialize(loc, core_decl)
331 ASSERT.kind_of core_decl, CSCD::Abstract
332
333 super(loc)
334
335 @core_decl = core_decl
336 end
337
338
339 def to_s
340 self.core_decl.to_s
341 end
342
343
344 def pretty_print(q)
345 q.pp self.core_decl
346 end
347
348
349 def exported_vars
350 self.core_decl.exported_vars
351 end
352
353
354 private
355
356 def __desugar__(env, event)
357 self.core_decl.desugar env.enter(event)
358 end
359 end
360
361
362
363 module_function
364
365 def make_structure(loc, pat, expr, local_decls)
366 ASSERT.kind_of pat, CSMP::Abstract
367 ASSERT.kind_of expr, CSME::Abstract
368 ASSERT.kind_of local_decls, ::Array
369
370 Structure.new(loc, pat, expr, local_decls.freeze).freeze
371 end
372
373
374 def make_import(loc, id, opt_fields)
375 ASSERT.kind_of id, CSME::Identifier::Abstract
376 ASSERT.opt_kind_of opt_fields, ::Array
377
378 Import::Entry.new(loc, id, opt_fields.freeze).freeze
379 end
380
381
382 def make_value_fields_of_import(loc, atomic_fields)
383 ASSERT.kind_of atomic_fields, ::Array
384
385 Import::Fields::Value.new(loc, atomic_fields.freeze).freeze
386 end
387
388
389 def make_function_fields_of_import(loc, atomic_fields)
390 ASSERT.kind_of atomic_fields, ::Array
391
392 Import::Fields::Function.new(loc, atomic_fields.freeze).freeze
393 end
394
395
396 def make_structure_fields_of_import(loc, atomic_fields)
397 ASSERT.kind_of atomic_fields, ::Array
398
399 Import::Fields::Structure.new(loc, atomic_fields.freeze).freeze
400 end
401
402
403 def make_core(loc, core_decl)
404 ASSERT.kind_of core_decl, CSCD::Abstract
405
406 Core.new(loc, core_decl).freeze
407 end
408
409 end # Umu::ConcreteSyntax::Module::Declaration
410
411 end # Umu::ConcreteSyntax::Module
412
413 end # Umu::ConcreteSyntax
414
415 end # Umu