// CTGstrategy.beh -- Strategy graph manipulation // $Id: strategy.beh,v 1.5 1997/09/12 02:04:32 dougo Exp $ // modified: Binoy : 1997/11/26 // Convert all strategy expressions into graphs. StrategyExpression { abstract StrategyGraph toGraph(ClassName source); } StrategyGraph { init (@ edgeVec = new Vector(); edges = new SGEdge_SList(); @) StrategyGraph toGraph(ClassName source) (@ Enumeration e = edges.elements(); while (e.hasMoreElements()) { edgeVec.addElement(e.nextElement()); } if (sources == null) { if (sourceEdges != null) { ClassGlobSet set = new ClassGlobSet(new ClassGlob_Commalist()); Enumeration e2 = sourceEdges.elements(); while (e2.hasMoreElements()) { Integer i = (Integer) e2.nextElement(); SGEdge edge = (SGEdge) edgeVec.elementAt(i.intValue()); set.setadd(edge.get_source()); } sources = set; } else { sources = OneClassGlob.parse(source.toString()); } } if (sourceEdges == null) { sourceEdges = new Integer_NList(); sources.allClassNames(new SourceEdgeCollector(this, sourceEdges)); } if (targets == null) { ClassGlobCollector c = new ClassGlobCollector(); allDests(c); targets = c.get_spec(); } return this; @) void addEdge(SGEdge edge) (@ edgeVec.addElement(edge); edges.addElement(edge); @) } Integer_NList { /** Append elements of v if not already present. */ void setadd(Vector v) (@ Enumeration e = v.elements(); while (e.hasMoreElements()) { Integer i = (Integer) e.nextElement(); if (!contains(i)) addElement(i); } @) } SourceEdgeCollector { before ClassName (@ edges.setadd(sg.getOutgoingIndices(host)); @) before AnyClass (@ // Add every edge in the strategy graph. int n = sg.get_edgeVec().size(); for (int i = 0; i < n; i++) edges.addElement(new Integer(i)); @) } PathDirective { StrategyGraph toGraph(ClassName source) to { NegativeConstraint, PositiveConstraint, To, ToStop } { (@ SGEdge edge = new SGEdge(); @) before PathDirective (@ return_val = new StrategyGraph(); ClassGlobSpec sourcespec = OneClassGlob.parse(source.toString()); return_val.set_sources(sourcespec); return_val.set_sourceEdges(Integer_NList.parse("0")); edge.set_source(sourcespec); @) before NegativeConstraint (@ edge.set_constraint(host); @) before PositiveConstraint (@ GlobSpec glob = host.get_glob(); ClassGlobSpec cglob = glob.collectClassGlobs(); GlobSpec eglob = glob.collectEdgeGlobs(); if (eglob != null) { System.err.println("Error: edge globs not yet supported."); } else if (cglob != null) { edge.set_dest(cglob); return_val.addEdge(edge); edge = new SGEdge(); edge.set_source(cglob); } @) before ToStop (@ // Bypass all outgoing edges from the targets. Bypassing constraint = new Bypassing(); constraint.set_glob(host.get_targets().toOutgoingEdgeSpec()); edge.set_constraint(constraint.intersectWith(edge.get_constraint())); @) after TargetDirective (@ ClassGlobSpec targets = host.get_targets(); edge.set_dest(targets); return_val.addEdge(edge); return_val.set_targets(targets); @) } } Bypassing { NegativeConstraint intersectWith(NegativeConstraint constraint) (@ if (constraint == null) return this; if (constraint instanceof OnlyThrough) return constraint; return new Bypassing(glob.union(constraint.get_glob())); @) } StrategyVariable { StrategyGraph toGraph(ClassName source) (@ System.err.println("Error: strategy variables not yet implemented."); return null; @) } CompoundStrategy { StrategyGraph toGraph(ClassName source) (@ System.err.println("Error: compound strategies not yet implemented."); return null; @) } StrategyGraph { traversal allSources(GlobVisitor) { // through -> *,edges,* through -> *,source,* bypassing { -> *,sources,*, -> *,targets,*, -> *,dest,*, -> *,constraint,* } to ClassGlob; } traversal allDests(GlobVisitor) { // through -> *,edges,* through -> *,dest,* bypassing { -> *,sources,*, -> *,targets,*, -> *,source,*, -> *,constraint,* } to ClassGlob; } } StrategyGraph { /** Return a list of indices of strategy edges incoming to c. */ public Vector getIncomingIndices(ClassNameI c) allDests(SGEdgeMatcher); /** Return a list of indices of strategy edges outgoing from c. */ public Vector getOutgoingIndices(ClassNameI c) allSources(SGEdgeMatcher); } SGEdgeMatcher { init (@ return_val = new Vector(); @) before ClassGlobSpec (@ if (host.match((ClassName) c)) return_val.addElement(new Integer(index)); index++; @) } StrategyGraph { void markReachableForwardFromSources(TraversalGraph tg) // through -> *,sources,* bypassing { -> *,edges,*, -> *,targets,* } to { ClassName, AnyClass } { (@ StrategyGraph sg; @) before StrategyGraph (@ tg.unmarkAllForward(); sg = host;@) before AnyClass (@ tg.markAllForward(); @) before ClassName (@ tg.markReachableForwardFrom(host, sg); @) } void markReachableBackwardFromTargets(TraversalGraph tg) // through -> *,targets,* bypassing { -> *,edges,*, -> *,sources,* } to { ClassName, AnyClass } { (@ StrategyGraph sg; @) before StrategyGraph (@ tg.unmarkAllBackward(); sg = host;@) before AnyClass (@ tg.markAllBackward(); @) before ClassName (@ tg.markReachableBackwardFrom(host, sg); @) } } StrategyGraph { /** Does the edge in the traversal graph satisfy the element predicate for the indexed edge in the strategy graph? */ public boolean meetsConstraint(int i, TGEdge edge) (@ SGEdge sgedge = (SGEdge) edgeVec.elementAt(i); return sgedge.checkConstraint(edge); @) } SGEdge { boolean checkConstraint(TGEdge edge) // via Constraint to GlobSpec to { Bypassing, OnlyThrough } { init (@ return_val = true; @) before Bypassing (@ return_val = !host.get_glob().match(edge); @) before OnlyThrough (@ return_val = host.get_glob().match(edge); @) } } StrategyGraph { boolean allSourcesAndTargetsMarked(TraversalGraph tg) // through { -> *,sources,*, -> *,targets,* } bypassing -> *,edges,* to { ClassName, AnyClass } { init (@ return_val = true; @) (@ boolean glob_answer = false; @) before ClassGlobSpec (@ glob_answer = false; @) before AnyClass (@ glob_answer = true; @) before ClassName (@ TGVertex v = tg.findVertex(host, false); if (v.is_in_trav()) glob_answer = true; else System.err.println("Warning: " + host + " is not in the traversal graph."); @) after ClassGlobSpec (@ if (glob_answer == false) return_val = false; @) } } StrategyGraph { String startSetCode(String indent, String setname, ClassName startt) (@ if (!sources.match(startt)) { System.err.println("Error: strategy cannot start at " + startt + "."); return ""; } String code = ""; Enumeration e = sourceEdges.elements(); while (e.hasMoreElements()) { Integer i = (Integer) e.nextElement(); code += indent + setname + ".set(" + i.intValue() + ");\n"; } return code; @) } StrategyGraph { int size() (@ return edges.size(); @) } //to get the first ClassName in a StrategyGraph StrategyGraph { ClassName getFirst() through SGEdge to ClassName{ (@ boolean flag;@) init (@ flag = true; @) around ClassName (@ if(flag){ return_val = host; flag = false; } @) } }