1 # coding: utf-8
2 # frozen_string_literal: true
3
4
5
6 module Umu
7
8 module Environment
9
10 class Entry < Abstraction::Record
11 attr_reader :ty_context
12 attr_reader :va_context
13 attr_reader :pref
14 attr_reader :trace_stack
15 attr_reader :sources
16
17
18 def self.deconstruct_keys
19 {
20 ty_context: ECT::Entry,
21 va_context: ECV::Abstract,
22 pref: Preference,
23 trace_stack: Tracer::Stack::Abstract,
24 sources: ::Hash
25 }.freeze
26 end
27
28
29 def initialize(ty_context, va_context, pref, trace_stack, sources)
30 ASSERT.kind_of ty_context, ECT::Entry
31 ASSERT.kind_of va_context, ECV::Abstract
32 ASSERT.kind_of pref, Preference
33 ASSERT.kind_of trace_stack, Tracer::Stack::Abstract
34 ASSERT.kind_of sources, ::Hash
35
36 @ty_context = ty_context
37 @va_context = va_context
38 @pref = pref
39 @trace_stack = trace_stack
40 @sources = sources
41 end
42
43
44 def to_s
45 '#<env>'
46 end
47
48
49 def ty_class_signat_of(value)
50 ASSERT.kind_of value, VC::Top
51
52 ASSERT.kind_of self.ty_context.class_signat_of(value),
53 ECTSC::Abstract
54 end
55
56
57 def ty_signat_of_class(klass)
58 ASSERT.subclass_of klass, VC::Top
59
60 ASSERT.kind_of self.ty_context.signat_of_class(klass), ECTSC::Base
61 end
62
63
64 def ty_lookup(sym, loc)
65 ASSERT.kind_of sym, ::Symbol
66 ASSERT.kind_of loc, LOC::Entry
67
68 ASSERT.kind_of self.ty_context.lookup(sym, loc, self), ECTSC::Base
69 end
70
71
72 def ty_kind_of?(lhs_value, rhs_signat)
73 ASSERT.kind_of lhs_value, VC::Top
74 ASSERT.kind_of rhs_signat, ECTSC::Base
75
76 ASSERT.bool self.ty_context.test_kind_of?(lhs_value, rhs_signat)
77 end
78
79
80 def va_lookup(sym, loc)
81 ASSERT.kind_of sym, ::Symbol
82 ASSERT.kind_of loc, LOC::Entry
83
84 self.va_context.lookup sym, loc, self
85 end
86
87
88 def va_get_bindings
89 self.va_context.get_bindings
90 end
91
92
93 def va_get_bindings_difference_with(other)
94 ASSERT.kind_of other, E::Entry
95
96 self.va_context.get_bindings_difference_with other.va_context
97 end
98
99
100 def va_extend_value(sym, value)
101 ASSERT.kind_of sym, ::Symbol
102 ASSERT.kind_of value, VC::Top
103
104
105 self.update_va_context(
106 self.va_context.extend(sym, ECV.make_value_target(value))
107 )
108 end
109
110
111 def va_extend_values(value_by_sym)
112 ASSERT.kind_of value_by_sym, ::Hash
113
114 self.update_va_context(
115 value_by_sym.inject(self.va_context) { |ctx, (sym, value)|
116 ASSERT.kind_of sym, ::Symbol
117 ASSERT.kind_of value, VC::Top
118
119 ctx.extend(sym, ECV.make_value_target(value))
120 }
121 )
122 end
123
124
125 def va_extend_recursive(sym, lam_expr)
126 ASSERT.kind_of sym, ::Symbol
127 ASSERT.kind_of lam_expr, ASCEN::Lambda::Entry
128
129
130 self.update_va_context(
131 self.va_context.extend(
132 sym,
133 ECV.make_recursive_target(lam_expr)
134 )
135 )
136 end
137
138
139 def va_extend_bindings(bindings)
140 ASSERT.kind_of bindings, ::Hash
141
142
143 self.update_va_context(
144 self.va_context.extend_bindings(bindings)
145 )
146 end
147
148
149 def update_va_context(va_context)
150 ASSERT.kind_of va_context, ECV::Abstract
151
152 self.update(va_context: va_context)
153 end
154
155
156 def update_trace_mode(bool)
157 ASSERT.bool bool
158
159 self.update_preference(
160 self.pref.update_trace_mode(bool)
161 )
162 end
163
164
165 def update_lex_trace_mode(bool)
166 ASSERT.bool bool
167
168 self.update_preference(
169 self.pref.update_lex_trace_mode(bool)
170 )
171 end
172
173
174 def update_dump_mode(bool)
175 ASSERT.bool bool
176
177 self.update_preference(
178 self.pref.update_dump_mode(bool)
179 )
180 end
181
182
183 def update_preference(pref)
184 ASSERT.kind_of pref, Preference
185
186 self.update(pref: pref)
187 end
188
189
190 def enter(event)
191 ASSERT.kind_of event, Tracer::Event
192
193 __update_trace_stack__ self.trace_stack.push(event)
194 end
195
196
197 def leave
198 __update_trace_stack__ self.trace_stack.pop
199 end
200
201
202 def update_line(file_name, line_num, line)
203
204 source = self.sources[file_name] || {}
205
206 __update_sources__(
207 self.sources.merge(
208 file_name => source.merge(line_num => line.freeze)
209 ).freeze
210 )
211 end
212
213
214 def update_source(file_name, text, start_line_num = 0)
215 ASSERT.kind_of file_name, ::String
216 ASSERT.kind_of text, ::String
217 ASSERT.kind_of start_line_num, ::Integer
218
219 source, _ = text.each_line.inject([{}, start_line_num]) {
220 |(sources, line_num), line|
221
222 [
223 sources.merge(line_num => line.chomp.freeze),
224 line_num + 1
225 ]
226 }
227
228 __update_sources__(
229 self.sources.merge(file_name => source.freeze).freeze
230 )
231 end
232
233
234 def print_backtrace
235 self.trace_stack.reverse_each.inject(LOC.make_initial_location) do
236 |last_loc, event|
237
238 current_loc = event.loc
239 =begin
240 STDERR.printf("* current_loc: %s, last_loc: %s\n",
241 current_loc.to_s, last_loc.to_s
242 )
243 =end
244 if current_loc != last_loc
245 opt_line = __lookup_line_at__ current_loc
246 if opt_line
247 STDERR.printf("\n%s:#%d>%s\n",
248 current_loc.file_name,
249 current_loc.line_num + 1,
250 opt_line
251 )
252 end
253 end
254
255 if self.pref.trace_mode?
256 STDERR.puts event.to_s
257 end
258
259 current_loc
260 end
261 end
262
263
264 private
265
266 def __update_trace_stack__(stack)
267 ASSERT.kind_of stack, Tracer::Stack::Abstract
268
269 self.update(trace_stack: stack)
270 end
271
272
273 def __update_sources__(sources)
274 ASSERT.kind_of sources, ::Hash
275
276 self.update(sources: sources)
277 end
278
279
280 def __lookup_line_at__(loc)
281 ASSERT.kind_of loc, LOC::Entry
282
283 opt_source = self.sources[loc.file_name]
284 if opt_source
285 opt_source[loc.line_num]
286 else
287 nil
288 end
289 end
290 end
291
292
293
294 module_function
295
296 def setup(pref)
297 ASSERT.kind_of pref, Preference
298
299 make_entry(
300 ECT.make,
301 ECV.make_initial,
302 pref,
303 Tracer::Stack.empty,
304 {}.freeze
305 )
306 end
307
308
309 def make_entry(ty_context, va_context, pref, trace_stack, sources)
310 ASSERT.kind_of ty_context, ECT::Entry
311 ASSERT.kind_of va_context, ECV::Abstract
312 ASSERT.kind_of pref, Preference
313 ASSERT.kind_of trace_stack, Tracer::Stack::Abstract
314 ASSERT.kind_of sources, ::Hash
315
316 Entry.new(ty_context, va_context, pref, trace_stack, sources).freeze
317 end
318 end # Umu::Environment
319
320 end # Umu