extract.lit - Folding of subject graphs ======================================= Description ----------- This module defines functions that can fold subject graphs, as they are usually found at the tips of the trace of a symbolic reduction process. Three versions are provided; `actualfold' for folding initiated by autorecursion, `splitrule' for folding initiated by introduced recursion and `finishfold' for folding initiated without recursion. ------------------------------------------------------------ Interface --------- Exported identifiers: > %export > actualfold || Fold subject graph according to autorecursion > splitrule || Fold subject graph according to introduced recursion > finishfold || Finish folding by introducing areas ------------------------------------------------------------ Includes -------- > %include "dnc.lit" > %include "../src/basic.lit" > %include "../src/pfun.lit" > %include "../src/graph.lit" > %include "../src/rule.lit" ------------------------------------------------------------ Implementation -------------- `Actualfold foldarea foldcont hist rule' is the result of folding occurrences of areas in `hist' to `foldcont', and introducing new areas for parts that aren't folded. `Self' determines whether an instance of a history graph is the history graph itself. We don't want to fold back something we unfolded earlier! > actualfold :: > [**] -> > [**] -> > (rgraph * **->(*,[**])) -> > (***->**->bool) -> > (*,[***]) -> > [(***,graph * ***)] -> > rule * ** -> > optional (rule * **,[rgraph * **]) > actualfold deltanodes rnfnodes foldarea self foldcont hist rule > = Absent, if list3=[] > = Present (mkrule rargs rroot rgraph'',areas'), otherwise > where rargs = lhs rule; rroot = rhs rule; rgraph = rulegraph rule > list2 = map (pairwith (findoccs hist rule)) (nodelist rgraph [rroot]--nodelist rgraph rargs) > || list2: list combining every node with list of every instantiable history graph > list3 = [(rnode,hgraph,mapping)|(rnode,(((hroot,hgraph),mapping):rest))<-list2] > || list3: list combining every instantiable node with first instantiable history graph > rgraph' > = foldr foldrec rgraph list3 > where foldrec (rnode,hgraph,mapping) = updategraph rnode (mapsnd (map (lookup mapping)) foldcont) > (rgraph'',areas') = finishfold foldarea fixednodes singlenodes rroot rgraph' > fixednodes = intersect (mkset (argnodes++foldednodes++rnfnodes)) (nodelist rgraph' [rroot]) > singlenodes = intersect deltanodes (nodelist rgraph' [rroot]) > argnodes = nodelist rgraph' rargs > foldednodes = map fst3 list3 > findoccs > :: [(***,graph * ***)] -> > rule * ** -> > ** -> > [((***,graph * ***),[(***,**)])] > findoccs hist rule rnode > = [ ((hroot,hgraph),mapping) > | ((hroot,hgraph),(seen,mapping,[]))<-list1 || Find instantiable history rgraphs... > ; unshared rnode (hroot,hgraph) mapping || ...which don't have shared contents... >|| ; ~self hroot rnode || ...and aren't the history graph itself > ] > where rargs = lhs rule; rroot = rhs rule; rgraph = rulegraph rule > list1 > = [((hroot,hgraph),inst (hroot,hgraph))|(hroot,hgraph)<-hist] > where inst (hroot,hgraph) > = instantiate (hgraph,rgraph) (hroot,rnode) ([],[],[]) > || list1: all instantiation attempts at rnode with the history rgraphs > unshared rnode (hroot,hgraph) mapping > = disjoint inner outer > where inner = map (lookup mapping) (fst (nodeset hgraph [hroot])) > outer = nodelist (prunegraph rnode rgraph) (rroot:rargs)--[rnode] ------------------------------------------------------------------------ Splitting a rule into areas to fold to a certain area > splitrule > :: (rgraph * **->(*,[**])) -> > [**] -> > [**] -> > rule * ** -> > rgraph * ** -> > (rule * **,[rgraph * **]) > splitrule fold rnfnodes deltanodes rule area > = (mkrule rargs rroot rgraph'',area':areas) > where > rargs = lhs rule; rroot = rhs rule; rgraph = rulegraph rule > aroot = rgraphroot area; agraph = rgraphgraph area > (rgraph'',areas) = finishfold fold fixednodes deltanodes rroot rgraph' > fixednodes = intersect (mkset (aroot:nodelist rgraph' rargs++rnfnodes)) (nodelist rgraph' [rroot]) > rgraph' = updategraph aroot (fold area') rgraph > area' = mkrgraph aroot agraph' > agraph' = foldr addnode emptygraph ins > ins = nodelist agraph [aroot]--outs > outs = nodelist (prunegraph aroot rgraph) (rroot:rargs++snd (nodeset agraph [aroot]))--[aroot] > addnode node = updategraph node (snd (dnc (const "in splitrule") rgraph node)) ------------------------------------------------------------ `Finishfold foldarea fixednodes root graph' finishes folding of a graph by introducing areas for parts of the graph that are not fixed in some way (e.g. when part of the pattern of the rule, already folded, or bearing a delta function symbol). > finishfold > :: (rgraph * **->(*,[**])) -> > [**] -> > [**] -> > ** -> > graph * ** -> > (graph * **,[rgraph * **]) > finishfold foldarea fixednodes singlenodes root graph > = (graph',areas) > where graph' = foldr foldarea' graph areas > foldarea' area = updategraph (rgraphroot area) (foldarea area) > areas = depthfirst generate process arearoots > process aroot > = mkrgraph aroot (foldr addnode emptygraph ins) > where outs_and_aroot = nodelist (prunegraph aroot graph) arearoots++fixednodes > ins = aroot:nodelist graph [aroot]--outs_and_aroot > generate area > = snd (nodeset agraph [aroot])--fixednodes > where aroot = rgraphroot area; agraph = rgraphgraph area > arearoots = mkset (root:singlenodes++singfixargs)--fixednodes > singfixargs = concat (map arguments (singlenodes++fixednodes)) > arguments node > = args, if def > = [], otherwise > where (def,(sym,args)) = dnc (const "in finishfold/1") graph node > addnode node > = updategraph node cnt, if def > = id, otherwise > where (def,cnt) = dnc (const "in finishfold/2") graph node