Skip to content

Commit

Permalink
[GR-19220] Raise SyntaxError on yield in singleton class definition (#…
Browse files Browse the repository at this point in the history
…2679)

PullRequest: truffleruby/3385
  • Loading branch information
eregon committed Jun 22, 2022
2 parents 4420a30 + f2452ab commit 4df60b6
Show file tree
Hide file tree
Showing 30 changed files with 205 additions and 213 deletions.
1 change: 0 additions & 1 deletion spec/tags/language/yield_tags.txt

This file was deleted.

6 changes: 6 additions & 0 deletions src/main/java/org/truffleruby/RubyContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.nodes.EncapsulatingNodeReference;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.AssumedValue;
import org.graalvm.collections.Pair;
import org.graalvm.options.OptionDescriptor;
Expand Down Expand Up @@ -713,6 +714,11 @@ public Map<Source, Integer> getSourceLineOffsets() {
return sourceLineOffsets;
}

@TruffleBoundary
public String fileLine(SourceSection section) {
return language.fileLine(this, section);
}

private static SecureRandom createRandomInstance() {
try {
/* We want to use a non-blocking source because this is what MRI does (via /dev/urandom) and it's been found
Expand Down
84 changes: 52 additions & 32 deletions src/main/java/org/truffleruby/RubyLanguage.java
Original file line number Diff line number Diff line change
Expand Up @@ -322,37 +322,6 @@ public static String getMimeType(boolean coverageEnabled) {
return coverageEnabled ? MIME_TYPE_COVERAGE : MIME_TYPE;
}

@TruffleBoundary
public static String fileLine(SourceSection section) {
if (section == null) {
return "no source section";
} else {
final String path = getPath(section.getSource());

if (section.isAvailable()) {
return path + ":" + section.getStartLine();
} else {
return path;
}
}
}

@TruffleBoundary
public static String filenameLine(SourceSection section) {
if (section == null) {
return "no source section";
} else {
final String path = getPath(section.getSource());
final String filename = new File(path).getName();

if (section.isAvailable()) {
return filename + ":" + section.getStartLine();
} else {
return filename;
}
}
}

public RubyLanguage() {
coreMethodAssumptions = new CoreMethodAssumptions(this);
coreStrings = new CoreStrings(this);
Expand Down Expand Up @@ -808,7 +777,58 @@ public String getSourcePath(Source source) {
if (path.startsWith(coreLoadPath)) {
return "<internal:core> " + path.substring(coreLoadPath.length() + 1);
} else {
return getPath(source);
return path;
}
}

/** Only use when no language/context is available (e.g. Node#toString). Prefer
* {@link RubyContext#fileLine(SourceSection)} as it accounts for coreLoadPath and line offsets. */
@TruffleBoundary
public static String fileLine(SourceSection section) {
if (section == null) {
return "no source section";
} else {
final String path = getPath(section.getSource());

if (section.isAvailable()) {
return path + ":" + section.getStartLine();
} else {
return path;
}
}
}

/** Prefer {@link RubyContext#fileLine(SourceSection)} as it is more concise. */
@TruffleBoundary
String fileLine(RubyContext context, SourceSection section) {
if (section == null) {
return "no source section";
} else {
final String path = getSourcePath(section.getSource());

if (section.isAvailable()) {
return path + ":" + RubySource.getStartLineAdjusted(context, section);
} else {
return path;
}
}
}

/** Only use when no language/context is available (e.g. Node#toString). Prefer
* {@link RubyContext#fileLine(SourceSection)} as it accounts for coreLoadPath and line offsets. */
@TruffleBoundary
public static String filenameLine(SourceSection section) {
if (section == null) {
return "no source section";
} else {
final String path = getPath(section.getSource());
final String filename = new File(path).getName();

if (section.isAvailable()) {
return filename + ":" + section.getStartLine();
} else {
return filename;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import org.truffleruby.core.string.StringUtils;
import org.truffleruby.core.support.TypeNodes;
import org.truffleruby.language.LexicalScope;
import org.truffleruby.language.Nil;
import org.truffleruby.language.RubyBaseNode;
import org.truffleruby.language.RubyCoreMethodRootNode;
import org.truffleruby.language.RubyNode;
Expand Down Expand Up @@ -284,8 +283,7 @@ private static void addMethod(
alwaysInlinedNodeFactory,
null,
callTarget,
callTargetSupplier,
Nil.INSTANCE));
callTargetSupplier));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public RubyNode createInvokePrimitiveNode(Source source, SourceIndexLength sourc
if (arguments.length != getPrimitiveArity()) {
throw new Error(
"Incorrect number of arguments (expected " + getPrimitiveArity() + ") at " +
RubyLanguage.fileLine(sourceSection.toSourceSection(source)));
RubyLanguage.getCurrentContext().fileLine(sourceSection.toSourceSection(source)));
}

for (int n = 0; n < arguments.length; n++) {
Expand Down
16 changes: 14 additions & 2 deletions src/main/java/org/truffleruby/core/exception/CoreExceptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -1017,9 +1017,21 @@ public RubySyntaxError syntaxErrorInvalidRetry(Node currentNode) {

@TruffleBoundary
public RubySyntaxError syntaxError(String message, Node currentNode, SourceSection sourceLocation) {
String messageWithFileLine;
if (sourceLocation != null) {
messageWithFileLine = context.fileLine(sourceLocation) + ": " + message;
} else {
messageWithFileLine = "(unknown):1: " + message;
}
return syntaxErrorAlreadyWithFileLine(messageWithFileLine, currentNode, sourceLocation);
}

@TruffleBoundary
public RubySyntaxError syntaxErrorAlreadyWithFileLine(String message, Node currentNode,
SourceSection sourceLocation) {
final RubyString messageString = StringOperations.createUTF8String(context, language,
StringOperations.encodeRope(message, UTF8Encoding.INSTANCE));
RubyClass exceptionClass = context.getCoreLibrary().syntaxErrorClass;
final RubyString messageString = StringOperations
.createUTF8String(context, language, StringOperations.encodeRope(message, UTF8Encoding.INSTANCE));
final Backtrace backtrace = context.getCallStack().getBacktrace(currentNode);
final Object cause = ThreadGetExceptionNode.getLastException(language);
showExceptionIfDebug(exceptionClass, messageString, backtrace);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/truffleruby/core/fiber/FiberManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public FiberManager(RubyLanguage language, RubyContext context) {

public void initialize(RubyFiber fiber, boolean blocking, RubyProc block, Node currentNode) {
final SourceSection sourceSection = block.getSharedMethodInfo().getSourceSection();
fiber.sourceLocation = RubyLanguage.fileLine(sourceSection);
fiber.sourceLocation = context.fileLine(sourceSection);
fiber.blocking = blocking;

final TruffleContext truffleContext = context.getEnv().getContext();
Expand Down Expand Up @@ -101,7 +101,7 @@ private void fiberMain(RubyContext context, RubyFiber fiber, RubyProc block, Nod
final FiberPoolThread thread = (FiberPoolThread) Thread.currentThread();
final SourceSection sourceSection = block.getSharedMethodInfo().getSourceSection();
final String oldName = thread.getName();
thread.setName(NAME_PREFIX + " id=" + thread.getId() + " from " + RubyLanguage.fileLine(sourceSection));
thread.setName(NAME_PREFIX + " id=" + thread.getId() + " from " + context.fileLine(sourceSection));

start(fiber, thread);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ public void setAutoloadConstant(RubyContext context, Node currentNode, String na
if (context.getOptions().LOG_AUTOLOAD) {
RubyLanguage.LOGGER.info(() -> String.format(
"%s: setting up autoload %s with %s",
RubyLanguage.fileLine(context.getCallStack().getTopMostUserSourceSection()),
context.fileLine(context.getCallStack().getTopMostUserSourceSection()),
autoloadConstant,
filename));
}
Expand Down
11 changes: 2 additions & 9 deletions src/main/java/org/truffleruby/core/module/ModuleNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -522,8 +522,7 @@ private RubySymbol createAccessor(RubyModule module, String name, Accessor acces
alwaysInlinedNodeFactory,
null,
callTarget,
null,
nil);
null);

module.fields.addMethod(getContext(), this, method);
return getLanguage().getSymbol(method.getName());
Expand Down Expand Up @@ -2326,7 +2325,7 @@ protected Object moduleUsing(Frame callerFrame, Object self, Object[] rubyArgs,
coreExceptions().runtimeError("Module#using is not called on self", this));
}
final InternalMethod callerMethod = RubyArguments.getMethod(callerFrame);
if (!isCalledFromClassOrModule(callerMethod)) {
if (!callerMethod.getSharedMethodInfo().isModuleBody()) {
errorProfile.enter();
throw new RaiseException(
getContext(),
Expand All @@ -2336,12 +2335,6 @@ protected Object moduleUsing(Frame callerFrame, Object self, Object[] rubyArgs,
return self;
}

@TruffleBoundary
private boolean isCalledFromClassOrModule(InternalMethod callerMethod) {
final String name = callerMethod.getSharedMethodInfo().getBacktraceName();
// Handles cases: <main> | <top | <class: | <module: | <singleton
return name.startsWith("<");
}
}

@CoreMethod(names = { "__allocate__", "__layout_allocate__" }, constructor = true, visibility = Visibility.PRIVATE)
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/truffleruby/core/thread/ThreadNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -424,12 +424,12 @@ protected Object initialize(VirtualFrame frame, RubyThread thread) {
@TruffleBoundary
private Object init(RubyThread thread, RubyProc block, ArgumentsDescriptor descriptor, Object[] args) {
final SourceSection sourceSection = block.getSharedMethodInfo().getSourceSection();
final String info = RubyLanguage.fileLine(sourceSection);
final String info = getContext().fileLine(sourceSection);
final String sharingReason = "creating Ruby Thread " + info;

if (getLanguage().options.SHARED_OBJECTS_ENABLED) {
getContext().getThreadManager().startSharing(thread, sharingReason);
SharedObjects.shareDeclarationFrame(getLanguage(), block);
SharedObjects.shareDeclarationFrame(getLanguage(), block, info);
}

getContext().getThreadManager().initialize(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ private void log(String message) {

final String displayedWarning = String.format(
"%s: %s",
RubyLanguage.fileLine(userSourceSection),
getContext().fileLine(userSourceSection),
message);

if (DISPLAYED_WARNINGS.add(displayedWarning)) {
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/org/truffleruby/language/WarnNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import com.oracle.truffle.api.nodes.DenyReplace;
import com.oracle.truffle.api.nodes.NodeCost;
import org.truffleruby.RubyContext;
import org.truffleruby.RubyLanguage;
import org.truffleruby.core.encoding.Encodings;
import org.truffleruby.core.rope.CodeRange;
import org.truffleruby.core.string.RubyString;
Expand Down Expand Up @@ -62,7 +61,7 @@ public void warningMessage(SourceSection sourceSection, String message) {

static void callWarn(RubyContext context, SourceSection sourceSection, String message,
MakeStringNode makeStringNode, DispatchNode callWarnNode) {
final String warningMessage = buildWarningMessage(sourceSection, message);
final String warningMessage = buildWarningMessage(context, sourceSection, message);

final RubyString warningString = makeStringNode
.executeMake(warningMessage, Encodings.UTF_8, CodeRange.CR_UNKNOWN);
Expand All @@ -71,8 +70,8 @@ static void callWarn(RubyContext context, SourceSection sourceSection, String me
}

@TruffleBoundary
private static String buildWarningMessage(SourceSection sourceSection, String message) {
final String sourceLocation = sourceSection != null ? RubyLanguage.fileLine(sourceSection) + ": " : "";
private static String buildWarningMessage(RubyContext context, SourceSection sourceSection, String message) {
final String sourceLocation = sourceSection != null ? context.fileLine(sourceSection) + ": " : "";
return sourceLocation + "warning: " + message;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ protected Object autoloadConstant(
if (getContext().getOptions().LOG_AUTOLOAD) {
RubyLanguage.LOGGER.info(() -> String.format(
"%s: %s::%s is being treated as missing while loading %s",
RubyLanguage.fileLine(getContext().getCallStack().getTopMostUserSourceSection()),
getContext().fileLine(getContext().getCallStack().getTopMostUserSourceSection()),
module.fields.getName(),
name,
expandedPath));
Expand All @@ -113,7 +113,7 @@ protected Object autoloadConstant(
if (getContext().getOptions().LOG_AUTOLOAD) {
RubyLanguage.LOGGER.info(() -> String.format(
"%s: autoloading %s with %s",
RubyLanguage.fileLine(getContext().getCallStack().getTopMostUserSourceSection()),
getContext().fileLine(getContext().getCallStack().getTopMostUserSourceSection()),
autoloadConstant,
autoloadConstant.getAutoloadConstant().getAutoloadPath()));
}
Expand Down Expand Up @@ -157,7 +157,7 @@ public static boolean autoloadUndefineConstantIfStillAutoload(RubyConstant autol
public static void logAutoloadResult(RubyContext context, RubyConstant constant, boolean undefined) {
if (context.getOptions().LOG_AUTOLOAD) {
final SourceSection section = context.getCallStack().getTopMostUserSourceSection();
final String message = RubyLanguage.fileLine(section) + ": " + constant + " " +
final String message = context.fileLine(section) + ": " + constant + " " +
(undefined
? "was marked as undefined as it was not assigned in "
: "was successfully autoloaded from ") +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.CompilerDirectives;
import org.truffleruby.RubyLanguage;
import com.oracle.truffle.api.TruffleSafepoint;
import org.truffleruby.core.exception.ExceptionOperations;
import org.truffleruby.language.RubyContextSourceNode;
Expand Down Expand Up @@ -137,7 +136,7 @@ private Object setLastExceptionAndRunRescue(VirtualFrame frame, Object exception

@TruffleBoundary
private void printBacktraceOnRescue(RescueNode rescue, AbstractTruffleException exception) {
String info = "rescued at " + RubyLanguage.fileLine(
String info = "rescued at " + getContext().fileLine(
getContext().getCallStack().getTopMostUserSourceSection(rescue.getEncapsulatingSourceSection())) +
":\n";
getContext().getDefaultBacktraceFormatter().printRubyExceptionOnEnvStderr(info, exception);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static RubySource createEvalSource(RubyContext context, Rope code, String
String.format("%02X", e.getNonAsciiCharacter());
throw new RaiseException(
context,
context.getCoreExceptions().syntaxError(
context.getCoreExceptions().syntaxErrorAlreadyWithFileLine(
message,
currentNode,
currentNode.getEncapsulatingSourceSection()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ private String findFeatureImpl(String feature) {
final SourceSection sourceSection = context.getCallStack().getTopMostUserSourceSection();
return String.format(
"starting search from %s for feature %s...",
RubyLanguage.fileLine(sourceSection),
context.fileLine(sourceSection),
originalFeature);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ private boolean requireConsideringAutoload(String feature, String expandedPath,
RubyLanguage.LOGGER
.info(() -> String.format(
"%s: requiring %s which is registered as an autoload for %s",
RubyLanguage.fileLine(getContext().getCallStack().getTopMostUserSourceSection()),
getContext().fileLine(getContext().getCallStack().getTopMostUserSourceSection()),
feature,
info));
}
Expand Down
Loading

0 comments on commit 4df60b6

Please sign in to comment.