Loading EDG/src/main/java/edg/slicing/ConstrainedAlgorithm.java +10 −1 Original line number Diff line number Diff line Loading @@ -78,6 +78,11 @@ public class ConstrainedAlgorithm implements SlicingAlgorithm edge.getType() == Edge.Type.Call); } // TRAVERSAL RESTRICTION TODO: Change this restriction to construction time removing structural arcs // GENERATOR NODES CONTAIN VALUE EDGES THAT MUST BE TRAVERSED ONLY IF THE GENERATOR NODE IS INCLUDED BY CONTROL if (currentNode.getType() == Node.Type.Generator && work.getPreviousEdgeType() != Edge.Type.Control) edges.removeIf(edge -> edge.getType() == Edge.Type.Value); for (NodeConstraint nodeConstraint : nodeConstraints) nodeConstraint.resolve(phase, edges); Loading Loading @@ -109,6 +114,10 @@ public class ConstrainedAlgorithm implements SlicingAlgorithm if (!currentEdge.isTraversable()) return newWorks; int sourceId = edg.getEdgeSource(currentEdge).getId(); int targetId = edg.getEdgeTarget(currentEdge).getId(); try { final Constraints constraints = work.getConstraints(); Loading e-Knife/src/main/java/eknife/erlang/ControlFlowGenerator.java +99 −54 Original line number Diff line number Diff line Loading @@ -18,15 +18,17 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator protected final Deque<Set<Node>> switchSelectorStack = new LinkedList<>(); protected final Deque<Boolean> switchHasDefaultStack = new LinkedList<>(); protected boolean absorbentPattern = false; protected boolean absorbentCondition = false; protected boolean ifContext = false; protected boolean stopCaseCFG = false; // protected boolean ifContext = false; protected int ttl = INFINITY; protected boolean generating = false; protected boolean parametersContext = false; protected Deque<Node> routineHanging = new LinkedList<>(); protected Deque<Node> anonymousRoutineHanging = new LinkedList<>(); protected final Deque<Set<Node>> lcStack = new LinkedList<>(); protected final Deque<Node> lcPrevRestriction = new LinkedList<>(); protected final Deque<Set<Node>> prevCaseGuardHanging = new LinkedList<>(); public ControlFlowGenerator(LAST graph) Loading Loading @@ -74,7 +76,7 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator routineHanging.push(n); super.visitRoutine(n, arg); routineHanging.pop(); hangingNodes.clear(); clearHanging(); hangingNodes.addAll(clauseHangingStack.peek()); connectTo(n); clauseHangingStack.pop(); Loading @@ -88,11 +90,12 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator { clauseHangingStack.push(new HashSet<>()); guardHangingStack.push(new HashSet<>()); routineHanging.push(n); anonymousRoutineHanging.push(n); connectTo(n); clearHanging(); super.visitAnonymousRoutine(n, arg); routineHanging.pop(); hangingNodes.clear(); anonymousRoutineHanging.pop(); clearHanging(); hangingNodes.addAll(clauseHangingStack.peek()); connectTo(n); guardHangingStack.pop(); Loading @@ -102,9 +105,8 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator @Override public void visitClause(Node n, Void arg) { if (graph.getParent(n).equals(routineHanging.peek())) { hangingNodes.clear(); if (graph.getParent(n).equals(routineHanging.peek())) { clearHanging(); hangingNodes.add(routineHanging.peek()); } Loading @@ -115,17 +117,25 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator returnSet.push(new HashSet<>()); graph.getChild(n, Node.Type.ParameterIn).accept(this, arg); graph.getChild(n, Node.Type.Parameters).accept(this, arg); graph.getChild(n, Node.Type.Guard).accept(this, arg); Node guardNode = graph.getChild(n, Node.Type.Guard); guardNode.accept(this, arg); if (!graph.getChildren(guardNode).isEmpty()) guardHangingStack.peek().addAll(hangingNodes); graph.getChild(n, Node.Type.Body).accept(this, arg); hangingNodes.addAll(returnSet.peek()); returnSet.pop(); hangingNodes.addAll(returnSet.pop()); graph.getChild(n, Node.Type.ParameterOut).accept(this, arg); hangingNodes.addAll(guardHangingStack.peek()); guardHangingStack.peek().clear(); connectTo(n); } @Override public void visitBlock(Node n, Void arg) { returnSet.push(new HashSet<>()); super.visitBlock(n, arg); hangingNodes.addAll(returnSet.pop()); } @Override public void visitEnclosed(Node n, Void arg) { Loading Loading @@ -153,6 +163,8 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator { super.visitDataConstructor(n, arg); connectTo(n); if (graph.isPatternZone(n) && !this.isMatchExprPattern(n)) guardHangingStack.peek().addAll(hangingNodes); } @Override Loading @@ -172,55 +184,67 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator @Override public void visitSwitch(Node n, Void arg) { if (n.getInfo().getConstruction().equals("if")) ifContext = true; else ifContext = false; returnSet.push(new HashSet<>()); switchStack.push(new HashSet<>()); graph.getChild(n, Node.Type.Selector).accept(this, arg); graph.getChild(n, Node.Type.Cases).accept(this, arg); hangingNodes.clear(); clearHanging(); hangingNodes.addAll(returnSet.peek()); connectTo(n); returnSet.pop(); absorbentCondition = false; ifContext = false; } @Override public void visitCases(Node n, Void arg){ absorbentPattern = false; absorbentCondition = false; stopCaseCFG = false; prevCaseGuardHanging.push(new HashSet<>()); super.visitCases(n, arg); returnSet.peek().addAll(Set.copyOf(prevCaseGuardHanging.peek())); prevCaseGuardHanging.pop(); stopCaseCFG = false; } @Override public void visitCase(Node n, Void arg) { if(!absorbentCondition) { hangingNodes.addAll(prevCaseGuardHanging.peekFirst()); if(!stopCaseCFG) { hangingNodes.addAll(prevCaseGuardHanging.peek()); prevCaseGuardHanging.peek().clear(); graph.getChild(n, Node.Type.Selectable).accept(this, arg); graph.getChild(n, Node.Type.Guard).accept(this, arg); prevCaseGuardHanging.peek().addAll(Set.copyOf(hangingNodes)); boolean prevIfContext = ifContext; // SAVE THE ABSORBENT CASE STATE AND RESTORE IT AFTER BODY boolean prevAbsorbentPattern = absorbentPattern; boolean prevAbsorbentCondition = absorbentCondition; graph.getChild(n, Node.Type.Body).accept(this, arg); absorbentCondition = prevAbsorbentCondition; ifContext = prevIfContext; absorbentPattern = prevAbsorbentPattern; stopCaseCFG = absorbentPattern && absorbentCondition; absorbentPattern = false; absorbentCondition = false; returnSet.peek().addAll(Set.copyOf(hangingNodes)); } } @Override public void visitSelectable(Node n, Void arg) { if (graph.getChildren(n).isEmpty() || this.isAbsorbentPattern(graph.getChild(n, 0))) absorbentPattern = true; else absorbentPattern = false; super.visitSelectable(n, arg); } @Override public void visitGuard(Node n, Void arg){ if (this.isIfTrueGuard(n)) if (this.isAbsorbentCondition(n)) absorbentCondition = true; super.visitGuard(n,arg); } Loading @@ -246,7 +270,7 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator public void visitVariable(Node n, Void arg) { connectTo(n); if (parametersContext && if (graph.isPatternZone(n) && !this.isMatchExprPattern(n) && ((Variable) n).getContext() == Variable.Context.Use) guardHangingStack.peek().addAll(hangingNodes); } Loading @@ -255,7 +279,7 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator public void visitLiteral(Node n, Void arg) { connectTo(n); if (parametersContext) if (graph.isPatternZone(n) && !this.isMatchExprPattern(n)) guardHangingStack.peek().addAll(hangingNodes); } Loading @@ -274,15 +298,6 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator connectTo(n); } @Override public void visitParameters(Node n, Void arg) { parametersContext = true; super.visitParameters(n, arg); parametersContext = false; connectTo(n); } @Override public void visitParameterOut(Node n, Void arg) { Loading @@ -305,16 +320,17 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator // LIST COMPREHENSIONS AND LISTS IN LIST COMPREHENSIONS @Override public void visitListComprehension(Node n, Void arg) { lcStack.push(new HashSet<>()); lcPrevRestriction.push(null); graph.getChild(n, Node.Type.Restrictions).accept(this, arg); graph.getChild(n, Node.Type.Value).accept(this, arg); ttl = 1; hangingNodes.addAll(lcStack.peekFirst()); connectTo(lcPrevRestriction.pop()); Node restrictions = graph.getChild(n, Node.Type.Restrictions); Node generator = graph.getChild(restrictions, Node.Type.Generator); // ERROR: More than 1 generator? graph.getChild(generator, Node.Type.Iterator).accept(this, arg); ttl = INFINITY; lcStack.pop(); Node firstGenerator = graph.getChild(restrictions, Node.Type.Generator); //connectTo(graph.getChild(firstGenerator, Node.Type.Iterator)); clearHanging(); hangingNodes.add(firstGenerator); connectTo(n); } @Override Loading @@ -329,36 +345,65 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator @Override public void visitFilter(Node n, Void arg) { super.visitFilter(n,arg); lcStack.peekFirst().addAll(hangingNodes); connectTo(lcPrevRestriction.pop()); clearHanging(); Node filterExpression = graph.getChild(n, Node.Type.Value); hangingNodes.add(filterExpression); lcPrevRestriction.push(filterExpression); } @Override public void visitGenerator(Node n, Void arg) { boolean isFirstGenerator = lcPrevRestriction.peek() == null; new EDG(graph).getChild(n, Node.Type.Iterator).accept(this, arg); new EDG(graph).getChild(n, Node.Type.Variable).accept(this, arg); lcStack.peekFirst().addAll(hangingNodes); connectTo(n); if (!isFirstGenerator) connectTo(lcPrevRestriction.pop()); clearHanging(); hangingNodes.add(n); lcPrevRestriction.push(n); } @Override public void visitList(Node n, Void arg) { super.visitList(n, arg); connectTo(n); if (graph.isPatternZone(n) && !this.isMatchExprPattern(n)) { if ((graph.getParent(n).getType() != Node.Type.List) && graph.getChildren(n).isEmpty()); guardHangingStack.peek().addAll(hangingNodes); } } private boolean isAbsorbentPattern(Node n) { if (n.getType() == Node.Type.Variable && ((Variable) n).getContext() == Variable.Context.Definition) return true; return false; } private boolean isIfTrueGuard(Node n) { private boolean isAbsorbentCondition(Node n) { List<Node> guardChildren = graph.getChildren(n); if (guardChildren.isEmpty()) return false; return true; Node exprNode = graph.getChildren( graph.getChildren( guardChildren.get(0) ).get(0) ).get(0); return exprNode.getType() == Node.Type.Literal && exprNode.getName().equals("true") && ifContext; exprNode.getName().equals("true"); } private boolean isMatchExprPattern(Node n) { return graph.getAncestor(n, Node.Type.Equality) != null || graph.getAncestor(n, Node.Type.Generator) != null; } } No newline at end of file e-Knife/src/main/java/eknife/erlang/ValueEdgeGenerator.java +29 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package eknife.erlang; import java.util.List; import java.util.Set; import edg.constraint.*; import edg.graph.Edge; Loading Loading @@ -158,6 +159,14 @@ public class ValueEdgeGenerator { } } } private boolean isCFGReached(Node node) { Set<Edge> outgoingCFGEdges = this.last.getEdges(node, LAST.Direction.Forwards); outgoingCFGEdges.removeIf(e -> e.getType() != Edge.Type.ControlFlow); return outgoingCFGEdges.size() > 0; } private void generateListComprehensionEdges() { final List<Node> listComprehensionNodes = this.last.getNodes(Node.Type.ListComprehension); Loading @@ -178,10 +187,27 @@ public class ValueEdgeGenerator { { final Node pattern = this.last.getChild(generator, Node.Type.Variable); final Node expression = this.last.getChild(generator, Node.Type.Iterator); this.generatePatternStructureEdges(generator, pattern); this.last.addEdge(expression, generator, Edge.Type.Value, EmptyConstraint.getConstraint()); this.last.addEdge(expression, pattern, Edge.Type.Value, positiveConstraint); } } private void generatePatternStructureEdges(Node generator, Node pattern){ switch(pattern.getType()){ case List: case DataConstructor: case Literal: this.last.addEdge(pattern, generator, Edge.Type.Value, EmptyConstraint.getConstraint()); List<Node> children = last.getChildrenNonResult(pattern); for (Node child : children) this.generatePatternStructureEdges(generator, child); break; default: break; } } private void generateRoutineCallEdges() { final List<Node> calls = this.last.getNodes(Node.Type.Call); Loading Loading @@ -212,6 +238,9 @@ public class ValueEdgeGenerator { if (this.last.getChildren(returnNode).isEmpty()) continue; if (!isCFGReached(returnNode)) continue; final Node returnExpr = this.last.getChild(returnNode, Node.Type.Value); final String returnText = returnNode.getName(); final int dstId = Integer.parseInt(returnText.substring(returnText.lastIndexOf(" ") + 1)); Loading Loading
EDG/src/main/java/edg/slicing/ConstrainedAlgorithm.java +10 −1 Original line number Diff line number Diff line Loading @@ -78,6 +78,11 @@ public class ConstrainedAlgorithm implements SlicingAlgorithm edge.getType() == Edge.Type.Call); } // TRAVERSAL RESTRICTION TODO: Change this restriction to construction time removing structural arcs // GENERATOR NODES CONTAIN VALUE EDGES THAT MUST BE TRAVERSED ONLY IF THE GENERATOR NODE IS INCLUDED BY CONTROL if (currentNode.getType() == Node.Type.Generator && work.getPreviousEdgeType() != Edge.Type.Control) edges.removeIf(edge -> edge.getType() == Edge.Type.Value); for (NodeConstraint nodeConstraint : nodeConstraints) nodeConstraint.resolve(phase, edges); Loading Loading @@ -109,6 +114,10 @@ public class ConstrainedAlgorithm implements SlicingAlgorithm if (!currentEdge.isTraversable()) return newWorks; int sourceId = edg.getEdgeSource(currentEdge).getId(); int targetId = edg.getEdgeTarget(currentEdge).getId(); try { final Constraints constraints = work.getConstraints(); Loading
e-Knife/src/main/java/eknife/erlang/ControlFlowGenerator.java +99 −54 Original line number Diff line number Diff line Loading @@ -18,15 +18,17 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator protected final Deque<Set<Node>> switchSelectorStack = new LinkedList<>(); protected final Deque<Boolean> switchHasDefaultStack = new LinkedList<>(); protected boolean absorbentPattern = false; protected boolean absorbentCondition = false; protected boolean ifContext = false; protected boolean stopCaseCFG = false; // protected boolean ifContext = false; protected int ttl = INFINITY; protected boolean generating = false; protected boolean parametersContext = false; protected Deque<Node> routineHanging = new LinkedList<>(); protected Deque<Node> anonymousRoutineHanging = new LinkedList<>(); protected final Deque<Set<Node>> lcStack = new LinkedList<>(); protected final Deque<Node> lcPrevRestriction = new LinkedList<>(); protected final Deque<Set<Node>> prevCaseGuardHanging = new LinkedList<>(); public ControlFlowGenerator(LAST graph) Loading Loading @@ -74,7 +76,7 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator routineHanging.push(n); super.visitRoutine(n, arg); routineHanging.pop(); hangingNodes.clear(); clearHanging(); hangingNodes.addAll(clauseHangingStack.peek()); connectTo(n); clauseHangingStack.pop(); Loading @@ -88,11 +90,12 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator { clauseHangingStack.push(new HashSet<>()); guardHangingStack.push(new HashSet<>()); routineHanging.push(n); anonymousRoutineHanging.push(n); connectTo(n); clearHanging(); super.visitAnonymousRoutine(n, arg); routineHanging.pop(); hangingNodes.clear(); anonymousRoutineHanging.pop(); clearHanging(); hangingNodes.addAll(clauseHangingStack.peek()); connectTo(n); guardHangingStack.pop(); Loading @@ -102,9 +105,8 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator @Override public void visitClause(Node n, Void arg) { if (graph.getParent(n).equals(routineHanging.peek())) { hangingNodes.clear(); if (graph.getParent(n).equals(routineHanging.peek())) { clearHanging(); hangingNodes.add(routineHanging.peek()); } Loading @@ -115,17 +117,25 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator returnSet.push(new HashSet<>()); graph.getChild(n, Node.Type.ParameterIn).accept(this, arg); graph.getChild(n, Node.Type.Parameters).accept(this, arg); graph.getChild(n, Node.Type.Guard).accept(this, arg); Node guardNode = graph.getChild(n, Node.Type.Guard); guardNode.accept(this, arg); if (!graph.getChildren(guardNode).isEmpty()) guardHangingStack.peek().addAll(hangingNodes); graph.getChild(n, Node.Type.Body).accept(this, arg); hangingNodes.addAll(returnSet.peek()); returnSet.pop(); hangingNodes.addAll(returnSet.pop()); graph.getChild(n, Node.Type.ParameterOut).accept(this, arg); hangingNodes.addAll(guardHangingStack.peek()); guardHangingStack.peek().clear(); connectTo(n); } @Override public void visitBlock(Node n, Void arg) { returnSet.push(new HashSet<>()); super.visitBlock(n, arg); hangingNodes.addAll(returnSet.pop()); } @Override public void visitEnclosed(Node n, Void arg) { Loading Loading @@ -153,6 +163,8 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator { super.visitDataConstructor(n, arg); connectTo(n); if (graph.isPatternZone(n) && !this.isMatchExprPattern(n)) guardHangingStack.peek().addAll(hangingNodes); } @Override Loading @@ -172,55 +184,67 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator @Override public void visitSwitch(Node n, Void arg) { if (n.getInfo().getConstruction().equals("if")) ifContext = true; else ifContext = false; returnSet.push(new HashSet<>()); switchStack.push(new HashSet<>()); graph.getChild(n, Node.Type.Selector).accept(this, arg); graph.getChild(n, Node.Type.Cases).accept(this, arg); hangingNodes.clear(); clearHanging(); hangingNodes.addAll(returnSet.peek()); connectTo(n); returnSet.pop(); absorbentCondition = false; ifContext = false; } @Override public void visitCases(Node n, Void arg){ absorbentPattern = false; absorbentCondition = false; stopCaseCFG = false; prevCaseGuardHanging.push(new HashSet<>()); super.visitCases(n, arg); returnSet.peek().addAll(Set.copyOf(prevCaseGuardHanging.peek())); prevCaseGuardHanging.pop(); stopCaseCFG = false; } @Override public void visitCase(Node n, Void arg) { if(!absorbentCondition) { hangingNodes.addAll(prevCaseGuardHanging.peekFirst()); if(!stopCaseCFG) { hangingNodes.addAll(prevCaseGuardHanging.peek()); prevCaseGuardHanging.peek().clear(); graph.getChild(n, Node.Type.Selectable).accept(this, arg); graph.getChild(n, Node.Type.Guard).accept(this, arg); prevCaseGuardHanging.peek().addAll(Set.copyOf(hangingNodes)); boolean prevIfContext = ifContext; // SAVE THE ABSORBENT CASE STATE AND RESTORE IT AFTER BODY boolean prevAbsorbentPattern = absorbentPattern; boolean prevAbsorbentCondition = absorbentCondition; graph.getChild(n, Node.Type.Body).accept(this, arg); absorbentCondition = prevAbsorbentCondition; ifContext = prevIfContext; absorbentPattern = prevAbsorbentPattern; stopCaseCFG = absorbentPattern && absorbentCondition; absorbentPattern = false; absorbentCondition = false; returnSet.peek().addAll(Set.copyOf(hangingNodes)); } } @Override public void visitSelectable(Node n, Void arg) { if (graph.getChildren(n).isEmpty() || this.isAbsorbentPattern(graph.getChild(n, 0))) absorbentPattern = true; else absorbentPattern = false; super.visitSelectable(n, arg); } @Override public void visitGuard(Node n, Void arg){ if (this.isIfTrueGuard(n)) if (this.isAbsorbentCondition(n)) absorbentCondition = true; super.visitGuard(n,arg); } Loading @@ -246,7 +270,7 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator public void visitVariable(Node n, Void arg) { connectTo(n); if (parametersContext && if (graph.isPatternZone(n) && !this.isMatchExprPattern(n) && ((Variable) n).getContext() == Variable.Context.Use) guardHangingStack.peek().addAll(hangingNodes); } Loading @@ -255,7 +279,7 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator public void visitLiteral(Node n, Void arg) { connectTo(n); if (parametersContext) if (graph.isPatternZone(n) && !this.isMatchExprPattern(n)) guardHangingStack.peek().addAll(hangingNodes); } Loading @@ -274,15 +298,6 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator connectTo(n); } @Override public void visitParameters(Node n, Void arg) { parametersContext = true; super.visitParameters(n, arg); parametersContext = false; connectTo(n); } @Override public void visitParameterOut(Node n, Void arg) { Loading @@ -305,16 +320,17 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator // LIST COMPREHENSIONS AND LISTS IN LIST COMPREHENSIONS @Override public void visitListComprehension(Node n, Void arg) { lcStack.push(new HashSet<>()); lcPrevRestriction.push(null); graph.getChild(n, Node.Type.Restrictions).accept(this, arg); graph.getChild(n, Node.Type.Value).accept(this, arg); ttl = 1; hangingNodes.addAll(lcStack.peekFirst()); connectTo(lcPrevRestriction.pop()); Node restrictions = graph.getChild(n, Node.Type.Restrictions); Node generator = graph.getChild(restrictions, Node.Type.Generator); // ERROR: More than 1 generator? graph.getChild(generator, Node.Type.Iterator).accept(this, arg); ttl = INFINITY; lcStack.pop(); Node firstGenerator = graph.getChild(restrictions, Node.Type.Generator); //connectTo(graph.getChild(firstGenerator, Node.Type.Iterator)); clearHanging(); hangingNodes.add(firstGenerator); connectTo(n); } @Override Loading @@ -329,36 +345,65 @@ public class ControlFlowGenerator extends VoidVisitor<Void> implements Generator @Override public void visitFilter(Node n, Void arg) { super.visitFilter(n,arg); lcStack.peekFirst().addAll(hangingNodes); connectTo(lcPrevRestriction.pop()); clearHanging(); Node filterExpression = graph.getChild(n, Node.Type.Value); hangingNodes.add(filterExpression); lcPrevRestriction.push(filterExpression); } @Override public void visitGenerator(Node n, Void arg) { boolean isFirstGenerator = lcPrevRestriction.peek() == null; new EDG(graph).getChild(n, Node.Type.Iterator).accept(this, arg); new EDG(graph).getChild(n, Node.Type.Variable).accept(this, arg); lcStack.peekFirst().addAll(hangingNodes); connectTo(n); if (!isFirstGenerator) connectTo(lcPrevRestriction.pop()); clearHanging(); hangingNodes.add(n); lcPrevRestriction.push(n); } @Override public void visitList(Node n, Void arg) { super.visitList(n, arg); connectTo(n); if (graph.isPatternZone(n) && !this.isMatchExprPattern(n)) { if ((graph.getParent(n).getType() != Node.Type.List) && graph.getChildren(n).isEmpty()); guardHangingStack.peek().addAll(hangingNodes); } } private boolean isAbsorbentPattern(Node n) { if (n.getType() == Node.Type.Variable && ((Variable) n).getContext() == Variable.Context.Definition) return true; return false; } private boolean isIfTrueGuard(Node n) { private boolean isAbsorbentCondition(Node n) { List<Node> guardChildren = graph.getChildren(n); if (guardChildren.isEmpty()) return false; return true; Node exprNode = graph.getChildren( graph.getChildren( guardChildren.get(0) ).get(0) ).get(0); return exprNode.getType() == Node.Type.Literal && exprNode.getName().equals("true") && ifContext; exprNode.getName().equals("true"); } private boolean isMatchExprPattern(Node n) { return graph.getAncestor(n, Node.Type.Equality) != null || graph.getAncestor(n, Node.Type.Generator) != null; } } No newline at end of file
e-Knife/src/main/java/eknife/erlang/ValueEdgeGenerator.java +29 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package eknife.erlang; import java.util.List; import java.util.Set; import edg.constraint.*; import edg.graph.Edge; Loading Loading @@ -158,6 +159,14 @@ public class ValueEdgeGenerator { } } } private boolean isCFGReached(Node node) { Set<Edge> outgoingCFGEdges = this.last.getEdges(node, LAST.Direction.Forwards); outgoingCFGEdges.removeIf(e -> e.getType() != Edge.Type.ControlFlow); return outgoingCFGEdges.size() > 0; } private void generateListComprehensionEdges() { final List<Node> listComprehensionNodes = this.last.getNodes(Node.Type.ListComprehension); Loading @@ -178,10 +187,27 @@ public class ValueEdgeGenerator { { final Node pattern = this.last.getChild(generator, Node.Type.Variable); final Node expression = this.last.getChild(generator, Node.Type.Iterator); this.generatePatternStructureEdges(generator, pattern); this.last.addEdge(expression, generator, Edge.Type.Value, EmptyConstraint.getConstraint()); this.last.addEdge(expression, pattern, Edge.Type.Value, positiveConstraint); } } private void generatePatternStructureEdges(Node generator, Node pattern){ switch(pattern.getType()){ case List: case DataConstructor: case Literal: this.last.addEdge(pattern, generator, Edge.Type.Value, EmptyConstraint.getConstraint()); List<Node> children = last.getChildrenNonResult(pattern); for (Node child : children) this.generatePatternStructureEdges(generator, child); break; default: break; } } private void generateRoutineCallEdges() { final List<Node> calls = this.last.getNodes(Node.Type.Call); Loading Loading @@ -212,6 +238,9 @@ public class ValueEdgeGenerator { if (this.last.getChildren(returnNode).isEmpty()) continue; if (!isCFGReached(returnNode)) continue; final Node returnExpr = this.last.getChild(returnNode, Node.Type.Value); final String returnText = returnNode.getName(); final int dstId = Integer.parseInt(returnText.substring(returnText.lastIndexOf(" ") + 1)); Loading