improve foreach loops with useful CF functions

This commit is contained in:
Renaud Pawlak 2020-06-15 14:40:33 +02:00
parent 0eaf12e805
commit e6dadf82fc
4 changed files with 65 additions and 11 deletions

View File

@ -23,14 +23,13 @@ import java.util.Set;
import javax.lang.model.element.ElementKind;
import org.jsweet.transpiler.util.AbstractTreeScanner;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAssign;
import com.sun.tools.javac.tree.JCTree.JCAssignOp;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCUnary;
import com.sun.tools.javac.tree.TreeScanner;
/**
* This AST scanner analyzes local variables to determine if they are locally
@ -39,7 +38,7 @@ import com.sun.tools.javac.tree.JCTree.JCUnary;
* @see JSweetContext
* @author Renaud Pawlak
*/
public class ConstAnalyzer extends AbstractTreeScanner {
public class ConstAnalyzer extends TreeScanner {
private Set<VarSymbol> modifiedVariables = new HashSet<>();
@ -51,13 +50,6 @@ public class ConstAnalyzer extends AbstractTreeScanner {
return modifiedVariables;
}
/**
* Creates a new constant variable analyzer.
*/
public ConstAnalyzer(TranspilationHandler logHandler, JSweetContext context) {
super(logHandler, context, null);
}
private void registerModification(JCTree tree) {
if (tree instanceof JCIdent && ((JCIdent) tree).sym.getKind() == ElementKind.LOCAL_VARIABLE) {
modifiedVariables.add((VarSymbol) ((JCIdent) tree).sym);

View File

@ -738,7 +738,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
footer.delete(0, footer.length());
setCompilationUnit(topLevel);
constAnalyzer = new ConstAnalyzer(getLogHandler(), context);
constAnalyzer = new ConstAnalyzer();
constAnalyzer.scan(topLevel);
String packge = topLevel.packge.toString();

View File

@ -42,5 +42,16 @@ public interface ForeachLoopElement extends ExtendedElement {
* The body of the foreach loop.
*/
ExtendedElement getBody();
/**
* Returns true if the loop contains a control flow statement
* (<code>break</code>, <code>continue</code>, <code>return</code>).
*/
boolean hasControlFlowStatement();
/**
* Returns true if the iteration variable is modified within the loop body.
*/
boolean isIterationVariableModified();
}

View File

@ -20,11 +20,19 @@ package org.jsweet.transpiler.model.support;
import javax.lang.model.element.VariableElement;
import org.jsweet.transpiler.ConstAnalyzer;
import org.jsweet.transpiler.model.ExtendedElement;
import org.jsweet.transpiler.model.ExtendedElementFactory;
import org.jsweet.transpiler.model.ForeachLoopElement;
import com.sun.tools.javac.tree.JCTree.JCBreak;
import com.sun.tools.javac.tree.JCTree.JCContinue;
import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop;
import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop;
import com.sun.tools.javac.tree.JCTree.JCForLoop;
import com.sun.tools.javac.tree.JCTree.JCReturn;
import com.sun.tools.javac.tree.JCTree.JCWhileLoop;
import com.sun.tools.javac.tree.TreeScanner;
/**
* See {@link ForeachLoopElement}.
@ -52,4 +60,47 @@ public class ForeachLoopElementSupport extends ExtendedElementSupport<JCEnhanced
return ExtendedElementFactory.INSTANCE.create(getTree().expr);
}
@Override
public boolean hasControlFlowStatement() {
boolean[] hasControlFlowStatement = { false };
new TreeScanner() {
@Override
public void visitBreak(JCBreak tree) {
hasControlFlowStatement[0] = true;
}
@Override
public void visitContinue(JCContinue tree) {
hasControlFlowStatement[0] = true;
}
@Override
public void visitReturn(JCReturn tree) {
hasControlFlowStatement[0] = true;
}
@Override
public void visitForeachLoop(JCEnhancedForLoop tree) {
// do not scan inner loops
}
@Override
public void visitDoLoop(JCDoWhileLoop tree) {
// do not scan inner loops
}
@Override
public void visitWhileLoop(JCWhileLoop tree) {
// do not scan inner loops
}
@Override
public void visitForLoop(JCForLoop tree) {
// do not scan inner loops
}
}.scan(getTree().body);
return hasControlFlowStatement[0];
}
@Override
public boolean isIterationVariableModified() {
ConstAnalyzer a = new ConstAnalyzer();
a.scan(getTree().body);
return a.getModifiedVariables().contains(getIterationVariable());
}
}