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

Commits on Apr 17, 2015

  1. Copy the full SHA
    ba39437 View commit details
  2. Copy the full SHA
    f27bb12 View commit details
  3. Copy the full SHA
    8bcf1a9 View commit details
  4. Copy the full SHA
    290ee99 View commit details
  5. Copy the full SHA
    90591e8 View commit details
9 changes: 0 additions & 9 deletions spec/truffle/tags/core/module/const_get_tags.txt

This file was deleted.

3 changes: 0 additions & 3 deletions spec/truffle/tags/core/module/instance_method_tags.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
fails:Module#private_instance_methods default list should be the same as passing true as an argument
fails:Module#private_instance_methods when passed true returns a unique list for a class including a module
fails:Module#private_instance_methods when passed true returns a unique list for a subclass
10 changes: 0 additions & 10 deletions spec/truffle/tags/core/module/public_instance_method_tags.txt

This file was deleted.

2 changes: 0 additions & 2 deletions spec/truffle/tags/core/unboundmethod/equal_value_tags.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
fails:UnboundMethod#== returns true if objects refer to the same method
fails:UnboundMethod#== returns true if either is an alias for the other
fails:UnboundMethod#== returns true if both are aliases for a third method
fails:UnboundMethod#== returns true if same method is extracted from the same subclass
Original file line number Diff line number Diff line change
@@ -1242,9 +1242,7 @@ private RubyMethod method(Object object, String name) {
if (method == null) {
throw new RaiseException(
getContext().getCoreLibrary().nameErrorUndefinedMethod(
name,
getContext().getCoreLibrary().getLogicalClass(object).getName(),
this));
name, getContext().getCoreLibrary().getLogicalClass(object), this));
}

return new RubyMethod(getContext().getCoreLibrary().getMethodClass(), object, method);
166 changes: 104 additions & 62 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ModuleNodes.java
Original file line number Diff line number Diff line change
@@ -560,7 +560,7 @@ public RubyNilClass autoload(RubyModule module, RubyString name, RubyString file
private RubyNilClass autoload(RubyModule module, String name, RubyString filename) {
if (invalidConstantName.profile(!IdUtil.isValidConstantName19(name))) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameError(String.format("autoload must be constant name: %s", name), this));
throw new RaiseException(getContext().getCoreLibrary().nameError(String.format("autoload must be constant name: %s", name), name, this));
}

if (emptyFilename.profile(emptyNode.empty(filename))) {
@@ -865,48 +865,14 @@ public boolean isConstDefined(RubyModule module, String name, UndefinedPlacehold
@Specialization
public boolean isConstDefined(RubyModule module, String fullName, boolean inherit) {
notDesignedForCompilation();

int start = 0, next;
if (fullName.startsWith("::")) {
module = getContext().getCoreLibrary().getObjectClass();
start += 2;
}

while ((next = fullName.indexOf("::", start)) != -1) {
String segment = fullName.substring(start, next);
RubyConstant constant = lookup(module, segment, inherit);
if (constant == null) {
return false;
} else if (constant.getValue() instanceof RubyModule) {
module = (RubyModule) constant.getValue();
} else {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeError(fullName.substring(0, next) + " does not refer to class/module", this));
}
start = next + 2;
}

String lastSegment = fullName.substring(start);
return lookup(module, lastSegment, inherit) != null;
}

private RubyConstant lookup(RubyModule module, String name, boolean inherit) {
if (!IdUtil.isValidConstantName19(name)) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameError(String.format("wrong constant name %s", name), this));
}

if (inherit) {
return ModuleOperations.lookupConstant(getContext(), LexicalScope.NONE, module, name);
} else {
return module.getConstants().get(name);
}
return ModuleOperations.lookupScopedConstant(getContext(), module, fullName, inherit, this) != null;
}

}

@CoreMethod(names = "const_get", required = 1)
public abstract static class ConstGetNode extends CoreMethodNode {
@CoreMethod(names = "const_get", required = 1, optional = 1)
@NodeChildren({ @NodeChild("module"), @NodeChild("name"), @NodeChild("inherit") })
public abstract static class ConstGetNode extends RubyNode {

@Child private DispatchHeadNode dispatch;

@@ -920,29 +886,62 @@ public ConstGetNode(ConstGetNode prev) {
dispatch = prev.dispatch;
}

@Specialization
public Object getConstant(VirtualFrame frame, RubyModule module, RubyString name) {
@CreateCast("name")
public RubyNode coerceToString(RubyNode name) {
return SymbolOrToStrNodeFactory.create(getContext(), getSourceSection(), name);
}

@Specialization(guards = "!isScoped(name)")
public Object getConstant(VirtualFrame frame, RubyModule module, String name, UndefinedPlaceholder inherit) {
return getConstant(frame, module, name, true);
}

@Specialization(guards = "isScoped(name)")
public Object getConstantScoped(VirtualFrame frame, RubyModule module, String name, UndefinedPlaceholder inherit) {
return getConstantScoped(frame, module, name, true);
}

@Specialization(guards = { "isTrue(inherit)", "!isScoped(name)" })
public Object getConstant(VirtualFrame frame, RubyModule module, String name, boolean inherit) {
return dispatch.dispatch(frame, module, name, null, new Object[] {});
}

@Specialization(guards = { "!isTrue(inherit)", "!isScoped(name)" })
public Object getConstantNoInherit(VirtualFrame frame, RubyModule module, String name, boolean inherit) {
notDesignedForCompilation();

return dispatch.dispatch(
frame,
module,
name,
null,
new Object[]{});
RubyConstant constant = module.getConstants().get(name);
if (constant == null) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorUninitializedConstant(module, name, this));
} else {
return constant.getValue();
}
}

@Specialization
public Object getConstant(VirtualFrame frame, RubyModule module, RubySymbol name) {
@Specialization(guards = "isScoped(name)")
public Object getConstantScoped(VirtualFrame frame, RubyModule module, String fullName, boolean inherit) {
notDesignedForCompilation();

return dispatch.dispatch(
frame,
module,
name,
null,
new Object[]{});
Object fullNameObject = RubyArguments.getUserArgument(frame.getArguments(), 0);
if (fullNameObject instanceof RubySymbol && !IdUtil.isValidConstantName19(fullName)) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameError(String.format("wrong constant name %s", fullName), fullName, this));
}

RubyConstant constant = ModuleOperations.lookupScopedConstant(getContext(), module, fullName, inherit, this);
if (constant == null) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorUninitializedConstant(module, fullName, this));
} else {
return constant.getValue();
}
}

boolean isScoped(String name) {
return name.contains("::");
}

}

@CoreMethod(names = "const_missing", required = 1)
@@ -985,7 +984,7 @@ public Object setConstant(RubyModule module, String name, Object value) {
notDesignedForCompilation();

if (!IdUtil.isValidConstantName19(name)) {
throw new RaiseException(getContext().getCoreLibrary().nameError(String.format("wrong constant name %s", name), this));
throw new RaiseException(getContext().getCoreLibrary().nameError(String.format("wrong constant name %s", name), name, this));
}

module.setConstant(this, name, value);
@@ -1632,6 +1631,43 @@ public boolean filter(InternalMethod method) {
}
}

@CoreMethod(names = "public_instance_method", required = 1)
@NodeChildren({ @NodeChild("module"), @NodeChild("name") })
public abstract static class PublicInstanceMethodNode extends RubyNode {

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

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

@CreateCast("name")
public RubyNode coerceToString(RubyNode name) {
return SymbolOrToStrNodeFactory.create(getContext(), getSourceSection(), name);
}

@Specialization
public RubyUnboundMethod publicInstanceMethod(RubyModule module, String name) {
notDesignedForCompilation();

// TODO(CS, 11-Jan-15) cache this lookup
final InternalMethod method = ModuleOperations.lookupMethod(module, name);

if (method == null || method.isUndefined()) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorUndefinedMethod(name, module, this));
} else if (method.getVisibility() != Visibility.PUBLIC) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorPrivateMethod(name, module, this));
}

return new RubyUnboundMethod(getContext().getCoreLibrary().getUnboundMethodClass(), module, method);
}

}

@CoreMethod(names = "public_instance_methods", optional = 1)
public abstract static class PublicInstanceMethodsNode extends CoreMethodNode {

@@ -1734,7 +1770,8 @@ public RubyArray instanceMethods(RubyModule module, boolean includeAncestors) {
}

@CoreMethod(names = "instance_method", required = 1)
public abstract static class InstanceMethodNode extends CoreMethodNode {
@NodeChildren({ @NodeChild("module"), @NodeChild("name") })
public abstract static class InstanceMethodNode extends RubyNode {

public InstanceMethodNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
@@ -1744,16 +1781,21 @@ public InstanceMethodNode(InstanceMethodNode prev) {
super(prev);
}

@CreateCast("name")
public RubyNode coerceToString(RubyNode name) {
return SymbolOrToStrNodeFactory.create(getContext(), getSourceSection(), name);
}

@Specialization
public RubyUnboundMethod instanceMethod(RubyModule module, RubySymbol name) {
public RubyUnboundMethod instanceMethod(RubyModule module, String name) {
notDesignedForCompilation();

// TODO(CS, 11-Jan-15) cache this lookup
final InternalMethod method = ModuleOperations.lookupMethod(module, name);

final InternalMethod method = ModuleOperations.lookupMethod(module, name.toString());

if (method == null) {
throw new UnsupportedOperationException();
if (method == null || method.isUndefined()) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorUndefinedMethod(name, module, this));
}

return new RubyUnboundMethod(getContext().getCoreLibrary().getUnboundMethodClass(), module, method);
Original file line number Diff line number Diff line change
@@ -32,6 +32,29 @@
@CoreClass(name = "UnboundMethod")
public abstract class UnboundMethodNodes {

@CoreMethod(names = "==", required = 1)
public abstract static class EqualNode extends CoreMethodNode {

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

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

@Specialization
boolean equal(RubyUnboundMethod self, RubyUnboundMethod other) {
return self.getMethod() == other.getMethod() && self.getOrigin() == other.getOrigin();
}

@Specialization(guards = "!isRubyUnboundMethod(arguments[1])")
boolean equal(RubyUnboundMethod self, Object other) {
return false;
}

}

@CoreMethod(names = "arity")
public abstract static class ArityNode extends CoreMethodNode {

Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ private void lookup(VirtualFrame frame, boolean checkIfDefined) {
return;
}
// TODO: should add " for #{receiver.inspect}" in error message
throw new RaiseException(getContext().getCoreLibrary().noMethodError(String.format("super: no superclass method `%s'", name), this));
throw new RaiseException(getContext().getCoreLibrary().noMethodError(String.format("super: no superclass method `%s'", name), name, this));
}

unmodifiedAssumption = declaringModule.getUnmodifiedAssumption();
Original file line number Diff line number Diff line change
@@ -10,13 +10,16 @@
package org.jruby.truffle.runtime;

import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.nodes.Node;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyModule;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.util.IdUtil;

import java.util.HashMap;
import java.util.Map;
@@ -137,6 +140,46 @@ public static RubyConstant lookupConstant(RubyContext context, LexicalScope lexi
return null;
}

public static RubyConstant lookupScopedConstant(RubyContext context, RubyModule module, String fullName, boolean inherit, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();

int start = 0, next;
if (fullName.startsWith("::")) {
module = context.getCoreLibrary().getObjectClass();
start += 2;
}

while ((next = fullName.indexOf("::", start)) != -1) {
String segment = fullName.substring(start, next);
RubyConstant constant = lookupConstantWithInherit(context, module, segment, inherit, currentNode);
if (constant == null) {
return null;
} else if (constant.getValue() instanceof RubyModule) {
module = (RubyModule) constant.getValue();
} else {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(context.getCoreLibrary().typeError(fullName.substring(0, next) + " does not refer to class/module", currentNode));
}
start = next + 2;
}

String lastSegment = fullName.substring(start);
return lookupConstantWithInherit(context, module, lastSegment, inherit, currentNode);
}

private static RubyConstant lookupConstantWithInherit(RubyContext context, RubyModule module, String name, boolean inherit, Node currentNode) {
if (!IdUtil.isValidConstantName19(name)) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(context.getCoreLibrary().nameError(String.format("wrong constant name %s", name), name, currentNode));
}

if (inherit) {
return ModuleOperations.lookupConstant(context, LexicalScope.NONE, module, name);
} else {
return module.getConstants().get(name);
}
}

@TruffleBoundary
public static Map<String, InternalMethod> getAllMethods(RubyModule module) {
CompilerAsserts.neverPartOfCompilation();
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@

import jnr.constants.platform.Errno;
import jnr.posix.FileStat;

import org.jcodings.Encoding;
import org.jcodings.EncodingDB;
import org.jcodings.transcode.EConvFlags;
@@ -844,54 +845,63 @@ public RubyException typeErrorCantCoerce(Object from, String to, Node currentNod
return typeError(String.format("%s can't be coerced into %s", from, to), currentNode);
}

public RubyException nameError(String message, Node currentNode) {
public RubyException nameError(String message, String name, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(nameErrorClass, context.makeString(message), RubyCallStack.getBacktrace(currentNode));
RubyException nameError = new RubyException(nameErrorClass, context.makeString(message), RubyCallStack.getBacktrace(currentNode));
nameError.getOperations().setInstanceVariable(nameError, "@name", context.getSymbolTable().getSymbol(name));
return nameError;
}

public RubyException nameErrorConstantNotDefined(RubyModule module, String name, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return nameError(String.format("constant %s::%s not defined", module.getName(), name), currentNode);
return nameError(String.format("constant %s::%s not defined", module.getName(), name), name, currentNode);
}

public RubyException nameErrorUninitializedConstant(RubyModule module, String name, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return nameError(String.format("uninitialized constant %s::%s", module.getName(), name), currentNode);
return nameError(String.format("uninitialized constant %s::%s", module.getName(), name), name, currentNode);
}

public RubyException nameErrorPrivateConstant(RubyModule module, String name, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return nameError(String.format("private constant %s::%s referenced", module.getName(), name), currentNode);
return nameError(String.format("private constant %s::%s referenced", module.getName(), name), name, currentNode);
}

public RubyException nameErrorInstanceNameNotAllowable(String name, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return nameError(String.format("`%s' is not allowable as an instance variable name", name), currentNode);
return nameError(String.format("`%s' is not allowable as an instance variable name", name), name, currentNode);
}

public RubyException nameErrorReadOnly(String name, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return nameError(String.format("%s is a read-only variable", name), currentNode);
return nameError(String.format("%s is a read-only variable", name), name, currentNode);
}

public RubyException nameErrorUndefinedLocalVariableOrMethod(String name, String object, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return nameError(String.format("undefined local variable or method `%s' for %s", name, object), currentNode);
return nameError(String.format("undefined local variable or method `%s' for %s", name, object), name, currentNode);
}

public RubyException nameErrorUndefinedMethod(String name, RubyModule module, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return nameError(String.format("undefined method `%s' for %s", name, module.getName()), name, currentNode);
}

public RubyException nameErrorUndefinedMethod(String name, String object, Node currentNode) {
public RubyException nameErrorPrivateMethod(String name, RubyModule module, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return nameError(String.format("undefined method `%s' for %s", name, object), currentNode);
return nameError(String.format("method `%s' for %s is private", name, module.getName()), name, currentNode);
}

public RubyException noMethodError(String message, Node currentNode) {
public RubyException noMethodError(String message, String name, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(context.getCoreLibrary().getNoMethodErrorClass(), context.makeString(message), RubyCallStack.getBacktrace(currentNode));
RubyException noMethodError = new RubyException(context.getCoreLibrary().getNoMethodErrorClass(), context.makeString(message), RubyCallStack.getBacktrace(currentNode));
noMethodError.getOperations().setInstanceVariable(noMethodError, "@name", context.getSymbolTable().getSymbol(name));
return noMethodError;
}

public RubyException noMethodErrorOnModule(String name, RubyModule module, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return noMethodError(String.format("undefined method `%s' for %s", name, module.getName()), currentNode);
return noMethodError(String.format("undefined method `%s' for %s", name, module.getName()), name, currentNode);
}

public RubyException noMethodErrorOnReceiver(String name, Object receiver, Node currentNode) {
@@ -901,12 +911,12 @@ public RubyException noMethodErrorOnReceiver(String name, Object receiver, Node
if (receiver instanceof RubyModule) {
repr = ((RubyModule) receiver).getName() + ":" + repr;
}
return noMethodError(String.format("undefined method `%s' for %s", name, repr), currentNode);
return noMethodError(String.format("undefined method `%s' for %s", name, repr), name, currentNode);
}

public RubyException privateMethodError(String name, RubyModule module, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return noMethodError(String.format("private method `%s' called for %s", name, module.toString()), currentNode);
return noMethodError(String.format("private method `%s' called for %s", name, module.toString()), name, currentNode);
}

public RubyException loadError(String message, Node currentNode) {
9 changes: 9 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/exception.rb
Original file line number Diff line number Diff line change
@@ -67,6 +67,15 @@ def exception(message=nil)

end

class NameError < StandardError
attr_reader :name

def initialize(*args)
super(args.shift)
@name = args.shift
end
end

class NoMethodError < NameError
attr_reader :name
attr_reader :args