crystalizer 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. data/Changelog +27 -0
  2. data/README +79 -0
  3. data/Rakefile +24 -0
  4. data/TODO +14 -0
  5. data/VERSION +1 -0
  6. data/benchmarks/bench.rb +129 -0
  7. data/benchmarks/concretize_test.rb +26 -0
  8. data/benchmarks/extconf.rb +10 -0
  9. data/benchmarks/tak_rb.rb +7 -0
  10. data/benchmarks/tak_so.rb +7 -0
  11. data/benchmarks/tak_source.rb +16 -0
  12. data/bin/rb2cx +162 -0
  13. data/doc/eval2c.txt +246 -0
  14. data/doc/gen_html.rb +26 -0
  15. data/doc/html_template +10 -0
  16. data/doc/index.txt +169 -0
  17. data/doc/limitations.txt +529 -0
  18. data/doc/optimizations.txt +185 -0
  19. data/doc/rb2cx.txt +130 -0
  20. data/doc/style.css +27 -0
  21. data/lib/concretizer.rb +3 -0
  22. data/lib/ruby2cext/c_function.rb +617 -0
  23. data/lib/ruby2cext/common_node_comp.rb +1412 -0
  24. data/lib/ruby2cext/compiler.rb +311 -0
  25. data/lib/ruby2cext/concretize.rb +269 -0
  26. data/lib/ruby2cext/error.rb +15 -0
  27. data/lib/ruby2cext/eval2c.rb +126 -0
  28. data/lib/ruby2cext/parser.rb +36 -0
  29. data/lib/ruby2cext/plugin.rb +24 -0
  30. data/lib/ruby2cext/plugins/builtin_methods.rb +817 -0
  31. data/lib/ruby2cext/plugins/cache_call.rb +293 -0
  32. data/lib/ruby2cext/plugins/case_optimize.rb +102 -0
  33. data/lib/ruby2cext/plugins/const_cache.rb +36 -0
  34. data/lib/ruby2cext/plugins/direct_self_call.rb +70 -0
  35. data/lib/ruby2cext/plugins/inline_builtin.rb +797 -0
  36. data/lib/ruby2cext/plugins/inline_methods.rb +68 -0
  37. data/lib/ruby2cext/plugins/ivar_cache.rb +147 -0
  38. data/lib/ruby2cext/plugins/require_include.rb +69 -0
  39. data/lib/ruby2cext/plugins/util.rb +154 -0
  40. data/lib/ruby2cext/plugins/warnings.rb +121 -0
  41. data/lib/ruby2cext/scopes.rb +225 -0
  42. data/lib/ruby2cext/str_to_c_strlit.rb +12 -0
  43. data/lib/ruby2cext/tools.rb +80 -0
  44. data/lib/ruby2cext/version.rb +22 -0
  45. data/results +68 -0
  46. data/setup.rb +1585 -0
  47. data/stuff/builtin_methods.rb +69 -0
  48. data/stuff/builtin_methods_test.rb +37 -0
  49. data/test/bootstrap.rb +10 -0
  50. data/test/causes_crash_all_opts.rb +1165 -0
  51. data/test/eval2c/test_eval2c.rb +37 -0
  52. data/test/temp_17.rb +16 -0
  53. data/test/temp_18.rb +8 -0
  54. data/test/temp_19.rb +8 -0
  55. data/test/temp_2.rb +7 -0
  56. data/test/temp_20.rb +5 -0
  57. data/test/temp_21.rb +161 -0
  58. data/test/temp_22.rb +7 -0
  59. data/test/temp_23.rb +7 -0
  60. data/test/temp_24.rb +219 -0
  61. data/test/temp_25.rb +7 -0
  62. data/test/temp_26.rb +11 -0
  63. data/test/temp_27.rb +11 -0
  64. data/test/temp_28.rb +9 -0
  65. data/test/temp_29.rb +9 -0
  66. data/test/temp_3.rb +0 -0
  67. data/test/temp_30.rb +0 -0
  68. data/test/temp_31.rb +10 -0
  69. data/test/temp_32.rb +10 -0
  70. data/test/temp_33.rb +15 -0
  71. data/test/temp_34.rb +15 -0
  72. data/test/temp_35.rb +7 -0
  73. data/test/temp_36.rb +7 -0
  74. data/test/temp_37.rb +10 -0
  75. data/test/temp_38.rb +10 -0
  76. data/test/temp_39.rb +0 -0
  77. data/test/temp_4.rb +7 -0
  78. data/test/temp_40.rb +50 -0
  79. data/test/temp_41.rb +50 -0
  80. data/test/temp_42.rb +8 -0
  81. data/test/temp_43.rb +8 -0
  82. data/test/temp_44.rb +0 -0
  83. data/test/temp_48.rb +7 -0
  84. data/test/temp_49.rb +7 -0
  85. data/test/temp_5.rb +7 -0
  86. data/test/temp_59.rb +7 -0
  87. data/test/temp_6.rb +7 -0
  88. data/test/temp_60.rb +7 -0
  89. data/test/temp_68.rb +239 -0
  90. data/test/temp_7.rb +7 -0
  91. data/test/temp_70.rb +7 -0
  92. data/test/temp_71.rb +7 -0
  93. data/test/temp_72.rb +13 -0
  94. data/test/temp_73.rb +7 -0
  95. data/test/temp_74.rb +7 -0
  96. data/test/temp_76.rb +7 -0
  97. data/test/temp_77.rb +13 -0
  98. data/test/temp_79.rb +7 -0
  99. data/test/temp_8.rb +14 -0
  100. data/test/temp_81.rb +14 -0
  101. data/test/temp_83.rb +0 -0
  102. data/test/temp_84.rb +7 -0
  103. data/test/temp_85.rb +7 -0
  104. data/test/temp_86.rb +14 -0
  105. data/test/temp_87.rb +7 -0
  106. data/test/temp_88.rb +7 -0
  107. data/test/temp_89.rb +7 -0
  108. data/test/temp_9.rb +14 -0
  109. data/test/temp_90.rb +0 -0
  110. data/test/temp_91.rb +7 -0
  111. data/test/temp_92.rb +7 -0
  112. data/test/temp_93.rb +7 -0
  113. data/test/temp_94.rb +7 -0
  114. data/test/temp_95.rb +7 -0
  115. data/test/temp_96.rb +0 -0
  116. data/test/temp_97.rb +0 -0
  117. data/test/temp_98.rb +7 -0
  118. data/test/temp_99.rb +7 -0
  119. data/test/test_concretize.rb +132 -0
  120. data/test/test_concretize_all.rb +15 -0
  121. data/test/test_crystalize_block.rb +73 -0
  122. data/test/test_files/test.rb +615 -0
  123. data/test/test_files/vmode_test.rb +73 -0
  124. data/test/test_files/warn_test.rb +35 -0
  125. data/test/test_syntax.rb +25 -0
  126. metadata +268 -0
@@ -0,0 +1,797 @@
1
+ # this one inlines things like [].empty? -- no ruby calls it's all in C
2
+ # builtin_methods does some more...
3
+ # broken currently
4
+ module Ruby2CExtension::Plugins
5
+
6
+ class InlineBuiltin < Ruby2CExtension::Plugin
7
+
8
+ include Util
9
+ extend Util
10
+
11
+ def initialize(compiler)
12
+ super(compiler)
13
+ compiler.add_preprocessor(:call, &method(:call))
14
+ compiler.add_preprocessor(:vcall, &method(:call))
15
+ compiler.add_preprocessor(:fcall, &method(:call))
16
+ compiler.add_preprocessor(:inline_pass, &method(:inline_pass))
17
+ end
18
+
19
+ def call(cfun, node)
20
+ hash = node.last
21
+ recv = hash[:recv] || [:self, {}]
22
+ klass = deduce_type(recv)
23
+ inline = INLINE[klass]
24
+ inline0 = klass ? INLINE[nil] : {}
25
+ mid = hash[:mid]
26
+ args = hash[:args] || [:array, []]
27
+ if :array==args.first and arity = args.last.size and
28
+ m = (inline[[mid, arity]] || inline0[[mid, arity]])
29
+ args = args.last
30
+ elsif m = (inline[mid] || inline0[mid])
31
+ return m[cfun, node, recv, args]
32
+ else
33
+ return node
34
+ end
35
+ if arity==0
36
+ return values(cfun, (m.arity<0) ? 1 : 0, recv, &m)
37
+ end
38
+ args = args.clone
39
+ first = args.shift
40
+ if klass = deduce_type(first)
41
+ if f = m[klass]
42
+ return values(cfun, (f.arity<0) ? (arity+1) : 0, recv, first, *args, &f)
43
+ else
44
+ return node
45
+ end
46
+ end
47
+ reuse = false
48
+ m.each_value { |f| reuse = false if f.arity<0 }
49
+ default = m[nil]
50
+ size = m.size - (default ? 1 : 0)
51
+ default ||= lambda { |cfun, recv, *args|
52
+ cfun.comp([:inline_pass, :call, {
53
+ :recv => recv,
54
+ :mid => mid,
55
+ :args => [:array, args]
56
+ }])
57
+ }
58
+ values(cfun, reuse ? (arity+1) : 1, first, recv, *args) { |first, recv, *args|
59
+ if size==0
60
+ default[cfun, recv, first, *args]
61
+ elsif size==1
62
+ m.each { |klass, f|
63
+ match = Class2Match[klass] or next
64
+ cfun.c_if(match[first]) {
65
+ cfun.assign_res(f[cfun, recv, first, *args])
66
+ }
67
+ }
68
+ cfun.c_else {
69
+ cfun.assign_res(default[cfun, recv, first, *args])
70
+ }
71
+ "res"
72
+ else
73
+ cfun.l("switch (TYPE(#{first})) {")
74
+ m.each { |klass, f|
75
+ type = Class2Type[klass] or next
76
+ cfun.l("case #{type}:")
77
+ cfun.assign_res(f[cfun, recv, first, *args])
78
+ cfun.l("break;")
79
+ }
80
+ cfun.l("default:")
81
+ cfun.assign_res(default[cfun, recv, first, *args])
82
+ cfun.l("}")
83
+ "res"
84
+ end
85
+ }
86
+ end
87
+
88
+ def inline_pass(cfun, node)
89
+ node.shift
90
+ node
91
+ end
92
+
93
+ Class2Type = {
94
+ NilClass => "T_NIL",
95
+ FalseClass => "T_FALSE",
96
+ TrueClass => "T_TRUE",
97
+ Fixnum => "T_FIXNUM",
98
+ Symbol => "T_SYMBOL",
99
+ Float => "T_FLOAT",
100
+ Bignum => "T_BIGNUM",
101
+ Regexp => "T_REGEXP",
102
+ String => "T_STRING",
103
+ Array => "T_ARRAY",
104
+ Hash => "T_HASH",
105
+ }
106
+
107
+ Class2Match = {
108
+ NilClass => lambda { |obj|
109
+ %{(#{obj} == Qnil)}
110
+ },
111
+ FalseClass => lambda { |obj|
112
+ %{(#{obj} == Qfalse)}
113
+ },
114
+ TrueClass => lambda { |obj|
115
+ %{(#{obj} == Qtrue)}
116
+ },
117
+ Fixnum => lambda { |obj|
118
+ %{FIXNUM_P(#{obj})}
119
+ },
120
+ Symbol => lambda { |obj|
121
+ %{SYMBOL_P(#{obj})}
122
+ },
123
+ Float => lambda { |obj|
124
+ %{(!SPECIAL_CONST_P(#{obj}) && (RBASIC(#{obj})->klass == rb_cFloat))}
125
+ },
126
+ Bignum => lambda { |obj|
127
+ %{(!SPECIAL_CONST_P(#{obj}) && (RBASIC(#{obj})->klass == rb_cBignum))}
128
+ },
129
+ Regexp => lambda { |obj|
130
+ %{(!SPECIAL_CONST_P(#{obj}) && (RBASIC(#{obj})->klass == rb_cRegexp))}
131
+ },
132
+ String => lambda { |obj|
133
+ %{(!SPECIAL_CONST_P(#{obj}) && (RBASIC(#{obj})->klass == rb_cString))}
134
+ },
135
+ Array => lambda { |obj|
136
+ %{(!SPECIAL_CONST_P(#{obj}) && (RBASIC(#{obj})->klass == rb_cArray))}
137
+ },
138
+ Hash => lambda { |obj|
139
+ %{(!SPECIAL_CONST_P(#{obj}) && (RBASIC(#{obj})->klass == rb_cHash))}
140
+ },
141
+ }
142
+
143
+ COMMON = {
144
+ [:equal?,1] => {nil => lambda { |cfun, this, that|
145
+ %{(#{this} == (#{that}) ? Qtrue : Qfalse)}
146
+ }},
147
+ [:'eql?',1] => {nil => lambda { |cfun, this, that|
148
+ %{(#{this} == (#{that}) ? Qtrue : Qfalse)}
149
+ }},
150
+ [:'==',1] => {nil => lambda { |cfun, this, that|
151
+ %{(#{this} == (#{that}) ? Qtrue : Qfalse)}
152
+ }},
153
+ [:'===',1] => {nil => lambda { |cfun, this, that|
154
+ %{(#{this} == (#{that}) ? Qtrue : Qfalse)}
155
+ }},
156
+ [:'=~',1] => {nil => lambda { |cfun, this, that|
157
+ %{Qfalse}
158
+ }},
159
+ [:'nil?',0] => lambda { |cfun, this|
160
+ %{Qfalse}
161
+ },
162
+ [:'class',0] => lambda { |cfun, this|
163
+ %{rb_obj_class(#{this})}
164
+ },
165
+ }
166
+
167
+ INLINE = {}
168
+
169
+ INLINE[nil] = {
170
+ [:__id__,0] => lambda { |cfun, this|
171
+ %{rb_obj_id(#{this})}
172
+ },
173
+ :__send__ => lambda { |cfun, node, this, args|
174
+ args = split_args(-2, args)
175
+ if args
176
+ method = args.shift
177
+ this = cfun.comp(this);
178
+ cfun.c_scope_res {
179
+ cfun.l "VALUE recv = #{this};"
180
+ cfun.build_args(args)
181
+ %{rb_funcall2(#{this}, rb_to_id(#{cfun.comp(method)}), argc, argv)}
182
+ }
183
+ else
184
+ node
185
+ end
186
+ }
187
+ }
188
+
189
+ INLINE[NilClass] = COMMON.merge({
190
+ [:'&',1] => {nil => lambda { |cfun, this, that|
191
+ %{Qfalse}
192
+ }},
193
+ [:'|',1] => {nil => lambda { |cfun, this, that|
194
+ %{(RTEST(#{that}) ? Qtrue : Qfalse)}
195
+ }},
196
+ [:'^',1] => {nil => lambda { |cfun, this, that|
197
+ %{(RTEST(#{that}) ? Qtrue : Qfalse)}
198
+ }},
199
+ [:'to_i',0] => lambda { |cfun, this|
200
+ %{INT2FIX(0)}
201
+ },
202
+ [:'to_f',0] => lambda { |cfun, this|
203
+ %{rb_float_new(0.0)}
204
+ },
205
+ [:'to_s',0] => lambda { |cfun, this|
206
+ %{rb_str_new2("")}
207
+ },
208
+ [:'to_a',0] => lambda { |cfun, this|
209
+ %{rb_ary_new2(0)}
210
+ },
211
+ [:'inspect',0] => lambda { |cfun, this|
212
+ %{rb_str_new2("nil")}
213
+ },
214
+ [:'nil?',0] => lambda { |cfun, this|
215
+ %{Qtrue}
216
+ },
217
+ })
218
+
219
+ INLINE[FalseClass] = COMMON.merge({
220
+ [:'&',1] => {nil => lambda { |cfun, this, that|
221
+ %{Qfalse}
222
+ }},
223
+ [:'|',1] => {nil => lambda { |cfun, this, that|
224
+ %{(RTEST(#{that}) ? Qtrue : Qfalse)}
225
+ }},
226
+ [:'^',1] => {nil => lambda { |cfun, this, that|
227
+ %{(RTEST(#{that}) ? Qtrue : Qfalse)}
228
+ }},
229
+ [:'to_s',0] => lambda { |cfun, this|
230
+ %{rb_str_new2("false")}
231
+ },
232
+ })
233
+
234
+ INLINE[TrueClass] = COMMON.merge({
235
+ [:'&',1] => {nil => lambda { |cfun, this, that|
236
+ %{(RTEST(#{that}) ? Qtrue : Qfalse)}
237
+ }},
238
+ [:'|',1] => {nil => lambda { |cfun, this, that|
239
+ %{Qtrue}
240
+ }},
241
+ [:'^',1] => {nil => lambda { |cfun, this, that|
242
+ %{(RTEST(#{that}) ? Qfalse : Qtrue)}
243
+ }},
244
+ [:'to_s',0] => lambda { |cfun, this|
245
+ %{rb_str_new2("true")}
246
+ },
247
+ })
248
+
249
+ INLINE[Symbol] = COMMON.merge({
250
+ [:'to_i',0] => lambda { |cfun, this|
251
+ %{LONG2FIX(SYM2ID(#{this}))}
252
+ },
253
+ [:'to_s',0] => lambda { |cfun, this|
254
+ %{rb_str_new2(rb_id2name(SYM2ID(#{this})))}
255
+ },
256
+ [:'to_sym',0] => lambda { |cfun, this|
257
+ this
258
+ },
259
+ [:'id2name',0] => lambda { |cfun, this|
260
+ %{rb_str_new2(rb_id2name(SYM2ID(#{this})))}
261
+ },
262
+ })
263
+
264
+ def self.fixnum_binary(reuse=false) # :yield: cfun, op, this, that
265
+ fix2long = lambda { |val|
266
+ val.clone.gsub!(/\ALONG2FIX\((\d+)\)\Z/, '\1') or
267
+ %{FIX2LONG(#{val})}
268
+ }
269
+ {
270
+ Fixnum => lambda { |cfun, this, that|
271
+ this = fix2long[this]
272
+ that = fix2long[that]
273
+ if reuse
274
+ c_scope_res {
275
+ cfun.l("long a = #{this};")
276
+ cfun.l("long b = #{that};")
277
+ yield(cfun, "a", "b")
278
+ }
279
+ else
280
+ yield(cfun, this, that)
281
+ end
282
+ }
283
+ }
284
+ end
285
+
286
+ INLINE[Fixnum] = COMMON.merge({
287
+ [:'===',1] => {Fixnum => lambda { |cfun, this, that|
288
+ %{((#{this} == #{that}) ? Qtrue : Qfalse)}
289
+ }},
290
+ [:'==',1] => {Fixnum => lambda { |cfun, this, that|
291
+ %{((#{this} == #{that}) ? Qtrue : Qfalse)}
292
+ }},
293
+ [:'>',1] => fixnum_binary { |cfun, this, that|
294
+ %{((#{this} > #{that}) ? Qtrue : Qfalse)}
295
+ },
296
+ [:'>=',1] => fixnum_binary { |cfun, this, that|
297
+ %{((#{this} >= #{that}) ? Qtrue : Qfalse)}
298
+ },
299
+ [:'<',1] => fixnum_binary { |cfun, this, that|
300
+ %{((#{this} < #{that}) ? Qtrue : Qfalse)}
301
+ },
302
+ [:'<=',1] => fixnum_binary { |cfun, this, that|
303
+ %{((#{this} <= #{that}) ? Qtrue : Qfalse)}
304
+ },
305
+ [:'<=>',1] => fixnum_binary(true) { |cfun, this, that|
306
+ %{INT2FIX((#{this} > #{that}) - (#{this} < #{that}))}
307
+ },
308
+ [:'+',1] => fixnum_binary { |cfun, this, that|
309
+ %{LONG2NUM(#{this} + #{that})}
310
+ },
311
+ [:'-',1] => fixnum_binary { |cfun, this, that|
312
+ %{LONG2NUM(#{this} - #{that})}
313
+ },
314
+ [:'&',1] => fixnum_binary { |cfun, this, that|
315
+ %{LONG2NUM(#{this} & #{that})}
316
+ },
317
+ [:'|',1] => fixnum_binary { |cfun, this, that|
318
+ %{LONG2NUM(#{this} | #{that})}
319
+ },
320
+ [:'^',1] => fixnum_binary { |cfun, this, that|
321
+ %{LONG2NUM(#{this} ^ #{that})}
322
+ },
323
+ [:'-@',0] => lambda { |cfun, this|
324
+ %{LONG2NUM(-FIX2LONG(#{this}))}
325
+ },
326
+ [:'to_f',0] => lambda { |cfun, this|
327
+ %{rb_float_new((double)FIX2LONG(#{this}))}
328
+ },
329
+ [:'size',0] => lambda { |cfun, this|
330
+ %{INT2FIX(sizeof(long))}
331
+ },
332
+ [:'zero?',0] => lambda { |cfun, this|
333
+ %{(FIX2LONG(#{this}) ? Qfalse : Qtrue)}
334
+ },
335
+ [:'abs',0] => lambda { |cfun, this, *|
336
+ cfun.l("long i = FIX2LONG(#{this});")
337
+ %{LONG2NUM((i < 0) ? -i : i)}
338
+ },
339
+ [:'to_s',0] => lambda { |cfun, this|
340
+ %{rb_fix2str(#{this}, 10)}
341
+ },
342
+ [:'to_int',0] => lambda { |cfun, this|
343
+ this
344
+ },
345
+ [:'to_i',0] => lambda { |cfun, this|
346
+ this
347
+ },
348
+ [:'floor',0] => lambda { |cfun, this|
349
+ this
350
+ },
351
+ [:'ceil',0] => lambda { |cfun, this|
352
+ this
353
+ },
354
+ [:'round',0] => lambda { |cfun, this|
355
+ this
356
+ },
357
+ [:'truncate',0] => lambda { |cfun, this|
358
+ this
359
+ },
360
+ [:'succ',0] => lambda { |cfun, this|
361
+ %{LONG2NUM(FIX2LONG(#{this}) + 1)}
362
+ },
363
+ [:'next',0] => lambda { |cfun, this|
364
+ %{LONG2NUM(FIX2LONG(#{this}) + 1)}
365
+ },
366
+ [:'integer?',0] => lambda { |cfun, this|
367
+ %{Qtrue}
368
+ },
369
+ })
370
+
371
+ def self.float_binary(reuse=false) # :yield: cfun, op, this, that
372
+ handle = lambda { |cfun, this, that|
373
+ this = %{RFLOAT(#{this})->value}
374
+ if reuse
375
+ c_scope_res {
376
+ cfun.l("double a = #{this};")
377
+ cfun.l("double b = #{that};")
378
+ yield(cfun, "a", "b")
379
+ }
380
+ else
381
+ yield(cfun, this, that)
382
+ end
383
+ }
384
+ {
385
+ Fixnum => lambda { |cfun, this, that|
386
+ handle[cfun, this, %{((double)FIX2LONG(#{that}))}]
387
+ },
388
+ Float => lambda { |cfun, this, that|
389
+ handle[cfun, this, %{RFLOAT(#{that})->value}]
390
+ },
391
+ Bignum => lambda { |cfun, this, that|
392
+ handle[cfun, this, %{rb_big2dbl(#{that})}]
393
+ },
394
+ }
395
+ end
396
+
397
+ INLINE[Float] = COMMON.merge({
398
+ [:eql?,1] => {nil => lambda { |cfun, this, that|
399
+ %{((#{Class2Match[Float][this]} &&
400
+ !isnan(#{this}) && !isnan(#{that}) &&
401
+ (#{this} == #{that})
402
+ ) ? Qtrue : Qfalse)}
403
+ }},
404
+ [:'===',1] => float_binary(true) {
405
+ %{((!isnan(#{this}) && !isnan(#{that}) && (#{this} == #{that})) ? Qtrue : Qfalse)}
406
+ },
407
+ [:'==',1] => float_binary(true) { |cfun, this, that|
408
+ %{((!isnan(#{this}) && !isnan(#{that}) &&
409
+ (#{this} == #{that})) ? Qtrue : Qfalse)}
410
+ },
411
+ [:'<=>',1] => float_binary(true) { |cfun, this, that|
412
+ %{((isnan(#{this}) || isnan(#{that})) ? Qnil :
413
+ INT2FIX((#{this} > #{that}) - (#{this} < #{that})))}
414
+ },
415
+ [:'>',1] => float_binary(true) { |cfun, this, that|
416
+ %{((!isnan(#{this}) && !isnan(#{that}) &&
417
+ (#{this} > #{that})) ? Qtrue : Qfalse)}
418
+ },
419
+ [:'>=',1] => float_binary(true) { |cfun, this, that|
420
+ %{((!isnan(#{this}) && !isnan(#{that}) &&
421
+ (#{this} >= #{that})) ? Qtrue : Qfalse)}
422
+ },
423
+ [:'<',1] => float_binary(true) { |cfun, this, that|
424
+ %{((!isnan(#{this}) && !isnan(#{that}) &&
425
+ (#{this} < #{that})) ? Qtrue : Qfalse)}
426
+ },
427
+ [:'<=',1] => float_binary(true) { |cfun, this, that|
428
+ %{((!isnan(#{this}) && !isnan(#{that}) &&
429
+ (#{this} <= #{that})) ? Qtrue : Qfalse)}
430
+ },
431
+ [:'+',1] => float_binary { |cfun, this, that|
432
+ %{rb_float_new(#{this} + #{that})}
433
+ },
434
+ [:'-',1] => float_binary { |cfun, this, that|
435
+ %{rb_float_new(#{this} - #{that})}
436
+ },
437
+ [:'*',1] => float_binary { |cfun, this, that|
438
+ %{rb_float_new(#{this} * #{that})}
439
+ },
440
+ [:'/',1] => float_binary { |cfun, this, that|
441
+ %{rb_float_new(#{this} / #{that})}
442
+ },
443
+ [:'**',1] => float_binary { |cfun, this, that|
444
+ %{rb_float_new(pow(#{this}, #{that}))}
445
+ },
446
+ [:'-@',0] => lambda { |cfun, this|
447
+ %{rb_float_new(-RFLOAT(#{this})->value)}
448
+ },
449
+ [:'to_f',0] => lambda { |cfun, this|
450
+ this
451
+ },
452
+ [:'abs',0] => lambda { |cfun, this|
453
+ %{rb_float_new(fabs(RFLOAT(#{this})->value))}
454
+ },
455
+ [:'zero?',0] => lambda { |cfun, this|
456
+ %{((RFLOAT(#{this})->value == 0.0) ? Qtrue : Qfalse)}
457
+ },
458
+ [:'to_i',0] => lambda { |cfun, this|
459
+ cfun.c_scope_res {
460
+ cfun.l("double f = RFLOAT(#{this})->value;")
461
+ cfun.l("f = (f >= 0.0) ? floor(f) : ceil(f);")
462
+ %{(FIXABLE(f) ? LONG2FIX((long)f) : rb_dbl2big(f))}
463
+ }
464
+ },
465
+ [:'to_int',0] => lambda { |cfun, this|
466
+ cfun.c_scope_res {
467
+ cfun.l("double f = RFLOAT(#{this})->value;")
468
+ cfun.l("f = (f >= 0.0) ? floor(f) : ceil(f);")
469
+ %{(FIXABLE(f) ? LONG2FIX((long)f) : rb_dbl2big(f))}
470
+ }
471
+ },
472
+ [:'truncate',0] => lambda { |cfun, this|
473
+ cfun.c_scope_res {
474
+ cfun.l("double f = RFLOAT(#{this})->value;")
475
+ cfun.l("f = (f >= 0.0) ? floor(f) : ceil(f);")
476
+ %{(FIXABLE(f) ? LONG2FIX((long)f) : rb_dbl2big(f))}
477
+ }
478
+ },
479
+ [:'floor',0] => lambda { |cfun, this|
480
+ cfun.c_scope_res {
481
+ cfun.l("double f = floor(RFLOAT(#{this})->value);")
482
+ %{(FIXABLE(f) ? LONG2FIX((long)f) : rb_dbl2big(f))}
483
+ }
484
+ },
485
+ [:'ceil',0] => lambda { |cfun, this|
486
+ cfun.c_scope_res {
487
+ cfun.l("double f = ceil(RFLOAT(#{this})->value);")
488
+ %{(FIXABLE(f) ? LONG2FIX((long)f) : rb_dbl2big(f))}
489
+ }
490
+ },
491
+ [:'round',0] => lambda { |cfun, this|
492
+ cfun.c_scope_res {
493
+ cfun.l("double f = RFLOAT(#{this})->value;")
494
+ cfun.l("f = (f >= 0.0) ? floor(f + 0.5) : ceil(f - 0.5);")
495
+ %{(FIXABLE(f) ? LONG2FIX((long)f) : rb_dbl2big(f))}
496
+ }
497
+ },
498
+ [:'nan?',0] => lambda { |cfun, this|
499
+ %{(isnan(RFLOAT(#{this})->value) ? Qtrue : Qfalse)}
500
+ },
501
+ [:'infinite?',0] => lambda { |cfun, this, *|
502
+ %{(isinf(RFLOAT(#{this})->value) ?
503
+ INT2FIX((RFLOAT(#{this})->value < 0) ? -1 : 1) :
504
+ Qnil)}
505
+ },
506
+ [:'finite?',0] => lambda { |cfun, this|
507
+ %{((isinf(RFLOAT(#{this})->value) || isnan(RFLOAT(#{this})->value)) ? Qfalse : Qtrue)}
508
+ },
509
+ [:'integer?',0] => lambda { |cfun, this|
510
+ %{Qfalse}
511
+ },
512
+ [:'nonzero?',0] => lambda { |cfun, this|
513
+ %{((RFLOAT(#{this})->value == 0.0) ? Qfalse : Qtrue)}
514
+ },
515
+ })
516
+
517
+ INLINE[String] = COMMON.merge({
518
+ [:'eql?',1] => {nil => lambda { |cfun, this, that|
519
+ %{(((TYPE(#{that}) == T_STRING) &&
520
+ (RSTRING(#{this})->len == RSTRING(#{that})->len) &&
521
+ !memcmp(#{this}, #{that}, RSTRING(#{this})->len)
522
+ ) ? Qtrue : Qfalse)}
523
+ }},
524
+ [:'==',1] => {String => lambda { |cfun, this, that|
525
+ %{(((RSTRING(#{this})->len == RSTRING(#{that})->len) &&
526
+ !rb_memcmp(#{this}, #{that}, RSTRING(#{this})->len)
527
+ ) ? Qtrue : Qfalse)}
528
+ }},
529
+ [:'===',1] => {String => lambda { |cfun, this, that|
530
+ %{(((RSTRING(#{this})->len == RSTRING(#{that})->len) &&
531
+ !rb_memcmp(#{this}, #{that}, RSTRING(#{this})->len)
532
+ ) ? Qtrue : Qfalse)}
533
+ }},
534
+ [:'=~',1] => {Regexp => lambda { |cfun, this, that|
535
+ %{rb_reg_match(#{that}, #{this})}
536
+ }},
537
+ [:'<=>',1] => {String => lambda { |cfun, this, that|
538
+ %{rb_str_cmp(#{this}, #{that})}
539
+ }},
540
+ [:'[]',1] => {nil => lambda { |cfun, this, that|
541
+ %{rb_str_aref(#{this}, #{that})}
542
+ }},
543
+ [:'[]',2] => {Fixnum => lambda { |cfun, this, index, len|
544
+ %{rb_str_substr(#{this}, FIX2LONG(#{index}), NUM2LONG(#{len}))}
545
+ }},
546
+ [:'[]=',2] => {nil => lambda { |cfun, this, that, other|
547
+ %{rb_str_aset(#{this}, #{that}, #{other})}
548
+ }},
549
+ [:'<<',1] => {nil => lambda { |cfun, this, that|
550
+ %{rb_str_concat(#{this}, #{that})}
551
+ }},
552
+ [:'empty?',0] => lambda { |cfun, this|
553
+ %{(RSTRING(#{this})->len ? Qfalse : Qtrue)}
554
+ },
555
+ [:'length',0] => lambda { |cfun, this|
556
+ %{LONG2NUM(RSTRING(#{this})->len)}
557
+ },
558
+ [:'size',0] => lambda { |cfun, this|
559
+ %{LONG2NUM(RSTRING(#{this})->len)}
560
+ },
561
+ [:'slice',1] => {nil => lambda { |cfun, this, that|
562
+ %{rb_str_aref(#{this}, #{that})}
563
+ }},
564
+ [:'slice',2] => {Fixnum => lambda { |cfun, this, index, len|
565
+ %{rb_str_substr(#{this}, FIX2LONG(#{index}), NUM2LONG(#{len}))}
566
+ }},
567
+ [:'concat',1] => {nil => lambda { |cfun, this, that|
568
+ %{rb_str_concat(#{this}, #{that})}
569
+ }},
570
+ [:'to_sym',0] => lambda { |cfun, this|
571
+ %{rb_str_intern(#{this})}
572
+ },
573
+ [:'intern',0] => lambda { |cfun, this|
574
+ %{rb_str_intern(#{this})}
575
+ },
576
+ [:'inspect',0] => lambda { |cfun, this|
577
+ %{rb_str_inspect(#{this})}
578
+ },
579
+ [:'dump',0] => lambda { |cfun, this|
580
+ %{rb_str_dump(#{this})}
581
+ },
582
+ [:'to_s',0] => lambda { |cfun, this|
583
+ this
584
+ },
585
+ [:'to_str',0] => lambda { |cfun, this|
586
+ this
587
+ },
588
+ [:'to_i',0] => lambda { |cfun, this|
589
+ %{rb_str_to_inum(#{this}, 10, Qfalse)}
590
+ },
591
+ [:'hex',0] => lambda { |cfun, this|
592
+ %{rb_str_to_inum(#{this}, 16, Qfalse)}
593
+ },
594
+ [:'oct',0] => lambda { |cfun, this|
595
+ %{rb_str_to_inum(#{this}, -8, Qfalse)}
596
+ },
597
+ })
598
+
599
+ INLINE[Array] = COMMON.merge({
600
+ [:'eql?',1] => {
601
+ },
602
+ [:'==',1] => {
603
+ },
604
+ [:'===',1] => {
605
+ },
606
+ [:'to_s',0] => lambda { |cfun, this|
607
+ %{rb_ary_to_s(#{this})}
608
+ },
609
+ [:'to_a',0] => lambda { |cfun, this|
610
+ this
611
+ },
612
+ [:'to_ary',0] => lambda { |cfun, this|
613
+ this
614
+ },
615
+ [:'slice',1] => {
616
+ Fixnum => lambda { |cfun, this, index|
617
+ },
618
+ nil => lambda { |cfun, this, index|
619
+ %{rb_ary_aref(1, &#{index}, #{this})}
620
+ }
621
+ },
622
+ [:'slice',2] => {
623
+ nil => lambda { |cfun, this, beg, len, *|
624
+ cfun.c_scope_res {
625
+ cfun.l("long beg = NUM2LONG(#{beg});")
626
+ cfun.l("if (beg<0) beg += RARRAY(#{this})->len;")
627
+ %{rb_ary_subseq(#{this}, beg, #{len})}
628
+ }
629
+ }
630
+ },
631
+ [:'[]',1] => {
632
+ Fixnum => lambda { |cfun, this, index|
633
+ },
634
+ nil => lambda { |cfun, this, index|
635
+ %{rb_ary_aref(1, &#{index}, #{this})}
636
+ }
637
+ },
638
+ [:'[]',2] => {
639
+ nil => lambda { |cfun, this, beg, len, *|
640
+ cfun.c_scope_res {
641
+ cfun.l("long beg = NUM2LONG(#{beg});")
642
+ cfun.l("if (beg<0) beg += RARRAY(#{this})->len;")
643
+ %{rb_ary_subseq(#{this}, beg, #{len})}
644
+ }
645
+ }
646
+ },
647
+ [:'[]=',2] => {Fixnum => lambda { |cfun, this, index, val|
648
+ cfun.l("rb_ary_store(#{this}, FIX2LONG(index), val);")
649
+ val
650
+ }},
651
+ [:'at',1] => {nil => lambda { |cfun, this, that|
652
+ %{rb_ary_entry(#{this}, NUM2LONG(#{that}))}
653
+ }},
654
+ [:'first',0] => lambda { |cfun, this|
655
+ %{((RARRAY(#{this})->len == 0) ? Qnil : RARRAY(#{this})->ptr[0])}
656
+ },
657
+ [:'last',0] => lambda { |cfun, this|
658
+ %{((RARRAY(#{this})->len == 0) ? Qnil : RARRAY(#{this})->ptr[RARRAY(#{this})->len-1])}
659
+ },
660
+ [:'concat',1] => {nil => lambda { |cfun, this, that|
661
+ %{rb_ary_concat(#{this}, #{that})}
662
+ }},
663
+ [:'<<',1] => {nil => lambda { |cfun, this, that|
664
+ %{rb_ary_push(#{this}, #{that})}
665
+ }},
666
+ [:'push',1] => {nil => lambda { |cfun, this, that|
667
+ %{rb_ary_push(#{this}, #{that})}
668
+ }},
669
+ [:'pop',0] => lambda { |cfun, this|
670
+ %{rb_ary_pop(#{this})}
671
+ },
672
+ [:'shift',0] => lambda { |cfun, this|
673
+ %{rb_ary_shift(#{this})}
674
+ },
675
+ [:'unshift',1] => {nil => lambda { |cfun, this, that|
676
+ %{rb_ary_unshift(#{this}, #{that})}
677
+ }},
678
+ [:'length',0] => lambda { |cfun, this|
679
+ %{LONG2NUM(RARRAY(#{this})->len)}
680
+ },
681
+ [:'size',0] => lambda { |cfun, this|
682
+ %{LONG2NUM(RARRAY(#{this})->len)}
683
+ },
684
+ [:'empty?',0] => lambda { |cfun, this|
685
+ %{(RARRAY(#{this})->len ? Qfalse : Qtrue)}
686
+ },
687
+ [:'reverse!',0] => lambda { |cfun, this|
688
+ %{rb_ary_reverse(#{this})}
689
+ },
690
+ [:'delete_at',1] => {nil => lambda { |cfun, this, that|
691
+ %{rb_ary_delete_at(#{this}, NUM2LONG(#{that}))}
692
+ }},
693
+ [:'clear',0] => lambda { |cfun, this|
694
+ %{rb_ary_clear(#{this})}
695
+ },
696
+ [:'include?',1] => {nil => lambda { |cfun, this, that|
697
+ %{rb_ary_includes(#{this}, #{that})}
698
+ }},
699
+ [:'<=>',1] => {nil => lambda { |cfun, this, that|
700
+ %{rb_ary_cmp(#{this}, #{that})}
701
+ }},
702
+ [:'+',1] => {nil => lambda { |cfun, this, that|
703
+ %{rb_ary_plus(#{this}, #{that})}
704
+ }},
705
+ [:'join',1] => {nil => lambda { |cfun, this, that|
706
+ %{rb_ary_join(#{this}, #{that})}
707
+ }},
708
+ })
709
+
710
+ INLINE[Hash] = COMMON.merge({
711
+ [:'eql?',1] => {
712
+ },
713
+ [:'==',1] => {
714
+ },
715
+ [:'===',1] => {
716
+ },
717
+ [:'to_hash',0] => lambda { |cfun, this|
718
+ this
719
+ },
720
+ [:'[]',1] => {nil => lambda { |cfun, this, that|
721
+ %{rb_hash_aref(#{this}, #{that})}
722
+ }},
723
+ [:'[]=',2] => {nil => lambda { |cfun, this, that, other|
724
+ %{rb_hash_aset(#{this}, #{that}, #{other})}
725
+ }},
726
+ [:'store',2] => {nil => lambda { |cfun, this, that, other|
727
+ %{rb_hash_aset(#{this}, #{that}, #{other})}
728
+ }},
729
+ [:'length',0] => lambda { |cfun, this|
730
+ %{INT2FIX(RHASH(#{this})->tbl->num_entries)}
731
+ },
732
+ [:'size',0] => lambda { |cfun, this|
733
+ %{INT2FIX(RHASH(#{this})->tbl->num_entries)}
734
+ },
735
+ [:'empty?',0] => lambda { |cfun, this|
736
+ %{(RHASH(#{this})->tbl->num_entries ? Qfalse : Qtrue)}
737
+ },
738
+ [:'delete',1] => {nil => lambda { |cfun, this, that|
739
+ %{rb_hash_delete(#{this}, #{that})}
740
+ }},
741
+ })
742
+
743
+ INLINE[Range] = COMMON.merge({
744
+ [:'eql?',1] => {nil => lambda { |cfun, this, that|
745
+ %{((rb_obj_is_instance_of(#{that}, rb_obj_class(#{this})) &&
746
+ (rb_eql(rb_ivar_get(#{this}, #{cfun.sym(:begin)}), rb_ivar_get(#{that}, #{cfun.sym(:begin)}))) &&
747
+ (rb_eql(rb_ivar_get(#{this}, #{cfun.sym(:end)}), rb_ivar_get(#{that}, #{cfun.sym(:end)}))) &&
748
+ (rb_eql(rb_ivar_get(#{this}, #{cfun.sym(:excl)}), rb_ivar_get(#{that}, #{cfun.sym(:excl)})))
749
+ ) ? Qtrue : Qfalse)}
750
+ }},
751
+ [:'==',1] => {nil => lambda { |cfun, this, that|
752
+ %{((rb_obj_is_instance_of(#{that}, rb_obj_class(#{this})) &&
753
+ (rb_equal(rb_ivar_get(#{this}, #{cfun.sym(:begin)}), rb_ivar_get(#{that}, #{cfun.sym(:begin)}))) &&
754
+ (rb_equal(rb_ivar_get(#{this}, #{cfun.sym(:end)}), rb_ivar_get(#{that}, #{cfun.sym(:end)}))) &&
755
+ (rb_equal(rb_ivar_get(#{this}, #{cfun.sym(:excl)}), rb_ivar_get(#{that}, #{cfun.sym(:excl)})))
756
+ ) ? Qtrue : Qfalse)}
757
+ }},
758
+ [:'===',1] => {
759
+ },
760
+ [:'first',0] => lambda { |cfun, this|
761
+ %{rb_ivar_get(#{this}, #{cfun.sym(:begin)})}
762
+ },
763
+ [:'begin',0] => lambda { |cfun, this|
764
+ %{rb_ivar_get(#{this}, #{cfun.sym(:begin)})}
765
+ },
766
+ [:'last',0] => lambda { |cfun, this|
767
+ %{rb_ivar_get(#{this}, #{cfun.sym(:end)})}
768
+ },
769
+ [:'end',0] => lambda { |cfun, this|
770
+ %{rb_ivar_get(#{this}, #{cfun.sym(:end)})}
771
+ },
772
+ [:'exclude_end?',0] => lambda { |cfun, this|
773
+ %{rb_ivar_get(#{this}, #{cfun.sym(:excl)})}
774
+ },
775
+ })
776
+
777
+ INLINE[Regexp] = COMMON.merge({
778
+ [:'eql?',1] => {
779
+ },
780
+ [:'==',1] => {
781
+ },
782
+ [:'===',1] => {String => lambda { |cfun, this, that|
783
+ cfun.l("StringValue(#{that});")
784
+ %{((rb_reg_search(#{this}, #{that}) < 0) ? Qfalse : Qtrue)}
785
+ }},
786
+ [:'=~',1] => {nil => lambda { |cfun, this, that|
787
+ %{rb_reg_match(#{this}, #{that})}
788
+ }},
789
+ [:'~',0] => lambda { |cfun, this|
790
+ %{rb_reg_match2(#{this})}
791
+ },
792
+ })
793
+
794
+ end
795
+
796
+ end
797
+