1- {-# LANGUAGE RankNTypes, BangPatterns, CPP, ExistentialQuantification, LambdaCase #-}
1+ {-# LANGUAGE RankNTypes, BangPatterns, CPP, ExistentialQuantification #-}
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
7- , Value (.. ), Thunk , ThunkState (.. ), Env , Scope , showValue
7+ , Value (.. ), Thunk , ThunkState (.. ), Env , Scope , showValue , isCanonicalForm
88 , PredefImpl , Predef (.. ), PredefCombinator , ($\)
9- , pdForce , pdClosedArgs , pdArity , pdStandard
9+ , pdForce , pdCanonicalArgs , pdArity , pdStandard
1010 , MetaThunks , Constraint , PredefTable , Globals (.. ), ConstValue (.. )
1111 , EvalM (.. ), runEvalM , runEvalOneM , reset , try , evalError , evalWarn
1212 , eval , apply , force , value2term , patternMatch , stdPredef
@@ -27,7 +27,7 @@ import GF.Grammar.Predef
2727import GF.Grammar.Lockfield (lockLabel )
2828import GF.Grammar.Printer
2929import GF.Data.Operations (Err (.. ))
30- import GF.Data.Utilities (splitAt' , (<||>) , anyM )
30+ import GF.Data.Utilities (splitAt' )
3131import GF.Infra.CheckM
3232import GF.Infra.Option
3333import Data.STRef
@@ -39,6 +39,7 @@ import Control.Monad.ST
3939import Control.Monad.ST.Unsafe
4040import Control.Applicative hiding (Const )
4141import qualified Control.Monad.Fail as Fail
42+ import Data.Functor ((<&>) )
4243import qualified Data.Map as Map
4344import GF.Text.Pretty
4445import PGF2.Transactions (LIndex )
@@ -143,36 +144,23 @@ showValue (VAlts _ _) = "VAlts"
143144showValue (VStrs _) = " VStrs"
144145showValue (VSymCat _ _ _) = " VSymCat"
145146
146- isOpen :: [Ident ] -> Term -> EvalM s Bool
147- isOpen bound (Vr x) = return $ x `notElem` bound
148- isOpen bound (App f x) = isOpen bound f <||> isOpen bound x
149- isOpen bound (Abs b x t) = isOpen (x: bound) t
150- isOpen bound (ImplArg t) = isOpen bound t
151- isOpen bound (Prod b x d cod) = isOpen bound d <||> isOpen (x: bound) cod
152- isOpen bound (Typed t ty) = isOpen bound t
153- isOpen bound (Example t s) = isOpen bound t
154- isOpen bound (RecType fs) = anyM (isOpen bound . snd ) fs
155- isOpen bound (R fs) = anyM (isOpen bound . snd . snd ) fs
156- isOpen bound (P t f) = isOpen bound t
157- isOpen bound (ExtR t t') = isOpen bound t <||> isOpen bound t'
158- isOpen bound (Table d cod) = isOpen bound d <||> isOpen bound cod
159- isOpen bound (T (TTyped ty) cs) = isOpen bound ty <||> anyM (isOpen bound . snd ) cs
160- isOpen bound (T (TWild ty) cs) = isOpen bound ty <||> anyM (isOpen bound . snd ) cs
161- isOpen bound (T _ cs) = anyM (isOpen bound . snd ) cs
162- isOpen bound (V ty cs) = isOpen bound ty <||> anyM (isOpen bound) cs
163- isOpen bound (S t x) = isOpen bound t <||> isOpen bound x
164- isOpen bound (Let (x,(ty,d)) t) = isOpen bound d <||> isOpen (x: bound) t
165- isOpen bound (C t t') = isOpen bound t <||> isOpen bound t'
166- isOpen bound (Glue t t') = isOpen bound t <||> isOpen bound t'
167- isOpen bound (EPattType ty) = isOpen bound ty
168- isOpen bound (ELincat c ty) = isOpen bound ty
169- isOpen bound (ELin c t) = isOpen bound t
170- isOpen bound (FV ts) = anyM (isOpen bound) ts
171- isOpen bound (Markup tag as ts) = anyM (isOpen bound) ts <||> anyM (isOpen bound . snd ) as
172- isOpen bound (Reset c t) = isOpen bound t
173- isOpen bound (Alts d as) = isOpen bound d <||> anyM (\ (x,y) -> isOpen bound x <||> isOpen bound y) as
174- isOpen bound (Strs ts) = anyM (isOpen bound) ts
175- isOpen _ _ = return False
147+ isCanonicalForm :: Value s -> Bool
148+ isCanonicalForm (VClosure {}) = True
149+ isCanonicalForm (VProd b x d cod) = isCanonicalForm d && isCanonicalForm cod
150+ isCanonicalForm (VRecType fs) = all (isCanonicalForm . snd ) fs
151+ isCanonicalForm (VR {}) = True
152+ isCanonicalForm (VTable d cod) = isCanonicalForm d && isCanonicalForm cod
153+ isCanonicalForm (VT {}) = True
154+ isCanonicalForm (VV {}) = True
155+ isCanonicalForm (VSort {}) = True
156+ isCanonicalForm (VInt {}) = True
157+ isCanonicalForm (VFlt {}) = True
158+ isCanonicalForm (VStr {}) = True
159+ isCanonicalForm VEmpty = True
160+ isCanonicalForm (VAlts d vs) = all (isCanonicalForm . snd ) vs
161+ isCanonicalForm (VStrs vs) = all isCanonicalForm vs
162+ isCanonicalForm (VMarkup tag as vs) = all (isCanonicalForm . snd ) as && all isCanonicalForm vs
163+ isCanonicalForm _ = False
176164
177165eval env (Vr x) vs = do (tnk,depth) <- lookup x env
178166 withVar depth $ do
@@ -238,12 +226,8 @@ eval env (S t1 t2) vs = do v1 <- eval env t1 []
238226 v1 -> return v0
239227eval env (Let (x,(_,t1)) t2) vs = do tnk <- newThunk env t1
240228 eval ((x,tnk): env) t2 vs
241- eval env t@ (Q q@ (m,id )) vs
242- | m == cPredef = do res <- evalPredef env t id vs
243- case res of
244- Const res -> return res
245- RunTime -> return (VApp q vs)
246- NonExist -> return (VApp (cPredef,cNonExist) [] )
229+ eval env (Q q@ (m,id )) vs
230+ | m == cPredef = evalPredef id vs
247231 | otherwise = do t <- getResDef q
248232 eval env t vs
249233eval env (QC q) vs = return (VApp q vs)
@@ -313,39 +297,46 @@ eval env (TSymCat d r rs) []= do rs <- forM rs $ \(i,(pv,ty)) ->
313297 Nothing -> evalError (" Variable" <+> pp pv <+> " is not in scope" )
314298 return (VSymCat d r rs)
315299eval env (TSymVar d r) [] = do return (VSymVar d r)
300+ eval env t@ (Opts n cs) vs = EvalM $ \ gr k e mt b r msgs ->
301+ case cs of
302+ [] -> return $ Fail (" No options in expression:" $$ ppTerm Unqualified 0 t) msgs
303+ ((l,t): _) -> case eval env t vs of EvalM f -> f gr k e mt b r msgs
316304eval env t vs = evalError (" Cannot reduce term" <+> pp t)
317305
306+ apply v [] = return v
318307apply (VMeta m vs0) vs = return (VMeta m (vs0++ vs))
319308apply (VSusp m k vs0) vs = return (VSusp m k (vs0++ vs))
320- apply (VApp f vs0) vs = return (VApp f (vs0++ vs))
309+ apply (VApp f@ (m,p) vs0) vs
310+ | m == cPredef = evalPredef p (vs0++ vs)
311+ | otherwise = return (VApp f (vs0++ vs))
321312apply (VGen i vs0) vs = return (VGen i (vs0++ vs))
322313apply (VClosure env (Abs b x t)) (v: vs) = eval ((x,v): env) t vs
323- apply v [] = return v
324314
325315
326316stdPredef :: PredefTable s
327317stdPredef = Map. fromList
328- [(cLength, pdStandard 1 $\ \ [v] -> case value2string v of
329- Const s -> return (Const (VInt (genericLength s)))
330- _ -> return RunTime )
331- ,(cTake, pdStandard 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericTake (value2int v1) (value2string v2))))
332- ,(cDrop, pdStandard 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericDrop (value2int v1) (value2string v2))))
333- ,(cTk, pdStandard 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericTk (value2int v1) (value2string v2))))
334- ,(cDp, pdStandard 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericDp (value2int v1) (value2string v2))))
335- ,(cIsUpper,pdStandard 1 $\ \ [v] -> return (fmap toPBool (liftA (all isUpper) (value2string v))))
336- ,(cToUpper,pdStandard 1 $\ \ [v] -> return (fmap string2value (liftA (map toUpper) (value2string v))))
337- ,(cToLower,pdStandard 1 $\ \ [v] -> return (fmap string2value (liftA (map toLower) (value2string v))))
338- ,(cEqStr, pdStandard 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 (==) (value2string v1) (value2string v2))))
339- ,(cOccur, pdStandard 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 occur (value2string v1) (value2string v2))))
340- ,(cOccurs, pdStandard 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 occurs (value2string v1) (value2string v2))))
341- ,(cEqInt, pdStandard 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 (==) (value2int v1) (value2int v2))))
342- ,(cLessInt,pdStandard 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 (<) (value2int v1) (value2int v2))))
343- ,(cPlus, pdStandard 2 $\ \ [v1,v2] -> return (fmap VInt (liftA2 (+) (value2int v1) (value2int v2))))
344- ,(cError, pdStandard 1 $\ \ [v] -> case value2string v of
345- Const msg -> fail msg
346- _ -> fail " Indescribable error appeared" )
318+ [(cLength, pd 1 $\ \ [v] -> case value2string v of
319+ Const s -> return (Const (VInt (genericLength s)))
320+ _ -> return RunTime )
321+ ,(cTake, pd 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericTake (value2int v1) (value2string v2))))
322+ ,(cDrop, pd 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericDrop (value2int v1) (value2string v2))))
323+ ,(cTk, pd 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericTk (value2int v1) (value2string v2))))
324+ ,(cDp, pd 2 $\ \ [v1,v2] -> return (fmap string2value (liftA2 genericDp (value2int v1) (value2string v2))))
325+ ,(cIsUpper,pd 1 $\ \ [v] -> return (fmap toPBool (liftA (all isUpper) (value2string v))))
326+ ,(cToUpper,pd 1 $\ \ [v] -> return (fmap string2value (liftA (map toUpper) (value2string v))))
327+ ,(cToLower,pd 1 $\ \ [v] -> return (fmap string2value (liftA (map toLower) (value2string v))))
328+ ,(cEqStr, pd 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 (==) (value2string v1) (value2string v2))))
329+ ,(cOccur, pd 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 occur (value2string v1) (value2string v2))))
330+ ,(cOccurs, pd 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 occurs (value2string v1) (value2string v2))))
331+ ,(cEqInt, pd 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 (==) (value2int v1) (value2int v2))))
332+ ,(cLessInt,pd 2 $\ \ [v1,v2] -> return (fmap toPBool (liftA2 (<) (value2int v1) (value2int v2))))
333+ ,(cPlus, pd 2 $\ \ [v1,v2] -> return (fmap VInt (liftA2 (+) (value2int v1) (value2int v2))))
334+ ,(cError, pd 1 $\ \ [v] -> case value2string v of
335+ Const msg -> fail msg
336+ _ -> fail " Indescribable error appeared" )
347337 ]
348338 where
339+ pd n = pdArity n . pdForce
349340 genericTk n = reverse . genericDrop n . reverse
350341 genericDp n = reverse . genericTake n . reverse
351342
@@ -773,51 +764,33 @@ value2int _ = RunTime
773764-- * Global/built-in definitions
774765
775766type PredefImpl a s = [a ] -> EvalM s (ConstValue (Value s ))
776- newtype Predef a s = Predef { runPredef :: Term -> Env s -> PredefImpl a s }
767+ newtype Predef a s = Predef { runPredef :: PredefImpl a s }
777768type PredefCombinator a b s = Predef a s -> Predef b s
778769
779- infix 0 $\\
770+ infix 1 $\\
780771
781772($\) :: PredefCombinator a b s -> PredefImpl a s -> Predef b s
782- k $\ f = k (Predef ( \ _ _ -> f) )
773+ k $\ f = k (Predef f )
783774
784775pdForce :: PredefCombinator (Value s ) (Thunk s ) s
785- pdForce def = Predef $ \ h env args -> do
776+ pdForce def = Predef $ \ args -> do
786777 argValues <- mapM force args
787- runPredef def h env argValues
778+ runPredef def argValues
788779
789- pdClosedArgs :: PredefCombinator (Value s ) (Value s ) s
790- pdClosedArgs def = Predef $ \ h env args -> do
791- open <- anyM (value2term True [] >=> isOpen [] ) args
792- if open then return RunTime else runPredef def h env args
780+ pdCanonicalArgs :: PredefCombinator (Value s ) (Value s ) s
781+ pdCanonicalArgs def = Predef $ \ args ->
782+ if all isCanonicalForm args then runPredef def args else return RunTime
793783
794784pdArity :: Int -> PredefCombinator (Thunk s ) (Thunk s ) s
795- pdArity n def = Predef $ \ h env args ->
785+ pdArity n def = Predef $ \ args ->
796786 case splitAt' n args of
797- Nothing -> do
798- t <- papply env h args
799- let t' = abstract 0 (n - length args) t
800- Const <$> eval env t' []
787+ Nothing -> return RunTime
801788 Just (usedArgs, remArgs) -> do
802- res <- runPredef def h env usedArgs
803- forM res $ \ v -> case remArgs of
804- [] -> return v
805- _ -> do
806- t <- value2term False (fst <$> env) v
807- eval env t remArgs
808- where
809- papply env t [] = return t
810- papply env t (arg: args) = do
811- arg <- tnk2term False (fst <$> env) arg
812- papply env (App t arg) args
813-
814- abstract i n t
815- | n <= 0 = t
816- | otherwise = let x = identV (rawIdentS " a" ) i
817- in Abs Explicit x (abstract (i + 1 ) (n - 1 ) (App t (Vr x)))
789+ res <- runPredef def usedArgs
790+ forM res $ \ v -> apply v remArgs
818791
819792pdStandard :: Int -> PredefCombinator (Value s ) (Thunk s ) s
820- pdStandard n = pdArity n . pdForce . pdClosedArgs
793+ pdStandard n = pdArity n . pdForce . pdCanonicalArgs
821794
822795-----------------------------------------------------------------------
823796-- * Evaluation monad
@@ -884,11 +857,16 @@ evalError msg = EvalM (\gr k e _ _ r ws -> e msg ws)
884857evalWarn :: Message -> EvalM s ()
885858evalWarn msg = EvalM (\ gr k e mt d r msgs -> k () mt d r (msg: msgs))
886859
887- evalPredef :: Env s -> Term -> Ident -> [Thunk s ] -> EvalM s (ConstValue (Value s ))
888- evalPredef env h id args = EvalM (\ globals@ (Gl _ predef) k e mt d r msgs ->
889- case fmap (\ def -> runPredef def h env args) (Map. lookup id predef) of
890- Just (EvalM f) -> f globals k e mt d r msgs
891- Nothing -> k RunTime mt d r msgs)
860+ evalPredef :: Ident -> [Thunk s ] -> EvalM s (Value s )
861+ evalPredef id args = do
862+ res <- EvalM $ \ globals@ (Gl _ predef) k e mt d r msgs ->
863+ case Map. lookup id predef <&> \ def -> runPredef def args of
864+ Just (EvalM f) -> f globals k e mt d r msgs
865+ Nothing -> k RunTime mt d r msgs
866+ case res of
867+ Const res -> return res
868+ RunTime -> return $ VApp (cPredef,id ) args
869+ NonExist -> return $ VApp (cPredef,cNonExist) []
892870
893871getResDef :: QIdent -> EvalM s Term
894872getResDef q = EvalM $ \ (Gl gr _) k e mt d r msgs -> do
0 commit comments