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 Binary
15
16 module Product
17
18 module Operator
19
20 module Abstraction
21
22 class Abstract < Umu::Abstraction::Model
23 def apply(_value, _env, _event)
24 raise X::InternalSubclassResponsibility
25 end
26 end
27
28
29
30 class Selector < Abstract
31 attr_reader :sel
32
33
34 def initialize(loc, sel)
35 ASSERT.kind_of sel, ::Object # Polymopic
36
37 super(loc)
38
39 @sel = sel
40 end
41 end
42
43 end # Umu::AbstractSyntax::Core::Expression::Binary::Product::Operator::Abstraction
44
45
46
47 class ByNumber < Abstraction::Selector
48 alias sel_num sel
49
50
51 def initialize(loc, sel_num)
52 ASSERT.kind_of sel_num, ::Integer
53
54 super
55 end
56
57
58 def to_s
59 '$' + self.sel_num.to_s
60 end
61
62
63 def pretty_print(q)
64 q.text format("$%d", self.sel_num)
65 end
66
67
68 def apply(value, env, _event)
69 ASSERT.kind_of value, VC::Top
70 ASSERT.kind_of env, E::Entry
71
72 unless value.kind_of? VCP::Abstract
73 raise X::TypeError.new(
74 self.loc,
75 env,
76 "Selection operator '$' require a Product, but %s : %s",
77 value.to_s,
78 value.type_sym.to_s
79 )
80 end
81
82 result = value.select_by_number self.sel_num, self.loc, env
83 ASSERT.kind_of result, VC::Top
84 end
85 end
86
87
88
89 class ByLabel < Abstraction::Selector
90 alias sel_sym sel
91
92 def initialize(loc, sel_sym)
93 ASSERT.kind_of sel_sym, ::Symbol
94
95 super
96 end
97
98
99 def to_s
100 '$' + self.sel_sym.to_s
101 end
102
103
104 def pretty_print(q)
105 q.text format("$%s", self.sel_sym.to_s)
106 end
107
108
109 def apply(value, env, _event)
110 ASSERT.kind_of value, VC::Top
111 ASSERT.kind_of env, E::Entry
112
113 unless value.kind_of? VCP::Named
114 raise X::TypeError.new(
115 self.loc,
116 env,
117 "Selection operator '$' require a Named, but %s : %s",
118 value.to_s,
119 value.type_sym.to_s
120 )
121 end
122
123 result = value.select_by_label self.sel_sym, self.loc, env
124 ASSERT.kind_of result, VC::Top
125 end
126 end
127
128
129
130 class Modifier < Abstraction::Selector
131 alias expr_by_label sel
132
133 def initialize(loc, expr_by_label)
134 ASSERT.kind_of expr_by_label, ::Hash
135
136 super
137 end
138
139
140 def to_s
141 format("$(%s)",
142 self.expr_by_label.map { |label, expr|
143 format "%s %s", label.to_s, expr.to_s
144 }.join(', ')
145 )
146 end
147
148
149 def pretty_print(q)
150 PRT.group_for_enum(
151 q, self.expr_by_label, bb:'$(', eb:')', join:' '
152 ) do |label, expr|
153
154 q.text label.to_s
155 q.pp expr
156 end
157 end
158
159
160 def apply(value, env, event)
161 ASSERT.kind_of value, VC::Top
162
163 unless value.kind_of? VCP::Named
164 raise X::TypeError.new(
165 self.loc,
166 env,
167 "Modifier operator '$(..)' require a Named, but %s : %s",
168 value.to_s,
169 value.type_sym.to_s
170 )
171 end
172
173 new_env = env.enter event
174 value_by_label = self.expr_by_label.inject({}) {
175 |hash, (label, expr)|
176 ASSERT.kind_of hash, ::Hash
177 ASSERT.kind_of label, ASCEU::Container::Named::Label
178 ASSERT.kind_of expr, ASCE::Abstract
179
180 result = expr.evaluate new_env
181 ASSERT.kind_of result, ASR::Value
182
183 hash.merge(label.sym => result.value) { |lab, _, _|
184 ASSERT.abort "No case - label: $s", lab.to_s
185 }
186 }
187
188 result = value.modify value_by_label, self.loc, env
189 ASSERT.kind_of result, VC::Top
190 end
191 end
192
193 end # Umu::AbstractSyntax::Core::Expression::Binary::Product::Operator
194
195
196
197 class Entry < Binary::Abstract
198 alias rhs_head_operator rhs
199 attr_reader :rhs_tail_operators
200 attr_reader :opt_operand_type_sym
201
202
203 def initialize(
204 loc, lhs_expr,
205 rhs_head_operator, rhs_tail_operators,
206 opt_operand_type_sym
207 )
208 ASSERT.kind_of lhs_expr, ASCE::Abstract
209 ASSERT.kind_of rhs_head_operator,
210 Binary::Product::Operator::Abstraction::Abstract
211 ASSERT.kind_of rhs_tail_operators, ::Array
212 ASSERT.opt_kind_of opt_operand_type_sym, ::Symbol
213
214 super(loc, lhs_expr, rhs_head_operator)
215
216 @rhs_tail_operators = rhs_tail_operators
217 @opt_operand_type_sym = opt_operand_type_sym
218 end
219
220
221 def rhs_operators
222 [self.rhs_head_operator] + self.rhs_tail_operators
223 end
224
225
226 def to_s
227 format("(%s%s)%s",
228 self.lhs_expr.to_s,
229
230 if self.opt_operand_type_sym
231 format " : %s", self.opt_operand_type_sym.to_s
232 else
233 ''
234 end,
235
236 self.rhs_operators.map(&:to_s).join
237 )
238 end
239
240
241 def pretty_print(q)
242 PRT.group q, bb:'(', eb:')' do
243 q.pp lhs_expr
244 if self.opt_operand_type_sym
245 q.text format(" : %s", self.opt_operand_type_sym.to_s)
246 end
247 end
248
249 PRT.group_for_enum q, self.rhs_operators
250 end
251
252
253 private
254
255 def __evaluate__(env, event)
256 ASSERT.kind_of env, E::Entry
257 ASSERT.kind_of event, E::Tracer::Event
258
259 new_env = env.enter event
260
261 lhs_result = self.lhs_expr.evaluate new_env
262 ASSERT.kind_of lhs_result, ASR::Value
263 init_operand = lhs_result.value
264
265 if self.opt_operand_type_sym
266 operand_type_sym = opt_operand_type_sym
267
268 operand_signat = new_env.ty_lookup operand_type_sym, self.loc
269 ASSERT.kind_of operand_signat, ECTSC::Base
270 unless env.ty_kind_of?(init_operand, operand_signat)
271 raise X::TypeError.new(
272 self.loc,
273 env,
274 "Expected a %s, but %s : %s",
275 operand_type_sym,
276 init_operand,
277 init_operand.type_sym
278 )
279 end
280 end
281
282 final_operand = self.rhs_operators.inject(init_operand) {
283 |operand, operator|
284 ASSERT.kind_of operand, VC::Top
285 ASSERT.kind_of operator, Operator::Abstraction::Abstract
286
287 operator.apply operand, new_env, event
288 }
289 ASSERT.kind_of final_operand, VC::Top
290 end
291 end
292
293 end # Umu::AbstractSyntax::Core::Expression::Binary::Product
294
295 end # Umu::AbstractSyntax::Core::Expression::Binary
296
297
298 module_function
299 def make_number_selector(loc, sel_num)
300 ASSERT.kind_of loc, LOC::Entry
301 ASSERT.kind_of sel_num, ::Integer
302
303 Binary::Product::Operator::ByNumber.new(loc, sel_num).freeze
304 end
305
306
307 def make_label_selector(loc, sel_sym)
308 ASSERT.kind_of loc, LOC::Entry
309 ASSERT.kind_of sel_sym, ::Symbol
310
311 Binary::Product::Operator::ByLabel.new(loc, sel_sym).freeze
312 end
313
314
315 def make_modifier(loc, expr_by_label)
316 ASSERT.kind_of loc, LOC::Entry
317 ASSERT.kind_of expr_by_label, ::Hash
318
319 Binary::Product::Operator::Modifier.new(loc, expr_by_label).freeze
320 end
321
322
323 def make_product(
324 loc, lhs_expr,
325 rhs_head_operator, rhs_tail_operators = [],
326 opt_operand_type_sym = nil
327 )
328 ASSERT.kind_of loc, LOC::Entry
329 ASSERT.kind_of lhs_expr, ASCE::Abstract
330 ASSERT.kind_of rhs_head_operator,
331 Binary::Product::Operator::Abstraction::Abstract
332 ASSERT.kind_of rhs_tail_operators, ::Array
333 ASSERT.opt_kind_of opt_operand_type_sym, ::Symbol
334
335 Binary::Product::Entry.new(
336 loc, lhs_expr, rhs_head_operator, rhs_tail_operators.freeze,
337 opt_operand_type_sym
338 ).freeze
339 end
340
341 end # Umu::AbstractSyntax::Core::Expression
342
343 end # Umu::AbstractSyntax::Core
344
345 end # Umu::AbstractSyntax
346
347 end # Umu