// strategy.beh -- Strategy graph manipulation // $Id: strategy.beh,v 1.3 2000/12/07 22:47:07 dougo Exp $ // 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 = sources.collectSourceEdges(this); } if (targets == null) { targets = collectTargets(); } return this; @) ClassGlobSet collectTargets() = allDests(ClassGlobCollector); 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); } @) } ClassGlobSpec { Integer_NList collectSourceEdges(StrategyGraph sg) = allClassNames { init (@ return_val = new Integer_NList(); @) before ClassName (@ return_val.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++) return_val.addElement(new Integer(i)); @) } } PathDirective { StrategyGraph toGraph(ClassName source) to { NegativeConstraint, PositiveConstraint, To, ToStop, NameMap } { (@ 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: via/through edge globs in strategies 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); @) before NameMap (@ return_val.set_namemap(host); @) } } 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; @) } NameMap { (@ Hashtable dict; @) Hashtable get_dict() (@ if (dict == null) dict = buildDict(); return dict; @) Hashtable buildDict() to Name { init (@ return_val = new Hashtable(); @) (@ Name sgName, cgName; @) before -> *,sgName,Name (@ sgName = dest; @) before -> *,cgName,Name (@ cgName = dest; @) after NameBinding (@ return_val.put(ClassName.parse(sgName.toString()), ClassName.parse(cgName.toString())); @) } } 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 { /** The number of edges. */ public int numEdges() (@ return edgeVec.size(); @) /** Return a list of indices of strategy edges incoming to c. */ public Vector getIncomingIndices(NameI c) allDests(SGEdgeMatcher); /** Return a list of indices of strategy edges outgoing from c. */ public Vector getOutgoingIndices(NameI c) allSources(SGEdgeMatcher); } SGEdgeMatcher { init (@ return_val = new Vector(); @) before ClassGlobSpec (@ if (host.match((ClassName) c)) return_val.addElement(new Integer(index)); index++; @) } StrategyGraph { public Enumeration getVertices() // through -> *,edges,* bypassing { -> *,sources,*, -> *,targets,*, -> *,constraint,* } to ClassName { (@ Hashtable vertices = new Hashtable(); @) before ClassName (@ vertices.put(host, host); @) return (@ vertices.elements() @) } public Enumeration getSources() // through -> *,sources,* bypassing { -> *,edges,*, -> *,targets,* } to { ClassName, AnyClass } { (@ Vector sources = new Vector(); boolean any = false; @) before AnyClass (@ any = true; @) before ClassName (@ sources.addElement(host); @) return (@ any ? null : sources.elements() @) } public Enumeration getTargets() // through -> *,targets,* bypassing { -> *,edges,*, -> *,sources,* } to { ClassName, AnyClass } { (@ Vector targets = new Vector(); boolean any = false; @) before AnyClass (@ any = true; @) before ClassName (@ targets.addElement(host); @) return (@ any ? null : targets.elements() @) } } StrategyGraph { /** Does the edge in the traversal graph satisfy the element predicate for the indexed edge in the strategy graph, with the given name map? */ public boolean meetsConstraint(int i, Edge edge, Dictionary nameMap) (@ SGEdge sgedge = (SGEdge) edgeVec.elementAt(i); return sgedge.checkConstraint(edge, nameMap); @) } SGEdge { boolean checkConstraint(Edge edge, Dictionary nameMap) via Constraint to GlobSpec { init (@ return_val = true; @) before GlobSpec (@ // FIXME: this should be cached GlobSpec mapped = host.deepCopy(); mapped.mapNames(nameMap); return_val = mapped.match(edge); @) after Bypassing (@ return_val = !return_val; @) } } StrategyGraph { String startSetCode(String indent, String setname, ClassName source) (@ if (!sources.match(source)) { System.err.println("Error: strategy cannot start at " + source + "."); 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(); @) }