ytljit 0.0.1
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 +29 -0
- data/Rakefile +22 -0
- data/ext/code_alloc.c +266 -0
- data/ext/extconf.rb +3 -0
- data/ext/ytljit.c +527 -0
- data/ext/ytljit.h +285 -0
- data/lib/ytljit/asm.rb +205 -0
- data/lib/ytljit/asmext.rb +199 -0
- data/lib/ytljit/asmext_x64.rb +212 -0
- data/lib/ytljit/asmext_x86.rb +128 -0
- data/lib/ytljit/asmutil.rb +182 -0
- data/lib/ytljit/codespace.rb +92 -0
- data/lib/ytljit/error.rb +7 -0
- data/lib/ytljit/instruction.rb +138 -0
- data/lib/ytljit/instruction_ia.rb +1298 -0
- data/lib/ytljit/instruction_x64.rb +41 -0
- data/lib/ytljit/instruction_x86.rb +11 -0
- data/lib/ytljit/marshal.rb +133 -0
- data/lib/ytljit/matcher.rb +235 -0
- data/lib/ytljit/rubyvm.rb +63 -0
- data/lib/ytljit/struct.rb +125 -0
- data/lib/ytljit/type.rb +112 -0
- data/lib/ytljit/util.rb +63 -0
- data/lib/ytljit/vm.rb +1649 -0
- data/lib/ytljit/vm_codegen.rb +491 -0
- data/lib/ytljit/vm_inline_method.rb +85 -0
- data/lib/ytljit/vm_inspect.rb +74 -0
- data/lib/ytljit/vm_sendnode.rb +561 -0
- data/lib/ytljit/vm_trans.rb +508 -0
- data/lib/ytljit/vm_type.rb +299 -0
- data/lib/ytljit/vm_type_gen.rb +158 -0
- data/lib/ytljit/vm_typeinf.rb +98 -0
- data/lib/ytljit.rb +46 -0
- data/test/asmsample.rb +117 -0
- data/test/cstest.rb +61 -0
- data/test/marshaltest.rb +27 -0
- data/test/test_assemble.rb +148 -0
- data/test/test_assemble2.rb +286 -0
- data/test/test_codespace.rb +102 -0
- data/test/test_typeinf.rb +21 -0
- data/test/tivmtest.rb +54 -0
- data/test/vmtest.rb +59 -0
- data/test/vmtest2.rb +41 -0
- data/test/vmtest3.rb +22 -0
- data/test/vmtest_compile_only.rb +41 -0
- data/test/vmtest_execute_only.rb +22 -0
- metadata +121 -0
@@ -0,0 +1,561 @@
|
|
1
|
+
module YTLJit
|
2
|
+
module VM
|
3
|
+
# Expression of VM is a set of Nodes
|
4
|
+
module Node
|
5
|
+
# Opt_flag operation
|
6
|
+
module OptFlagOp
|
7
|
+
def is_args_splat
|
8
|
+
(@opt_flag & (1 << 1)) != 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def is_args_blockarg
|
12
|
+
(@opt_flag & (1 << 2)) != 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def is_fcall
|
16
|
+
(@opt_flag & (1 << 3)) != 0
|
17
|
+
end
|
18
|
+
|
19
|
+
def is_vcall
|
20
|
+
(@opt_flag & (1 << 4)) != 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def is_tailcall
|
24
|
+
(@opt_flag & (1 << 5)) != 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def is_tailrecursion
|
28
|
+
(@opt_flag & (1 << 6)) != 0
|
29
|
+
end
|
30
|
+
|
31
|
+
def is_super
|
32
|
+
(@opt_flag & (1 << 7)) != 0
|
33
|
+
end
|
34
|
+
|
35
|
+
def is_opt_send
|
36
|
+
(@opt_flag & (1 << 8)) != 0
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Send methodes
|
41
|
+
class SendNode<BaseNode
|
42
|
+
include HaveChildlenMixin
|
43
|
+
include OptFlagOp
|
44
|
+
include SendNodeCodeGen
|
45
|
+
include NodeUtil
|
46
|
+
include SendUtil
|
47
|
+
|
48
|
+
@@current_node = nil
|
49
|
+
@@special_node_tab = {}
|
50
|
+
|
51
|
+
def self.node
|
52
|
+
@@current_node
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.add_special_send_node(name)
|
56
|
+
@@special_node_tab[name] = self
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.make_send_node(parent, func, arguments, op_flag)
|
60
|
+
spcl = @@special_node_tab[func.name]
|
61
|
+
newobj = nil
|
62
|
+
if spcl then
|
63
|
+
newobj = spcl.new(parent, func, arguments, op_flag)
|
64
|
+
else
|
65
|
+
newobj = self.new(parent, func, arguments, op_flag)
|
66
|
+
end
|
67
|
+
func.parent = newobj
|
68
|
+
arguments.each do |ele|
|
69
|
+
ele.parent = newobj
|
70
|
+
end
|
71
|
+
|
72
|
+
newobj
|
73
|
+
end
|
74
|
+
|
75
|
+
def initialize(parent, func, arguments, op_flag)
|
76
|
+
super(parent)
|
77
|
+
@func = func
|
78
|
+
@arguments = arguments
|
79
|
+
@opt_flag = op_flag
|
80
|
+
@var_return_address = nil
|
81
|
+
@next_node = @@current_node
|
82
|
+
@@current_node = self
|
83
|
+
|
84
|
+
@class_top = search_class_top
|
85
|
+
@frame_info = search_frame_info
|
86
|
+
|
87
|
+
@modified_instance_var = nil
|
88
|
+
@modified_local_var = [{}]
|
89
|
+
end
|
90
|
+
|
91
|
+
attr_accessor :func
|
92
|
+
attr_accessor :arguments
|
93
|
+
attr :opt_flag
|
94
|
+
attr :var_return_address
|
95
|
+
attr :next_node
|
96
|
+
attr :class_top
|
97
|
+
attr :modified_local_var
|
98
|
+
attr :modified_instance_var
|
99
|
+
|
100
|
+
def traverse_childlen
|
101
|
+
@arguments.each do |arg|
|
102
|
+
yield arg
|
103
|
+
end
|
104
|
+
yield @func
|
105
|
+
end
|
106
|
+
|
107
|
+
def collect_candidate_type_regident(context, slf)
|
108
|
+
p @func.name
|
109
|
+
context
|
110
|
+
end
|
111
|
+
|
112
|
+
def collect_info(context)
|
113
|
+
traverse_childlen {|rec|
|
114
|
+
context = rec.collect_info(context)
|
115
|
+
}
|
116
|
+
if is_fcall or is_vcall then
|
117
|
+
# Call method of same class
|
118
|
+
mt = @class_top.method_tab[@func.name]
|
119
|
+
if mt then
|
120
|
+
miv = mt.modified_instance_var
|
121
|
+
if miv then
|
122
|
+
miv.each do |vname, vall|
|
123
|
+
context.modified_instance_var[vname] = vall
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
@modified_local_var = context.modified_local_var.dup
|
130
|
+
@modified_instance_var = context.modified_instance_var.dup
|
131
|
+
|
132
|
+
context
|
133
|
+
end
|
134
|
+
|
135
|
+
def collect_candidate_type(context)
|
136
|
+
# prev env
|
137
|
+
context = @arguments[0].collect_candidate_type(context)
|
138
|
+
|
139
|
+
# block is after detect method
|
140
|
+
blknode = @arguments[1]
|
141
|
+
|
142
|
+
# other
|
143
|
+
@arguments[2.. -1].each do |arg|
|
144
|
+
context = arg.collect_candidate_type(context)
|
145
|
+
end
|
146
|
+
|
147
|
+
# function select
|
148
|
+
context = @func.collect_candidate_type(context)
|
149
|
+
|
150
|
+
signat = signature(context)
|
151
|
+
mt = nil
|
152
|
+
if is_fcall or is_vcall then
|
153
|
+
mt = @func.method_top_node(@class_top, nil)
|
154
|
+
else
|
155
|
+
@arguments[2].decide_type_once(context.to_key)
|
156
|
+
slf = @arguments[2].type
|
157
|
+
if slf.instance_of?(RubyType::DefaultType0) then
|
158
|
+
# Chaos
|
159
|
+
|
160
|
+
else
|
161
|
+
mt = @func.method_top_node(@class_top, slf)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
if mt then
|
166
|
+
same_type(self, mt, context.to_key, signat, context)
|
167
|
+
same_type(mt, self, signat, context.to_key, context)
|
168
|
+
|
169
|
+
context.current_method_signature_node.push @arguments
|
170
|
+
mt.yield_node.map do |ynode|
|
171
|
+
yargs = ynode.arguments
|
172
|
+
ysignat = ynode.signature(context)
|
173
|
+
same_type(blknode, ynode, ysignat, signat, context)
|
174
|
+
same_type(ynode, blknode, signat, ysignat, context)
|
175
|
+
end
|
176
|
+
context.current_method_signature_node.pop
|
177
|
+
|
178
|
+
context = mt.collect_candidate_type(context, @arguments, signat)
|
179
|
+
|
180
|
+
context.current_method_signature_node.push @arguments
|
181
|
+
mt.yield_node.map do |ynode|
|
182
|
+
yargs = ynode.arguments
|
183
|
+
ysignat = ynode.signature(context)
|
184
|
+
if blknode.is_a?(TopNode) then
|
185
|
+
# Have block
|
186
|
+
context = blknode.collect_candidate_type(context,
|
187
|
+
yargs, ysignat)
|
188
|
+
else
|
189
|
+
context = blknode.collect_candidate_type(context)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
context.current_method_signature_node.pop
|
193
|
+
else
|
194
|
+
context = collect_candidate_type_regident(context, slf)
|
195
|
+
end
|
196
|
+
|
197
|
+
@body.collect_candidate_type(context)
|
198
|
+
end
|
199
|
+
|
200
|
+
def compile(context)
|
201
|
+
context = super(context)
|
202
|
+
|
203
|
+
context.start_using_reg(TMPR2)
|
204
|
+
context.start_using_reg(TMPR3)
|
205
|
+
callconv = @func.calling_convention(context)
|
206
|
+
fnc = nil
|
207
|
+
|
208
|
+
case callconv
|
209
|
+
when :c_vararg
|
210
|
+
context.start_using_reg(TMPR2)
|
211
|
+
|
212
|
+
context = gen_make_argv(context) do |context, rarg|
|
213
|
+
context.start_using_reg(FUNC_ARG[0])
|
214
|
+
context.start_using_reg(FUNC_ARG[1])
|
215
|
+
context.start_using_reg(FUNC_ARG[2])
|
216
|
+
|
217
|
+
context.cpustack_pushn(3 * AsmType::MACHINE_WORD.size)
|
218
|
+
casm = context.assembler
|
219
|
+
# Method Select
|
220
|
+
# it is legal. use TMPR2 for method select
|
221
|
+
# use TMPR3 for store self
|
222
|
+
context = @func.compile(context)
|
223
|
+
fnc = context.ret_reg
|
224
|
+
casm.with_retry do
|
225
|
+
casm.mov(FUNC_ARG[0], rarg.size) # argc
|
226
|
+
casm.mov(FUNC_ARG[1], TMPR2) # argv
|
227
|
+
casm.mov(FUNC_ARG[2], TMPR3) # self
|
228
|
+
end
|
229
|
+
context.set_reg_content(FUNC_ARG[0], nil)
|
230
|
+
context.set_reg_content(FUNC_ARG[1], TMPR2)
|
231
|
+
context.set_reg_content(FUNC_ARG[2], context.ret_node)
|
232
|
+
|
233
|
+
context = gen_call(context, fnc, 3)
|
234
|
+
context.cpustack_popn(3 * AsmType::MACHINE_WORD.size)
|
235
|
+
|
236
|
+
context.end_using_reg(FUNC_ARG[2])
|
237
|
+
context.end_using_reg(FUNC_ARG[1])
|
238
|
+
context.end_using_reg(FUNC_ARG[0])
|
239
|
+
context.end_using_reg(TMPR2)
|
240
|
+
context.ret_reg = RETR
|
241
|
+
context.ret_node = self
|
242
|
+
|
243
|
+
decide_type_once(context.to_key)
|
244
|
+
context = @type.to_box.gen_unboxing(context)
|
245
|
+
|
246
|
+
context
|
247
|
+
end
|
248
|
+
|
249
|
+
when :c_fixarg
|
250
|
+
numarg = @arguments.size - 2
|
251
|
+
|
252
|
+
numarg.times do |i|
|
253
|
+
context.start_using_reg(FUNC_ARG[i])
|
254
|
+
end
|
255
|
+
context.cpustack_pushn(numarg * AsmType::MACHINE_WORD.size)
|
256
|
+
|
257
|
+
argpos = 0
|
258
|
+
cursrc = 0
|
259
|
+
@arguments.each do |arg|
|
260
|
+
# skip prevenv and block_argument
|
261
|
+
if cursrc < 2 then
|
262
|
+
cursrc = cursrc + 1
|
263
|
+
next
|
264
|
+
end
|
265
|
+
|
266
|
+
if cursrc == 2 then
|
267
|
+
# Self
|
268
|
+
# Method Select
|
269
|
+
# it is legal. use TMPR2 for method select
|
270
|
+
# use TMPR3 for store self
|
271
|
+
context = @func.compile(context)
|
272
|
+
fnc = context.ret_reg
|
273
|
+
casm = context.assembler
|
274
|
+
casm.with_retry do
|
275
|
+
casm.mov(FUNC_ARG[0], TMPR3)
|
276
|
+
end
|
277
|
+
context.set_reg_content(FUNC_ARG[0], context.ret_node)
|
278
|
+
else
|
279
|
+
# other arg.
|
280
|
+
context = arg.compile(context)
|
281
|
+
context.ret_node.decide_type_once(context.to_key)
|
282
|
+
rtype = context.ret_node.type
|
283
|
+
context = rtype.gen_boxing(context)
|
284
|
+
casm = context.assembler
|
285
|
+
casm.with_retry do
|
286
|
+
casm.mov(FUNC_ARG[argpos], context.ret_reg)
|
287
|
+
end
|
288
|
+
context.set_reg_content(FUNC_ARG[argpos], context.ret_node)
|
289
|
+
end
|
290
|
+
argpos = argpos + 1
|
291
|
+
cursrc = cursrc + 1
|
292
|
+
end
|
293
|
+
|
294
|
+
context = gen_call(context, fnc, numarg)
|
295
|
+
|
296
|
+
context.cpustack_popn(numarg * AsmType::MACHINE_WORD.size)
|
297
|
+
numarg.times do |i|
|
298
|
+
context.end_using_reg(FUNC_ARG[numarg - i - 1])
|
299
|
+
end
|
300
|
+
context.end_using_reg(fnc)
|
301
|
+
|
302
|
+
decide_type_once(context.to_key)
|
303
|
+
context = @type.to_box.gen_unboxing(context)
|
304
|
+
|
305
|
+
when :ytl
|
306
|
+
numarg = @arguments.size
|
307
|
+
|
308
|
+
numarg.times do |i|
|
309
|
+
context.start_using_reg(FUNC_ARG_YTL[i])
|
310
|
+
end
|
311
|
+
context.cpustack_pushn(numarg * 8)
|
312
|
+
|
313
|
+
# push prev env
|
314
|
+
casm = context.assembler
|
315
|
+
casm.with_retry do
|
316
|
+
casm.mov(FUNC_ARG_YTL[0], BPR)
|
317
|
+
end
|
318
|
+
context.set_reg_content(FUNC_ARG_YTL[0], BPR)
|
319
|
+
|
320
|
+
# block
|
321
|
+
# eval block
|
322
|
+
# local block
|
323
|
+
|
324
|
+
# compile block with other code space and context
|
325
|
+
tcontext = context.dup
|
326
|
+
@arguments[1].compile(tcontext)
|
327
|
+
|
328
|
+
casm = context.assembler
|
329
|
+
casm.with_retry do
|
330
|
+
entry = @arguments[1].code_space.var_base_immidiate_address
|
331
|
+
casm.mov(FUNC_ARG_YTL[1], entry)
|
332
|
+
end
|
333
|
+
context.set_reg_content(FUNC_ARG_YTL[1], nil)
|
334
|
+
|
335
|
+
# other arguments
|
336
|
+
@arguments[3..-1].each_with_index do |arg, i|
|
337
|
+
context = arg.compile(context)
|
338
|
+
casm = context.assembler
|
339
|
+
casm.with_retry do
|
340
|
+
casm.mov(FUNC_ARG_YTL[i + 3], context.ret_reg)
|
341
|
+
end
|
342
|
+
context.set_reg_content(FUNC_ARG_YTL[i + 3], context.ret_node)
|
343
|
+
end
|
344
|
+
|
345
|
+
# self
|
346
|
+
# Method Select
|
347
|
+
# it is legal. use TMPR2 for method select
|
348
|
+
# use TMPR3 for store self
|
349
|
+
context = @func.compile(context)
|
350
|
+
fnc = context.ret_reg
|
351
|
+
casm = context.assembler
|
352
|
+
casm.with_retry do
|
353
|
+
casm.mov(FUNC_ARG_YTL[2], TMPR3)
|
354
|
+
end
|
355
|
+
context.set_reg_content(FUNC_ARG_YTL[2], @arguments[2])
|
356
|
+
|
357
|
+
context = gen_call(context, fnc, numarg)
|
358
|
+
|
359
|
+
context.cpustack_popn(numarg * 8)
|
360
|
+
numarg.size.times do |i|
|
361
|
+
context.end_using_reg(FUNC_ARG_YTL[numarg - i])
|
362
|
+
end
|
363
|
+
context.end_using_reg(fnc)
|
364
|
+
end
|
365
|
+
|
366
|
+
decide_type_once(context.to_key)
|
367
|
+
if @type.is_a?(RubyType::RubyTypeUnboxed) and
|
368
|
+
@type.ruby_type == Float then
|
369
|
+
context.ret_reg = XMM0
|
370
|
+
else
|
371
|
+
context.ret_reg = RETR
|
372
|
+
end
|
373
|
+
context.ret_node = self
|
374
|
+
context.end_using_reg(TMPR3)
|
375
|
+
context.end_using_reg(TMPR2)
|
376
|
+
|
377
|
+
context = @body.compile(context)
|
378
|
+
context
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
class SendCoreDefineMethodNode<SendNode
|
383
|
+
add_special_send_node :"core#define_method"
|
384
|
+
def initialize(parent, func, arguments, op_flag)
|
385
|
+
super
|
386
|
+
@new_method = arguments[5]
|
387
|
+
if arguments[4].is_a?(LiteralNode) then
|
388
|
+
@new_method.name = arguments[4].value
|
389
|
+
@class_top.method_tab[arguments[4].value] = @new_method
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
def traverse_childlen
|
394
|
+
yield @body
|
395
|
+
yield @new_method
|
396
|
+
end
|
397
|
+
|
398
|
+
def collect_candidate_type(context)
|
399
|
+
# type inference of @new method execute when "send" instruction.
|
400
|
+
@body.collect_candidate_type(context)
|
401
|
+
context
|
402
|
+
end
|
403
|
+
|
404
|
+
def compile(context)
|
405
|
+
context = @body.compile(context)
|
406
|
+
ocs = context.code_space
|
407
|
+
# Allocate new code space in compiling @new_method
|
408
|
+
context = @new_method.compile(context)
|
409
|
+
context.set_code_space(ocs)
|
410
|
+
|
411
|
+
context
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
class SendPlusNode<SendNode
|
416
|
+
include ArithmeticOperationUtil
|
417
|
+
include SendUtil
|
418
|
+
add_special_send_node :+
|
419
|
+
|
420
|
+
def initialize(parent, func, arguments, op_flag)
|
421
|
+
super
|
422
|
+
end
|
423
|
+
|
424
|
+
def collect_candidate_type_regident(context, slf)
|
425
|
+
case [slf.ruby_type]
|
426
|
+
when [Fixnum], [Float], [String]
|
427
|
+
same_type(@arguments[3], @arguments[2],
|
428
|
+
context.to_key, context.to_key, context)
|
429
|
+
same_type(@arguments[2], @arguments[3],
|
430
|
+
context.to_key, context.to_key, context)
|
431
|
+
same_type(self, @arguments[2],
|
432
|
+
context.to_key, context.to_key, context)
|
433
|
+
same_type(@arguments[2], self,
|
434
|
+
context.to_key, context.to_key, context)
|
435
|
+
end
|
436
|
+
|
437
|
+
context
|
438
|
+
end
|
439
|
+
|
440
|
+
#=begin
|
441
|
+
def compile(context)
|
442
|
+
@arguments[2].decide_type_once(context.to_key)
|
443
|
+
rtype = @arguments[2].type
|
444
|
+
if rtype.is_a?(RubyType::DefaultType0) or
|
445
|
+
@class_top.method_tab(rtype.ruby_type)[@func.name] then
|
446
|
+
return super(context)
|
447
|
+
end
|
448
|
+
|
449
|
+
context.current_method_signature.push signature(context)
|
450
|
+
context = gen_eval_self(context)
|
451
|
+
if rtype.ruby_type == Fixnum then
|
452
|
+
context = gen_arithmetic_operation(context, :add, TMPR2, TMPR)
|
453
|
+
elsif rtype.ruby_type == Float then
|
454
|
+
context = gen_arithmetic_operation(context, :addsd, XMM4, XMM0)
|
455
|
+
else
|
456
|
+
raise "Unkown method #{rtype.ruby_type}##{@func.name}"
|
457
|
+
end
|
458
|
+
context.current_method_signature.pop
|
459
|
+
@body.compile(context)
|
460
|
+
end
|
461
|
+
#=end
|
462
|
+
end
|
463
|
+
|
464
|
+
class SendCompareNode<SendNode
|
465
|
+
include SendUtil
|
466
|
+
def collect_candidate_type_regident(context, slf)
|
467
|
+
same_type(@arguments[3], @arguments[2],
|
468
|
+
context.to_key, context.to_key, context)
|
469
|
+
same_type(@arguments[2], @arguments[3],
|
470
|
+
context.to_key, context.to_key, context)
|
471
|
+
tt = RubyType::BaseType.from_ruby_class(true)
|
472
|
+
@type_list.add_type(context.to_key, tt)
|
473
|
+
tt = RubyType::BaseType.from_ruby_class(false)
|
474
|
+
@type_list.add_type(context.to_key, tt)
|
475
|
+
|
476
|
+
context
|
477
|
+
end
|
478
|
+
|
479
|
+
def compile(context)
|
480
|
+
@arguments[2].decide_type_once(context.to_key)
|
481
|
+
rtype = @arguments[2].type
|
482
|
+
if rtype.ruby_type.is_a?(RubyType::DefaultType0) or
|
483
|
+
@class_top.method_tab(rtype.ruby_type)[@func.name] then
|
484
|
+
return super(context)
|
485
|
+
end
|
486
|
+
|
487
|
+
context.current_method_signature.push signature(context)
|
488
|
+
context = gen_eval_self(context)
|
489
|
+
if rtype.ruby_type == Fixnum then
|
490
|
+
context = compile_compare(context)
|
491
|
+
else
|
492
|
+
raise "Unkown method #{rtype.ruby_type} #{@func.name}"
|
493
|
+
end
|
494
|
+
context.current_method_signature.pop
|
495
|
+
@body.compile(context)
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
class SendGtNode<SendCompareNode
|
500
|
+
include CompareOperationUtil
|
501
|
+
add_special_send_node :<
|
502
|
+
def compile_compare(context)
|
503
|
+
context = gen_compare_operation(context , :setg, TMPR2, TMPR)
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
class SendGeNode<SendCompareNode
|
508
|
+
include CompareOperationUtil
|
509
|
+
add_special_send_node :<=
|
510
|
+
def compile_compare(context)
|
511
|
+
context = gen_compare_operation(context , :setge, TMPR2, TMPR)
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
class SendLtNode<SendCompareNode
|
516
|
+
include CompareOperationUtil
|
517
|
+
add_special_send_node :>
|
518
|
+
def compile_compare(context)
|
519
|
+
context = gen_compare_operation(context , :setl, TMPR2, TMPR)
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
class SendLeNode<SendCompareNode
|
524
|
+
include CompareOperationUtil
|
525
|
+
add_special_send_node :>=
|
526
|
+
def compile_compare(context)
|
527
|
+
context = gen_compare_operation(context , :setle, TMPR2, TMPR)
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
class SendRefNode<SendNode
|
532
|
+
include SendUtil
|
533
|
+
add_special_send_node :[]
|
534
|
+
def collect_candidate_type_regident(context, slf)
|
535
|
+
case [slf.ruby_type]
|
536
|
+
when [Array]
|
537
|
+
fixtype = RubyType::BaseType.from_ruby_class(Fixnum)
|
538
|
+
@arguments[3].add_type(context.to_key, fixtype)
|
539
|
+
@arguments[2].add_element_node(context.to_key, self, context)
|
540
|
+
key = context.to_key
|
541
|
+
decide_type_once(key)
|
542
|
+
# @arguments[2].type = nil
|
543
|
+
# @arguments[2].decide_type_once(context.to_key)
|
544
|
+
epare = @arguments[2].element_node_list[0]
|
545
|
+
ekey = epare[0]
|
546
|
+
enode = epare[1]
|
547
|
+
if enode != self then
|
548
|
+
same_type(self, enode, key, ekey, context)
|
549
|
+
same_type(enode, self, ekey, key, context)
|
550
|
+
end
|
551
|
+
|
552
|
+
when [Hash]
|
553
|
+
@arguments[2].add_element_node(context.to_key, self, context)
|
554
|
+
end
|
555
|
+
|
556
|
+
context
|
557
|
+
end
|
558
|
+
end
|
559
|
+
end
|
560
|
+
end
|
561
|
+
end
|