diff options
| author | aarne <aarne@cs.chalmers.se> | 2008-05-21 09:26:44 +0000 |
|---|---|---|
| committer | aarne <aarne@cs.chalmers.se> | 2008-05-21 09:26:44 +0000 |
| commit | 055c0d0d5a5bb0dc75904fe53df7f2e4f5732a8f (patch) | |
| tree | 0e63fb68c69c8f6ad0f78893c63420f0a3600e1c /src-3.0/GF/Compile/GrammarToCanon.hs | |
| parent | 915a1de71783ab8446b1af9e72c7ba7dfbc12d3f (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/GrammarToCanon.hs')
| -rw-r--r-- | src-3.0/GF/Compile/GrammarToCanon.hs | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/src-3.0/GF/Compile/GrammarToCanon.hs b/src-3.0/GF/Compile/GrammarToCanon.hs new file mode 100644 index 000000000..09c0d3d95 --- /dev/null +++ b/src-3.0/GF/Compile/GrammarToCanon.hs @@ -0,0 +1,293 @@ +---------------------------------------------------------------------- +-- | +-- Module : GrammarToCanon +-- Maintainer : AR +-- Stability : (stable) +-- Portability : (portable) +-- +-- > CVS $Date: 2005/11/11 23:24:33 $ +-- > CVS $Author: aarne $ +-- > CVS $Revision: 1.23 $ +-- +-- Code generator from optimized GF source code to GFC. +----------------------------------------------------------------------------- + +module GF.Compile.GrammarToCanon (showGFC, + redModInfo, redQIdent + ) where + +import GF.Data.Operations +import GF.Data.Zipper +import GF.Infra.Option +import GF.Grammar.Grammar +import GF.Infra.Ident +import GF.Grammar.PrGrammar +import GF.Infra.Modules +import GF.Grammar.Macros +import qualified GF.Canon.AbsGFC as G +import qualified GF.Canon.GFC as C +import GF.Canon.MkGFC +---- import Alias +import qualified GF.Canon.PrintGFC as P + +import Control.Monad +import Data.List (nub,sortBy) + +-- compilation of optimized grammars to canonical GF. AR 5/10/2001 -- 12/5/2003 + +-- | This is the top-level function printing a gfc file +showGFC :: SourceGrammar -> String +showGFC = err id id . liftM (P.printTree . grammar2canon) . redGrammar + +-- | any grammar, first trying without dependent types +-- abstract syntax without dependent types +redGrammar :: SourceGrammar -> Err C.CanonGrammar +redGrammar (MGrammar gr) = liftM MGrammar $ mapM redModInfo $ filter active gr where + active (_,m) = case typeOfModule m of + MTInterface -> False + _ -> True + +redModInfo :: (Ident, SourceModInfo) -> Err (Ident, C.CanonModInfo) +redModInfo (c,info) = do + c' <- redIdent c + info' <- case info of + ModMod m -> do + let isIncompl = not $ isCompleteModule m + (e,os) <- if isIncompl then return ([],[]) else redExtOpen m ---- + flags <- mapM redFlag $ flags m + (a,mt0) <- case mtype m of + MTConcrete a -> do + a' <- redIdent a + return (a', MTConcrete a') + MTAbstract -> return (c',MTAbstract) --- c' not needed + MTResource -> return (c',MTResource) --- c' not needed + MTInterface -> return (c',MTResource) ---- not needed + MTInstance _ -> return (c',MTResource) --- c' not needed + MTTransfer x y -> return (c',MTTransfer (om x) (om y)) --- c' not needed + + --- this generates empty GFC reosurce for interface and incomplete + let js = if isIncompl then emptyBinTree else jments m + mt = mt0 ---- if isIncompl then MTResource else mt0 + + defss <- mapM (redInfo a) $ tree2list $ js + let defs0 = concat defss + let lgh = length defs0 + defs <- return $ sorted2tree $ defs0 -- sorted, but reduced + let flags1 = if isIncompl then C.flagIncomplete : flags else flags + let flags' = G.Flg (identC "modulesize") (identC ("n"++show lgh)) : flags1 + return $ ModMod $ Module mt MSComplete flags' e os defs + return (c',info') + where + redExtOpen m = do + e' <- case extends m of + es -> mapM (liftM inheritAll . redIdent) es + os' <- mapM (\o -> case o of + OQualif q _ i -> liftM (OSimple q) (redIdent i) + _ -> prtBad "cannot translate unqualified open in" c) $ opens m + return (e',nub os') + om = oSimple . openedModule --- normalizing away qualif + +redInfo :: Ident -> (Ident,Info) -> Err [(Ident,C.Info)] +redInfo am (c,info) = errIn ("translating definition of" +++ prt c) $ do + c' <- redIdent c + case info of + AbsCat (Yes cont) pfs -> do + let fs = case pfs of + Yes ts -> [(m,c) | Q m c <- ts] + _ -> [] + returns c' $ C.AbsCat cont fs + AbsFun (Yes typ) pdf -> do + let df = case pdf of + Yes t -> t -- definition or "data" + _ -> Eqs [] -- primitive notion + returns c' $ C.AbsFun typ df + AbsTrans t -> + returns c' $ C.AbsTrans t + + ResParam (Yes (ps,_)) -> do + ps' <- mapM redParam ps + returns c' $ C.ResPar ps' + + CncCat pty ptr ppr -> case (pty,ptr,ppr) of + (Yes ty, Yes (Abs _ t), Yes pr) -> do + ty' <- redCType ty + trm' <- redCTerm t + pr' <- redCTerm pr + return [(c', C.CncCat ty' trm' pr')] + _ -> prtBad ("cannot reduce rule for") c + + CncFun mt ptr ppr -> case (mt,ptr,ppr) of + (Just (cat,_), Yes trm, Yes pr) -> do + cat' <- redIdent cat + (xx,body,_) <- termForm trm + xx' <- mapM redArgvar xx + body' <- errIn (prt body) $ redCTerm body ---- debug + pr' <- redCTerm pr + return [(c',C.CncFun (G.CIQ am cat') xx' body' pr')] + _ -> prtBad ("cannot reduce rule" +++ show info +++ "for") c ---- debug + + AnyInd s b -> do + b' <- redIdent b + returns c' $ C.AnyInd s b' + + _ -> return [] --- retain some operations + where + returns f i = return [(f,i)] + +redQIdent :: QIdent -> Err G.CIdent +redQIdent (m,c) = return $ G.CIQ m c + +redIdent :: Ident -> Err Ident +redIdent x + | isWildIdent x = return $ identC "h_" --- needed in declarations + | otherwise = return $ identC $ prt x --- + +redFlag :: Option -> Err G.Flag +redFlag (Opt (f,[x])) = return $ G.Flg (identC f) (identC x) +redFlag o = Bad $ "cannot reduce option" +++ prOpt o + +redDecl :: Decl -> Err G.Decl +redDecl (x,a) = liftM2 G.Decl (redIdent x) (redType a) + +redType :: Type -> Err G.Exp +redType = redTerm + +redTerm :: Type -> Err G.Exp +redTerm t = return $ rtExp t + +-- to normalize records and record types +sortByFst :: Ord a => [(a,b)] -> [(a,b)] +sortByFst = sortBy (\ x y -> compare (fst x) (fst y)) + +-- resource + +redParam :: Param -> Err G.ParDef +redParam (c,cont) = do + c' <- redIdent c + cont' <- mapM (redCType . snd) cont + return $ G.ParD c' cont' + +redArgvar :: Ident -> Err G.ArgVar +redArgvar x = case x of + IA (x,i) -> return $ G.A (identC x) (toInteger i) + IAV (x,b,i) -> return $ G.AB (identC x) (toInteger b) (toInteger i) + _ -> Bad $ "cannot reduce" +++ show x +++ "as argument variable" + +redLindef :: Term -> Err G.Term +redLindef t = case t of + Abs x b -> redCTerm b --- + _ -> redCTerm t + +redCType :: Type -> Err G.CType +redCType t = case t of + RecType lbs -> do + let (ls,ts) = unzip lbs + ls' = map redLabel ls + ts' <- mapM redCType ts + return $ G.RecType $ map (uncurry G.Lbg) $ sortByFst $ zip ls' ts' + Table p v -> liftM2 G.Table (redCType p) (redCType v) + Q m c -> liftM G.Cn $ redQIdent (m,c) + QC m c -> liftM G.Cn $ redQIdent (m,c) + + App (Q (IC "Predef") (IC "Ints")) (EInt n) -> return $ G.TInts (toInteger n) + + Sort "Str" -> return $ G.TStr + Sort "Tok" -> return $ G.TStr + _ -> prtBad "cannot reduce to canonical the type" t + +redCTerm :: Term -> Err G.Term +redCTerm t = case t of + Vr x -> checkAgain + (liftM G.Arg $ redArgvar x) + (liftM G.LI $ redIdent x) --- for parametrize optimization + App _ s -> do -- only constructor applications can remain + (_,c,xx) <- termForm t + xx' <- mapM redCTerm xx + case c of + QC p c -> liftM2 G.Par (redQIdent (p,c)) (return xx') + Q (IC "Predef") (IC "error") -> fail $ "error: " ++ stringFromTerm s + _ -> prtBad "expected constructor head instead of" c + Q p c -> liftM G.I (redQIdent (p,c)) + QC p c -> liftM2 G.Par (redQIdent (p,c)) (return []) + R rs -> do + let (ls,tts) = unzip rs + ls' = map redLabel ls + ts <- mapM (redCTerm . snd) tts + return $ G.R $ map (uncurry G.Ass) $ sortByFst $ zip ls' ts + RecType [] -> return $ G.R [] --- comes out in parsing + P tr l -> do + tr' <- redCTerm tr + return $ G.P tr' (redLabel l) + PI tr l _ -> redCTerm $ P tr l ----- + T i cs -> do + ty <- getTableType i + ty' <- redCType ty + let (ps,ts) = unzip cs + ps' <- mapM redPatt ps + ts' <- mapM redCTerm ts + return $ G.T ty' $ map (uncurry G.Cas) $ zip (map singleton ps') ts' + TSh i cs -> do + ty <- getTableType i + ty' <- redCType ty + let (pss,ts) = unzip cs + pss' <- mapM (mapM redPatt) pss + ts' <- mapM redCTerm ts + return $ G.T ty' $ map (uncurry G.Cas) $ zip pss' ts' + V ty ts -> do + ty' <- redCType ty + ts' <- mapM redCTerm ts + return $ G.V ty' ts' + S u v -> liftM2 G.S (redCTerm u) (redCTerm v) + K s -> return $ G.K (G.KS s) + EInt i -> return $ G.EInt i + EFloat i -> return $ G.EFloat i + C u v -> liftM2 G.C (redCTerm u) (redCTerm v) + FV ts -> liftM G.FV $ mapM redCTerm ts +--- Ready ss -> return $ G.Ready [redStr ss] --- obsolete + + Alts (d,vs) -> do --- + d' <- redCTermTok d + vs' <- mapM redVariant vs + return $ G.K $ G.KP d' vs' + + Empty -> return $ G.E + +--- Strs ss -> return $ G.Strs [s | K s <- ss] --- + +---- Glue obsolete in canon, should not occur here + Glue x y -> redCTerm (C x y) + + _ -> Bad ("cannot reduce term" +++ prt t) + +redPatt :: Patt -> Err G.Patt +redPatt p = case p of + PP m c ps -> liftM2 G.PC (redQIdent (m,c)) (mapM redPatt ps) + PR rs -> do + let (ls,tts) = unzip rs + ls' = map redLabel ls + ts <- mapM redPatt tts + return $ G.PR $ map (uncurry G.PAss) $ sortByFst $ zip ls' ts + PT _ q -> redPatt q + PInt i -> return $ G.PI i + PFloat i -> return $ G.PF i + PV x -> liftM G.PV $ redIdent x --- for parametrize optimization + _ -> prtBad "cannot reduce pattern" p + +redLabel :: Label -> G.Label +redLabel (LIdent s) = G.L $ identC s +redLabel (LVar i) = G.LV $ toInteger i + +redVariant :: (Term, Term) -> Err G.Variant +redVariant (v,c) = do + v' <- redCTermTok v + c' <- redCTermTok c + return $ G.Var v' c' + +redCTermTok :: Term -> Err [String] +redCTermTok t = case t of + K s -> return [s] + Empty -> return [] + C a b -> liftM2 (++) (redCTermTok a) (redCTermTok b) + Strs ss -> return [s | K s <- ss] --- + _ -> prtBad "cannot get strings from term" t + |
