CF supported for function literals
This commit is contained in:
@@ -105,6 +105,11 @@ public class JetControlFlowProcessor {
|
|||||||
exitElement(element);
|
exitElement(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
|
||||||
|
value(expression.getExpression(), false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitConstantExpression(JetConstantExpression expression) {
|
public void visitConstantExpression(JetConstantExpression expression) {
|
||||||
builder.readNode(expression);
|
builder.readNode(expression);
|
||||||
|
|||||||
+43
-41
@@ -1,7 +1,6 @@
|
|||||||
package org.jetbrains.jet.lang.cfg.pseudocode;
|
package org.jetbrains.jet.lang.cfg.pseudocode;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilder;
|
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilder;
|
||||||
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilderAdapter;
|
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilderAdapter;
|
||||||
import org.jetbrains.jet.lang.cfg.Label;
|
import org.jetbrains.jet.lang.cfg.Label;
|
||||||
@@ -18,17 +17,20 @@ import java.util.Stack;
|
|||||||
*/
|
*/
|
||||||
public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAdapter {
|
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 int labelCount = 0;
|
||||||
|
|
||||||
private final Stack<JetControlFlowInstructionsGeneratorWorker> builders = new Stack<JetControlFlowInstructionsGeneratorWorker>();
|
private final Stack<JetControlFlowInstructionsGeneratorWorker> builders = new Stack<JetControlFlowInstructionsGeneratorWorker>();
|
||||||
|
|
||||||
public JetControlFlowInstructionsGenerator() {
|
public JetControlFlowInstructionsGenerator(JetElement subroutine) {
|
||||||
super(null);
|
super(null);
|
||||||
pushBuilder();
|
pushBuilder(subroutine);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pushBuilder() {
|
private void pushBuilder(JetElement subroutine) {
|
||||||
Pseudocode parentPseudocode = builder == null ? new Pseudocode() : builders.peek().getPseudocode();
|
JetControlFlowInstructionsGeneratorWorker worker = new JetControlFlowInstructionsGeneratorWorker(subroutine);
|
||||||
JetControlFlowInstructionsGeneratorWorker worker = new JetControlFlowInstructionsGeneratorWorker(parentPseudocode);
|
|
||||||
builders.push(worker);
|
builders.push(worker);
|
||||||
builder = worker;
|
builder = worker;
|
||||||
}
|
}
|
||||||
@@ -42,7 +44,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
@Override
|
@Override
|
||||||
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
|
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
|
||||||
if (isFunctionLiteral) {
|
if (isFunctionLiteral) {
|
||||||
pushBuilder();
|
pushBuilder(builder.getCurrentSubroutine());
|
||||||
builder.enterSubroutine(subroutine, false);
|
builder.enterSubroutine(subroutine, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -57,8 +59,8 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
JetControlFlowInstructionsGeneratorWorker worker = popBuilder();
|
JetControlFlowInstructionsGeneratorWorker worker = popBuilder();
|
||||||
JetControlFlowInstructionsGeneratorWorker builder = builders.peek();
|
JetControlFlowInstructionsGeneratorWorker builder = builders.peek();
|
||||||
FunctionLiteralValueInstruction instruction = new FunctionLiteralValueInstruction(subroutine);
|
FunctionLiteralValueInstruction instruction = new FunctionLiteralValueInstruction(subroutine);
|
||||||
builder.add(instruction);
|
|
||||||
instruction.setBody(worker.getPseudocode());
|
instruction.setBody(worker.getPseudocode());
|
||||||
|
builder.add(instruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,40 +68,14 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
return builders.peek().getPseudocode();
|
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 class JetControlFlowInstructionsGeneratorWorker implements JetControlFlowBuilder {
|
||||||
|
|
||||||
private final Pseudocode pseudocode;
|
private final Pseudocode pseudocode;
|
||||||
|
private final JetElement currentSubroutine;
|
||||||
|
|
||||||
private JetControlFlowInstructionsGeneratorWorker(@Nullable Pseudocode parent) {
|
private JetControlFlowInstructionsGeneratorWorker(JetElement currentSubroutine) {
|
||||||
this.pseudocode = new Pseudocode();
|
this.pseudocode = new Pseudocode();
|
||||||
|
this.currentSubroutine = currentSubroutine;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pseudocode getPseudocode() {
|
public Pseudocode getPseudocode() {
|
||||||
@@ -142,14 +118,14 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
|
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
|
||||||
Label entryPoint = createUnboundLabel();
|
Label entryPoint = createUnboundLabel();
|
||||||
BlockInfo blockInfo = new BlockInfo(subroutine, entryPoint, createUnboundLabel());
|
BlockInfo blockInfo = new BlockInfo(subroutine, entryPoint, createUnboundLabel());
|
||||||
subroutineInfo.push(blockInfo);
|
// subroutineInfo.push(blockInfo);
|
||||||
elementToBlockInfo.put(subroutine, blockInfo);
|
elementToBlockInfo.put(subroutine, blockInfo);
|
||||||
bindLabel(entryPoint);
|
bindLabel(entryPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetElement getCurrentSubroutine() {
|
public JetElement getCurrentSubroutine() {
|
||||||
return subroutineInfo.empty() ? null : subroutineInfo.peek().getElement();
|
return currentSubroutine;// subroutineInfo.empty() ? null : subroutineInfo.peek().getElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -159,7 +135,9 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Label getExitPoint(@NotNull JetElement labelElement) {
|
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));
|
bindLabel(getExitPoint(subroutine));
|
||||||
add(new SubroutineExitInstruction(subroutine));
|
add(new SubroutineExitInstruction(subroutine));
|
||||||
elementToBlockInfo.remove(subroutine);
|
elementToBlockInfo.remove(subroutine);
|
||||||
|
// subroutineInfo.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -203,7 +182,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bindLabel(@NotNull Label label) {
|
public void bindLabel(@NotNull Label label) {
|
||||||
pseudocode.addLabel(label);
|
pseudocode.bindLabel(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class Pseudocode {
|
public class Pseudocode {
|
||||||
|
|
||||||
public class PseudocodeLabel implements Label {
|
public class PseudocodeLabel implements Label {
|
||||||
private final String name;
|
private final String name;
|
||||||
|
private Integer targetInstructionIndex;
|
||||||
|
|
||||||
|
|
||||||
private PseudocodeLabel(String name) {
|
private PseudocodeLabel(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -28,35 +31,37 @@ public class Pseudocode {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getTargetInstructionIndex() {
|
||||||
|
return targetInstructionIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetInstructionIndex(int targetInstructionIndex) {
|
||||||
|
this.targetInstructionIndex = targetInstructionIndex;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private List<Instruction> resolve() {
|
private List<Instruction> resolve() {
|
||||||
Integer result = labels.get(this);
|
assert targetInstructionIndex != null;
|
||||||
assert result != null;
|
return instructions.subList(getTargetInstructionIndex(), instructions.size());
|
||||||
return instructions.subList(result, instructions.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<Instruction> instructions = new ArrayList<Instruction>();
|
private final List<Instruction> instructions = new ArrayList<Instruction>();
|
||||||
private final Map<Label, Integer> labels = new LinkedHashMap<Label, Integer>();
|
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
|
||||||
|
|
||||||
// @Nullable
|
|
||||||
// private final Pseudocode parent;
|
|
||||||
//
|
|
||||||
// public Pseudocode(Pseudocode parent) {
|
|
||||||
// this.parent = parent;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public PseudocodeLabel createLabel(String name) {
|
public PseudocodeLabel createLabel(String name) {
|
||||||
return new PseudocodeLabel(name);
|
PseudocodeLabel label = new PseudocodeLabel(name);
|
||||||
|
labels.add(label);
|
||||||
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addInstruction(Instruction instruction) {
|
public void addInstruction(Instruction instruction) {
|
||||||
instructions.add(instruction);
|
instructions.add(instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLabel(Label label) {
|
public void bindLabel(Label label) {
|
||||||
labels.put(label, instructions.size());
|
((PseudocodeLabel) label).setTargetInstructionIndex(instructions.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postProcess() {
|
public void postProcess() {
|
||||||
@@ -144,9 +149,9 @@ public class Pseudocode {
|
|||||||
public void dumpInstructions(@NotNull PrintStream out) {
|
public void dumpInstructions(@NotNull PrintStream out) {
|
||||||
for (int i = 0, instructionsSize = instructions.size(); i < instructionsSize; i++) {
|
for (int i = 0, instructionsSize = instructions.size(); i < instructionsSize; i++) {
|
||||||
Instruction instruction = instructions.get(i);
|
Instruction instruction = instructions.get(i);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (PseudocodeLabel label: labels) {
|
||||||
if (entry.getValue() == i) {
|
if (label.getTargetInstructionIndex() == i) {
|
||||||
out.println(entry.getKey() + ":");
|
out.println(label.getName() + ":");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.println(" " + instruction);
|
out.println(" " + instruction);
|
||||||
@@ -155,14 +160,13 @@ public class Pseudocode {
|
|||||||
|
|
||||||
public void dumpGraph(@NotNull final PrintStream out) {
|
public void dumpGraph(@NotNull final PrintStream out) {
|
||||||
String graphHeader = "digraph g";
|
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(graphHeader + " {");
|
||||||
out.println(style);
|
out.println(style);
|
||||||
|
|
||||||
final Map<Instruction, String> nodeToName = new HashMap<Instruction, String>();
|
|
||||||
for (Instruction node : instructions) {
|
for (Instruction node : instructions) {
|
||||||
if (node instanceof UnconditionalJumpInstruction) {
|
if (node instanceof UnconditionalJumpInstruction) {
|
||||||
continue;
|
continue;
|
||||||
@@ -195,7 +199,7 @@ public class Pseudocode {
|
|||||||
@Override
|
@Override
|
||||||
public void visitFunctionLiteralValue(FunctionLiteralValueInstruction instruction) {
|
public void visitFunctionLiteralValue(FunctionLiteralValueInstruction instruction) {
|
||||||
int index = count[0];
|
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);
|
printEdge(out, nodeToName.get(instruction), "n" + index, null);
|
||||||
visitInstructionWithNext(instruction);
|
visitInstructionWithNext(instruction);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,21 +230,21 @@ public class TopDownAnalyzer {
|
|||||||
declaringScope.addFunctionDescriptor(descriptor);
|
declaringScope.addFunctionDescriptor(descriptor);
|
||||||
functions.put(function, descriptor);
|
functions.put(function, descriptor);
|
||||||
|
|
||||||
// JetExpression bodyExpression = function.getBodyExpression();
|
JetExpression bodyExpression = function.getBodyExpression();
|
||||||
// if (bodyExpression != null) {
|
if (bodyExpression != null) {
|
||||||
// System.out.println("-------------");
|
System.out.println("-------------");
|
||||||
// JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator();
|
JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator(function);
|
||||||
// new JetControlFlowProcessor(semanticServices, trace, instructionsGenerator).generate(function, bodyExpression);
|
new JetControlFlowProcessor(semanticServices, trace, instructionsGenerator).generate(function, bodyExpression);
|
||||||
// Pseudocode pseudocode = instructionsGenerator.getPseudocode();
|
Pseudocode pseudocode = instructionsGenerator.getPseudocode();
|
||||||
// pseudocode.postProcess();
|
pseudocode.postProcess();
|
||||||
// pseudocode.dumpInstructions(System.out);
|
pseudocode.dumpInstructions(System.out);
|
||||||
// System.out.println("-------------");
|
System.out.println("-------------");
|
||||||
// try {
|
try {
|
||||||
// pseudocode.dumpGraph(new PrintStream("/Users/abreslav/work/cfg.dot"));
|
pseudocode.dumpGraph(new PrintStream("/Users/abreslav/work/cfg.dot"));
|
||||||
// } catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
// e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processProperty(WritableScope declaringScope, JetProperty property) {
|
private void processProperty(WritableScope declaringScope, JetProperty property) {
|
||||||
|
|||||||
@@ -29,6 +29,6 @@ public class JetPsiCheckerTest extends LightDaemonAnalyzerTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testQualifiedThis() throws Exception {
|
public void testQualifiedThis() throws Exception {
|
||||||
// doTest("/checker/QualifiedThis.jet", true, true);
|
doTest("/checker/QualifiedThis.jet", true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user