aboutsummaryrefslogtreecommitdiff
path: root/sucl/graph.dcl
diff options
context:
space:
mode:
Diffstat (limited to 'sucl/graph.dcl')
-rw-r--r--sucl/graph.dcl208
1 files changed, 208 insertions, 0 deletions
diff --git a/sucl/graph.dcl b/sucl/graph.dcl
new file mode 100644
index 0000000..bd1738d
--- /dev/null
+++ b/sucl/graph.dcl
@@ -0,0 +1,208 @@
+definition module graph
+
+from StdOverloaded import ==
+
+// A rule associating a replacement with a pattern
+//:: Rule sym var
+
+// A mapping from variables to nodes (unrooted)
+:: Graph sym var
+
+// A node, bearing the contents of a variable
+:: Node sym var
+ :== (sym,[var])
+
+/*
+
+graph.lit - Unrooted graphs
+===========================
+
+Description
+-----------
+
+This script implements an abstract type for unrooted graphs and useful
+functions to manipulate them.
+
+------------------------------------------------------------
+
+Interface
+---------
+
+Exported identifiers:
+
+> %export
+> compilegraph || Compile graph from list of node definitions
+> emptygraph || The empty unrooted graph
+> extgraph || Extend a graph with the image of a matching
+> foldgraph || Fold up a graph
+> graph || Unrooted graphs over functorspace * and nodespace **
+> instance || Check whether second graph is instance of first
+> instantiate || Matches a pattern in a graph, if possible
+> movegraph || Move a graph to a new node domain
+> nodecontents || Determine the contents of a node
+> nodelist || Determine the preorder list of reachable nodes from a given node
+> nodeset || Determine the reachable nodes from a given node
+> overwritegraph || Overwrite a graph with a given graph
+> paths || List of all paths in the graph
+> printgraph || Prints a graph seen from given nodes
+> prunegraph || Undefine the contents of a node
+> redirectgraph || Redirects all references to nodes in a graph
+> refcount || Determines the reference count function of a graph
+> restrictgraph || Restricts the graph to certain defined nodes
+> showgraph || Text representation of a graph
+> updategraph || Update the contents of a node
+
+Required types: none
+
+------------------------------------------------------------
+
+Includes
+--------
+
+> %include "basic.lit" || foldlr mapsnd showlist showpair
+> %include "pfun.lit" || domres emptypfun extend overwrite pfun postcomp restrict showpfun total
+
+------------------------------------------------------------
+
+Implementation
+--------------
+
+> abstype graph * **
+> with emptygraph :: graph * **
+> updategraph :: ** -> (*,[**]) -> graph * ** -> graph * **
+> prunegraph :: ** -> graph * ** -> graph * **
+> restrictgraph :: [**] -> graph * ** -> graph * **
+> redirectgraph :: (**->**) -> graph * ** -> graph * **
+> overwritegraph :: graph * ** -> graph * ** -> graph * **
+> showgraph :: (*->[char]) -> (**->[char]) -> graph * ** -> [char]
+> nodecontents :: graph * ** -> ** -> (bool,(*,[**]))
+> nodeset :: graph * ** -> [**] -> ([**],[**])
+
+> movegraph :: (***->**) -> [***] -> graph * *** -> graph * **
+> printgraph :: (*->[char]) -> (**->[char]) -> graph * ** -> [**] -> [[char]]
+> refcount :: graph * ** -> [**] -> ** -> num
+
+> graph * ** == pfun ** (*,[**])
+
+> emptygraph = emptypfun
+> updategraph = extend
+> prunegraph = restrict
+> restrictgraph = domres
+> redirectgraph = postcomp.mapsnd.map
+> overwritegraph = overwrite
+> showgraph showfunc shownode = showpfun shownode (showpair showfunc (showlist shownode))
+*/
+
+// The empty graph.
+emptygraph :: Graph .sym .var
+
+// Assign a node to a variable in a graph.
+updategraph :: .var (Node .sym .var) (Graph .sym .var) -> Graph .sym .var
+
+// Unassign a variable in a graph, making it free.
+prunegraph :: .var (Graph .sym .var) -> Graph .sym .var
+
+// Restrict a graph to a given domain, i.e.
+// make all variables free except those in the domain.
+restrictgraph :: !.[var] .(Graph sym var) -> Graph sym var | == var
+
+// Redirect references (node arguments) in a graph
+// according to a redirection function
+redirectgraph :: (.var->.var) !(Graph .sym .var) -> Graph .sym .var | == var
+
+// Overwrite the variables in the second graph by their contents in the first.
+// Keeps the contents of the second graph if free in the first.
+overwritegraph :: !(Graph .sym .var) (Graph .sym .var) -> Graph .sym .var
+
+// Movegraph moves a graph to a different variable domain
+// Requires a list of bound variables in the graph
+movegraph :: (var1->.var2) !.[var1] .(Graph sym var1) -> Graph sym .var2 | == var1
+
+// Varcontents obtains the contents of a variable in a graph
+// Returns a boolean determining if it's bound, and
+// its contents if the boolean is True.
+varcontents :: !(Graph .sym var) var -> (.Bool,Node .sym var) | == var
+
+// Graphvars determines the top-level-bound and free variables in a graph,
+// reachable from a given list of variables.
+// No duplicates.
+graphvars :: .(Graph sym var) !.[var] -> (.[var],.[var]) | == var
+
+// Graphvarlist determines all top level variables in a graph,
+// reachable from a given list of variables.
+// No duplicates.
+varlist :: .(Graph sym var) !.[var] -> .[var] | == var
+
+// Cannot remember what this one does???
+prefix :: .(Graph sym var) .[var] !.[var] -> .([var],[var]) | == var
+
+// Do reference counting in a graph for the outer bindings.
+// References from case branches are counted once only.
+// Initial list of variables is counted too.
+refcount :: .(Graph sym var) !.[var] -> (var -> Int) | == var
+
+// Determine whether the second argument is an instance of the first,
+// i.e. whether there is a structure preserving mapping from the first to the second.
+// Free variables may be mapped to anything.
+// Bound variables may not be mapped to free variables.
+isinstance
+ :: (.Graph sym pvar,pvar)
+ (.Graph sym var,var)
+ -> Bool
+ | == sym
+ & == var
+ & == pvar
+
+/*
+> compilegraph :: [(**,(*,[**]))] -> graph * **
+> compilegraph = foldr (uncurry updategraph) emptygraph
+
+------------------------------------------------------------------------
+
+> foldgraph
+> :: (**->***->***) ->
+> (**->***) ->
+> (*->[***]->***) ->
+> graph * ** ->
+> [**] ->
+> [***]
+
+> foldgraph folddef foldref foldcont graph roots
+> = foldedroots
+> where count = refcount graph roots
+> (unused,foldedroots) = foldlm fold ([],roots)
+> fold (seen,node)
+> = (seen,foldref node), if member seen node
+> = (seen'',cond (def&count node>1) (folddef node folded) folded), otherwise
+> where (seen'',folded)
+> = (seen',foldcont sym foldedargs), if def
+> = (node:seen,foldref node), otherwise
+> (seen',foldedargs) = foldlm fold (node:seen,args)
+> (def,(sym,args)) = nodecontents graph node
+
+
+> paths :: graph * ** -> ** -> [[**]]
+
+> paths graph node
+> = paths' [] node []
+> where paths' top node rest
+> = rest, if member top node
+> = top':cond def (foldr (paths' top') rest args) rest, otherwise
+> where (def,(sym,args)) = nodecontents graph node
+> top' = node:top
+
+
+> extgraph :: graph * ** -> graph * *** -> [***] -> pfun *** ** -> graph * ** -> graph * **
+> extgraph sgraph pattern pnodes matching graph
+> = foldr addnode graph pnodes
+> where addnode pnode
+> = total id (postcomp addnode' matching) pnode, if fst (nodecontents pattern pnode)
+> = id, otherwise
+> addnode' snode
+> = updategraph snode scont, if sdef
+> = id, otherwise
+>|| = error "extgraph: closed node mapped to open node", otherwise
+> || Could have used id, but let's report error when there is one...
+> where (sdef,scont) = nodecontents sgraph snode
+
+*/