Skip to content

Commit b4b9974

Browse files
committed
More comprehensive open term check for builtin eval
1 parent 80de452 commit b4b9974

File tree

2 files changed

+59
-11
lines changed

2 files changed

+59
-11
lines changed

src/compiler/api/GF/Compile/Compute/Concrete.hs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import GF.Grammar.Predef
2626
import GF.Grammar.Lockfield(lockLabel)
2727
import GF.Grammar.Printer
2828
import GF.Data.Operations(Err(..))
29+
import GF.Data.Utilities((<||>),anyM)
2930
import GF.Infra.CheckM
3031
import GF.Infra.Option
3132
import Data.STRef
@@ -142,6 +143,37 @@ showValue (VAlts _ _) = "VAlts"
142143
showValue (VStrs _) = "VStrs"
143144
showValue (VSymCat _ _ _) = "VSymCat"
144145

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
176+
145177
eval env (Vr x) vs = do (tnk,depth) <- lookup x env
146178
withVar depth $ do
147179
v <- force tnk
@@ -208,18 +240,15 @@ eval env (Let (x,(_,t1)) t2) vs = do tnk <- newThunk env t1
208240
eval ((x,tnk):env) t2 vs
209241
eval env (Q q@(m,id)) vs
210242
| m == cPredef = do vs' <- mapM force vs -- FIXME this does not allow for partial application!
211-
if any isVar vs'
212-
then return (VApp q vs)
213-
else do res <- evalPredef id vs'
214-
case res of
215-
Const res -> return res
216-
RunTime -> return (VApp q vs)
217-
NonExist -> return (VApp (cPredef,cNonExist) [])
243+
open <- anyM (value2term True [] >=> isOpen []) vs'
244+
if open then return (VApp q vs) else do
245+
res <- evalPredef id vs'
246+
case res of
247+
Const res -> return res
248+
RunTime -> return (VApp q vs)
249+
NonExist -> return (VApp (cPredef,cNonExist) [])
218250
| otherwise = do t <- getResDef q
219251
eval env t vs
220-
where
221-
isVar (VGen _ _) = True
222-
isVar _ = False
223252
eval env (QC q) vs = return (VApp q vs)
224253
eval env (C t1 t2) [] = do v1 <- eval env t1 []
225254
v2 <- eval env t2 []

src/compiler/api/GF/Data/Utilities.hs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module GF.Data.Utilities(module GF.Data.Utilities) where
1616

1717
import Data.Maybe
1818
import Data.List
19-
import Control.Monad (MonadPlus(..),liftM,when)
19+
import Control.Monad (MonadPlus(..),foldM,liftM,when)
2020
import qualified Data.Set as Set
2121

2222
-- * functions on lists
@@ -140,6 +140,25 @@ whenM bm m = flip when m =<< bm
140140

141141
repeatM m = whenM m (repeatM m)
142142

143+
infixr 3 <&&>
144+
infixr 2 <||>
145+
146+
-- | Boolean conjunction lifted to applicative functors.
147+
(<&&>) :: Applicative f => f Bool -> f Bool -> f Bool
148+
(<&&>) = liftA2 (&&)
149+
150+
-- | Boolean disjunction lifted to applicative functors.
151+
(<||>) :: Applicative f => f Bool -> f Bool -> f Bool
152+
(<||>) = liftA2 (||)
153+
154+
-- | Check whether a monadic predicate holds for every element of a collection.
155+
allM :: (Foldable f, Monad m) => (a -> m Bool) -> f a -> m Bool
156+
allM p = foldM (\b x -> if b then p x else return False) True
157+
158+
-- | Check whether a monadic predicate holds for any element of a collection.
159+
anyM :: (Foldable f, Monad m) => (a -> m Bool) -> f a -> m Bool
160+
anyM p = foldM (\b x -> if b then return True else p x) False
161+
143162
-- * functions on Maybes
144163

145164
-- | Returns true if the argument is Nothing or Just []

0 commit comments

Comments
 (0)