packages feed

visual-graphrewrite-0.4.0.1: GraphRewrite/Internal/RewriteTypes.hs

-- | Types which are specific to a graph rewrite system.
module GraphRewrite.Internal.RewriteTypes

where

  import Data.IntMap hiding (map)
  import Prelude hiding (lookup, exp)

  -- | Arity is a non-negative integer which represents the number of arguments a function can take.
  type Arity = Int

  -- | An expression.
  data Expr
      = SCons Int        -- ^ A constructor token. May occur on either the left or right side of a rule.
      | SFun  Arity Int  -- ^ A function token. May only occur on the right side of a rule (definition). Arity is pretty redundant at the moment.
      | SLit String      -- ^ String literal. Usually handled the same way as a 0 argument constructor.
      | SHole Int        -- ^ Represents join points in a rule. Should not appear in data graphs.
      | SRef Int         -- ^ Refers to an other expressions. Sharing can be expressed with this token in data graphs and right side of rules.
      | SApp Expr [Expr] -- ^ Represents an application. An expression can be applied to a list of expressions. The first one can only be SFun or SCons (or SRef). Can appear everywhere, but if on the right side of a rule, the first expression can only be an SCons.
        deriving (Eq, Show)

  -- | A rewrite system is essentially a mapping of function identifiers to alternative definitions.
  data RewriteSystem = RewriteSystem
      { rules :: IntMap [Rule]
      , names :: IntMap String -- TODO: document this.
      }
                       deriving (Show)

  -- | An empty 'RewriteSystem'.
  defaultRS :: RewriteSystem
  defaultRS = RewriteSystem { rules = empty, names = empty }


  -- | A rule represents a function alternative.
  data Rule = Rule
    { patts :: [Expr]     -- ^ A list of expressions representing pattern bindings.
    , exp   :: Expr       -- ^ The function definition.
    , graph :: Graph      -- ^ Images of references in the definition.
    }
              deriving (Eq, Show)

  -- | A graph is represented by a mapping from integers to expressions.
  type Graph = IntMap Expr

  -- | This is a normal graph with one expression designated as root node.
  type PointedGraph = (Expr, Graph)

  -- | A tree which represents a graph rewrite procedure. Every node has an arbitrary amount of children, the rightmost node is usually the head normal form.
  data RewriteTree = Step PointedGraph [RewriteTree]
              deriving (Show)

  -- | Branch point in a 'RewriteTree'. First component is the node
  -- which is stored inside the branch. Second component is a list of
  -- trees to the left of the selected node in reverse order. Third
  -- component is a list of trees to the right of the selected node in
  -- normal order.
  data RewriteBranch = RewriteBranch
      { node :: PointedGraph   -- ^ Node which is stored inside the branch.
      , left :: [RewriteTree]  -- ^ List of 'RewriteTree's to the left
                               --   of the selected node in reverse order.
      , rght :: [RewriteTree]  -- ^ List of 'RewriteTree's to the right
                               --   of the selected node in normal order.
      }

  -- | A 'Context' represents a well, er... context around a
  -- particular subtree of a 'RewriteTree'. This means that from that
  -- subtree and its 'Context', one can reconstruct the entire
  -- 'RewriteTree'. This is a one-hole context.
  type Context = [RewriteBranch]

  -- | Gets the rightmost 'PointedGraph' from a 'RewriteTree'.
  lastGraph :: RewriteTree -> PointedGraph
  lastGraph (Step pg []) = pg
  lastGraph (Step _ trs) = lastGraph $ last trs

  -- | This function tries to eliminate SApp structures nested in the first argument.
  flattenSApp :: RewriteSystem -> Expr -> Graph ->
    ( Expr, [Expr])          -- ^ Symbol to be applied. Can only be SFun, SCons or SLit. & Arguments. In case of SFun, this can not be empty, otherwise this should be empty.
  flattenSApp rs (SApp x xs) g
    = case deref rs x g of
      SApp y ys  -> flattenSApp rs (SApp y (ys ++ xs)) g
      x          -> (x, xs)
  flattenSApp _ x _       -- in case of SLit, SCons, SFun
    = (x, [])


  -- | Gets an 'Expr' structure's identifier as a string.
  exprID :: Expr -> String
  exprID (SCons c) = show c
  exprID (SFun _ f) = show f
  exprID (SLit l) = l
  exprID (SHole h) = show h
  exprID (SRef r) = show r
  exprID e = exprID $ fst $ flattenSApp defaultRS e empty

  -- | Recursively replace SRef structure for the referenced expression. Errors out if there is no dereference.
  deref
      :: RewriteSystem -- ^ Surrounding context.
      -> Expr -- ^ Expression to be dereferenced. If not an SRef then this will be the result.
      -> Graph -- ^ Images of SRefs
      -> Expr -- ^ Dereferenced expression.
  deref rs e@(SRef _) im = deref rs e' im''
      where
        (e', im') = deref' rs e im
        im'' = im `union` im'
  deref _ e _ = e

  -- | Replace SRef structure for the referenced expression. This is a shallow implementation. See also: 'deref'.
  deref'
      :: RewriteSystem
      -> Expr
      -> Graph
      -> (Expr, Graph)
  deref' rs (SRef ref) im = case lookup ref im of
                              Just e -> (e, empty)
                              Nothing -> case lookup ref (rules rs) of
                                          Just [r] -> (exp r, graph r)
                                          Just _  -> error $ "There is a problem dereferencing " ++ show ref ++ ". Check your source."
                                          Nothing -> error $ "No reference found for " ++ show ref ++ ". This shouldn't happen."



{-
 f x = x

 Rule
    { patts = [SHole 3]
    , exp   = SHole 3
    , graph = fromList []
    }

------------------------------------------

 f x = y + y where y = x * x

 Rule
    { patts = [SHole 3]
    , exp   = SApp (SFun 2 320) [SRef 0, SRef 0]
    , graph = fromList
        [ (0, SApp (SFun 2 321) [SHole 3, SHole 3])
        ]

----------------------------------------- lehet hogy régi
egy szabály:


  (++) ((:) x xs) ys   =  (:) x ((++) xs ys)
  (++) _          ys   =  ys

 -->

  (++) ((:) 4@x 5@xs) 2@ys   =  (:) x ((++) xs ys)
  (++) 1@_          2@ys   =  ys

 -->

  Rules (++) [r1, r2]

  r1 = Rule
            [ SApp (SCons (:)) [SHole 4, SHole 5]
            , SHole 2]
            (SApp (SCons (:)) [SHole 4, SApp (SFun (++) [SHole 5, SHole 2])])

  r2 = Rule [ SHole 1, SHole 2] (SHole 2)
----------------------------------------
  app 1@f 2@x = 3@f x

-->
  Rules "app" [Rule [SHole 1, SHole 2] (SApp (SFun "f") [SHole 2])]

----------------------------------------

  f 1@x@((:) 2@a 3@b) = 4@(++) x b

-->
  Rules "f"
    Rule [SRef 1]
         (SApp (SFun (++)) [SRef 1, SHole 3])
         [ 1 |-> Rule [SApp (SCons (:)) [SHole 2, SHole 3]]
----------------------------------------

  result = 1@(f 2@1)

-->
  Rules "result" [Rule [] 1 [1 |-> (SFun "f", [2]), 2 |-> (SLit "1", [])

----------------------------------------

    result = f y

    y = sum [1..10000]

    f x = x + x + y
-->

    result = f y y
      where
        y = 10

    f y x = x + x + y

---------------------------------------

    cycle 1@x = 2@y  where  y = x ++ y

-->
   Rules "cycle" [
        Rule [SHole 1]
             (SRef 1)
             [ 1 -> SApp (SFun (++)) [SHole 1, SRef 1 ]]
-}