module FoFrontEnd where
import Fol

libLookup :: [Fol.Library] -> String -> String -> [Fol.Clause]
libLookup lib m name = 
    case lib of
    [] -> error ("module " ++ m ++ " not found.")
    (s,_,p):t | s == m -> propLookup p
              where propLookup [] = error ("lemma " ++ m ++ "." ++ 
                                           name ++ " not found.")
                    propLookup ((Qname _ n,_,cl,_):t') | n == name =
                       case cl of
                       [ClOr [ClInline (Qname m' name')]] -> 
                           libLookup lib m' name'
                       [ClOr [ClNinline (Qname m' name')]] -> 
                           libLookupNeg lib m' name'
                       _ -> cl
                    propLookup (h:t') = propLookup t'
    h:t -> libLookup t m name

libLookupNeg :: [Fol.Library] -> String -> String -> [Fol.Clause]
libLookupNeg lib m name = 
    case lib of
    [] -> error ("module " ++ m ++ " not found.")
    (s,_,p):t | s == m -> propLookup p
              where propLookup [] = error ("lemma " ++ m ++ "." ++ 
                                           name ++ " not found.")
                    propLookup ((Qname _ n,_,_,cl):t') | n == name =
                       case cl of
                       [ClOr [ClInline (Qname m' name')]] -> 
                           libLookup lib m' name'
                       [ClOr [ClNinline (Qname m' name')]] -> 
                           libLookupNeg lib m' name'
                       _ -> cl
                    propLookup (h:t') = propLookup t'
    h:t -> libLookupNeg t m name

slice :: [Fol.Library] -> Fol.Library -> Fol.Prop -> Fol.ProofObl
slice lib (mName,code,props) (propName,lemmas,propT,propF) = proofOb
    where proofOb = (propName,defCode++lemmaCode, prop)
          prop = 
              case propF of 
              [ClOr [ClInline  (Qname m n)]] -> libLookup llib m n
              [ClOr [ClNinline (Qname m n)]] -> libLookupNeg llib m n
              _ -> propF
          defCode   = map snd (sliceCode (([],code),fv))
          lemmaCode = foldl findLemma [] lemmas
          findLemma code (Qname m n) = code ++ (libLookup llib m n)
          llib = (mName,code,props):lib
          keep name ((kept,notYet),toVisit) (s,cl) = 
              if name == s then
                     (((s,cl):kept,notYet),fvClause toVisit cl)
              else
                     ((kept,(s,cl):notYet),toVisit)
          filterV name toVisit lDef = foldl (keep name) (([],[]),toVisit) lDef
          sliceCode ((kept,notYet),toVisit) = 
              case toVisit of
              []   -> kept
              x:xs -> let ((k,n),t) = filterV x xs notYet in
                          sliceCode ((k++kept,n),t) 
          fv = foldl fvClause [] propF

splitAndSlice :: [Fol.Library] -> Fol.Library -> [Fol.ProofObl]
splitAndSlice lib (n, code, props) = map (slice lib (n,code,props)) props