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

Commits on Apr 15, 2015

  1. Copy the full SHA
    26c44c1 View commit details
  2. Copy the full SHA
    88b5751 View commit details
  3. Copy the full SHA
    3ffab94 View commit details
  4. Copy the full SHA
    01364ae View commit details
  5. Copy the full SHA
    f2d2fa8 View commit details
14 changes: 0 additions & 14 deletions spec/truffle/tags/core/module/const_defined_tags.txt

This file was deleted.

12 changes: 0 additions & 12 deletions spec/truffle/tags/core/module/define_method_tags.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
fails:Module#define_method when given an UnboundMethod passes the given arguments to the new method
fails:Module#define_method when given an UnboundMethod adds the new method to the methods list
fails:Module#define_method when given an UnboundMethod defining a method on a singleton class doesn't raise TypeError when calling the method
fails:Module#define_method defines the given method as an instance method with the given name in self
fails:Module#define_method calls #method_added after the method is added to the Module
fails:Module#define_method raises an ArgumentError when no block is given
fails:Module#define_method is private
fails:Module#define_method method body is an UnboundMethod allows methods defined on a different object
fails:Module#define_method when name is :initialize given an UnboundMethod sets the visibility to private when method is named :initialize
fails:Method#define_method when passed a Method object defines a method with the same #parameters as the original
fails:Method#define_method when passed an UnboundMethod object defines a method with the same #arity as the original
fails:Method#define_method when passed an UnboundMethod object defines a method with the same #parameters as the original
fails:Module#define_method allows an UnboundMethod from a module to be defined on a class
fails:Module#define_method allows an UnboundMethod from a parent class to be defined on a child class
fails:Module#define_method allows an UnboundMethod from a module to be defined on another unrelated module
1 change: 0 additions & 1 deletion spec/truffle/tags/core/module/included_modules_tags.txt

This file was deleted.

2 changes: 1 addition & 1 deletion tool/jt.rb
Original file line number Diff line number Diff line change
@@ -316,7 +316,7 @@ def tag_all(*args)

def untag(path, *args)
puts
puts "WARNING: untag is currently not very reliable - run `jt test #{path} #{args * ' '}` after and manually annotate any new failures"
puts "WARNING: untag is currently not very reliable - run `jt test #{[path,*args] * ' '}` after and manually annotate any new failures"
puts
mspec 'tag', '--del', 'fails', '--pass', path, *args
end
94 changes: 78 additions & 16 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ModuleNodes.java
Original file line number Diff line number Diff line change
@@ -816,7 +816,8 @@ public RubyArray constants(RubyModule module, boolean inherit) {
}

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

public ConstDefinedNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
@@ -826,29 +827,55 @@ public ConstDefinedNode(ConstDefinedNode prev) {
super(prev);
}

@Specialization
public boolean isConstDefined(RubyModule module, RubyString name, @SuppressWarnings("unused") UndefinedPlaceholder inherit) {
notDesignedForCompilation();
@CreateCast("name")
public RubyNode coerceToString(RubyNode name) {
return SymbolOrToStrNodeFactory.create(getContext(), getSourceSection(), name);
}

return ModuleOperations.lookupConstant(getContext(), LexicalScope.NONE, module, name.toString()) != null;
@Specialization
public boolean isConstDefined(RubyModule module, String name, @SuppressWarnings("unused") UndefinedPlaceholder inherit) {
return isConstDefined(module, name, true);
}

@Specialization
public boolean isConstDefined(RubyModule module, RubyString name, boolean inherit) {
public boolean isConstDefined(RubyModule module, String fullName, boolean inherit) {
notDesignedForCompilation();

if (inherit) {
return ModuleOperations.lookupConstant(getContext(), LexicalScope.NONE, module, name.toString()) != null;
} else {
return module.getConstants().containsKey(name.toString());
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;
}

@Specialization
public boolean isConstDefined(RubyModule module, RubySymbol name, @SuppressWarnings("unused") UndefinedPlaceholder inherit) {
notDesignedForCompilation();
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));
}

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

}
@@ -959,6 +986,12 @@ public RubyNode coerceToString(RubyNode name) {
return SymbolOrToStrNodeFactory.create(getContext(), getSourceSection(), name);
}

@Specialization
public RubySymbol defineMethod(RubyModule module, String name, UndefinedPlaceholder proc, UndefinedPlaceholder block) {
notDesignedForCompilation();
throw new RaiseException(getContext().getCoreLibrary().argumentError("needs either proc or block", this));
}

@Specialization
public RubySymbol defineMethod(RubyModule module, String name, UndefinedPlaceholder proc, RubyProc block) {
notDesignedForCompilation();
@@ -984,8 +1017,10 @@ public RubySymbol defineMethod(RubyModule module, String name, RubyMethod method
public RubySymbol defineMethod(VirtualFrame frame, RubyModule module, String name, RubyUnboundMethod method, UndefinedPlaceholder block) {
notDesignedForCompilation();

if (module instanceof RubyClass && !ModuleOperations.assignableTo((RubyClass) module, method.getOrigin())) {
ruby(frame, "raise TypeError, 'bind argument must be a subclass of " + method.getOrigin().getName() + "'");
RubyModule origin = method.getOrigin();
if (!ModuleOperations.canBindMethodTo(origin, module)) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeError("bind argument must be a subclass of " + origin.getName(), this));
}

// TODO CS 5-Apr-15 TypeError if the method came from a singleton
@@ -1190,6 +1225,33 @@ public RubyNilClass included(Object subclass) {

}

@CoreMethod(names = "included_modules")
public abstract static class IncludedModulesNode extends CoreMethodNode {

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

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

@Specialization
RubyArray includedModules(RubyModule module) {
notDesignedForCompilation();

final List<RubyModule> modules = new ArrayList<>();

for (RubyModule included : module.parentAncestors()) {
if (included.isOnlyAModule()) {
modules.add(included);
}
}

return RubyArray.fromObjects(getContext().getCoreLibrary().getArrayClass(), modules.toArray(new Object[modules.size()]));
}
}

@CoreMethod(names = "method_defined?", required = 1, optional = 1)
public abstract static class MethodDefinedNode extends CoreMethodNode {

Original file line number Diff line number Diff line change
@@ -76,14 +76,12 @@ private RubyClass metaClass(VirtualFrame frame, Object object) {
public RubyMethod bind(VirtualFrame frame, RubyUnboundMethod unboundMethod, Object object) {
notDesignedForCompilation();
RubyModule module = unboundMethod.getMethod().getDeclaringModule();
if (module instanceof RubyClass) {
if (!ModuleOperations.assignableTo(metaClass(frame, object), module)) {
CompilerDirectives.transferToInterpreter();
if (((RubyClass) module).isSingleton()) {
throw new RaiseException(getContext().getCoreLibrary().typeError("singleton method called for a different object", this));
} else {
throw new RaiseException(getContext().getCoreLibrary().typeError("bind argument must be an instance of " + module.getName(), this));
}
if (!ModuleOperations.canBindMethodTo(module, metaClass(frame, object))) {
CompilerDirectives.transferToInterpreter();
if (((RubyClass) module).isSingleton()) {
throw new RaiseException(getContext().getCoreLibrary().typeError("singleton method called for a different object", this));
} else {
throw new RaiseException(getContext().getCoreLibrary().typeError("bind argument must be an instance of " + module.getName(), this));
}
}

Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@

import com.oracle.truffle.api.CompilerAsserts;
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.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyModule;
@@ -39,6 +39,14 @@ public static boolean assignableTo(RubyClass thisClass, RubyModule otherClass) {
return includesModule(thisClass, otherClass);
}

public static boolean canBindMethodTo(RubyModule origin, RubyModule module) {
if (!(origin instanceof RubyClass)) {
return true;
} else {
return ((module instanceof RubyClass) && ModuleOperations.assignableTo((RubyClass) module, origin));
}
}

@TruffleBoundary
public static Map<String, RubyConstant> getAllConstants(RubyModule module) {
CompilerAsserts.neverPartOfCompilation();