mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-06-17 05:50:12 -06:00
* The following modules are no longer used and have been removed completely: GF.Compile.Compute.ConcreteLazy GF.Compile.Compute.ConcreteStrict GF.Compile.Refresh * The STM monad has been commented out. It was only used in GF.Compile.SubExpOpt, where could be replaced with a plain State monad, since no error handling was needed. One of the functions was hardwired to the Err monad, but did in fact not use error handling, so it was turned into a pure function. * The function errVal has been renamed to fromErr (since it is analogous to fromMaybe). * Replaced 'fail' with 'raise' and 'return ()' with 'done' in a few places. * Some additional old code that was already commented out has been removed.
281 lines
7.7 KiB
Haskell
281 lines
7.7 KiB
Haskell
----------------------------------------------------------------------
|
|
-- |
|
|
-- Module : MMacros
|
|
-- Maintainer : AR
|
|
-- Stability : (stable)
|
|
-- Portability : (portable)
|
|
--
|
|
-- > CVS $Date: 2005/05/10 12:49:13 $
|
|
-- > CVS $Author: aarne $
|
|
-- > CVS $Revision: 1.9 $
|
|
--
|
|
-- some more abstractions on grammars, esp. for Edit
|
|
-----------------------------------------------------------------------------
|
|
|
|
module GF.Grammar.MMacros where
|
|
|
|
import GF.Data.Operations
|
|
--import GF.Data.Zipper
|
|
|
|
import GF.Grammar.Grammar
|
|
import GF.Grammar.Printer
|
|
import GF.Infra.Ident
|
|
--import GF.Compile.Refresh
|
|
import GF.Grammar.Values
|
|
----import GrammarST
|
|
import GF.Grammar.Macros
|
|
|
|
import Control.Monad
|
|
import GF.Text.Pretty
|
|
|
|
-- ** Some more abstractions on grammars, esp. for Edit
|
|
|
|
{-
|
|
nodeTree :: Tree -> TrNode
|
|
argsTree :: Tree -> [Tree]
|
|
|
|
nodeTree (Tr (n,_)) = n
|
|
argsTree (Tr (_,ts)) = ts
|
|
|
|
isFocusNode :: TrNode -> Bool
|
|
bindsNode :: TrNode -> Binds
|
|
atomNode :: TrNode -> Atom
|
|
valNode :: TrNode -> Val
|
|
constrsNode :: TrNode -> Constraints
|
|
metaSubstsNode :: TrNode -> MetaSubst
|
|
|
|
isFocusNode (N (_,_,_,_,b)) = b
|
|
bindsNode (N (b,_,_,_,_)) = b
|
|
atomNode (N (_,a,_,_,_)) = a
|
|
valNode (N (_,_,v,_,_)) = v
|
|
constrsNode (N (_,_,_,(c,_),_)) = c
|
|
metaSubstsNode (N (_,_,_,(_,m),_)) = m
|
|
|
|
atomTree :: Tree -> Atom
|
|
valTree :: Tree -> Val
|
|
|
|
atomTree = atomNode . nodeTree
|
|
valTree = valNode . nodeTree
|
|
|
|
mkNode :: Binds -> Atom -> Val -> (Constraints, MetaSubst) -> TrNode
|
|
mkNode binds atom vtyp cs = N (binds,atom,vtyp,cs,False)
|
|
|
|
metasTree :: Tree -> [MetaId]
|
|
metasTree = concatMap metasNode . scanTree where
|
|
metasNode n = [m | AtM m <- [atomNode n]] ++ map fst (metaSubstsNode n)
|
|
|
|
varsTree :: Tree -> [(Var,Val)]
|
|
varsTree t = [(x,v) | N (_,AtV x,v,_,_) <- scanTree t]
|
|
|
|
constrsTree :: Tree -> Constraints
|
|
constrsTree = constrsNode . nodeTree
|
|
|
|
allConstrsTree :: Tree -> Constraints
|
|
allConstrsTree = concatMap constrsNode . scanTree
|
|
|
|
changeConstrs :: (Constraints -> Constraints) -> TrNode -> TrNode
|
|
changeConstrs f (N (b,a,v,(c,m),x)) = N (b,a,v,(f c, m),x)
|
|
|
|
changeMetaSubst :: (MetaSubst -> MetaSubst) -> TrNode -> TrNode
|
|
changeMetaSubst f (N (b,a,v,(c,m),x)) = N (b,a,v,(c, f m),x)
|
|
|
|
changeAtom :: (Atom -> Atom) -> TrNode -> TrNode
|
|
changeAtom f (N (b,a,v,(c,m),x)) = N (b,f a,v,(c, m),x)
|
|
|
|
-- * on the way to Edit
|
|
|
|
uTree :: Tree
|
|
uTree = Tr (uNode, []) -- unknown tree
|
|
|
|
uNode :: TrNode
|
|
uNode = mkNode [] uAtom uVal ([],[])
|
|
|
|
|
|
uAtom :: Atom
|
|
uAtom = AtM meta0
|
|
|
|
mAtom :: Atom
|
|
mAtom = AtM meta0
|
|
-}
|
|
|
|
type Var = Ident
|
|
|
|
uVal :: Val
|
|
uVal = vClos uExp
|
|
|
|
vClos :: Exp -> Val
|
|
vClos = VClos []
|
|
|
|
uExp :: Exp
|
|
uExp = Meta meta0
|
|
|
|
mExp, mExp0 :: Exp
|
|
mExp = Meta meta0
|
|
mExp0 = mExp
|
|
|
|
meta2exp :: MetaId -> Exp
|
|
meta2exp = Meta
|
|
{-
|
|
atomC :: Fun -> Atom
|
|
atomC = AtC
|
|
|
|
funAtom :: Atom -> Err Fun
|
|
funAtom a = case a of
|
|
AtC f -> return f
|
|
_ -> prtBad "not function head" a
|
|
|
|
atomIsMeta :: Atom -> Bool
|
|
atomIsMeta atom = case atom of
|
|
AtM _ -> True
|
|
_ -> False
|
|
|
|
getMetaAtom :: Atom -> Err MetaId
|
|
getMetaAtom a = case a of
|
|
AtM m -> return m
|
|
_ -> Bad "the active node is not meta"
|
|
-}
|
|
cat2val :: Context -> Cat -> Val
|
|
cat2val cont cat = vClos $ mkApp (Q cat) [Meta i | i <- [1..length cont]]
|
|
|
|
val2cat :: Val -> Err Cat
|
|
val2cat v = liftM valCat (val2exp v)
|
|
|
|
substTerm :: [Ident] -> Substitution -> Term -> Term
|
|
substTerm ss g c = case c of
|
|
Vr x -> maybe c id $ lookup x g
|
|
App f a -> App (substTerm ss g f) (substTerm ss g a)
|
|
Abs b x t -> let y = mkFreshVarX ss x in
|
|
Abs b y (substTerm (y:ss) ((x, Vr y):g) t)
|
|
Prod b x a t -> let y = mkFreshVarX ss x in
|
|
Prod b y (substTerm ss g a) (substTerm (y:ss) ((x,Vr y):g) t)
|
|
_ -> c
|
|
|
|
metaSubstExp :: MetaSubst -> [(MetaId,Exp)]
|
|
metaSubstExp msubst = [(m, fromErr (meta2exp m) (val2expSafe v)) | (m,v) <- msubst]
|
|
|
|
-- ** belong here rather than to computation
|
|
|
|
substitute :: [Var] -> Substitution -> Exp -> Err Exp
|
|
substitute v s = return . substTerm v s
|
|
|
|
alphaConv :: [Var] -> (Var,Var) -> Exp -> Err Exp ---
|
|
alphaConv oldvars (x,x') = substitute (x:x':oldvars) [(x,Vr x')]
|
|
|
|
--alphaFresh :: [Var] -> Exp -> Err Exp
|
|
--alphaFresh vs = refreshTermN $ maxVarIndex vs
|
|
|
|
-- | done in a state monad
|
|
--alphaFreshAll :: [Var] -> [Exp] -> Err [Exp]
|
|
--alphaFreshAll vs = mapM $ alphaFresh vs
|
|
|
|
-- | for display
|
|
val2exp :: Val -> Err Exp
|
|
val2exp = val2expP False
|
|
|
|
-- | for type checking
|
|
val2expSafe :: Val -> Err Exp
|
|
val2expSafe = val2expP True
|
|
|
|
val2expP :: Bool -> Val -> Err Exp
|
|
val2expP safe v = case v of
|
|
|
|
VClos g@(_:_) e@(Meta _) -> if safe
|
|
then Bad (render ("unsafe value substitution" <+> ppValue Unqualified 0 v))
|
|
else substVal g e
|
|
VClos g e -> substVal g e
|
|
VApp f c -> liftM2 App (val2expP safe f) (val2expP safe c)
|
|
VCn c -> return $ Q c
|
|
VGen i x -> if safe
|
|
then Bad (render ("unsafe val2exp" <+> ppValue Unqualified 0 v))
|
|
else return $ Vr $ x --- in editing, no alpha conversions presentv
|
|
VRecType xs->do xs <- mapM (\(l,v) -> val2expP safe v >>= \e -> return (l,e)) xs
|
|
return (RecType xs)
|
|
VType -> return typeType
|
|
where
|
|
substVal g e = mapPairsM (val2expP safe) g >>= return . (\s -> substTerm [] s e)
|
|
|
|
isConstVal :: Val -> Bool
|
|
isConstVal v = case v of
|
|
VApp f c -> isConstVal f && isConstVal c
|
|
VCn _ -> True
|
|
VClos [] e -> null $ freeVarsExp e
|
|
_ -> False --- could be more liberal
|
|
|
|
mkProdVal :: Binds -> Val -> Err Val ---
|
|
mkProdVal bs v = do
|
|
bs' <- mapPairsM val2exp bs
|
|
v' <- val2exp v
|
|
return $ vClos $ foldr (uncurry (Prod Explicit)) v' bs'
|
|
|
|
freeVarsExp :: Exp -> [Ident]
|
|
freeVarsExp e = case e of
|
|
Vr x -> [x]
|
|
App f c -> freeVarsExp f ++ freeVarsExp c
|
|
Abs _ x b -> filter (/=x) (freeVarsExp b)
|
|
Prod _ x a b -> freeVarsExp a ++ filter (/=x) (freeVarsExp b)
|
|
_ -> [] --- thus applies to abstract syntax only
|
|
|
|
int2var :: Int -> Ident
|
|
int2var = identS . ('$':) . show
|
|
|
|
meta0 :: MetaId
|
|
meta0 = 0
|
|
|
|
termMeta0 :: Term
|
|
termMeta0 = Meta meta0
|
|
|
|
identVar :: Term -> Err Ident
|
|
identVar (Vr x) = return x
|
|
identVar _ = Bad "not a variable"
|
|
|
|
|
|
-- | light-weight rename for user interaction; also change names of internal vars
|
|
qualifTerm :: Ident -> Term -> Term
|
|
qualifTerm m = qualif [] where
|
|
qualif xs t = case t of
|
|
Abs b x t -> let x' = chV x in Abs b x' $ qualif (x':xs) t
|
|
Prod b x a t -> Prod b x (qualif xs a) $ qualif (x:xs) t
|
|
Vr x -> let x' = chV x in if (elem x' xs) then (Vr x') else (Q (m,x))
|
|
Cn c -> Q (m,c)
|
|
Con c -> QC (m,c)
|
|
_ -> composSafeOp (qualif xs) t
|
|
chV x = string2var $ ident2raw x
|
|
|
|
string2var :: RawIdent -> Ident
|
|
string2var s = case showRawIdent s of
|
|
c:'_':i -> identV (rawIdentS [c]) (readIntArg i) ---
|
|
_ -> identC s
|
|
|
|
-- | reindex variables so that they tell nesting depth level
|
|
reindexTerm :: Term -> Term
|
|
reindexTerm = qualif (0,[]) where
|
|
qualif dg@(d,g) t = case t of
|
|
Abs b x t -> let x' = ind x d in Abs b x' $ qualif (d+1, (x,x'):g) t
|
|
Prod b x a t -> let x' = ind x d in Prod b x' (qualif dg a) $ qualif (d+1, (x,x'):g) t
|
|
Vr x -> Vr $ look x g
|
|
_ -> composSafeOp (qualif dg) t
|
|
look x = maybe x id . lookup x --- if x is not in scope it is unchanged
|
|
ind x d = identC $ ident2raw x `prefixRawIdent` rawIdentS "_" `prefixRawIdent` rawIdentS (show d)
|
|
|
|
{-
|
|
-- this method works for context-free abstract syntax
|
|
-- and is meant to be used in simple embedded GF applications
|
|
|
|
exp2tree :: Exp -> Err Tree
|
|
exp2tree e = do
|
|
(bs,f,xs) <- termForm e
|
|
cont <- case bs of
|
|
[] -> return []
|
|
_ -> prtBad "cannot convert bindings in" e
|
|
at <- case f of
|
|
Q m c -> return $ AtC (m,c)
|
|
QC m c -> return $ AtC (m,c)
|
|
Meta m -> return $ AtM m
|
|
K s -> return $ AtL s
|
|
EInt n -> return $ AtI n
|
|
EFloat n -> return $ AtF n
|
|
_ -> prtBad "cannot convert to atom" f
|
|
ts <- mapM exp2tree xs
|
|
return $ Tr (N (cont,at,uVal,([],[]),True),ts)
|
|
-}
|