implementation module strat // $Id$ import spine import history import rule import dnc import graph import pfun import basic from general import No,Yes,---> import StdEnv /* strat.lit - Extended functional strategy ======================================== Description ----------- Describe in a few paragraphs what this module defines. ------------------------------------------------------------ Interface --------- Exported identifiers: > %export > law > strategy > substrategy > makernfstrategy > checkconstr > checkimport > checklaws > checkrules > checktype > forcenodes > rulelaw > trylaw > tryrules Required types: identifier - type@source.lit type@source.lit ... ------------------------------------------------------------ Includes -------- > %include "dnc.lit" > %include "../src/basic.lit" > %include "../src/pfun.lit" > %include "../src/graph.lit" -instantiate > %include "../src/rule.lit" > %include "../src/spine.lit" ------------------------------------------------------------ Types ----- */ :: Substrategy sym var pvar result :== ((Spine sym var pvar) -> result) result var -> result :: Strategy sym var pvar result :== (Substrategy sym var pvar result) (Graph sym var) ((Subspine sym var pvar) -> result) result (Node sym var) -> result :: Law sym var pvar result :== (Substrategy sym var pvar result) (Graph sym var) ((Subspine sym var pvar) -> result) result [var] result -> result //------------------------------------------------------------------------ makernfstrategy :: .(History sym var) // History of previous rooted graphs attached to nodes (Strategy sym var pvar (Answer sym var pvar)) // Strategy for a defined node .[var] // List of nodes known in RNF (closed pattern nodes of subject rule+strict args) var // Root of replacement (Graph sym var) // Subject graph -> Answer sym var pvar | Eq sym & Eq var & Eq pvar makernfstrategy hist strat rnfnodes node graph = substrat [] spinecont rnfanswer node where spinecont spine = Yes spine rnfanswer = No substrat spinenodes spinecont rnfanswer node | isMember node spinenodes = subspinecont Cycle | isMember node rnfnodes = rnfanswer | not def = subspinecont Strict = strat` (substrat spinenodes`) graph subspinecont rnfanswer cnt where (def,cnt) = dnc (const "in makernfstrategy") graph node spinenodes` = [node:spinenodes] subspinecont subspine = spinecont (node,subspine) strat` = (checkhistory--->"strat.checkhistory begins from strat.makernfstrategy.substrat.strat`") (graph,node) spinenodes` hist strat /* ------------------------------------------------------------------------ NORMAL REWRITE RULE STRATEGY */ tryrules :: ((Graph sym pvar) pvar var -> .Bool) (Substrategy sym var pvar result) (Graph sym var) ((Subspine sym var pvar) -> result) .[var] -> result .[Rule sym pvar] -> result | == sym & == var & == pvar tryrules matchable substrat subject found sargs = foldr (matchrule matchable substrat subject found sargs) matchrule :: ((Graph sym pvar) pvar var -> .Bool) (Substrategy sym var pvar result) (Graph sym var) ((Subspine sym var pvar) -> result) .[var] (Rule sym pvar) result -> result | == sym & == var & == pvar matchrule matchable substrat subject found sargs rule fail | eqlen pargs sargs = matchnodes matchable` subject substrat foundsub fail pattern foundmatch pairs emptypfun = fail where pargs = arguments rule pattern = rulegraph rule pairs = zip2 pargs sargs matchable` = matchable pattern foundsub matching rnode spine = found (Partial rule matching rnode spine) foundmatch matching = found (Redex rule matching) matchnodes :: (pvar var -> .Bool) (Graph sym var) (Substrategy sym var pvar result) ((Pfun pvar var) pvar (Spine sym var pvar) -> result) result (Graph sym pvar) -> ((Pfun pvar var) -> result) [.(pvar,var)] (Pfun pvar var) -> result | == sym & == var & == pvar matchnodes matchable subject substrat found fail pattern = foldr matchpair where matchpair (pnode,snode) match matching | not (matchable pnode snode) = fail | not pdef = match (extend pnode snode matching) | not sdef = found matching pnode openspine = substrat (found matching pnode) rnfanswer snode where openspine = (snode,Open (mkrgraph pnode pattern)) rnfanswer | psym==ssym && eqlen pargs sargs = foldr matchpair match` psargs matching = fail match` matching = match (extend pnode snode matching) psargs = zip2 pargs sargs (pdef,(psym,pargs)) = (dnc (const "in matchnodes (pattern)")) pattern pnode (sdef,(ssym,sargs)) = (dnc (const "in matchnodes (subject)")) subject snode /* ------------------------------------------------------------------------ SPECIAL LAW STRATEGY Does not try to reduce arguments before matching. > rulelaw > :: rule * *** -> > law * ** *** **** > rulelaw rule substrat subject found rnf snids fail > = trylaw subject found snids rule fail > trylaw > :: graph * ** -> > (subspine * ** ***->****) -> > [**] -> > rule * *** -> > **** -> > **** > trylaw graph found sargs rule fail > = lawmatch pattern graph fail found' pairs emptypfun, if eqlen pargs sargs > = fail, otherwise > where pargs = lhs rule; pattern = rulegraph rule > found' matching = found (Redex rule matching) > pairs = zip2 pargs sargs > lawmatch > :: graph * *** -> > graph * ** -> > **** -> > (pfun *** **->****) -> > [(***,**)] -> > pfun *** ** -> **** > lawmatch pattern subject fail > = foldr lawmatch' > where lawmatch' (pnode,snode) success matching > = success matching', if ~pdef > = fail, if ~sdef \/ ssym~=psym \/ ~eqlen pargs sargs > = foldr lawmatch' success (zip2 pargs sargs) matching', otherwise > where matching' = extend pnode snode matching > (pdef,(psym,pargs)) = (dnc (const "in lawmatch/1")) pattern pnode > (sdef,(ssym,sargs)) = (dnc (const "in lawmatch/2")) subject snode */ rulelaw :: (Rule sym pvar) -> Law sym var pvar result | == sym & == var & == pvar rulelaw rule = law where law substrat subject found rnf snids fail = trylaw subject found snids rule fail trylaw :: (Graph sym var) (.(Subspine sym var pvar) -> result) .[var] (Rule sym pvar) result -> result | == sym & == var & == pvar trylaw graph found sargs rule fail | eqlen pargs sargs = lawmatch pattern graph fail found` pairs emptypfun = fail where pargs = arguments rule; pattern = rulegraph rule found` matching = found (Redex rule matching) pairs = zip2 pargs sargs lawmatch :: (Graph sym pvar) (Graph sym var) result -> ((Pfun pvar var) -> result) [.(pvar,var)] (Pfun pvar var) -> result | == sym & == var & == pvar lawmatch pattern subject fail = foldr lawmatch` where lawmatch` (pnode,snode) success matching | not pdef = success matching` | not sdef || ssym <> psym || not (eqlen pargs sargs) = fail = foldr lawmatch` success (zip2 pargs sargs) matching` where matching` = extend pnode snode matching (pdef,(psym,pargs)) = (dnc (const "in lawmatch (pattern)")) pattern pnode (sdef,(ssym,sargs)) = (dnc (const "in lawmatch (subject)")) subject snode /* ------------------------------------------------------------------------ FORCING EVALUATION OF (STRICT) ARGUMENTS */ forcenodes :: (Substrategy sym var pvar .result) ((Subspine sym var pvar) -> .result) .result !.[var] -> .result forcenodes substrat found rnf nodes = foldr forcenode rnf (zip2 [0..] nodes) where forcenode (argno,nid) rnfrest = substrat foundforce rnfrest nid where foundforce spine = found (Force argno spine) /* ------------------------------------------------------------------------ STRATEGY COMPOSITION Check for an instance in the termination history. */ checkhistory :: (Graph sym var,var) [var] (History sym var) (Strategy sym var pvar result) -> Strategy sym var pvar result | Eq sym & Eq var checkhistory (sgraph,snode) spinenodes history defaultstrategy = (if (isEmpty histpats) defaultstrategy unsafestrategy) <--- "strat.checkhistory ends" where histpats = (matchhistory--->"history.matchhistory begins from strat.checkhistory.histpats") history spinenodes sgraph snode unsafestrategy _ _ found _ _ = found (Unsafe (hd histpats)) // Check for curried applications checkarity :: !(sym -> Int) // Arity of function symbol (Strategy sym var pvar .result) // Default strategy (Substrategy sym var pvar .result) // Substrategy (Graph sym var) // Subject graph ((Subspine sym var pvar) -> .result) // Spine continuation .result // RNF continuation !.(Node sym var) // Subject node -> .result checkarity funarity defaultstrategy substrat subject found rnf (ssym,sargs) | shortern arity sargs = rnf | eqlenn arity sargs = defaultstrategy substrat subject found rnf (ssym,sargs) = abort ("checktype: symbol occurrence with actual arity "+++toString (length sargs)+++" greater than its type arity "+++toString arity) where arity = funarity ssym shortern n _ | n<=0 = False shortern _ [] = True shortern n [x:xs] = shortern (n-1) xs eqlenn n _ | n<0 = False eqlenn 0 [] = True eqlenn n [x:xs] = eqlenn (n-1) xs // Check for strict arguments checkstricts :: !(sym -> [.Bool]) // Strict arguments of function (Strategy sym var pvar .result) // Default strategy (Substrategy sym var pvar .result) // Substrategy (Graph sym var) // Subject graph ((Subspine sym var pvar) -> .result) // Spine continuation .result // RNF continuation !.(Node sym var) // Subject node -> .result checkstricts funstricts defaultstrategy substrat subject found rnf (ssym,sargs) = forcenodes substrat found rnf` strictnodes where rnf` = defaultstrategy substrat subject found rnf (ssym,sargs) tstricts = funstricts ssym strictnodes = [sarg\\(True,sarg)<-zip2 tstricts sargs] // Check (hard coded) laws checklaws :: [(sym,Law sym var pvar result)] (Strategy sym var pvar result) (Substrategy sym var pvar result) (Graph sym var) ((Subspine sym var pvar) -> result) result (Node sym var) -> result | == sym checklaws laws defaultstrategy substrat subject found rnf (ssym,sargs) = foldr checklaw (defaultstrategy substrat subject found rnf (ssym,sargs)) laws where checklaw (lsym,law) fail | lsym==ssym = law substrat subject found rnf sargs fail = fail // Check a list of rewrite rules (this is the real thing) checkrules :: ((Graph sym pvar) pvar var -> .Bool) (sym -> .[Rule sym pvar]) (Strategy sym var pvar result) (Substrategy sym var pvar result) (Graph sym var) ((Subspine sym var pvar) -> result) result (Node sym var) -> result | == sym & == var & == pvar checkrules matchable ruledefs defstrat substrat subject found rnf (ssym,sargs) = tryrules matchable substrat subject found sargs fail (ruledefs ssym) where fail = defstrat substrat subject found rnf (ssym,sargs) // Check for delta/imported/abstract/black-box (whatever) symbols checkimport :: !(sym->.Bool) (Strategy sym var pvar .result) (Substrategy sym var pvar .result) (Graph sym var) ((Subspine sym var pvar) -> .result) .result .(Node sym var) -> .result checkimport local defstrat substrat subject found rnf (ssym,sargs) | not (local ssym) = found Delta = defstrat substrat subject found rnf (ssym,sargs) // Check for constructors checkconstr :: (sym->String) (sym->.Bool) (Strategy sym var pvar .result) (Substrategy sym var pvar .result) (Graph sym var) ((Subspine sym var pvar) -> .result) .result .(Node sym var) -> .result checkconstr showsym isconstr defstrat substrat subject found rnf (ssym,sargs) | isconstr ssym ---> ("strat.checkconstr begins for "+++showsym ssym) = rnf <--- ("strat.checkconstr ends (RNF)") = defstrat substrat subject found rnf (ssym,sargs) <--- ("strat.checkconstr ends (default strategy)")