Class: Duby::Typer::Simple
Direct Known Subclasses
JVM
Constant Summary
Constants included
from Duby
Duby::TransformError, VERSION
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#alias_type(short, long) ⇒ Object
-
#boolean_type ⇒ Object
-
#cycle(count) ⇒ Object
-
#cycling=(c) ⇒ Object
-
#cycling? ⇒ Boolean
-
#default_type ⇒ Object
-
#defer(node) ⇒ Object
-
#deferred_nodes ⇒ Object
-
#define_type(name, superclass, interfaces) ⇒ Object
-
#error(node, error_or_msg = nil, backtrace = nil) ⇒ Object
-
#field_type(cls, name) ⇒ Object
-
#field_type_hash(cls) ⇒ Object
-
#field_types ⇒ Object
-
#fixnum_type ⇒ Object
-
#float_type ⇒ Object
-
#get_method_type_hash(target_type, name, parameter_types) ⇒ Object
-
#infer(node) ⇒ Object
-
#infer_signature(method_def) ⇒ Object
-
#initialize(self_type) ⇒ Simple
constructor
A new instance of Simple.
-
#learn_field_type(cls, name, type) ⇒ Object
-
#learn_local_type(scope, name, type) ⇒ Object
-
#learn_method_type(target_type, name, parameter_types, type, exceptions) ⇒ Object
-
#local_type(scope, name) ⇒ Object
-
#local_type_hash(scope) ⇒ Object
-
#local_types ⇒ Object
-
#method_type(target_type, name, parameter_types) ⇒ Object
-
#method_types ⇒ Object
-
#name ⇒ Object
-
#no_type ⇒ Object
-
#null_type ⇒ Object
-
#plugins ⇒ Object
-
#resolve(raise = false) ⇒ Object
-
#self_type ⇒ Object
-
#string_type ⇒ Object
-
#type_definition(name, superclass, interfaces) ⇒ Object
-
#type_reference(name, array = false, meta = false) ⇒ Object
Methods inherited from BaseTyper
#log, #to_s
Methods included from Duby
compile, parse, run, typer_plugins
Constructor Details
#initialize(self_type) ⇒ Simple
Returns a new instance of Simple.
35
36
37
38
39
40
41
42
43
44
|
# File 'lib/duby/typer.rb', line 35
def initialize(self_type)
@known_types = {}
@known_types["self"] = type_reference(self_type)
@known_types["fixnum"] = type_reference("fixnum")
@known_types["float"] = type_reference("float")
@known_types["string"] = type_reference("string")
@known_types["boolean"] = type_reference("boolean")
@errors = []
end
|
Instance Attribute Details
Returns the value of attribute errors.
33
34
35
|
# File 'lib/duby/typer.rb', line 33
def errors
@errors
end
|
#known_types ⇒ Object
Returns the value of attribute known_types.
33
34
35
|
# File 'lib/duby/typer.rb', line 33
def known_types
@known_types
end
|
Instance Method Details
#alias_type(short, long) ⇒ Object
244
245
246
247
|
# File 'lib/duby/typer.rb', line 244
def alias_type(short, long)
@known_types[type_reference(short, false, false)] = type_reference(long, false, false)
@known_types[type_reference(short, false, true)] = type_reference(long, false, true)
end
|
#boolean_type ⇒ Object
70
71
72
|
# File 'lib/duby/typer.rb', line 70
def boolean_type
known_types["boolean"]
end
|
#cycle(count) ⇒ Object
206
207
208
209
210
211
212
213
214
215
216
217
218
|
# File 'lib/duby/typer.rb', line 206
def cycle(count)
@cycling = true
count.times do |i|
begin
log "[Cycle #{i}]: Started..."
yield i
ensure
log "[Cycle #{i}]: Complete!"
end
end
ensure
@cycling = false
end
|
#cycling=(c) ⇒ Object
202
203
204
|
# File 'lib/duby/typer.rb', line 202
def cycling=(c)
@cycling = c
end
|
#cycling? ⇒ Boolean
198
199
200
|
# File 'lib/duby/typer.rb', line 198
def cycling?
@cycling
end
|
#default_type ⇒ Object
54
55
56
|
# File 'lib/duby/typer.rb', line 54
def default_type
nil
end
|
#defer(node) ⇒ Object
279
280
281
282
283
284
285
286
287
288
289
290
|
# File 'lib/duby/typer.rb', line 279
def defer(node)
if @error_next
log "Marking #{node} as an error"
@error_next = false
error(node)
else
return if deferred_nodes.include? node
log "Deferring inference for #{node}"
deferred_nodes << node
end
end
|
#deferred_nodes ⇒ Object
249
250
251
|
# File 'lib/duby/typer.rb', line 249
def deferred_nodes
@deferred_nodes ||= []
end
|
#define_type(name, superclass, interfaces) ⇒ Object
82
83
84
85
86
87
88
89
90
91
|
# File 'lib/duby/typer.rb', line 82
def define_type(name, superclass, interfaces)
log "New type defined: '#{name}' < '#{superclass}'"
known_types[name] = type_definition(name, superclass, interfaces)
old_self, known_types["self"] = known_types["self"], known_types[name]
yield
known_types["self"] = old_self
known_types[name]
end
|
#error(node, error_or_msg = nil, backtrace = nil) ⇒ Object
264
265
266
267
268
269
270
271
272
273
274
275
276
277
|
# File 'lib/duby/typer.rb', line 264
def error(node, error_or_msg=nil, backtrace=nil)
if error_or_msg.kind_of? InferenceError
error = error_or_msg
elsif error_or_msg
error = InferenceError.new(error_or_msg, node)
error.set_backtrace(backtrace) if backtrace
else
error = InferenceError.new("Unable to infer type.", node)
end
@errors << error
node.resolve_if(self) do
AST.error_type
end
end
|
#field_type(cls, name) ⇒ Object
136
137
138
|
# File 'lib/duby/typer.rb', line 136
def field_type(cls, name)
field_type_hash(cls)[name]
end
|
#field_type_hash(cls) ⇒ Object
120
121
122
|
# File 'lib/duby/typer.rb', line 120
def field_type_hash(cls)
field_types[cls] ||= {}
end
|
#field_types ⇒ Object
116
117
118
|
# File 'lib/duby/typer.rb', line 116
def field_types
@field_types ||= {}
end
|
#fixnum_type ⇒ Object
58
59
60
|
# File 'lib/duby/typer.rb', line 58
def fixnum_type
known_types["fixnum"]
end
|
#float_type ⇒ Object
62
63
64
|
# File 'lib/duby/typer.rb', line 62
def float_type
known_types["float"]
end
|
#get_method_type_hash(target_type, name, parameter_types) ⇒ Object
224
225
226
227
228
229
230
231
232
233
234
|
# File 'lib/duby/typer.rb', line 224
def get_method_type_hash(target_type, name, parameter_types)
method_types[target_type] ||= {}
method_types[target_type][name] ||= {}
method_types[target_type][name][parameter_types.size] ||= {}
current = method_types[target_type][name][parameter_types.size]
parameter_types.each {|type| current[type] ||= {}; current = current[type]}
current
end
|
#infer(node) ⇒ Object
253
254
255
256
257
258
259
260
261
262
|
# File 'lib/duby/typer.rb', line 253
def infer(node)
begin
node.infer(self)
rescue InferenceError => ex
ex.node ||= node
error(node, ex)
rescue Exception => ex
error(node, ex.message, ex.backtrace)
end
end
|
#infer_signature(method_def) ⇒ Object
124
125
|
# File 'lib/duby/typer.rb', line 124
def infer_signature(method_def)
end
|
#learn_field_type(cls, name, type) ⇒ Object
127
128
129
130
131
132
133
134
|
# File 'lib/duby/typer.rb', line 127
def learn_field_type(cls, name, type)
log "Learned field type under #{cls} : #{name} = #{type}"
field_type_hash(cls)[name] ||= known_types[type] || type
type
end
|
#learn_local_type(scope, name, type) ⇒ Object
93
94
95
96
97
98
99
100
|
# File 'lib/duby/typer.rb', line 93
def learn_local_type(scope, name, type)
log "Learned local type under #{scope} : #{name} = #{type}"
local_type_hash(scope)[name] ||= known_types[type] || type
type
end
|
#learn_method_type(target_type, name, parameter_types, type, exceptions) ⇒ Object
140
141
142
143
144
145
146
147
148
|
# File 'lib/duby/typer.rb', line 140
def learn_method_type(target_type, name, parameter_types, type, exceptions)
log "Learned method #{name} (#{parameter_types}) on #{target_type} = #{type}"
get_method_type_hash(target_type, name, parameter_types)[:type] = known_types[type] || type
imported_types = parameter_types.map {|param| known_types[param] || param}
get_method_type_hash(target_type, name, imported_types)[:type] = type
end
|
#local_type(scope, name) ⇒ Object
102
103
104
105
106
|
# File 'lib/duby/typer.rb', line 102
def local_type(scope, name)
log "Retrieved local type in #{scope} : #{name} = #{local_type_hash(scope)[name]}"
local_type_hash(scope)[name]
end
|
#local_type_hash(scope) ⇒ Object
112
113
114
|
# File 'lib/duby/typer.rb', line 112
def local_type_hash(scope)
local_types[scope] ||= {}
end
|
#local_types ⇒ Object
108
109
110
|
# File 'lib/duby/typer.rb', line 108
def local_types
@local_types ||= {}
end
|
#method_type(target_type, name, parameter_types) ⇒ Object
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
# File 'lib/duby/typer.rb', line 150
def method_type(target_type, name, parameter_types)
if (target_type && target_type.error?) ||
parameter_types.any? {|t| t && t.error?}
return AST.error_type
end
constructor = (name == 'new' && target_type && target_type.meta?)
if constructor
simple_type = get_method_type_hash(target_type.unmeta, 'initialize', parameter_types)[:type]
else
simple_type = get_method_type_hash(target_type, name, parameter_types)[:type]
end
if !simple_type
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} not found."
simple_type = plugins do |plugin|
plugin.method_type(self, target_type, name, parameter_types)
end
end
return nil unless simple_type
if constructor
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} = #{target_type}"
target_type.unmeta
else
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} = #{simple_type}"
simple_type
end
end
|
#method_types ⇒ Object
220
221
222
|
# File 'lib/duby/typer.rb', line 220
def method_types
@method_types ||= {}
end
|
46
47
48
|
# File 'lib/duby/typer.rb', line 46
def name
"Simple"
end
|
185
186
187
188
189
190
191
192
193
194
195
196
|
# File 'lib/duby/typer.rb', line 185
def plugins
if cycling?
Duby.typer_plugins.each do |plugin|
log "Invoking plugin: #{plugin}"
result = yield plugin
return result if result
end
end
nil
end
|
#resolve(raise = false) ⇒ Object
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
|
# File 'lib/duby/typer.rb', line 292
def resolve(raise = false)
count = deferred_nodes.size + 1
log "Entering type inference cycle"
retried = false
cycle(count) do |i|
old_deferred = @deferred_nodes
@deferred_nodes = deferred_nodes.select do |node|
type = infer(node)
log "[Cycle #{i}]: Inferred type for #{node}: #{type || 'FAILED'}"
type == default_type
end
if @deferred_nodes.size == 0
log "[Cycle #{i}]: Resolved all types, exiting"
break
elsif old_deferred == @deferred_nodes
if @error_next || retried
log "[Cycle #{i}]: Made no progress, bailing out"
break
else
retried = true
@error_next = true
redo
end
end
retried = false
end
error_nodes = @errors.map {|e| e.node} + deferred_nodes
if raise && !error_nodes.empty?
msg = "Could not infer typing for nodes:"
error_nodes.map do |e|
msg << "\n "
msg << "#{e} at line #{e.line_number} (child of #{e.parent})"
end
raise InferenceError.new(msg)
end
end
|
#self_type ⇒ Object
50
51
52
|
# File 'lib/duby/typer.rb', line 50
def self_type
known_types["self"]
end
|
#string_type ⇒ Object
66
67
68
|
# File 'lib/duby/typer.rb', line 66
def string_type
known_types["string"]
end
|
#type_definition(name, superclass, interfaces) ⇒ Object
#type_reference(name, array = false, meta = false) ⇒ Object
236
237
238
|
# File 'lib/duby/typer.rb', line 236
def type_reference(name, array=false, meta=false)
AST::TypeReference.new(name, array, meta)
end
|