Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 49ef265b38d0
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 71ae5d495367
Choose a head ref
  • 2 commits
  • 9 files changed
  • 1 contributor

Commits on Jan 6, 2016

  1. Copy the full SHA
    18c78f2 View commit details
  2. 4
    Copy the full SHA
    71ae5d4 View commit details
6 changes: 0 additions & 6 deletions spec/truffle/tags/language/block_tags.txt
Original file line number Diff line number Diff line change
@@ -5,15 +5,9 @@ fails:A block yielded a single Array raises a TypeError if #to_hash does not ret
fails:A block yielded a single Array raises the error raised inside #to_hash
fails:A block yielded a single Object receives the object if #to_ary returns nil
fails:A block yielded a single Array assigns nil to unassigned required arguments
fails:A block yielded a single Array assigns elements to optional arguments
fails:A block yielded a single Array assgins elements to post arguments
fails:A block yielded a single Array assigns elements to required arguments when a keyword rest argument is present
fails:A block yielded a single Array assigns elements to mixed argument types
fails:A block yielded a single Array calls #to_hash on the last element if keyword arguments are present
fails:A block yielded a single Array assigns the last element to a non-keyword argument if #to_hash returns nil
fails:A block yielded a single Array raises a TypeError if #to_hash does not return a Hash
fails:A block yielded a single Array raises the error raised inside #to_hash
fails:A block yielded a single Object receives the object if #to_ary returns nil
fails:Block-local variables override shadowed variables from the outer scope
fails:A block yielded a single Array does not treat hashes with string keys as keyword arguments
fails:A block yielded a single Array calls #to_hash on the last element when there are more arguments than parameters
1 change: 0 additions & 1 deletion spec/truffle/tags/language/class_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
fails:A class definition extending an object (sclass) can use return to cause the enclosing method to return
fails:A class definition extending an object (sclass) allows accessing the block of the original scope
4 changes: 0 additions & 4 deletions spec/truffle/tags/language/lambda_tags.txt
Original file line number Diff line number Diff line change
@@ -5,15 +5,11 @@ fails:"A lambda expression 'lambda { ... }' assigns variables from parameters fo
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> ((*a, b)) { [a, b] }"
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> ((a, b, *c, d), (*e, f, g), (*h)) do\n [a, b, c, d, e, f, g, h]\n end"
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (a, (b, (c, *d, (e, (*f)), g), (h, (i, j)))) do\n [a, b, c, d, e, f, g, h, i, j]\n end"
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (*, **k) { k }"
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (a: @a = -> (a: 1) { a }, b:) do\n [a, b]\n end"
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (a, b=1, *c, (*d, (e)), f: 2, g:, h:, **k, &l) do\n [a, b, c, d, e, f, g, h, k, l]\n end"
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> a, b=1, *c, d, e:, f: 2, g:, **k, &l do\n [a, b, c, d, e, f, g, k, l]\n end"
fails:"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda { |(*a, b)| [a, b] }"
fails:"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda do |(a, b, *c, d), (*e, f, g), (*h)|\n [a, b, c, d, e, f, g, h]\n end"
fails:"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda do |a, (b, (c, *d, (e, (*f)), g), (h, (i, j)))|\n [a, b, c, d, e, f, g, h, i, j]\n end"
fails:"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda { |*, **k| k }"
fails:"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda do |a: (@a = -> (a: 1) { a }), b:|\n [a, b]\n end"
fails:"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda do |a, b=1, *c, (*d, (e)), f: 2, g:, h:, **k, &l|\n [a, b, c, d, e, f, g, h, k, l]\n end"
fails:"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda do |a, b=1, *c, d, e:, f: 2, g:, **k, &l|\n [a, b, c, d, e, f, g, k, l]\n end"
fails:A lambda literal -> () { } assigns variables from parameters with circular optional argument reference shadows an existing method with the same name as the argument
3 changes: 0 additions & 3 deletions spec/truffle/tags/language/method_tags.txt
Original file line number Diff line number Diff line change
@@ -13,9 +13,6 @@ fails:"A method assigns local variables from method parameters for definition \n
fails:"A method assigns local variables from method parameters for definition \n def m(a=1, (b, *c), (*d, e))\n [a, b, c, d, e]\n end"
fails:"A method assigns local variables from method parameters for definition \n def m(a=1, (b, *c), (d, (*e, f)))\n [a, b, c, d, e, f]\n end"
fails:"A method assigns local variables from method parameters for definition \n def m(a=1, b: 2) [a, b] end"
fails:"A method assigns local variables from method parameters for definition \n def m(*, **) end"
fails:"A method assigns local variables from method parameters for definition \n def m(*a, **) a end"
fails:"A method assigns local variables from method parameters for definition \n def m(*, **k) k end"
fails:"A method assigns local variables from method parameters for definition \n def m(*a, **k) [a, k] end"
fails:"A method assigns local variables from method parameters for definition \n def m(a: def m(a: 1) a end, b:)\n [a, b]\n end"
fails:"A method assigns local variables from method parameters for definition \n def m(a, b=1, *c, (*d, (e)), f: 2, g:, h:, **k, &l)\n [a, b, c, d, e, f, g, h, k, l]\n end"
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
@@ -28,21 +29,31 @@ public class MethodDefinitionNode extends RubyNode {

private final String name;
private final SharedMethodInfo sharedMethodInfo;

private final CallTarget callTarget;
private final boolean captureBlock;

public MethodDefinitionNode(RubyContext context, SourceSection sourceSection, String name, SharedMethodInfo sharedMethodInfo,
CallTarget callTarget) {
CallTarget callTarget, boolean captureBlock) {
super(context, sourceSection);
this.name = name;
this.sharedMethodInfo = sharedMethodInfo;
this.callTarget = callTarget;
this.captureBlock = captureBlock;
}

public InternalMethod executeMethod(VirtualFrame frame) {
final DynamicObject dummyModule = getContext().getCoreLibrary().getObjectClass();
final Visibility dummyVisibility = Visibility.PUBLIC;
return new InternalMethod(sharedMethodInfo, name, dummyModule, dummyVisibility, callTarget);

final DynamicObject capturedBlock;

if (captureBlock) {
capturedBlock = RubyArguments.getBlock(frame.getArguments());
} else {
capturedBlock = null;
}

return new InternalMethod(sharedMethodInfo, name, dummyModule, dummyVisibility, false, null, callTarget, capturedBlock);
}

@Override
@@ -57,4 +68,5 @@ public String getName() {
public SharedMethodInfo getSharedMethodInfo() {
return sharedMethodInfo;
}

}
Original file line number Diff line number Diff line change
@@ -49,11 +49,16 @@ public final Object execute(VirtualFrame frame) {
argumentsObjects[i] = arguments[i].execute(frame);
}

final DynamicObject block = RubyArguments.getBlock(frame.getArguments());
DynamicObject block = RubyArguments.getBlock(frame.getArguments());

if (block == null) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().noBlockToYieldTo(this));

block = RubyArguments.getMethod(frame.getArguments()).getCapturedBlock();

if (block == null) {
throw new RaiseException(getContext().getCoreLibrary().noBlockToYieldTo(this));
}
}

if (unsplat) {
Original file line number Diff line number Diff line change
@@ -38,19 +38,24 @@ public class InternalMethod implements ObjectGraphNode {
private final DynamicObject proc; // only if method is created from a Proc

private final CallTarget callTarget;
private final DynamicObject capturedBlock;

public static InternalMethod fromProc(SharedMethodInfo sharedMethodInfo, String name, DynamicObject declaringModule,
Visibility visibility, DynamicObject proc, CallTarget callTarget) {
return new InternalMethod(sharedMethodInfo, name, declaringModule, visibility, false, proc, callTarget);
return new InternalMethod(sharedMethodInfo, name, declaringModule, visibility, false, proc, callTarget, null);
}

public InternalMethod(SharedMethodInfo sharedMethodInfo, String name, DynamicObject declaringModule,
Visibility visibility, CallTarget callTarget) {
this(sharedMethodInfo, name, declaringModule, visibility, false, null, callTarget);
this(sharedMethodInfo, name, declaringModule, visibility, false, null, callTarget, null);
}
public InternalMethod(SharedMethodInfo sharedMethodInfo, String name, DynamicObject declaringModule,
Visibility visibility, boolean undefined, DynamicObject proc, CallTarget callTarget) {
this(sharedMethodInfo, name, declaringModule, visibility, undefined, proc, callTarget, null);
}

private InternalMethod(SharedMethodInfo sharedMethodInfo, String name, DynamicObject declaringModule,
Visibility visibility, boolean undefined, DynamicObject proc, CallTarget callTarget) {
public InternalMethod(SharedMethodInfo sharedMethodInfo, String name, DynamicObject declaringModule,
Visibility visibility, boolean undefined, DynamicObject proc, CallTarget callTarget, DynamicObject capturedBlock) {
assert RubyGuards.isRubyModule(declaringModule);
this.sharedMethodInfo = sharedMethodInfo;
this.declaringModule = declaringModule;
@@ -59,6 +64,7 @@ private InternalMethod(SharedMethodInfo sharedMethodInfo, String name, DynamicOb
this.undefined = undefined;
this.proc = proc;
this.callTarget = callTarget;
this.capturedBlock = capturedBlock;
}

public SharedMethodInfo getSharedMethodInfo() {
@@ -91,28 +97,28 @@ public InternalMethod withDeclaringModule(DynamicObject newDeclaringModule) {
if (newDeclaringModule == declaringModule) {
return this;
} else {
return new InternalMethod(sharedMethodInfo, name, newDeclaringModule, visibility, undefined, proc, callTarget);
return new InternalMethod(sharedMethodInfo, name, newDeclaringModule, visibility, undefined, proc, callTarget, capturedBlock);
}
}

public InternalMethod withName(String newName) {
if (newName.equals(name)) {
return this;
} else {
return new InternalMethod(sharedMethodInfo, newName, declaringModule, visibility, undefined, proc, callTarget);
return new InternalMethod(sharedMethodInfo, newName, declaringModule, visibility, undefined, proc, callTarget, capturedBlock);
}
}

public InternalMethod withVisibility(Visibility newVisibility) {
if (newVisibility == visibility) {
return this;
} else {
return new InternalMethod(sharedMethodInfo, name, declaringModule, newVisibility, undefined, proc, callTarget);
return new InternalMethod(sharedMethodInfo, name, declaringModule, newVisibility, undefined, proc, callTarget, capturedBlock);
}
}

public InternalMethod undefined() {
return new InternalMethod(sharedMethodInfo, name, declaringModule, visibility, true, proc, callTarget);
return new InternalMethod(sharedMethodInfo, name, declaringModule, visibility, true, proc, callTarget, capturedBlock);
}

public boolean isVisibleTo(Node currentNode, DynamicObject callerClass) {
@@ -161,4 +167,7 @@ public Set<DynamicObject> getAdjacentObjects() {
return adjacent;
}

public DynamicObject getCapturedBlock() {
return capturedBlock;
}
}
Original file line number Diff line number Diff line change
@@ -797,7 +797,7 @@ public RubyNode visitCaseNode(org.jruby.ast.CaseNode node) {
return addNewlineIfNeeded(node, ret);
}

private RubyNode openModule(SourceSection sourceSection, RubyNode defineOrGetNode, String name, org.jruby.ast.Node bodyNode) {
private RubyNode openModule(SourceSection sourceSection, RubyNode defineOrGetNode, String name, org.jruby.ast.Node bodyNode, boolean sclass) {
LexicalScope newLexicalScope = environment.pushLexicalScope();
try {
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, newLexicalScope, Arity.NO_ARGUMENTS, name, false, null, false, false, false);
@@ -807,7 +807,7 @@ private RubyNode openModule(SourceSection sourceSection, RubyNode defineOrGetNod

final BodyTranslator moduleTranslator = new BodyTranslator(currentNode, context, this, newEnvironment, source, false);

final MethodDefinitionNode definitionMethod = moduleTranslator.compileClassNode(sourceSection, name, bodyNode);
final MethodDefinitionNode definitionMethod = moduleTranslator.compileClassNode(sourceSection, name, bodyNode, sclass);

return new OpenModuleNode(context, sourceSection, defineOrGetNode, definitionMethod, newLexicalScope);
} finally {
@@ -824,7 +824,7 @@ private RubyNode openModule(SourceSection sourceSection, RubyNode defineOrGetNod
* newly allocated module or class.
* </p>
*/
private MethodDefinitionNode compileClassNode(SourceSection sourceSection, String name, org.jruby.ast.Node bodyNode) {
private MethodDefinitionNode compileClassNode(SourceSection sourceSection, String name, org.jruby.ast.Node bodyNode, boolean sclass) {
RubyNode body;

parentSourceSection.push(sourceSection);
@@ -840,12 +840,15 @@ private MethodDefinitionNode compileClassNode(SourceSection sourceSection, Strin

final RubyRootNode rootNode = new RubyRootNode(context, sourceSection, environment.getFrameDescriptor(), environment.getSharedMethodInfo(), body, environment.needsDeclarationFrame());

return new MethodDefinitionNode(
final MethodDefinitionNode definitionNode = new MethodDefinitionNode(
context,
sourceSection,
environment.getSharedMethodInfo().getName(),
environment.getSharedMethodInfo(),
Truffle.getRuntime().createCallTarget(rootNode));
Truffle.getRuntime().createCallTarget(rootNode),
sclass);

return definitionNode;
}

@Override
@@ -865,7 +868,7 @@ public RubyNode visitClassNode(org.jruby.ast.ClassNode node) {

final DefineOrGetClassNode defineOrGetClass = new DefineOrGetClassNode(context, sourceSection, name, lexicalParent, superClass);

final RubyNode ret = openModule(sourceSection, defineOrGetClass, name, node.getBodyNode());
final RubyNode ret = openModule(sourceSection, defineOrGetClass, name, node.getBodyNode(), false);
return addNewlineIfNeeded(node, ret);
}

@@ -1957,7 +1960,7 @@ public RubyNode visitModuleNode(org.jruby.ast.ModuleNode node) {

final DefineOrGetModuleNode defineModuleNode = new DefineOrGetModuleNode(context, sourceSection, name, lexicalParent);

final RubyNode ret = openModule(sourceSection, defineModuleNode, name, node.getBodyNode());
final RubyNode ret = openModule(sourceSection, defineModuleNode, name, node.getBodyNode(), false);
return addNewlineIfNeeded(node, ret);
}

@@ -2675,7 +2678,7 @@ public RubyNode visitSClassNode(org.jruby.ast.SClassNode node) {

final SingletonClassNode singletonClassNode = SingletonClassNodeGen.create(context, sourceSection, receiverNode);

final RubyNode ret = openModule(sourceSection, singletonClassNode, "(singleton-def)", node.getBodyNode());
final RubyNode ret = openModule(sourceSection, singletonClassNode, "(singleton-def)", node.getBodyNode(), true);
return addNewlineIfNeeded(node, ret);
}

Original file line number Diff line number Diff line change
@@ -212,7 +212,7 @@ public MethodDefinitionNode compileMethodNode(SourceSection sourceSection, Strin
context, body.getSourceSection(), environment.getFrameDescriptor(), environment.getSharedMethodInfo(), body, environment.needsDeclarationFrame());

final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
return new MethodDefinitionNode(context, sourceSection, methodName, environment.getSharedMethodInfo(), callTarget);
return new MethodDefinitionNode(context, sourceSection, methodName, environment.getSharedMethodInfo(), callTarget, false);
}

private void declareArguments(SourceSection sourceSection, String methodName, SharedMethodInfo sharedMethodInfo) {