Skip to content

Commit 5c3e58d

Browse files
committed
Translate ForwardingSuperNode
1 parent b013c2e commit 5c3e58d

File tree

7 files changed

+233
-21
lines changed

7 files changed

+233
-21
lines changed

src/main/java/org/truffleruby/language/arguments/ReadKeywordArgumentNode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ public static ReadKeywordArgumentNode create(RubySymbol name, RubyNode defaultVa
4040
return ReadKeywordArgumentNodeGen.create(name, defaultValue);
4141
}
4242

43+
public RubySymbol getName() {
44+
return name;
45+
}
46+
4347
@Override
4448
public final Object execute(VirtualFrame frame) {
4549
return execute(frame, readUserKeywordsHashNode.execute(frame));

src/main/java/org/truffleruby/language/supercall/ZSuperOutsideMethodNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public ZSuperOutsideMethodNode(boolean insideDefineMethod) {
3232
}
3333

3434
@Override
35-
public final Object execute(VirtualFrame frame) {
35+
public Object execute(VirtualFrame frame) {
3636
// This is MRI behavior
3737
if (insideDefineMethod) { // TODO (eregon, 22 July 2015): This check should be more dynamic.
3838
throw new RaiseException(getContext(), coreExceptions().runtimeError(

src/main/java/org/truffleruby/parser/ReloadArgumentsTranslator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public RubyNode[] reload(ArgsParseNode node) {
101101

102102
RubyNode kwArgsNode = null;
103103

104-
if (node.hasKwargs()) {
104+
if (node.getKeywordCount() > 0) {
105105
final int keywordIndex = node.getKeywordsIndex();
106106
final int keywordCount = node.getKeywordCount();
107107
RubyNode[] keyValues = new RubyNode[keywordCount * 2];

src/main/java/org/truffleruby/parser/TranslatorEnvironment.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.concurrent.atomic.AtomicInteger;
1616

1717
import com.oracle.truffle.api.Assumption;
18+
import org.prism.Nodes;
1819
import org.truffleruby.Layouts;
1920
import com.oracle.truffle.api.CompilerDirectives;
2021
import com.oracle.truffle.api.frame.FrameSlotKind;
@@ -85,6 +86,10 @@ public final class TranslatorEnvironment {
8586

8687
public final String modulePath;
8788
public final String methodName;
89+
/** Only set for literal blocks passed to a method, e.g. "foo" for `foo { ... }` */
90+
public String literalBlockPassedToMethod = null;
91+
/** Only set for def methods */
92+
public Nodes.ParametersNode parametersNode = null;
8893

8994
// TODO(CS): overflow? and it should be per-context, or even more local
9095
private static final AtomicInteger tempIndex = new AtomicInteger();
@@ -241,10 +246,12 @@ public int declareLocalTemp(String indicator) {
241246
}
242247

243248
public Integer findFrameSlotOrNull(Object name) {
249+
assert name != null;
244250
return nameToIndex.get(name);
245251
}
246252

247253
public int findFrameSlot(Object name) {
254+
assert name != null;
248255
Integer index = nameToIndex.get(name);
249256
if (index == null) {
250257
throw CompilerDirectives.shouldNotReachHere("Could not find slot " + name);
@@ -279,6 +286,7 @@ public RubyNode findLocalVarOrNilNode(String name, SourceIndexLength sourceSecti
279286
}
280287

281288
public ReadLocalNode findLocalVarNode(String name, SourceIndexLength sourceSection) {
289+
assert name != null;
282290
TranslatorEnvironment current = this;
283291
int level = 0;
284292

src/main/java/org/truffleruby/parser/YARPBlockNodeTranslator.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
public final class YARPBlockNodeTranslator extends YARPTranslator {
4747
private final Nodes.ParametersNode parameters;
4848
private final Arity arity;
49-
private final String currentCallMethodName;
5049

5150
public YARPBlockNodeTranslator(
5251
RubyLanguage language,
@@ -57,12 +56,10 @@ public YARPBlockNodeTranslator(
5756
Node currentNode,
5857
RubyDeferredWarnings rubyWarnings,
5958
Nodes.ParametersNode parameters,
60-
Arity arity,
61-
String currentCallMethodName) {
59+
Arity arity) {
6260
super(language, environment, sourceBytes, source, parserContext, currentNode, rubyWarnings);
6361
this.parameters = parameters;
6462
this.arity = arity;
65-
this.currentCallMethodName = currentCallMethodName;
6663
}
6764

6865
public RubyNode compileBlockNode(Nodes.Node body, String[] locals, boolean isStabbyLambda,
@@ -90,7 +87,7 @@ public RubyNode compileBlockNode(Nodes.Node body, String[] locals, boolean isSta
9087

9188
final RubyNode bodyNode = translateNodeOrNil(body).simplifyAsTailExpression();
9289

93-
final boolean isLambdaMethodCall = !isStabbyLambda && currentCallMethodName.equals("lambda");
90+
final boolean isLambdaMethodCall = !isStabbyLambda && environment.literalBlockPassedToMethod.equals("lambda");
9491
final boolean emitLambda = isStabbyLambda || isLambdaMethodCall;
9592

9693
final Supplier<RootCallTarget> procCompiler = procCompiler(
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
* Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 2.0, or
7+
* GNU General Public License version 2, or
8+
* GNU Lesser General Public License version 2.1.
9+
*/
10+
package org.truffleruby.parser;
11+
12+
import java.util.ArrayList;
13+
import java.util.List;
14+
15+
import org.prism.AbstractNodeVisitor;
16+
import org.prism.Nodes;
17+
import org.truffleruby.RubyLanguage;
18+
import org.truffleruby.core.hash.ConcatHashLiteralNode;
19+
import org.truffleruby.core.hash.HashLiteralNode;
20+
import org.truffleruby.language.RubyNode;
21+
import org.truffleruby.language.arguments.MissingArgumentBehavior;
22+
import org.truffleruby.language.arguments.ReadKeywordArgumentNode;
23+
import org.truffleruby.language.arguments.ReadPreArgumentNode;
24+
import org.truffleruby.language.literal.NilLiteralNode;
25+
import org.truffleruby.language.literal.ObjectLiteralNode;
26+
27+
28+
/** Produces code to reload arguments from local variables back into the arguments array. Only works for simple cases.
29+
* Used for zsuper calls which pass the same arguments, but will pick up modifications made to them in the method so
30+
* far. */
31+
public final class YARPReloadArgumentsTranslator extends AbstractNodeVisitor<RubyNode> {
32+
33+
private final RubyLanguage language;
34+
private final YARPTranslator yarpTranslator;
35+
private final boolean hasKeywordArguments;
36+
37+
private int index = 0;
38+
private int restParameterIndex = -1;
39+
40+
public YARPReloadArgumentsTranslator(
41+
RubyLanguage language,
42+
YARPTranslator yarpTranslator,
43+
Nodes.ParametersNode parametersNode) {
44+
this.language = language;
45+
this.yarpTranslator = yarpTranslator;
46+
this.hasKeywordArguments = parametersNode.keywords.length > 0 || parametersNode.keyword_rest != null;
47+
}
48+
49+
public int getRestParameterIndex() {
50+
return restParameterIndex;
51+
}
52+
53+
public RubyNode[] reload(Nodes.ParametersNode parametersNode) {
54+
final List<RubyNode> sequence = new ArrayList<>();
55+
56+
for (var node : parametersNode.requireds) {
57+
sequence.add(node.accept(this)); // Nodes.RequiredParameterNode is expected here
58+
index++;
59+
}
60+
61+
for (var node : parametersNode.optionals) {
62+
sequence.add(node.accept(this)); // Nodes.OptionalParameterNode is expected here
63+
index++;
64+
}
65+
66+
if (parametersNode.rest != null) {
67+
restParameterIndex = index;
68+
sequence.add(parametersNode.rest.accept(this)); // Nodes.RestParameterNode is expected here
69+
}
70+
71+
int postCount = parametersNode.posts.length;
72+
if (postCount > 0) {
73+
index = -postCount;
74+
for (var node : parametersNode.posts) {
75+
sequence.add(node.accept(this)); // Nodes.RequiredParameterNode is expected here
76+
index++;
77+
}
78+
}
79+
80+
RubyNode kwArgsNode = null;
81+
82+
if (parametersNode.keywords.length > 0) {
83+
final int keywordCount = parametersNode.keywords.length;
84+
RubyNode[] keyValues = new RubyNode[keywordCount * 2];
85+
86+
for (int i = 0; i < keywordCount; i++) {
87+
// Nodes.RequiredKeywordParameterNode/Nodes.OptionalKeywordParameterNode are expected here
88+
final Nodes.Node kwArg = parametersNode.keywords[i];
89+
final RubyNode value = kwArg.accept(this);
90+
var name = ((ReadKeywordArgumentNode) value).getName();
91+
RubyNode key = new ObjectLiteralNode(name);
92+
keyValues[2 * i] = key;
93+
keyValues[2 * i + 1] = value;
94+
}
95+
kwArgsNode = HashLiteralNode.create(keyValues);
96+
}
97+
98+
if (parametersNode.keyword_rest != null) {
99+
// Nodes.KeywordRestParameterNode/Nodes.NoKeywordsParameterNode are expected here
100+
final RubyNode keyRest = parametersNode.keyword_rest.accept(this);
101+
if (kwArgsNode == null) {
102+
kwArgsNode = keyRest;
103+
} else {
104+
kwArgsNode = new ConcatHashLiteralNode(new RubyNode[]{ kwArgsNode, keyRest });
105+
}
106+
107+
}
108+
109+
if (kwArgsNode != null) {
110+
sequence.add(kwArgsNode);
111+
}
112+
113+
return sequence.toArray(RubyNode.EMPTY_ARRAY);
114+
}
115+
116+
@Override
117+
public RubyNode visitRequiredParameterNode(Nodes.RequiredParameterNode node) {
118+
return yarpTranslator.getEnvironment().findLocalVarNode(node.name, null);
119+
}
120+
121+
@Override
122+
public RubyNode visitOptionalParameterNode(Nodes.OptionalParameterNode node) {
123+
return yarpTranslator.getEnvironment().findLocalVarNode(node.name, null);
124+
}
125+
126+
@Override
127+
public RubyNode visitMultiTargetNode(Nodes.MultiTargetNode node) {
128+
return Translator.profileArgument(language,
129+
new ReadPreArgumentNode(index, hasKeywordArguments, MissingArgumentBehavior.NIL));
130+
}
131+
132+
@Override
133+
public RubyNode visitRestParameterNode(Nodes.RestParameterNode node) {
134+
return yarpTranslator.getEnvironment().findLocalVarNode(node.name, null);
135+
}
136+
137+
@Override
138+
public RubyNode visitRequiredKeywordParameterNode(Nodes.RequiredKeywordParameterNode node) {
139+
return yarpTranslator.getEnvironment().findLocalVarNode(node.name, null);
140+
}
141+
142+
@Override
143+
public RubyNode visitOptionalKeywordParameterNode(Nodes.OptionalKeywordParameterNode node) {
144+
return yarpTranslator.getEnvironment().findLocalVarNode(node.name, null);
145+
}
146+
147+
@Override
148+
public RubyNode visitKeywordRestParameterNode(Nodes.KeywordRestParameterNode node) {
149+
return yarpTranslator.getEnvironment().findLocalVarNode(node.name, null);
150+
}
151+
152+
@Override
153+
public RubyNode visitNoKeywordsParameterNode(Nodes.NoKeywordsParameterNode node) {
154+
return defaultVisit(node);
155+
}
156+
157+
@Override
158+
protected RubyNode defaultVisit(Nodes.Node node) {
159+
var nilNode = new NilLiteralNode();
160+
return YARPTranslator.assignPositionAndFlags(node, nilNode);
161+
}
162+
163+
}

0 commit comments

Comments
 (0)