Skip to content

Commit

Permalink
Showing 9 changed files with 134 additions and 19 deletions.
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/exception/no_method_error_tags.txt

This file was deleted.

3 changes: 3 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/Layouts.java
Original file line number Diff line number Diff line change
@@ -28,6 +28,8 @@
import org.jruby.truffle.core.exception.ExceptionLayoutImpl;
import org.jruby.truffle.core.exception.NameErrorLayout;
import org.jruby.truffle.core.exception.NameErrorLayoutImpl;
import org.jruby.truffle.core.exception.NoMethodErrorLayout;
import org.jruby.truffle.core.exception.NoMethodErrorLayoutImpl;
import org.jruby.truffle.core.exception.SystemCallErrorLayout;
import org.jruby.truffle.core.exception.SystemCallErrorLayoutImpl;
import org.jruby.truffle.core.fiber.FiberLayout;
@@ -124,6 +126,7 @@ public abstract class Layouts {
public static final ModuleLayout MODULE = ModuleLayoutImpl.INSTANCE;
public static final MutexLayout MUTEX = MutexLayoutImpl.INSTANCE;
public static final NameErrorLayout NAME_ERROR = NameErrorLayoutImpl.INSTANCE;
public static final NoMethodErrorLayout NO_METHOD_ERROR = NoMethodErrorLayoutImpl.INSTANCE;
public static final ObjectRangeLayout OBJECT_RANGE = ObjectRangeLayoutImpl.INSTANCE;
public static final PointerLayout POINTER = PointerLayoutImpl.INSTANCE;
public static final ProcLayout PROC = ProcLayoutImpl.INSTANCE;
4 changes: 4 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/core/CoreLibrary.java
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@
import org.jruby.truffle.core.encoding.EncodingNodesFactory;
import org.jruby.truffle.core.exception.ExceptionNodesFactory;
import org.jruby.truffle.core.exception.NameErrorNodesFactory;
import org.jruby.truffle.core.exception.NoMethodErrorNodesFactory;
import org.jruby.truffle.core.exception.SystemCallErrorNodesFactory;
import org.jruby.truffle.core.fiber.FiberNodesFactory;
import org.jruby.truffle.core.hash.HashNodesFactory;
@@ -397,6 +398,7 @@ public CoreLibrary(RubyContext context) {
nameErrorClass = defineClass(standardErrorClass, "NameError");
Layouts.CLASS.setInstanceFactoryUnsafe(nameErrorClass, Layouts.NAME_ERROR.createNameErrorShape(nameErrorClass, nameErrorClass));
noMethodErrorClass = defineClass(nameErrorClass, "NoMethodError");
Layouts.CLASS.setInstanceFactoryUnsafe(noMethodErrorClass, Layouts.NO_METHOD_ERROR.createNoMethodErrorShape(noMethodErrorClass, noMethodErrorClass));

// StandardError > SystemCallError
systemCallErrorClass = defineClass(standardErrorClass, "SystemCallError");
@@ -679,6 +681,7 @@ public void addPrimitives() {
primitiveManager.addPrimitiveNodes(IOBufferPrimitiveNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(ExceptionNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(NameErrorNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(NoMethodErrorNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(SystemCallErrorNodesFactory.getFactories());
return null;
}, () -> {
@@ -709,6 +712,7 @@ public void addCoreMethods() {
coreMethodNodeManager.addCoreMethodNodes(ConditionVariableNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(ExceptionNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(NameErrorNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(NoMethodErrorNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(SystemCallErrorNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(FalseClassNodesFactory.getFactories());
return null;
Original file line number Diff line number Diff line change
@@ -280,13 +280,13 @@ private DynamicObject buildMethodMissingException(Object self, DynamicObject nam
final String name = nameObject.toString();

if (lastCallWasSuper()) {
return coreExceptions().noSuperMethodError(name, self, this);
return coreExceptions().noSuperMethodError(name, self, args, this);
} else if (lastCallWasCallingPrivateMethod(self, name)) {
return coreExceptions().privateMethodError(name, self, this);
return coreExceptions().privateMethodError(name, self, args, this);
} else if (lastCallWasVCall()) {
return coreExceptions().nameErrorUndefinedLocalVariableOrMethod(name, self, this);
} else {
return coreExceptions().noMethodErrorOnReceiver(name, self, this);
return coreExceptions().noMethodErrorOnReceiver(name, self, args, this);
}
}

Original file line number Diff line number Diff line change
@@ -25,6 +25,8 @@
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.RubyGuards;

import static org.jruby.truffle.core.array.ArrayHelpers.createArray;

public class CoreExceptions {

private final RubyContext context;
@@ -502,9 +504,10 @@ public DynamicObject nameError(String message, Object receiver, String name, Nod
// NoMethodError

@TruffleBoundary
public DynamicObject noMethodError(String message, Object receiver, String name, Node currentNode) {
public DynamicObject noMethodError(String message, Object receiver, String name, Object[] args, Node currentNode) {
final DynamicObject messageString = StringOperations.createString(context, StringOperations.encodeRope(message, UTF8Encoding.INSTANCE));
DynamicObject noMethodError = ExceptionOperations.createNameError(context.getCoreLibrary().getNoMethodErrorClass(), messageString, context.getCallStack().getBacktrace(currentNode), receiver, context.getSymbolTable().getSymbol(name));
final DynamicObject argsArray = createArray(context, args, args.length);
final DynamicObject noMethodError = ExceptionOperations.createNoMethodError(context.getCoreLibrary().getNoMethodErrorClass(), messageString, context.getCallStack().getBacktrace(currentNode), receiver, context.getSymbolTable().getSymbol(name), argsArray);
return noMethodError;
}

@@ -518,26 +521,26 @@ public DynamicObject noSuperMethodOutsideMethodError(Node currentNode) {
}

@TruffleBoundary
public DynamicObject noSuperMethodError(String name, Object self, Node currentNode) {
return noMethodError(String.format("super: no superclass method `%s'", name), self, name, currentNode);
public DynamicObject noSuperMethodError(String name, Object self, Object[] args, Node currentNode) {
return noMethodError(String.format("super: no superclass method `%s'", name), self, name, args, currentNode);
}

@TruffleBoundary
public DynamicObject noMethodErrorOnReceiver(String name, Object receiver, Node currentNode) {
public DynamicObject noMethodErrorOnReceiver(String name, Object receiver, Object[] args, Node currentNode) {
final DynamicObject logicalClass = context.getCoreLibrary().getLogicalClass(receiver);
final String moduleName = Layouts.MODULE.getFields(logicalClass).getName();

// e.g. BasicObject does not have inspect
final boolean hasInspect = ModuleOperations.lookupMethod(logicalClass, "inspect", Visibility.PUBLIC) != null;
final Object stringRepresentation = hasInspect ? context.send(receiver, "inspect", null) : context.getCoreLibrary().getNilObject();

return noMethodError(String.format("undefined method `%s' for %s:%s", name, stringRepresentation, moduleName), receiver, name, currentNode);
return noMethodError(String.format("undefined method `%s' for %s:%s", name, stringRepresentation, moduleName), receiver, name, args, currentNode);
}

@TruffleBoundary
public DynamicObject privateMethodError(String name, Object self, Node currentNode) {
public DynamicObject privateMethodError(String name, Object self, Object[] args, Node currentNode) {
String className = Layouts.MODULE.getFields(context.getCoreLibrary().getLogicalClass(self)).getName();
return noMethodError(String.format("private method `%s' called for %s", name, className), self, name, currentNode);
return noMethodError(String.format("private method `%s' called for %s", name, className), self, name, args, currentNode);
}

// LoadError
Original file line number Diff line number Diff line change
@@ -54,4 +54,8 @@ public static DynamicObject createNameError(DynamicObject rubyClass, Object mess
return Layouts.NAME_ERROR.createNameError(Layouts.CLASS.getInstanceFactory(rubyClass), message, backtrace, receiver, name);
}

public static DynamicObject createNoMethodError(DynamicObject rubyClass, Object message, Backtrace backtrace, Object receiver, Object name, DynamicObject args) {
return Layouts.NO_METHOD_ERROR.createNoMethodError(Layouts.CLASS.getInstanceFactory(rubyClass), message, backtrace, receiver, name, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2016 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.core.exception;

import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.DynamicObjectFactory;
import com.oracle.truffle.api.object.dsl.Layout;
import com.oracle.truffle.api.object.dsl.Nullable;
import org.jruby.truffle.language.backtrace.Backtrace;

@Layout
public interface NoMethodErrorLayout extends NameErrorLayout {

DynamicObjectFactory createNoMethodErrorShape(
DynamicObject logicalClass,
DynamicObject metaClass);

DynamicObject createNoMethodError(
DynamicObjectFactory factory,
Object message,
@Nullable Backtrace backtrace,
@Nullable Object receiver,
Object name,
Object args);

Object getArgs(DynamicObject object);
void setArgs(DynamicObject object, Object value);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2016 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.core.exception;

import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.builtins.CoreClass;
import org.jruby.truffle.builtins.CoreMethod;
import org.jruby.truffle.builtins.CoreMethodArrayArgumentsNode;
import org.jruby.truffle.builtins.Primitive;
import org.jruby.truffle.builtins.PrimitiveArrayArgumentsNode;
import org.jruby.truffle.language.objects.AllocateObjectNode;
import org.jruby.truffle.language.objects.AllocateObjectNodeGen;

@CoreClass("NoMethodError")
public abstract class NoMethodErrorNodes {

@CoreMethod(names = "allocate", constructor = true)
public abstract static class AllocateNode extends CoreMethodArrayArgumentsNode {

@Child private AllocateObjectNode allocateObjectNode;

public AllocateNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
allocateObjectNode = AllocateObjectNodeGen.create(context, sourceSection, null, null);
}

@Specialization
public DynamicObject allocateNoMethodError(DynamicObject rubyClass) {
return allocateObjectNode.allocate(rubyClass, nil(), null, null, nil(), nil());
}

}

@CoreMethod(names = "args")
public abstract static class ArgsNode extends CoreMethodArrayArgumentsNode {

@Specialization
public Object args(DynamicObject self) {
return Layouts.NO_METHOD_ERROR.getArgs(self);
}

}

@Primitive(name = "no_method_error_set_args")
public abstract static class ArgsSetNode extends PrimitiveArrayArgumentsNode {

@Specialization
public Object setArgs(DynamicObject error, Object args) {
Layouts.NO_METHOD_ERROR.setArgs(error, args);
return args;
}

}


}
12 changes: 6 additions & 6 deletions truffle/src/main/ruby/core/exception.rb
Original file line number Diff line number Diff line change
@@ -183,18 +183,18 @@ class LocalJumpError < StandardError
class NameError < StandardError

def initialize(*args)
super(args.shift)
Truffle.invoke_primitive :name_error_set_name, self, args.shift
name = args.size > 1 ? args.pop : nil
super(*args)
Truffle.invoke_primitive :name_error_set_name, self, name
end
end

class NoMethodError < NameError
attr_reader :args

def initialize(*arguments)
super(arguments.shift)
@name = arguments.shift
@args = arguments.shift
args = arguments.size > 2 ? arguments.pop : nil
super(*arguments) # TODO BJF Jul 24, 2016 Need to handle NoMethodError.new(1,2,3,4)
Truffle.invoke_primitive :no_method_error_set_args, self, args
end
end

0 comments on commit 460a2c4

Please sign in to comment.