@SuppressWarnings("unchecked") @JRubyMethod(name = "names") public IRubyObject names(ThreadContext context) { Ruby runtime = context.runtime; EncodingService service = runtime.getEncodingService(); Entry entry = service.findEncodingOrAliasEntry(name); RubyArray result = runtime.newArray(); HashEntryIterator i; i = service.getEncodings().entryIterator(); while (i.hasNext()) { CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e = ((CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry>) i.next()); if (e.value == entry) { result.append( RubyString.newUsAsciiStringShared(runtime, e.bytes, e.p, e.end - e.p).freeze(context)); } } i = service.getAliases().entryIterator(); while (i.hasNext()) { CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e = ((CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry>) i.next()); if (e.value == entry) { result.append( RubyString.newUsAsciiStringShared(runtime, e.bytes, e.p, e.end - e.p).freeze(context)); } } result.append(runtime.newString(EXTERNAL)); result.append(runtime.newString(LOCALE)); return result; }
/** match_end */ @JRubyMethod(name = "end", compat = CompatVersion.RUBY1_8) public IRubyObject end(ThreadContext context, IRubyObject index) { int i = RubyNumeric.num2int(index); Ruby runtime = context.getRuntime(); int e = endCommon(runtime, i); return e < 0 ? runtime.getNil() : RubyFixnum.newFixnum(runtime, e); }
public static RubyClass createThreadClass(Ruby runtime) { // FIXME: In order for Thread to play well with the standard 'new' behavior, // it must provide an allocator that can create empty object instances which // initialize then fills with appropriate data. RubyClass threadClass = runtime.defineClass( "Thread", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); runtime.setThread(threadClass); threadClass.index = ClassIndex.THREAD; threadClass.setReifiedClass(RubyThread.class); threadClass.defineAnnotatedMethods(RubyThread.class); RubyThread rubyThread = new RubyThread(runtime, threadClass); // TODO: need to isolate the "current" thread from class creation rubyThread.threadImpl = new NativeThread(rubyThread, Thread.currentThread()); runtime.getThreadService().setMainThread(Thread.currentThread(), rubyThread); // set to default thread group runtime.getDefaultThreadGroup().addDirectly(rubyThread); threadClass.setMarshal(ObjectMarshal.NOT_MARSHALABLE_MARSHAL); return threadClass; }
public static IRubyObject lexicalSearchConst( ThreadContext context, StaticScope scope, MutableCallSite site, String constName, boolean noPrivateConsts) throws Throwable { Ruby runtime = context.runtime; IRubyObject constant = scope.getConstantInner(constName); if (constant == null) { constant = UndefinedValue.UNDEFINED; } SwitchPoint switchPoint = (SwitchPoint) runtime.getConstantInvalidator(constName).getData(); // bind constant until invalidated MethodHandle target = Binder.from(site.type()).drop(0, 2).constant(constant); MethodHandle fallback = Binder.from(site.type()) .append(site, constName) .append(noPrivateConsts) .invokeStatic(LOOKUP, Bootstrap.class, "lexicalSearchConst"); site.setTarget(switchPoint.guardWithTest(target, fallback)); return constant; }
private IRubyObject handleReturnJump( ThreadContext context, JumpException.ReturnJump rj, int jumpTarget) { int target = rj.getTarget(); Ruby runtime = context.getRuntime(); // lambda always just returns the value if (target == jumpTarget && isLambda()) { return (IRubyObject) rj.getValue(); } // returns can't propagate out of threads if (isThread()) { throw runtime.newThreadError("return can't jump across threads"); } // If the block-receiving method is not still active and the original // enclosing frame is no longer on the stack, it's a bad return. // FIXME: this is not very efficient for cases where it won't error if (target == jumpTarget && !context.isJumpTargetAlive(target, 1)) { throw runtime.newLocalJumpError( RubyLocalJumpError.Reason.RETURN, (IRubyObject) rj.getValue(), "unexpected return"); } // otherwise, let it propagate throw rj; }
@SuppressWarnings("unchecked") @JRubyMethod(name = "name_list", meta = true) public static IRubyObject name_list(ThreadContext context, IRubyObject recv) { Ruby runtime = context.runtime; EncodingService service = runtime.getEncodingService(); RubyArray result = runtime.newArray(service.getEncodings().size() + service.getAliases().size()); HashEntryIterator i; i = service.getEncodings().entryIterator(); while (i.hasNext()) { CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e = ((CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry>) i.next()); result.append( RubyString.newUsAsciiStringShared(runtime, e.bytes, e.p, e.end - e.p).freeze(context)); } i = service.getAliases().entryIterator(); while (i.hasNext()) { CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e = ((CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry>) i.next()); result.append( RubyString.newUsAsciiStringShared(runtime, e.bytes, e.p, e.end - e.p).freeze(context)); } result.append(runtime.newString(EXTERNAL)); result.append(runtime.newString(LOCALE)); return result; }
@JRubyMethod(name = "_id2ref", required = 1, module = true, visibility = Visibility.PRIVATE) public static IRubyObject id2ref(IRubyObject recv, IRubyObject id) { Ruby runtime = id.getRuntime(); if (!(id instanceof RubyFixnum)) { throw recv.getRuntime().newTypeError(id, recv.getRuntime().getFixnum()); } RubyFixnum idFixnum = (RubyFixnum) id; long longId = idFixnum.getLongValue(); if (longId == 0) { return runtime.getFalse(); } else if (longId == 2) { return runtime.getTrue(); } else if (longId == 4) { return runtime.getNil(); } else if (longId % 2 != 0) { // odd return runtime.newFixnum((longId - 1) / 2); } else { if (runtime.isObjectSpaceEnabled()) { IRubyObject object = runtime.getObjectSpace().id2ref(longId); if (object == null) { return runtime.getNil(); } return object; } else { runtime .getWarnings() .warn("ObjectSpace is disabled; _id2ref only supports immediates, pass -X+O to enable"); return runtime.getNil(); } } }
/** flo_to_s */ @JRubyMethod(name = "to_s") @Override public IRubyObject to_s() { Ruby runtime = getRuntime(); if (Double.isInfinite(value)) return RubyString.newString(runtime, value < 0 ? "-Infinity" : "Infinity"); if (Double.isNaN(value)) return RubyString.newString(runtime, "NaN"); ByteList buf = new ByteList(); // Under 1.9, use full-precision float formatting (JRUBY-4846). // Double-precision can represent around 16 decimal digits; // we use 20 to ensure full representation. Sprintf.sprintf(buf, Locale.US, "%#.20g", this); int e = buf.indexOf('e'); if (e == -1) e = buf.getRealSize(); ASCIIEncoding ascii = ASCIIEncoding.INSTANCE; if (!ascii.isDigit(buf.get(e - 1))) { buf.setRealSize(0); Sprintf.sprintf(buf, Locale.US, "%#.14e", this); e = buf.indexOf('e'); if (e == -1) e = buf.getRealSize(); } int p = e; while (buf.get(p - 1) == '0' && ascii.isDigit(buf.get(p - 2))) p--; System.arraycopy(buf.getUnsafeBytes(), e, buf.getUnsafeBytes(), p, buf.getRealSize() - e); buf.setRealSize(p + buf.getRealSize() - e); buf.setEncoding(USASCIIEncoding.INSTANCE); return runtime.newString(buf); }
public static RubyClass createFloatClass(Ruby runtime) { RubyClass floatc = runtime.defineClass( "Float", runtime.getNumeric(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); runtime.setFloat(floatc); floatc.setClassIndex(ClassIndex.FLOAT); floatc.setReifiedClass(RubyFloat.class); floatc.kindOf = new RubyModule.JavaClassKindOf(RubyFloat.class); floatc.getSingletonClass().undefineMethod("new"); // Java Doubles are 64 bit long: floatc.defineConstant("ROUNDS", RubyFixnum.newFixnum(runtime, ROUNDS)); floatc.defineConstant("RADIX", RubyFixnum.newFixnum(runtime, RADIX)); floatc.defineConstant("MANT_DIG", RubyFixnum.newFixnum(runtime, MANT_DIG)); floatc.defineConstant("DIG", RubyFixnum.newFixnum(runtime, DIG)); // Double.MAX_EXPONENT since Java 1.6 floatc.defineConstant("MIN_EXP", RubyFixnum.newFixnum(runtime, MIN_EXP)); // Double.MAX_EXPONENT since Java 1.6 floatc.defineConstant("MAX_EXP", RubyFixnum.newFixnum(runtime, MAX_EXP)); floatc.defineConstant("MIN_10_EXP", RubyFixnum.newFixnum(runtime, MIN_10_EXP)); floatc.defineConstant("MAX_10_EXP", RubyFixnum.newFixnum(runtime, MAX_10_EXP)); floatc.defineConstant("MIN", RubyFloat.newFloat(runtime, Double.MIN_VALUE)); floatc.defineConstant("MAX", RubyFloat.newFloat(runtime, Double.MAX_VALUE)); floatc.defineConstant("EPSILON", RubyFloat.newFloat(runtime, EPSILON)); floatc.defineConstant("INFINITY", RubyFloat.newFloat(runtime, INFINITY)); floatc.defineConstant("NAN", RubyFloat.newFloat(runtime, NAN)); floatc.defineAnnotatedMethods(RubyFloat.class); return floatc; }
@Override public RubyHash to_hash() { Ruby runtime = getRuntime(); RubyHash hash = RubyHash.newHash(runtime); hash.replace(runtime.getCurrentContext(), this); return hash; }
/** do_coerce */ protected final RubyArray doCoerce(ThreadContext context, IRubyObject other, boolean err) { if (!other.respondsTo("coerce")) { if (err) { coerceRescue(context, other); } return null; } final Ruby runtime = context.runtime; final IRubyObject $ex = context.getErrorInfo(); final IRubyObject result; try { result = coerceBody(context, other); } catch (RaiseException e) { // e.g. NoMethodError: undefined method `coerce' if (e.getException().kind_of_p(context, runtime.getStandardError()).isTrue()) { context.setErrorInfo($ex); // restore $! RubyWarnings warnings = context.runtime.getWarnings(); warnings.warn("Numerical comparison operators will no more rescue exceptions of #coerce"); warnings.warn("in the next release. Return nil in #coerce if the coercion is impossible."); if (err) { coerceFailed(context, other); } return null; } else { throw e; } } return coerceResult(runtime, result, err); }
private IRubyObject stepCommon19(ThreadContext context, IRubyObject step, Block block) { Ruby runtime = context.getRuntime(); if (begin instanceof RubyFixnum && end instanceof RubyFixnum && step instanceof RubyFixnum) { fixnumStep(context, runtime, ((RubyFixnum) step).getLongValue(), block); } else if (begin instanceof RubyFloat || end instanceof RubyFloat || step instanceof RubyFloat) { RubyNumeric.floatStep19(context, runtime, begin, end, step, isExclusive, block); } else if (begin instanceof RubyNumeric || !checkIntegerType(runtime, begin, "to_int").isNil() || !checkIntegerType(runtime, end, "to_int").isNil()) { numericStep19(context, runtime, step, block); } else { IRubyObject tmp = begin.checkStringType(); if (!tmp.isNil()) { StepBlockCallBack callback = new StepBlockCallBack(block, RubyFixnum.one(runtime), step); Block blockCallback = CallBlock.newCallClosure( this, runtime.getRange(), Arity.singleArgument(), callback, context); ((RubyString) tmp).uptoCommon19(context, end, isExclusive, blockCallback); } else { if (!begin.respondsTo("succ")) throw runtime.newTypeError("can't iterate from " + begin.getMetaClass().getName()); // range_each_func(range, step_i, b, e, args); rangeEach(context, new StepBlockCallBack(block, RubyFixnum.one(runtime), step)); } } return this; }
private static IRubyObject callCmpMethod( ThreadContext context, IRubyObject recv, IRubyObject other, IRubyObject returnValueOnError) { Ruby runtime = context.runtime; if (recv == other) return runtime.getTrue(); try { IRubyObject result = invokedynamic(context, recv, OP_CMP, other); // This is only to prevent throwing exceptions by cmperr - it has poor performance if (result.isNil()) { return returnValueOnError; } return RubyBoolean.newBoolean(runtime, cmpint(context, result, recv, other) == 0); } catch (RaiseException e) { if (e.getException().kind_of_p(context, runtime.getStandardError()).isTrue()) { // clear error info resulting from failure to compare (JRUBY-3292) context.setErrorInfo(runtime.getNil()); return returnValueOnError; } else { throw e; } } }
@JRubyMethod(name = "round", compat = CompatVersion.RUBY1_9) public IRubyObject round19(ThreadContext context, IRubyObject arg) { int ndigits = RubyNumeric.num2int(arg); if (ndigits > 0) return RubyKernel.new_float(this, this); if (ndigits == 0) return this; ndigits = -ndigits; Ruby runtime = context.getRuntime(); if (ndigits < 0) throw runtime.newArgumentError("ndigits out of range"); IRubyObject f = Numeric.int_pow(context, 10, ndigits); if (this instanceof RubyFixnum && f instanceof RubyFixnum) { long x = ((RubyFixnum) this).getLongValue(); long y = ((RubyFixnum) f).getLongValue(); boolean neg = x < 0; if (neg) x = -x; x = (x + y / 2) / y * y; if (neg) x = -x; return RubyFixnum.newFixnum(runtime, x); } else { IRubyObject h = f.callMethod(context, "/", RubyFixnum.two(runtime)); IRubyObject r = callMethod(context, "%", f); IRubyObject n = callMethod(context, "-", r); if (!r.callMethod(context, "<", h).isTrue()) n = n.callMethod(context, "+", f); return n; } }
public static RubyClass createIntegerClass(Ruby runtime) { RubyClass integer = runtime.defineClass( "Integer", runtime.getNumeric(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); runtime.setInteger(integer); integer.index = ClassIndex.INTEGER; integer.setReifiedClass(RubyInteger.class); integer.kindOf = new RubyModule.KindOf() { public boolean isKindOf(IRubyObject obj, RubyModule type) { return obj instanceof RubyInteger; } }; integer.getSingletonClass().undefineMethod("new"); if (!runtime.is1_9()) { integer.includeModule(runtime.getPrecision()); } integer.defineAnnotatedMethods(RubyInteger.class); return integer; }
public static RubyClass createPointerClass(Ruby runtime, RubyModule module) { RubyClass pointerClass = module.defineClassUnder( "Pointer", module.getClass(AbstractMemory.ABSTRACT_MEMORY_RUBY_CLASS), RubyInstanceConfig.REIFY_RUBY_CLASSES ? new ReifyingAllocator(Pointer.class) : PointerAllocator.INSTANCE); pointerClass.defineAnnotatedMethods(Pointer.class); pointerClass.defineAnnotatedConstants(Pointer.class); pointerClass.setReifiedClass(Pointer.class); pointerClass.kindOf = new RubyModule.KindOf() { @Override public boolean isKindOf(IRubyObject obj, RubyModule type) { return obj instanceof Pointer && super.isKindOf(obj, type); } }; module.defineClassUnder( "NullPointerError", runtime.getRuntimeError(), runtime.getRuntimeError().getAllocator()); // Add Pointer::NULL as a constant Pointer nullPointer = new Pointer(runtime, pointerClass, new NullMemoryIO(runtime)); pointerClass.setConstant("NULL", nullPointer); runtime .getNilClass() .addMethod("to_ptr", new NilToPointerMethod(runtime.getNilClass(), nullPointer)); return pointerClass; }
public static RubyModule createComparable(Ruby runtime) { RubyModule comparableModule = runtime.defineModule("Comparable"); runtime.setComparable(comparableModule); comparableModule.defineAnnotatedMethods(RubyComparable.class); return comparableModule; }
@JRubyMethod(name = "odd?") public RubyBoolean odd_p(ThreadContext context) { Ruby runtime = context.runtime; if (callMethod(context, "%", RubyFixnum.two(runtime)) != RubyFixnum.zero(runtime)) { return runtime.getTrue(); } return runtime.getFalse(); }
@JRubyMethod(name = "compatible?", meta = true) public static IRubyObject compatible_p( ThreadContext context, IRubyObject self, IRubyObject first, IRubyObject second) { Ruby runtime = context.runtime; Encoding enc = areCompatible(first, second); return enc == null ? runtime.getNil() : runtime.getEncodingService().getEncoding(enc); }
/** Create the ObjectSpace module and add it to the Ruby runtime. */ public static RubyModule createObjectSpaceModule(Ruby runtime) { RubyModule objectSpaceModule = runtime.defineModule("ObjectSpace"); runtime.setObjectSpaceModule(objectSpaceModule); objectSpaceModule.defineAnnotatedMethods(RubyObjectSpace.class); return objectSpaceModule; }
@JRubyMethod(name = "locale_charmap", meta = true) public static IRubyObject locale_charmap(ThreadContext context, IRubyObject recv) { Ruby runtime = context.runtime; EncodingService service = runtime.getEncodingService(); ByteList name = new ByteList(service.getLocaleEncoding().getName()); return RubyString.newUsAsciiStringNoCopy(runtime, name); }
@JRubyMethod(name = "even?") public RubyBoolean even_p(ThreadContext context) { Ruby runtime = context.getRuntime(); if (callMethod(context, "%", RubyFixnum.two(runtime)) == RubyFixnum.zero(runtime)) { return runtime.getTrue(); } return runtime.getFalse(); }
/** int_chr */ @JRubyMethod(name = "chr", compat = CompatVersion.RUBY1_8) public RubyString chr(ThreadContext context) { Ruby runtime = context.getRuntime(); long value = getLongValue(); if (value < 0 || value > 0xff) throw runtime.newRangeError(this.toString() + " out of char range"); return RubyString.newStringShared(runtime, SINGLE_CHAR_BYTELISTS[(int) value]); }
public static DateTimeZone getTimeZone(Ruby runtime, String zone) { DateTimeZone cachedZone = runtime.getTimezoneCache().get(zone); if (cachedZone != null) return cachedZone; String originalZone = zone; TimeZone tz = TimeZone.getTimeZone(getEnvTimeZone(runtime).toString()); // Value of "TZ" property is of a bit different format, // which confuses the Java's TimeZone.getTimeZone(id) method, // and so, we need to convert it. Matcher tzMatcher = TZ_PATTERN.matcher(zone); if (tzMatcher.matches()) { String sign = tzMatcher.group(2); String hours = tzMatcher.group(3); String minutes = tzMatcher.group(4); // GMT+00:00 --> Etc/GMT, see "MRI behavior" // comment below. if (("00".equals(hours) || "0".equals(hours)) && (minutes == null || ":00".equals(minutes) || ":0".equals(minutes))) { zone = "Etc/GMT"; } else { // Invert the sign, since TZ format and Java format // use opposite signs, sigh... Also, Java API requires // the sign to be always present, be it "+" or "-". sign = ("-".equals(sign) ? "+" : "-"); // Always use "GMT" since that's required by Java API. zone = "GMT" + sign + hours; if (minutes != null) { zone += minutes; } } tz = TimeZone.getTimeZone(zone); } else { if (LONG_TZNAME.containsKey(zone)) tz.setID(LONG_TZNAME.get(zone.toUpperCase())); } // MRI behavior: With TZ equal to "GMT" or "UTC", Time.now // is *NOT* considered as a proper GMT/UTC time: // ENV['TZ']="GMT" // Time.now.gmt? ==> false // ENV['TZ']="UTC" // Time.now.utc? ==> false // Hence, we need to adjust for that. if ("GMT".equalsIgnoreCase(zone) || "UTC".equalsIgnoreCase(zone)) { zone = "Etc/" + zone; tz = TimeZone.getTimeZone(zone); } DateTimeZone dtz = DateTimeZone.forTimeZone(tz); runtime.getTimezoneCache().put(originalZone, dtz); return dtz; }
@JRubyMethod(name = "find", meta = true) public static IRubyObject find(ThreadContext context, IRubyObject recv, IRubyObject str) { Ruby runtime = context.runtime; // Wacky but true...return arg if it is an encoding looking for itself if (str instanceof RubyEncoding) return str; return runtime.getEncodingService().rubyEncodingFromObject(str); }
private synchronized IRubyObject status(Ruby runtime) { if (threadImpl.isAlive()) { return RubyString.newStringShared(runtime, status.get().bytes); } else if (exitingException != null) { return runtime.getNil(); } else { return runtime.getFalse(); } }
public static IRubyObject newLocationArray(Ruby runtime, RubyStackTraceElement[] elements) { RubyArray ary = runtime.newArray(elements.length); for (RubyStackTraceElement element : elements) { ary.append(new RubyThread.Location(runtime, runtime.getLocation(), element)); } return ary; }
/** rb_dbl2big + LONG2FIX at once (numeric.c) */ public static IRubyObject dbl2num(Ruby runtime, double val) { if (Double.isInfinite(val)) { throw runtime.newFloatDomainError(val < 0 ? "-Infinity" : "Infinity"); } if (Double.isNaN(val)) { throw runtime.newFloatDomainError("NaN"); } return convertToNum(val, runtime); }
@JRubyMethod(rest = true, visibility = PRIVATE) public IRubyObject initialize(ThreadContext context, IRubyObject[] args, Block block) { Ruby runtime = getRuntime(); if (!block.isGiven()) throw runtime.newThreadError("must be called with a block"); if (threadImpl != null) throw runtime.newThreadError("already initialized thread"); RubyRunnable runnable = new RubyRunnable(this, args, block); return startWith(runnable); }
@JRubyMethod(rest = true, name = "start", meta = true, compat = RUBY1_9) public static RubyThread start19(IRubyObject recv, IRubyObject[] args, Block block) { Ruby runtime = recv.getRuntime(); // The error message may appear incongruous here, due to the difference // between JRuby's Thread model and MRI's. // We mimic MRI's message in the name of compatibility. if (!block.isGiven()) throw runtime.newArgumentError("tried to create Proc object without a block"); return startThread(recv, args, false, block); }