From d2c503bd5f5a65814057ce38af9923b2a83bf2f5 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 1 Apr 2011 14:04:51 +0400 Subject: [PATCH] CF supported for function literals --- .../jet/lang/cfg/JetControlFlowProcessor.java | 5 ++ .../JetControlFlowInstructionsGenerator.java | 84 ++++++++++--------- .../jet/lang/cfg/pseudocode/Pseudocode.java | 46 +++++----- .../jet/lang/resolve/TopDownAnalyzer.java | 30 +++---- .../jet/checkers/JetPsiCheckerTest.java | 2 +- 5 files changed, 89 insertions(+), 78 deletions(-) diff --git a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index d1dc349fd03..bcca35ce89e 100644 --- a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -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); diff --git a/idea/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java b/idea/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java index 2948f9b1318..4453869d388 100644 --- a/idea/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java +++ b/idea/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java @@ -1,7 +1,6 @@ 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 loopInfo = new Stack(); +// private final Stack subroutineInfo = new Stack(); + private final Map elementToBlockInfo = new HashMap(); private int labelCount = 0; + private final Stack builders = new Stack(); - 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 loopInfo = new Stack(); - private final Stack subroutineInfo = new Stack(); - private final Map elementToBlockInfo = new HashMap(); - 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; + } + } } diff --git a/idea/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java b/idea/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java index 9e40dd604b7..40f684f1630 100644 --- a/idea/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java +++ b/idea/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java @@ -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 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 instructions = new ArrayList(); - private final Map labels = new LinkedHashMap(); - -// @Nullable -// private final Pseudocode parent; -// -// public Pseudocode(Pseudocode parent) { -// this.parent = parent; -// } + private final List labels = new ArrayList(); 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 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()); } - 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 nodeToName) { out.println(graphHeader + " {"); out.println(style); - final Map nodeToName = new HashMap(); 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); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 6d9bac71f17..a40150373e9 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -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) { diff --git a/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java b/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java index 70b1519da38..fb257b919d0 100644 --- a/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java @@ -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); } }