Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
BEGIN LICENSE BLOCK ***** Version: CPL 1.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Common Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.eclipse.org/legal/cpl-v10.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. Copyright (C) 2001 Chad Fowler <chadfowler@chadfowler.com> Copyright (C) 2001 Alan Moore <alan_moore@gmx.net> Copyright (C) 2001 Ed Sinjiashvili <slorcim@users.sourceforge.net> Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de> Copyright (C) 2002 Benoit Cerrina <b.cerrina@wanadoo.fr> Copyright (C) 2002-2006 Thomas E Enebo <enebo@acm.org> Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se> Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de> Copyright (C) 2005 Charles O Nutter <headius@headius.com> Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com> Alternatively, the contents of this file may be used under the terms of either of the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the CPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the CPL, the GPL or the LGPL. END LICENSE BLOCK ***
 
 package org.jruby;
 
 import static org.jruby.RubyEnumerator.enumeratorize;
 
 import java.util.List;
 
 import static org.jruby.runtime.Visibility.*;
 import static org.jruby.CompatVersion.*;
 
 
 import static org.jruby.javasupport.util.RuntimeHelpers.invokedynamic;
 import static org.jruby.runtime.MethodIndex.HASH;
 import static org.jruby.runtime.MethodIndex.OP_CMP;

Author(s):
jpetersen
 
 @JRubyClass(name="Range", include="Enumerable")
 public class RubyRange extends RubyObject {
     private IRubyObject begin;
     private IRubyObject end;
     private boolean isExclusive;
 
     public static RubyClass createRangeClass(Ruby runtime) {
         RubyClass result = runtime.defineClass("Range"runtime.getObject(), );
         runtime.setRange(result);
 
         result.index = .;
         result.setReifiedClass(RubyRange.class);
 
         result.kindOf = new RubyModule.KindOf() {
             public boolean isKindOf(IRubyObject objRubyModule type) {
                 return obj instanceof RubyRange;
             }
         };
         
         result.setMarshal();
         result.includeModule(runtime.getEnumerable());
 
         result.defineAnnotatedMethods(RubyRange.class);
        return result;
    }
    private static final ObjectAllocator RANGE_ALLOCATOR = new ObjectAllocator() {
        public IRubyObject allocate(Ruby runtimeRubyClass klass) {
            return new RubyRange(runtimeklass);
        }
    };    
    private RubyRange(Ruby runtimeRubyClass klass) {
        super(runtimeklass);
         =  = runtime.getNil();
    }
    public static RubyRange newRange(Ruby runtimeThreadContext contextIRubyObject beginIRubyObject endboolean isExclusive) {
        RubyRange range = new RubyRange(runtimeruntime.getRange());
        range.init(contextbeginendisExclusive);
        return range;
    }
    public static RubyRange newExclusiveRange(Ruby runtimeThreadContext contextIRubyObject beginIRubyObject end) {
        RubyRange range = new RubyRange(runtimeruntime.getRange());
        range.init(contextbeginendtrue);
        return range;
    }
    public static RubyRange newInclusiveRange(Ruby runtimeThreadContext contextIRubyObject beginIRubyObject end) {
        RubyRange range = new RubyRange(runtimeruntime.getRange());
        range.init(contextbeginendfalse);
        return range;
    }
    @Override
    public void copySpecialInstanceVariables(IRubyObject clone) {
        RubyRange range = (RubyRange)clone;
        range.begin = ;
        range.end = ;
        range.isExclusive = ;
    }
    final boolean checkBegin(long length) {
        long beg = RubyNumeric.num2long(this.);
        if(beg < 0) {
            beg += length;
            if(beg < 0) {
                return false;
            }
        } else if(length < beg) {
            return false;
        }
        return true;
    }
    final long[] begLen(long lenint err){
        long beg = RubyNumeric.num2long(this.);
        long end = RubyNumeric.num2long(this.);
        if (beg < 0) {
            beg += len;
            if (beg < 0) {
                if (err != 0) throw getRuntime().newRangeError(beg + ".." + ( ? "." : "") + end + " out of range");
                return null;
            }
        }
        if (err == 0 || err == 2) {
            if (beg > len) {
                if (err != 0) throw getRuntime().newRangeError(beg + ".." + ( ? "." : "") + end + " out of range");
                return null;
            }
            if (end > lenend = len;
        }
        if (end < 0) end += len;
        if (!end++;
        len = end - beg;
        if (len < 0) len = 0;
        return new long[]{beglen};
    }
    final int[] begLenInt(int lenint err){
        int beg = RubyNumeric.num2int(this.);
        int end = RubyNumeric.num2int(this.);
        if (beg < 0) {
            beg += len;
            if (beg < 0) {
                if (err != 0) throw getRuntime().newRangeError(beg + ".." + ( ? "." : "") + end + " out of range");
                return null;
            }
        }
        if (err == 0 || err == 2) {
            if (beg > len) {
                if (err != 0) throw getRuntime().newRangeError(beg + ".." + ( ? "." : "") + end + " out of range");
                return null;
            }
            if (end > lenend = len;
        }
        if (end < 0) end += len;
        if (!end++;
        len = end - beg;
        if (len < 0) len = 0;
        return new int[]{beglen};
    }
    private void init(ThreadContext contextIRubyObject beginIRubyObject endboolean isExclusive) {
        if (!(begin instanceof RubyFixnum && end instanceof RubyFixnum)) {
            try {
                IRubyObject result = invokedynamic(contextbeginend);
                if (result.isNil()) throw getRuntime().newArgumentError("bad value for range");
            } catch (RaiseException re) {
                throw getRuntime().newArgumentError("bad value for range");
            }
        }
        this. = begin;
        this. = end;
        this. = isExclusive;
    }
    
    @JRubyMethod(required = 2, optional = 1, visibility = )
    public IRubyObject initialize(ThreadContext contextIRubyObject[] argsBlock unusedBlock) {
        if (!.isNil() || !.isNil()) {
            throw getRuntime().newNameError("`initialize' called twice""initialize");
        }
        init(contextargs[0], args[1], args.length > 2 && args[2].isTrue());
        return getRuntime().getNil();
    }
    @JRubyMethod(name = {"first""begin"})
    public IRubyObject first() {
        return ;
    }
    @JRubyMethod(name = {"last""end"})
    public IRubyObject last() {
        return ;
    }
    
    @JRubyMethod(name = "hash")
    public RubyFixnum hash(ThreadContext context) {
        long hash =  ? 1 : 0;
        long h = hash;
        
        long v = invokedynamic(context).convertToInteger().getLongValue();
        hash ^= v << 1;
        v = invokedynamic(context).convertToInteger().getLongValue();
        hash ^= v << 9;
        hash ^= h << 24;
        return getRuntime().newFixnum(hash);
    }
    
    private static byte[] DOTDOTDOT = "...".getBytes();
    private static byte[] DOTDOT = "..".getBytes();
    @JRubyMethod(name = "inspect")
    public IRubyObject inspect(ThreadContext context) {
        RubyString str = inspect(context).strDup(context.runtime);
        RubyString str2 = inspect(context);
        str.cat( ?  : );
        str.concat(str2);
        str.infectBy(str2);
        return str;
    }
    
    @JRubyMethod(name = "to_s")
    public IRubyObject to_s(ThreadContext context) {
        RubyString str = RubyString.objAsString(context).strDup(context.runtime);
        RubyString str2 = RubyString.objAsString(context);
        str.cat( ?  : );
        str.concat(str2);
        str.infectBy(str2);
        return str;
    }
    @JRubyMethod(name = "exclude_end?")
    public RubyBoolean exclude_end_p() {
        return getRuntime().newBoolean();
    }
    @JRubyMethod(name = "==", required = 1)
    public IRubyObject op_equal(ThreadContext contextIRubyObject other) {
        if (this == otherreturn getRuntime().getTrue();
        if (!(other instanceof RubyRange)) return getRuntime().getFalse();
        RubyRange otherRange = (RubyRangeother;
        if (equalInternal(contextotherRange.begin) &&
            equalInternal(contextotherRange.end) &&
             == otherRange.isExclusivereturn getRuntime().getTrue();
        return getRuntime().getFalse();
    }
    @JRubyMethod(name = "eql?", required = 1)
    public IRubyObject eql_p(ThreadContext contextIRubyObject other) {
        if (this == otherreturn getRuntime().getTrue();
        if (!(other instanceof RubyRange)) return getRuntime().getFalse();
        RubyRange otherRange = (RubyRange)other;
        if (eqlInternal(contextotherRange.begin) &&
            eqlInternal(contextotherRange.end) &&
             == otherRange.isExclusivereturn getRuntime().getTrue();
        return getRuntime().getFalse();
    }
    private static abstract class RangeCallBack {
        abstract void call(ThreadContext contextIRubyObject arg);
    }
    private static final class StepBlockCallBack extends RangeCallBack implements BlockCallback {
        final Block block;
        IRubyObject iter;
        final IRubyObject step;
        StepBlockCallBack(Block blockIRubyObject iterIRubyObject step) {
            this. = block;
            this. = iter;
            this. = step;
        }
        public IRubyObject call(ThreadContext contextIRubyObject[] argsBlock originalBlock) {
            call(contextargs[0]);
            return context.runtime.getNil();
        }
        void call(ThreadContext contextIRubyObject arg) {
            if ( instanceof RubyFixnum) {
                 = RubyFixnum.newFixnum(context.runtime, ((RubyFixnum)).getLongValue() - 1);
            } else {
                 = .callMethod(context"-", RubyFixnum.one(context.runtime));
            }
            if ( == RubyFixnum.zero(context.runtime)) {
                .yield(contextarg);
                 = ;
            }
        }
    }
    private IRubyObject rangeLt(ThreadContext contextIRubyObject aIRubyObject b) {
        IRubyObject result = invokedynamic(contextab);
        if (result.isNil()) return null;
        return RubyComparable.cmpint(contextresultab) < 0 ? getRuntime().getTrue() : null;
    }
    private IRubyObject rangeLe(ThreadContext contextIRubyObject aIRubyObject b) {
        IRubyObject result = invokedynamic(contextab);
        if (result.isNil()) return null;
        int c = RubyComparable.cmpint(contextresultab);
        if (c == 0) return RubyFixnum.zero(getRuntime());
        return c < 0 ? getRuntime().getTrue() : null;
    }    
    private void rangeEach(ThreadContext contextRangeCallBack callback) {
        IRubyObject v = ;
        if () {
            while (rangeLt(contextv) != null) {
                callback.call(contextv);
                v = v.callMethod(context"succ");
            }
        } else {
            IRubyObject c;
            while ((c = rangeLe(contextv)) != null && c.isTrue()) {
                callback.call(contextv);
                if (c == RubyFixnum.zero(getRuntime())) break;
                v = v.callMethod(context"succ");
            }
        }
    }
    public IRubyObject to_a(ThreadContext contextfinal Block block) {
        final Ruby runtime = context.runtime;
        if ( instanceof RubyFixnum &&  instanceof RubyFixnum) {
            long lim = ((RubyFixnum).getLongValue();
            if (!lim++;
            long base = ((RubyFixnum).getLongValue();
            long size = lim - base;
            if (size > .) {
                throw runtime.newRangeError("Range size too large for to_a");
            }
            if (size < 0) return RubyArray.newEmptyArray(runtime);
            IRubyObject[] array = new IRubyObject[(int)size];
            for (int i = 0; i < sizei++) {
                array[i] = RubyFixnum.newFixnum(runtimebase + i);
            }
            return RubyArray.newArrayNoCopy(runtimearray);
        } else {
            return RubyEnumerable.to_a(contextthis);
        }
    }
    @JRubyMethod(compat = )
    public IRubyObject each(ThreadContext contextfinal Block block) {
        final Ruby runtime = context.runtime;
        if (!block.isGiven()) return enumeratorize(runtimethis"each");
        if ( instanceof RubyFixnum &&  instanceof RubyFixnum) {
            fixnumEach(contextruntimeblock);
        } else if ( instanceof RubyString) {
            ((RubyString).uptoCommon18(contextblock);
        } else {
            if (!.respondsTo("succ")) throw getRuntime().newTypeError(
                    "can't iterate from " + .getMetaClass().getName());
            rangeEach(contextnew RangeCallBack() {
                @Override
                void call(ThreadContext contextIRubyObject arg) {
                    block.yield(contextarg);
                }
            });
        }
        return this;
    }
    private void fixnumEach(ThreadContext contextRuby runtimeBlock block) {
        // We must avoid integer overflows.
        long to = ((RubyFixnum).getLongValue();
        if () {
            if (to == .return;
            to--;
        }
        long from = ((RubyFixnum).getLongValue();
        if (block.getBody().getArgumentType() == .) {
            IRubyObject nil = runtime.getNil();
            long i;
            for (i = fromi < toi++) {
                block.yield(contextnil);
            }
            if (i <= to) {
                block.yield(contextnil);
            }
        } else {
            long i;
            for (i = fromi < toi++) {
                block.yield(context, RubyFixnum.newFixnum(runtimei));
            }
            if (i <= to) {
                block.yield(context, RubyFixnum.newFixnum(runtimei));
            }
        }
    }
    @JRubyMethod(name = "each", compat = )
    public IRubyObject each19(final ThreadContext contextfinal Block block) {
        Ruby runtime = context.runtime;
        if (!block.isGiven()) return enumeratorize(runtimethis"each");
        if ( instanceof RubyFixnum &&  instanceof RubyFixnum) {
            fixnumEach(contextruntimeblock);
        } else if ( instanceof RubyString) {
            ((RubyString).uptoCommon19(contextblock);
        } else if ( instanceof RubySymbol) {
            .asString().uptoCommon19(context.asString(), blocktrue);
        } else {
            if (!.respondsTo("succ")) throw getRuntime().newTypeError(
                    "can't iterate from " + .getMetaClass().getName());
            rangeEach(contextnew RangeCallBack() {
                @Override
                void call(ThreadContext contextIRubyObject arg) {
                    block.yield(contextarg);
                }
            });
        }
        return this;
    }
    @JRubyMethod(compat = )
    public IRubyObject step(ThreadContext contextIRubyObject stepBlock block) {
        return block.isGiven() ? stepCommon(contextstepblock) : enumeratorize(context.runtimethis"step"step);
    }
    @JRubyMethod(compat = )
    public IRubyObject step(ThreadContext contextBlock block) {
        return block.isGiven() ? stepCommon(context, RubyFixnum.one(context.runtime), block)  : enumeratorize(context.runtimethis"step");
    }
    private IRubyObject stepCommon(ThreadContext contextIRubyObject stepBlock block) {
        final Ruby runtime = context.runtime;
        long unit = RubyNumeric.num2long(step);
        if (unit < 0) throw runtime.newArgumentError("step can't be negative");
        if ( instanceof RubyFixnum &&  instanceof RubyFixnum) {
            if (unit == 0) throw runtime.newArgumentError("step can't be 0");
            fixnumStep(contextruntimeunitblock);
        } else {
            IRubyObject tmp = .checkStringType();
            if (!tmp.isNil()) {
                if (unit == 0) throw runtime.newArgumentError("step can't be 0");
                // rb_iterate((VALUE(*)_((VALUE)))str_step, (VALUE)args, step_i, (VALUE)iter);
                StepBlockCallBack callback = new StepBlockCallBack(block, RubyFixnum.one(runtime), step);
                Block blockCallback = CallBlock.newCallClosure(thisruntime.getRange(), Arity.singleArgument(), callbackcontext);
                ((RubyString)tmp).uptoCommon18(contextblockCallback);
            } else if ( instanceof RubyNumeric) {
                if (equalInternal(contextstep, RubyFixnum.zero(runtime))) throw runtime.newArgumentError("step can't be 0");
                numericStep(contextruntimestepblock);
            } else {
                if (unit == 0) throw runtime.newArgumentError("step can't be 0");
                if (!.respondsTo("succ")) throw runtime.newTypeError("can't iterate from " + .getMetaClass().getName());
                // range_each_func(range, step_i, b, e, args);
                rangeEach(contextnew StepBlockCallBack(block, RubyFixnum.one(runtime), step));
            }
        }
        return this;
    }
    private void fixnumStep(ThreadContext contextRuby runtimelong stepBlock block) {
        // We must avoid integer overflows.
        // Any method calling this method must ensure that "step" is greater than 0.
        long to = ((RubyFixnum).getLongValue();
        if () {
            if (to == .return;
            to--;
        }
        long tov = . - step;
        if (to < tovtov = to;
        long i;
        for (i = ((RubyFixnum)).getLongValue(); i <= tovi += step) {
            block.yield(context, RubyFixnum.newFixnum(runtimei));
        }
        if (i <= to) {
            block.yield(context, RubyFixnum.newFixnum(runtimei));
        }
    }
    private void numericStep(ThreadContext contextRuby runtimeIRubyObject stepBlock block) {
        final String method =  ? "<" : "<=";
        IRubyObject beg = ;
        while (beg.callMethod(contextmethod).isTrue()) {
            block.yield(contextbeg);
            beg = beg.callMethod(context"+"step);
        }
    }
    @JRubyMethod(name = "step", compat = )
    public IRubyObject step19(final ThreadContext contextfinal Block block) {
        return block.isGiven() ? stepCommon19(context, RubyFixnum.one(context.runtime), block) : enumeratorize(context.runtimethis"step");
    }
    @JRubyMethod(name = "step", compat = )
    public IRubyObject step19(final ThreadContext contextIRubyObject stepfinal Block block) {
        Ruby runtime = context.runtime;
        if (!block.isGiven()) return enumeratorize(runtimethis"step"step);
        if (!(step instanceof RubyNumeric)) step = step.convertToInteger("to_int");
        IRubyObject zero = RubyFixnum.zero(runtime);
        if (step.callMethod(context"<"zero).isTrue()) throw runtime.newArgumentError("step can't be negative");
        if (!step.callMethod(context">"zero).isTrue()) throw runtime.newArgumentError("step can't be 0");
        return stepCommon19(contextstepblock);
    }
    private IRubyObject stepCommon19(ThreadContext contextIRubyObject stepBlock block) {
        Ruby runtime = context.runtime;
        if ( instanceof RubyFixnum &&  instanceof RubyFixnum && step instanceof RubyFixnum) {
            fixnumStep(contextruntime, ((RubyFixnum)step).getLongValue(), block);
        } else if ( instanceof RubyFloat ||  instanceof RubyFloat || step instanceof RubyFloat) {
            RubyNumeric.floatStep19(contextruntimestepblock);
        } else if ( instanceof RubyNumeric ||
                        !TypeConverter.checkIntegerType(runtime"to_int").isNil() ||
                        !TypeConverter.checkIntegerType(runtime"to_int").isNil()) {
            numericStep19(contextruntimestepblock);
        } else {
            IRubyObject tmp = .checkStringType();
            if (!tmp.isNil()) {
                StepBlockCallBack callback = new StepBlockCallBack(block, RubyFixnum.one(runtime), step);
                Block blockCallback = CallBlock.newCallClosure(thisruntime.getRange(), Arity.singleArgument(), callbackcontext);
                ((RubyString)tmp).uptoCommon19(contextblockCallback);
            } else {
                if (!.respondsTo("succ")) throw runtime.newTypeError("can't iterate from " + .getMetaClass().getName());
                // range_each_func(range, step_i, b, e, args);
                rangeEach(contextnew StepBlockCallBack(block, RubyFixnum.one(runtime), step));
            }
        }
        return this;
    }
    private void numericStep19(ThreadContext contextRuby runtimeIRubyObject stepBlock block) {
        final String method =  ? "<" : "<=";
        IRubyObject beg = ;
        long i = 0;
        while (beg.callMethod(contextmethod).isTrue()) {
            block.yield(contextbeg);
            i++;
            beg = .callMethod(context"+", RubyFixnum.newFixnum(runtimei).callMethod(context"*"step));
        }
    }
    @JRubyMethod(name = {"include?""member?""==="}, required = 1, compat = )
    public RubyBoolean include_p(ThreadContext contextIRubyObject obj) {
        if (rangeLe(contextobj) != null) {
            if () {
                if (rangeLt(contextobj) != null) {
                    return context.runtime.getTrue();
                }
            } else {
                if (rangeLe(contextobj) != null) {
                    return context.runtime.getTrue();
                }
            }
        }
        return context.runtime.getFalse();
    }
    // framed for invokeSuper
    @JRubyMethod(name = {"include?""member?"}, frame = true, compat = )
    public IRubyObject include_p19(ThreadContext contextIRubyObject obj) {
        Ruby runtime = context.runtime;
        if ( instanceof RubyNumeric ||  instanceof RubyNumeric ||
                !TypeConverter.convertToTypeWithCheck(runtime.getInteger(), "to_int").isNil() ||
                !TypeConverter.convertToTypeWithCheck(runtime.getInteger(), "to_int").isNil()) {
            if (rangeLe(contextobj) != null) {
                if () {
                    if (rangeLt(contextobj) != nullreturn runtime.getTrue();
                } else {
                    if (rangeLe(contextobj) != nullreturn runtime.getTrue();
                }
            }
            return runtime.getFalse();
        } else if ( instanceof RubyString &&  instanceof RubyString &&
                ((RubyString).getByteList().getRealSize() == 1 &&
                ((RubyString).getByteList().getRealSize() == 1) {
            if (obj.isNil()) return runtime.getFalse();
            if (obj instanceof RubyString) {
                ByteList Vbytes = ((RubyString)obj).getByteList();
                if (Vbytes.getRealSize() != 1) return runtime.getFalse();
                int v = Vbytes.getUnsafeBytes()[Vbytes.getBegin()] & 0xff;
                ByteList Bbytes = ((RubyString)).getByteList();
                int b = Bbytes.getUnsafeBytes()[Bbytes.getBegin()] & 0xff;
                ByteList Ebytes = ((RubyString)).getByteList();
                int e = Ebytes.getUnsafeBytes()[Ebytes.getBegin()] & 0xff;
                if (Encoding.isAscii(v) && Encoding.isAscii(b) && Encoding.isAscii(e)) {
                    if ((b <= v && v < e) || (! && v == e)) return runtime.getTrue();
                    return runtime.getFalse();
                }
            }
        }
        return RuntimeHelpers.invokeSuper(contextthisobj.);
    }
    @JRubyMethod(name = "===", compat = )
    public IRubyObject eqq_p19(ThreadContext contextIRubyObject obj) {
        return callMethod(context"include?"obj);
    }
    @JRubyMethod(name = "cover?", compat = )
    public IRubyObject cover_p(ThreadContext contextIRubyObject obj) {
        return include_p(contextobj); // 1.8 "include?"
    }
    @JRubyMethod(compat = , frame = true)
    public IRubyObject min(ThreadContext contextBlock block) {
        if (block.isGiven()) {
            return RuntimeHelpers.invokeSuper(contextthisblock);
        } else {
            int c = RubyComparable.cmpint(contextinvokedynamic(context), );
            if (c > 0 || (c == 0 && )) {
                return context.runtime.getNil();
            }
            return ;
        }
    }
    @JRubyMethod(compat = , frame = true)
    public IRubyObject max(ThreadContext contextBlock block) {
        if (.callMethod(context">").isTrue()) {
            return context.runtime.getNil();
        }
        if (block.isGiven() ||  && !( instanceof RubyNumeric)) {
            return RuntimeHelpers.invokeSuper(contextthisblock);
        } else {
            int c = RubyComparable.cmpint(contextinvokedynamic(context), );
            Ruby runtime = context.runtime;
            if () {
                if (!( instanceof RubyInteger)) throw runtime.newTypeError("cannot exclude non Integer end value");
                if (c == 0) return runtime.getNil();
                if ( instanceof RubyFixnumreturn RubyFixnum.newFixnum(runtime, ((RubyFixnum)).getLongValue() - 1);
                return .callMethod(context"-", RubyFixnum.one(runtime));
            }
            return ;
        }
    }
    @JRubyMethod(name = "first", compat = )
    public IRubyObject first(ThreadContext context) {
        return ;
    }
    @JRubyMethod(name = "first", compat = )
    public IRubyObject first(ThreadContext contextIRubyObject arg) {
        final Ruby runtime = context.runtime;
        final int num = RubyNumeric.num2int(arg);
        final RubyArray result = runtime.newArray(num);
        try {
            RubyEnumerable.callEach(runtimecontextthis.new BlockCallback() {
                int n = num;
                public IRubyObject call(ThreadContext ctxIRubyObject[] largsBlock blk) {
                    if (-- <= 0) throw .;
                    result.append(largs[0]);
                    return runtime.getNil();
                }
            });
        } catch (JumpException.SpecialJump sj) {}
        return result;
    }
    @JRubyMethod(name = "last", compat = )
    public IRubyObject last(ThreadContext context) {
        return ;
    }
    @JRubyMethod(name = "last", compat = )
    public IRubyObject last(ThreadContext contextIRubyObject arg) {
        return ((RubyArray)RubyKernel.new_array(contextthisthis)).last(arg);
    }
    private static final ObjectMarshal RANGE_MARSHAL = new ObjectMarshal() {
        public void marshalTo(Ruby runtimeObject objRubyClass type,
                              MarshalStream marshalStreamthrows IOException {
            RubyRange range = (RubyRange)obj;
            marshalStream.registerLinkTarget(range);
            List<Variable<Object>> attrs = range.getVariableList();
            attrs.add(new VariableEntry<Object>("begin"range.begin));
            attrs.add(new VariableEntry<Object>("end"range.end));
            attrs.add(new VariableEntry<Object>("excl"range.isExclusive ? runtime.getTrue() : runtime.getFalse()));
            marshalStream.dumpVariables(attrs);
        }
        public Object unmarshalFrom(Ruby runtimeRubyClass type,
                                    UnmarshalStream unmarshalStreamthrows IOException {
            RubyRange range = (RubyRange)type.allocate();
            
            unmarshalStream.registerLinkTarget(range);
            // FIXME: Maybe we can just gank these off the line directly?
            unmarshalStream.defaultVariablesUnmarshal(range);
            
            range.begin = (IRubyObject)range.removeInternalVariable("begin");
            range.end = (IRubyObject)range.removeInternalVariable("end");
            range.isExclusive = ((IRubyObject)range.removeInternalVariable("excl")).isTrue();
            return range;
        }
    };