Skip to content

Commit

Permalink
[Truffle] Start implementing Module#deprecate_constant
Browse files Browse the repository at this point in the history
  • Loading branch information
Brandon Fish committed Sep 25, 2016
1 parent daa6c8d commit b06f580
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 6 deletions.
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/module/deprecate_constant_tags.txt
@@ -1,5 +1,2 @@
fails:Module#deprecate_constant accepts multiple symbols and strings as constant names
fails:Module#deprecate_constant returns self
fails:Module#deprecate_constant raises a NameError when given an undefined name
fails:Module#deprecate_constant when accessing the deprecated module passes the accessing
fails:Module#deprecate_constant when accessing the deprecated module warns with a message
Expand Up @@ -312,7 +312,8 @@ public void setConstantInternal(RubyContext context, Node currentNode, String na
while (true) {
final RubyConstant previous = constants.get(name);
final boolean isPrivate = previous != null && previous.isPrivate();
final RubyConstant newValue = new RubyConstant(rubyModuleObject, value, isPrivate, autoload);
final boolean isDeprecated = previous != null && previous.isDeprecated();
final RubyConstant newValue = new RubyConstant(rubyModuleObject, value, isPrivate, autoload, isDeprecated);

if ((previous == null) ? (constants.putIfAbsent(name, newValue) == null) : constants.replace(name, previous, newValue)) {
newLexicalVersion();
Expand Down Expand Up @@ -453,6 +454,26 @@ public void changeConstantVisibility(
}
}

@TruffleBoundary
public void deprecateConstant(
final RubyContext context,
final Node currentNode,
final String name) {

while (true) {
final RubyConstant previous = constants.get(name);

if (previous == null) {
throw new RaiseException(context.getCoreExceptions().nameErrorUninitializedConstant(rubyModuleObject, name, currentNode));
}

if (constants.replace(name, previous, previous.withDeprecated())) {
newLexicalVersion();
break;
}
}
}

public RubyContext getContext() {
return context;
}
Expand Down
Expand Up @@ -1629,6 +1629,29 @@ public DynamicObject privateConstant(VirtualFrame frame, DynamicObject module, O
}
}

@CoreMethod(names = "deprecate_constant", rest = true)
public abstract static class DeprecateConstantNode extends CoreMethodArrayArgumentsNode {

@Child NameToJavaStringNode nameToJavaStringNode = NameToJavaStringNode.create();
@Child IsFrozenNode isFrozenNode;

public DeprecateConstantNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.nameToJavaStringNode = NameToJavaStringNode.create();
this.isFrozenNode = IsFrozenNodeGen.create(context, sourceSection, null);
}

@Specialization
public DynamicObject deprecateConstant(VirtualFrame frame, DynamicObject module, Object[] args) {
isFrozenNode.raiseIfFrozen(module);
for (Object arg : args) {
String name = nameToJavaStringNode.executeToJavaString(frame, arg);
Layouts.MODULE.getFields(module).deprecateConstant(getContext(), this, name);
}
return module;
}
}

@CoreMethod(names = "public_constant", rest = true)
public abstract static class PublicConstantNode extends CoreMethodArrayArgumentsNode {

Expand Down
18 changes: 16 additions & 2 deletions truffle/src/main/java/org/jruby/truffle/language/RubyConstant.java
Expand Up @@ -20,13 +20,15 @@ public class RubyConstant {
private final Object value;
private final boolean isPrivate;
private final boolean autoload;
private final boolean isDeprecated;

public RubyConstant(DynamicObject declaringModule, Object value, boolean isPrivate, boolean autoload) {
public RubyConstant(DynamicObject declaringModule, Object value, boolean isPrivate, boolean autoload, boolean isDeprecated) {
assert RubyGuards.isRubyModule(declaringModule);
this.declaringModule = declaringModule;
this.value = value;
this.isPrivate = isPrivate;
this.autoload = autoload;
this.isDeprecated = isDeprecated;
}

public DynamicObject getDeclaringModule() {
Expand All @@ -41,11 +43,23 @@ public boolean isPrivate() {
return isPrivate;
}

public boolean isDeprecated() {
return isDeprecated;
}

public RubyConstant withPrivate(boolean isPrivate) {
if (isPrivate == this.isPrivate) {
return this;
} else {
return new RubyConstant(declaringModule, value, isPrivate, autoload);
return new RubyConstant(declaringModule, value, isPrivate, autoload, isDeprecated);
}
}

public RubyConstant withDeprecated() {
if (this.isDeprecated()) {
return this;
} else {
return new RubyConstant(declaringModule, value, isPrivate, autoload, true);
}
}

Expand Down
Expand Up @@ -74,9 +74,17 @@ protected RubyConstant lookupConstant(
if (!isVisible) {
throw new RaiseException(coreExceptions().nameErrorPrivateConstant(module, name, this));
}
if(constant != null && constant.isDeprecated()){
warnDeprecatedConstant(name);
}
return constant;
}

@TruffleBoundary
private void warnDeprecatedConstant(String name) {
getContext().getJRubyRuntime().getWarnings().warn("constant " + name + " is deprecated");
}

public Assumption getUnmodifiedAssumption(DynamicObject module) {
return Layouts.MODULE.getFields(module).getUnmodifiedAssumption();
}
Expand All @@ -90,6 +98,9 @@ protected RubyConstant lookupConstantUncached(DynamicObject module, String name)
if (!isVisible) {
throw new RaiseException(coreExceptions().nameErrorPrivateConstant(module, name, this));
}
if(constant != null && constant.isDeprecated()){
warnDeprecatedConstant(name);
}
return constant;
}

Expand Down
Expand Up @@ -10,6 +10,7 @@
package org.jruby.truffle.language.constants;

import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
Expand Down Expand Up @@ -49,6 +50,9 @@ protected RubyConstant lookupConstant(VirtualFrame frame,
if (!isVisible) {
throw new RaiseException(coreExceptions().nameErrorPrivateConstant(getModule(), name, this));
}
if(constant != null && constant.isDeprecated()){
warnDeprecatedConstant(name);
}
return constant;
}

Expand All @@ -64,4 +68,9 @@ protected boolean isVisible(RubyConstant constant) {
return constant == null || constant.isVisibleTo(getContext(), lexicalScope, getModule());
}

@TruffleBoundary
private void warnDeprecatedConstant(String name) {
getContext().getJRubyRuntime().getWarnings().warn("constant " + name + " is deprecated");
}

}
Expand Up @@ -74,6 +74,9 @@ private RubyConstant deepConstantSearch(String name, DynamicObject lexicalParent
if (constant != null && !constant.isVisibleTo(getContext(), LexicalScope.NONE, lexicalParent)) {
throw new RaiseException(getContext().getCoreExceptions().nameErrorPrivateConstant(lexicalParent, name, this));
}
if(constant != null && constant.isDeprecated()){
warnDeprecatedConstant(name);
}
return constant;
}

Expand All @@ -85,4 +88,9 @@ public RequireNode getRequireNode() {
return requireNode;
}

@TruffleBoundary
private void warnDeprecatedConstant(String name) {
getContext().getJRubyRuntime().getWarnings().warn("constant " + name + " is deprecated");
}

}

0 comments on commit b06f580

Please sign in to comment.