提交 d2c503bd 编写于 作者: A Andrey Breslav

CF supported for function literals

上级 f8a5c257
......@@ -105,6 +105,11 @@ public class JetControlFlowProcessor {
exitElement(element);
}
@Override
public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
value(expression.getExpression(), false);
}
@Override
public void visitConstantExpression(JetConstantExpression expression) {
builder.readNode(expression);
......
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilder;
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilderAdapter;
import org.jetbrains.jet.lang.cfg.Label;
......@@ -18,17 +17,20 @@ import java.util.Stack;
*/
public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAdapter {
private final Stack<BlockInfo> loopInfo = new Stack<BlockInfo>();
// private final Stack<BlockInfo> subroutineInfo = new Stack<BlockInfo>();
private final Map<JetElement, BlockInfo> elementToBlockInfo = new HashMap<JetElement, BlockInfo>();
private int labelCount = 0;
private final Stack<JetControlFlowInstructionsGeneratorWorker> builders = new Stack<JetControlFlowInstructionsGeneratorWorker>();
public JetControlFlowInstructionsGenerator() {
public JetControlFlowInstructionsGenerator(JetElement subroutine) {
super(null);
pushBuilder();
pushBuilder(subroutine);
}
private void pushBuilder() {
Pseudocode parentPseudocode = builder == null ? new Pseudocode() : builders.peek().getPseudocode();
JetControlFlowInstructionsGeneratorWorker worker = new JetControlFlowInstructionsGeneratorWorker(parentPseudocode);
private void pushBuilder(JetElement subroutine) {
JetControlFlowInstructionsGeneratorWorker worker = new JetControlFlowInstructionsGeneratorWorker(subroutine);
builders.push(worker);
builder = worker;
}
......@@ -42,7 +44,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
@Override
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
if (isFunctionLiteral) {
pushBuilder();
pushBuilder(builder.getCurrentSubroutine());
builder.enterSubroutine(subroutine, false);
}
else {
......@@ -57,8 +59,8 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
JetControlFlowInstructionsGeneratorWorker worker = popBuilder();
JetControlFlowInstructionsGeneratorWorker builder = builders.peek();
FunctionLiteralValueInstruction instruction = new FunctionLiteralValueInstruction(subroutine);
builder.add(instruction);
instruction.setBody(worker.getPseudocode());
builder.add(instruction);
}
}
......@@ -66,40 +68,14 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
return builders.peek().getPseudocode();
}
private static class BlockInfo {
private final JetElement element;
private final Label entryPoint;
private final Label exitPoint;
private BlockInfo(JetElement element, Label entryPoint, Label exitPoint) {
this.element = element;
this.entryPoint = entryPoint;
this.exitPoint = exitPoint;
}
public JetElement getElement() {
return element;
}
public Label getEntryPoint() {
return entryPoint;
}
public Label getExitPoint() {
return exitPoint;
}
}
private final Stack<BlockInfo> loopInfo = new Stack<BlockInfo>();
private final Stack<BlockInfo> subroutineInfo = new Stack<BlockInfo>();
private final Map<JetElement, BlockInfo> elementToBlockInfo = new HashMap<JetElement, BlockInfo>();
private class JetControlFlowInstructionsGeneratorWorker implements JetControlFlowBuilder {
private final Pseudocode pseudocode;
private final JetElement currentSubroutine;
private JetControlFlowInstructionsGeneratorWorker(@Nullable Pseudocode parent) {
private JetControlFlowInstructionsGeneratorWorker(JetElement currentSubroutine) {
this.pseudocode = new Pseudocode();
this.currentSubroutine = currentSubroutine;
}
public Pseudocode getPseudocode() {
......@@ -142,14 +118,14 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
Label entryPoint = createUnboundLabel();
BlockInfo blockInfo = new BlockInfo(subroutine, entryPoint, createUnboundLabel());
subroutineInfo.push(blockInfo);
// subroutineInfo.push(blockInfo);
elementToBlockInfo.put(subroutine, blockInfo);
bindLabel(entryPoint);
}
@Override
public JetElement getCurrentSubroutine() {
return subroutineInfo.empty() ? null : subroutineInfo.peek().getElement();
return currentSubroutine;// subroutineInfo.empty() ? null : subroutineInfo.peek().getElement();
}
@Override
......@@ -159,7 +135,9 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
@Override
public Label getExitPoint(@NotNull JetElement labelElement) {
return elementToBlockInfo.get(labelElement).getExitPoint();
BlockInfo blockInfo = elementToBlockInfo.get(labelElement);
assert blockInfo != null : labelElement.getText();
return blockInfo.getExitPoint();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
......@@ -169,6 +147,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
bindLabel(getExitPoint(subroutine));
add(new SubroutineExitInstruction(subroutine));
elementToBlockInfo.remove(subroutine);
// subroutineInfo.pop();
}
@Override
......@@ -203,7 +182,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
@Override
public void bindLabel(@NotNull Label label) {
pseudocode.addLabel(label);
pseudocode.bindLabel(label);
}
@Override
......@@ -227,4 +206,27 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
}
}
private static class BlockInfo {
private final JetElement element;
private final Label entryPoint;
private final Label exitPoint;
private BlockInfo(JetElement element, Label entryPoint, Label exitPoint) {
this.element = element;
this.entryPoint = entryPoint;
this.exitPoint = exitPoint;
}
public JetElement getElement() {
return element;
}
public Label getEntryPoint() {
return entryPoint;
}
public Label getExitPoint() {
return exitPoint;
}
}
}
......@@ -11,8 +11,11 @@ import java.util.*;
* @author abreslav
*/
public class Pseudocode {
public class PseudocodeLabel implements Label {
private final String name;
private Integer targetInstructionIndex;
private PseudocodeLabel(String name) {
this.name = name;
......@@ -28,35 +31,37 @@ public class Pseudocode {
return name;
}
public int getTargetInstructionIndex() {
return targetInstructionIndex;
}
public void setTargetInstructionIndex(int targetInstructionIndex) {
this.targetInstructionIndex = targetInstructionIndex;
}
@Nullable
private List<Instruction> resolve() {
Integer result = labels.get(this);
assert result != null;
return instructions.subList(result, instructions.size());
assert targetInstructionIndex != null;
return instructions.subList(getTargetInstructionIndex(), instructions.size());
}
}
private final List<Instruction> instructions = new ArrayList<Instruction>();
private final Map<Label, Integer> labels = new LinkedHashMap<Label, Integer>();
// @Nullable
// private final Pseudocode parent;
//
// public Pseudocode(Pseudocode parent) {
// this.parent = parent;
// }
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
public PseudocodeLabel createLabel(String name) {
return new PseudocodeLabel(name);
PseudocodeLabel label = new PseudocodeLabel(name);
labels.add(label);
return label;
}
public void addInstruction(Instruction instruction) {
instructions.add(instruction);
}
public void addLabel(Label label) {
labels.put(label, instructions.size());
public void bindLabel(Label label) {
((PseudocodeLabel) label).setTargetInstructionIndex(instructions.size());
}
public void postProcess() {
......@@ -144,9 +149,9 @@ public class Pseudocode {
public void dumpInstructions(@NotNull PrintStream out) {
for (int i = 0, instructionsSize = instructions.size(); i < instructionsSize; i++) {
Instruction instruction = instructions.get(i);
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
if (entry.getValue() == i) {
out.println(entry.getKey() + ":");
for (PseudocodeLabel label: labels) {
if (label.getTargetInstructionIndex() == i) {
out.println(label.getName() + ":");
}
}
out.println(" " + instruction);
......@@ -155,14 +160,13 @@ public class Pseudocode {
public void dumpGraph(@NotNull final PrintStream out) {
String graphHeader = "digraph g";
dumpSubgraph(out, graphHeader, new int[1], "");
dumpSubgraph(out, graphHeader, new int[1], "", new HashMap<Instruction, String>());
}
private void dumpSubgraph(final PrintStream out, String graphHeader, final int[] count, String style) {
private void dumpSubgraph(final PrintStream out, String graphHeader, final int[] count, String style, final Map<Instruction, String> nodeToName) {
out.println(graphHeader + " {");
out.println(style);
final Map<Instruction, String> nodeToName = new HashMap<Instruction, String>();
for (Instruction node : instructions) {
if (node instanceof UnconditionalJumpInstruction) {
continue;
......@@ -195,7 +199,7 @@ public class Pseudocode {
@Override
public void visitFunctionLiteralValue(FunctionLiteralValueInstruction instruction) {
int index = count[0];
instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";");
instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName);
printEdge(out, nodeToName.get(instruction), "n" + index, null);
visitInstructionWithNext(instruction);
}
......
......@@ -230,21 +230,21 @@ public class TopDownAnalyzer {
declaringScope.addFunctionDescriptor(descriptor);
functions.put(function, descriptor);
// JetExpression bodyExpression = function.getBodyExpression();
// if (bodyExpression != null) {
// System.out.println("-------------");
// JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator();
// new JetControlFlowProcessor(semanticServices, trace, instructionsGenerator).generate(function, bodyExpression);
// Pseudocode pseudocode = instructionsGenerator.getPseudocode();
// pseudocode.postProcess();
// pseudocode.dumpInstructions(System.out);
// System.out.println("-------------");
// try {
// pseudocode.dumpGraph(new PrintStream("/Users/abreslav/work/cfg.dot"));
// } catch (FileNotFoundException e) {
// e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
// }
// }
JetExpression bodyExpression = function.getBodyExpression();
if (bodyExpression != null) {
System.out.println("-------------");
JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator(function);
new JetControlFlowProcessor(semanticServices, trace, instructionsGenerator).generate(function, bodyExpression);
Pseudocode pseudocode = instructionsGenerator.getPseudocode();
pseudocode.postProcess();
pseudocode.dumpInstructions(System.out);
System.out.println("-------------");
try {
pseudocode.dumpGraph(new PrintStream("/Users/abreslav/work/cfg.dot"));
} catch (FileNotFoundException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}
private void processProperty(WritableScope declaringScope, JetProperty property) {
......
......@@ -29,6 +29,6 @@ public class JetPsiCheckerTest extends LightDaemonAnalyzerTestCase {
}
public void testQualifiedThis() throws Exception {
// doTest("/checker/QualifiedThis.jet", true, true);
doTest("/checker/QualifiedThis.jet", true, true);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册