---------------------------------------------------------------------- -- | -- Maintainer : PL -- Stability : (stable) -- Portability : (portable) -- -- > CVS $Date: 2005/05/11 10:28:16 $ -- > CVS $Author: peb $ -- > CVS $Revision: 1.5 $ -- -- Instantiating all types which only have one single element. -- -- Should be merged into 'GF.Conversion.FiniteToSimple' ----------------------------------------------------------------------------- module GF.Conversion.RemoveSingletons where import GF.System.Tracing import GF.Infra.Print import GF.Formalism.Utilities import GF.Formalism.GCFG import GF.Formalism.SimpleGFC import GF.Conversion.Types import GF.Data.SortedList import GF.Data.Assoc import Data.List (mapAccumL) convertGrammar :: SGrammar -> SGrammar convertGrammar grammar = if singles == emptyAssoc then grammar else tracePrt "RemoveSingletons - non-singleton rules" (prt . length) $ map (convertRule singles) grammar where singles = calcSingletons grammar convertRule :: Assoc SCat (SyntaxForest Fun, Maybe STerm) -> SRule -> SRule convertRule singles rule@(Rule (Abs _ decls _) _) = if all (Nothing ==) singleArgs then rule else instantiateSingles singleArgs rule where singleArgs = map (lookupAssoc singles . decl2cat) decls instantiateSingles :: [Maybe (SyntaxForest Fun, Maybe STerm)] -> SRule -> SRule instantiateSingles singleArgs (Rule (Abs decl decls (Name fun profile)) (Cnc lcat lcats lterm)) = Rule (Abs decl decls' (Name fun profile')) (Cnc lcat lcats' lterm') where (decls', lcats') = unzip [ (d, l) | (Nothing, d, l) <- zip3 singleArgs decls lcats ] profile' = map (fmap fst) exProfile `composeProfiles` profile newArgs = map (fmap snd) exProfile lterm' = fmap (instantiateLin newArgs) lterm exProfile = snd $ mapAccumL mkProfile 0 singleArgs mkProfile nr (Just trm) = (nr, Constant trm) mkProfile nr (Nothing) = (nr+1, Unify [nr]) instantiateLin :: [Profile (Maybe STerm)] -> STerm -> STerm instantiateLin newArgs = inst where inst (Arg nr cat path) = case newArgs !! nr of Unify [nr'] -> Arg nr' cat path Constant (Just term) -> termFollowPath path term Constant Nothing -> error "RemoveSingletons.instantiateLin: This should not happen (argument has no linearization)" inst (cn :^ terms) = cn :^ map inst terms inst (Rec rec) = Rec [ (lbl, inst term) | (lbl, term) <- rec ] inst (term :. lbl) = inst term +. lbl inst (Tbl tbl) = Tbl [ (pat, inst term) | (pat, term) <- tbl ] inst (term :! sel) = inst term +! inst sel inst (Variants ts) = variants (map inst ts) inst (t1 :++ t2) = inst t1 ?++ inst t2 inst term = term ---------------------------------------------------------------------- calcSingletons :: SGrammar -> Assoc SCat (SyntaxForest Fun, Maybe STerm) calcSingletons rules = listAssoc singleCats where singleCats = tracePrt "RemoveSingletons - singleton cats" (prtSep " ") $ [ (cat, (constantNameToForest name, lin)) | (cat, [([], name, lin)]) <- rulesByCat ] rulesByCat = groupPairs $ nubsort [ (decl2cat cat, (args, name, lin)) | Rule (Abs cat args name) (Cnc _ _ lin) <- rules ]