diff --git a/core/src/main/java/org/jruby/truffle/nodes/cast/LambdaNode.java b/core/src/main/java/org/jruby/truffle/nodes/cast/LambdaNode.java index 85998add02a..170f09b5399 100644 --- a/core/src/main/java/org/jruby/truffle/nodes/cast/LambdaNode.java +++ b/core/src/main/java/org/jruby/truffle/nodes/cast/LambdaNode.java @@ -38,7 +38,8 @@ public Object execute(VirtualFrame frame) { return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.LAMBDA, method.getSharedMethodInfo(), method.getCallTarget(), method.getCallTarget(), method.getCallTarget(), - method.getDeclarationFrame(), method.getDeclaringModule(), method, RubyArguments.getSelf(frame.getArguments()), null); + method.getCallTarget(), method.getDeclarationFrame(), method.getDeclaringModule(), method, + RubyArguments.getSelf(frame.getArguments()), null); } @Override diff --git a/core/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java b/core/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java index a3a5e7d6dbc..8b4fad292ad 100644 --- a/core/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java +++ b/core/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java @@ -2510,7 +2510,7 @@ public Object max(VirtualFrame frame, RubyArray array) { final RubyProc block = new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.PROC, maxBlock.getSharedMethodInfo(), maxBlock.getCallTarget(), maxBlock.getCallTarget(), - maxBlock.getCallTarget(), maximumClosureFrame.materialize(), null, null, array, null); + maxBlock.getCallTarget(), maxBlock.getCallTarget(), maximumClosureFrame.materialize(), null, null, array, null); eachNode.call(frame, array, "each", block); @@ -2629,7 +2629,8 @@ public Object min(VirtualFrame frame, RubyArray array) { final RubyProc block = new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.PROC, minBlock.getSharedMethodInfo(), minBlock.getCallTarget(), minBlock.getCallTarget(), - minBlock.getCallTarget(), minimumClosureFrame.materialize(), null, null, array, null); + minBlock.getCallTarget(), minBlock.getCallTarget(), minimumClosureFrame.materialize(), null, + null, array, null); eachNode.call(frame, array, "each", block); diff --git a/core/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java b/core/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java index 063c601ac89..de544890c2c 100644 --- a/core/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java +++ b/core/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java @@ -1239,9 +1239,9 @@ public RubyProc proc(RubyProc block) { notDesignedForCompilation(); return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.LAMBDA, - block.getSharedMethodInfo(), block.getCallTargetForMethods(), block.getCallTargetForMethods(), - block.getCallTargetForMethods(), block.getDeclarationFrame(), block.getDeclaringModule(), - block.getMethod(), block.getSelfCapturedInScope(), block.getBlockCapturedInScope()); + block.getSharedMethodInfo(), block.getCallTargetForLambdas(), block.getCallTargetForLambdas(), + block.getCallTargetForLambdas(), block.getCallTargetForLambdas(), block.getDeclarationFrame(), + block.getDeclaringModule(), block.getMethod(), block.getSelfCapturedInScope(), block.getBlockCapturedInScope()); } } @@ -1487,8 +1487,9 @@ public RubyProc proc(RubyProc block) { return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.PROC, block.getSharedMethodInfo(), block.getCallTargetForProcs(), block.getCallTargetForProcs(), - block.getCallTargetForMethods(), block.getDeclarationFrame(), block.getDeclaringModule(), - block.getMethod(), block.getSelfCapturedInScope(), block.getBlockCapturedInScope()); + block.getCallTargetForLambdas(), block.getCallTargetForMethods(), block.getDeclarationFrame(), + block.getDeclaringModule(), block.getMethod(), block.getSelfCapturedInScope(), + block.getBlockCapturedInScope()); } } diff --git a/core/src/main/java/org/jruby/truffle/nodes/core/ProcNodes.java b/core/src/main/java/org/jruby/truffle/nodes/core/ProcNodes.java index 7e61e8aa191..2c8dd1833fd 100644 --- a/core/src/main/java/org/jruby/truffle/nodes/core/ProcNodes.java +++ b/core/src/main/java/org/jruby/truffle/nodes/core/ProcNodes.java @@ -114,7 +114,7 @@ public InitializeNode(InitializeNode prev) { @Specialization public RubyNilClass initialize(RubyProc proc, RubyProc block) { proc.initialize(block.getSharedMethodInfo(), block.getCallTargetForProcs(), - block.getCallTargetForProcs(), block.getCallTargetForMethods(), block.getDeclarationFrame(), + block.getCallTargetForProcs(), block.getCallTargetForProcs(), block.getCallTargetForMethods(), block.getDeclarationFrame(), block.getDeclaringModule(), block.getMethod(), block.getSelfCapturedInScope(), block.getBlockCapturedInScope()); diff --git a/core/src/main/java/org/jruby/truffle/nodes/methods/BlockDefinitionNode.java b/core/src/main/java/org/jruby/truffle/nodes/methods/BlockDefinitionNode.java index 65387e6c33e..ef657ba63e9 100644 --- a/core/src/main/java/org/jruby/truffle/nodes/methods/BlockDefinitionNode.java +++ b/core/src/main/java/org/jruby/truffle/nodes/methods/BlockDefinitionNode.java @@ -34,18 +34,21 @@ public class BlockDefinitionNode extends RubyNode { private final CallTarget callTargetForBlocks; private final CallTarget callTargetForProcs; + private final CallTarget callTargetForLambdas; private final CallTarget callTargetForMethods; private final boolean requiresDeclarationFrame; public BlockDefinitionNode(RubyContext context, SourceSection sourceSection, SharedMethodInfo sharedMethodInfo, boolean requiresDeclarationFrame, CallTarget callTargetForBlocks, - CallTarget callTargetForProcs, CallTarget callTargetForMethods) { + CallTarget callTargetForProcs, CallTarget callTargetForLambdas, + CallTarget callTargetForMethods) { super(context, sourceSection); this.sharedMethodInfo = sharedMethodInfo; this.callTargetForBlocks = callTargetForBlocks; this.callTargetForProcs = callTargetForProcs; + this.callTargetForLambdas = callTargetForLambdas; this.callTargetForMethods = callTargetForMethods; this.requiresDeclarationFrame = requiresDeclarationFrame; @@ -73,8 +76,8 @@ public Object execute(VirtualFrame frame) { } return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.PROC, sharedMethodInfo, - callTargetForBlocks, callTargetForProcs, callTargetForMethods, declarationFrame, declaringModule, - RubyArguments.getMethod(frame.getArguments()), RubyArguments.getSelf(frame.getArguments()), + callTargetForBlocks, callTargetForProcs, callTargetForLambdas, callTargetForMethods, declarationFrame, + declaringModule, RubyArguments.getMethod(frame.getArguments()), RubyArguments.getSelf(frame.getArguments()), RubyArguments.getBlock(frame.getArguments())); } diff --git a/core/src/main/java/org/jruby/truffle/runtime/core/RubyProc.java b/core/src/main/java/org/jruby/truffle/runtime/core/RubyProc.java index 27059fb681a..6fdaed18600 100644 --- a/core/src/main/java/org/jruby/truffle/runtime/core/RubyProc.java +++ b/core/src/main/java/org/jruby/truffle/runtime/core/RubyProc.java @@ -34,11 +34,9 @@ public static enum Type { private final Type type; @CompilationFinal private SharedMethodInfo sharedMethodInfo; - /** Call target for blocks, which have special arguments destructuring */ @CompilationFinal private CallTarget callTargetForBlocks; - /** Call target for actual Proc arguments, which handle break differently */ @CompilationFinal private CallTarget callTargetForProcs; - /** Call target for lambdas and methods, which have strict arguments destructuring */ + @CompilationFinal private CallTarget callTargetForLambdas; @CompilationFinal private CallTarget callTargetForMethods; @CompilationFinal private MaterializedFrame declarationFrame; @CompilationFinal private RubyModule declaringModule; @@ -52,19 +50,21 @@ public RubyProc(RubyClass procClass, Type type) { } public RubyProc(RubyClass procClass, Type type, SharedMethodInfo sharedMethodInfo, CallTarget callTargetForBlocks, - CallTarget callTargetForProcs, CallTarget callTargetForMethods, MaterializedFrame declarationFrame, - RubyModule declaringModule, MethodLike method, Object self, RubyProc block) { + CallTarget callTargetForProcs, CallTarget callTargetForLambdas, CallTarget callTargetForMethods, + MaterializedFrame declarationFrame, RubyModule declaringModule, MethodLike method, Object self, RubyProc block) { this(procClass, type); - initialize(sharedMethodInfo, callTargetForBlocks, callTargetForProcs, callTargetForMethods, declarationFrame, - declaringModule, method, self, block); + initialize(sharedMethodInfo, callTargetForBlocks, callTargetForProcs, callTargetForLambdas, + callTargetForMethods, declarationFrame, declaringModule, method, self, block); } public void initialize(SharedMethodInfo sharedMethodInfo, CallTarget callTargetForBlocks, CallTarget callTargetForProcs, - CallTarget callTargetForMethods, MaterializedFrame declarationFrame, RubyModule declaringModule, - MethodLike method, Object self, RubyProc block) { + CallTarget callTargetForLambdas, CallTarget callTargetForMethods, + MaterializedFrame declarationFrame, RubyModule declaringModule, MethodLike method, + Object self, RubyProc block) { this.sharedMethodInfo = sharedMethodInfo; this.callTargetForBlocks = callTargetForBlocks; this.callTargetForProcs = callTargetForProcs; + this.callTargetForLambdas = callTargetForLambdas; this.callTargetForMethods = callTargetForMethods; this.declarationFrame = declarationFrame; this.declaringModule = declaringModule; @@ -80,7 +80,7 @@ public CallTarget getCallTargetForType() { case PROC: return callTargetForProcs; case LAMBDA: - return callTargetForMethods; + return callTargetForLambdas; } throw new UnsupportedOperationException(type.toString()); @@ -110,6 +110,10 @@ public CallTarget getCallTargetForProcs() { return callTargetForProcs; } + public CallTarget getCallTargetForLambdas() { + return callTargetForLambdas; + } + public CallTarget getCallTargetForMethods() { return callTargetForMethods; } diff --git a/core/src/main/java/org/jruby/truffle/runtime/core/RubySymbol.java b/core/src/main/java/org/jruby/truffle/runtime/core/RubySymbol.java index 5671b45057c..e286e53a6f6 100644 --- a/core/src/main/java/org/jruby/truffle/runtime/core/RubySymbol.java +++ b/core/src/main/java/org/jruby/truffle/runtime/core/RubySymbol.java @@ -55,7 +55,7 @@ public RubyProc toProc(SourceSection sourceSection, final RubyNode currentNode) final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); return new RubyProc(context.getCoreLibrary().getProcClass(), RubyProc.Type.PROC, sharedMethodInfo, callTarget, - callTarget, callTarget, null, null, null, getContext().getCoreLibrary().getNilObject(), null); + callTarget, callTarget, callTarget, null, null, null, getContext().getCoreLibrary().getNilObject(), null); } public org.jruby.RubySymbol getJRubySymbol() { diff --git a/core/src/main/java/org/jruby/truffle/translator/MethodTranslator.java b/core/src/main/java/org/jruby/truffle/translator/MethodTranslator.java index d968f81db72..844e1949eac 100644 --- a/core/src/main/java/org/jruby/truffle/translator/MethodTranslator.java +++ b/core/src/main/java/org/jruby/truffle/translator/MethodTranslator.java @@ -190,6 +190,8 @@ public RubyNode compileFunctionNode(SourceSection sourceSection, String methodNa behaveAsBlockNode.replace(behaveAsBlockNode.getAsBlock()); } + final CallTarget callTargetAsBlock = Truffle.getRuntime().createCallTarget(newRootNodeForBlocks); + for (BehaveAsProcNode behaveAsProcNode : NodeUtil.findAllNodeInstances(newRootNodeForBlocks, BehaveAsProcNode.class)) { behaveAsProcNode.replace(behaveAsProcNode.getNotAsProc()); } @@ -206,7 +208,17 @@ public RubyNode compileFunctionNode(SourceSection sourceSection, String methodNa final CallTarget callTargetAsProc = Truffle.getRuntime().createCallTarget(newRootNodeForProcs); - final CallTarget callTargetAsBlock = Truffle.getRuntime().createCallTarget(newRootNodeForBlocks); + final RubyRootNode newRootNodeForLambdas = rootNode.cloneRubyRootNode(); + + for (BehaveAsBlockNode behaveAsBlockNode : NodeUtil.findAllNodeInstances(newRootNodeForLambdas, BehaveAsBlockNode.class)) { + behaveAsBlockNode.replace(behaveAsBlockNode.getAsBlock()); + } + + for (BehaveAsProcNode behaveAsProcNode : NodeUtil.findAllNodeInstances(newRootNodeForLambdas, BehaveAsProcNode.class)) { + behaveAsProcNode.replace(behaveAsProcNode.getAsProc()); + } + + final CallTarget callTargetAsLambda = Truffle.getRuntime().createCallTarget(newRootNodeForLambdas); final RubyRootNode newRootNodeForMethods = rootNode.cloneRubyRootNode(); @@ -229,7 +241,7 @@ public RubyNode compileFunctionNode(SourceSection sourceSection, String methodNa final CallTarget callTargetAsMethod = Truffle.getRuntime().createCallTarget(newRootNodeWithCatchReturn); return new BlockDefinitionNode(context, sourceSection, environment.getSharedMethodInfo(), - environment.needsDeclarationFrame(), callTargetAsBlock, callTargetAsProc, callTargetAsMethod); + environment.needsDeclarationFrame(), callTargetAsBlock, callTargetAsProc, callTargetAsLambda, callTargetAsMethod); } else { return new MethodDefinitionNode(context, sourceSection, methodName, environment.getSharedMethodInfo(), environment.needsDeclarationFrame(), Truffle.getRuntime().createCallTarget(rootNode)); diff --git a/spec/truffle/tags/language/block_tags.txt b/spec/truffle/tags/language/block_tags.txt index 397c781f748..1e461f2be9d 100644 --- a/spec/truffle/tags/language/block_tags.txt +++ b/spec/truffle/tags/language/block_tags.txt @@ -17,3 +17,4 @@ 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:Block-local variables override shadowed variables from the outer scope +fails:Post-args are required