Skip to content

Commit

Permalink
[Truffle] Fix constant lookup Mod::Const: no lexical scope in that case.
Browse files Browse the repository at this point in the history
* Match MRI uninitialized constant message.
* Add a couple assert to clarify the possible arguments values.
  • Loading branch information
eregon committed Nov 10, 2014
1 parent f0ef342 commit 4bf104a
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 18 deletions.
Expand Up @@ -561,7 +561,7 @@ public Object getConstant(VirtualFrame frame, RubyModule module, RubySymbol name
}
}

@CoreMethod(names = "const_missing", needsSelf = false, required = 1)
@CoreMethod(names = "const_missing", required = 1)
public abstract static class ConstMissingNode extends CoreMethodNode {

public ConstMissingNode(RubyContext context, SourceSection sourceSection) {
Expand All @@ -573,8 +573,8 @@ public ConstMissingNode(ConstMissingNode prev) {
}

@Specialization
public Object methodMissing(RubySymbol name) {
throw new RaiseException(getContext().getCoreLibrary().nameErrorUninitializedConstant(name.toString(), this));
public Object methodMissing(RubyModule module, RubySymbol name) {
throw new RaiseException(getContext().getCoreLibrary().nameErrorUninitializedConstant(module, name.toString(), this));
}

}
Expand Down
Expand Up @@ -59,12 +59,14 @@ public static Map<String, RubyConstant> getAllConstants(RubyModule module) {
}

/**
* @param lexicalScope The surrounding LexicalScope, null if it is ignored (as in Mod::Constant)
* @param lexicalScope The surrounding LexicalScope (as in Constant),
* or null if it is ignored (as in Mod::Constant or ::Constant)
* @param module The receiver of the constant lookup.
* Identical to lexicalScope.getLiveModule() if there no qualifier (Constant).
* Must be identical to lexicalScope.getLiveModule() if lexicalScope != null.
*/
public static RubyConstant lookupConstant(RubyContext context, LexicalScope lexicalScope, RubyModule module, String name) {
CompilerAsserts.neverPartOfCompilation();
assert lexicalScope == null || lexicalScope.getLiveModule() == module;

RubyConstant constant;

Expand All @@ -79,8 +81,8 @@ public static RubyConstant lookupConstant(RubyContext context, LexicalScope lexi
final RubyClass objectClass = context.getCoreLibrary().getObjectClass();

if (lexicalScope != null) {
if (lexicalScope.getLiveModule() == module && lexicalScope != context.getRootLexicalScope()) {
// Already looked in module.
if (lexicalScope != context.getRootLexicalScope()) {
// Already looked in the top lexical scope, which is module.
lexicalScope = lexicalScope.getParent();
}

Expand Down
11 changes: 6 additions & 5 deletions core/src/main/java/org/jruby/truffle/runtime/RubyConstant.java
Expand Up @@ -9,6 +9,7 @@
*/
package org.jruby.truffle.runtime;

import com.oracle.truffle.api.CompilerAsserts;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyModule;

Expand Down Expand Up @@ -37,12 +38,13 @@ public void setPrivate(boolean isPrivate) {
}

public boolean isVisibleTo(RubyContext context, LexicalScope lexicalScope, RubyModule module) {
CompilerAsserts.neverPartOfCompilation();
assert lexicalScope == null || lexicalScope.getLiveModule() == module;

if (!isPrivate) {
return true;
}

final LexicalScope topLexicalScope = lexicalScope;

// Look in lexical scope
if (lexicalScope != null) {
while (lexicalScope != context.getRootLexicalScope()) {
Expand All @@ -62,9 +64,8 @@ public boolean isVisibleTo(RubyContext context, LexicalScope lexicalScope, RubyM
}
}

// Look in Object if there is no qualifier (just CONST, neither Mod::CONST nor ::CONST).
if (topLexicalScope != null && topLexicalScope.getLiveModule() == module && // This is a guess, we should have that info from AST
context.getCoreLibrary().getObjectClass() == declaringModule) {
// Allow Object constants if looking with lexical scope.
if (lexicalScope != null && context.getCoreLibrary().getObjectClass() == declaringModule) {
return true;
}

Expand Down
Expand Up @@ -510,6 +510,7 @@ public RubyException typeErrorCantConvertInto(String from, String to, Node curre
}

public RubyException typeErrorCantConvertInto(Object from, RubyClass to, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return typeErrorCantConvertInto(box(from).getLogicalClass().getName(), to.getName(), currentNode);
}

Expand All @@ -523,9 +524,9 @@ public RubyException nameError(String message, Node currentNode) {
return new RubyException(nameErrorClass, context.makeString(message), RubyCallStack.getBacktrace(currentNode));
}

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

public RubyException nameErrorPrivateConstant(RubyModule module, String name, Node currentNode) {
Expand Down
Expand Up @@ -305,7 +305,7 @@ public void changeConstantVisibility(RubyNode currentNode, RubySymbol constant,
rubyConstant.setPrivate(isPrivate);
newLexicalVersion();
} else {
throw new RaiseException(context.getCoreLibrary().nameErrorUninitializedConstant(constant.toString(), currentNode));
throw new RaiseException(context.getCoreLibrary().nameErrorUninitializedConstant(this, constant.toString(), currentNode));
}
}

Expand Down
Expand Up @@ -632,7 +632,7 @@ public RubyNode visitColon2Node(org.jruby.ast.Colon2Node node) {

final RubyNode lhs = node.getLeftNode().accept(this);

return new ReadConstantNode(context, translate(node.getPosition()), node.getName(), lhs, environment.getLexicalScope());
return new ReadConstantNode(context, translate(node.getPosition()), node.getName(), lhs, LexicalScope.NONE);
}

@Override
Expand Down Expand Up @@ -681,9 +681,10 @@ public RubyNode visitConstNode(org.jruby.ast.ConstNode node) {
// Unqualified constant access, as in CONST
final SourceSection sourceSection = translate(node.getPosition());

RubyNode moduleNode = new LexicalScopeNode(context, sourceSection, environment.getLexicalScope());
final LexicalScope lexicalScope = environment.getLexicalScope();
final RubyNode moduleNode = new LexicalScopeNode(context, sourceSection, lexicalScope);

return new ReadConstantNode(context, sourceSection, node.getName(), moduleNode, environment.getLexicalScope());
return new ReadConstantNode(context, sourceSection, node.getName(), moduleNode, lexicalScope);
}

@Override
Expand Down

0 comments on commit 4bf104a

Please sign in to comment.