Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updates NilChkResolver with several fixes:
- Method calls remove any assumption about the nullness of non-local variable, since the method call might modify such variables. - Improves the scope stack for better management of various control flow patterns. - Fixes handling of break, continue, return and exception throwing. - Uses the result of null checks within loop conditions. Extracts LabelRewriter from Rewriter and run this translation after NilChkResolver. Updates EnhancedForRewriter to handle loop labels. Change on 2016/02/18 by kstanger <kstanger@google.com> ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=114972263
- Loading branch information
Showing
12 changed files
with
870 additions
and
269 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
141 changes: 141 additions & 0 deletions
141
translator/src/main/java/com/google/devtools/j2objc/translate/LabelRewriter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
/* | ||
* Copyright 2011 Google Inc. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.google.devtools.j2objc.translate; | ||
|
||
import com.google.devtools.j2objc.ast.Block; | ||
import com.google.devtools.j2objc.ast.BreakStatement; | ||
import com.google.devtools.j2objc.ast.ContinueStatement; | ||
import com.google.devtools.j2objc.ast.DoStatement; | ||
import com.google.devtools.j2objc.ast.EmptyStatement; | ||
import com.google.devtools.j2objc.ast.EnhancedForStatement; | ||
import com.google.devtools.j2objc.ast.ForStatement; | ||
import com.google.devtools.j2objc.ast.LabeledStatement; | ||
import com.google.devtools.j2objc.ast.MethodDeclaration; | ||
import com.google.devtools.j2objc.ast.SimpleName; | ||
import com.google.devtools.j2objc.ast.Statement; | ||
import com.google.devtools.j2objc.ast.TreeUtil; | ||
import com.google.devtools.j2objc.ast.TreeVisitor; | ||
import com.google.devtools.j2objc.ast.WhileStatement; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
/** | ||
* Rewrites multiple labels that have the same name. | ||
* Rewrites labeled break and continue statements, converting them to goto for | ||
* the correct control flow. | ||
* | ||
* @author Tom Ball, Keith Stanger | ||
*/ | ||
public class LabelRewriter extends TreeVisitor { | ||
|
||
@Override | ||
public boolean visit(MethodDeclaration node) { | ||
// Rename any labels that have the same names; legal in Java but not C. | ||
final Map<String, Integer> labelCounts = new HashMap<>(); | ||
node.accept(new TreeVisitor() { | ||
@Override | ||
public void endVisit(LabeledStatement labeledStatement) { | ||
final String name = labeledStatement.getLabel().getIdentifier(); | ||
int value = labelCounts.containsKey(name) ? labelCounts.get(name) + 1 : 1; | ||
labelCounts.put(name, value); | ||
if (value > 1) { | ||
final String newName = name + '_' + value; | ||
labeledStatement.setLabel(new SimpleName(newName)); | ||
// Update references to this label. | ||
labeledStatement.accept(new TreeVisitor() { | ||
@Override | ||
public void endVisit(ContinueStatement node) { | ||
if (node.getLabel() != null && node.getLabel().getIdentifier().equals(name)) { | ||
node.setLabel(new SimpleName(newName)); | ||
} | ||
} | ||
@Override | ||
public void endVisit(BreakStatement node) { | ||
if (node.getLabel() != null && node.getLabel().getIdentifier().equals(name)) { | ||
node.setLabel(new SimpleName(newName)); | ||
} | ||
} | ||
}); | ||
|
||
} | ||
} | ||
}); | ||
return true; | ||
} | ||
|
||
private static Statement getLoopBody(Statement s) { | ||
if (s instanceof DoStatement) { | ||
return ((DoStatement) s).getBody(); | ||
} else if (s instanceof EnhancedForStatement) { | ||
return ((EnhancedForStatement) s).getBody(); | ||
} else if (s instanceof ForStatement) { | ||
return ((ForStatement) s).getBody(); | ||
} else if (s instanceof WhileStatement) { | ||
return ((WhileStatement) s).getBody(); | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public void endVisit(LabeledStatement node) { | ||
Statement loopBody = getLoopBody(node.getBody()); | ||
|
||
final String labelIdentifier = node.getLabel().getIdentifier(); | ||
|
||
final boolean[] hasContinue = new boolean[1]; | ||
final boolean[] hasBreak = new boolean[1]; | ||
node.accept(new TreeVisitor() { | ||
@Override | ||
public void endVisit(ContinueStatement node) { | ||
if (node.getLabel() != null && node.getLabel().getIdentifier().equals(labelIdentifier)) { | ||
hasContinue[0] = true; | ||
node.setLabel(new SimpleName("continue_" + labelIdentifier)); | ||
} | ||
} | ||
@Override | ||
public void endVisit(BreakStatement node) { | ||
if (node.getLabel() != null && node.getLabel().getIdentifier().equals(labelIdentifier)) { | ||
hasBreak[0] = true; | ||
node.setLabel(new SimpleName("break_" + labelIdentifier)); | ||
} | ||
} | ||
}); | ||
|
||
if (hasContinue[0]) { | ||
assert loopBody != null : "Continue statements must be inside a loop."; | ||
LabeledStatement newLabelStmt = new LabeledStatement("continue_" + labelIdentifier); | ||
newLabelStmt.setBody(new EmptyStatement()); | ||
// Put the loop body into an inner block so the continue label is outside | ||
// the scope of any variable initializations. | ||
Block newBlock = new Block(); | ||
loopBody.replaceWith(newBlock); | ||
newBlock.getStatements().add(loopBody); | ||
newBlock.getStatements().add(newLabelStmt); | ||
} | ||
if (hasBreak[0]) { | ||
LabeledStatement newLabelStmt = new LabeledStatement("break_" + labelIdentifier); | ||
newLabelStmt.setBody(new EmptyStatement()); | ||
TreeUtil.insertAfter(node, newLabelStmt); | ||
} | ||
|
||
if (hasContinue[0] || hasBreak[0]) { | ||
// Replace this node with its statement, thus deleting the label. | ||
node.replaceWith(TreeUtil.remove(node.getBody())); | ||
} | ||
} | ||
} |
Oops, something went wrong.