1- {-# LANGUAGE RankNTypes, BangPatterns, CPP, ExistentialQuantification #-}
1+ {-# LANGUAGE RankNTypes, BangPatterns, CPP, ExistentialQuantification, LambdaCase #-}
22
33-- | Functions for computing the values of terms in the concrete syntax, in
44-- | preparation for PMCFG generation.
55module GF.Compile.Compute.Concrete
66 ( normalForm , normalFlatForm , normalStringForm
77 , Value (.. ), Thunk , ThunkState (.. ), Env , Scope , showValue
8- , MetaThunks , Constraint , Globals (.. ), ConstValue (.. )
8+ , PredefImpl , Predef (.. ), PredefCombinator , ($\)
9+ , pdForce , pdClosedArgs , pdArity , pdStandard
10+ , MetaThunks , Constraint , PredefTable , Globals (.. ), ConstValue (.. )
911 , EvalM (.. ), runEvalM , runEvalOneM , reset , evalError , evalWarn
1012 , eval , apply , force , value2term , patternMatch , stdPredef
1113 , unsafeIOToEvalM
@@ -26,6 +28,7 @@ import GF.Grammar.Predef
2628import GF.Grammar.Lockfield (lockLabel )
2729import GF.Grammar.Printer
2830import GF.Data.Operations (Err (.. ))
31+ import GF.Data.Utilities (splitAt' ,(<||>) ,anyM )
2932import GF.Infra.CheckM
3033import GF.Infra.Option
3134import Data.STRef
@@ -142,6 +145,37 @@ showValue (VAlts _ _) = "VAlts"
142145showValue (VStrs _) = " VStrs"
143146showValue (VSymCat _ _ _) = " VSymCat"
144147
148+ isOpen :: [Ident ] -> Term -> EvalM s Bool
149+ isOpen bound (Vr x) = return $ x `notElem` bound
150+ isOpen bound (App f x) = isOpen bound f <||> isOpen bound x
151+ isOpen bound (Abs b x t) = isOpen (x: bound) t
152+ isOpen bound (ImplArg t) = isOpen bound t
153+ isOpen bound (Prod b x d cod) = isOpen bound d <||> isOpen (x: bound) cod
154+ isOpen bound (Typed t ty) = isOpen bound t
155+ isOpen bound (Example t s) = isOpen bound t
156+ isOpen bound (RecType fs) = anyM (isOpen bound . snd ) fs
157+ isOpen bound (R fs) = anyM (isOpen bound . snd . snd ) fs
158+ isOpen bound (P t f) = isOpen bound t
159+ isOpen bound (ExtR t t') = isOpen bound t <||> isOpen bound t'
160+ isOpen bound (Table d cod) = isOpen bound d <||> isOpen bound cod
161+ isOpen bound (T (TTyped ty) cs) = isOpen bound ty <||> anyM (isOpen bound . snd ) cs
162+ isOpen bound (T (TWild ty) cs) = isOpen bound ty <||> anyM (isOpen bound . snd ) cs
163+ isOpen bound (T _ cs) = anyM (isOpen bound . snd ) cs
164+ isOpen bound (V ty cs) = isOpen bound ty <||> anyM (isOpen bound) cs
165+ isOpen bound (S t x) = isOpen bound t <||> isOpen bound x
166+ isOpen bound (Let (x,(ty,d)) t) = isOpen bound d <||> isOpen (x: bound) t
167+ isOpen bound (C t t') = isOpen bound t <||> isOpen bound t'
168+ isOpen bound (Glue t t') = isOpen bound t <||> isOpen bound t'
169+ isOpen bound (EPattType ty) = isOpen bound ty
170+ isOpen bound (ELincat c ty) = isOpen bound ty
171+ isOpen bound (ELin c t) = isOpen bound t
172+ isOpen bound (FV ts) = anyM (isOpen bound) ts
173+ isOpen bound (Markup tag as ts) = anyM (isOpen bound) ts <||> anyM (isOpen bound . snd ) as
174+ isOpen bound (Reset c t) = isOpen bound t
175+ isOpen bound (Alts d as) = isOpen bound d <||> anyM (\ (x,y) -> isOpen bound x <||> isOpen bound y) as
176+ isOpen bound (Strs ts) = anyM (isOpen bound) ts
177+ isOpen _ _ = return False
178+
145179eval env (Vr x) vs = do (tnk,depth) <- lookup x env
146180 withVar depth $ do
147181 v <- force tnk
@@ -206,9 +240,8 @@ eval env (S t1 t2) vs = do v1 <- eval env t1 []
206240 v1 -> return v0
207241eval env (Let (x,(_,t1)) t2) vs = do tnk <- newThunk env t1
208242 eval ((x,tnk): env) t2 vs
209- eval env (Q q@ (m,id )) vs
210- | m == cPredef = do vs' <- mapM force vs
211- res <- evalPredef id vs'
243+ eval env t@ (Q q@ (m,id )) vs
244+ | m == cPredef = do res <- evalPredef env t id vs
212245 case res of
213246 Const res -> return res
214247 RunTime -> return (VApp q vs)
@@ -292,25 +325,25 @@ apply (VClosure env (Abs b x t)) (v:vs) = eval ((x,v):env) t vs
292325apply v [] = return v
293326
294327
295- stdPredef :: Map. Map Ident ([ Value s ] -> EvalM s ( ConstValue ( Value s )))
328+ stdPredef :: PredefTable s
296329stdPredef = Map. fromList
297- [(cLength, \ [v] -> case value2string v of
298- Const s -> return (Const (VInt (genericLength s)))
299- _ -> return RunTime )
300- ,(cTake, \ [v1,v2] -> return (fmap string2value (liftA2 genericTake (value2int v1) (value2string v2))))
301- ,(cDrop, \ [v1,v2] -> return (fmap string2value (liftA2 genericDrop (value2int v1) (value2string v2))))
302- ,(cTk, \ [v1,v2] -> return (fmap string2value (liftA2 genericTk (value2int v1) (value2string v2))))
303- ,(cDp, \ [v1,v2] -> return (fmap string2value (liftA2 genericDp (value2int v1) (value2string v2))))
304- ,(cIsUpper,\ [v] -> return (fmap toPBool (liftA (all isUpper) (value2string v))))
305- ,(cToUpper,\ [v] -> return (fmap string2value (liftA (map toUpper) (value2string v))))
306- ,(cToLower,\ [v] -> return (fmap string2value (liftA (map toLower) (value2string v))))
307- ,(cEqStr, \ [v1,v2] -> return (fmap toPBool (liftA2 (==) (value2string v1) (value2string v2))))
308- ,(cOccur, \ [v1,v2] -> return (fmap toPBool (liftA2 occur (value2string v1) (value2string v2))))
309- ,(cOccurs, \ [v1,v2] -> return (fmap toPBool (liftA2 occurs (value2string v1) (value2string v2))))
310- ,(cEqInt, \ [v1,v2] -> return (fmap toPBool (liftA2 (==) (value2int v1) (value2int v2))))
311- ,(cLessInt,\ [v1,v2] -> return (fmap toPBool (liftA2 (<) (value2int v1) (value2int v2))))
312- ,(cPlus, \ [v1,v2] -> return (fmap VInt (liftA2 (+) (value2int v1) (value2int v2))))
313- ,(cError, \ [v] -> case value2string v of
330+ [(cLength, pdStandard 1 $\ \ [v] -> case value2string v of
331+ Const s -> return (Const (VInt (genericLength s)))
332+ _ -> return RunTime )
333+ ,(cTake, pdStandard 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericTake (value2int v1) (value2string v2))))
334+ ,(cDrop, pdStandard 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericDrop (value2int v1) (value2string v2))))
335+ ,(cTk, pdStandard 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericTk (value2int v1) (value2string v2))))
336+ ,(cDp, pdStandard 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericDp (value2int v1) (value2string v2))))
337+ ,(cIsUpper,pdStandard 1 $\ \ [v] -> return (fmap toPBool (liftA (all isUpper) (value2string v))))
338+ ,(cToUpper,pdStandard 1 $\ \ [v] -> return (fmap string2value (liftA (map toUpper) (value2string v))))
339+ ,(cToLower,pdStandard 1 $\ \ [v] -> return (fmap string2value (liftA (map toLower) (value2string v))))
340+ ,(cEqStr, pdStandard 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 (==) (value2string v1) (value2string v2))))
341+ ,(cOccur, pdStandard 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 occur (value2string v1) (value2string v2))))
342+ ,(cOccurs, pdStandard 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 occurs (value2string v1) (value2string v2))))
343+ ,(cEqInt, pdStandard 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 (==) (value2int v1) (value2int v2))))
344+ ,(cLessInt,pdStandard 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 (<) (value2int v1) (value2int v2))))
345+ ,(cPlus, pdStandard 2 $\ \ [v1,v2] -> return (fmap VInt (liftA2 (+) (value2int v1) (value2int v2))))
346+ ,(cError, pdStandard 1 $\ \ [v] -> case value2string v of
314347 Const msg -> fail msg
315348 _ -> fail " Indescribable error appeared" )
316349 ]
@@ -671,6 +704,16 @@ instance Applicative ConstValue where
671704 liftA2 f _ RunTime = RunTime
672705#endif
673706
707+ instance Foldable ConstValue where
708+ foldr f a (Const x) = f x a
709+ foldr f a RunTime = a
710+ foldr f a NonExist = a
711+
712+ instance Traversable ConstValue where
713+ traverse f (Const x) = Const <$> f x
714+ traverse f RunTime = pure RunTime
715+ traverse f NonExist = pure NonExist
716+
674717value2string v = fmap (\ (_,ws,_) -> unwords ws) (value2string' v False [] [] )
675718
676719value2string' (VStr w1) True (w2: ws) qs = Const (False ,(w1++ w2): ws,qs)
@@ -728,12 +771,63 @@ string2value' (w:ws) = VC (VStr w) (string2value' ws)
728771value2int (VInt n) = Const n
729772value2int _ = RunTime
730773
774+ -----------------------------------------------------------------------
775+ -- * Global/built-in definitions
776+
777+ type PredefImpl a s = [a ] -> EvalM s (ConstValue (Value s ))
778+ newtype Predef a s = Predef { runPredef :: Term -> Env s -> PredefImpl a s }
779+ type PredefCombinator a b s = Predef a s -> Predef b s
780+
781+ infix 0 $\\
782+
783+ ($\) :: PredefCombinator a b s -> PredefImpl a s -> Predef b s
784+ k $\ f = k (Predef (\ _ _ -> f))
785+
786+ pdForce :: PredefCombinator (Value s ) (Thunk s ) s
787+ pdForce def = Predef $ \ h env args -> do
788+ argValues <- mapM force args
789+ runPredef def h env argValues
790+
791+ pdClosedArgs :: PredefCombinator (Value s ) (Value s ) s
792+ pdClosedArgs def = Predef $ \ h env args -> do
793+ open <- anyM (value2term True [] >=> isOpen [] ) args
794+ if open then return RunTime else runPredef def h env args
795+
796+ pdArity :: Int -> PredefCombinator (Thunk s ) (Thunk s ) s
797+ pdArity n def = Predef $ \ h env args ->
798+ case splitAt' n args of
799+ Nothing -> do
800+ t <- papply env h args
801+ let t' = abstract 0 (n - length args) t
802+ Const <$> eval env t' []
803+ Just (usedArgs, remArgs) -> do
804+ res <- runPredef def h env usedArgs
805+ forM res $ \ v -> case remArgs of
806+ [] -> return v
807+ _ -> do
808+ t <- value2term False (fst <$> env) v
809+ eval env t remArgs
810+ where
811+ papply env t [] = return t
812+ papply env t (arg: args) = do
813+ arg <- tnk2term False (fst <$> env) arg
814+ papply env (App t arg) args
815+
816+ abstract i n t
817+ | n <= 0 = t
818+ | otherwise = let x = identV (rawIdentS " a" ) i
819+ in Abs Explicit x (abstract (i + 1 ) (n - 1 ) (App t (Vr x)))
820+
821+ pdStandard :: Int -> PredefCombinator (Value s ) (Thunk s ) s
822+ pdStandard n = pdArity n . pdForce . pdClosedArgs
823+
731824-----------------------------------------------------------------------
732825-- * Evaluation monad
733826
734827type MetaThunks s = Map. Map MetaId (Thunk s )
735828type Cont s r = MetaThunks s -> Int -> r -> [Message ] -> ST s (CheckResult r [Message ])
736- data Globals = Gl Grammar (forall s . Map. Map Ident ([Value s ] -> EvalM s (ConstValue (Value s ))))
829+ type PredefTable s = Map. Map Ident (Predef (Thunk s ) s )
830+ data Globals = Gl Grammar (forall s . PredefTable s )
737831newtype EvalM s a = EvalM (forall r . Globals -> (a -> Cont s r ) -> Cont s r )
738832
739833instance Functor (EvalM s ) where
@@ -792,9 +886,9 @@ evalError msg = EvalM (\gr k _ _ r msgs -> return (Fail msg msgs))
792886evalWarn :: Message -> EvalM s ()
793887evalWarn msg = EvalM (\ gr k mt d r msgs -> k () mt d r (msg: msgs))
794888
795- evalPredef :: Ident -> [Value s ] -> EvalM s (ConstValue (Value s ))
796- evalPredef id vs = EvalM (\ globals@ (Gl _ predef) k mt d r msgs ->
797- case fmap (\ f -> f vs ) (Map. lookup id predef) of
889+ evalPredef :: Env s -> Term -> Ident -> [Thunk s ] -> EvalM s (ConstValue (Value s ))
890+ evalPredef env h id args = EvalM (\ globals@ (Gl _ predef) k mt d r msgs ->
891+ case fmap (\ def -> runPredef def h env args ) (Map. lookup id predef) of
798892 Just (EvalM f) -> f globals k mt d r msgs
799893 Nothing -> k RunTime mt d r msgs)
800894
0 commit comments