13514
|
1 /*
|
|
2 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
|
|
3 * code is released under a tri EPL/GPL/LGPL license. You can use it,
|
|
4 * redistribute it and/or modify it under the terms of the:
|
|
5 *
|
|
6 * Eclipse Public License version 1.0
|
|
7 * GNU General Public License version 2
|
|
8 * GNU Lesser General Public License version 2.1
|
|
9 */
|
|
10 package com.oracle.truffle.ruby.nodes.core;
|
|
11
|
|
12 import java.math.*;
|
|
13
|
|
14 import com.oracle.truffle.api.*;
|
|
15 import com.oracle.truffle.api.dsl.*;
|
|
16 import com.oracle.truffle.api.frame.*;
|
|
17 import com.oracle.truffle.ruby.runtime.*;
|
|
18 import com.oracle.truffle.ruby.runtime.core.*;
|
|
19 import com.oracle.truffle.ruby.runtime.core.array.*;
|
|
20
|
|
21 @CoreClass(name = "Fixnum")
|
|
22 public abstract class FixnumNodes {
|
|
23
|
|
24 @CoreMethod(names = "+@", maxArgs = 0)
|
|
25 public abstract static class PosNode extends CoreMethodNode {
|
|
26
|
|
27 public PosNode(RubyContext context, SourceSection sourceSection) {
|
|
28 super(context, sourceSection);
|
|
29 }
|
|
30
|
|
31 public PosNode(PosNode prev) {
|
|
32 super(prev);
|
|
33 }
|
|
34
|
|
35 @Specialization
|
|
36 public int pos(int value) {
|
|
37 return value;
|
|
38 }
|
|
39
|
|
40 }
|
|
41
|
|
42 @CoreMethod(names = "-@", maxArgs = 0)
|
|
43 public abstract static class NegNode extends CoreMethodNode {
|
|
44
|
|
45 public NegNode(RubyContext context, SourceSection sourceSection) {
|
|
46 super(context, sourceSection);
|
|
47 }
|
|
48
|
|
49 public NegNode(NegNode prev) {
|
|
50 super(prev);
|
|
51 }
|
|
52
|
|
53 @Specialization(rewriteOn = ArithmeticException.class)
|
|
54 public int neg(int value) {
|
|
55 return ExactMath.subtractExact(0, value);
|
|
56 }
|
|
57
|
|
58 @Specialization
|
|
59 public BigInteger negWithOverflow(int value) {
|
|
60 return BigInteger.valueOf(value).negate();
|
|
61 }
|
|
62
|
|
63 }
|
|
64
|
|
65 @CoreMethod(names = "+", minArgs = 1, maxArgs = 1)
|
|
66 public abstract static class AddNode extends CoreMethodNode {
|
|
67
|
|
68 public AddNode(RubyContext context, SourceSection sourceSection) {
|
|
69 super(context, sourceSection);
|
|
70 }
|
|
71
|
|
72 public AddNode(AddNode prev) {
|
|
73 super(prev);
|
|
74 }
|
|
75
|
|
76 @Specialization(rewriteOn = ArithmeticException.class)
|
|
77 public int add(int a, int b) {
|
|
78 return ExactMath.addExact(a, b);
|
|
79 }
|
|
80
|
|
81 @Specialization
|
|
82 public Object addWithOverflow(int a, int b) {
|
|
83 return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).add(BigInteger.valueOf(b)));
|
|
84 }
|
|
85
|
|
86 @Specialization
|
|
87 public double add(int a, double b) {
|
|
88 return a + b;
|
|
89 }
|
|
90
|
|
91 @Specialization
|
|
92 public Object add(int a, BigInteger b) {
|
|
93 return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).add(b));
|
|
94 }
|
|
95
|
|
96 }
|
|
97
|
|
98 @CoreMethod(names = "-", minArgs = 1, maxArgs = 1)
|
|
99 public abstract static class SubNode extends CoreMethodNode {
|
|
100
|
|
101 public SubNode(RubyContext context, SourceSection sourceSection) {
|
|
102 super(context, sourceSection);
|
|
103 }
|
|
104
|
|
105 public SubNode(SubNode prev) {
|
|
106 super(prev);
|
|
107 }
|
|
108
|
|
109 @Specialization(rewriteOn = ArithmeticException.class)
|
|
110 public int sub(int a, int b) {
|
|
111 return ExactMath.subtractExact(a, b);
|
|
112 }
|
|
113
|
|
114 @Specialization
|
|
115 public Object subWithOverflow(int a, int b) {
|
|
116 return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).subtract(BigInteger.valueOf(b)));
|
|
117 }
|
|
118
|
|
119 @Specialization
|
|
120 public double sub(int a, double b) {
|
|
121 return a - b;
|
|
122 }
|
|
123
|
|
124 @Specialization
|
|
125 public Object sub(int a, BigInteger b) {
|
|
126 return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).subtract(b));
|
|
127 }
|
|
128
|
|
129 }
|
|
130
|
|
131 @CoreMethod(names = "*", minArgs = 1, maxArgs = 1)
|
|
132 public abstract static class MulNode extends CoreMethodNode {
|
|
133
|
|
134 public MulNode(RubyContext context, SourceSection sourceSection) {
|
|
135 super(context, sourceSection);
|
|
136 }
|
|
137
|
|
138 public MulNode(MulNode prev) {
|
|
139 super(prev);
|
|
140 }
|
|
141
|
|
142 @Specialization(rewriteOn = ArithmeticException.class)
|
|
143 public int mul(int a, int b) {
|
|
144 return ExactMath.multiplyExact(a, b);
|
|
145 }
|
|
146
|
|
147 @Specialization
|
|
148 public Object mulWithOverflow(int a, int b) {
|
|
149 return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).multiply(BigInteger.valueOf(b)));
|
|
150 }
|
|
151
|
|
152 @Specialization
|
|
153 public double mul(int a, double b) {
|
|
154 return a * b;
|
|
155 }
|
|
156
|
|
157 @Specialization
|
|
158 public Object mul(int a, BigInteger b) {
|
|
159 return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).multiply(b));
|
|
160 }
|
|
161
|
|
162 }
|
|
163
|
|
164 @CoreMethod(names = "**", minArgs = 1, maxArgs = 1)
|
|
165 public abstract static class PowNode extends CoreMethodNode {
|
|
166
|
|
167 public PowNode(RubyContext context, SourceSection sourceSection) {
|
|
168 super(context, sourceSection);
|
|
169 }
|
|
170
|
|
171 public PowNode(PowNode prev) {
|
|
172 super(prev);
|
|
173 }
|
|
174
|
|
175 @Specialization
|
|
176 public Object pow(int a, int b) {
|
|
177 return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).pow(b));
|
|
178 }
|
|
179
|
|
180 @Specialization
|
|
181 public double pow(int a, double b) {
|
|
182 return Math.pow(a, b);
|
|
183 }
|
|
184
|
|
185 @Specialization
|
|
186 public Object pow(int a, BigInteger b) {
|
|
187 final BigInteger bigA = BigInteger.valueOf(a);
|
|
188
|
|
189 BigInteger result = BigInteger.ONE;
|
|
190
|
|
191 for (BigInteger n = BigInteger.ZERO; b.compareTo(b) < 0; n = n.add(BigInteger.ONE)) {
|
|
192 result = result.multiply(bigA);
|
|
193 }
|
|
194
|
|
195 return result;
|
|
196 }
|
|
197
|
|
198 }
|
|
199
|
|
200 @CoreMethod(names = "/", minArgs = 1, maxArgs = 1)
|
|
201 public abstract static class DivNode extends CoreMethodNode {
|
|
202
|
|
203 public DivNode(RubyContext context, SourceSection sourceSection) {
|
|
204 super(context, sourceSection);
|
|
205 }
|
|
206
|
|
207 public DivNode(DivNode prev) {
|
|
208 super(prev);
|
|
209 }
|
|
210
|
|
211 @Specialization
|
|
212 public int div(int a, int b) {
|
|
213 return a / b;
|
|
214 }
|
|
215
|
|
216 @Specialization
|
|
217 public double div(int a, double b) {
|
|
218 return a / b;
|
|
219 }
|
|
220
|
|
221 @Specialization
|
|
222 public int div(@SuppressWarnings("unused") int a, @SuppressWarnings("unused") BigInteger b) {
|
|
223 return 0;
|
|
224 }
|
|
225 }
|
|
226
|
|
227 @CoreMethod(names = "%", minArgs = 1, maxArgs = 1)
|
|
228 public abstract static class ModNode extends CoreMethodNode {
|
|
229
|
|
230 public ModNode(RubyContext context, SourceSection sourceSection) {
|
|
231 super(context, sourceSection);
|
|
232 }
|
|
233
|
|
234 public ModNode(ModNode prev) {
|
|
235 super(prev);
|
|
236 }
|
|
237
|
|
238 @Specialization
|
|
239 public int mod(int a, int b) {
|
|
240 return a % b;
|
|
241 }
|
|
242
|
|
243 @Specialization
|
|
244 public double mod(@SuppressWarnings("unused") int a, @SuppressWarnings("unused") double b) {
|
|
245 throw new UnsupportedOperationException();
|
|
246 }
|
|
247
|
|
248 @Specialization
|
|
249 public BigInteger mod(@SuppressWarnings("unused") int a, BigInteger b) {
|
|
250 return b;
|
|
251 }
|
|
252 }
|
|
253
|
|
254 @CoreMethod(names = "divmod", minArgs = 1, maxArgs = 1)
|
|
255 public abstract static class DivModNode extends CoreMethodNode {
|
|
256
|
|
257 public DivModNode(RubyContext context, SourceSection sourceSection) {
|
|
258 super(context, sourceSection);
|
|
259 }
|
|
260
|
|
261 public DivModNode(DivModNode prev) {
|
|
262 super(prev);
|
|
263 }
|
|
264
|
|
265 @Specialization
|
|
266 public RubyArray divMod(int a, int b) {
|
|
267 int q;
|
|
268
|
|
269 if (b < 0) {
|
|
270 if (a < 0) {
|
|
271 q = -a / -b;
|
|
272 } else {
|
|
273 q = -(a / -b);
|
|
274 }
|
|
275 } else {
|
|
276 if (a < 0) {
|
|
277 q = -(-a / b);
|
|
278 } else {
|
|
279 q = a / b;
|
|
280 }
|
|
281 }
|
|
282
|
|
283 int r = a - q * b;
|
|
284
|
|
285 if ((r < 0 && b > 0) || (r > 0 && b < 0)) {
|
|
286 r += b;
|
|
287 q -= 1;
|
|
288 }
|
|
289
|
|
290 final FixnumImmutablePairArrayStore store = new FixnumImmutablePairArrayStore(q, r);
|
|
291 return new RubyArray(getContext().getCoreLibrary().getArrayClass(), store);
|
|
292 }
|
|
293
|
|
294 @Specialization
|
|
295 public RubyArray divMod(@SuppressWarnings("unused") int a, @SuppressWarnings("unused") double b) {
|
|
296 throw new UnsupportedOperationException();
|
|
297 }
|
|
298
|
|
299 @Specialization
|
|
300 public RubyArray divMod(int a, BigInteger b) {
|
|
301 return RubyBignum.divMod(getContext(), BigInteger.valueOf(a), b);
|
|
302 }
|
|
303 }
|
|
304
|
|
305 @CoreMethod(names = "<", minArgs = 1, maxArgs = 1)
|
|
306 public abstract static class LessNode extends CoreMethodNode {
|
|
307
|
|
308 public LessNode(RubyContext context, SourceSection sourceSection) {
|
|
309 super(context, sourceSection);
|
|
310 }
|
|
311
|
|
312 public LessNode(LessNode prev) {
|
|
313 super(prev);
|
|
314 }
|
|
315
|
|
316 @Specialization
|
|
317 public boolean less(int a, int b) {
|
|
318 return a < b;
|
|
319 }
|
|
320
|
|
321 @Specialization
|
|
322 public boolean less(int a, double b) {
|
|
323 return a < b;
|
|
324 }
|
|
325
|
|
326 @Specialization
|
|
327 public boolean less(int a, BigInteger b) {
|
|
328 return BigInteger.valueOf(a).compareTo(b) < 0;
|
|
329 }
|
|
330 }
|
|
331
|
|
332 @CoreMethod(names = "<=", minArgs = 1, maxArgs = 1)
|
|
333 public abstract static class LessEqualNode extends CoreMethodNode {
|
|
334
|
|
335 public LessEqualNode(RubyContext context, SourceSection sourceSection) {
|
|
336 super(context, sourceSection);
|
|
337 }
|
|
338
|
|
339 public LessEqualNode(LessEqualNode prev) {
|
|
340 super(prev);
|
|
341 }
|
|
342
|
|
343 @Specialization
|
|
344 public boolean lessEqual(int a, int b) {
|
|
345 return a <= b;
|
|
346 }
|
|
347
|
|
348 @Specialization
|
|
349 public boolean lessEqual(int a, double b) {
|
|
350 return a <= b;
|
|
351 }
|
|
352
|
|
353 @Specialization
|
|
354 public boolean lessEqual(int a, BigInteger b) {
|
|
355 return BigInteger.valueOf(a).compareTo(b) <= 0;
|
|
356 }
|
|
357 }
|
|
358
|
|
359 @CoreMethod(names = {"==", "==="}, minArgs = 1, maxArgs = 1)
|
|
360 public abstract static class EqualNode extends CoreMethodNode {
|
|
361
|
|
362 public EqualNode(RubyContext context, SourceSection sourceSection) {
|
|
363 super(context, sourceSection);
|
|
364 }
|
|
365
|
|
366 public EqualNode(EqualNode prev) {
|
|
367 super(prev);
|
|
368 }
|
|
369
|
|
370 @Specialization
|
|
371 public boolean equal(int a, int b) {
|
|
372 return a == b;
|
|
373 }
|
|
374
|
|
375 @Specialization
|
|
376 public boolean equal(int a, double b) {
|
|
377 return a == b;
|
|
378 }
|
|
379
|
|
380 @Specialization
|
|
381 public boolean equal(int a, BigInteger b) {
|
|
382 return BigInteger.valueOf(a).compareTo(b) == 0;
|
|
383 }
|
|
384 }
|
|
385
|
|
386 @CoreMethod(names = "<=>", minArgs = 1, maxArgs = 1)
|
|
387 public abstract static class CompareNode extends CoreMethodNode {
|
|
388
|
|
389 public CompareNode(RubyContext context, SourceSection sourceSection) {
|
|
390 super(context, sourceSection);
|
|
391 }
|
|
392
|
|
393 public CompareNode(CompareNode prev) {
|
|
394 super(prev);
|
|
395 }
|
|
396
|
|
397 @Specialization
|
|
398 public int compare(int a, int b) {
|
|
399 return Integer.compare(a, b);
|
|
400 }
|
|
401
|
|
402 @Specialization
|
|
403 public int compare(int a, double b) {
|
|
404 return Double.compare(a, b);
|
|
405 }
|
|
406
|
|
407 @Specialization
|
|
408 public int compare(int a, BigInteger b) {
|
|
409 return BigInteger.valueOf(a).compareTo(b);
|
|
410 }
|
|
411 }
|
|
412
|
|
413 @CoreMethod(names = "!=", minArgs = 1, maxArgs = 1)
|
|
414 public abstract static class NotEqualNode extends CoreMethodNode {
|
|
415
|
|
416 public NotEqualNode(RubyContext context, SourceSection sourceSection) {
|
|
417 super(context, sourceSection);
|
|
418 }
|
|
419
|
|
420 public NotEqualNode(NotEqualNode prev) {
|
|
421 super(prev);
|
|
422 }
|
|
423
|
|
424 @Specialization
|
|
425 public boolean notEqual(int a, int b) {
|
|
426 return a != b;
|
|
427 }
|
|
428
|
|
429 @Specialization
|
|
430 public boolean notEqual(int a, double b) {
|
|
431 return a != b;
|
|
432 }
|
|
433
|
|
434 @Specialization
|
|
435 public boolean notEqual(int a, BigInteger b) {
|
|
436 return BigInteger.valueOf(a).compareTo(b) != 0;
|
|
437 }
|
|
438 }
|
|
439
|
|
440 @CoreMethod(names = ">=", minArgs = 1, maxArgs = 1)
|
|
441 public abstract static class GreaterEqualNode extends CoreMethodNode {
|
|
442
|
|
443 public GreaterEqualNode(RubyContext context, SourceSection sourceSection) {
|
|
444 super(context, sourceSection);
|
|
445 }
|
|
446
|
|
447 public GreaterEqualNode(GreaterEqualNode prev) {
|
|
448 super(prev);
|
|
449 }
|
|
450
|
|
451 @Specialization
|
|
452 public boolean greaterEqual(int a, int b) {
|
|
453 return a >= b;
|
|
454 }
|
|
455
|
|
456 @Specialization
|
|
457 public boolean greaterEqual(int a, double b) {
|
|
458 return a >= b;
|
|
459 }
|
|
460
|
|
461 @Specialization
|
|
462 public boolean greaterEqual(int a, BigInteger b) {
|
|
463 return BigInteger.valueOf(a).compareTo(b) >= 0;
|
|
464 }
|
|
465 }
|
|
466
|
|
467 @CoreMethod(names = ">", minArgs = 1, maxArgs = 1)
|
|
468 public abstract static class GreaterNode extends CoreMethodNode {
|
|
469
|
|
470 public GreaterNode(RubyContext context, SourceSection sourceSection) {
|
|
471 super(context, sourceSection);
|
|
472 }
|
|
473
|
|
474 public GreaterNode(GreaterNode prev) {
|
|
475 super(prev);
|
|
476 }
|
|
477
|
|
478 @Specialization
|
|
479 public boolean equal(int a, int b) {
|
|
480 return a > b;
|
|
481 }
|
|
482
|
|
483 @Specialization
|
|
484 public boolean equal(int a, double b) {
|
|
485 return a > b;
|
|
486 }
|
|
487
|
|
488 @Specialization
|
|
489 public boolean equal(int a, BigInteger b) {
|
|
490 return BigInteger.valueOf(a).compareTo(b) > 0;
|
|
491 }
|
|
492 }
|
|
493
|
|
494 @CoreMethod(names = "~", maxArgs = 0)
|
|
495 public abstract static class ComplementNode extends CoreMethodNode {
|
|
496
|
|
497 public ComplementNode(RubyContext context, SourceSection sourceSection) {
|
|
498 super(context, sourceSection);
|
|
499 }
|
|
500
|
|
501 public ComplementNode(ComplementNode prev) {
|
|
502 super(prev);
|
|
503 }
|
|
504
|
|
505 @Specialization
|
|
506 public int complement(int n) {
|
|
507 return ~n;
|
|
508 }
|
|
509
|
|
510 }
|
|
511
|
|
512 @CoreMethod(names = "&", minArgs = 1, maxArgs = 1)
|
|
513 public abstract static class BitAndNode extends CoreMethodNode {
|
|
514
|
|
515 public BitAndNode(RubyContext context, SourceSection sourceSection) {
|
|
516 super(context, sourceSection);
|
|
517 }
|
|
518
|
|
519 public BitAndNode(BitAndNode prev) {
|
|
520 super(prev);
|
|
521 }
|
|
522
|
|
523 @Specialization
|
|
524 public int bitAnd(int a, int b) {
|
|
525 return a & b;
|
|
526 }
|
|
527
|
|
528 @Specialization
|
|
529 public Object bitAnd(int a, BigInteger b) {
|
|
530 return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).and(b));
|
|
531 }
|
|
532 }
|
|
533
|
|
534 @CoreMethod(names = "|", minArgs = 1, maxArgs = 1)
|
|
535 public abstract static class BitOrNode extends CoreMethodNode {
|
|
536
|
|
537 public BitOrNode(RubyContext context, SourceSection sourceSection) {
|
|
538 super(context, sourceSection);
|
|
539 }
|
|
540
|
|
541 public BitOrNode(BitOrNode prev) {
|
|
542 super(prev);
|
|
543 }
|
|
544
|
|
545 @Specialization
|
|
546 public int bitOr(int a, int b) {
|
|
547 return a | b;
|
|
548 }
|
|
549
|
|
550 @Specialization
|
|
551 public Object bitOr(int a, BigInteger b) {
|
|
552 return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).or(b));
|
|
553 }
|
|
554 }
|
|
555
|
|
556 @CoreMethod(names = "^", minArgs = 1, maxArgs = 1)
|
|
557 public abstract static class BitXOrNode extends CoreMethodNode {
|
|
558
|
|
559 public BitXOrNode(RubyContext context, SourceSection sourceSection) {
|
|
560 super(context, sourceSection);
|
|
561 }
|
|
562
|
|
563 public BitXOrNode(BitXOrNode prev) {
|
|
564 super(prev);
|
|
565 }
|
|
566
|
|
567 @Specialization
|
|
568 public int bitXOr(int a, int b) {
|
|
569 return a ^ b;
|
|
570 }
|
|
571
|
|
572 @Specialization
|
|
573 public Object bitXOr(int a, BigInteger b) {
|
|
574 return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).xor(b));
|
|
575 }
|
|
576 }
|
|
577
|
|
578 @CoreMethod(names = "<<", minArgs = 1, maxArgs = 1)
|
|
579 public abstract static class LeftShiftNode extends CoreMethodNode {
|
|
580
|
|
581 public LeftShiftNode(RubyContext context, SourceSection sourceSection) {
|
|
582 super(context, sourceSection);
|
|
583 }
|
|
584
|
|
585 public LeftShiftNode(LeftShiftNode prev) {
|
|
586 super(prev);
|
|
587 }
|
|
588
|
|
589 @Specialization
|
|
590 public Object leftShift(int a, int b) {
|
|
591 if (b > 0) {
|
|
592 if (RubyFixnum.SIZE - Integer.numberOfLeadingZeros(a) + b > RubyFixnum.SIZE - 1) {
|
|
593 return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).shiftLeft(b));
|
|
594 } else {
|
|
595 return a << b;
|
|
596 }
|
|
597 } else {
|
|
598 if (-b >= Integer.SIZE) {
|
|
599 return 0;
|
|
600 } else {
|
|
601 return a >> -b;
|
|
602 }
|
|
603 }
|
|
604 }
|
|
605
|
|
606 }
|
|
607
|
|
608 @CoreMethod(names = ">>", minArgs = 1, maxArgs = 1)
|
|
609 public abstract static class RightShiftNode extends CoreMethodNode {
|
|
610
|
|
611 public RightShiftNode(RubyContext context, SourceSection sourceSection) {
|
|
612 super(context, sourceSection);
|
|
613 }
|
|
614
|
|
615 public RightShiftNode(RightShiftNode prev) {
|
|
616 super(prev);
|
|
617 }
|
|
618
|
|
619 @Specialization
|
|
620 public int rightShift(int a, int b) {
|
|
621 if (b > 0) {
|
|
622 return a >> b;
|
|
623 } else {
|
|
624 if (-b >= RubyFixnum.SIZE) {
|
|
625 return 0;
|
|
626 } else {
|
|
627 return a >> -b;
|
|
628 }
|
|
629 }
|
|
630 }
|
|
631
|
|
632 }
|
|
633
|
|
634 @CoreMethod(names = "[]", minArgs = 1, maxArgs = 1)
|
|
635 public abstract static class GetIndexNode extends CoreMethodNode {
|
|
636
|
|
637 public GetIndexNode(RubyContext context, SourceSection sourceSection) {
|
|
638 super(context, sourceSection);
|
|
639 }
|
|
640
|
|
641 public GetIndexNode(GetIndexNode prev) {
|
|
642 super(prev);
|
|
643 }
|
|
644
|
|
645 @Specialization
|
|
646 public int getIndex(int self, int index) {
|
|
647 if ((self & (1 << index)) == 0) {
|
|
648 return 0;
|
|
649 } else {
|
|
650 return 1;
|
|
651 }
|
|
652 }
|
|
653
|
|
654 }
|
|
655
|
|
656 @CoreMethod(names = "chr", maxArgs = 0)
|
|
657 public abstract static class ChrNode extends CoreMethodNode {
|
|
658
|
|
659 public ChrNode(RubyContext context, SourceSection sourceSection) {
|
|
660 super(context, sourceSection);
|
|
661 }
|
|
662
|
|
663 public ChrNode(ChrNode prev) {
|
|
664 super(prev);
|
|
665 }
|
|
666
|
|
667 @Specialization
|
|
668 public RubyString chr(int n) {
|
|
669 // TODO(CS): not sure about encoding here
|
|
670 return getContext().makeString((char) n);
|
|
671 }
|
|
672
|
|
673 }
|
|
674
|
|
675 @CoreMethod(names = "inspect", maxArgs = 0)
|
|
676 public abstract static class InpsectNode extends CoreMethodNode {
|
|
677
|
|
678 public InpsectNode(RubyContext context, SourceSection sourceSection) {
|
|
679 super(context, sourceSection);
|
|
680 }
|
|
681
|
|
682 public InpsectNode(InpsectNode prev) {
|
|
683 super(prev);
|
|
684 }
|
|
685
|
|
686 @Specialization
|
|
687 public RubyString inspect(int n) {
|
|
688 return getContext().makeString(Integer.toString(n));
|
|
689 }
|
|
690
|
|
691 }
|
|
692
|
|
693 @CoreMethod(names = "nonzero?", maxArgs = 0)
|
|
694 public abstract static class NonZeroNode extends CoreMethodNode {
|
|
695
|
|
696 public NonZeroNode(RubyContext context, SourceSection sourceSection) {
|
|
697 super(context, sourceSection);
|
|
698 }
|
|
699
|
|
700 public NonZeroNode(NonZeroNode prev) {
|
|
701 super(prev);
|
|
702 }
|
|
703
|
|
704 @Specialization
|
|
705 public Object nonZero(int value) {
|
|
706 if (value == 0) {
|
|
707 return false;
|
|
708 } else {
|
|
709 return value;
|
|
710 }
|
|
711 }
|
|
712
|
|
713 }
|
|
714
|
|
715 @CoreMethod(names = "size", needsSelf = false, maxArgs = 0)
|
|
716 public abstract static class SizeNode extends CoreMethodNode {
|
|
717
|
|
718 public SizeNode(RubyContext context, SourceSection sourceSection) {
|
|
719 super(context, sourceSection);
|
|
720 }
|
|
721
|
|
722 public SizeNode(SizeNode prev) {
|
|
723 super(prev);
|
|
724 }
|
|
725
|
|
726 @Specialization
|
|
727 public int size() {
|
|
728 return Integer.SIZE / Byte.SIZE;
|
|
729 }
|
|
730
|
|
731 }
|
|
732
|
|
733 @CoreMethod(names = "step", needsBlock = true, minArgs = 2, maxArgs = 2)
|
|
734 public abstract static class StepNode extends YieldingCoreMethodNode {
|
|
735
|
|
736 public StepNode(RubyContext context, SourceSection sourceSection) {
|
|
737 super(context, sourceSection);
|
|
738 }
|
|
739
|
|
740 public StepNode(StepNode prev) {
|
|
741 super(prev);
|
|
742 }
|
|
743
|
|
744 @Specialization
|
|
745 public NilPlaceholder step(VirtualFrame frame, int from, int to, int step, RubyProc block) {
|
|
746 for (int i = from; i <= to; i += step) {
|
|
747 yield(frame, block, i);
|
|
748 }
|
|
749
|
|
750 return NilPlaceholder.INSTANCE;
|
|
751 }
|
|
752
|
|
753 }
|
|
754
|
|
755 @CoreMethod(names = "times", needsBlock = true, maxArgs = 0)
|
|
756 public abstract static class TimesNode extends YieldingCoreMethodNode {
|
|
757
|
|
758 public TimesNode(RubyContext context, SourceSection sourceSection) {
|
|
759 super(context, sourceSection);
|
|
760 }
|
|
761
|
|
762 public TimesNode(TimesNode prev) {
|
|
763 super(prev);
|
|
764 }
|
|
765
|
|
766 @Specialization
|
|
767 public int times(VirtualFrame frame, int n, RubyProc block) {
|
|
768 for (int i = 0; i < n; i++) {
|
|
769 yield(frame, block, i);
|
|
770 }
|
|
771
|
|
772 return n;
|
|
773 }
|
|
774
|
|
775 }
|
|
776
|
|
777 @CoreMethod(names = {"to_i", "to_int"}, maxArgs = 0)
|
|
778 public abstract static class ToINode extends CoreMethodNode {
|
|
779
|
|
780 public ToINode(RubyContext context, SourceSection sourceSection) {
|
|
781 super(context, sourceSection);
|
|
782 }
|
|
783
|
|
784 public ToINode(ToINode prev) {
|
|
785 super(prev);
|
|
786 }
|
|
787
|
|
788 @Specialization
|
|
789 public int toI(int n) {
|
|
790 return n;
|
|
791 }
|
|
792
|
|
793 }
|
|
794
|
|
795 @CoreMethod(names = "to_f", maxArgs = 0)
|
|
796 public abstract static class ToFNode extends CoreMethodNode {
|
|
797
|
|
798 public ToFNode(RubyContext context, SourceSection sourceSection) {
|
|
799 super(context, sourceSection);
|
|
800 }
|
|
801
|
|
802 public ToFNode(ToFNode prev) {
|
|
803 super(prev);
|
|
804 }
|
|
805
|
|
806 @Specialization
|
|
807 public double toF(int n) {
|
|
808 return n;
|
|
809 }
|
|
810
|
|
811 }
|
|
812
|
|
813 @CoreMethod(names = "to_s", maxArgs = 0)
|
|
814 public abstract static class ToSNode extends CoreMethodNode {
|
|
815
|
|
816 public ToSNode(RubyContext context, SourceSection sourceSection) {
|
|
817 super(context, sourceSection);
|
|
818 }
|
|
819
|
|
820 public ToSNode(ToSNode prev) {
|
|
821 super(prev);
|
|
822 }
|
|
823
|
|
824 @Specialization
|
|
825 public RubyString toS(int n) {
|
|
826 return getContext().makeString(Integer.toString(n));
|
|
827 }
|
|
828
|
|
829 }
|
|
830
|
|
831 @CoreMethod(names = "upto", needsBlock = true, minArgs = 1, maxArgs = 1)
|
|
832 public abstract static class UpToNode extends YieldingCoreMethodNode {
|
|
833
|
|
834 public UpToNode(RubyContext context, SourceSection sourceSection) {
|
|
835 super(context, sourceSection);
|
|
836 }
|
|
837
|
|
838 public UpToNode(UpToNode prev) {
|
|
839 super(prev);
|
|
840 }
|
|
841
|
|
842 @Specialization
|
|
843 public NilPlaceholder upto(VirtualFrame frame, int from, int to, RubyProc block) {
|
|
844 for (int i = from; i <= to; i++) {
|
|
845 yield(frame, block, i);
|
|
846 }
|
|
847
|
|
848 return NilPlaceholder.INSTANCE;
|
|
849 }
|
|
850
|
|
851 }
|
|
852
|
|
853 }
|