packages feed

cap-1.0: src/Language/Cap/Debug/FDT.hs

module Language.Cap.Debug.FDT
       (buildFDT,fdtParent,fdtQuestion)
       where

import Language.Cap.Interpret.Pretty
import Language.Cap.Debug.Algorithmic
import Language.Cap.Debug.EDT
import Language.Cap.Debug.Trace
import Language.Cap.Debug.TraceMode

import Data.Char
import System.IO.Unsafe

infixl 3 >+<

{- | Generates a question for a node in the ART.  Questions are made up by
     comparing the redex to a most evaluated form.
-}
fdtQuestion :: MapMode -> Graph -> NodeName -> String
fdtQuestion m g n =
  (pretty $ fdtRedex m g n) ++ " =?= " ++ (pretty $ fdtMef m g n) ++ "\n"

-- | Constructs an FDT for a given trace.
buildFDT :: Graph -> ADT
buildFDT g =
  buildFDT' g ""
  where
    -- | Constructs an FDT starting at a specific node in the ART.
    buildFDT' :: Graph -> NodeName -> ADT
    buildFDT' g n = Node n (map (buildFDT' g) (children g n))
    
    -- | Gathers the children of a node in the ART.
    children :: Graph -> NodeName -> [NodeName]
    children g n = [name | name <- allNodes g,    ('r':name) `elem` allNodes g
                                               && fdtParent g name == Just n]

-- | Find the parent (as defined for the FDT) of a node in the ART.
fdtParent :: Graph -> NodeName -> Maybe NodeName
fdtParent g n =
  case nodeValue g n of
    Just (Atom a)          -> edtParent n
    Just (Application f _) -> edtParent (nodeLast g f)

-- | Create a redex for any application or atom node in the trace.
fdtRedex :: MapMode -> Graph -> NodeName -> PrettyTerm
fdtRedex _ g "" = PAtom "main"
fdtRedex m g n  = case nodeValue g n of
                    Just x -> fdtMeaT m g x

fdtMeaT :: MapMode -> Graph -> NodeInfo -> PrettyTerm
fdtMeaT m g (Atom a) = PAtom a
fdtMeaT m g (Application i j) = PApplication (fdtMea m g i) (fdtMef m g j)

fdtMea :: MapMode -> Graph -> NodeName -> PrettyTerm
fdtMea m g n =
  case nodeValue g l of
    Just x -> fdtMeaT m g x
  where
    l = nodeLast g n

-- | Either this is a function symbol (i.e. all lower case letters)
--   or it is an application of a function symbol.
--   Neither may have a result pointer.
--   Longer version is to check the arity of the graph. this is better
--   because it allows for the possibility of a computation not having been
--   demanded.  The short-cut would result in a mapping {} in this situation.
--   Thus if the shortcut is used, empty mappings should be replaced with the _
--   symbol to indicate that the expression was never needed.
isFunction :: Graph -> NodeName -> Bool
isFunction g n = 
  case nodeValue g at of
    Just (Atom a)          -> isFunctionName g at
    Just (Application i j) -> isFunctionName g i
  where
    at = (nodeLast g n)

isFunctionName :: Graph -> NodeName -> Bool
isFunctionName g n =
  case nodeValue g n of
    Just (Atom a)          -> isAllLowerCase a
    Just (Application i j) -> isFunctionName g i
  where
    isAllLowerCase :: String -> Bool
    isAllLowerCase = all (`elem` "abcdefghijklmnopqrstuvwxyz")

-- | Find the most evaluated form for any node in the trace
fdtMef :: MapMode -> Graph -> NodeName -> PrettyTerm
fdtMef m g n =
  if isFunction g n
    then fdtMap m g (nodeLast g n)
    else fdtMea m g n

(>+<) :: NodeName -> Graph -> NodeName -> Bool
(n >+< g) m = n /= m && ('r':m) `elem` allNodes g && n `elem` nodeHeads g m

(>-<) :: NodeName -> Graph -> NodeName -> Bool
(n >-< g) m = n /= m && ('r':m) `elem` allNodes g && nodeHead g m == n

fdtMap :: MapMode -> Graph -> NodeName -> PrettyTerm
fdtMap Index g n =
  PMap [M (args Index g m n) (fdtMef Index g m) | m <- allNodes g, (n >+< g) m]
fdtMap IndexFunctions g n =
  fdtMap' g n (nodeHead g n)
fdtMap OnTheFly g n =
  PMap (map (makeMap g) (filter (isAppOf g n) (allApplications g)))
  -- Needs to be an underscore if it's an empty mapping, because we don't know
  -- if it's a function symbol or a value

fdtMap' :: Graph -> NodeName -> NodeName -> PrettyTerm
fdtMap' g n m =
  PMap [M (args IndexFunctions g m' n) (fdtMef IndexFunctions g m')
          | m' <- allNodes g, (m >-< g) m' && n `elem` nodeHeads g m']

args :: MapMode -> Graph -> NodeName -> NodeName -> [PrettyTerm]
args mm g m n =
  if m /= n then
    case nodeValue g m of
      Just (Application i j) -> args mm g (nodeLast g i) n ++ [fdtMef mm g j]
      Just (Atom x)          -> []
  else []

isAppOf :: Graph -> NodeName -> NodeName -> Bool
isAppOf g n m = 
  case nodeValue g m of
    Just (Application n' o) -> n == nodeLast g n'
    _                       -> False

makeMap :: Graph -> NodeName -> Mapping
makeMap g m =
  case nodeValue g m of
    Just (Application _ o) -> M [fdtMef OnTheFly g o] (fdtRes OnTheFly g m)

fdtRes :: MapMode -> Graph -> NodeName -> PrettyTerm
fdtRes m g n = if ('r':n) `elem` allNodes g then fdtMef m g n
                                            else fdtMap m g n