forked from GitHub/gf-core
changed names of resource-1.3; added a note on homepage on release
This commit is contained in:
765
src/GF/Source/SourceToGrammar.hs
Normal file
765
src/GF/Source/SourceToGrammar.hs
Normal file
@@ -0,0 +1,765 @@
|
||||
----------------------------------------------------------------------
|
||||
-- |
|
||||
-- Module : SourceToGrammar
|
||||
-- Maintainer : AR
|
||||
-- Stability : (stable)
|
||||
-- Portability : (portable)
|
||||
--
|
||||
-- > CVS $Date: 2005/10/04 11:05:07 $
|
||||
-- > CVS $Author: aarne $
|
||||
-- > CVS $Revision: 1.28 $
|
||||
--
|
||||
-- based on the skeleton Haskell module generated by the BNF converter
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
module GF.Source.SourceToGrammar ( transGrammar,
|
||||
transInclude,
|
||||
transModDef,
|
||||
transOldGrammar,
|
||||
transExp,
|
||||
newReservedWords
|
||||
) where
|
||||
|
||||
import qualified GF.Grammar.Grammar as G
|
||||
import qualified GF.Grammar.PrGrammar as GP
|
||||
import qualified GF.Infra.Modules as GM
|
||||
import qualified GF.Grammar.Macros as M
|
||||
import qualified GF.Compile.Update as U
|
||||
import qualified GF.Infra.Option as GO
|
||||
import qualified GF.Compile.ModDeps as GD
|
||||
import GF.Grammar.Predef
|
||||
import GF.Infra.Ident
|
||||
import GF.Source.AbsGF
|
||||
import GF.Source.PrintGF
|
||||
import GF.Compile.RemoveLiT --- for bw compat
|
||||
import GF.Data.Operations
|
||||
import GF.Infra.Option
|
||||
|
||||
import Control.Monad
|
||||
import Data.Char
|
||||
import Data.List (genericReplicate)
|
||||
import qualified Data.ByteString.Char8 as BS
|
||||
|
||||
-- based on the skeleton Haskell module generated by the BNF converter
|
||||
|
||||
type Result = Err String
|
||||
|
||||
failure :: Show a => a -> Err b
|
||||
failure x = Bad $ "Undefined case: " ++ show x
|
||||
|
||||
getIdentPos :: PIdent -> Err (Ident,Int)
|
||||
getIdentPos x = case x of
|
||||
PIdent ((line,_),c) -> return (IC c,line)
|
||||
|
||||
transIdent :: PIdent -> Err Ident
|
||||
transIdent = liftM fst . getIdentPos
|
||||
|
||||
transName :: Name -> Err Ident
|
||||
transName n = case n of
|
||||
IdentName i -> transIdent i
|
||||
ListName i -> liftM mkListId (transIdent i)
|
||||
|
||||
transNamePos :: Name -> Err (Ident,Int)
|
||||
transNamePos n = case n of
|
||||
IdentName i -> getIdentPos i
|
||||
ListName i -> liftM (\ (c,p) -> (mkListId c,p)) (getIdentPos i)
|
||||
|
||||
transGrammar :: Grammar -> Err G.SourceGrammar
|
||||
transGrammar x = case x of
|
||||
Gr moddefs -> do
|
||||
moddefs' <- mapM transModDef moddefs
|
||||
GD.mkSourceGrammar moddefs'
|
||||
|
||||
transModDef :: ModDef -> Err (Ident, G.SourceModInfo)
|
||||
transModDef x = case x of
|
||||
|
||||
MMain id0 id concspecs -> do
|
||||
id0' <- transIdent id0
|
||||
id' <- transIdent id
|
||||
concspecs' <- mapM transConcSpec concspecs
|
||||
return $ (id0', GM.ModMainGrammar (GM.MainGrammar id' concspecs'))
|
||||
|
||||
MModule compl mtyp body -> do
|
||||
|
||||
let mstat' = transComplMod compl
|
||||
|
||||
(trDef, mtyp', id') <- case mtyp of
|
||||
MTAbstract id -> do
|
||||
id' <- transIdent id
|
||||
return (transAbsDef, GM.MTAbstract, id')
|
||||
MTResource id -> mkModRes id GM.MTResource body
|
||||
MTConcrete id open -> do
|
||||
id' <- transIdent id
|
||||
open' <- transIdent open
|
||||
return (transCncDef, GM.MTConcrete open', id')
|
||||
MTTransfer id a b -> do
|
||||
id' <- transIdent id
|
||||
a' <- transOpen a
|
||||
b' <- transOpen a
|
||||
return (transAbsDef, GM.MTTransfer a' b', id')
|
||||
MTInterface id -> mkModRes id GM.MTInterface body
|
||||
MTInstance id open -> do
|
||||
open' <- transIdent open
|
||||
mkModRes id (GM.MTInstance open') body
|
||||
|
||||
mkBody (mstat', trDef, mtyp', id') body
|
||||
where
|
||||
poss = emptyBinTree ----
|
||||
|
||||
mkBody xx@(mstat', trDef, mtyp', id') bod = case bod of
|
||||
MNoBody incls -> do
|
||||
mkBody xx $ MBody (Ext incls) NoOpens []
|
||||
MBody extends opens defs -> do
|
||||
extends' <- transExtend extends
|
||||
opens' <- transOpens opens
|
||||
defs0 <- mapM trDef $ getTopDefs defs
|
||||
poss0 <- return [(i,p) | Left ds <- defs0, (i,p,_) <- ds]
|
||||
defs' <- U.buildAnyTree [(i,d) | Left ds <- defs0, (i,_,d) <- ds]
|
||||
flags' <- return $ concatModuleOptions [o | Right o <- defs0]
|
||||
let poss1 = buildPosTree id' poss0
|
||||
return (id',
|
||||
GM.ModMod (GM.Module mtyp' mstat' flags' extends' opens' defs' poss1))
|
||||
MReuse _ -> do
|
||||
return (id', GM.ModMod (GM.Module mtyp' mstat' noModuleOptions [] [] emptyBinTree poss))
|
||||
MUnion imps -> do
|
||||
imps' <- mapM transIncluded imps
|
||||
return (id',
|
||||
GM.ModMod (GM.Module (GM.MTUnion mtyp' imps') mstat' noModuleOptions [] [] emptyBinTree poss))
|
||||
|
||||
MWith m insts -> mkBody xx $ MWithEBody [] m insts NoOpens []
|
||||
MWithBody m insts opens defs -> mkBody xx $ MWithEBody [] m insts opens defs
|
||||
MWithE extends m insts -> mkBody xx $ MWithEBody extends m insts NoOpens []
|
||||
MWithEBody extends m insts opens defs -> do
|
||||
extends' <- mapM transIncludedExt extends
|
||||
m' <- transIncludedExt m
|
||||
insts' <- mapM transOpen insts
|
||||
opens' <- transOpens opens
|
||||
defs0 <- mapM trDef $ getTopDefs defs
|
||||
poss0 <- return [(i,p) | Left ds <- defs0, (i,p,_) <- ds]
|
||||
defs' <- U.buildAnyTree [(i,d) | Left ds <- defs0, (i,_,d) <- ds]
|
||||
flags' <- return $ concatModuleOptions [o | Right o <- defs0]
|
||||
let poss1 = buildPosTree id' poss0
|
||||
return (id',
|
||||
GM.ModWith (GM.Module mtyp' mstat' flags' extends' opens' defs' poss1) m' insts')
|
||||
|
||||
mkModRes id mtyp body = do
|
||||
id' <- transIdent id
|
||||
case body of
|
||||
MReuse c -> do
|
||||
c' <- transIdent c
|
||||
mtyp' <- trMReuseType mtyp c'
|
||||
return (transResDef, GM.MTReuse mtyp', id')
|
||||
_ -> return (transResDef, mtyp, id')
|
||||
trMReuseType mtyp c = case mtyp of
|
||||
GM.MTInterface -> return $ GM.MRInterface c
|
||||
GM.MTInstance op -> return $ GM.MRInstance c op
|
||||
GM.MTResource -> return $ GM.MRResource c
|
||||
|
||||
|
||||
transComplMod :: ComplMod -> GM.ModuleStatus
|
||||
transComplMod x = case x of
|
||||
CMCompl -> GM.MSComplete
|
||||
CMIncompl -> GM.MSIncomplete
|
||||
|
||||
getTopDefs :: [TopDef] -> [TopDef]
|
||||
getTopDefs x = x
|
||||
|
||||
transConcSpec :: ConcSpec -> Err (GM.MainConcreteSpec Ident)
|
||||
transConcSpec x = case x of
|
||||
ConcSpec id concexp -> do
|
||||
id' <- transIdent id
|
||||
(m,mi,mo) <- transConcExp concexp
|
||||
return $ GM.MainConcreteSpec id' m mi mo
|
||||
|
||||
transConcExp :: ConcExp ->
|
||||
Err (Ident, Maybe (GM.OpenSpec Ident),Maybe (GM.OpenSpec Ident))
|
||||
transConcExp x = case x of
|
||||
ConcExp id transfers -> do
|
||||
id' <- transIdent id
|
||||
trs <- mapM transTransfer transfers
|
||||
tin <- case [o | Left o <- trs] of
|
||||
[o] -> return $ Just o
|
||||
[] -> return $ Nothing
|
||||
_ -> Bad "ambiguous transfer in"
|
||||
tout <- case [o | Right o <- trs] of
|
||||
[o] -> return $ Just o
|
||||
[] -> return $ Nothing
|
||||
_ -> Bad "ambiguous transfer out"
|
||||
return (id',tin,tout)
|
||||
|
||||
transTransfer :: Transfer ->
|
||||
Err (Either (GM.OpenSpec Ident)(GM.OpenSpec Ident))
|
||||
transTransfer x = case x of
|
||||
TransferIn open -> liftM Left $ transOpen open
|
||||
TransferOut open -> liftM Right $ transOpen open
|
||||
|
||||
transExtend :: Extend -> Err [(Ident,GM.MInclude Ident)]
|
||||
transExtend x = case x of
|
||||
Ext ids -> mapM transIncludedExt ids
|
||||
NoExt -> return []
|
||||
|
||||
transOpens :: Opens -> Err [GM.OpenSpec Ident]
|
||||
transOpens x = case x of
|
||||
NoOpens -> return []
|
||||
OpenIn opens -> mapM transOpen opens
|
||||
|
||||
transOpen :: Open -> Err (GM.OpenSpec Ident)
|
||||
transOpen x = case x of
|
||||
OName id -> liftM (GM.OSimple GM.OQNormal) $ transIdent id
|
||||
OQualQO q id -> liftM2 GM.OSimple (transQualOpen q) (transIdent id)
|
||||
OQual q id m -> liftM3 GM.OQualif (transQualOpen q) (transIdent id) (transIdent m)
|
||||
|
||||
transQualOpen :: QualOpen -> Err GM.OpenQualif
|
||||
transQualOpen x = case x of
|
||||
QOCompl -> return GM.OQNormal
|
||||
QOInterface -> return GM.OQInterface
|
||||
QOIncompl -> return GM.OQIncomplete
|
||||
|
||||
transIncluded :: Included -> Err (Ident,[Ident])
|
||||
transIncluded x = case x of
|
||||
IAll i -> liftM (flip (curry id) []) $ transIdent i
|
||||
ISome i ids -> liftM2 (curry id) (transIdent i) (mapM transIdent ids)
|
||||
IMinus i ids -> liftM2 (curry id) (transIdent i) (mapM transIdent ids) ----
|
||||
|
||||
transIncludedExt :: Included -> Err (Ident, GM.MInclude Ident)
|
||||
transIncludedExt x = case x of
|
||||
IAll i -> liftM2 (,) (transIdent i) (return GM.MIAll)
|
||||
ISome i ids -> liftM2 (,) (transIdent i) (liftM GM.MIOnly $ mapM transIdent ids)
|
||||
IMinus i ids -> liftM2 (,) (transIdent i) (liftM GM.MIExcept $ mapM transIdent ids)
|
||||
|
||||
--- where no position is saved
|
||||
nopos :: Int
|
||||
nopos = -1
|
||||
|
||||
buildPosTree :: Ident -> [(Ident,Int)] -> BinTree Ident (String,(Int,Int))
|
||||
buildPosTree m = buildTree . mkPoss . filter ((>0) . snd) where
|
||||
mkPoss cs = case cs of
|
||||
(i,p):rest@((_,q):_) -> (i,(name,(p,max p (q-1)))) : mkPoss rest
|
||||
(i,p):[] -> (i,(name,(p,p+100))) : [] --- don't know last line
|
||||
_ -> []
|
||||
name = prIdent m ++ ".gf" ----
|
||||
|
||||
transAbsDef :: TopDef -> Err (Either [(Ident, Int, G.Info)] GO.ModuleOptions)
|
||||
transAbsDef x = case x of
|
||||
DefCat catdefs -> liftM (Left . concat) $ mapM transCatDef catdefs
|
||||
DefFun fundefs -> do
|
||||
fundefs' <- mapM transFunDef fundefs
|
||||
returnl [(fun, nopos, G.AbsFun (yes typ) nope) | (funs,typ) <- fundefs', fun <- funs]
|
||||
DefFunData fundefs -> do
|
||||
fundefs' <- mapM transFunDef fundefs
|
||||
returnl $
|
||||
[(cat, nopos, G.AbsCat nope (yes [G.Cn fun])) | (funs,typ) <- fundefs',
|
||||
fun <- funs,
|
||||
Ok (_,cat) <- [M.valCat typ]
|
||||
] ++
|
||||
[(fun, nopos, G.AbsFun (yes typ) (yes G.EData)) | (funs,typ) <- fundefs', fun <- funs]
|
||||
DefDef defs -> do
|
||||
defs' <- liftM concat $ mapM getDefsGen defs
|
||||
returnl [(c, nopos, G.AbsFun nope pe) | ((c,p),(_,pe)) <- defs']
|
||||
DefData ds -> do
|
||||
ds' <- mapM transDataDef ds
|
||||
returnl $
|
||||
[(c, nopos, G.AbsCat nope (yes ps)) | (c,ps) <- ds'] ++
|
||||
[(f, nopos, G.AbsFun nope (yes G.EData)) | (_,fs) <- ds', tf <- fs, f <- funs tf]
|
||||
DefTrans defs -> do
|
||||
defs' <- liftM concat $ mapM getDefsGen defs
|
||||
returnl [(c, nopos, G.AbsTrans f) | ((c,p),(_,Yes f)) <- defs']
|
||||
DefFlag defs -> liftM (Right . concatModuleOptions) $ mapM transFlagDef defs
|
||||
_ -> Bad $ "illegal definition in abstract module:" ++++ printTree x
|
||||
where
|
||||
-- to get data constructors as terms
|
||||
funs t = case t of
|
||||
G.Cn f -> [f]
|
||||
G.Q _ f -> [f]
|
||||
G.QC _ f -> [f]
|
||||
_ -> []
|
||||
|
||||
returnl :: a -> Err (Either a b)
|
||||
returnl = return . Left
|
||||
|
||||
transFlagDef :: FlagDef -> Err GO.ModuleOptions
|
||||
transFlagDef x = case x of
|
||||
FlagDef f x -> parseModuleOptions ["--" ++ prPIdent f ++ "=" ++ prPIdent x]
|
||||
where
|
||||
prPIdent (PIdent (_,c)) = BS.unpack c
|
||||
|
||||
|
||||
-- | Cat definitions can also return some fun defs
|
||||
-- if it is a list category definition
|
||||
transCatDef :: CatDef -> Err [(Ident, Int, G.Info)]
|
||||
transCatDef x = case x of
|
||||
SimpleCatDef id ddecls -> do
|
||||
(id',pos) <- getIdentPos id
|
||||
liftM (:[]) $ cat id' pos ddecls
|
||||
ListCatDef id ddecls -> listCat id ddecls 0
|
||||
ListSizeCatDef id ddecls size -> listCat id ddecls size
|
||||
where
|
||||
cat i pos ddecls = do
|
||||
-- i <- transIdent id
|
||||
cont <- liftM concat $ mapM transDDecl ddecls
|
||||
return (i, pos, G.AbsCat (yes cont) nope)
|
||||
listCat id ddecls size = do
|
||||
(id',pos) <- getIdentPos id
|
||||
let
|
||||
li = mkListId id'
|
||||
baseId = mkBaseId id'
|
||||
consId = mkConsId id'
|
||||
catd0@(c,p,G.AbsCat (Yes cont0) _) <- cat li pos ddecls
|
||||
let
|
||||
catd = (c,pos,G.AbsCat (Yes cont0) (Yes [G.Cn baseId,G.Cn consId]))
|
||||
cont = [(mkId x i,ty) | (i,(x,ty)) <- zip [0..] cont0]
|
||||
xs = map (G.Vr . fst) cont
|
||||
cd = M.mkDecl (M.mkApp (G.Vr id') xs)
|
||||
lc = M.mkApp (G.Vr li) xs
|
||||
niltyp = M.mkProdSimple (cont ++ genericReplicate size cd) lc
|
||||
nilfund = (baseId, nopos, G.AbsFun (yes niltyp) (yes G.EData))
|
||||
constyp = M.mkProdSimple (cont ++ [cd, M.mkDecl lc]) lc
|
||||
consfund = (consId, nopos, G.AbsFun (yes constyp) (yes G.EData))
|
||||
return [catd,nilfund,consfund]
|
||||
mkId x i = if isWildIdent x then (varX i) else x
|
||||
|
||||
transFunDef :: FunDef -> Err ([Ident], G.Type)
|
||||
transFunDef x = case x of
|
||||
FunDef ids typ -> liftM2 (,) (mapM transIdent ids) (transExp typ)
|
||||
|
||||
transDataDef :: DataDef -> Err (Ident,[G.Term])
|
||||
transDataDef x = case x of
|
||||
DataDef id ds -> liftM2 (,) (transIdent id) (mapM transData ds)
|
||||
where
|
||||
transData d = case d of
|
||||
DataId id -> liftM G.Cn $ transIdent id
|
||||
DataQId id0 id -> liftM2 G.QC (transIdent id0) (transIdent id)
|
||||
|
||||
transResDef :: TopDef -> Err (Either [(Ident, Int, G.Info)] GO.ModuleOptions)
|
||||
transResDef x = case x of
|
||||
DefPar pardefs -> do
|
||||
pardefs' <- mapM transParDef pardefs
|
||||
returnl $ [(p, nopos, G.ResParam (if null pars
|
||||
then nope -- abstract param type
|
||||
else (yes (pars,Nothing))))
|
||||
| (p,pars) <- pardefs']
|
||||
++ [(f, nopos, G.ResValue (yes (M.mkProdSimple co (G.Cn p),Nothing))) |
|
||||
(p,pars) <- pardefs', (f,co) <- pars]
|
||||
|
||||
DefOper defs -> do
|
||||
defs' <- liftM concat $ mapM getDefs defs
|
||||
returnl $
|
||||
concatMap mkOverload [(f, p, G.ResOper pt pe) | ((f,p),(pt,pe)) <- defs']
|
||||
|
||||
DefLintype defs -> do
|
||||
defs' <- liftM concat $ mapM getDefs defs
|
||||
returnl [(f, p, G.ResOper pt pe) | ((f,p),(pt,pe)) <- defs']
|
||||
|
||||
DefFlag defs -> liftM (Right . concatModuleOptions) $ mapM transFlagDef defs
|
||||
_ -> Bad $ "illegal definition form in resource" +++ printTree x
|
||||
where
|
||||
mkOverload op@(c,p,j) = case j of
|
||||
G.ResOper _ (Yes df) -> case M.appForm df of
|
||||
(keyw, ts@(_:_)) | isOverloading keyw -> case last ts of
|
||||
G.R fs ->
|
||||
[(c,p,G.ResOverload [m | G.Vr m <- ts] [(ty,fu) | (_,(Just ty,fu)) <- fs])]
|
||||
_ -> [op]
|
||||
_ -> [op]
|
||||
|
||||
-- to enable separare type signature --- not type-checked
|
||||
G.ResOper (Yes df) _ -> case M.appForm df of
|
||||
(keyw, ts@(_:_)) | isOverloading keyw -> case last ts of
|
||||
G.RecType _ -> []
|
||||
_ -> [op]
|
||||
_ -> [op]
|
||||
_ -> [(c,p,j)]
|
||||
isOverloading keyw =
|
||||
GP.prt keyw == "overload" -- overload is a "soft keyword"
|
||||
isRec t = case t of
|
||||
G.R _ -> True
|
||||
_ -> False
|
||||
|
||||
transParDef :: ParDef -> Err (Ident, [G.Param])
|
||||
transParDef x = case x of
|
||||
ParDefDir id params -> liftM2 (,) (transIdent id) (mapM transParConstr params)
|
||||
ParDefAbs id -> liftM2 (,) (transIdent id) (return [])
|
||||
_ -> Bad $ "illegal definition in resource:" ++++ printTree x
|
||||
|
||||
transCncDef :: TopDef -> Err (Either [(Ident, Int, G.Info)] GO.ModuleOptions)
|
||||
transCncDef x = case x of
|
||||
DefLincat defs -> do
|
||||
defs' <- liftM concat $ mapM transPrintDef defs
|
||||
returnl [(f, nopos, G.CncCat (yes t) nope nope) | (f,t) <- defs']
|
||||
DefLindef defs -> do
|
||||
defs' <- liftM concat $ mapM getDefs defs
|
||||
returnl [(f, p, G.CncCat pt pe nope) | ((f,p),(pt,pe)) <- defs']
|
||||
DefLin defs -> do
|
||||
defs' <- liftM concat $ mapM getDefs defs
|
||||
returnl [(f, p, G.CncFun Nothing pe nope) | ((f,p),(_,pe)) <- defs']
|
||||
DefPrintCat defs -> do
|
||||
defs' <- liftM concat $ mapM transPrintDef defs
|
||||
returnl [(f, nopos, G.CncCat nope nope (yes e)) | (f,e) <- defs']
|
||||
DefPrintFun defs -> do
|
||||
defs' <- liftM concat $ mapM transPrintDef defs
|
||||
returnl [(f, nopos, G.CncFun Nothing nope (yes e)) | (f,e) <- defs']
|
||||
DefPrintOld defs -> do --- a guess, for backward compatibility
|
||||
defs' <- liftM concat $ mapM transPrintDef defs
|
||||
returnl [(f, nopos, G.CncFun Nothing nope (yes e)) | (f,e) <- defs']
|
||||
DefFlag defs -> liftM (Right . concatModuleOptions) $ mapM transFlagDef defs
|
||||
DefPattern defs -> do
|
||||
defs' <- liftM concat $ mapM getDefs defs
|
||||
let defs2 = [(f, termInPattern t) | (f,(_,Yes t)) <- defs']
|
||||
returnl [(f, p, G.CncFun Nothing (yes t) nope) | ((f,p),t) <- defs2]
|
||||
|
||||
_ -> errIn ("illegal definition in concrete syntax:") $ transResDef x
|
||||
|
||||
transPrintDef :: PrintDef -> Err [(Ident,G.Term)]
|
||||
transPrintDef x = case x of
|
||||
PrintDef ids exp -> do
|
||||
(ids,e) <- liftM2 (,) (mapM transName ids) (transExp exp)
|
||||
return $ [(i,e) | i <- ids]
|
||||
|
||||
getDefsGen :: Def -> Err [((Ident, Int),(G.Perh G.Type, G.Perh G.Term))]
|
||||
getDefsGen d = case d of
|
||||
DDecl ids t -> do
|
||||
ids' <- mapM transNamePos ids
|
||||
t' <- transExp t
|
||||
return [(i,(yes t', nope)) | i <- ids']
|
||||
DDef ids e -> do
|
||||
ids' <- mapM transNamePos ids
|
||||
e' <- transExp e
|
||||
return [(i,(nope, yes e')) | i <- ids']
|
||||
DFull ids t e -> do
|
||||
ids' <- mapM transNamePos ids
|
||||
t' <- transExp t
|
||||
e' <- transExp e
|
||||
return [(i,(yes t', yes e')) | i <- ids']
|
||||
DPatt id patts e -> do
|
||||
id' <- transNamePos id
|
||||
ps' <- mapM transPatt patts
|
||||
e' <- transExp e
|
||||
return [(id',(nope, yes (G.Eqs [(ps',e')])))]
|
||||
|
||||
-- | sometimes you need this special case, e.g. in linearization rules
|
||||
getDefs :: Def -> Err [((Ident,Int), (G.Perh G.Type, G.Perh G.Term))]
|
||||
getDefs d = case d of
|
||||
DPatt id patts e -> do
|
||||
id' <- transNamePos id
|
||||
xs <- mapM tryMakeVar patts
|
||||
e' <- transExp e
|
||||
return [(id',(nope, yes (M.mkAbs xs e')))]
|
||||
_ -> getDefsGen d
|
||||
|
||||
-- | accepts a pattern that is either a variable or a wild card
|
||||
tryMakeVar :: Patt -> Err Ident
|
||||
tryMakeVar p = do
|
||||
p' <- transPatt p
|
||||
case p' of
|
||||
G.PV i -> return i
|
||||
G.PW -> return identW
|
||||
_ -> Bad $ "not a legal pattern in lambda binding" +++ GP.prt p'
|
||||
|
||||
transExp :: Exp -> Err G.Term
|
||||
transExp x = case x of
|
||||
EIdent id -> liftM G.Vr $ transIdent id
|
||||
EConstr id -> liftM G.Con $ transIdent id
|
||||
ECons id -> liftM G.Cn $ transIdent id
|
||||
EQConstr m c -> liftM2 G.QC (transIdent m) (transIdent c)
|
||||
EQCons m c -> liftM2 G.Q (transIdent m) (transIdent c)
|
||||
EString str -> return $ G.K str
|
||||
ESort sort -> return $ G.Sort $ transSort sort
|
||||
EInt n -> return $ G.EInt n
|
||||
EFloat n -> return $ G.EFloat n
|
||||
EMeta -> return $ G.Meta $ M.int2meta 0
|
||||
EEmpty -> return G.Empty
|
||||
-- [ C x_1 ... x_n ] becomes (ListC x_1 ... x_n)
|
||||
EList i es -> do
|
||||
i' <- transIdent i
|
||||
es' <- mapM transExp (exps2list es)
|
||||
return $ foldl G.App (G.Vr (mkListId i')) es'
|
||||
EStrings [] -> return G.Empty
|
||||
EStrings str -> return $ foldr1 G.C $ map G.K $ words str
|
||||
ERecord defs -> erecord2term defs
|
||||
ETupTyp _ _ -> do
|
||||
let tups t = case t of
|
||||
ETupTyp x y -> tups x ++ [y] -- right-associative parsing
|
||||
_ -> [t]
|
||||
es <- mapM transExp $ tups x
|
||||
return $ G.RecType $ M.tuple2recordType es
|
||||
ETuple tuplecomps -> do
|
||||
es <- mapM transExp [e | TComp e <- tuplecomps]
|
||||
return $ G.R $ M.tuple2record es
|
||||
EProj exp id -> liftM2 G.P (transExp exp) (trLabel id)
|
||||
EApp exp0 exp -> liftM2 G.App (transExp exp0) (transExp exp)
|
||||
ETable cases -> liftM (G.T G.TRaw) (transCases cases)
|
||||
ETTable exp cases ->
|
||||
liftM2 (\t c -> G.T (G.TTyped t) c) (transExp exp) (transCases cases)
|
||||
EVTable exp cases ->
|
||||
liftM2 (\t c -> G.V t c) (transExp exp) (mapM transExp cases)
|
||||
ECase exp cases -> do
|
||||
exp' <- transExp exp
|
||||
cases' <- transCases cases
|
||||
let annot = case exp' of
|
||||
G.Typed _ t -> G.TTyped t
|
||||
_ -> G.TRaw
|
||||
return $ G.S (G.T annot cases') exp'
|
||||
ECTable binds exp -> liftM2 M.mkCTable (mapM transBind binds) (transExp exp)
|
||||
|
||||
EVariants exps -> liftM G.FV $ mapM transExp exps
|
||||
EPre exp alts -> liftM2 (curry G.Alts) (transExp exp) (mapM transAltern alts)
|
||||
EStrs exps -> liftM G.Strs $ mapM transExp exps
|
||||
ESelect exp0 exp -> liftM2 G.S (transExp exp0) (transExp exp)
|
||||
EExtend exp0 exp -> liftM2 G.ExtR (transExp exp0) (transExp exp)
|
||||
EAbstr binds exp -> liftM2 M.mkAbs (mapM transBind binds) (transExp exp)
|
||||
ETyped exp0 exp -> liftM2 G.Typed (transExp exp0) (transExp exp)
|
||||
EExample exp str -> liftM2 G.Example (transExp exp) (return str)
|
||||
|
||||
EProd decl exp -> liftM2 M.mkProdSimple (transDecl decl) (transExp exp)
|
||||
ETType exp0 exp -> liftM2 G.Table (transExp exp0) (transExp exp)
|
||||
EConcat exp0 exp -> liftM2 G.C (transExp exp0) (transExp exp)
|
||||
EGlue exp0 exp -> liftM2 G.Glue (transExp exp0) (transExp exp)
|
||||
ELet defs exp -> do
|
||||
exp' <- transExp exp
|
||||
defs0 <- mapM locdef2fields defs
|
||||
defs' <- mapM tryLoc $ concat defs0
|
||||
return $ M.mkLet defs' exp'
|
||||
where
|
||||
tryLoc (c,(mty,Just e)) = return (c,(mty,e))
|
||||
tryLoc (c,_) = Bad $ "local definition of" +++ GP.prt c +++ "without value"
|
||||
ELetb defs exp -> transExp $ ELet defs exp
|
||||
EWhere exp defs -> transExp $ ELet defs exp
|
||||
|
||||
EPattType typ -> liftM G.EPattType (transExp typ)
|
||||
EPatt patt -> liftM G.EPatt (transPatt patt)
|
||||
|
||||
ELString (LString str) -> return $ G.K (BS.unpack str) -- use the grammar encoding here
|
||||
ELin id -> liftM G.LiT $ transIdent id
|
||||
|
||||
EEqs eqs -> liftM G.Eqs $ mapM transEquation eqs
|
||||
|
||||
_ -> Bad $ "translation not yet defined for" +++ printTree x ----
|
||||
|
||||
exps2list :: Exps -> [Exp]
|
||||
exps2list NilExp = []
|
||||
exps2list (ConsExp e es) = e : exps2list es
|
||||
|
||||
--- this is complicated: should we change Exp or G.Term ?
|
||||
|
||||
erecord2term :: [LocDef] -> Err G.Term
|
||||
erecord2term ds = do
|
||||
ds' <- mapM locdef2fields ds
|
||||
mkR $ concat ds'
|
||||
where
|
||||
mkR fs = do
|
||||
fs' <- transF fs
|
||||
return $ case fs' of
|
||||
Left ts -> G.RecType ts
|
||||
Right ds -> G.R ds
|
||||
transF [] = return $ Left [] --- empty record always interpreted as record type
|
||||
transF fs@(f:_) = case f of
|
||||
(lab,(Just ty,Nothing)) -> mapM tryRT fs >>= return . Left
|
||||
_ -> mapM tryR fs >>= return . Right
|
||||
tryRT f = case f of
|
||||
(lab,(Just ty,Nothing)) -> return (G.ident2label lab,ty)
|
||||
_ -> Bad $ "illegal record type field" +++ GP.prt (fst f) --- manifest fields ?!
|
||||
tryR f = case f of
|
||||
(lab,(mty, Just t)) -> return (G.ident2label lab,(mty,t))
|
||||
_ -> Bad $ "illegal record field" +++ GP.prt (fst f)
|
||||
|
||||
|
||||
locdef2fields :: LocDef -> Err [(Ident, (Maybe G.Type, Maybe G.Type))]
|
||||
locdef2fields d = case d of
|
||||
LDDecl ids t -> do
|
||||
labs <- mapM transIdent ids
|
||||
t' <- transExp t
|
||||
return [(lab,(Just t',Nothing)) | lab <- labs]
|
||||
LDDef ids e -> do
|
||||
labs <- mapM transIdent ids
|
||||
e' <- transExp e
|
||||
return [(lab,(Nothing, Just e')) | lab <- labs]
|
||||
LDFull ids t e -> do
|
||||
labs <- mapM transIdent ids
|
||||
t' <- transExp t
|
||||
e' <- transExp e
|
||||
return [(lab,(Just t', Just e')) | lab <- labs]
|
||||
|
||||
trLabel :: Label -> Err G.Label
|
||||
trLabel x = case x of
|
||||
LIdent (PIdent (_, s)) -> return $ G.LIdent s
|
||||
LVar x -> return $ G.LVar $ fromInteger x
|
||||
|
||||
transSort :: Sort -> Ident
|
||||
transSort Sort_Type = cType
|
||||
transSort Sort_PType = cPType
|
||||
transSort Sort_Tok = cTok
|
||||
transSort Sort_Str = cStr
|
||||
transSort Sort_Strs = cStrs
|
||||
|
||||
|
||||
{-
|
||||
--- no more used 7/1/2006 AR
|
||||
transPatts :: Patt -> Err [G.Patt]
|
||||
transPatts p = case p of
|
||||
PDisj p1 p2 -> liftM2 (++) (transPatts p1) (transPatts p2)
|
||||
PC id patts -> liftM (map (G.PC id) . combinations) $ mapM transPatts patts
|
||||
PQC q id patts -> liftM (map (G.PP q id) . combinations) (mapM transPatts patts)
|
||||
|
||||
PR pattasss -> do
|
||||
let (lss,ps) = unzip [(ls,p) | PA ls p <- pattasss]
|
||||
ls = map LIdent $ concat lss
|
||||
ps0 <- mapM transPatts ps
|
||||
let ps' = combinations ps0
|
||||
lss' <- mapM trLabel ls
|
||||
let rss = map (zip lss') ps'
|
||||
return $ map G.PR rss
|
||||
PTup pcs -> do
|
||||
ps0 <- mapM transPatts [e | PTComp e <- pcs]
|
||||
let ps' = combinations ps0
|
||||
return $ map (G.PR . M.tuple2recordPatt) ps'
|
||||
_ -> liftM singleton $ transPatt p
|
||||
-}
|
||||
|
||||
transPatt :: Patt -> Err G.Patt
|
||||
transPatt x = case x of
|
||||
PW -> return G.wildPatt
|
||||
PV id -> liftM G.PV $ transIdent id
|
||||
PC id patts -> liftM2 G.PC (transIdent id) (mapM transPatt patts)
|
||||
PCon id -> liftM2 G.PC (transIdent id) (return [])
|
||||
PInt n -> return $ G.PInt n
|
||||
PFloat n -> return $ G.PFloat n
|
||||
PStr str -> return $ G.PString str
|
||||
PR pattasss -> do
|
||||
let (lss,ps) = unzip [(ls,p) | PA ls p <- pattasss]
|
||||
ls = map LIdent $ concat lss
|
||||
liftM G.PR $ liftM2 zip (mapM trLabel ls) (mapM transPatt ps)
|
||||
PTup pcs ->
|
||||
liftM (G.PR . M.tuple2recordPatt) (mapM transPatt [e | PTComp e <- pcs])
|
||||
PQ id0 id -> liftM3 G.PP (transIdent id0) (transIdent id) (return [])
|
||||
PQC id0 id patts ->
|
||||
liftM3 G.PP (transIdent id0) (transIdent id) (mapM transPatt patts)
|
||||
PDisj p1 p2 -> liftM2 G.PAlt (transPatt p1) (transPatt p2)
|
||||
PSeq p1 p2 -> liftM2 G.PSeq (transPatt p1) (transPatt p2)
|
||||
PRep p -> liftM G.PRep (transPatt p)
|
||||
PNeg p -> liftM G.PNeg (transPatt p)
|
||||
PAs x p -> liftM2 G.PAs (transIdent x) (transPatt p)
|
||||
PChar -> return G.PChar
|
||||
PChars s -> return $ G.PChars s
|
||||
PMacro c -> liftM G.PMacro $ transIdent c
|
||||
PM m c -> liftM2 G.PM (transIdent m) (transIdent c)
|
||||
|
||||
transBind :: Bind -> Err Ident
|
||||
transBind x = case x of
|
||||
BIdent id -> transIdent id
|
||||
BWild -> return identW
|
||||
|
||||
transDecl :: Decl -> Err [G.Decl]
|
||||
transDecl x = case x of
|
||||
DDec binds exp -> do
|
||||
xs <- mapM transBind binds
|
||||
exp' <- transExp exp
|
||||
return [(x,exp') | x <- xs]
|
||||
DExp exp -> liftM (return . M.mkDecl) $ transExp exp
|
||||
|
||||
transCases :: [Case] -> Err [G.Case]
|
||||
transCases = mapM transCase
|
||||
|
||||
transCase :: Case -> Err G.Case
|
||||
transCase (Case p exp) = do
|
||||
patt <- transPatt p
|
||||
exp' <- transExp exp
|
||||
return (patt,exp')
|
||||
|
||||
transEquation :: Equation -> Err G.Equation
|
||||
transEquation x = case x of
|
||||
Equ apatts exp -> liftM2 (,) (mapM transPatt apatts) (transExp exp)
|
||||
|
||||
transAltern :: Altern -> Err (G.Term, G.Term)
|
||||
transAltern x = case x of
|
||||
Alt exp0 exp -> liftM2 (,) (transExp exp0) (transExp exp)
|
||||
|
||||
transParConstr :: ParConstr -> Err G.Param
|
||||
transParConstr x = case x of
|
||||
ParConstr id ddecls -> do
|
||||
id' <- transIdent id
|
||||
ddecls' <- mapM transDDecl ddecls
|
||||
return (id',concat ddecls')
|
||||
|
||||
transDDecl :: DDecl -> Err [G.Decl]
|
||||
transDDecl x = case x of
|
||||
DDDec binds exp -> transDecl $ DDec binds exp
|
||||
DDExp exp -> transDecl $ DExp exp
|
||||
|
||||
-- | to deal with the old format, sort judgements in two modules, forming
|
||||
-- their names from a given string, e.g. file name or overriding user-given string
|
||||
transOldGrammar :: Options -> FilePath -> OldGrammar -> Err G.SourceGrammar
|
||||
transOldGrammar opts name0 x = case x of
|
||||
OldGr includes topdefs -> do --- includes must be collected separately
|
||||
let moddefs = sortTopDefs topdefs
|
||||
g1 <- transGrammar $ Gr moddefs
|
||||
removeLiT g1 --- needed for bw compatibility with an obsolete feature
|
||||
where
|
||||
sortTopDefs ds = [mkAbs a, mkCnc ops (c ++ r)]
|
||||
where
|
||||
ops = map fst ps
|
||||
(a,r,c,ps) = foldr srt ([],[],[],[]) ds
|
||||
srt d (a,r,c,ps) = case d of
|
||||
DefCat catdefs -> (d:a,r,c,ps)
|
||||
DefFun fundefs -> (d:a,r,c,ps)
|
||||
DefFunData fundefs -> (d:a,r,c,ps)
|
||||
DefDef defs -> (d:a,r,c,ps)
|
||||
DefData pardefs -> (d:a,r,c,ps)
|
||||
DefPar pardefs -> (a,d:r,c,ps)
|
||||
DefOper defs -> (a,d:r,c,ps)
|
||||
DefLintype defs -> (a,d:r,c,ps)
|
||||
DefLincat defs -> (a,r,d:c,ps)
|
||||
DefLindef defs -> (a,r,d:c,ps)
|
||||
DefLin defs -> (a,r,d:c,ps)
|
||||
DefPattern defs -> (a,r,d:c,ps)
|
||||
DefFlag defs -> (a,r,d:c,ps) --- a guess
|
||||
DefPrintCat printdefs -> (a,r,d:c,ps)
|
||||
DefPrintFun printdefs -> (a,r,d:c,ps)
|
||||
DefPrintOld printdefs -> (a,r,d:c,ps)
|
||||
-- DefPackage m ds -> (a,r,c,(m,ds):ps) -- OBSOLETE
|
||||
_ -> (a,r,c,ps)
|
||||
mkAbs a = MModule q (MTAbstract absName) (MBody ne (OpenIn []) (topDefs a))
|
||||
mkCnc ps r = MModule q (MTConcrete cncName absName) (MBody ne (OpenIn []) (topDefs r))
|
||||
topDefs t = t
|
||||
ne = NoExt
|
||||
q = CMCompl
|
||||
|
||||
name = maybe name0 (++ ".gf") $ moduleFlag optName opts
|
||||
absName = identPI $ maybe topic id $ moduleFlag optAbsName opts
|
||||
resName = identPI $ maybe ("Res" ++ lang) id $ moduleFlag optResName opts
|
||||
cncName = identPI $ maybe lang id $ moduleFlag optCncName opts
|
||||
|
||||
identPI s = PIdent ((0,0),BS.pack s)
|
||||
|
||||
(beg,rest) = span (/='.') name
|
||||
(topic,lang) = case rest of -- to avoid overwriting old files
|
||||
".gf" -> ("Abs" ++ beg,"Cnc" ++ beg)
|
||||
".cf" -> ("Abs" ++ beg,"Cnc" ++ beg)
|
||||
".ebnf" -> ("Abs" ++ beg,"Cnc" ++ beg)
|
||||
[] -> ("Abs" ++ beg,"Cnc" ++ beg)
|
||||
_:s -> (beg, takeWhile (/='.') s)
|
||||
|
||||
transInclude :: Include -> Err [FilePath]
|
||||
transInclude x = Bad "Old GF with includes no more supported in GF 3.0"
|
||||
|
||||
newReservedWords :: [String]
|
||||
newReservedWords =
|
||||
words $ "abstract concrete interface incomplete " ++
|
||||
"instance out open resource reuse transfer union with where"
|
||||
|
||||
termInPattern :: G.Term -> G.Term
|
||||
termInPattern t = M.mkAbs xx $ G.R [(s, (Nothing, toP body))] where
|
||||
toP t = case t of
|
||||
G.Vr x -> G.P t s
|
||||
_ -> M.composSafeOp toP t
|
||||
s = G.LIdent (BS.pack "s")
|
||||
(xx,body) = abss [] t
|
||||
abss xs t = case t of
|
||||
G.Abs x b -> abss (x:xs) b
|
||||
_ -> (reverse xs,t)
|
||||
|
||||
mkListId,mkConsId,mkBaseId :: Ident -> Ident
|
||||
mkListId = prefixId (BS.pack "List")
|
||||
mkConsId = prefixId (BS.pack "Cons")
|
||||
mkBaseId = prefixId (BS.pack "Base")
|
||||
|
||||
prefixId :: BS.ByteString -> Ident -> Ident
|
||||
prefixId pref id = identC (BS.append pref (ident2bs id))
|
||||
Reference in New Issue
Block a user