implementation module rewr // $Id$ import rule import graph import pfun import basic import StdEnv /* Rewriting of graphs Exported identifiers: \begin{description} \item[\tt unfold] Apply a rewrite rule to a graph \item[\tt xunfold] As {\tt unfold}, but also provides full matching from the applied rule to the (resulting) subject graph \item[\tt fold] Apply a rewrite rule in reverse to a graph \item[\tt instantiate] Instantiate a graph with a pattern \end{description} Temporarily hidden: \begin{description} \item[\tt build] Build a copy of a graph \end{description} Temporarily not exported: \begin{description} \item[\tt getmap] Determine mapping from one graph to another \item[\tt existmap] Determine if a mapping from one graph to another exists \end{description} > %export foldfn getmapping instantiate xunfold unfold :: pfun *** ** -> || Mapping as result from match of lhs rule * *** -> || Rule to unfold ([**],graph * **,**) -> || Heap,graph,node ([**],graph * **,**) || New heap,graph,node > xunfold > :: ** -> || Root of the redex to unfold > rule * *** -> || Rule to unfold by > ( [**], || Unused heap > **, || Root of subject > graph * **, || Subject graph > pfun *** ** || Matching of pattern from rule to subject > ) -> > ( [**], || Remaining heap > **, || Possibly redirected root of subject > graph * **, || Extended subject graph > pfun *** ** || Extended matching from rule to subject > ) fold :: pfun *** ** -> || Mapping as result from match of rhs rule * *** -> || Rule to fold ([**],graph * **,**) -> || Heap,graph,node ([**],graph * **,**) || New heap,graph,node > build > :: graph * *** -> *** -> || Graph,root to be copied > ([**],[**],graph * **,pfun *** **) -> || Heap,init nodes,init graph,init mapping > ([**],[**],graph * **,pfun *** **) || New heap,new nodes,new graph,new mapping > getmap :: graph * *** -> *** -> graph * ** -> ** -> pfun *** ** > existmap :: graph * *** -> *** -> graph * ** -> ** -> bool Implementation > %include "basic.lit" > %include "pfun.lit" > %include "graph.lit" -instantiate > %include "rule.lit" */ xunfold :: var (Rule sym pvar) !( [var] , var , Graph sym var , Pfun pvar var ) -> ( [var] , var , Graph sym var , Pfun pvar var ) | == var & == pvar xunfold redexroot rule (heap,root,subject,matching) = (heap`,redirection root,redirectgraph redirection subject`,matching`) where (heap`,[rhs`:_],subject`,matching`) = build (rulegraph rule) (ruleroot rule) (heap,[],subject,matching) redirection = adjust redexroot rhs` id rewrinstantiate :: .(Graph sym pvar) // Pattern to instantiate with pvar // Root of the pattern var // Open node to instantiate (.[var],.Graph sym var) // Heap,graph -> .([var],Graph sym var) // New heap,graph | == var & == pvar rewrinstantiate pattern proot node (heap,graph) | not closed = (heap,graph) = (heap``,graph``) where (heap``,params``,graph``,_) = foldr (build pattern) (heap,[],graph`,extend proot node emptypfun) params (closed,(f,params)) = varcontents pattern proot graph` = updategraph node (f,params``) graph build :: (Graph sym pvar) pvar ( [var] , [var] , Graph sym var , !Pfun pvar var ) -> ( [var] , [var] , Graph sym var , Pfun pvar var ) | == var & == pvar build pattern node (heap,nodes,graph,mapping) | seen = (heap,[seenas:nodes],graph,mapping) | not closed = (heap`,[node`:nodes],graph,mapping`) = (heap``,[node`:nodes],graph``,mapping``) where (seen,seenas) = apply mapping node [node`:heap`] = heap mapping` = extend node node` mapping (closed,(f,params)) = varcontents pattern node (heap``,params``,graph``,mapping``) = foldr (build pattern) (heap`,[],graph`,mapping`) params graph` = updategraph node` (f,params``) graph /* Mapping > getmap pattern patnode graph node > = getmapping nomatch pattern graph (patnode,node) id emptypfun > where nomatch = error "getmap: pattern and graph do not match" > existmap pattern patnode graph node > = getmapping False pattern graph (patnode,node) (const True) emptypfun */ getmapping :: tsym (Graph sym pvar) (Graph sym var) !(pvar,var) ((Pfun pvar var) -> tsym) !(Pfun pvar var) -> tsym | == sym & == var & == pvar getmapping failure patgraph graph (patnode,node) success mapping | seen = if (seenas==node) (success mapping) failure | not patdef = success mapping` | not (def && patfunc==func && eqlen patargs args) = failure = foldr (getmapping failure patgraph graph) success (zip2 patargs args) mapping` where (seen,seenas) = apply mapping patnode (patdef,(patfunc,patargs)) = varcontents patgraph patnode (def,(func,args)) = varcontents graph node mapping` = extend patnode node mapping /* The foldfn operation folds an area of a graph back to a function call. The following two conditions must be satisfied in order not to need a heap of fresh nodes: 1: At least one node is freed by the fold operation to hold the root of the redex. This is the root of the reduct; since it must be freed, the rule that is folded by must not be a projection function; 2: No other new nodes are necessary. Therefore, all nodes of the pattern of the rule that is folded by except the root must also occur in the replacement. Furthermore, the pattern of the rule is only given by its root symbol and its arguments; the arguments are open nodes. */ foldfn :: (Pfun pvar var) // Matching of replacement sym // Symbol at root of pattern [pvar] // Arguments of pattern pvar // Root of replacement (Graph sym var) // Subject graph -> Graph sym var // Folded subject | == pvar foldfn matching symbol arguments replacementroot sgraph = updategraph (domatching replacementroot) (symbol,map domatching arguments) sgraph where domatching = total nomatching matching nomatching = abort "foldfn: no matching of argument of pattern"