rubinius-core-api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,115 @@
1
+ /*
2
+ **** BEGIN LICENSE BLOCK *****
3
+ * Version: CPL 1.0/GPL 2.0/LGPL 2.1
4
+ *
5
+ * The contents of this file are subject to the Common Public
6
+ * License Version 1.0 (the "License"); you may not use this file
7
+ * except in compliance with the License. You may obtain a copy of
8
+ * the License at http://www.eclipse.org/legal/cpl-v10.html
9
+ *
10
+ * Software distributed under the License is distributed on an "AS
11
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12
+ * implied. See the License for the specific language governing
13
+ * rights and limitations under the License.
14
+ *
15
+ * Copyright (C) 2011 Charles O Nutter <headius@headius.com>
16
+ *
17
+ * Alternatively, the contents of this file may be used under the terms of
18
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
19
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20
+ * in which case the provisions of the GPL or the LGPL are applicable instead
21
+ * of those above. If you wish to allow use of your version of this file only
22
+ * under the terms of either the GPL or the LGPL, and not to allow others to
23
+ * use your version of this file under the terms of the CPL, indicate your
24
+ * decision by deleting the provisions above and replace them with the notice
25
+ * and other provisions required by the GPL or the LGPL. If you do not delete
26
+ * the provisions above, a recipient may use your version of this file under
27
+ * the terms of any one of the CPL, the GPL or the LGPL.
28
+ ***** END LICENSE BLOCK *****/
29
+ package org.jruby.ext.rubinius;
30
+
31
+ import java.util.concurrent.LinkedBlockingQueue;
32
+ import java.util.concurrent.TimeUnit;
33
+ import org.jruby.Ruby;
34
+ import org.jruby.RubyClass;
35
+ import org.jruby.RubyFixnum;
36
+ import org.jruby.RubyFloat;
37
+ import org.jruby.RubyObject;
38
+ import org.jruby.anno.JRubyMethod;
39
+ import org.jruby.runtime.ObjectAllocator;
40
+ import org.jruby.runtime.ThreadContext;
41
+ import org.jruby.runtime.builtin.IRubyObject;
42
+
43
+ public class RubiniusChannel extends RubyObject {
44
+ private final LinkedBlockingQueue<IRubyObject> queue = new LinkedBlockingQueue();
45
+
46
+ public RubiniusChannel(Ruby runtime, RubyClass metaclass) {
47
+ super(runtime, metaclass);
48
+ }
49
+
50
+ public static void createChannelClass(Ruby runtime) {
51
+ RubyClass channelClass = runtime
52
+ .getOrCreateModule("Rubinius")
53
+ .defineClassUnder("Channel", runtime.getObject(), new ObjectAllocator() {
54
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
55
+ return new RubiniusChannel(runtime, klazz);
56
+ }
57
+ });
58
+ channelClass.setReifiedClass(RubiniusChannel.class);
59
+
60
+ channelClass.defineAnnotatedMethods(RubiniusChannel.class);
61
+ }
62
+
63
+ @JRubyMethod(name = "new", meta = true)
64
+ public static IRubyObject rbNew(ThreadContext context, IRubyObject channelClass) {
65
+ return new RubiniusChannel(context.runtime, (RubyClass)channelClass);
66
+ }
67
+
68
+ @JRubyMethod(name = {"send", "<<"})
69
+ public IRubyObject send(ThreadContext context, IRubyObject value) {
70
+ queue.add(value);
71
+ return context.nil;
72
+ }
73
+
74
+ @JRubyMethod
75
+ public IRubyObject receive(ThreadContext context) {
76
+ try {
77
+ return queue.take();
78
+ } catch (InterruptedException ie) {
79
+ return context.runtime.getFalse();
80
+ }
81
+ }
82
+
83
+ private static final int NANOSECONDS = 1000000;
84
+
85
+ @JRubyMethod
86
+ public IRubyObject receive_timeout(ThreadContext context, IRubyObject timeout) {
87
+ long time = 0;
88
+ if (timeout instanceof RubyFixnum) {
89
+ time = ((RubyFixnum)timeout).getLongValue() * NANOSECONDS;
90
+ } else if (timeout instanceof RubyFloat) {
91
+ time = (long)(((RubyFloat)timeout).getDoubleValue() * NANOSECONDS);
92
+ } else if (timeout.isNil()) {
93
+ time = -1;
94
+ } else {
95
+ throw context.runtime.newTypeError("expected Fixnum or Float to Channel#receive_timeout");
96
+ }
97
+
98
+ try {
99
+ if (time == -1) {
100
+ return queue.take();
101
+ } else {
102
+ return queue.poll(time, TimeUnit.NANOSECONDS);
103
+ }
104
+ } catch (InterruptedException ie) {
105
+ return context.runtime.getFalse();
106
+ }
107
+ }
108
+
109
+ @JRubyMethod
110
+ public IRubyObject try_receive(ThreadContext context) {
111
+ IRubyObject result = queue.poll();
112
+ if (result == null) return context.nil;
113
+ return result;
114
+ }
115
+ }
@@ -0,0 +1,57 @@
1
+ /*
2
+ **** BEGIN LICENSE BLOCK *****
3
+ * Version: CPL 1.0/GPL 2.0/LGPL 2.1
4
+ *
5
+ * The contents of this file are subject to the Common Public
6
+ * License Version 1.0 (the "License"); you may not use this file
7
+ * except in compliance with the License. You may obtain a copy of
8
+ * the License at http://www.eclipse.org/legal/cpl-v10.html
9
+ *
10
+ * Software distributed under the License is distributed on an "AS
11
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12
+ * implied. See the License for the specific language governing
13
+ * rights and limitations under the License.
14
+ *
15
+ * Copyright (C) 2011 Charles O Nutter <headius@headius.com>
16
+ *
17
+ * Alternatively, the contents of this file may be used under the terms of
18
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
19
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20
+ * in which case the provisions of the GPL or the LGPL are applicable instead
21
+ * of those above. If you wish to allow use of your version of this file only
22
+ * under the terms of either the GPL or the LGPL, and not to allow others to
23
+ * use your version of this file under the terms of the CPL, indicate your
24
+ * decision by deleting the provisions above and replace them with the notice
25
+ * and other provisions required by the GPL or the LGPL. If you do not delete
26
+ * the provisions above, a recipient may use your version of this file under
27
+ * the terms of any one of the CPL, the GPL or the LGPL.
28
+ ***** END LICENSE BLOCK *****/
29
+ package org.jruby.ext.rubinius;
30
+
31
+ import org.jruby.RubyHash;
32
+ import org.jruby.anno.JRubyMethod;
33
+ import org.jruby.runtime.ThreadContext;
34
+ import org.jruby.runtime.builtin.IRubyObject;
35
+
36
+ public class RubiniusEnvironmentAccess {
37
+
38
+ @JRubyMethod(module = true)
39
+ public static IRubyObject getenv(ThreadContext context, IRubyObject self, IRubyObject name) {
40
+ return getEnv(context).op_aref(context, name);
41
+ }
42
+
43
+ @JRubyMethod(module = true)
44
+ public static IRubyObject setenv(ThreadContext context, IRubyObject self, IRubyObject name, IRubyObject value) {
45
+ return getEnv(context).op_aset(context, name, value);
46
+ }
47
+
48
+ @JRubyMethod(module = true)
49
+ public static IRubyObject environ_as_hash(ThreadContext context, IRubyObject self) {
50
+ return getEnv(context).dup();
51
+ }
52
+
53
+ private static RubyHash getEnv(ThreadContext context) {
54
+ return context.runtime.getENV();
55
+ }
56
+
57
+ }
@@ -0,0 +1,42 @@
1
+ /*
2
+ **** BEGIN LICENSE BLOCK *****
3
+ * Version: CPL 1.0/GPL 2.0/LGPL 2.1
4
+ *
5
+ * The contents of this file are subject to the Common Public
6
+ * License Version 1.0 (the "License"); you may not use this file
7
+ * except in compliance with the License. You may obtain a copy of
8
+ * the License at http://www.eclipse.org/legal/cpl-v10.html
9
+ *
10
+ * Software distributed under the License is distributed on an "AS
11
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12
+ * implied. See the License for the specific language governing
13
+ * rights and limitations under the License.
14
+ *
15
+ * Copyright (C) 2011 Charles O Nutter <headius@headius.com>
16
+ *
17
+ * Alternatively, the contents of this file may be used under the terms of
18
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
19
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20
+ * in which case the provisions of the GPL or the LGPL are applicable instead
21
+ * of those above. If you wish to allow use of your version of this file only
22
+ * under the terms of either the GPL or the LGPL, and not to allow others to
23
+ * use your version of this file under the terms of the CPL, indicate your
24
+ * decision by deleting the provisions above and replace them with the notice
25
+ * and other provisions required by the GPL or the LGPL. If you do not delete
26
+ * the provisions above, a recipient may use your version of this file under
27
+ * the terms of any one of the CPL, the GPL or the LGPL.
28
+ ***** END LICENSE BLOCK *****/
29
+ package org.jruby.ext.rubinius;
30
+
31
+ import org.jruby.anno.JRubyMethod;
32
+ import org.jruby.runtime.ThreadContext;
33
+ import org.jruby.runtime.builtin.IRubyObject;
34
+
35
+ public class RubiniusKernel {
36
+
37
+ @JRubyMethod(module = true)
38
+ public static IRubyObject StringValue(ThreadContext context, IRubyObject self, IRubyObject arg) {
39
+ return arg.convertToString();
40
+ }
41
+
42
+ }
@@ -0,0 +1,111 @@
1
+ /*
2
+ **** BEGIN LICENSE BLOCK *****
3
+ * Version: CPL 1.0/GPL 2.0/LGPL 2.1
4
+ *
5
+ * The contents of this file are subject to the Common Public
6
+ * License Version 1.0 (the "License"); you may not use this file
7
+ * except in compliance with the License. You may obtain a copy of
8
+ * the License at http://www.eclipse.org/legal/cpl-v10.html
9
+ *
10
+ * Software distributed under the License is distributed on an "AS
11
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12
+ * implied. See the License for the specific language governing
13
+ * rights and limitations under the License.
14
+ *
15
+ * Copyright (C) 2011 Charles O Nutter <headius@headius.com>
16
+ *
17
+ * Alternatively, the contents of this file may be used under the terms of
18
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
19
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20
+ * in which case the provisions of the GPL or the LGPL are applicable instead
21
+ * of those above. If you wish to allow use of your version of this file only
22
+ * under the terms of either the GPL or the LGPL, and not to allow others to
23
+ * use your version of this file under the terms of the CPL, indicate your
24
+ * decision by deleting the provisions above and replace them with the notice
25
+ * and other provisions required by the GPL or the LGPL. If you do not delete
26
+ * the provisions above, a recipient may use your version of this file under
27
+ * the terms of any one of the CPL, the GPL or the LGPL.
28
+ ***** END LICENSE BLOCK *****/
29
+ package org.jruby.ext.rubinius;
30
+
31
+ import java.io.IOException;
32
+ import org.jruby.Ruby;
33
+ import org.jruby.RubyClass;
34
+ import org.jruby.RubyModule;
35
+ import org.jruby.RubyObject;
36
+ import org.jruby.exceptions.RaiseException;
37
+ import org.jruby.internal.runtime.methods.JavaMethod;
38
+ import org.jruby.runtime.ObjectAllocator;
39
+ import org.jruby.runtime.ThreadContext;
40
+ import org.jruby.runtime.builtin.IRubyObject;
41
+ import org.jruby.runtime.load.Library;
42
+ import static org.jruby.runtime.Visibility.*;
43
+
44
+ /**
45
+ * This extension defines a number of classes/modules and modifications to core
46
+ * that are used by parts of Rubinius's kernel and libraries. The intent here is
47
+ * to provide as many of those Rubinius-borne features as possible to allow
48
+ * users to write to those APIs (for their own libraries or for extending JRuby)
49
+ * and eventually to share more of Rubinius's core class implementations with
50
+ * JRuby.
51
+ */
52
+ public class RubiniusLibrary implements Library {
53
+ public void load(final Ruby runtime, boolean wrap) throws IOException {
54
+ RubyModule rubinius = runtime.getOrCreateModule("Rubinius");
55
+
56
+ final IRubyObject undefined = new RubyObject(runtime, runtime.getObject());
57
+ runtime.getKernel().addMethod("undefined", new JavaMethod.JavaMethodZero(runtime.getKernel(), PRIVATE) {
58
+ @Override
59
+ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name) {
60
+ return undefined;
61
+ }
62
+ });
63
+
64
+ // Tuple class
65
+ RubiniusTuple.createTupleClass(runtime);
66
+ runtime.getLoadService().require("rubinius/kernel/common/tuple.rb");
67
+
68
+ // Type module
69
+ RubyModule type = runtime.defineModule("Type");
70
+ type.defineAnnotatedMethods(RubiniusType.class);
71
+ runtime.getLoadService().require("rubinius/kernel/common/type.rb");
72
+
73
+ // LookupTable is just Hash for now
74
+ rubinius.setConstant("LookupTable", runtime.getHash());
75
+
76
+ // EnvironmentAccess
77
+ RubyModule envAccess = rubinius.defineModuleUnder("EnvironmentAccess");
78
+ envAccess.defineAnnotatedMethods(RubiniusEnvironmentAccess.class);
79
+ runtime.getLoadService().require("rubinius/kernel/common/env.rb");
80
+
81
+ // Thread-borne recursion detector stuff
82
+ runtime.getLoadService().require("rubinius/kernel/common/thread.rb");
83
+
84
+ // Extensions to Kernel
85
+ runtime.getKernel().defineAnnotatedMethods(RubiniusKernel.class);
86
+
87
+ // Channel class; we require bootstrap, overwrite it, and then require common
88
+ runtime.getLoadService().require("rubinius/kernel/bootstrap/channel.rb");
89
+ RubiniusChannel.createChannelClass(runtime);
90
+ runtime.getLoadService().require("rubinius/kernel/common/channel.rb");
91
+
92
+ // Rubinius exception types
93
+ RubyClass vmException = rubinius.defineClassUnder("VMException", runtime.getException(), runtime.getException().getAllocator());
94
+ rubinius.defineClassUnder("ObjectBoundsExceededError", vmException, vmException.getAllocator());
95
+ rubinius.defineClassUnder("AssertionError", vmException, vmException.getAllocator());
96
+
97
+ // ByteArray
98
+ RubiniusByteArray.createByteArrayClass(runtime);
99
+ runtime.getLoadService().require("rubinius/kernel/common/bytearray.rb");
100
+ }
101
+
102
+ public static RaiseException object_bounds_exceeded_error(ThreadContext context, String message) {
103
+ throw context.runtime.newRaiseException(
104
+ (RubyClass)context.runtime.getClassFromPath("Rubinius::ObjectBoundsExceededError"),
105
+ message);
106
+ }
107
+
108
+ public static RaiseException argument_error(ThreadContext context, String message) {
109
+ throw context.runtime.newArgumentError(message);
110
+ }
111
+ }
@@ -0,0 +1,302 @@
1
+ /*
2
+ **** BEGIN LICENSE BLOCK *****
3
+ * Version: CPL 1.0/GPL 2.0/LGPL 2.1
4
+ *
5
+ * The contents of this file are subject to the Common Public
6
+ * License Version 1.0 (the "License"); you may not use this file
7
+ * except in compliance with the License. You may obtain a copy of
8
+ * the License at http://www.eclipse.org/legal/cpl-v10.html
9
+ *
10
+ * Software distributed under the License is distributed on an "AS
11
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12
+ * implied. See the License for the specific language governing
13
+ * rights and limitations under the License.
14
+ *
15
+ * Copyright (C) 2010 Charles O Nutter <headius@headius.com>
16
+ *
17
+ * Alternatively, the contents of this file may be used under the terms of
18
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
19
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20
+ * in which case the provisions of the GPL or the LGPL are applicable instead
21
+ * of those above. If you wish to allow use of your version of this file only
22
+ * under the terms of either the GPL or the LGPL, and not to allow others to
23
+ * use your version of this file under the terms of the CPL, indicate your
24
+ * decision by deleting the provisions above and replace them with the notice
25
+ * and other provisions required by the GPL or the LGPL. If you do not delete
26
+ * the provisions above, a recipient may use your version of this file under
27
+ * the terms of any one of the CPL, the GPL or the LGPL.
28
+ ***** END LICENSE BLOCK *****/
29
+ package org.jruby.ext.rubinius;
30
+
31
+ import java.util.Arrays;
32
+ import org.jruby.Ruby;
33
+ import org.jruby.RubyArray;
34
+ import org.jruby.RubyClass;
35
+ import org.jruby.RubyFixnum;
36
+ import org.jruby.RubyObject;
37
+ import org.jruby.anno.JRubyMethod;
38
+ import org.jruby.javasupport.util.RuntimeHelpers;
39
+ import org.jruby.runtime.ObjectAllocator;
40
+ import org.jruby.runtime.ThreadContext;
41
+ import org.jruby.runtime.builtin.IRubyObject;
42
+ import org.jruby.util.ArraysUtil;
43
+
44
+ public class RubiniusTuple extends RubyObject {
45
+
46
+ private IRubyObject[] ary;
47
+
48
+ public RubiniusTuple(Ruby runtime, int size) {
49
+ super(runtime, (RubyClass) runtime.getClassFromPath("Rubinius::Tuple"));
50
+
51
+ this.ary = new IRubyObject[size];
52
+ RuntimeHelpers.fillNil(ary, runtime);
53
+ }
54
+
55
+ public RubiniusTuple(Ruby runtime, int size, IRubyObject fill) {
56
+ super(runtime, (RubyClass) runtime.getClassFromPath("Rubinius::Tuple"));
57
+
58
+ this.ary = new IRubyObject[size];
59
+ if (fill == runtime.getNil()) {
60
+ RuntimeHelpers.fillNil(ary, runtime);
61
+ } else {
62
+ Arrays.fill(this.ary, fill);
63
+ }
64
+ }
65
+
66
+ public static void createTupleClass(Ruby runtime) {
67
+ RubyClass tupleClass = runtime.getOrCreateModule("Rubinius").defineClassUnder("Tuple", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
68
+ tupleClass.setReifiedClass(RubiniusTuple.class);
69
+
70
+ tupleClass.defineAnnotatedMethods(RubiniusTuple.class);
71
+ }
72
+
73
+ public int num_fields() {
74
+ return ary.length;
75
+ }
76
+
77
+ public IRubyObject field(int index) {
78
+ return ary[index];
79
+ }
80
+
81
+ private void bounds_exceeded_error(ThreadContext state, String method, long index) {
82
+ throw RubiniusLibrary.object_bounds_exceeded_error(state, method + ": index " + index + " out of bounds for size " + ary.length);
83
+ }
84
+
85
+ static RubiniusTuple create(ThreadContext context, int size) {
86
+ return new RubiniusTuple(context.runtime, size);
87
+ }
88
+
89
+ static RubiniusTuple create(ThreadContext context, int size, IRubyObject fill) {
90
+ return new RubiniusTuple(context.runtime, size, fill);
91
+ }
92
+
93
+ @JRubyMethod(meta = true)
94
+ public static IRubyObject allocate(ThreadContext state, IRubyObject baClass, IRubyObject size) {
95
+ throw state.runtime.newTypeError("Tuple cannot be created via allocate()");
96
+ }
97
+
98
+ @JRubyMethod(name = "new", meta = true)
99
+ public static IRubyObject rbNew(ThreadContext state, IRubyObject tupleCls, IRubyObject fields) {
100
+ long size = fields.convertToInteger().getLongValue();
101
+ if (size < 0) {
102
+ RubiniusLibrary.argument_error(state, "negative tuple size");
103
+ } else if (size > Integer.MAX_VALUE) {
104
+ RubiniusLibrary.argument_error(state, "too large tuple size");
105
+ }
106
+ return RubiniusTuple.create(state, (int) size);
107
+ }
108
+
109
+ @JRubyMethod(meta = true)
110
+ public static IRubyObject pattern(ThreadContext state, IRubyObject size, IRubyObject obj) {
111
+ long cnt = size.convertToInteger().getLongValue();
112
+
113
+ if (cnt < 0) {
114
+ RubiniusLibrary.argument_error(state, "negative tuple size");
115
+ } else if (cnt > Integer.MAX_VALUE) {
116
+ RubiniusLibrary.argument_error(state, "too large tuple size");
117
+ }
118
+
119
+ return RubiniusTuple.create(state, (int) cnt, obj);
120
+ }
121
+
122
+ @JRubyMethod(name = {"[]", "at"})
123
+ public IRubyObject op_aref(ThreadContext state, IRubyObject index) {
124
+ long idx = index.convertToInteger().getLongValue();
125
+
126
+ if (idx < 0 || num_fields() <= idx) {
127
+ bounds_exceeded_error(state, "Tuple::put_prim", idx);
128
+ }
129
+
130
+ return ary[(int) idx];
131
+ }
132
+
133
+ @JRubyMethod(name = {"[]=", "put"})
134
+ public IRubyObject op_aset(ThreadContext state, IRubyObject index, IRubyObject val) {
135
+ long idx = index.convertToInteger().getLongValue();
136
+
137
+ if (idx < 0 || num_fields() <= idx) {
138
+ bounds_exceeded_error(state, "Tuple::put_prim", idx);
139
+ }
140
+
141
+ this.ary[(int) idx] = val;
142
+ return val;
143
+ }
144
+
145
+ @JRubyMethod
146
+ public IRubyObject fields(ThreadContext state) {
147
+ return RubyFixnum.newFixnum(state.runtime, ary.length);
148
+ }
149
+
150
+ @JRubyMethod(required = 4)
151
+ public IRubyObject copy_from(ThreadContext state, IRubyObject[] args) {
152
+ IRubyObject _other = args[0];
153
+ IRubyObject start = args[1];
154
+ IRubyObject length = args[2];
155
+ IRubyObject dest = args[3];
156
+
157
+ RubiniusTuple other = (RubiniusTuple) _other;
158
+ int osize = other.num_fields();
159
+ int size = this.num_fields();
160
+
161
+ long src_start = start.convertToInteger().getLongValue();
162
+ long dst_start = dest.convertToInteger().getLongValue();
163
+ long len = length.convertToInteger().getLongValue();
164
+
165
+ // left end should be within range
166
+ if (src_start < 0 || src_start > osize) {
167
+ other.bounds_exceeded_error(state, "Tuple::copy_from", src_start);
168
+ }
169
+
170
+ if (dst_start < 0 || dst_start > size) {
171
+ bounds_exceeded_error(state, "Tuple::copy_from", dst_start);
172
+ }
173
+
174
+ // length can not be negative and must fit in src/dest
175
+ if (len < 0) {
176
+ other.bounds_exceeded_error(state, "Tuple::copy_from", len);
177
+ }
178
+
179
+ if ((src_start + len) > osize) {
180
+ other.bounds_exceeded_error(state, "Tuple::copy_from", src_start + len);
181
+ }
182
+
183
+ if (len > (size - dst_start)) {
184
+ bounds_exceeded_error(state, "Tuple::copy_from", len);
185
+ }
186
+
187
+ // A memmove within the tuple
188
+ if (other == this) {
189
+ // No movement, no work!
190
+ if (src_start == dst_start) {
191
+ return this;
192
+ }
193
+ // right shift
194
+ if (src_start < dst_start) {
195
+ for (long dest_idx = dst_start + len - 1,
196
+ src_idx = src_start + len - 1;
197
+ src_idx >= src_start;
198
+ src_idx--, dest_idx--) {
199
+ this.ary[(int) dest_idx] = this.ary[(int) src_idx];
200
+ }
201
+ } else {
202
+ // left shift
203
+ for (long dest_idx = dst_start,
204
+ src_idx = src_start;
205
+ src_idx < src_start + len;
206
+ src_idx++, dest_idx++) {
207
+ this.ary[(int) dest_idx] = this.ary[(int) src_idx];
208
+ }
209
+ }
210
+
211
+ } else {
212
+ for (long src = src_start, dst = dst_start;
213
+ src < (src_start + len);
214
+ ++src, ++dst) {
215
+ // Since we have carefully checked the bounds we don't need
216
+ // to do it in at/put
217
+ IRubyObject obj = other.ary[(int) src];
218
+ this.ary[(int) dst] = obj;
219
+ }
220
+ }
221
+
222
+ return this;
223
+ }
224
+
225
+ @JRubyMethod
226
+ public IRubyObject dup() {
227
+ return super.dup();
228
+ }
229
+
230
+ @JRubyMethod
231
+ public IRubyObject delete(ThreadContext state, IRubyObject start, IRubyObject length, IRubyObject obj) {
232
+ int size = this.num_fields();
233
+ long len = length.convertToInteger().getLongValue();
234
+ long lend = start.convertToInteger().getLongValue();
235
+ long rend = lend + len;
236
+
237
+ if (size == 0 || len == 0) {
238
+ return RubyFixnum.zero(state.runtime);
239
+ }
240
+ if (lend < 0 || lend >= size) {
241
+ bounds_exceeded_error(state, "Tuple::delete_inplace", lend);
242
+ }
243
+
244
+ if (rend < 0 || rend > size) {
245
+ bounds_exceeded_error(state, "Tuple::delete_inplace", rend);
246
+ }
247
+
248
+ int i = (int) lend;
249
+ while (i < rend) {
250
+ if (this.ary[i] == obj) {
251
+ int j = i;
252
+ ++i;
253
+ while (i < rend) {
254
+ IRubyObject val = this.ary[i];
255
+ if (val != obj) {
256
+ // no need to set write_barrier since it's already
257
+ // referenced to this object
258
+ this.ary[j] = val;
259
+ ++j;
260
+ }
261
+ ++i;
262
+ }
263
+ // cleanup all the bins after
264
+ i = j;
265
+ while (i < rend) {
266
+ this.ary[i] = state.nil;
267
+ ++i;
268
+ }
269
+ return RubyFixnum.newFixnum(state.runtime, rend - j);
270
+ }
271
+ ++i;
272
+ }
273
+ return RubyFixnum.zero(state.runtime);
274
+ }
275
+
276
+ @JRubyMethod
277
+ public IRubyObject reverse(ThreadContext state, IRubyObject o_start, IRubyObject o_total) {
278
+ long start = o_start.convertToInteger().getLongValue();
279
+ long total = o_total.convertToInteger().getLongValue();
280
+
281
+ if (total <= 0 || start < 0 || start >= num_fields()) {
282
+ return this;
283
+ }
284
+
285
+ long end = start + total - 1;
286
+ if (end >= num_fields()) {
287
+ end = num_fields() - 1;
288
+ }
289
+
290
+ int pos1 = (int) start;
291
+ int pos2 = (int) end;
292
+
293
+ IRubyObject tmp;
294
+ while (pos1 < pos2) {
295
+ tmp = ary[pos1];
296
+ ary[pos1++] = ary[pos2];
297
+ ary[pos2--] = tmp;
298
+ }
299
+
300
+ return this;
301
+ }
302
+ }