packages feed

ampersand-3.0.2: src/lib/DatabaseDesign/Ampersand/Fspec/ShowMeatGrinder.hs

{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-} 
module DatabaseDesign.Ampersand.Fspec.ShowMeatGrinder 
  (meatGrinder)
where

import Data.List
import Data.Ord
import DatabaseDesign.Ampersand.Fspec.Fspec
import DatabaseDesign.Ampersand.Fspec.Motivations
import DatabaseDesign.Ampersand.Basics
import DatabaseDesign.Ampersand.Misc
import DatabaseDesign.Ampersand.Fspec.ShowADL
import DatabaseDesign.Ampersand.Core.AbstractSyntaxTree
import DatabaseDesign.Ampersand.ADL1.Pair
import Data.Hashable
import Data.Maybe

fatal :: Int -> String -> a
fatal = fatalMsg "Fspec.ShowMeatGrinder"

meatGrinder :: Options -> Fspc -> (FilePath, String)
meatGrinder flags fSpec = ("TemporaryPopulationsFileOfRap" ,content)
 where 
  content = unlines
     ([ "{- Do not edit manually. This code has been generated!!!"
      , "    Generated with "++ampersandVersionStr
      , "    Generated at "++show (genTime flags)
      , "-}"
      , ""
      , "CONTEXT RapPopulations"]
      ++ (concat.intersperse  []) (map (lines.showADL) (metaPops flags fSpec fSpec)) 
      ++
      [ ""
      , "ENDCONTEXT"
      ])
data Pop = Pop { popName ::String
               , popSource :: String
               , popTarget :: String
               , popPairs :: [(String,String)]
               } 
         | Comment { comment :: String  -- Not-so-nice way to get comments in a list of populations. Since it is local to this module, it is not so bad, I guess...
                   } 
instance ShowADL Pop where
 showADL pop = 
  case pop of
      Pop{} -> "POPULATION "++ popName pop++
                  " ["++popSource pop++" * "++popTarget pop++"] CONTAINS"
              ++
              if null (popPairs pop)
              then "[]" 
              else "\n"++indent++"[ "++intercalate ("\n"++indent++"; ") showContent++indent++"]"
      Comment{} -> "-- "++comment pop        
    where indent = "   "
          showContent = map showPaire (popPairs pop)
          showPaire (s,t) = "( "++show s++" , "++show t++" )"


techId :: Identified a => a -> String
techId = show.hash.name
class AdlId a where
 uri :: a -> String

instance AdlId Fspc where 
 uri a= "Ctx"++techId a
instance AdlId Pattern where 
 uri a= "Pat"++techId a
instance AdlId A_Concept where 
 uri a= "Cpt"++techId a
instance AdlId ConceptDef where 
 uri a= "CDf"++techId a
instance AdlId Rule where 
 uri a= "Rul"++techId a
instance AdlId A_Gen where 
 uri a= "Gen"++(show.hash) g
        where g = case a of
                    Isa{} -> ((name.gengen) a++(name.genspc) a)
                    IsE{} -> ((concat.map name.genrhs) a++(name.genspc) a)
instance AdlId Declaration where 
 uri a= "Dcl"++techId a
instance AdlId Purpose where 
 uri a= "Prp"++(show.hash)((show.origin) a)
instance AdlId Sign where 
 uri (Sign s t) = "Sgn"++(show.hash) (uri s++uri t)
instance AdlId Paire where
 uri p = "Paire"++(show.hash) (srcPaire p++"_"++trgPaire p)
 
data RelPopuType = InitPop | CurrPop deriving Show
mkUriRelPopu :: Declaration -> RelPopuType  -> String
mkUriRelPopu d t = show t++"Of"++uri d

instance AdlId Atom where
 uri a="Atm"++atmVal a++"Of"++(uri.atmRoot) a  


mkAtom :: A_Concept -> String -> Atom
mkAtom cpt value = Atom { atmRoot = cpt -- Was: root cpt.  <SJ 20131117> Han, "root cpt" cannot be correct in this spot. I am quite sure that "cpt" is correct. Please confer.
                        , atmVal  = value
                        }

class MetaPopulations a where
 metaPops :: Options -> Fspc -> a -> [Pop]

instance MetaPopulations Fspc where
 metaPops flags _ fSpec = 
   filter (not.nullContent)
    (
    [ Comment " "
    , Comment "The following relations are all known to be declared. This list"
    , Comment "should be helpful during the developement of the meatgrinder."
    , Comment "NOTE:"
    , Comment "  The order of the relations is determined in a special way, based on Concepts."
    ]
  ++[Comment ("  "++show i++") "++"Pop "++(show.name) dcl++" "++(show.name.source) dcl++" "++(show.name.target) dcl) | (i,dcl) <- (declOrder.allDecls)       fSpec]
  ++[ Pop "ctxnm"   "Context" "Conid"
           [(uri fSpec,name fSpec)]
    ]
  ++[ Comment " ", Comment $ "*** Patterns: (count="++(show.length.vpatterns) fSpec++") ***"]
  ++   concat [metaPops flags fSpec pat | pat <- (sortBy (comparing name).vpatterns  )    fSpec]
  ++[ Comment " ", Comment $ "*** Rules: (count="++(show.length.allRules) fSpec++")***"]
  ++   concat [metaPops flags fSpec rul | rul <- (sortBy (comparing name).allRules)    fSpec]


  ++[ Comment " ", Comment $ "*** Concepts: (count="++(show.length.allConcepts) fSpec++")***"]
  ++   concat [metaPops flags fSpec cpt | cpt <- (sortBy (comparing name).allConcepts)    fSpec]
  ++[ Comment " ", Comment $ "*** Generalisations: (count="++(show.length.vgens) fSpec++") ***"]
  ++   concat [metaPops flags fSpec gen | gen <- vgens          fSpec]
  ++[ Comment " ", Comment $ "*** Declarations: (count="++(show.length.allDecls) fSpec++") ***"]
  ++   concat [metaPops flags fSpec dcl | (_,dcl) <- (declOrder.allDecls)       fSpec]
  ++[ Comment " ", Comment $ "*** Atoms: ***"]
  ++   concat [metaPops flags fSpec atm | atm <- allAtoms]
  )
   where
    allAtoms :: [Atom]
    allAtoms = nub (concatMap atoms (initialPops fSpec))
      where 
        atoms :: Population -> [Atom]
        atoms udp = case udp of
          PRelPopu{} ->  map (mkAtom ((source.popdcl) udp).srcPaire) (popps udp) 
                      ++ map (mkAtom ((target.popdcl) udp).trgPaire) (popps udp) 
          PCptPopu{} ->  map (mkAtom (        popcpt  udp)         ) (popas udp)
    nullContent :: Pop -> Bool
    nullContent (Pop _ _ _ []) = True
    nullContent _ = False
    -- | the order of relations is done by an order of the concepts, which is a hardcoded list 
    declOrder ::[Declaration] -> [(Int,Declaration)]
    declOrder decls = zip [1..] (concatMap (sortBy f) (declGroups conceptOrder decls))
      where 
        conceptOrder = ["Pattern"
                       ,"Rule"
                       ,"Declaration"
                       ,"RelPopu"
                       ,"A_Concept"
                       ,"Concept"
                       ]
        f a b =
          case comparing (name.source) a b of
            EQ -> case comparing (name.target) a b of
                    EQ -> comparing (name) a b 
                    x  -> x
            x -> x
        declGroups :: [String] -> [Declaration] -> [[Declaration]]
        declGroups [] ds = [ds]
        declGroups (nm:nms) ds = [x] ++ declGroups nms y
           where
             (x,y) = partition crit ds
             crit dcl = or [(name.source) dcl == nm, (name.target) dcl == nm]
instance MetaPopulations Pattern where
 metaPops _ fSpec pat = 
   [ Comment " "
   , Comment $ "*** Pattern `"++name pat++"` ***"
   , Pop "ctxpats" "Context" "Pattern"
          [(uri fSpec,uri pat)]
   , Pop "ptxps"   "Pattern" "Blob"
          [(uri pat,uri x) | x <- ptxps pat]
   , Pop "ptnm"    "Pattern" "Conid"
          [(uri pat, ptnm pat)]
-- following fiedls would be double (ptctx = ~ctxpats)
--   , Pop "ptctx" "Pattern" "Context"
--          [(uri pat,uri fSpec)]
   , Pop "ptdcs"   "Pattern" "Declaration"
          [(uri pat,uri x) | x <- ptdcs pat]
   , Pop "ptgns"   "Pattern" "Gen"
          [(uri pat,uri x) | x <- ptgns pat]
--HJO, 20130728: TODO: De Image (Picture) van het pattern moet worden gegenereerd op een of andere manier:
--   , Pop "ptpic"   "Pattern" "Image"
--          [(uri pat,uri x) | x <- ptpic pat]
   , Pop "ptrls"   "Pattern" "Rule"
          [(uri pat,uri x) | x <- ptrls pat]
   ]
instance MetaPopulations Rule where
 metaPops _ fSpec rul =
   [ Comment " "
   , Comment $ "*** Rule `"++name rul++"` ***"
   , Pop "rrnm"  "Rule" "ADLid"
          [(uri rul,rrnm rul)]
   , Pop "rrmean"  "Rule" "Blob"
          [(uri rul,show(rrmean rul))]
   , Pop "rrpurpose"  "Rule" "Blob"
          [(uri rul,showADL x) | x <- explanations rul]
   , Pop "rrexp"  "Rule" "ExpressionID"
          [(uri rul,showADL (rrexp rul))]
--HJO, 20130728: TODO: De Image (Picture) van de rule moet worden gegenereerd op een of andere manier:
--   , Pop "rrpic"   "Rule" "Image"
--          [(uri rul,uri x) | x <- rrpic pat]
   , Pop "rrviols"  "Rule" "Violation"
          [(uri rul,show v) | (r,v) <- allViolations fSpec, r == rul]

   ]
instance MetaPopulations Declaration where
 metaPops _ fSpec dcl = 
   case dcl of 
     Sgn{} ->
      [ Comment " "
      , Comment $ "*** Declaration `"++name dcl++" ["++(name.source.decsgn) dcl++" * "++(name.target.decsgn) dcl++"]"++"` ***"
      , Pop "decmean"    "Declaration" "Blob"
             [(uri dcl, show(decMean dcl))]
      , Pop "decpurpose" "Declaration" "Blob"
             [(uri dcl, showADL x) | x <- explanations dcl]
--      , Pop "decexample"    "Declaration" "PragmaSentence"
--             [(uri dcl, unwords ["PRAGMA",show (decprL dcl),show (decprM dcl),show (decprR dcl)])]
      , Pop "decprps" "Declaration" "PropertyRule"
             [(uri dcl, uri rul) | rul <- filter ofDecl (allRules fSpec)]
      , Pop "declaredthrough" "PropertyRule" "Property" 
             [(uri rul,show prp) | rul <- filter ofDecl (allRules fSpec), Just (prp,d) <- [rrdcl rul], d == dcl]
      , Pop "decpopu" "Declaration" "PairID"
             [(uri dcl,mkUriRelPopu dcl CurrPop)] 
--      , Pop "inipopu" "Declaration" "PairID"
--             [(uri dcl,mkUriRelPopu dcl InitPop)] 
      , Pop "decsgn" "Declaration" "Sign"
             [(uri dcl,uri (decsgn dcl))]
      , Pop "decprL" "Declaration" "String"
             [(uri dcl,decprL dcl)]
      , Pop "decprM" "Declaration" "String"
             [(uri dcl,decprM dcl)]
      , Pop "decprR" "Declaration" "String"
             [(uri dcl,decprR dcl)]
      , Pop "decnm" "Declaration" "Varid"
             [(uri dcl, name dcl)]
 --TODO HIER GEBLEVEN. (HJO, 20130802)

--      , Pop "cptos" "PlainConcept" "AtomID"
--      , Pop "exprvalue" "ExpressionID" "Expression"
--      , Pop "rels" "ExpressionID" "Declaration"
--relnm : Relation × Varid The name of a relation used as a relation token.
--relsgn : Relation × Sign The sign of a relation.
--reldcl : Relation × Declaration A relation token refers to a relation.
--rrnm : Rule × ADLid The name of a rule.
--rrexp : Rule × ExpressionID The rule expressed in relation algebra.
--rrmean : Rule × Blob The meanings of a rule.
--rrpurpose : Rule × Blob The purposes of a rule.
      ] 
             
     Isn{} -> fatal 157 "Isn is not implemented yet"
     Vs{}  -> fatal 158 "Vs is not implemented yet"
    where
      ofDecl :: Rule -> Bool
      ofDecl rul = case rrdcl rul of
                     Nothing -> False
                     Just (_,d) -> d == dcl   
instance MetaPopulations Atom where
 metaPops _ _ _ = []
--   [ Pop "root"  "AtomID" "Concept"
--          [(uri atm,uri(atmRoot atm))]
--   , Pop "atomvalue"  "AtomID" "AtomValue"
--          [(uri atm,atmVal atm)]
--   ]
instance MetaPopulations Paire where
 metaPops _ _ p =
  [ Pop "left" "PairID" "AtomID"
         [(uri p, srcPaire p)]
  , Pop "right" "PairID" "AtomID"
         [(uri p, trgPaire p)]
  ]
instance MetaPopulations A_Gen where
 metaPops _ _ gen =
  [ Pop "genspc"  "Gen" "PlainConcept"
            [(uri gen,uri(genspc gen))]
  ]++
  case gen of
   Isa{} ->
     [ Pop "gengen"  "Gen" "PlainConcept"
            [(uri gen,uri(gengen gen))]
     ] 
   IsE{} ->
     [ Pop "genrhs"  "Gen" "PlainConcept"
          [(uri gen,uri c) | c<-genrhs gen]
     ]
instance MetaPopulations A_Concept where
 metaPops _ fSpec cpt = 
   case cpt of
     PlainConcept{} ->
      [ Comment " "
      , Comment $ "*** Concept `"++name cpt++"` ***"
      , Pop "ctxcs"   "Context" "PlainConcept"
           [(uri fSpec,uri cpt)]
      , Pop "cptnm"      "Concept" "Conid"   
             [(uri cpt, name cpt)]
-- removed: equals ctxcs~
--     , Pop "context"    "PlainConcept" "Context"
--             [(uri cpt,uri fSpec)]
-- removed:
--    , Pop "cpttp"      "PlainConcept" "Blob"
--           [(uri cpt,cpttp cpt) ]
-- removed:
--    , Pop "cptdf"      "PlainConcept" "Blob"
--           [(uri cpt,showADL x) | x <- cptdf cpt]
      , Pop "cptpurpose" "PlainConcept" "Blob"
             [(uri cpt,showADL x) | lang <- [English,Dutch], x <- fromMaybe [] (purposeOf fSpec lang cpt) ]
      ]
     ONE -> [
            ]
instance MetaPopulations Sign where
 metaPops _ _ sgn = 
      [ Pop "src"    "Sign" "Concept"
             [(uri sgn, uri (source sgn))]
      , Pop "trg"   "Sign" "Concept"
             [(uri sgn, uri (target sgn))]
      ]