packages feed

cpsa-4.4.6: src/CPSA/DL/Compiler.hs

module CPSA.DL.Compiler where

import CPSA.DL.Structs
import CPSA.DL.Prolog

compileQuery :: MonadFail m => Id -> Gen -> Query -> m (Gen, [Clause])
compileQuery k g (Query sym ids f) =
    do
      (g', pl, cls) <- compileForm k g f
      return (g', Clause ((sym, map Var (k : ids)), [pl]) : cls)

compileForm :: MonadFail m => Id -> Gen -> Formula ->
               m (Gen, Body, [Clause])
compileForm k g (Atom _ sym ts) =
    return (g, PAtm (sym, Var k : ts), [])
compileForm k g (Not _ f) =
    do
      (g', b, cls) <- compileForm k g f
      let vs = fv f
      let (g'', sym, cl) = makeClause k g' vs b
      return (g'', PNot (PAtm (sym, map Var (k : vs))), cl : cls)
compileForm k g (And _ fs) =
    do
      (g', bs, cls) <- compileForms k g fs
      return (g', Conj bs, cls)
compileForm k g (Or _ fs) =
    do
      (g', bs, cls) <- compileForms k g fs
      return (g', Disj bs, cls)
compileForm k g (Exists _  _ f) =
    compileForm k g f
compileForm k g (Diamond _ act f) =
    do
      (g', b, cls) <- compileForm k g f
      let vs = fv f
      let (g'', sym, cl) = makeClause k g' vs b
      return $ compileStep k g'' (cl : cls) act sym vs

-- Compile a list of formulas.
compileForms :: MonadFail m => Id -> Gen -> [Formula] ->
                m (Gen, [Body], [Clause])
compileForms _ g [] =
    return (g, [], [])
compileForms k g (f : fs) =
    do
      (g', b, cls) <- compileForm k g f
      (g'', bs, cls') <- compileForms k g' fs
      return (g'', b : bs, cls ++ cls')

-- Generate a clause from some free variables and a body.
makeClause :: Id -> Gen -> [Id] -> Body -> (Gen, String, Clause)
makeClause k g vs body =
    (g', sym, Clause ((sym, map Var (k : vs)), [body]))
    where
      (g', sym) = predSym g

compileStep :: Id -> Gen -> [Clause] -> Act ->
               String -> [Id] -> (Gen, Body, [Clause])
compileStep k g cls act sym vs =
    (g'', Conj (step act : twas), cls)
    where
      (g', k') = cloneId g k
      (g'', tvs) = cloneVars g' vs
      step act =
          PAtm ("step" ++ actSuffix act, [Var k, Sym "O", Var k'])
      twas = compileTwas act k k' tvs
             [PAtm (sym, Var k' : map (Var . snd) tvs)]

cloneVars :: Gen -> [Id] -> (Gen, [(Id, Id)])
cloneVars g [] = (g, [])
cloneVars g (v : vs) =
    (g'', (v, v') : vs')
    where
      (g', vs') = cloneVars g vs
      (g'', v') = cloneVar g' v

cloneVar :: Gen -> Id -> (Gen, Id)
cloneVar g v =
    case idSort v of
      Mesg -> cloneId g v
      Strd -> cloneId g v
      Node -> cloneId g v
      Othr -> (g, v) -- Don't clone integers

compileTwas :: Act -> Id -> Id -> [(Id, Id)] -> [Body] -> [Body]
compileTwas _ _ _ [] bs = bs
compileTwas act k k' ((v, v') : tvs) bs =
    case idSort v of
      Othr -> bs'
      _ -> twaAtom act k v k' v' : bs'
    where
      bs' = compileTwas act k k' tvs bs

actSuffix :: Act -> String
actSuffix One = ""
actSuffix Plus = "_plus"
actSuffix Star = "_star"

twa :: Sort -> String
twa Mesg = "mtwa"
twa Strd = "stwa"
twa Node = "ntwa"
twa Othr = error "Bad TWA sort"

twaAtom :: Act -> Id -> Id -> Id -> Id -> Body
twaAtom act k v k' v' =
    PAtm (twa (idSort v) ++ actSuffix act,
          [Var k, Var v, Sym "O", Var k', Var v'])