Skip to content

Commit

Permalink
Showing 17 changed files with 195 additions and 62 deletions.
8 changes: 0 additions & 8 deletions spec/truffle/tags/core/exception/receiver_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
@@ -26,6 +26,8 @@
import org.jruby.truffle.core.encoding.EncodingLayoutImpl;
import org.jruby.truffle.core.exception.ExceptionLayout;
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.SystemCallErrorLayout;
import org.jruby.truffle.core.exception.SystemCallErrorLayoutImpl;
import org.jruby.truffle.core.fiber.FiberLayout;
@@ -121,6 +123,7 @@ public abstract class Layouts {
public static final MethodLayout METHOD = MethodLayoutImpl.INSTANCE;
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 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
@@ -44,6 +44,7 @@
import org.jruby.truffle.core.encoding.EncodingConverterNodesFactory;
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.SystemCallErrorNodesFactory;
import org.jruby.truffle.core.fiber.FiberNodesFactory;
import org.jruby.truffle.core.hash.HashNodesFactory;
@@ -394,6 +395,7 @@ public CoreLibrary(RubyContext context) {

// StandardError > NameError
nameErrorClass = defineClass(standardErrorClass, "NameError");
Layouts.CLASS.setInstanceFactoryUnsafe(nameErrorClass, Layouts.NAME_ERROR.createNameErrorShape(nameErrorClass, nameErrorClass));
noMethodErrorClass = defineClass(nameErrorClass, "NoMethodError");

// StandardError > SystemCallError
@@ -676,6 +678,7 @@ public void addPrimitives() {
primitiveManager.addPrimitiveNodes(IOPrimitiveNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(IOBufferPrimitiveNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(ExceptionNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(NameErrorNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(SystemCallErrorNodesFactory.getFactories());
return null;
}, () -> {
@@ -705,6 +708,7 @@ public void addCoreMethods() {
coreMethodNodeManager.addCoreMethodNodes(ClassNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(ConditionVariableNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(ExceptionNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(NameErrorNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(SystemCallErrorNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(FalseClassNodesFactory.getFactories());
return null;
Original file line number Diff line number Diff line change
@@ -280,7 +280,7 @@ private DynamicObject buildMethodMissingException(Object self, DynamicObject nam
final String name = nameObject.toString();

if (lastCallWasSuper()) {
return coreExceptions().noSuperMethodError(name, this);
return coreExceptions().noSuperMethodError(name, self, this);
} else if (lastCallWasCallingPrivateMethod(self, name)) {
return coreExceptions().privateMethodError(name, self, this);
} else if (lastCallWasVCall()) {
Original file line number Diff line number Diff line change
@@ -120,6 +120,11 @@ public DynamicObject argumentErrorInvalidValue(Object object, String expectedTyp
return argumentError(String.format("invalid value for %s(): %s", badClassName, expectedType), currentNode);
}

@TruffleBoundary
public DynamicObject argumentErrorNoReceiver(Node currentNode) {
return argumentError("no receiver is available", currentNode);
}

@TruffleBoundary
public DynamicObject argumentError(String message, Node currentNode, Throwable javaThrowable) {
return argumentError(StringOperations.encodeRope(message, UTF8Encoding.INSTANCE), currentNode, javaThrowable);
@@ -406,7 +411,7 @@ public DynamicObject typeError(String message, Node currentNode, Throwable javaT

@TruffleBoundary
public DynamicObject nameErrorConstantNotDefined(DynamicObject module, String name, Node currentNode) {
return nameError(String.format("constant %s::%s not defined", Layouts.MODULE.getFields(module).getName(), name), name, currentNode);
return nameError(String.format("constant %s::%s not defined", Layouts.MODULE.getFields(module).getName(), name), null, name, currentNode);
}

@TruffleBoundary
@@ -418,103 +423,103 @@ public DynamicObject nameErrorUninitializedConstant(DynamicObject module, String
} else {
message = String.format("uninitialized constant %s::%s", Layouts.MODULE.getFields(module).getName(), name);
}
return nameError(message, name, currentNode);
return nameError(message, module, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorUninitializedClassVariable(DynamicObject module, String name, Node currentNode) {
assert RubyGuards.isRubyModule(module);
return nameError(String.format("uninitialized class variable %s in %s", name, Layouts.MODULE.getFields(module).getName()), name, currentNode);
return nameError(String.format("uninitialized class variable %s in %s", name, Layouts.MODULE.getFields(module).getName()), module, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorPrivateConstant(DynamicObject module, String name, Node currentNode) {
return nameError(String.format("private constant %s::%s referenced", Layouts.MODULE.getFields(module).getName(), name), name, currentNode);
return nameError(String.format("private constant %s::%s referenced", Layouts.MODULE.getFields(module).getName(), name), module, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorInstanceNameNotAllowable(String name, Node currentNode) {
return nameError(String.format("`%s' is not allowable as an instance variable name", name), name, currentNode);
public DynamicObject nameErrorInstanceNameNotAllowable(String name, Object receiver, Node currentNode) {
return nameError(String.format("`%s' is not allowable as an instance variable name", name), receiver, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorInstanceVariableNotDefined(String name, Node currentNode) {
return nameError(String.format("instance variable %s not defined", name), name, currentNode);
public DynamicObject nameErrorInstanceVariableNotDefined(String name, Object receiver, Node currentNode) {
return nameError(String.format("instance variable %s not defined", name), receiver, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorReadOnly(String name, Node currentNode) {
return nameError(String.format("%s is a read-only variable", name), name, currentNode);
return nameError(String.format("%s is a read-only variable", name), null, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorUndefinedLocalVariableOrMethod(String name, Object receiver, Node currentNode) {
// TODO: should not be just the class, but rather sth like name_err_mesg_to_str() in MRI error.c
String className = Layouts.MODULE.getFields(context.getCoreLibrary().getLogicalClass(receiver)).getName();
return nameError(String.format("undefined local variable or method `%s' for %s", name, className), name, currentNode);
return nameError(String.format("undefined local variable or method `%s' for %s", name, className), receiver, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorUndefinedMethod(String name, DynamicObject module, Node currentNode) {
assert RubyGuards.isRubyModule(module);
return nameError(String.format("undefined method `%s' for %s", name, Layouts.MODULE.getFields(module).getName()), name, currentNode);
return nameError(String.format("undefined method `%s' for %s", name, Layouts.MODULE.getFields(module).getName()), module, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorMethodNotDefinedIn(DynamicObject module, String name, Node currentNode) {
return nameError(String.format("method `%s' not defined in %s", name, Layouts.MODULE.getFields(module).getName()), name, currentNode);
return nameError(String.format("method `%s' not defined in %s", name, Layouts.MODULE.getFields(module).getName()), module, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorPrivateMethod(String name, DynamicObject module, Node currentNode) {
return nameError(String.format("method `%s' for %s is private", name, Layouts.MODULE.getFields(module).getName()), name, currentNode);
return nameError(String.format("method `%s' for %s is private", name, Layouts.MODULE.getFields(module).getName()), module, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorLocalVariableNotDefined(String name, DynamicObject binding, Node currentNode) {
assert RubyGuards.isRubyBinding(binding);
return nameError(String.format("local variable `%s' not defined for %s", name, binding.toString()), name, currentNode);
return nameError(String.format("local variable `%s' not defined for %s", name, binding.toString()), binding, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorClassVariableNotDefined(String name, DynamicObject module, Node currentNode) {
assert RubyGuards.isRubyModule(module);
return nameError(String.format("class variable `%s' not defined for %s", name, Layouts.MODULE.getFields(module).getName()), name, currentNode);
return nameError(String.format("class variable `%s' not defined for %s", name, Layouts.MODULE.getFields(module).getName()), module, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameErrorImportNotFound(String name, Node currentNode) {
return nameError(String.format("import '%s' not found", name), name, currentNode);
return nameError(String.format("import '%s' not found", name), null, name, currentNode);
}

@TruffleBoundary
public DynamicObject nameError(String message, String name, Node currentNode) {
public DynamicObject nameError(String message, Object receiver, String name, Node currentNode) {
final DynamicObject nameString = StringOperations.createString(context, StringOperations.encodeRope(message, UTF8Encoding.INSTANCE));
DynamicObject nameError = ExceptionOperations.createRubyException(context.getCoreLibrary().getNameErrorClass(), nameString, context.getCallStack().getBacktrace(currentNode));
nameError.define("@name", context.getSymbolTable().getSymbol(name), 0);
DynamicObject nameError = ExceptionOperations.createNameError(context.getCoreLibrary().getNameErrorClass(), nameString, context.getCallStack().getBacktrace(currentNode), receiver, context.getSymbolTable().getSymbol(name));
return nameError;
}

// NoMethodError

@TruffleBoundary
public DynamicObject noMethodError(String message, String name, Node currentNode) {
public DynamicObject noMethodError(String message, Object receiver, String name, Node currentNode) {
final DynamicObject messageString = StringOperations.createString(context, StringOperations.encodeRope(message, UTF8Encoding.INSTANCE));
DynamicObject noMethodError = ExceptionOperations.createRubyException(context.getCoreLibrary().getNoMethodErrorClass(), messageString, context.getCallStack().getBacktrace(currentNode));
noMethodError.define("@name", context.getSymbolTable().getSymbol(name), 0);
DynamicObject noMethodError = ExceptionOperations.createNameError(context.getCoreLibrary().getNoMethodErrorClass(), messageString, context.getCallStack().getBacktrace(currentNode), receiver, context.getSymbolTable().getSymbol(name));
return noMethodError;
}

@TruffleBoundary
public DynamicObject noSuperMethodOutsideMethodError(Node currentNode) {
DynamicObject noMethodError = noMethodError("super called outside of method", "<unknown>", currentNode);
noMethodError.define("@name", context.getCoreLibrary().getNilObject(), 0); // FIXME: the name of the method is not known in this case currently
final DynamicObject messageString = StringOperations.createString(context, StringOperations.encodeRope("super called outside of method", UTF8Encoding.INSTANCE));
// TODO BJF Jul 21, 2016 Review to add receiver
DynamicObject noMethodError = ExceptionOperations.createNameError(context.getCoreLibrary().getNoMethodErrorClass(), messageString, context.getCallStack().getBacktrace(currentNode), null, context.getSymbolTable().getSymbol("<unknown>"));
// FIXME: the name of the method is not known in this case currently
return noMethodError;
}

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

@TruffleBoundary
@@ -526,13 +531,13 @@ public DynamicObject noMethodErrorOnReceiver(String name, Object receiver, Node
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), name, currentNode);
return noMethodError(String.format("undefined method `%s' for %s:%s", name, stringRepresentation, moduleName), receiver, name, currentNode);
}

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

// LoadError
Original file line number Diff line number Diff line change
@@ -134,8 +134,8 @@ public AllocateNode(RubyContext context, SourceSection sourceSection) {
}

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

}
Original file line number Diff line number Diff line change
@@ -50,4 +50,8 @@ public static DynamicObject createSystemCallError(DynamicObject rubyClass, Objec
return Layouts.SYSTEM_CALL_ERROR.createSystemCallError(Layouts.CLASS.getInstanceFactory(rubyClass), message, backtrace, errno);
}

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

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 NameErrorLayout extends ExceptionLayout {

DynamicObjectFactory createNameErrorShape(
DynamicObject logicalClass,
DynamicObject metaClass);

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

Object getName(DynamicObject object);
void setName(DynamicObject object, Object value);

Object getReceiver(DynamicObject object);
void setReceiver(DynamicObject object, Object value);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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.control.RaiseException;
import org.jruby.truffle.language.objects.AllocateObjectNode;
import org.jruby.truffle.language.objects.AllocateObjectNodeGen;

@CoreClass("NameError")
public abstract class NameErrorNodes {

@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 allocateNameError(DynamicObject rubyClass) {
return allocateObjectNode.allocate(rubyClass, nil(), null, null, nil());
}

}

@CoreMethod(names = "name")
public abstract static class NameNode extends CoreMethodArrayArgumentsNode {

@Specialization
public Object name(DynamicObject self) {
return Layouts.NAME_ERROR.getName(self);
}

}

@CoreMethod(names = "receiver")
public abstract static class ReceiverNode extends CoreMethodArrayArgumentsNode {

@Specialization
public Object receiver(DynamicObject self) {
final Object receiver = Layouts.NAME_ERROR.getReceiver(self);

// TODO BJF July 21, 2016 Implement name error in message field

if (receiver == null) {
throw new RaiseException(coreExceptions().argumentErrorNoReceiver(this));
}
return receiver;
}

}

@Primitive(name = "name_error_set_name")
public abstract static class NameSetNode extends PrimitiveArrayArgumentsNode {

@Specialization
public Object setName(DynamicObject error, Object name) {
Layouts.NAME_ERROR.setName(error, name);
return name;
}

}


}
Original file line number Diff line number Diff line change
@@ -975,7 +975,7 @@ public RubyNode coerceToString(RubyNode name) {
@TruffleBoundary
@Specialization
public boolean isInstanceVariableDefined(DynamicObject object, String name) {
final String ivar = SymbolTable.checkInstanceVariableName(getContext(), name, this);
final String ivar = SymbolTable.checkInstanceVariableName(getContext(), name, object, this);
return object.getShape().hasProperty(ivar);
}

@@ -1045,10 +1045,10 @@ public RubyNode coerceToString(RubyNode name) {
@TruffleBoundary
@Specialization
public Object removeInstanceVariable(DynamicObject object, String name) {
final String ivar = SymbolTable.checkInstanceVariableName(getContext(), name, this);
final String ivar = SymbolTable.checkInstanceVariableName(getContext(), name, object, this);
final Object value = object.get(ivar, nil());
if (!object.delete(name)) {
throw new RaiseException(coreExceptions().nameErrorInstanceVariableNotDefined(name, this));
throw new RaiseException(coreExceptions().nameErrorInstanceVariableNotDefined(name, object, this));
}
return value;
}
Original file line number Diff line number Diff line change
@@ -522,7 +522,7 @@ public AutoloadNode(RubyContext context, SourceSection sourceSection) {
@Specialization(guards = "isRubyString(filename)")
public DynamicObject autoload(DynamicObject module, String name, DynamicObject filename) {
if (!IdUtil.isValidConstantName19(name)) {
throw new RaiseException(coreExceptions().nameError(String.format("autoload must be constant name: %s", name), name, this));
throw new RaiseException(coreExceptions().nameError(String.format("autoload must be constant name: %s", name), module, name, this));
}

if (isEmptyNode.executeIsEmpty(filename)) {
@@ -686,7 +686,7 @@ public RubyNode coerceToString(RubyNode name) {
@TruffleBoundary(throwsControlFlowException = true)
@Specialization
public boolean isClassVariableDefinedString(DynamicObject module, String name) {
SymbolTable.checkClassVariableName(getContext(), name, this);
SymbolTable.checkClassVariableName(getContext(), name, module, this);

final Object value = ModuleOperations.lookupClassVariable(module, name);

@@ -710,7 +710,7 @@ public RubyNode coerceToString(RubyNode name) {
@Specialization
@TruffleBoundary(throwsControlFlowException = true)
public Object getClassVariable(DynamicObject module, String name) {
SymbolTable.checkClassVariableName(getContext(), name, this);
SymbolTable.checkClassVariableName(getContext(), name, module, this);

final Object value = ModuleOperations.lookupClassVariable(module, name);

@@ -739,7 +739,7 @@ public RubyNode coerceToString(RubyNode name) {
@Specialization
@TruffleBoundary(throwsControlFlowException = true)
public Object setClassVariable(DynamicObject module, String name, Object value) {
SymbolTable.checkClassVariableName(getContext(), name, this);
SymbolTable.checkClassVariableName(getContext(), name, module, this);

ModuleOperations.setClassVariable(getContext(), module, name, value, this);

@@ -964,7 +964,7 @@ public RubyNode coerceToString(RubyNode name) {
@Specialization
public Object setConstant(DynamicObject module, String name, Object value) {
if (!IdUtil.isValidConstantName19(name)) {
throw new RaiseException(coreExceptions().nameError(String.format("wrong constant name %s", name), name, this));
throw new RaiseException(coreExceptions().nameError(String.format("wrong constant name %s", name), module, name, this));
}

Layouts.MODULE.getFields(module).setConstant(getContext(), this, name, value);
@@ -1655,7 +1655,7 @@ public RubyNode coerceToString(RubyNode name) {
@TruffleBoundary(throwsControlFlowException = true)
@Specialization
public Object removeClassVariableString(DynamicObject module, String name) {
SymbolTable.checkClassVariableName(getContext(), name, this);
SymbolTable.checkClassVariableName(getContext(), name, module, this);
return ModuleOperations.removeClassVariable(Layouts.MODULE.getFields(module), getContext(), this, name);
}

Original file line number Diff line number Diff line change
@@ -183,7 +183,7 @@ public static RubyConstant lookupScopedConstant(RubyContext context, DynamicObje

final String lastSegment = fullName.substring(start);
if (!IdUtil.isValidConstantName19(lastSegment)) {
throw new RaiseException(context.getCoreExceptions().nameError(String.format("wrong constant name %s", fullName), fullName, currentNode));
throw new RaiseException(context.getCoreExceptions().nameError(String.format("wrong constant name %s", fullName), module, fullName, currentNode));
}

return lookupConstantWithInherit(context, module, lastSegment, inherit, currentNode);
@@ -194,7 +194,7 @@ public static RubyConstant lookupConstantWithInherit(RubyContext context, Dynami
assert RubyGuards.isRubyModule(module);

if (!IdUtil.isValidConstantName19(name)) {
throw new RaiseException(context.getCoreExceptions().nameError(String.format("wrong constant name %s", name), name, currentNode));
throw new RaiseException(context.getCoreExceptions().nameError(String.format("wrong constant name %s", name), module, name, currentNode));
}

if (inherit) {
Original file line number Diff line number Diff line change
@@ -181,13 +181,15 @@ public Collection<DynamicObject> allSymbols() {
public static String checkInstanceVariableName(
RubyContext context,
String name,
Object receiver,
Node currentNode) {
// if (!IdUtil.isValidInstanceVariableName(name)) {

// check like Rubinius does for compatibility with their Struct Ruby implementation.
if (!(name.startsWith("@") && name.length() > 1 && IdUtil.isInitialCharacter(name.charAt(1)))) {
throw new RaiseException(context.getCoreExceptions().nameErrorInstanceNameNotAllowable(
name,
receiver,
currentNode));
}
return name;
@@ -197,10 +199,12 @@ public static String checkInstanceVariableName(
public static String checkClassVariableName(
RubyContext context,
String name,
Object receiver,
Node currentNode) {
if (!IdUtil.isValidClassVariableName(name)) {
throw new RaiseException(context.getCoreExceptions().nameErrorInstanceNameNotAllowable(
name,
receiver,
currentNode));
}
return name;
Original file line number Diff line number Diff line change
@@ -94,7 +94,7 @@ private Object doMissingConstant(
boolean isValidConstantName,
DynamicObject symbolName) {
if (!isValidConstantName) {
throw new RaiseException(coreExceptions().nameError(formatError(name), name, this));
throw new RaiseException(coreExceptions().nameError(formatError(name), module, name, this));
}

if (constMissingNode == null) {
Original file line number Diff line number Diff line change
@@ -32,18 +32,18 @@ public ObjectIVarGetNode(boolean checkName) {
@Specialization(guards = "name == cachedName", limit = "getCacheLimit()")
public Object ivarGetCached(DynamicObject object, String name,
@Cached("name") String cachedName,
@Cached("createReadFieldNode(checkName(cachedName))") ReadObjectFieldNode readObjectFieldNode) {
@Cached("createReadFieldNode(checkName(cachedName, object))") ReadObjectFieldNode readObjectFieldNode) {
return readObjectFieldNode.execute(object);
}

@TruffleBoundary
@Specialization(contains = "ivarGetCached")
public Object ivarGetUncached(DynamicObject object, String name) {
return object.get(checkName(name), nil());
return object.get(checkName(name, object), nil());
}

protected String checkName(String name) {
return checkName ? SymbolTable.checkInstanceVariableName(getContext(), name, this) : name;
protected String checkName(String name, DynamicObject object) {
return checkName ? SymbolTable.checkInstanceVariableName(getContext(), name, object, this) : name;
}

protected ReadObjectFieldNode createReadFieldNode(String name) {
Original file line number Diff line number Diff line change
@@ -32,20 +32,20 @@ public ObjectIVarSetNode(boolean checkName) {
@Specialization(guards = "name == cachedName", limit = "getCacheLimit()")
public Object ivarSetCached(DynamicObject object, String name, Object value,
@Cached("name") String cachedName,
@Cached("createWriteFieldNode(checkName(cachedName))") WriteObjectFieldNode writeObjectFieldNode) {
@Cached("createWriteFieldNode(checkName(cachedName, object))") WriteObjectFieldNode writeObjectFieldNode) {
writeObjectFieldNode.execute(object, value);
return value;
}

@TruffleBoundary
@Specialization(contains = "ivarSetCached")
public Object ivarSetUncached(DynamicObject object, String name, Object value) {
object.define(checkName(name), value, 0);
object.define(checkName(name, object), value, 0);
return value;
}

protected String checkName(String name) {
return checkName ? SymbolTable.checkInstanceVariableName(getContext(), name, this) : name;
protected String checkName(String name, DynamicObject object) {
return checkName ? SymbolTable.checkInstanceVariableName(getContext(), name, object, this) : name;
}

protected WriteObjectFieldNode createWriteFieldNode(String name) {
4 changes: 1 addition & 3 deletions truffle/src/main/ruby/core/exception.rb
Original file line number Diff line number Diff line change
@@ -181,16 +181,14 @@ class LocalJumpError < StandardError
end

class NameError < StandardError
attr_reader :name

def initialize(*args)
super(args.shift)
@name = args.shift
Truffle.invoke_primitive :name_error_set_name, self, args.shift
end
end

class NoMethodError < NameError
attr_reader :name
attr_reader :args

def initialize(*arguments)

0 comments on commit 5399dcc

Please sign in to comment.