summaryrefslogtreecommitdiff
path: root/src-3.0/GF/Compile/Update.hs
diff options
context:
space:
mode:
authoraarne <aarne@cs.chalmers.se>2008-05-21 09:26:44 +0000
committeraarne <aarne@cs.chalmers.se>2008-05-21 09:26:44 +0000
commit055c0d0d5a5bb0dc75904fe53df7f2e4f5732a8f (patch)
tree0e63fb68c69c8f6ad0f78893c63420f0a3600e1c /src-3.0/GF/Compile/Update.hs
parent915a1de71783ab8446b1af9e72c7ba7dfbc12d3f (diff)
GF/src is now for 2.9, and the new sources are in src-3.0 - keep it this way until the release of GF 3
Diffstat (limited to 'src-3.0/GF/Compile/Update.hs')
-rw-r--r--src-3.0/GF/Compile/Update.hs135
1 files changed, 135 insertions, 0 deletions
diff --git a/src-3.0/GF/Compile/Update.hs b/src-3.0/GF/Compile/Update.hs
new file mode 100644
index 000000000..82d7a609e
--- /dev/null
+++ b/src-3.0/GF/Compile/Update.hs
@@ -0,0 +1,135 @@
+----------------------------------------------------------------------
+-- |
+-- Module : Update
+-- Maintainer : AR
+-- Stability : (stable)
+-- Portability : (portable)
+--
+-- > CVS $Date: 2005/05/30 18:39:44 $
+-- > CVS $Author: aarne $
+-- > CVS $Revision: 1.8 $
+--
+-- (Description of the module)
+-----------------------------------------------------------------------------
+
+module GF.Compile.Update (updateRes, buildAnyTree, combineAnyInfos, unifyAnyInfo,
+ -- * these auxiliaries should be somewhere else
+ -- since they don't use the info types
+ groupInfos, sortInfos, combineInfos, unifyInfos,
+ tryInsert, unifAbsDefs, unifConstrs
+ ) where
+
+import GF.Infra.Ident
+import GF.Grammar.Grammar
+import GF.Grammar.PrGrammar
+import GF.Infra.Modules
+
+import GF.Data.Operations
+
+import Data.List
+import Control.Monad
+
+-- | update a resource module by adding a new or changing an old definition
+updateRes :: SourceGrammar -> Ident -> Ident -> Info -> SourceGrammar
+updateRes gr@(MGrammar ms) m i info = MGrammar $ map upd ms where
+ upd (n,mod)
+ | n /= m = (n,mod)
+ | n == m = case mod of
+ ModMod r -> (m,ModMod $ updateModule r i info)
+ _ -> (n,mod) --- no error msg
+
+-- | combine a list of definitions into a balanced binary search tree
+buildAnyTree :: [(Ident,Info)] -> Err (BinTree Ident Info)
+buildAnyTree ias = do
+ ias' <- combineAnyInfos ias
+ return $ buildTree ias'
+
+
+-- | unifying information for abstract, resource, and concrete
+combineAnyInfos :: [(Ident,Info)] -> Err [(Ident,Info)]
+combineAnyInfos = combineInfos unifyAnyInfo
+
+unifyAnyInfo :: Ident -> Info -> Info -> Err Info
+unifyAnyInfo c i j = errIn ("combining information for" +++ prt c) $ case (i,j) of
+ (AbsCat mc1 mf1, AbsCat mc2 mf2) ->
+ liftM2 AbsCat (unifPerhaps mc1 mc2) (unifConstrs mf1 mf2) -- adding constrs
+ (AbsFun mt1 md1, AbsFun mt2 md2) ->
+ liftM2 AbsFun (unifPerhaps mt1 mt2) (unifAbsDefs md1 md2) -- adding defs
+
+ (ResParam mt1, ResParam mt2) -> liftM ResParam $ unifPerhaps mt1 mt2
+ (ResOper mt1 m1, ResOper mt2 m2) ->
+ liftM2 ResOper (unifPerhaps mt1 mt2) (unifPerhaps m1 m2)
+
+ (CncCat mc1 mf1 mp1, CncCat mc2 mf2 mp2) ->
+ liftM3 CncCat (unifPerhaps mc1 mc2) (unifPerhaps mf1 mf2) (unifPerhaps mp1 mp2)
+ (CncFun m mt1 md1, CncFun _ mt2 md2) ->
+ liftM2 (CncFun m) (unifPerhaps mt1 mt2) (unifPerhaps md1 md2) ---- adding defs
+-- for bw compatibility with unspecified printnames in old GF
+ (CncFun Nothing Nope (Yes pr),_) ->
+ unifyAnyInfo c (CncCat Nope Nope (Yes pr)) j
+ (_,CncFun Nothing Nope (Yes pr)) ->
+ unifyAnyInfo c i (CncCat Nope Nope (Yes pr))
+
+ _ -> Bad $ "cannot unify informations in" ++++ show i ++++ "and" ++++ show j
+
+--- these auxiliaries should be somewhere else since they don't use the info types
+
+groupInfos :: Eq a => [(a,b)] -> [[(a,b)]]
+groupInfos = groupBy (\i j -> fst i == fst j)
+
+sortInfos :: Ord a => [(a,b)] -> [(a,b)]
+sortInfos = sortBy (\i j -> compare (fst i) (fst j))
+
+combineInfos :: Ord a => (a -> b -> b -> Err b) -> [(a,b)] -> Err [(a,b)]
+combineInfos f ris = do
+ let riss = groupInfos $ sortInfos ris
+ mapM (unifyInfos f) riss
+
+unifyInfos :: (a -> b -> b -> Err b) -> [(a,b)] -> Err (a,b)
+unifyInfos _ [] = Bad "empty info list"
+unifyInfos unif ris = do
+ let c = fst $ head ris
+ let infos = map snd ris
+ let ([i],is) = splitAt 1 infos
+ info <- foldM (unif c) i is
+ return (c,info)
+
+
+tryInsert :: Ord a => (b -> b -> Err b) -> (b -> b) ->
+ BinTree a b -> (a,b) -> Err (BinTree a b)
+tryInsert unif indir tree z@(x, info) = case justLookupTree x tree of
+ Ok info0 -> do
+ info1 <- unif info info0
+ return $ updateTree (x,info1) tree
+ _ -> return $ updateTree (x,indir info) tree
+
+{- ----
+case tree of
+ NT -> return $ BT (x, indir info) NT NT
+ BT c@(a,info0) left right
+ | x < a -> do
+ left' <- tryInsert unif indir left z
+ return $ BT c left' right
+ | x > a -> do
+ right' <- tryInsert unif indir right z
+ return $ BT c left right'
+ | x == a -> do
+ info' <- unif info info0
+ return $ BT (x,info') left right
+-}
+
+--- addToMaybeList m c = maybe (return c) (\old -> return (c ++ old)) m
+
+unifAbsDefs :: Perh Term -> Perh Term -> Err (Perh Term)
+unifAbsDefs p1 p2 = case (p1,p2) of
+ (Nope, _) -> return p2
+ (_, Nope) -> return p1
+ (Yes (Eqs bs), Yes (Eqs ds)) -> return $ yes $ Eqs $ bs ++ ds --- order!
+ _ -> Bad "update conflict for definitions"
+
+unifConstrs :: Perh [Term] -> Perh [Term] -> Err (Perh [Term])
+unifConstrs p1 p2 = case (p1,p2) of
+ (Nope, _) -> return p2
+ (_, Nope) -> return p1
+ (Yes bs, Yes ds) -> return $ yes $ bs ++ ds
+ _ -> Bad "update conflict for constructors"