Skip to content

Commit aa3a03e

Browse files
authored
Merge pull request #179 from phantamanta44/majestic
majestic: predef evaluation + option..of construct
2 parents f0b42f4 + b29ec2a commit aa3a03e

File tree

9 files changed

+629
-309
lines changed

9 files changed

+629
-309
lines changed

src/compiler/api/GF/Compile/CheckGrammar.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ checkInfo opts cwd sgr sm (c,info) = checkInModule cwd (snd sm) NoLoc empty $ do
302302
-- | for grammars obtained otherwise than by parsing ---- update!!
303303
checkReservedId :: Ident -> Check ()
304304
checkReservedId x =
305-
when (isReservedWord x) $
305+
when (isReservedWord GF x) $
306306
checkWarn ("reserved word used as identifier:" <+> x)
307307

308308
-- auxiliaries

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

Lines changed: 75 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
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.
55
module 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
2727
import GF.Grammar.Lockfield(lockLabel)
2828
import GF.Grammar.Printer
2929
import GF.Data.Operations(Err(..))
30-
import GF.Data.Utilities(splitAt',(<||>),anyM)
30+
import GF.Data.Utilities(splitAt')
3131
import GF.Infra.CheckM
3232
import GF.Infra.Option
3333
import Data.STRef
@@ -39,6 +39,7 @@ import Control.Monad.ST
3939
import Control.Monad.ST.Unsafe
4040
import Control.Applicative hiding (Const)
4141
import qualified Control.Monad.Fail as Fail
42+
import Data.Functor ((<&>))
4243
import qualified Data.Map as Map
4344
import GF.Text.Pretty
4445
import PGF2.Transactions(LIndex)
@@ -143,36 +144,23 @@ showValue (VAlts _ _) = "VAlts"
143144
showValue (VStrs _) = "VStrs"
144145
showValue (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

177165
eval 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
239227
eval 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
249233
eval 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)
315299
eval 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
316304
eval env t vs = evalError ("Cannot reduce term" <+> pp t)
317305

306+
apply v [] = return v
318307
apply (VMeta m vs0) vs = return (VMeta m (vs0++vs))
319308
apply (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))
321312
apply (VGen i vs0) vs = return (VGen i (vs0++vs))
322313
apply (VClosure env (Abs b x t)) (v:vs) = eval ((x,v):env) t vs
323-
apply v [] = return v
324314

325315

326316
stdPredef :: PredefTable s
327317
stdPredef = 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

775766
type 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 }
777768
type 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

784775
pdForce :: 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

794784
pdArity :: 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

819792
pdStandard :: 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)
884857
evalWarn :: Message -> EvalM s ()
885858
evalWarn 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

893871
getResDef :: QIdent -> EvalM s Term
894872
getResDef q = EvalM $ \(Gl gr _) k e mt d r msgs -> do

0 commit comments

Comments
 (0)