You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/11/27 14:17:44 UTC
[groovy] branch master updated: Minor refactoring: simplify code of tail recursive transformation
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 6993045 Minor refactoring: simplify code of tail recursive transformation
6993045 is described below
commit 6993045f820f8854438208e732b734e5238438dd
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sat Nov 27 20:59:40 2021 +0800
Minor refactoring: simplify code of tail recursive transformation
---
.../transform/tailrec/InWhileLoopWrapper.java | 17 +++--
.../transform/tailrec/RecursivenessTester.java | 6 +-
.../ReturnStatementToIterationConverter.java | 69 ++++++++---------
.../transform/tailrec/StatementReplacer.java | 58 ++++----------
.../tailrec/TailRecursiveASTTransformation.java | 89 +++++++++-------------
.../tailrec/TernaryToIfStatementConverter.java | 3 +-
.../tailrec/VariableExpressionReplacer.java | 3 +-
7 files changed, 98 insertions(+), 147 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/tailrec/InWhileLoopWrapper.java b/src/main/java/org/codehaus/groovy/transform/tailrec/InWhileLoopWrapper.java
index baed933..69a7c07 100644
--- a/src/main/java/org/codehaus/groovy/transform/tailrec/InWhileLoopWrapper.java
+++ b/src/main/java/org/codehaus/groovy/transform/tailrec/InWhileLoopWrapper.java
@@ -27,11 +27,16 @@ import org.codehaus.groovy.ast.stmt.EmptyStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.ast.stmt.TryCatchStatement;
import org.codehaus.groovy.ast.stmt.WhileStatement;
-import org.codehaus.groovy.ast.tools.GeneralUtils;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import java.util.List;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.boolX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.catchS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.tryCatchS;
+
/**
* Wrap the body of a method in a while loop, nested in a try-catch.
* This is the first step in making a tail recursive method iterative.
@@ -44,13 +49,13 @@ import java.util.List;
*/
public class InWhileLoopWrapper {
public void wrap(MethodNode method) {
- BlockStatement oldBody = DefaultGroovyMethods.asType(method.getCode(), BlockStatement.class);
- TryCatchStatement tryCatchStatement = GeneralUtils.tryCatchS(oldBody, EmptyStatement.INSTANCE, GeneralUtils.catchS(GeneralUtils.param(ClassHelper.make(GotoRecurHereException.class), "ignore"), new ContinueStatement(InWhileLoopWrapper.LOOP_LABEL)));
+ BlockStatement oldBody = (BlockStatement) method.getCode();
+ TryCatchStatement tryCatchStatement = tryCatchS(oldBody, EmptyStatement.INSTANCE, catchS(param(ClassHelper.make(GotoRecurHereException.class), "ignore"), new ContinueStatement(InWhileLoopWrapper.LOOP_LABEL)));
- WhileStatement whileLoop = new WhileStatement(GeneralUtils.boolX(GeneralUtils.constX(true)), GeneralUtils.block(new VariableScope(method.getVariableScope()), tryCatchStatement));
+ WhileStatement whileLoop = new WhileStatement(boolX(constX(true)), block(new VariableScope(method.getVariableScope()), tryCatchStatement));
List<Statement> whileLoopStatements = ((BlockStatement) whileLoop.getLoopBlock()).getStatements();
if (whileLoopStatements.size() > 0) whileLoopStatements.get(0).setStatementLabel(LOOP_LABEL);
- BlockStatement newBody = GeneralUtils.block(new VariableScope(method.getVariableScope()));
+ BlockStatement newBody = block(new VariableScope(method.getVariableScope()));
newBody.addStatement(whileLoop);
method.setCode(newBody);
}
diff --git a/src/main/java/org/codehaus/groovy/transform/tailrec/RecursivenessTester.java b/src/main/java/org/codehaus/groovy/transform/tailrec/RecursivenessTester.java
index 592b50c..13f094a 100644
--- a/src/main/java/org/codehaus/groovy/transform/tailrec/RecursivenessTester.java
+++ b/src/main/java/org/codehaus/groovy/transform/tailrec/RecursivenessTester.java
@@ -29,13 +29,13 @@ import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
+import static org.codehaus.groovy.runtime.DefaultGroovyMethods.invokeMethod;
import static org.codehaus.groovy.runtime.DefaultGroovyMethods.transpose;
/**
@@ -87,7 +87,7 @@ public class RecursivenessTester {
return false;
}
- return ((boolean) (DefaultGroovyMethods.invokeMethod(call.getObjectExpression(), "isThisExpression", new Object[0])));
+ return ((boolean) (invokeMethod(call.getObjectExpression(), "isThisExpression", EMPTY_OBJECT_ARRAY)));
}
private boolean methodParamsMatchCallArgs(MethodNode method, Expression call) {
@@ -118,4 +118,6 @@ public class RecursivenessTester {
ClassNode boxedParam = ClassHelper.getWrapper(paramType);
return boxedArg.isDerivedFrom(boxedParam) || boxedParam.isDerivedFrom(boxedArg);
}
+
+ private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
}
diff --git a/src/main/java/org/codehaus/groovy/transform/tailrec/ReturnStatementToIterationConverter.java b/src/main/java/org/codehaus/groovy/transform/tailrec/ReturnStatementToIterationConverter.java
index 7f4beaf..e1c37bc 100644
--- a/src/main/java/org/codehaus/groovy/transform/tailrec/ReturnStatementToIterationConverter.java
+++ b/src/main/java/org/codehaus/groovy/transform/tailrec/ReturnStatementToIterationConverter.java
@@ -18,7 +18,6 @@
*/
package org.codehaus.groovy.transform.tailrec;
-import groovy.lang.Closure;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.expr.BinaryExpression;
import org.codehaus.groovy.ast.expr.Expression;
@@ -29,14 +28,17 @@ import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.codehaus.groovy.ast.stmt.Statement;
-import org.codehaus.groovy.ast.tools.GeneralUtils;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static org.codehaus.groovy.runtime.DefaultGroovyMethods.minus;
/**
* Translates all return statements into an invocation of the next iteration. This can be either
@@ -57,13 +59,13 @@ public class ReturnStatementToIterationConverter {
this.recurStatement = recurStatement;
}
- public Statement convert(ReturnStatement statement, final Map<Integer, Map> positionMapping) {
+ public Statement convert(ReturnStatement statement, final Map<Integer, Map<String, Object>> positionMapping) {
Expression recursiveCall = statement.getExpression();
if (!isAMethodCalls(recursiveCall)) return statement;
- final Map<String, Map> tempMapping = new LinkedHashMap<String, Map>();
+ final Map<String, Map<String, Object>> tempMapping = new LinkedHashMap<>();
final Map<String, ExpressionStatement> tempDeclarations = new LinkedHashMap<>();
- final List<ExpressionStatement> argAssignments = new ArrayList<ExpressionStatement>();
+ final List<ExpressionStatement> argAssignments = new ArrayList<>();
final BlockStatement result = new BlockStatement();
result.copyStatementLabels(statement);
@@ -71,25 +73,20 @@ public class ReturnStatementToIterationConverter {
/* Create temp declarations for all method arguments.
* Add the declarations and var mapping to tempMapping and tempDeclarations for further reference.
*/
- DefaultGroovyMethods.eachWithIndex(getArguments(recursiveCall), new Closure<Void>(this, this) {
- public void doCall(Expression expression, int index) {
- ExpressionStatement tempDeclaration = createTempDeclaration(index, positionMapping, tempMapping, tempDeclarations);
- result.addStatement(tempDeclaration);
- }
-
- });
+ final List<Expression> arguments = getArguments(recursiveCall);
+ for (int i = 0, n = arguments.size(); i < n; i++) {
+ ExpressionStatement tempDeclaration = createTempDeclaration(i, positionMapping, tempMapping, tempDeclarations);
+ result.addStatement(tempDeclaration);
+ }
/*
* Assign the iteration variables their new value before recuring
*/
- DefaultGroovyMethods.eachWithIndex(getArguments(recursiveCall), new Closure<Void>(this, this) {
- public void doCall(Expression expression, int index) {
- ExpressionStatement argAssignment = createAssignmentToIterationVariable(expression, index, positionMapping);
- argAssignments.add(argAssignment);
- result.addStatement(argAssignment);
- }
-
- });
+ for (int i = 0, n = arguments.size(); i < n; i++) {
+ ExpressionStatement argAssignment = createAssignmentToIterationVariable(arguments.get(i), i, positionMapping);
+ argAssignments.add(argAssignment);
+ result.addStatement(argAssignment);
+ }
Set<String> unusedTemps = replaceAllArgUsages(argAssignments, tempMapping);
for (String temp : unusedTemps) {
@@ -101,19 +98,19 @@ public class ReturnStatementToIterationConverter {
return result;
}
- private ExpressionStatement createAssignmentToIterationVariable(Expression expression, int index, Map<Integer, Map> positionMapping) {
+ private ExpressionStatement createAssignmentToIterationVariable(Expression expression, int index, Map<Integer, Map<String, Object>> positionMapping) {
String argName = (String) positionMapping.get(index).get("name");
- ClassNode argAndTempType = DefaultGroovyMethods.asType(positionMapping.get(index).get("type"), ClassNode.class);
- ExpressionStatement argAssignment = (ExpressionStatement) GeneralUtils.assignS(GeneralUtils.varX(argName, argAndTempType), expression);
+ ClassNode argAndTempType = (ClassNode) positionMapping.get(index).get("type");
+ ExpressionStatement argAssignment = (ExpressionStatement) assignS(varX(argName, argAndTempType), expression);
return argAssignment;
}
- private ExpressionStatement createTempDeclaration(int index, Map<Integer, Map> positionMapping, Map<String, Map> tempMapping, Map<String, ExpressionStatement> tempDeclarations) {
- final String argName = (String) positionMapping.get(index).get("name");
+ private ExpressionStatement createTempDeclaration(int index, Map<Integer, Map<String, Object>> positionMapping, Map<String, Map<String, Object>> tempMapping, Map<String, ExpressionStatement> tempDeclarations) {
+ String argName = (String) positionMapping.get(index).get("name");
+ ClassNode argAndTempType = (ClassNode) positionMapping.get(index).get("type");
String tempName = "_" + argName + "_";
- ClassNode argAndTempType = DefaultGroovyMethods.asType(positionMapping.get(index).get("type"), ClassNode.class);
ExpressionStatement tempDeclaration = AstHelper.createVariableAlias(tempName, argAndTempType, argName);
- Map<String, Object> map = new LinkedHashMap<String, Object>(2);
+ Map<String, Object> map = new LinkedHashMap<>(2);
map.put("name", tempName);
map.put("type", argAndTempType);
tempMapping.put(argName, map);
@@ -135,19 +132,13 @@ public class ReturnStatementToIterationConverter {
return MethodCallExpression.class == clazz || StaticMethodCallExpression.class == clazz;
}
- private Set<String> replaceAllArgUsages(List<ExpressionStatement> iterationVariablesAssignmentNodes, Map<String, Map> tempMapping) {
- Set<String> unusedTempNames = DefaultGroovyMethods.asType(DefaultGroovyMethods.collect(tempMapping.values(), new Closure<String>(this, this) {
- public String doCall(Map nameAndType) {
- return (String) nameAndType.get("name");
- }
-
- }), Set.class);
- VariableReplacedListener tracker = new UsedVariableTracker();
+ private Set<String> replaceAllArgUsages(List<ExpressionStatement> iterationVariablesAssignmentNodes, Map<String, Map<String, Object>> tempMapping) {
+ Set<String> unusedTempNames = tempMapping.values().stream().map(nameAndType -> (String) nameAndType.get("name")).collect(Collectors.toSet());
+ UsedVariableTracker tracker = new UsedVariableTracker();
for (ExpressionStatement statement : iterationVariablesAssignmentNodes) {
- replaceArgUsageByTempUsage((BinaryExpression) statement.getExpression(), tempMapping, (UsedVariableTracker) tracker);
+ replaceArgUsageByTempUsage((BinaryExpression) statement.getExpression(), tempMapping, tracker);
}
-
- unusedTempNames = DefaultGroovyMethods.minus(unusedTempNames, ((UsedVariableTracker) tracker).getUsedVariableNames());
+ unusedTempNames = minus(unusedTempNames, tracker.getUsedVariableNames());
return unusedTempNames;
}
diff --git a/src/main/java/org/codehaus/groovy/transform/tailrec/StatementReplacer.java b/src/main/java/org/codehaus/groovy/transform/tailrec/StatementReplacer.java
index d404006..32831ea 100644
--- a/src/main/java/org/codehaus/groovy/transform/tailrec/StatementReplacer.java
+++ b/src/main/java/org/codehaus/groovy/transform/tailrec/StatementReplacer.java
@@ -28,10 +28,10 @@ import org.codehaus.groovy.ast.stmt.ForStatement;
import org.codehaus.groovy.ast.stmt.IfStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.ast.stmt.WhileStatement;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Consumer;
/**
* Tool for replacing Statement objects in an AST by other Statement instances.
@@ -58,72 +58,42 @@ public class StatementReplacer extends CodeVisitorSupport {
}
public void visitBlockStatement(final BlockStatement block) {
- List<Statement> copyOfStatements = new ArrayList<Statement>(block.getStatements());
- DefaultGroovyMethods.eachWithIndex(copyOfStatements, new Closure<Void>(this, this) {
- public void doCall(Statement statement, final int index) {
- replaceIfNecessary(statement, new Closure<Statement>(StatementReplacer.this, StatementReplacer.this) {
- public Statement doCall(Statement node) {
- block.getStatements().set(index, node);
- return node;
- }
- });
- }
- });
+ List<Statement> copyOfStatements = new ArrayList<>(block.getStatements());
+ for (int i = 0, n = copyOfStatements.size(); i < n; i++) {
+ final int index = i;
+ Statement statement = copyOfStatements.get(index);
+ replaceIfNecessary(statement, (Statement node) -> block.getStatements().set(index, node));
+ }
super.visitBlockStatement(block);
}
public void visitIfElse(final IfStatement ifElse) {
- replaceIfNecessary(ifElse.getIfBlock(), new Closure<Statement>(this, this) {
- public Statement doCall(Statement s) {
- ifElse.setIfBlock(s);
- return s;
- }
- });
- replaceIfNecessary(ifElse.getElseBlock(), new Closure<Statement>(this, this) {
- public Statement doCall(Statement s) {
- ifElse.setElseBlock(s);
- return s;
- }
- });
+ replaceIfNecessary(ifElse.getIfBlock(), ifElse::setIfBlock);
+ replaceIfNecessary(ifElse.getElseBlock(), ifElse::setElseBlock);
super.visitIfElse(ifElse);
}
public void visitForLoop(final ForStatement forLoop) {
- replaceIfNecessary(forLoop.getLoopBlock(), new Closure<Statement>(this, this) {
- public Statement doCall(Statement s) {
- forLoop.setLoopBlock(s);
- return s;
- }
- });
+ replaceIfNecessary(forLoop.getLoopBlock(), forLoop::setLoopBlock);
super.visitForLoop(forLoop);
}
public void visitWhileLoop(final WhileStatement loop) {
- replaceIfNecessary(loop.getLoopBlock(), new Closure<Statement>(this, this) {
- public Statement doCall(Statement s) {
- loop.setLoopBlock(s);
- return s;
- }
- });
+ replaceIfNecessary(loop.getLoopBlock(), loop::setLoopBlock);
super.visitWhileLoop(loop);
}
public void visitDoWhileLoop(final DoWhileStatement loop) {
- replaceIfNecessary(loop.getLoopBlock(), new Closure<Statement>(this, this) {
- public Statement doCall(Statement s) {
- loop.setLoopBlock(s);
- return s;
- }
- });
+ replaceIfNecessary(loop.getLoopBlock(), loop::setLoopBlock);
super.visitDoWhileLoop(loop);
}
- private void replaceIfNecessary(Statement nodeToCheck, Closure replacementCode) {
+ private void replaceIfNecessary(Statement nodeToCheck, Consumer<? super Statement> replacementCode) {
if (conditionFulfilled(nodeToCheck)) {
Statement replacement = replaceWith.call(nodeToCheck);
replacement.setSourcePosition(nodeToCheck);
replacement.copyNodeMetaData(nodeToCheck);
- replacementCode.call(replacement);
+ replacementCode.accept(replacement);
}
}
diff --git a/src/main/java/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.java
index d406f39..721f7b2 100644
--- a/src/main/java/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.java
@@ -39,10 +39,10 @@ import org.codehaus.groovy.classgen.ReturnAdder;
import org.codehaus.groovy.classgen.VariableScopeVisitor;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.codehaus.groovy.transform.AbstractASTTransformation;
import org.codehaus.groovy.transform.GroovyASTTransformation;
+import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -57,16 +57,13 @@ public class TailRecursiveASTTransformation extends AbstractASTTransformation {
@Override
public void visit(ASTNode[] nodes, SourceUnit source) {
init(nodes, source);
-
- MethodNode method = DefaultGroovyMethods.asType(nodes[1], MethodNode.class);
+ MethodNode method = (MethodNode) nodes[1];
if (method.isAbstract()) {
addError("Annotation " + TailRecursiveASTTransformation.getMY_TYPE_NAME() + " cannot be used for abstract methods.", method);
return;
-
}
-
if (hasAnnotation(method, ClassHelper.make(Memoized.class))) {
ClassNode memoizedClassNode = ClassHelper.make(Memoized.class);
for (AnnotationNode annotationNode : method.getAnnotations()) {
@@ -74,22 +71,16 @@ public class TailRecursiveASTTransformation extends AbstractASTTransformation {
if (annotationNode.getClassNode().equals(memoizedClassNode)) {
addError("Annotation " + TailRecursiveASTTransformation.getMY_TYPE_NAME() + " must be placed before annotation @Memoized.", annotationNode);
return;
-
}
-
}
-
}
-
if (!hasRecursiveMethodCalls(method)) {
AnnotationNode annotationNode = method.getAnnotations(ClassHelper.make(TailRecursive.class)).get(0);
addError("No recursive calls detected. You must remove annotation " + TailRecursiveASTTransformation.getMY_TYPE_NAME() + ".", annotationNode);
return;
-
}
-
transformToIteration(method, source);
ensureAllRecursiveCallsHaveBeenTransformed(method);
}
@@ -105,7 +96,6 @@ public class TailRecursiveASTTransformation extends AbstractASTTransformation {
} else {
transformNonVoidMethodToIteration(method, source);
}
-
}
private void transformVoidMethodToIteration(MethodNode method) {
@@ -140,13 +130,11 @@ public class TailRecursiveASTTransformation extends AbstractASTTransformation {
return ((ReturnStatement) node).getExpression() instanceof TernaryExpression;
}
-
};
Closure<Statement> replaceWithIfStatement = new Closure<Statement>(this, this) {
public Statement doCall(ReturnStatement statement) {
return ternaryToIfStatement.convert(statement);
}
-
};
StatementReplacer replacer = new StatementReplacer(whenReturnWithTernary, replaceWithIfStatement);
replacer.replaceIn(method.getCode());
@@ -154,13 +142,17 @@ public class TailRecursiveASTTransformation extends AbstractASTTransformation {
}
private void addLocalVariablesForAllParameters(MethodNode method, Map<String, Map> nameAndTypeMapping) {
- final BlockStatement code = DefaultGroovyMethods.asType(method.getCode(), BlockStatement.class);
- DefaultGroovyMethods.each(nameAndTypeMapping, new Closure<Void>(this, this) {
- public void doCall(String paramName, Map localNameAndType) {
- code.getStatements().add(0, AstHelper.createVariableDefinition((String) localNameAndType.get("name"), (ClassNode) localNameAndType.get("type"), new VariableExpression(paramName, (ClassNode) localNameAndType.get("type"))));
- }
-
- });
+ final BlockStatement code = (BlockStatement) method.getCode();
+ nameAndTypeMapping.forEach((paramName, localNameAndType) ->
+ code.getStatements().add(
+ 0,
+ AstHelper.createVariableDefinition(
+ (String) localNameAndType.get("name"),
+ (ClassNode) localNameAndType.get("type"),
+ new VariableExpression(paramName, (ClassNode) localNameAndType.get("type"))
+ )
+ )
+ );
}
private void replaceAllAccessToParams(MethodNode method, Map<String, Map> nameAndTypeMapping) {
@@ -168,36 +160,33 @@ public class TailRecursiveASTTransformation extends AbstractASTTransformation {
}
public Map<String, Map> name2VariableMappingFor(MethodNode method) {
- final Map<String, Map> nameAndTypeMapping = new LinkedHashMap<String, Map>();
- DefaultGroovyMethods.each(method.getParameters(), new Closure<LinkedHashMap<String, Object>>(this, this) {
- public LinkedHashMap<String, Object> doCall(Parameter param) {
- String paramName = param.getName();
- ClassNode paramType = DefaultGroovyMethods.asType(param.getType(), ClassNode.class);
- String iterationVariableName = iterationVariableName(paramName);
- LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>(2);
- map.put("name", iterationVariableName);
- map.put("type", paramType);
- return putAt0(nameAndTypeMapping, paramName, map);
- }
-
+ final Map<String, Map> nameAndTypeMapping = new LinkedHashMap<>();
+ Arrays.stream(method.getParameters()).forEach((Parameter param) -> {
+ String paramName = param.getName();
+ ClassNode paramType = param.getType();
+ String iterationVariableName = iterationVariableName(paramName);
+ LinkedHashMap<String, Object> map = new LinkedHashMap<>(2);
+ map.put("name", iterationVariableName);
+ map.put("type", paramType);
+ putAt0(nameAndTypeMapping, paramName, map);
});
+
return nameAndTypeMapping;
}
public Map<Integer, Map> position2VariableMappingFor(MethodNode method) {
- final Map<Integer, Map> positionMapping = new LinkedHashMap<Integer, Map>();
- DefaultGroovyMethods.eachWithIndex(method.getParameters(), new Closure<LinkedHashMap<String, Object>>(this, this) {
- public LinkedHashMap<String, Object> doCall(Parameter param, int index) {
- String paramName = param.getName();
- ClassNode paramType = DefaultGroovyMethods.asType(param.getType(), ClassNode.class);
- String iterationVariableName = TailRecursiveASTTransformation.this.iterationVariableName(paramName);
- LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>(2);
- map.put("name", iterationVariableName);
- map.put("type", paramType);
- return putAt0(positionMapping, index, map);
- }
-
- });
+ final Map<Integer, Map> positionMapping = new LinkedHashMap<>();
+ final Parameter[] parameters = method.getParameters();
+ for (int i = 0, n = parameters.length; i < n; i++) {
+ Parameter param = parameters[i];
+ String paramName = param.getName();
+ ClassNode paramType = param.getType();
+ String iterationVariableName = TailRecursiveASTTransformation.this.iterationVariableName(paramName);
+ LinkedHashMap<String, Object> map = new LinkedHashMap<>(2);
+ map.put("name", iterationVariableName);
+ map.put("type", paramType);
+ putAt0(positionMapping, i, map);
+ }
return positionMapping;
}
@@ -211,7 +200,7 @@ public class TailRecursiveASTTransformation extends AbstractASTTransformation {
}
@SuppressWarnings("Instanceof")
- private void replaceRecursiveReturnsOutsideClosures(final MethodNode method, final Map<Integer, Map> positionMapping) {
+ private void replaceRecursiveReturnsOutsideClosures(final MethodNode method, final Map<Integer, Map<String, Object>> positionMapping) {
Closure<Boolean> whenRecursiveReturn = new Closure<Boolean>(this, this) {
public Boolean doCall(Statement statement, boolean inClosure) {
if (inClosure) return false;
@@ -232,14 +221,13 @@ public class TailRecursiveASTTransformation extends AbstractASTTransformation {
public Statement doCall(ReturnStatement statement) {
return new ReturnStatementToIterationConverter().convert(statement, positionMapping);
}
-
};
StatementReplacer replacer = new StatementReplacer(whenRecursiveReturn, replaceWithContinueBlock);
replacer.replaceIn(method.getCode());
}
@SuppressWarnings("Instanceof")
- private void replaceRecursiveReturnsInsideClosures(final MethodNode method, final Map<Integer, Map> positionMapping) {
+ private void replaceRecursiveReturnsInsideClosures(final MethodNode method, final Map<Integer, Map<String, Object>> positionMapping) {
Closure<Boolean> whenRecursiveReturn = new Closure<Boolean>(this, this) {
public Boolean doCall(Statement statement, boolean inClosure) {
if (!inClosure) return false;
@@ -254,13 +242,11 @@ public class TailRecursiveASTTransformation extends AbstractASTTransformation {
return isRecursiveIn(inner, method);
}
-
};
Closure<Statement> replaceWithThrowLoopException = new Closure<Statement>(this, this) {
public Statement doCall(ReturnStatement statement) {
return new ReturnStatementToIterationConverter(AstHelper.recurByThrowStatement()).convert(statement, positionMapping);
}
-
};
StatementReplacer replacer = new StatementReplacer(whenRecursiveReturn, replaceWithThrowLoopException);
replacer.replaceIn(method.getCode());
@@ -280,7 +266,6 @@ public class TailRecursiveASTTransformation extends AbstractASTTransformation {
for (Expression expression : remainingRecursiveCalls) {
addError("Recursive call could not be transformed by @TailRecursive. Maybe it's not a tail call.", expression);
}
-
}
private boolean hasRecursiveMethodCalls(MethodNode method) {
diff --git a/src/main/java/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.java b/src/main/java/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.java
index 8803071..9a092b6 100644
--- a/src/main/java/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.java
+++ b/src/main/java/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.java
@@ -24,7 +24,6 @@ import org.codehaus.groovy.ast.stmt.Statement;
import static org.codehaus.groovy.ast.tools.GeneralUtils.ifElseS;
import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
-import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asType;
/**
* Since a ternary statement has more than one exit point tail-recursiveness testing cannot be easily done.
@@ -35,7 +34,7 @@ public class TernaryToIfStatementConverter {
public Statement convert(ReturnStatement statementWithInnerTernaryExpression) {
if (!(statementWithInnerTernaryExpression.getExpression() instanceof TernaryExpression))
return statementWithInnerTernaryExpression;
- TernaryExpression ternary = asType(statementWithInnerTernaryExpression.getExpression(), TernaryExpression.class);
+ TernaryExpression ternary = (TernaryExpression) statementWithInnerTernaryExpression.getExpression();
return ifElseS(ternary.getBooleanExpression(), returnS(ternary.getTrueExpression()), returnS(ternary.getFalseExpression()));
}
}
diff --git a/src/main/java/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.java b/src/main/java/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.java
index ad73fcb..c115bb5 100644
--- a/src/main/java/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.java
+++ b/src/main/java/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.java
@@ -39,7 +39,6 @@ import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
import org.codehaus.groovy.ast.stmt.ThrowStatement;
import org.codehaus.groovy.ast.stmt.WhileStatement;
import org.codehaus.groovy.ast.tools.GeneralUtils;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import java.lang.reflect.Method;
@@ -182,7 +181,7 @@ public class VariableExpressionReplacer extends CodeVisitorSupport {
//Use reflection to enable CompileStatic
String getterName = GeneralUtils.getGetterName(propName);
Method getExpressionMethod = node.getClass().getMethod(getterName);
- return DefaultGroovyMethods.asType(getExpressionMethod.invoke(node), Expression.class);
+ return (Expression) getExpressionMethod.invoke(node);
} catch (Throwable t) {
UncheckedThrow.rethrow(t);
return null;