1 34 package org.jruby; 35 36 import org.jruby.runtime.Block; 37 import org.jruby.runtime.CallbackFactory; 38 import org.jruby.runtime.ObjectAllocator; 39 import org.jruby.runtime.ThreadContext; 40 import org.jruby.runtime.builtin.IRubyObject; 41 42 46 public abstract class RubyInteger extends RubyNumeric { 47 48 public static RubyClass createIntegerClass(Ruby runtime) { 49 RubyClass integer = runtime.defineClass("Integer", runtime.getClass("Numeric"), 50 ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); 51 CallbackFactory callbackFactory = runtime.callbackFactory(RubyInteger.class); 52 integer.getSingletonClass().undefineMethod("allocate"); 53 integer.getSingletonClass().undefineMethod("new"); 54 55 integer.defineFastMethod("integer?", callbackFactory.getFastMethod("int_p")); 56 integer.defineMethod("upto", callbackFactory.getMethod("upto", RubyKernel.IRUBY_OBJECT)); 57 integer.defineMethod("downto", callbackFactory.getMethod("downto", RubyKernel.IRUBY_OBJECT)); 58 integer.defineMethod("times", callbackFactory.getMethod("times")); 59 60 integer.includeModule(runtime.getModule("Precision")); 61 62 integer.defineFastMethod("succ", callbackFactory.getFastMethod("succ")); 63 integer.defineFastMethod("next", callbackFactory.getFastMethod("succ")); 64 integer.defineFastMethod("chr", callbackFactory.getFastMethod("chr")); 65 integer.defineFastMethod("to_i", callbackFactory.getFastMethod("to_i")); 66 integer.defineFastMethod("to_int", callbackFactory.getFastMethod("to_i")); 67 integer.defineFastMethod("floor", callbackFactory.getFastMethod("to_i")); 68 integer.defineFastMethod("ceil", callbackFactory.getFastMethod("to_i")); 69 integer.defineFastMethod("round", callbackFactory.getFastMethod("to_i")); 70 integer.defineFastMethod("truncate", callbackFactory.getFastMethod("to_i")); 71 72 integer.getMetaClass().defineFastMethod("induced_from", callbackFactory.getFastSingletonMethod("induced_from", 73 RubyKernel.IRUBY_OBJECT)); 74 return integer; 75 } 76 77 public RubyInteger(Ruby runtime, RubyClass rubyClass) { 78 super(runtime, rubyClass); 79 } 80 81 public RubyInteger convertToInteger() { 82 return this; 83 } 84 85 protected RubyFloat toFloat() { 87 return RubyFloat.newFloat(getRuntime(), getDoubleValue()); 88 } 89 90 94 95 98 public IRubyObject int_p() { 99 return getRuntime().getTrue(); 100 } 101 102 105 public IRubyObject upto(IRubyObject to, Block block) { 106 ThreadContext context = getRuntime().getCurrentContext(); 107 108 if (this instanceof RubyFixnum && to instanceof RubyFixnum) { 109 110 RubyFixnum toFixnum = (RubyFixnum) to; 111 long toValue = toFixnum.getLongValue(); 112 for (long i = getLongValue(); i <= toValue; i++) { 113 context.yield(RubyFixnum.newFixnum(getRuntime(), i), block); 114 } 115 } else { 116 RubyNumeric i = this; 117 118 while (true) { 119 if (i.callMethod(context, ">", to).isTrue()) { 120 break; 121 } 122 context.yield(i, block); 123 i = (RubyNumeric) i.callMethod(context, "+", RubyFixnum.one(getRuntime())); 124 } 125 } 126 return this; 127 } 128 129 132 public IRubyObject downto(IRubyObject to, Block block) { 134 ThreadContext context = getRuntime().getCurrentContext(); 135 136 if (this instanceof RubyFixnum && to instanceof RubyFixnum) { 137 RubyFixnum toFixnum = (RubyFixnum) to; 138 long toValue = toFixnum.getLongValue(); 139 for (long i = getLongValue(); i >= toValue; i--) { 140 context.yield(RubyFixnum.newFixnum(getRuntime(), i), block); 141 } 142 } else { 143 RubyNumeric i = this; 144 145 while (true) { 146 if (i.callMethod(context, "<", to).isTrue()) { 147 break; 148 } 149 context.yield(i, block); 150 i = (RubyNumeric) i.callMethod(context, "-", RubyFixnum.one(getRuntime())); 151 } 152 } 153 return this; 154 } 155 156 public IRubyObject times(Block block) { 157 ThreadContext context = getRuntime().getCurrentContext(); 158 159 if (this instanceof RubyFixnum) { 160 161 long value = getLongValue(); 162 for (long i = 0; i < value; i++) { 163 context.yield(RubyFixnum.newFixnum(getRuntime(), i), block); 164 } 165 } else { 166 RubyNumeric i = RubyFixnum.zero(getRuntime()); 167 while (true) { 168 if (!i.callMethod(context, "<", this).isTrue()) { 169 break; 170 } 171 context.yield(i, block); 172 i = (RubyNumeric) i.callMethod(context, "+", RubyFixnum.one(getRuntime())); 173 } 174 } 175 176 return this; 177 } 178 179 182 public IRubyObject succ() { 183 if (this instanceof RubyFixnum) { 184 return RubyFixnum.newFixnum(getRuntime(), getLongValue() + 1L); 185 } else { 186 return callMethod(getRuntime().getCurrentContext(), "+", RubyFixnum.one(getRuntime())); 187 } 188 } 189 190 193 public RubyString chr() { 194 if (getLongValue() < 0 || getLongValue() > 0xff) { 195 throw getRuntime().newRangeError(this.toString() + " out of char range"); 196 } 197 return getRuntime().newString(new String (new char[] { (char) getLongValue() })); 198 } 199 200 203 public RubyInteger to_i() { 204 return this; 205 } 206 207 211 212 215 public static IRubyObject induced_from(IRubyObject recv, IRubyObject other) { 216 if (other instanceof RubyFixnum || other instanceof RubyBignum) { 217 return other; 218 } else if (other instanceof RubyFloat) { 219 return other.callMethod(recv.getRuntime().getCurrentContext(), "to_i"); 220 } else { 221 throw recv.getRuntime().newTypeError( 222 "failed to convert " + other.getMetaClass().getName() + " into Integer"); 223 } 224 } 225 } 226 | Popular Tags |