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: c3a3f56b15f9
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f048d4f5987e
Choose a head ref
  • 7 commits
  • 15 files changed
  • 1 contributor

Commits on Mar 8, 2015

  1. [Truffle] Hash#delete

    chrisseaton committed Mar 8, 2015
    Copy the full SHA
    351d101 View commit details
  2. [Truffle] Hash#eql?

    chrisseaton committed Mar 8, 2015
    Copy the full SHA
    448dfc5 View commit details
  3. [Truffle] Hash#==

    chrisseaton committed Mar 8, 2015
    Copy the full SHA
    e09f9bf View commit details
  4. Copy the full SHA
    1f371b7 View commit details
  5. Copy the full SHA
    ba5f8a6 View commit details
  6. [Truffle] Range#cover?

    chrisseaton committed Mar 8, 2015
    Copy the full SHA
    e8cc0d8 View commit details
  7. [Truffle] Array#to_ary

    chrisseaton committed Mar 8, 2015
    Copy the full SHA
    f048d4f View commit details
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/array/to_ary_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/hash/delete_tags.txt

This file was deleted.

10 changes: 0 additions & 10 deletions spec/truffle/tags/core/hash/eql_tags.txt

This file was deleted.

12 changes: 0 additions & 12 deletions spec/truffle/tags/core/hash/equal_value_tags.txt

This file was deleted.

3 changes: 0 additions & 3 deletions spec/truffle/tags/core/hash/initialize_copy_tags.txt

This file was deleted.

2 changes: 0 additions & 2 deletions spec/truffle/tags/core/hash/initialize_tags.txt

This file was deleted.

24 changes: 0 additions & 24 deletions spec/truffle/tags/core/range/cover_tags.txt
Original file line number Diff line number Diff line change
@@ -1,25 +1 @@
fails:Range#cover? returns true if other is an element of self
fails:Range#cover? compares values using <=>
fails:Range#cover? raises an ArgumentError without exactly one argument
fails:Range#cover? returns true if argument is equal to the first value of the range
fails:Range#cover? returns true if argument is equal to the last value of the range
fails:Range#cover? returns true if argument is less than the last value of the range and greater than the first value
fails:Range#cover? returns true if argument is sole element in the range
fails:Range#cover? returns false if range is empty
fails:Range#cover? returns false if the range does not contain the argument
fails:Range#cover? uses the range element's <=> to make the comparison
fails:Range#cover? uses a continuous inclusion test
fails:Range#cover? on string elements returns true if other is matched by element.succ
fails:Range#cover? on string elements returns true if other is not matched by element.succ
fails:Range#cover? with weird succ when included end value returns false if other is less than first element
fails:Range#cover? with weird succ when included end value returns true if other is equal as first element
fails:Range#cover? with weird succ when included end value returns true if other is matched by element.succ
fails:Range#cover? with weird succ when included end value returns true if other is not matched by element.succ
fails:Range#cover? with weird succ when included end value returns true if other is equal as last element but not matched by element.succ
fails:Range#cover? with weird succ when included end value returns false if other is greater than last element but matched by element.succ
fails:Range#cover? with weird succ when excluded end value returns false if other is less than first element
fails:Range#cover? with weird succ when excluded end value returns true if other is equal as first element
fails:Range#cover? with weird succ when excluded end value returns true if other is matched by element.succ
fails:Range#cover? with weird succ when excluded end value returns true if other is not matched by element.succ
fails:Range#cover? with weird succ when excluded end value returns false if other is equal as last element but not matched by element.succ
fails:Range#cover? with weird succ when excluded end value returns false if other is greater than last element but matched by element.succ
3 changes: 3 additions & 0 deletions spec/truffle/tags/language/hash_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fails:Hash literal calls #to_hash to convert an '**obj' element
fails:Hash literal merges the containing Hash into the **obj before importing obj's items
fails:Hash literal merges multiple nested '**obj' in Hash literals
84 changes: 36 additions & 48 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/HashNodes.java
Original file line number Diff line number Diff line change
@@ -569,31 +569,38 @@ public Object defaultProc(RubyHash hash) {

}

@CoreMethod(names = "delete", required = 1, raiseIfFrozenSelf = true)
@CoreMethod(names = "delete", required = 1, needsBlock = true, raiseIfFrozenSelf = true)
public abstract static class DeleteNode extends HashCoreMethodNode {

@Child private CallDispatchHeadNode eqlNode;
@Child private FindEntryNode findEntryNode;
@Child private YieldDispatchHeadNode yieldNode;

public DeleteNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
eqlNode = DispatchHeadNodeFactory.createMethodCall(context, false, false, null);
findEntryNode = new FindEntryNode(context, sourceSection);
yieldNode = new YieldDispatchHeadNode(context);
}

public DeleteNode(DeleteNode prev) {
super(prev);
eqlNode = prev.eqlNode;
findEntryNode = prev.findEntryNode;
yieldNode = prev.yieldNode;
}

@Specialization(guards = "isNull")
public RubyNilClass deleteNull(RubyHash hash, Object key) {
return getContext().getCoreLibrary().getNilObject();
public Object deleteNull(VirtualFrame frame, RubyHash hash, Object key, Object block) {
if (block == UndefinedPlaceholder.INSTANCE) {
return getContext().getCoreLibrary().getNilObject();
} else {
return yieldNode.dispatch(frame, (RubyProc) block, key);
}
}

@Specialization(guards = {"!isNull", "!isBuckets", "!isCompareByIdentity(arguments[0])"})
public Object deletePackedArray(VirtualFrame frame, RubyHash hash, Object key) {
public Object deletePackedArray(VirtualFrame frame, RubyHash hash, Object key, Object block) {
final Object[] store = (Object[]) hash.getStore();
final int size = hash.getSize();

@@ -611,17 +618,25 @@ public Object deletePackedArray(VirtualFrame frame, RubyHash hash, Object key) {
}
}

return getContext().getCoreLibrary().getNilObject();
if (block == UndefinedPlaceholder.INSTANCE) {
return getContext().getCoreLibrary().getNilObject();
} else {
return yieldNode.dispatch(frame, (RubyProc) block, key);
}
}

@Specialization(guards = "isBuckets")
public Object delete(VirtualFrame frame, RubyHash hash, Object key) {
public Object delete(VirtualFrame frame, RubyHash hash, Object key, Object block) {
notDesignedForCompilation();

final HashSearchResult hashSearchResult = findEntryNode.search(frame, hash, key);

if (hashSearchResult.getEntry() == null) {
return getContext().getCoreLibrary().getNilObject();
if (block == UndefinedPlaceholder.INSTANCE) {
return getContext().getCoreLibrary().getNilObject();
} else {
return yieldNode.dispatch(frame, (RubyProc) block, key);
}
}

final Entry entry = hashSearchResult.getEntry();
@@ -750,7 +765,7 @@ public boolean emptyPackedArray(RubyHash hash) {

}

@CoreMethod(names = "initialize", needsBlock = true, optional = 1)
@CoreMethod(names = "initialize", needsBlock = true, optional = 1, raiseIfFrozenSelf = true)
public abstract static class InitializeNode extends HashCoreMethodNode {

public InitializeNode(RubyContext context, SourceSection sourceSection) {
@@ -762,26 +777,26 @@ public InitializeNode(InitializeNode prev) {
}

@Specialization
public RubyNilClass initialize(RubyHash hash, UndefinedPlaceholder defaultValue, UndefinedPlaceholder block) {
public RubyHash initialize(RubyHash hash, UndefinedPlaceholder defaultValue, UndefinedPlaceholder block) {
notDesignedForCompilation();
hash.setStore(null, 0, null, null);
hash.setDefaultBlock(null);
return getContext().getCoreLibrary().getNilObject();
return hash;
}

@Specialization
public RubyNilClass initialize(RubyHash hash, UndefinedPlaceholder defaultValue, RubyProc block) {
public RubyHash initialize(RubyHash hash, UndefinedPlaceholder defaultValue, RubyProc block) {
notDesignedForCompilation();
hash.setStore(null, 0, null, null);
hash.setDefaultBlock(block);
return getContext().getCoreLibrary().getNilObject();
return hash;
}

@Specialization
public RubyNilClass initialize(RubyHash hash, Object defaultValue, UndefinedPlaceholder block) {
public RubyHash initialize(RubyHash hash, Object defaultValue, UndefinedPlaceholder block) {
notDesignedForCompilation();
hash.setDefaultValue(defaultValue);
return getContext().getCoreLibrary().getNilObject();
return hash;
}

@Specialization(guards = "!isUndefinedPlaceholder(arguments[1])")
@@ -792,7 +807,8 @@ public Object initialize(RubyHash hash, Object defaultValue, RubyProc block) {

}

@CoreMethod(names = "initialize_copy", visibility = Visibility.PRIVATE, required = 1)
// TODO CS 8-Mar-15 visibility = Visibility.PRIVATE
@CoreMethod(names = {"initialize_copy", "replace"}, required = 1, raiseIfFrozenSelf = true)
public abstract static class InitializeCopyNode extends HashCoreMethodNode {

public InitializeCopyNode(RubyContext context, SourceSection sourceSection) {
@@ -847,6 +863,11 @@ public RubyHash dupBuckets(RubyHash self, RubyHash from) {

return self;
}

@Specialization(guards = "!isRubyHash(arguments[1])")
public Object dupBuckets(VirtualFrame frame, RubyHash self, Object other) {
return ruby(frame, "replace(Rubinius::Type.coerce_to other, Hash, :to_hash)", "other", other);
}

private void copyOther(RubyHash self, RubyHash from) {
self.setDefaultBlock(from.getDefaultBlock());
@@ -1337,39 +1358,6 @@ public RubyHash rehashBuckets(RubyHash hash) {

}

@CoreMethod(names = "replace", required = 1)
public abstract static class ReplaceNode extends HashCoreMethodNode {

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

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

@Specialization
public RubyHash replace(VirtualFrame frame, RubyHash hash, RubyHash other) {
notDesignedForCompilation();

ruby(frame, "Rubinius.check_frozen");

HashOperations.verySlowSetKeyValues(hash, HashOperations.verySlowToKeyValues(other), false);
hash.setDefaultBlock(other.getDefaultBlock());
hash.setDefaultValue(other.getDefaultValue());

return hash;
}

@Specialization(guards = "!isRubyHash(arguments[1])")
public Object replace(VirtualFrame frame, RubyHash hash, Object other) {
notDesignedForCompilation();

return ruby(frame, "replace(Rubinius::Type.coerce_to other, Hash, :to_hash)", "other", other);
}

}

@RubiniusOnly
@CoreMethod(names = "_default_value")
public abstract static class DefaultValueNode extends HashCoreMethodNode {
Original file line number Diff line number Diff line change
@@ -163,30 +163,65 @@ public VMObjectEqualPrimitiveNode(VMObjectEqualPrimitiveNode prev) {
}

@Specialization
public Object vmObjectEqual(boolean a, boolean b) {
public boolean vmObjectEqual(boolean a, boolean b) {
return a == b;
}

@Specialization(guards = "!isBoolean(arguments[1])")
public boolean vmObjectEqual(boolean a, Object b) {
return false;
}

@Specialization
public boolean vmObjectEqual(int a, int b) {
return a == b;
}

@Specialization
public boolean vmObjectEqual(int a, long b) {
return a == b;
}

@Specialization(guards = {"!isInteger(arguments[1])", "!isLong(arguments[1])"})
public boolean vmObjectEqual(int a, Object b) {
return false;
}

@Specialization
public Object vmObjectEqual(int a, int b) {
public boolean vmObjectEqual(long a, int b) {
return a == b;
}

@Specialization
public Object vmObjectEqual(long a, long b) {
public boolean vmObjectEqual(long a, long b) {
return a == b;
}

@Specialization(guards = {"!isInteger(arguments[1])", "!isLong(arguments[1])"})
public boolean vmObjectEqual(long a, Object b) {
return false;
}

@Specialization
public Object vmObjectEqual(double a, double b) {
public boolean vmObjectEqual(double a, double b) {
return a == b;
}

@Specialization(guards = "!isDouble(arguments[1])")
public boolean vmObjectEqual(double a, Object b) {
return false;
}

@Specialization
public Object vmObjectEqual(RubyBasicObject a, RubyBasicObject b) {
public boolean vmObjectEqual(RubyBasicObject a, RubyBasicObject b) {
return a == b;
}

@Specialization(guards = "!isRubyBasicObject(arguments[1])")
public boolean vmObjectEqual(RubyBasicObject a, Object b) {
return false;
}

}

@RubiniusPrimitive(name = "vm_object_kind_of", needsSelf = false)
Original file line number Diff line number Diff line change
@@ -1638,6 +1638,28 @@ public RubyNode visitInstVarNode(org.jruby.ast.InstVarNode node) {
}
}

if (sourceSection.getSource().getPath().equals("core:/core/rubinius/common/range.rb")) {
if (nameWithoutSigil.equals("@begin")) {
return new RubyCallNode(context, sourceSection,
"begin",
new SelfNode(context, sourceSection),
null,
false);
} else if (nameWithoutSigil.equals("@end")) {
return new RubyCallNode(context, sourceSection,
"end",
new SelfNode(context, sourceSection),
null,
false);
} else if (nameWithoutSigil.equals("@excl")) {
return new RubyCallNode(context, sourceSection,
"exclude_end?",
new SelfNode(context, sourceSection),
null,
false);
}
}

final RubyNode receiver = new SelfNode(context, sourceSection);

return new ReadInstanceVariableNode(context, sourceSection, nameWithoutSigil, receiver, false);
1 change: 1 addition & 0 deletions truffle/src/main/ruby/core.rb
Original file line number Diff line number Diff line change
@@ -62,6 +62,7 @@
require_relative 'core/rubinius/common/object_space'
require_relative 'core/rubinius/common/proc'
require_relative 'core/rubinius/common/string'
require_relative 'core/rubinius/common/range'
require_relative 'core/rubinius/common/struct'
require_relative 'core/rubinius/common/symbol'
require_relative 'core/rubinius/common/regexp'
4 changes: 4 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/array.rb
Original file line number Diff line number Diff line change
@@ -415,4 +415,8 @@ def fetch(idx, default=undefined)
at(idx)
end

def to_ary
self
end

end
55 changes: 55 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/hash.rb
Original file line number Diff line number Diff line change
@@ -313,4 +313,59 @@ def value?(value)

alias_method :has_value?, :value?

def eql?(other)
# Just like ==, but uses eql? to compare values.
return true if self.equal? other
unless other.kind_of? Hash
return false unless other.respond_to? :to_hash
return other.eql?(self)
end

return false unless other.size == size

Thread.detect_recursion self, other do
each_item do |item|
other_item = other.find_item(item.key)

# Other doesn't even have this key
return false unless other_item

# Order of the comparison matters! We must compare our value with
# the other Hash's value and not the other way around.
unless Rubinius::Type::object_equal(item.value, other_item.value) or
item.value.eql?(other_item.value)
return false
end
end
end
true
end

def ==(other)
return true if self.equal? other
unless other.kind_of? Hash
return false unless other.respond_to? :to_hash
return other == self
end

return false unless other.size == size

Thread.detect_recursion self, other do
each_item do |item|
other_item = other.find_item(item.key)

# Other doesn't even have this key
return false unless other_item

# Order of the comparison matters! We must compare our value with
# the other Hash's value and not the other way around.
unless Rubinius::Type::object_equal(item.value, other_item.value) or
item.value == other_item.value
return false
end
end
end
true
end

end
50 changes: 50 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/range.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright (c) 2007-2014, Evan Phoenix and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Rubinius nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Only part of Rubinius' range.rb

class Range

def cover?(value)
# MRI uses <=> to compare, so must we.

beg_compare = (@begin <=> value)
return false unless beg_compare

if Comparable.compare_int(beg_compare) <= 0
end_compare = (value <=> @end)

if @excl
return true if Comparable.compare_int(end_compare) < 0
else
return true if Comparable.compare_int(end_compare) <= 0
end
end

false
end

end