Skip to content

Commit

Permalink
Showing 2 changed files with 67 additions and 35 deletions.
101 changes: 67 additions & 34 deletions core/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java
Original file line number Diff line number Diff line change
@@ -32,11 +32,21 @@
import org.jruby.truffle.nodes.methods.locals.ReadLevelVariableNodeFactory;
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.nodes.core.ArrayNodesFactory.AtNodeFactory;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.UndefinedPlaceholder;
import org.jruby.truffle.runtime.control.BreakException;
import org.jruby.truffle.runtime.control.NextException;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.control.RedoException;
import org.jruby.truffle.runtime.core.*;
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyModule;
import org.jruby.truffle.runtime.core.RubyNilClass;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.runtime.core.RubyRange;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.truffle.runtime.core.RubySymbol;
import org.jruby.truffle.runtime.methods.MethodLike;
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
import org.jruby.truffle.runtime.util.ArrayUtils;
@@ -529,24 +539,26 @@ public boolean equal(VirtualFrame frame, RubyArray a, Object b) {

}

@CoreMethod(names = {"[]", "at"}, required = 1, optional = 1, lowerFixnumParameters = {0, 1})
public abstract static class IndexNode extends ArrayCoreMethodNode {
@CoreMethod(names = "at", required = 1, lowerFixnumParameters = 0)
public abstract static class AtNode extends ArrayCoreMethodNode {

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

public IndexNode(IndexNode prev) {
public AtNode(AtNode prev) {
super(prev);
}

public abstract Object executeAt(RubyArray array, int index);

@Specialization(guards = "isNull")
public RubyNilClass getNull(RubyArray array, int index, UndefinedPlaceholder undefined) {
public RubyNilClass getNull(RubyArray array, int index) {
return getContext().getCoreLibrary().getNilObject();
}

@Specialization(guards = "isIntegerFixnum", rewriteOn=UnexpectedResultException.class)
public int getIntegerFixnumInBounds(RubyArray array, int index, UndefinedPlaceholder undefined) throws UnexpectedResultException {
@Specialization(guards = "isIntegerFixnum", rewriteOn = UnexpectedResultException.class)
public int getIntegerFixnumInBounds(RubyArray array, int index) throws UnexpectedResultException {
int normalisedIndex = array.normaliseIndex(index);

if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -557,7 +569,7 @@ public int getIntegerFixnumInBounds(RubyArray array, int index, UndefinedPlaceho
}

@Specialization(contains = "getIntegerFixnumInBounds", guards = "isIntegerFixnum")
public Object getIntegerFixnum(RubyArray array, int index, UndefinedPlaceholder undefined) {
public Object getIntegerFixnum(RubyArray array, int index) {
int normalisedIndex = array.normaliseIndex(index);

if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -567,25 +579,8 @@ public Object getIntegerFixnum(RubyArray array, int index, UndefinedPlaceholder
}
}

@Specialization(guards = "isIntegerFixnum")
public Object getIntegerFixnum(RubyArray array, int index, int length) {
notDesignedForCompilation();

final int normalisedIndex = array.normaliseIndex(index);

if (normalisedIndex < 0 || normalisedIndex > array.getSize() || length < 0) {
return getContext().getCoreLibrary().getNilObject();
} else if (normalisedIndex == array.getSize()) {
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), null, 0);
} else {
final int end = Math.min(array.getSize(), normalisedIndex + length);

return new RubyArray(getContext().getCoreLibrary().getArrayClass(), Arrays.copyOfRange((int[]) array.getStore(), normalisedIndex, end), end - normalisedIndex);
}
}

@Specialization(guards = "isLongFixnum", rewriteOn=UnexpectedResultException.class)
public long getLongFixnumInBounds(RubyArray array, int index, UndefinedPlaceholder undefined) throws UnexpectedResultException {
@Specialization(guards = "isLongFixnum", rewriteOn = UnexpectedResultException.class)
public long getLongFixnumInBounds(RubyArray array, int index) throws UnexpectedResultException {
int normalisedIndex = array.normaliseIndex(index);

if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -596,8 +591,7 @@ public long getLongFixnumInBounds(RubyArray array, int index, UndefinedPlacehold
}

@Specialization(contains = "getLongFixnumInBounds", guards = "isLongFixnum")
public Object getLongFixnum(RubyArray array, int index, UndefinedPlaceholder undefined) {

public Object getLongFixnum(RubyArray array, int index) {
int normalisedIndex = array.normaliseIndex(index);

if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -607,8 +601,8 @@ public Object getLongFixnum(RubyArray array, int index, UndefinedPlaceholder und
}
}

@Specialization(guards = "isFloat", rewriteOn=UnexpectedResultException.class)
public double getFloatInBounds(RubyArray array, int index, UndefinedPlaceholder undefined) throws UnexpectedResultException {
@Specialization(guards = "isFloat", rewriteOn = UnexpectedResultException.class)
public double getFloatInBounds(RubyArray array, int index) throws UnexpectedResultException {
int normalisedIndex = array.normaliseIndex(index);

if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -619,7 +613,7 @@ public double getFloatInBounds(RubyArray array, int index, UndefinedPlaceholder
}

@Specialization(contains = "getFloatInBounds", guards = "isFloat")
public Object getFloat(RubyArray array, int index, UndefinedPlaceholder undefined) {
public Object getFloat(RubyArray array, int index) {
int normalisedIndex = array.normaliseIndex(index);

if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -630,7 +624,7 @@ public Object getFloat(RubyArray array, int index, UndefinedPlaceholder undefine
}

@Specialization(guards = "isObject")
public Object getObject(RubyArray array, int index, UndefinedPlaceholder undefined) {
public Object getObject(RubyArray array, int index) {
int normalisedIndex = array.normaliseIndex(index);

if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -640,6 +634,45 @@ public Object getObject(RubyArray array, int index, UndefinedPlaceholder undefin
}
}

}

@CoreMethod(names = "[]", required = 1, optional = 1, lowerFixnumParameters = { 0, 1 })
public abstract static class IndexNode extends ArrayCoreMethodNode {

@Child protected AtNode atNode;

public IndexNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
atNode = AtNodeFactory.create(context, sourceSection, new RubyNode[] { null, null });
}

public IndexNode(IndexNode prev) {
super(prev);
atNode = prev.atNode;
}

@Specialization
public Object get(RubyArray array, int index, UndefinedPlaceholder undefined) {
return atNode.executeAt(array, index);
}

@Specialization(guards = "isIntegerFixnum")
public Object getIntegerFixnum(RubyArray array, int index, int length) {

This comment has been minimized.

Copy link
@chrisseaton

chrisseaton Jan 12, 2015

Contributor

This could do with a better name. I was looking at it thinking it was the normal [n] case when in fact it's the [n, m] case isn't it?

This comment has been minimized.

Copy link
@eregon

eregon Jan 12, 2015

Author Member

Yes, agreed, let's name it sliceIntegerFixnum.
Or sliceInt or sliceIntArray?
Also, for the node name, maybe GetNode or SliceNode since it does more than just indexing?

This comment has been minimized.

Copy link
@chrisseaton

chrisseaton Jan 12, 2015

Contributor

Slice-whatever is fine. I'm not so sure about the second idea. I'd like to be able to tell at a glance what method this is in a stack trace, and for operators I think uniformity is good.

This comment has been minimized.

Copy link
@eregon

eregon Jan 12, 2015

Author Member

So "Index" is []?
RubySpec calls it element_reference, MRI calls it aref, HashNodes uses GetIndexNode, etc.
Behavior of Array#[] is like index + slice so I don't know what would be a good name based on semantics anyway.

notDesignedForCompilation();

final int normalisedIndex = array.normaliseIndex(index);

if (normalisedIndex < 0 || normalisedIndex > array.getSize() || length < 0) {
return getContext().getCoreLibrary().getNilObject();
} else if (normalisedIndex == array.getSize()) {
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), null, 0);
} else {
final int end = Math.min(array.getSize(), normalisedIndex + length);

return new RubyArray(getContext().getCoreLibrary().getArrayClass(), Arrays.copyOfRange((int[]) array.getStore(), normalisedIndex, end), end - normalisedIndex);
}
}

@Specialization(guards = "isObject")
public Object getObject(RubyArray array, int index, int length) {
notDesignedForCompilation();
1 change: 0 additions & 1 deletion spec/truffle/tags/core/array/at_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
fails:Array#at tries to convert the passed argument to an Integer using #to_int
fails:Array#at raises an ArgumentError when 2 or more arguments is passed

0 comments on commit 8c74bc3

Please sign in to comment.