cast_off 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +578 -0
- data/README.en +256 -0
- data/bin/CastOff +145 -0
- data/cast_off.gemspec +25 -0
- data/ext/cast_off/cast_off.c.rb +1386 -0
- data/ext/cast_off/cast_off.h +24 -0
- data/ext/cast_off/depend +70 -0
- data/ext/cast_off/extconf.rb +19 -0
- data/ext/cast_off/generated_c_include/inline_api.h +507 -0
- data/ext/cast_off/generated_c_include/iter_api.h +595 -0
- data/ext/cast_off/generated_c_include/unbox_api.h.rb +76 -0
- data/ext/cast_off/generated_c_include/vm_api.h +751 -0
- data/ext/cast_off/ruby_source/atomic.h +56 -0
- data/ext/cast_off/ruby_source/constant.h +34 -0
- data/ext/cast_off/ruby_source/debug.h +41 -0
- data/ext/cast_off/ruby_source/eval_intern.h +234 -0
- data/ext/cast_off/ruby_source/gc.h +98 -0
- data/ext/cast_off/ruby_source/id.h +175 -0
- data/ext/cast_off/ruby_source/insns.inc +179 -0
- data/ext/cast_off/ruby_source/insns_info.inc +695 -0
- data/ext/cast_off/ruby_source/internal.h +227 -0
- data/ext/cast_off/ruby_source/iseq.h +125 -0
- data/ext/cast_off/ruby_source/manual_update.h +135 -0
- data/ext/cast_off/ruby_source/method.h +105 -0
- data/ext/cast_off/ruby_source/node.h +503 -0
- data/ext/cast_off/ruby_source/thread_pthread.h +51 -0
- data/ext/cast_off/ruby_source/thread_win32.h +40 -0
- data/ext/cast_off/ruby_source/vm_core.h +756 -0
- data/ext/cast_off/ruby_source/vm_exec.h +184 -0
- data/ext/cast_off/ruby_source/vm_insnhelper.c +1748 -0
- data/ext/cast_off/ruby_source/vm_insnhelper.h +220 -0
- data/ext/cast_off/ruby_source/vm_opts.h +51 -0
- data/lib/cast_off.rb +15 -0
- data/lib/cast_off/compile.rb +629 -0
- data/lib/cast_off/compile/basicblock.rb +144 -0
- data/lib/cast_off/compile/cfg.rb +391 -0
- data/lib/cast_off/compile/code_manager.rb +284 -0
- data/lib/cast_off/compile/configuration.rb +2368 -0
- data/lib/cast_off/compile/dependency.rb +240 -0
- data/lib/cast_off/compile/information.rb +775 -0
- data/lib/cast_off/compile/instruction.rb +446 -0
- data/lib/cast_off/compile/ir/call_ir.rb +2348 -0
- data/lib/cast_off/compile/ir/guard_ir.rb +423 -0
- data/lib/cast_off/compile/ir/jump_ir.rb +223 -0
- data/lib/cast_off/compile/ir/operand.rb +934 -0
- data/lib/cast_off/compile/ir/param_ir.rb +98 -0
- data/lib/cast_off/compile/ir/return_ir.rb +92 -0
- data/lib/cast_off/compile/ir/simple_ir.rb +808 -0
- data/lib/cast_off/compile/ir/sub_ir.rb +212 -0
- data/lib/cast_off/compile/iseq.rb +454 -0
- data/lib/cast_off/compile/method_information.rb +1384 -0
- data/lib/cast_off/compile/namespace/namespace.rb +556 -0
- data/lib/cast_off/compile/namespace/uuid.rb +323 -0
- data/lib/cast_off/compile/stack.rb +65 -0
- data/lib/cast_off/compile/translator.rb +1562 -0
- data/lib/cast_off/suggestion.rb +98 -0
- data/lib/cast_off/util.rb +58 -0
- metadata +107 -0
@@ -0,0 +1,934 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
|
3
|
+
module CastOff::Compiler
|
4
|
+
module SimpleIR
|
5
|
+
class TypeContainer
|
6
|
+
include CastOff::Util
|
7
|
+
|
8
|
+
undef_method(:==)
|
9
|
+
undef_method(:eql?)
|
10
|
+
undef_method(:hash)
|
11
|
+
undef_method(:to_s)
|
12
|
+
|
13
|
+
attr_reader :types, :state
|
14
|
+
# state = :undefined || :initialized || :dynamic || :static
|
15
|
+
|
16
|
+
# undefined は、何と交わっても、交わった相手の状態に変わる
|
17
|
+
# initialized は、dynamic と交わったときのみ、相手の状態に変わる
|
18
|
+
# dynamic は、何と交わっても dynamic のまま
|
19
|
+
# static は、何と交わっても static のまま
|
20
|
+
|
21
|
+
# ignore に入っていたら @types に加えない
|
22
|
+
# annotation に入っていたら dynamic にするときに、annotation で指定された型にする, ignore に含まれているものは加えない
|
23
|
+
|
24
|
+
def initialize()
|
25
|
+
@types = []
|
26
|
+
@state = :undefined
|
27
|
+
@annotation = []
|
28
|
+
@ignore = []
|
29
|
+
@unboxing_state = :undefined
|
30
|
+
@negative_cond_value = false
|
31
|
+
end
|
32
|
+
|
33
|
+
### unboxing begin ###
|
34
|
+
def unbox()
|
35
|
+
case @unboxing_state
|
36
|
+
when :can_unbox
|
37
|
+
@unboxing_state = :unboxed
|
38
|
+
return true
|
39
|
+
when :unboxed
|
40
|
+
return false
|
41
|
+
end
|
42
|
+
bug()
|
43
|
+
end
|
44
|
+
|
45
|
+
def unboxed?
|
46
|
+
@unboxing_state == :unboxed
|
47
|
+
end
|
48
|
+
|
49
|
+
def box()
|
50
|
+
case @unboxing_state
|
51
|
+
when :unboxed, :can_unbox, :can_not_unbox
|
52
|
+
@unboxing_state = :boxed
|
53
|
+
return true
|
54
|
+
when :boxed
|
55
|
+
return false
|
56
|
+
end
|
57
|
+
bug()
|
58
|
+
end
|
59
|
+
|
60
|
+
def boxed?
|
61
|
+
@unboxing_state == :boxed
|
62
|
+
end
|
63
|
+
|
64
|
+
def can_unbox?
|
65
|
+
if instance_of?(LocalVariable) || instance_of?(TmpVariable) || instance_of?(Literal)
|
66
|
+
if dynamic? || @types.size != 1
|
67
|
+
false
|
68
|
+
else
|
69
|
+
true
|
70
|
+
end
|
71
|
+
else
|
72
|
+
# ConstWrapper, Self, Pointer, Argument, TmpBuffer
|
73
|
+
false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def can_not_unbox?
|
78
|
+
@unboxing_state == :can_not_unbox
|
79
|
+
end
|
80
|
+
|
81
|
+
def can_unbox()
|
82
|
+
bug() unless @unboxing_state == :undefined
|
83
|
+
@unboxing_state = :can_unbox
|
84
|
+
end
|
85
|
+
|
86
|
+
def can_not_unbox()
|
87
|
+
case @unboxing_state
|
88
|
+
when :undefined, :can_unbox
|
89
|
+
@unboxing_state = :can_not_unbox
|
90
|
+
true
|
91
|
+
when :can_not_unbox
|
92
|
+
false
|
93
|
+
else
|
94
|
+
bug()
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def box_unbox_undefined?
|
99
|
+
@unboxing_state == :undefined
|
100
|
+
end
|
101
|
+
### unboxing end ###
|
102
|
+
|
103
|
+
FloatWrapper = ClassWrapper.new(Float, true)
|
104
|
+
FixnumWrapper = ClassWrapper.new(Fixnum, true)
|
105
|
+
def declare_class()
|
106
|
+
case @unboxing_state
|
107
|
+
when :unboxed
|
108
|
+
bug() if dynamic?
|
109
|
+
bug() unless @types.size == 1
|
110
|
+
c = @types[0]
|
111
|
+
case c
|
112
|
+
when FloatWrapper
|
113
|
+
return :double
|
114
|
+
when FixnumWrapper
|
115
|
+
return :long
|
116
|
+
end
|
117
|
+
when :can_unbox, :can_not_unbox, :boxed
|
118
|
+
return :VALUE
|
119
|
+
end
|
120
|
+
bug()
|
121
|
+
end
|
122
|
+
|
123
|
+
def declare()
|
124
|
+
case declare_class()
|
125
|
+
when :double
|
126
|
+
return 'double'
|
127
|
+
when :long
|
128
|
+
return 'long'
|
129
|
+
when :VALUE
|
130
|
+
return 'VALUE'
|
131
|
+
end
|
132
|
+
bug()
|
133
|
+
end
|
134
|
+
|
135
|
+
def to_name()
|
136
|
+
bug()
|
137
|
+
end
|
138
|
+
|
139
|
+
def to_debug_string()
|
140
|
+
"#{self}(#{dynamic? ? 'dynamic' : @types.join(", ")})"
|
141
|
+
end
|
142
|
+
|
143
|
+
def to_s()
|
144
|
+
case declare_class()
|
145
|
+
when :double
|
146
|
+
return "#{to_name()}_Float"
|
147
|
+
when :long
|
148
|
+
return "#{to_name()}_Fixnum"
|
149
|
+
when :VALUE
|
150
|
+
return to_name()
|
151
|
+
end
|
152
|
+
bug()
|
153
|
+
end
|
154
|
+
|
155
|
+
def class_exact?
|
156
|
+
bug()
|
157
|
+
end
|
158
|
+
|
159
|
+
def is_class_exact()
|
160
|
+
bug()
|
161
|
+
end
|
162
|
+
|
163
|
+
def reset()
|
164
|
+
@ignore.clear()
|
165
|
+
case @state
|
166
|
+
when :undefined
|
167
|
+
bug()
|
168
|
+
when :initialized, :dynamic
|
169
|
+
@types = []
|
170
|
+
@state = :undefined
|
171
|
+
when :static
|
172
|
+
# nothing to do
|
173
|
+
else
|
174
|
+
bug()
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def not_initialized()
|
179
|
+
# @ignore のせいで :undefined になっているものとしか交わらなかったため、initialize されなかったものがある。
|
180
|
+
# そのため、@ignore が空のときに、ここに来る場合がある。
|
181
|
+
@state = :dynamic
|
182
|
+
end
|
183
|
+
|
184
|
+
def is_not(types)
|
185
|
+
bug() if @state == :static
|
186
|
+
bug() unless (@types & @ignore).empty?
|
187
|
+
bug() if types.empty?
|
188
|
+
types = types.map{|t| convert(t)}
|
189
|
+
if (types - @ignore).empty?
|
190
|
+
false
|
191
|
+
else
|
192
|
+
@ignore |= types
|
193
|
+
@types -= types
|
194
|
+
true
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def is_also(t)
|
199
|
+
t = convert(t)
|
200
|
+
return false if @ignore.include?(t)
|
201
|
+
case @state
|
202
|
+
when :undefined
|
203
|
+
@state = :initialized
|
204
|
+
bug() unless @types.empty?
|
205
|
+
@types << t
|
206
|
+
return true
|
207
|
+
when :initialized
|
208
|
+
bug() if @types.empty?
|
209
|
+
if @types.include?(t)
|
210
|
+
return false
|
211
|
+
else
|
212
|
+
@types << t
|
213
|
+
return true
|
214
|
+
end
|
215
|
+
when :static
|
216
|
+
bug() if @types.empty?
|
217
|
+
bug() unless @types.include?(t)
|
218
|
+
return false
|
219
|
+
when :dynamic
|
220
|
+
return false
|
221
|
+
else
|
222
|
+
bug()
|
223
|
+
end
|
224
|
+
bug()
|
225
|
+
end
|
226
|
+
|
227
|
+
def undefined?()
|
228
|
+
@state == :undefined
|
229
|
+
end
|
230
|
+
|
231
|
+
def dynamic?()
|
232
|
+
@state == :dynamic
|
233
|
+
end
|
234
|
+
|
235
|
+
def is_dynamic()
|
236
|
+
return false if @state == :dynamic
|
237
|
+
return false if @state == :static
|
238
|
+
if annotated?
|
239
|
+
if (@annotation - @ignore - @types).empty?
|
240
|
+
return false
|
241
|
+
else
|
242
|
+
@state = :initialized
|
243
|
+
@types |= (@annotation - @ignore)
|
244
|
+
return true
|
245
|
+
end
|
246
|
+
else
|
247
|
+
@state = :dynamic
|
248
|
+
return true
|
249
|
+
end
|
250
|
+
bug()
|
251
|
+
end
|
252
|
+
|
253
|
+
def static?()
|
254
|
+
@state == :static
|
255
|
+
end
|
256
|
+
|
257
|
+
def is_static(types)
|
258
|
+
bug() if types.empty?
|
259
|
+
types = types.map{|t| convert(t)}
|
260
|
+
bug() unless (@ignore & types).empty?
|
261
|
+
case @state
|
262
|
+
when :undefined
|
263
|
+
bug() unless @types.empty?
|
264
|
+
@types = types
|
265
|
+
@state = :static
|
266
|
+
return true
|
267
|
+
when :static
|
268
|
+
bug() unless @types == types
|
269
|
+
return false
|
270
|
+
end
|
271
|
+
bug()
|
272
|
+
end
|
273
|
+
|
274
|
+
def is_annotated(types)
|
275
|
+
# 代入の対象となるような変数(local, instance, class, global variable)は、
|
276
|
+
# static ではなく annotated とする。
|
277
|
+
# initialized にしちゃうと、dynamic と union したときに、dynamic になってしまうのがもどかしい。
|
278
|
+
bug() unless @state == :undefined
|
279
|
+
bug() unless @annotation.empty?
|
280
|
+
bug() unless @ignore.empty?
|
281
|
+
bug() if types.empty?
|
282
|
+
@annotation = types.map{|t| convert(t)}
|
283
|
+
@annotation.freeze()
|
284
|
+
end
|
285
|
+
|
286
|
+
def is_just?(c)
|
287
|
+
case c
|
288
|
+
when Class, ClassWrapper
|
289
|
+
return is_just_class(c)
|
290
|
+
when Array
|
291
|
+
return is_just_classes(c)
|
292
|
+
end
|
293
|
+
bug()
|
294
|
+
end
|
295
|
+
|
296
|
+
def is_also?(c)
|
297
|
+
case c
|
298
|
+
when Class, ClassWrapper
|
299
|
+
return is_also_class(c)
|
300
|
+
end
|
301
|
+
bug()
|
302
|
+
end
|
303
|
+
|
304
|
+
def union(v)
|
305
|
+
bug() if (v.types + @types).find{|t| not t.is_a?(ClassWrapper)}
|
306
|
+
union_types = v.types - @ignore
|
307
|
+
case @state
|
308
|
+
when :undefined
|
309
|
+
bug() unless @types.empty?
|
310
|
+
case v.state
|
311
|
+
when :undefined
|
312
|
+
return false
|
313
|
+
when :initialized, :static
|
314
|
+
return false if union_types.empty?
|
315
|
+
@state = :initialized
|
316
|
+
@types |= union_types
|
317
|
+
return true
|
318
|
+
when :dynamic
|
319
|
+
return is_dynamic()
|
320
|
+
else
|
321
|
+
bug()
|
322
|
+
end
|
323
|
+
when :initialized
|
324
|
+
bug() if @types.empty?
|
325
|
+
case v.state
|
326
|
+
when :undefined
|
327
|
+
return false
|
328
|
+
when :initialized, :static
|
329
|
+
if (union_types - @types).empty?
|
330
|
+
return false
|
331
|
+
else
|
332
|
+
@types |= union_types
|
333
|
+
return true
|
334
|
+
end
|
335
|
+
when :dynamic
|
336
|
+
return is_dynamic()
|
337
|
+
else
|
338
|
+
bug()
|
339
|
+
end
|
340
|
+
when :static
|
341
|
+
bug() if @types.empty?
|
342
|
+
case v.state
|
343
|
+
when :undefined, :dynamic
|
344
|
+
return false
|
345
|
+
when :initialized, :static
|
346
|
+
bug() unless (union_types - @types).empty? || negative_cond_value?
|
347
|
+
return false
|
348
|
+
else
|
349
|
+
bug()
|
350
|
+
end
|
351
|
+
when :dynamic
|
352
|
+
return false
|
353
|
+
else
|
354
|
+
bug()
|
355
|
+
end
|
356
|
+
bug()
|
357
|
+
end
|
358
|
+
|
359
|
+
def is_negative_cond_value
|
360
|
+
@negative_cond_value = true
|
361
|
+
end
|
362
|
+
|
363
|
+
private
|
364
|
+
|
365
|
+
def negative_cond_value?
|
366
|
+
@negative_cond_value
|
367
|
+
end
|
368
|
+
|
369
|
+
def is_just_classes(classes)
|
370
|
+
classes = classes.map{|c| convert(c)}
|
371
|
+
case @state
|
372
|
+
when :undefined
|
373
|
+
bug()
|
374
|
+
when :initialized, :static
|
375
|
+
bug() if @types.empty?
|
376
|
+
bug() if classes.empty?
|
377
|
+
return false unless (@types - classes).empty?
|
378
|
+
return false unless (classes - @types).empty?
|
379
|
+
return true
|
380
|
+
when :dynamic
|
381
|
+
return false
|
382
|
+
end
|
383
|
+
bug()
|
384
|
+
end
|
385
|
+
|
386
|
+
def is_just_class(klass)
|
387
|
+
klass = convert(klass)
|
388
|
+
case @state
|
389
|
+
when :undefined
|
390
|
+
bug()
|
391
|
+
when :initialized, :static
|
392
|
+
bug() if @types.empty?
|
393
|
+
return false if @types.size != 1
|
394
|
+
return false if @types[0] != klass
|
395
|
+
return true
|
396
|
+
when :dynamic
|
397
|
+
return false
|
398
|
+
end
|
399
|
+
bug()
|
400
|
+
end
|
401
|
+
|
402
|
+
def is_also_class(klass)
|
403
|
+
klass = convert(klass)
|
404
|
+
case @state
|
405
|
+
when :undefined
|
406
|
+
bug()
|
407
|
+
when :initialized, :static
|
408
|
+
bug() if @types.empty?
|
409
|
+
return @types.include?(klass)
|
410
|
+
when :dynamic
|
411
|
+
return false
|
412
|
+
end
|
413
|
+
bug()
|
414
|
+
end
|
415
|
+
|
416
|
+
def convert(t)
|
417
|
+
case t
|
418
|
+
when ClassWrapper
|
419
|
+
# nothing to do
|
420
|
+
when Class
|
421
|
+
t = ClassWrapper.new(t, true)
|
422
|
+
else
|
423
|
+
bug()
|
424
|
+
end
|
425
|
+
t
|
426
|
+
end
|
427
|
+
|
428
|
+
def annotated?
|
429
|
+
not @annotation.empty?
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
class ConstWrapper < TypeContainer
|
434
|
+
attr_reader :path
|
435
|
+
|
436
|
+
def initialize(flag, *ids, translator)
|
437
|
+
super()
|
438
|
+
@chain = ids
|
439
|
+
@flag = flag
|
440
|
+
@path = "#{@flag ? '::' : nil}#{@chain.join("::")}"
|
441
|
+
@translator = translator
|
442
|
+
@name = @translator.allocate_name("const_#{@path}")
|
443
|
+
@translator.declare_constant(@name)
|
444
|
+
conf = @translator.configuration
|
445
|
+
@cache_constant_p = @prefetch_constant_p = conf.prefetch_constant? && conf.has_binding?
|
446
|
+
if prefetch?
|
447
|
+
begin
|
448
|
+
val = conf.evaluate_by_passed_binding(@path)
|
449
|
+
c = ClassWrapper.new(val, false)
|
450
|
+
rescue
|
451
|
+
@prefetch_constant_p = false
|
452
|
+
c = nil
|
453
|
+
end
|
454
|
+
else
|
455
|
+
c = nil
|
456
|
+
end
|
457
|
+
if c && @translator.get_c_classname(c)
|
458
|
+
is_static([c])
|
459
|
+
else
|
460
|
+
is_dynamic()
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
def get_constant_chain
|
465
|
+
ret = []
|
466
|
+
ret << " cast_off_tmp = #{@flag ? 'rb_cObject' : 'Qnil'};"
|
467
|
+
@chain.each do |id|
|
468
|
+
ret << " cast_off_tmp = cast_off_get_constant(cast_off_tmp, #{@translator.allocate_id(id)});"
|
469
|
+
end
|
470
|
+
ret << " #{@name} = cast_off_tmp;"
|
471
|
+
ret.join("\n")
|
472
|
+
end
|
473
|
+
|
474
|
+
def cache?
|
475
|
+
@cache_constant_p
|
476
|
+
end
|
477
|
+
|
478
|
+
def prefetch?
|
479
|
+
@prefetch_constant_p
|
480
|
+
end
|
481
|
+
|
482
|
+
def class_exact?
|
483
|
+
false
|
484
|
+
end
|
485
|
+
|
486
|
+
def to_name
|
487
|
+
@name
|
488
|
+
end
|
489
|
+
|
490
|
+
def source
|
491
|
+
@path
|
492
|
+
end
|
493
|
+
|
494
|
+
def eql?(v)
|
495
|
+
return false unless v.is_a?(ConstWrapper)
|
496
|
+
@path == v.path
|
497
|
+
end
|
498
|
+
|
499
|
+
def ==(v)
|
500
|
+
eql?(v)
|
501
|
+
end
|
502
|
+
|
503
|
+
def hash
|
504
|
+
@path.to_s.hash
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
class Literal < TypeContainer
|
509
|
+
include CastOff::Util
|
510
|
+
|
511
|
+
attr_reader :val, :literal_value
|
512
|
+
|
513
|
+
def initialize(val, translator)
|
514
|
+
super()
|
515
|
+
case val
|
516
|
+
when NilClass
|
517
|
+
@val = "Qnil"
|
518
|
+
type = NilClass
|
519
|
+
@literal_value = nil
|
520
|
+
when Fixnum, Symbol, Bignum, Float, String, Regexp, Array, Range, TrueClass, FalseClass, Class
|
521
|
+
@val = translator.allocate_object(val)
|
522
|
+
type = val.class
|
523
|
+
@literal_value = val
|
524
|
+
else
|
525
|
+
bug("unexpected object #{val}")
|
526
|
+
end
|
527
|
+
is_static([type])
|
528
|
+
end
|
529
|
+
|
530
|
+
def to_s()
|
531
|
+
case declare_class()
|
532
|
+
when :double, :long
|
533
|
+
return "#{@literal_value}"
|
534
|
+
when :VALUE
|
535
|
+
return to_name()
|
536
|
+
end
|
537
|
+
bug()
|
538
|
+
end
|
539
|
+
|
540
|
+
def class_exact?
|
541
|
+
true
|
542
|
+
end
|
543
|
+
|
544
|
+
def to_name
|
545
|
+
@val
|
546
|
+
end
|
547
|
+
|
548
|
+
def source
|
549
|
+
@literal_value.inspect
|
550
|
+
end
|
551
|
+
|
552
|
+
def eql?(v)
|
553
|
+
return false unless v.is_a?(Literal)
|
554
|
+
@literal_value == v.literal_value
|
555
|
+
end
|
556
|
+
|
557
|
+
def ==(v)
|
558
|
+
eql?(v)
|
559
|
+
end
|
560
|
+
|
561
|
+
def hash()
|
562
|
+
@literal_value.hash()
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
class Self < TypeContainer
|
567
|
+
include CastOff::Util
|
568
|
+
|
569
|
+
def initialize(translator)
|
570
|
+
super()
|
571
|
+
reciever_class = translator.reciever_class
|
572
|
+
if reciever_class
|
573
|
+
#is_static(reciever_class)
|
574
|
+
reciever_class = [reciever_class] unless reciever_class.instance_of?(Array)
|
575
|
+
reciever_class.each{|c| is_also(c)}
|
576
|
+
else
|
577
|
+
is_dynamic()
|
578
|
+
end
|
579
|
+
end
|
580
|
+
|
581
|
+
def class_exact?
|
582
|
+
false
|
583
|
+
end
|
584
|
+
|
585
|
+
def to_name
|
586
|
+
"self"
|
587
|
+
end
|
588
|
+
|
589
|
+
def source
|
590
|
+
"self"
|
591
|
+
end
|
592
|
+
|
593
|
+
def eql?(v)
|
594
|
+
v.is_a?(Self)
|
595
|
+
end
|
596
|
+
|
597
|
+
def ==(v)
|
598
|
+
eql?(v)
|
599
|
+
end
|
600
|
+
|
601
|
+
def hash
|
602
|
+
self.to_name.hash
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
606
|
+
class Variable < TypeContainer
|
607
|
+
def initialize()
|
608
|
+
super()
|
609
|
+
@isclassexact = false
|
610
|
+
end
|
611
|
+
|
612
|
+
def class_exact?
|
613
|
+
@isclassexact
|
614
|
+
end
|
615
|
+
|
616
|
+
def is_class_exact()
|
617
|
+
bug() if @isclassexact
|
618
|
+
@isclassexact = true
|
619
|
+
end
|
620
|
+
|
621
|
+
def has_undefined_path()
|
622
|
+
# nothing to do
|
623
|
+
end
|
624
|
+
|
625
|
+
def declare?
|
626
|
+
self.is_a?(LocalVariable) || self.is_a?(TmpVariable) || self.is_a?(Pointer)
|
627
|
+
end
|
628
|
+
end
|
629
|
+
|
630
|
+
class TmpVariable < Variable
|
631
|
+
include CastOff::Util
|
632
|
+
attr_reader :index
|
633
|
+
|
634
|
+
def initialize(index)
|
635
|
+
super()
|
636
|
+
@index = index
|
637
|
+
end
|
638
|
+
|
639
|
+
def to_name
|
640
|
+
"tmp#{@index}"
|
641
|
+
end
|
642
|
+
|
643
|
+
def source
|
644
|
+
bug()
|
645
|
+
end
|
646
|
+
|
647
|
+
def eql?(v)
|
648
|
+
return false unless v.is_a?(TmpVariable)
|
649
|
+
@index == v.index
|
650
|
+
end
|
651
|
+
|
652
|
+
def ==(v)
|
653
|
+
eql?(v)
|
654
|
+
end
|
655
|
+
|
656
|
+
def hash
|
657
|
+
self.to_name.hash
|
658
|
+
end
|
659
|
+
|
660
|
+
def has_undefined_path()
|
661
|
+
bug()
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
class Pointer < Variable
|
666
|
+
def initialize
|
667
|
+
super()
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
class InstanceVariable < Pointer
|
672
|
+
attr_reader :id
|
673
|
+
|
674
|
+
def initialize(id, types)
|
675
|
+
super()
|
676
|
+
@id = id
|
677
|
+
@name = id.slice(1, id.size - 1)
|
678
|
+
|
679
|
+
if types
|
680
|
+
bug() unless types.is_a?(Array)
|
681
|
+
is_annotated(types)
|
682
|
+
end
|
683
|
+
end
|
684
|
+
|
685
|
+
def to_name
|
686
|
+
"instance_#{@name}"
|
687
|
+
end
|
688
|
+
|
689
|
+
def source
|
690
|
+
@id.to_s
|
691
|
+
end
|
692
|
+
|
693
|
+
def eql?(v)
|
694
|
+
return false unless v.is_a?(InstanceVariable)
|
695
|
+
@id == v.id
|
696
|
+
end
|
697
|
+
|
698
|
+
def ==(v)
|
699
|
+
eql?(v)
|
700
|
+
end
|
701
|
+
|
702
|
+
def hash
|
703
|
+
self.to_name.hash
|
704
|
+
end
|
705
|
+
end
|
706
|
+
|
707
|
+
class ClassVariable < Pointer
|
708
|
+
attr_reader :id
|
709
|
+
|
710
|
+
def initialize(id, types)
|
711
|
+
super()
|
712
|
+
@id = id
|
713
|
+
@name = id.slice(2, id.size - 2)
|
714
|
+
|
715
|
+
if types
|
716
|
+
bug() unless types.is_a?(Array)
|
717
|
+
is_annotated(types)
|
718
|
+
end
|
719
|
+
end
|
720
|
+
|
721
|
+
def to_name
|
722
|
+
"class_#{@name}"
|
723
|
+
end
|
724
|
+
|
725
|
+
def source
|
726
|
+
@id.to_s
|
727
|
+
end
|
728
|
+
|
729
|
+
def eql?(v)
|
730
|
+
return false unless v.is_a?(ClassVariable)
|
731
|
+
@id == v.id
|
732
|
+
end
|
733
|
+
|
734
|
+
def ==(v)
|
735
|
+
eql?(v)
|
736
|
+
end
|
737
|
+
|
738
|
+
def hash
|
739
|
+
self.to_name.hash
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
class GlobalVariable < Pointer
|
744
|
+
attr_reader :id
|
745
|
+
|
746
|
+
def initialize(gentry, types, translator)
|
747
|
+
super()
|
748
|
+
@id = gentry
|
749
|
+
@name = gentry.slice(1, gentry.size - 1)
|
750
|
+
@name = translator.allocate_name(@name)
|
751
|
+
|
752
|
+
if types
|
753
|
+
bug() unless types.is_a?(Array)
|
754
|
+
is_annotated(types)
|
755
|
+
end
|
756
|
+
end
|
757
|
+
|
758
|
+
def to_name
|
759
|
+
"global_#{@name}"
|
760
|
+
end
|
761
|
+
|
762
|
+
def source
|
763
|
+
@id.to_s
|
764
|
+
end
|
765
|
+
|
766
|
+
def eql?(v)
|
767
|
+
return false unless v.is_a?(GlobalVariable)
|
768
|
+
@id == v.id
|
769
|
+
end
|
770
|
+
|
771
|
+
def ==(v)
|
772
|
+
eql?(v)
|
773
|
+
end
|
774
|
+
|
775
|
+
def hash
|
776
|
+
self.to_name.hash
|
777
|
+
end
|
778
|
+
end
|
779
|
+
|
780
|
+
class DynamicVariable < Pointer
|
781
|
+
attr_reader :index, :level
|
782
|
+
|
783
|
+
def initialize(name, idx, op_idx, lv, types)
|
784
|
+
super()
|
785
|
+
@name = name
|
786
|
+
@index = idx
|
787
|
+
@op_idx = op_idx
|
788
|
+
@level = lv
|
789
|
+
|
790
|
+
if types
|
791
|
+
bug() unless types.is_a?(Array)
|
792
|
+
is_annotated(types)
|
793
|
+
end
|
794
|
+
end
|
795
|
+
|
796
|
+
def to_name
|
797
|
+
"dfp#{@level}[#{@op_idx}]"
|
798
|
+
end
|
799
|
+
|
800
|
+
def source
|
801
|
+
@name.to_s
|
802
|
+
end
|
803
|
+
|
804
|
+
def eql?(v)
|
805
|
+
return false unless v.is_a?(DynamicVariable)
|
806
|
+
@index == v.index && @level == v.level
|
807
|
+
end
|
808
|
+
|
809
|
+
def ==(v)
|
810
|
+
eql?(v)
|
811
|
+
end
|
812
|
+
|
813
|
+
def hash
|
814
|
+
self.to_name.hash
|
815
|
+
end
|
816
|
+
|
817
|
+
def declare?
|
818
|
+
false
|
819
|
+
end
|
820
|
+
end
|
821
|
+
|
822
|
+
class Argument < Variable
|
823
|
+
attr_reader :id, :lvar
|
824
|
+
|
825
|
+
def initialize(name, id, op_idx, lv, types)
|
826
|
+
super()
|
827
|
+
@name = name
|
828
|
+
@id = id
|
829
|
+
@op_idx = op_idx
|
830
|
+
@level = lv
|
831
|
+
@lvar = "local#{@id}_#{@name}" # FIXME
|
832
|
+
|
833
|
+
if types
|
834
|
+
bug() unless types.is_a?(Array)
|
835
|
+
is_static(types)
|
836
|
+
end
|
837
|
+
end
|
838
|
+
|
839
|
+
def to_name
|
840
|
+
"<Argument:#{@id}_#{@name}>"
|
841
|
+
end
|
842
|
+
|
843
|
+
def source
|
844
|
+
bug()
|
845
|
+
end
|
846
|
+
|
847
|
+
def eql?(v)
|
848
|
+
return false unless v.is_a?(Argument)
|
849
|
+
@id == v.id
|
850
|
+
end
|
851
|
+
|
852
|
+
def ==(v)
|
853
|
+
eql?(v)
|
854
|
+
end
|
855
|
+
|
856
|
+
def hash
|
857
|
+
self.to_name.hash
|
858
|
+
end
|
859
|
+
end
|
860
|
+
|
861
|
+
class LocalVariable < Variable
|
862
|
+
attr_reader :id, :name
|
863
|
+
|
864
|
+
def initialize(name, id, op_idx, lv, types)
|
865
|
+
super()
|
866
|
+
@name = name
|
867
|
+
@id = id
|
868
|
+
@op_idx = op_idx
|
869
|
+
@level = lv
|
870
|
+
|
871
|
+
if types
|
872
|
+
bug() unless types.is_a?(Array)
|
873
|
+
is_annotated(types)
|
874
|
+
end
|
875
|
+
end
|
876
|
+
|
877
|
+
def to_name
|
878
|
+
"local#{@id}_#{@name}"
|
879
|
+
end
|
880
|
+
|
881
|
+
def source
|
882
|
+
@name.to_s
|
883
|
+
end
|
884
|
+
|
885
|
+
def eql?(v)
|
886
|
+
return false unless v.is_a?(LocalVariable)
|
887
|
+
@id == v.id
|
888
|
+
end
|
889
|
+
|
890
|
+
def ==(v)
|
891
|
+
eql?(v)
|
892
|
+
end
|
893
|
+
|
894
|
+
def hash
|
895
|
+
self.to_name.hash
|
896
|
+
end
|
897
|
+
|
898
|
+
def has_undefined_path()
|
899
|
+
bug()
|
900
|
+
end
|
901
|
+
end
|
902
|
+
|
903
|
+
class TmpBuffer < Variable
|
904
|
+
attr_reader :index
|
905
|
+
|
906
|
+
def initialize(index)
|
907
|
+
super()
|
908
|
+
@index = index
|
909
|
+
end
|
910
|
+
|
911
|
+
def to_name
|
912
|
+
"cast_off_argv[#{@index}]"
|
913
|
+
end
|
914
|
+
|
915
|
+
def source
|
916
|
+
bug()
|
917
|
+
end
|
918
|
+
|
919
|
+
def eql?(v)
|
920
|
+
return false unless v.is_a?(TmpBuffer)
|
921
|
+
@index == v.index
|
922
|
+
end
|
923
|
+
|
924
|
+
def ==(v)
|
925
|
+
eql?(v)
|
926
|
+
end
|
927
|
+
|
928
|
+
def hash
|
929
|
+
self.to_name.hash
|
930
|
+
end
|
931
|
+
end
|
932
|
+
end
|
933
|
+
end
|
934
|
+
|