Skip to content

Commit 0f2234e

Browse files
authored
Change Painless function node to use a block instead of raw statements (#46884)
This change improves the node structure of SFunction. SFunction now uses an SBlock instead of a List of AStatments reducing code duplication and gives a future target for symbol table scoping.
1 parent f4c2964 commit 0f2234e

File tree

5 files changed

+23
-40
lines changed

5 files changed

+23
-40
lines changed

modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ public ANode visitFunction(FunctionContext ctx) {
272272
statements.add((AStatement)visit(ctx.block().dstatement()));
273273
}
274274

275-
return new SFunction(location(ctx), rtnType, name, paramTypes, paramNames, statements, false);
275+
return new SFunction(location(ctx), rtnType, name, paramTypes, paramNames, new SBlock(location(ctx), statements), false);
276276
}
277277

278278
@Override

modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ void analyze(Locals locals) {
175175

176176
// desugar lambda body into a synthetic method
177177
String name = locals.getNextSyntheticName();
178-
desugared = new SFunction(
179-
location, PainlessLookupUtility.typeToCanonicalTypeName(returnType), name, paramTypes, paramNames, statements, true);
178+
desugared = new SFunction(location, PainlessLookupUtility.typeToCanonicalTypeName(returnType), name, paramTypes, paramNames,
179+
new SBlock(location, statements), true);
180180
desugared.storeSettings(settings);
181181
desugared.generateSignature(locals.getPainlessLookup());
182182
desugared.analyze(Locals.newLambdaScope(locals.getProgramScope(), desugared.name, returnType,

modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArrayFunctionRef.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.objectweb.asm.Type;
2929

3030
import java.util.Arrays;
31+
import java.util.Collections;
3132
import java.util.Objects;
3233
import java.util.Set;
3334

@@ -61,9 +62,11 @@ void extractVariables(Set<String> variables) {
6162

6263
@Override
6364
void analyze(Locals locals) {
64-
SReturn code = new SReturn(location, new ENewArray(location, type, Arrays.asList(new EVariable(location, "size")), false));
65+
SReturn code = new SReturn(location,
66+
new ENewArray(location, type, Arrays.asList(new EVariable(location, "size")), false));
6567
function = new SFunction(location, type, locals.getNextSyntheticName(),
66-
Arrays.asList("int"), Arrays.asList("size"), Arrays.asList(code), true);
68+
Collections.singletonList("int"), Collections.singletonList("size"),
69+
new SBlock(location, Collections.singletonList(code)), true);
6770
function.storeSettings(settings);
6871
function.generateSignature(locals.getPainlessLookup());
6972
function.extractVariables(null);

modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
*/
3737
public final class SBlock extends AStatement {
3838

39-
private final List<AStatement> statements;
39+
final List<AStatement> statements;
4040

4141
public SBlock(Location location, List<AStatement> statements) {
4242
super(location);

modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public final class SFunction extends AStatement {
5050
public final String name;
5151
private final List<String> paramTypeStrs;
5252
private final List<String> paramNameStrs;
53-
private final List<AStatement> statements;
53+
private final SBlock block;
5454
public final boolean synthetic;
5555

5656
private CompilerSettings settings;
@@ -65,35 +65,31 @@ public final class SFunction extends AStatement {
6565
private Variable loop = null;
6666

6767
public SFunction(Location location, String rtnType, String name,
68-
List<String> paramTypes, List<String> paramNames, List<AStatement> statements,
68+
List<String> paramTypes, List<String> paramNames, SBlock block,
6969
boolean synthetic) {
7070
super(location);
7171

7272
this.rtnTypeStr = Objects.requireNonNull(rtnType);
7373
this.name = Objects.requireNonNull(name);
7474
this.paramTypeStrs = Collections.unmodifiableList(paramTypes);
7575
this.paramNameStrs = Collections.unmodifiableList(paramNames);
76-
this.statements = Collections.unmodifiableList(statements);
76+
this.block = Objects.requireNonNull(block);
7777
this.synthetic = synthetic;
7878
}
7979

8080
@Override
8181
void storeSettings(CompilerSettings settings) {
82-
for (AStatement statement : statements) {
83-
statement.storeSettings(settings);
84-
}
82+
block.storeSettings(settings);
8583

8684
this.settings = settings;
8785
}
8886

8987
@Override
9088
void extractVariables(Set<String> variables) {
91-
for (AStatement statement : statements) {
92-
// we reset the list for function scope
93-
// note this is not stored for this node
94-
// but still required for lambdas
95-
statement.extractVariables(new HashSet<>());
96-
}
89+
// we reset the list for function scope
90+
// note this is not stored for this node
91+
// but still required for lambdas
92+
block.extractVariables(new HashSet<>());
9793
}
9894

9995
void generateSignature(PainlessLookup painlessLookup) {
@@ -131,28 +127,14 @@ void generateSignature(PainlessLookup painlessLookup) {
131127

132128
@Override
133129
void analyze(Locals locals) {
134-
if (statements == null || statements.isEmpty()) {
130+
if (block.statements.isEmpty()) {
135131
throw createError(new IllegalArgumentException("Cannot generate an empty function [" + name + "]."));
136132
}
137133

138134
locals = Locals.newLocalScope(locals);
139-
140-
AStatement last = statements.get(statements.size() - 1);
141-
142-
for (AStatement statement : statements) {
143-
// Note that we do not need to check after the last statement because
144-
// there is no statement that can be unreachable after the last.
145-
if (allEscape) {
146-
throw createError(new IllegalArgumentException("Unreachable statement."));
147-
}
148-
149-
statement.lastSource = statement == last;
150-
151-
statement.analyze(locals);
152-
153-
methodEscape = statement.methodEscape;
154-
allEscape = statement.allEscape;
155-
}
135+
block.lastSource = true;
136+
block.analyze(locals);
137+
methodEscape = block.methodEscape;
156138

157139
if (!methodEscape && returnType != void.class) {
158140
throw createError(new IllegalArgumentException("Not all paths provide a return value for method [" + name + "]."));
@@ -184,9 +166,7 @@ void write(MethodWriter function, Globals globals) {
184166
function.visitVarInsn(Opcodes.ISTORE, loop.getSlot());
185167
}
186168

187-
for (AStatement statement : statements) {
188-
statement.write(function, globals);
189-
}
169+
block.write(function, globals);
190170

191171
if (!methodEscape) {
192172
if (returnType == void.class) {
@@ -205,6 +185,6 @@ public String toString() {
205185
if (false == (paramTypeStrs.isEmpty() && paramNameStrs.isEmpty())) {
206186
description.add(joinWithName("Args", pairwiseToString(paramTypeStrs, paramNameStrs), emptyList()));
207187
}
208-
return multilineToString(description, statements);
188+
return multilineToString(description, block.statements);
209189
}
210190
}

0 commit comments

Comments
 (0)