{-# LANGUAGE UnicodeSyntax, FlexibleContexts #-}
module GraphRewriting.Strategies.LeftmostOutermost where
import GraphRewriting.Pattern
import GraphRewriting.Graph.Write
import GraphRewriting.Graph.Read
import GraphRewriting.Rule
import GraphRewriting.Strategies.Control
import Data.List (intersect, (\\))
-- | Gives us the the 'left' port for a given node
class LeftmostOutermost n where lmoPort ∷ n → Maybe Port
instance LeftmostOutermost n ⇒ LeftmostOutermost (Wrapper n) where lmoPort = lmoPort . wrapped
getLmoPort ∷ (LeftmostOutermost n) ⇒ Node → Pattern n Port
getLmoPort n = do
node ← liftReader $ readNode n
case lmoPort node of
Nothing → fail "Term is in WHNF"
Just lo → return lo
-- It does not compile with this type signature, even when IncoherentInstances are given in Control.
moveControl ∷ (View [Port] n, View Control n, LeftmostOutermost n) => Rule n
moveControl = do
Control {stack = s} ← node
control ← previous
lmo1 ← getLmoPort control
n ← branchNodes =<< liftReader . adverseNodes control =<< getLmoPort control
return $ do
updateNode control NoControl
updateNode n (Control {stack = control : s})
-- It does not compile with this type signature, even when IncoherentInstances are given in Control.
leftmostOutermost ∷ (View Control n, View [Port] n) ⇒ Rule n → Rule n
leftmostOutermost r = do
rewrite ← r
ns ← history -- we want the first node of the matching pattern
let topnode = last ns
Control {stack = s} ← liftReader $ inspectNode topnode
return $ do
updateNode topnode NoControl -- First we set the topnode to not be the control node any more
oldNodes ← readNodeList
rewrite -- then we perform the rewrite
newNodes ← readNodeList
let s' = intersect s newNodes -- only consider nodes for the control marker that exist
if null s' -- even the topmost node has been replaced
then do -- we assign the control marker to one of the newly created nodes
let addedNodes = newNodes \\ oldNodes
updateNode (head addedNodes) (Control {stack = []}) -- finally we set the previous node on the stack as the control node
else do -- set the previous node on the stack as the control node
updateNode (head s') (Control {stack = tail s'})