summaryrefslogtreecommitdiff
path: root/src/GF/CF/CanonToCF.hs
diff options
context:
space:
mode:
authoraarne <unknown>2003-09-22 13:16:55 +0000
committeraarne <unknown>2003-09-22 13:16:55 +0000
commitb1402e8bd6a68a891b00a214d6cf184d66defe19 (patch)
tree90372ac4e53dce91cf949dbf8e93be06f1d9e8bd /src/GF/CF/CanonToCF.hs
Founding the newly structured GF2.0 cvs archive.
Diffstat (limited to 'src/GF/CF/CanonToCF.hs')
-rw-r--r--src/GF/CF/CanonToCF.hs157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/GF/CF/CanonToCF.hs b/src/GF/CF/CanonToCF.hs
new file mode 100644
index 000000000..6f7dc6d6b
--- /dev/null
+++ b/src/GF/CF/CanonToCF.hs
@@ -0,0 +1,157 @@
+module CanonToCF where
+
+import Operations
+import Option
+import Ident
+import AbsGFC
+import GFC
+import PrGrammar
+import CMacros
+import qualified Modules as M
+import CF
+import CFIdent
+import List (nub)
+import Monad
+
+-- AR 27/1/2000 -- 3/12/2001 -- 8/6/2003
+
+-- The main function: for a given cnc module m, build the CF grammar with all the
+-- rules coming from modules that m extends. The categories are qualified by
+-- the abstract module name a that m is of.
+
+canon2cf :: Options -> CanonGrammar -> Ident -> Err CF
+canon2cf opts gr c = do
+ let ms = M.allExtends gr c
+ a <- M.abstractOfConcrete gr c
+ let cncs = [m | (n, M.ModMod m) <- M.modules gr, elem n ms]
+ let mms = [(a, tree2list (M.jments m)) | m <- cncs]
+ rules0 <- liftM concat $ mapM (uncurry (cnc2cfCond opts)) mms
+ let rules = filter (not . isCircularCF) rules0 ---- temporarily here
+ let predef = const [] ---- mkCFPredef cfcats
+ return $ CF (groupCFRules rules, predef)
+
+cnc2cfCond :: Options -> Ident -> [(Ident,Info)] -> Err [CFRule]
+cnc2cfCond opts m gr =
+ liftM concat $
+ mapM lin2cf [(m,fun,cat,args,lin) | (fun, CncFun cat args lin _) <- gr]
+
+type IFun = Ident
+type ICat = CIdent
+
+-- all CF rules corresponding to a linearization rule
+lin2cf :: (Ident, IFun, ICat, [ArgVar], Term) -> Err [CFRule]
+lin2cf (m,fun,cat,args,lin) = errIn ("building CF rule for" +++ prt fun) $ do
+ rhss0 <- allLinValues lin -- :: [(Label, [([Patt],Term)])]
+ rhss1 <- mapM (mkCFItems m) (concat rhss0) -- :: [(Label, [[PreCFItem]])]
+ mapM (mkCfRules m fun cat args) rhss1 >>= return . nub . concat
+
+-- making sequences of CF items from every branch in a linearization
+mkCFItems :: Ident -> (Label, [([Patt],Term)]) -> Err (Label, [[PreCFItem]])
+mkCFItems m (lab,pts) = do
+ itemss <- mapM (term2CFItems m) (map snd pts)
+ return (lab, concat itemss) ---- combinations? (test!)
+
+-- making CF rules from sequences of CF items
+mkCfRules :: Ident -> IFun -> ICat -> [ArgVar] -> (Label, [[PreCFItem]]) -> Err [CFRule]
+mkCfRules m fun cat args (lab, itss) = mapM mkOneRule itss
+ where
+ mkOneRule its = do
+ let nonterms = zip [0..] [(pos,d,v) | PNonterm _ pos d v <- its]
+ profile = mkProfile nonterms
+ cfcat = CFCat (redirectIdent m cat,lab)
+ cffun = CFFun (AC (CIQ m fun), profile)
+ cfits = map precf2cf its
+ return (cffun,(cfcat,cfits))
+ mkProfile nonterms = map mkOne args
+ where
+ mkOne (A c i) = mkOne (AB c 0 i)
+ mkOne (AB _ b i) = (map mkB [0..b-1], [k | (k,(j,_,True)) <- nonterms, j==i])
+ where
+ mkB j = [p | (p,(k, LV l,False)) <- nonterms, k == i, l == j]
+
+-- intermediate data structure of CFItems with information for profiles
+data PreCFItem =
+ PTerm RegExp -- like ordinary Terminal
+ | PNonterm CIdent Integer Label Bool -- cat, position, part/bind, whether arg
+ deriving Eq
+
+precf2cf :: PreCFItem -> CFItem
+precf2cf (PTerm r) = CFTerm r
+precf2cf (PNonterm cm _ (L c) True) = CFNonterm (ident2CFCat cm c)
+precf2cf (PNonterm _ _ _ False) = CFNonterm catVarCF
+
+
+-- the main job in translating linearization rules into sequences of cf items
+term2CFItems :: Ident -> Term -> Err [[PreCFItem]]
+term2CFItems m t = errIn "forming cf items" $ case t of
+ S c _ -> t2c c
+
+ T _ cc -> do
+ its <- mapM t2c [t | Cas _ t <- cc]
+ tryMkCFTerm (concat its)
+
+ C t1 t2 -> do
+ its1 <- t2c t1
+ its2 <- t2c t2
+ return [x ++ y | x <- its1, y <- its2]
+
+ FV ts -> do
+ its <- mapM t2c ts
+ tryMkCFTerm (concat its)
+
+ P arg s -> extrR arg s
+
+ K (KS s) -> return [[PTerm (RegAlts [s]) | not (null s)]]
+
+ E -> return [[]]
+
+ K (KP d vs) -> do
+ let its = [PTerm (RegAlts [s]) | s <- d]
+ let itss = [[PTerm (RegAlts [s]) | s <- t] | Var t _ <- vs]
+ tryMkCFTerm (its : itss)
+
+ _ -> prtBad "no cf for" t ----
+
+ where
+
+ t2c = term2CFItems m
+
+ -- optimize the number of rules by a factorization
+ tryMkCFTerm :: [[PreCFItem]] -> Err [[PreCFItem]]
+ tryMkCFTerm ii@(its:itss) | all (\x -> length x == length its) itss =
+ case mapM mkOne (counterparts ii) of
+ Ok tt -> return [tt]
+ _ -> return ii
+ where
+ mkOne cfits = case mapM mkOneTerm cfits of
+ Ok tt -> return $ PTerm (RegAlts (concat (nub tt)))
+ _ -> mkOneNonTerm cfits
+ mkOneTerm (PTerm (RegAlts t)) = return t
+ mkOneTerm _ = Bad ""
+ mkOneNonTerm (n@(PNonterm _ _ _ _) : cc) =
+ if all (== n) cc
+ then return n
+ else Bad ""
+ mkOneNonTerm _ = Bad ""
+ counterparts ll = [map (!! i) ll | i <- [0..length (head ll) - 1]]
+ tryMkCFTerm itss = return itss
+
+ extrR arg lab = case (arg,lab) of
+ (Arg (A cat pos), l@(L _)) -> return [[PNonterm (CIQ m cat) pos l True]]
+ (Arg (A cat pos), l@(LV _)) -> return [[PNonterm (CIQ m cat) pos l False]]
+ (Arg (AB cat pos b), l@(L _)) -> return [[PNonterm (CIQ m cat) pos l True]]
+ (Arg (AB cat pos b), l@(LV _)) -> return [[PNonterm (CIQ m cat) pos l False]]
+ ---- ??
+ _ -> prtBad "cannot extract record field from" arg
+
+{- Proof + 1 @ 4 catVarCF :: CFCat
+PNonterm CIdent Integer Label Bool -- cat, position, part/bind, whether arg
+
+
+mkCFPredef :: [CFCat] -> CFPredef
+mkCFPredef cats s =
+ [(cat, metaCFFun) | TM _ _ <- [s], cat <- cats] ++
+ [(cat, varCFFun x) | TV x <- [s], cat <- cats] ++
+ [(cat, lit) | TL t <- [s], Just (cat,lit) <- [getCFLiteral t]] ++
+ [(cat, lit) | TI i <- [s], Just (cat,lit) <- [getCFLiteral (show i)]] ---
+-}