Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 76b7f0ccd74c
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ec4bc4e7ff9c
Choose a head ref
  • 2 commits
  • 5 files changed
  • 2 contributors

Commits on Mar 16, 2015

  1. Copy the full SHA
    04ec0c3 View commit details
  2. Merge pull request #2710 from bjfish/truffle_array_slice_bang

    [Truffle] Adding Array#slice! to array.rb
    nirvdrum committed Mar 16, 2015
    Copy the full SHA
    ec4bc4e View commit details
10 changes: 0 additions & 10 deletions spec/truffle/tags/core/array/slice_tags.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.rubinius;

import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyNilClass;

public abstract class ArrayPrimitiveNodes {

@RubiniusPrimitive(name = "tuple_copy_from")
public static abstract class TupleCopyFromPrimitiveNode extends RubiniusPrimitiveNode {

public TupleCopyFromPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public TupleCopyFromPrimitiveNode(TupleCopyFromPrimitiveNode prev) {
super(prev);
}

@Specialization
public Object tupleCopyFrom() {
return null;
}

}

}
Original file line number Diff line number Diff line change
@@ -54,6 +54,7 @@ public static RubiniusPrimitiveManager create() {
nodeFactories.addAll(RegexpPrimitiveNodesFactory.getFactories());
nodeFactories.addAll(ModulePrimitiveNodesFactory.getFactories());
nodeFactories.addAll(RandomPrimitiveNodesFactory.getFactories());
nodeFactories.addAll(ArrayPrimitiveNodesFactory.getFactories());

final Map<String, RubiniusPrimitiveConstructor> primitives = new HashMap<>();

48 changes: 42 additions & 6 deletions truffle/src/main/ruby/core/rubinius/api/shims/tuple.rb
Original file line number Diff line number Diff line change
@@ -14,12 +14,6 @@ def self.pattern(num, val)
Tuple.new(num, val)
end

def copy_from(other, start, length, dest)
# TODO CS 6-Feb-15 use higher level indexing when it works
length.times do |n|
self[dest + n] = other[start + n]
end
end

end

@@ -28,6 +22,48 @@ def copy_from(other, start, length, dest)

class Array

def copy_from(other, start, length, dest)
Rubinius.primitive :tuple_copy_from

unless other.kind_of? Array # Rubinius::Tuple # We use Array
raise TypeError, "Tuple#copy_from was expecting an Array, not a #{other.class}"
end
start = Rubinius::Type.coerce_to start, Fixnum, :to_i
length = Rubinius::Type.coerce_to length, Fixnum, :to_i
dest = Rubinius::Type.coerce_to dest, Fixnum, :to_i

if start < 0 || start > other.size # other.fields
raise IndexError, "Start %d is out of bounds %d" % [start, other.size]# other.fields]
end

if dest < 0 || dest > self.size # self.fields
raise IndexError, "Destination %d is out of bounds %d" % [dest, self.size] # self.fields]
end

if length < 0
raise IndexError, "length %d must be positive" % [length]
end

if (start + length) > other.size # other.fields
raise IndexError, "end index %d can not exceed size of source %d" % [start+length, other.size]# other.fields]
end

if length > ( self.size - dest )#self.fields - dest)
raise IndexError, "length %d can not exceed space %d in destination" % [length, self.size - dest]#self.fields - dest]
end

src = start
dst = dest
while src < (start + length)
put dst, other.at(src)
src += 1
dst += 1
end

self
end


def swap(a, b)
temp = at(a)
self[a] = at(b)
107 changes: 107 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/array.rb
Original file line number Diff line number Diff line change
@@ -474,6 +474,42 @@ def each_index
self
end

# WARNING: This method does no boundary checking. It is expected that
# the caller handle that, eg #slice!
def delete_range(index, del_length)
# optimize for fast removal..
reg_start = index + del_length
reg_length = @total - reg_start
if reg_start <= @total
# If we're removing from the front, also reset @start to better
# use the Tuple
if index == 0
# Use a shift start optimization if we're only removing one
# element and the shift started isn't already huge.
if del_length == 1
@start += 1
else
@tuple.copy_from @tuple, reg_start + @start, reg_length, 0
@start = 0
end
else
@tuple.copy_from @tuple, reg_start + @start, reg_length,
@start + index
end

# TODO we leave the old references in the Tuple, we should
# probably clear them out though.
# MODIFIED Can't -= the @total to modify length
#@total -= del_length
del_length.times do
self.pop
end

end
end

private :delete_range

def fill(a=undefined, b=undefined, c=undefined)
Rubinius.check_frozen

@@ -879,6 +915,77 @@ def shuffle!(options = undefined)
self
end

def slice!(start, length=undefined)
Rubinius.check_frozen

if undefined.equal? length
if start.kind_of? Range
range = start
out = self[range]

range_start = Rubinius::Type.coerce_to_collection_index range.begin
if range_start < 0
range_start = range_start + @total
end

range_end = Rubinius::Type.coerce_to_collection_index range.end
if range_end < 0
range_end = range_end + @total
elsif range_end >= @total
range_end = @total - 1
range_end += 1 if range.exclude_end?
end

range_length = range_end - range_start
range_length += 1 unless range.exclude_end?
range_end -= 1 if range.exclude_end?

if range_start < @total && range_start >= 0 && range_end < @total && range_end >= 0 && range_length > 0
delete_range(range_start, range_length)
end
else
# make sure that negative values are not passed through to the
# []= assignment
start = Rubinius::Type.coerce_to_collection_index start
start = start + @total if start < 0
# This is to match the MRI behaviour of not extending the array
# with nil when specifying an index greater than the length
# of the array.
return out unless start >= 0 and start < @total

out = @tuple.at start + @start

# Check for shift style.
if start == 0
@tuple.put @start, nil
# @total -= 1 # MODIFIED Can't modify size using @total
self.shift
@start += 1
else
delete_range(start, 1)
end
end
else
start = Rubinius::Type.coerce_to_collection_index start
length = Rubinius::Type.coerce_to_collection_index length

out = self[start, length]

if start < 0
start = @total + start
end
if start + length > @total
length = @total - start
end

if start < @total && start >= 0
delete_range(start, length)
end
end

out
end

def to_ary
self
end