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 Product
17
18 module Operator
19
20 class Abstract < Expression::Abstract; end
21
22
23
24 class NumberSelector < Abstract
25 attr_reader :sel_num
26
27
28 def initialize(loc, sel_num)
29 ASSERT.kind_of sel_num, ::Integer
30
31 super(loc)
32
33 @sel_num = sel_num
34 end
35
36
37 def to_s
38 '$' + self.sel_num.to_s
39 end
40
41
42 private
43
44 def __desugar__(_env, _event)
45 ASCE.make_number_selector self.loc, self.sel_num
46 end
47 end
48
49
50
51 class LabelSelector < Abstract
52 attr_reader :sel_sym
53
54
55 def initialize(loc, sel_sym)
56 ASSERT.kind_of sel_sym, ::Symbol
57
58 super(loc)
59
60 @sel_sym = sel_sym
61 end
62
63
64 def to_s
65 '$' + self.sel_sym.to_s
66 end
67
68
69 private
70
71 def __desugar__(_env, _event)
72 ASCE.make_label_selector self.loc, self.sel_sym
73 end
74 end
75
76
77
78 class Modifier < Abstract
79 attr_reader :fields
80
81
82 def initialize(loc, fields)
83 ASSERT.kind_of fields, ::Array
84
85 super(loc)
86
87 @fields = fields
88 end
89
90
91 def to_s
92 format("$(%s)",
93 self.fields.map { |label, opt_expr|
94 format("%s%s",
95 label.to_s,
96
97 if opt_expr
98 ' ' + opt_expr.to_s
99 else
100 ''
101 end
102 )
103 }.join(', ')
104 )
105 end
106
107
108 def pretty_print(q)
109 PRT.group_for_enum q, self.fields, bb:'$(', eb:')', join:' ' do
110 |label, opt_expr|
111
112 q.text label.to_s
113 if opt_expr
114 q.pp opt_expr
115 end
116 end
117 end
118
119
120 private
121
122 def __desugar__(env, event)
123 expr_by_label = self.fields.inject({}) { |hash, (label, opt_expr)|
124 ASSERT.kind_of label, CSCEU::Container::Named::Label
125 ASSERT.opt_kind_of opt_expr, CSCE::Abstract
126
127 expr = if opt_expr
128 opt_expr
129 else
130 CSCE.make_identifier label.loc, label.sym
131 end
132
133 new_env = env.enter event
134 hash.merge(label.desugar(new_env) => expr.desugar(new_env)) {
135 raise X::SyntaxError.new(
136 label.loc,
137 format("In modifier of named tuple, " +
138 "duplicated label: '%s'",
139 label.to_s
140 )
141 )
142 }
143 }.freeze
144
145 ASCE.make_modifier self.loc, expr_by_label
146 end
147 end
148
149 end # Umu::ConcreteSyntax::Core::Expression::Binary::Product::Operator
150
151
152
153 class Entry < Binary::Abstract
154 alias lhs_expr lhs
155 alias rhs_head_opr rhs
156 attr_reader :rhs_tail_oprs
157
158
159 def initialize(loc, lhs_expr, rhs_head_opr, rhs_tail_oprs)
160 ASSERT.kind_of lhs_expr, CSCE::Abstract
161 ASSERT.kind_of rhs_head_opr, Operator::Abstract
162 ASSERT.kind_of rhs_tail_oprs, ::Array
163
164 super(loc, lhs_expr, rhs_head_opr)
165
166 @rhs_tail_oprs = rhs_tail_oprs
167 end
168
169
170 def to_s
171 format("(%s)%s",
172 self.lhs_expr.to_s,
173 self.rhs_oprs.map(&:to_s).join
174 )
175 end
176
177
178 def pretty_print(q)
179 PRT.group q, bb:'(', eb:')' do
180 q.pp self.lhs_expr
181 end
182
183 PRT.group_for_enum q, self.rhs_oprs
184 end
185
186
187 def rhs_oprs
188 [self.rhs_head_opr] + self.rhs_tail_oprs
189 end
190
191
192 private
193
194 def __desugar__(env, event)
195 new_env = env.enter event
196
197 ASCE.make_product(
198 self.loc,
199 self.lhs_expr.desugar(new_env),
200 self.rhs_head_opr.desugar(new_env),
201 self.rhs_tail_oprs.map { |mess|
202 ASSERT.kind_of mess, Operator::Abstract
203
204 mess.desugar(new_env)
205 }
206 )
207 end
208 end
209
210 end # Umu::ConcreteSyntax::Core::Expression::Binary::Product
211
212 end # Umu::ConcreteSyntax::Core::Expression::Binary
213
214
215 module_function
216
217 def make_number_selector(loc, sel_num)
218 ASSERT.kind_of loc, LOC::Entry
219 ASSERT.kind_of sel_num, ::Integer
220
221 Binary::Product::Operator::NumberSelector.new(loc, sel_num).freeze
222 end
223
224
225 def make_label_selector(loc, sel_sym)
226 ASSERT.kind_of loc, LOC::Entry
227 ASSERT.kind_of sel_sym, ::Symbol
228
229 Binary::Product::Operator::LabelSelector.new(loc, sel_sym).freeze
230 end
231
232
233 def make_modifier(loc, fields)
234 ASSERT.kind_of loc, LOC::Entry
235 ASSERT.kind_of fields, ::Array
236
237 Binary::Product::Operator::Modifier.new(loc, fields.freeze).freeze
238 end
239
240
241 def make_product(loc, lhs_expr, rhs_head_opr, rhs_tail_oprs = [])
242 ASSERT.kind_of loc, LOC::Entry
243 ASSERT.kind_of lhs_expr, CSCE::Abstract
244 ASSERT.kind_of rhs_head_opr, Binary::Product::Operator::Abstract
245 ASSERT.kind_of rhs_tail_oprs, ::Array
246
247 Binary::Product::Entry.new(
248 loc, lhs_expr, rhs_head_opr, rhs_tail_oprs.freeze
249 ).freeze
250 end
251
252 end # Umu::ConcreteSyntax::Core::Expression
253
254 end # Umu::ConcreteSyntax::Core
255
256 end # Umu::ConcreteSyntax
257
258 end # Umu