mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-24 03:52:50 -06:00
partial support for runtime parameters
This commit is contained in:
@@ -8,7 +8,7 @@ module GF.Compile.Compute.Concrete
|
|||||||
, EvalM, runEvalM, evalError
|
, EvalM, runEvalM, evalError
|
||||||
, eval, apply, force, value2term
|
, eval, apply, force, value2term
|
||||||
, newMeta,getMeta,setMeta
|
, newMeta,getMeta,setMeta
|
||||||
, newEvaluatedThunk,getAllParamValues
|
, newThunk,newEvaluatedThunk,getAllParamValues
|
||||||
, lookupParams
|
, lookupParams
|
||||||
) where
|
) where
|
||||||
|
|
||||||
@@ -34,6 +34,7 @@ import Control.Applicative
|
|||||||
import qualified Control.Monad.Fail as Fail
|
import qualified Control.Monad.Fail as Fail
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import GF.Text.Pretty
|
import GF.Text.Pretty
|
||||||
|
import PGF2.Transactions(LIndex)
|
||||||
|
|
||||||
-- * Main entry points
|
-- * Main entry points
|
||||||
|
|
||||||
@@ -78,8 +79,9 @@ data Value s
|
|||||||
| VPattType (Value s)
|
| VPattType (Value s)
|
||||||
| VAlts (Value s) [(Value s, Value s)]
|
| VAlts (Value s) [(Value s, Value s)]
|
||||||
| VStrs [Value s]
|
| VStrs [Value s]
|
||||||
| VSymCat Int Int -- This is only generated internally in
|
-- This last constructor is only generated internally
|
||||||
-- the PMCFG generator.
|
-- in the PMCFG generator.
|
||||||
|
| VSymCat Int LIndex [(LIndex, Thunk s)]
|
||||||
|
|
||||||
|
|
||||||
eval env (Vr x) vs = case lookup x env of
|
eval env (Vr x) vs = case lookup x env of
|
||||||
@@ -181,6 +183,11 @@ eval env (Alts d as) [] = do vd <- eval env d []
|
|||||||
return (VAlts vd vas)
|
return (VAlts vd vas)
|
||||||
eval env (Strs ts) [] = do vs <- mapM (\t -> eval env t []) ts
|
eval env (Strs ts) [] = do vs <- mapM (\t -> eval env t []) ts
|
||||||
return (VStrs vs)
|
return (VStrs vs)
|
||||||
|
eval env (TSymCat d r rs) []= do rs <- forM rs $ \(i,pv) ->
|
||||||
|
case lookup pv env of
|
||||||
|
Just tnk -> return (i,tnk)
|
||||||
|
Nothing -> evalError ("Variable" <+> pp pv <+> "is not in scope")
|
||||||
|
return (VSymCat d r rs)
|
||||||
eval env t vs = evalError ("Cannot reduce term" <+> pp t)
|
eval env t vs = evalError ("Cannot reduce term" <+> pp t)
|
||||||
|
|
||||||
apply (VMeta m env vs0) vs = do st <- getMeta m
|
apply (VMeta m env vs0) vs = do st <- getMeta m
|
||||||
|
|||||||
@@ -15,13 +15,17 @@ module GF.Compile.GeneratePMCFG
|
|||||||
|
|
||||||
import GF.Grammar hiding (VApp)
|
import GF.Grammar hiding (VApp)
|
||||||
import GF.Grammar.Predef
|
import GF.Grammar.Predef
|
||||||
|
import GF.Grammar.Lookup
|
||||||
import GF.Infra.CheckM
|
import GF.Infra.CheckM
|
||||||
import GF.Infra.Option
|
import GF.Infra.Option
|
||||||
import GF.Text.Pretty
|
import GF.Text.Pretty
|
||||||
import GF.Compile.Compute.Concrete
|
import GF.Compile.Compute.Concrete
|
||||||
|
import GF.Data.Operations(Err(..))
|
||||||
import PGF2.Transactions
|
import PGF2.Transactions
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
|
import Data.List(mapAccumL)
|
||||||
|
import Debug.Trace
|
||||||
|
|
||||||
generatePMCFG :: Options -> FilePath -> SourceGrammar -> SourceModule -> Check SourceModule
|
generatePMCFG :: Options -> FilePath -> SourceGrammar -> SourceModule -> Check SourceModule
|
||||||
generatePMCFG opts cwd gr cmo@(cm,cmi) = do
|
generatePMCFG opts cwd gr cmo@(cm,cmi) = do
|
||||||
@@ -38,35 +42,40 @@ addPMCFG opts cwd gr cmi id_info = return id_info
|
|||||||
pmcfgForm :: Grammar -> L Ident -> Term -> Context -> Check [[[Symbol]]]
|
pmcfgForm :: Grammar -> L Ident -> Term -> Context -> Check [[[Symbol]]]
|
||||||
pmcfgForm gr _ t ctxt =
|
pmcfgForm gr _ t ctxt =
|
||||||
runEvalM gr $ do
|
runEvalM gr $ do
|
||||||
(_,args) <- mapAccumM (\(d,r) (_,_,ty) -> do (r,v) <- type2metaValue d r ty
|
((_,ms),args) <- mapAccumM (\(d,ms) (_,_,ty) -> do
|
||||||
return ((d+1,r),v))
|
let (ms',_,t) = type2metaTerm gr d ms 0 [] ty
|
||||||
(0,0) ctxt
|
tnk <- trace (show (ppTerm Unqualified 0 t)) $ newThunk [] t
|
||||||
|
return ((d+1,ms'),tnk))
|
||||||
|
(0,Map.empty) ctxt
|
||||||
|
sequence_ [newMeta (Just ty) i | (i,ty) <- Map.toList ms]
|
||||||
v <- eval [] t args
|
v <- eval [] t args
|
||||||
(lins,_) <- value2pmcfg v []
|
(lins,_) <- value2pmcfg v []
|
||||||
return (reverse lins)
|
return (reverse lins)
|
||||||
|
|
||||||
type2metaValue :: Int -> Int -> Type -> EvalM s (Int,Thunk s)
|
type2metaTerm :: SourceGrammar -> Int -> Map.Map MetaId Type -> LIndex -> [(LIndex,Ident)] -> Type -> (Map.Map MetaId Type,Int,Term)
|
||||||
type2metaValue d r (Sort s) | s == cStr = do
|
type2metaTerm gr d ms r rs (Sort s) | s == cStr =
|
||||||
tnk <- newEvaluatedThunk (VSymCat d r)
|
(ms,r+1,TSymCat d r rs)
|
||||||
return (r+1,tnk)
|
type2metaTerm gr d ms r rs (RecType lbls) =
|
||||||
type2metaValue d r (RecType lbls) = do
|
let ((ms',r'),ass) = mapAccumL (\(ms,r) (lbl,ty) -> let (ms',r',t) = type2metaTerm gr d ms r rs ty
|
||||||
(r,lbls) <- mapAccumM (\i (lbl,ty) -> do (i,tnk) <- type2metaValue d i ty
|
in ((ms',r'),(lbl,(Just ty,t))))
|
||||||
return (i,(lbl,tnk)))
|
(ms,r) lbls
|
||||||
r lbls
|
in (ms',r',R ass)
|
||||||
tnk <- newEvaluatedThunk (VR lbls)
|
type2metaTerm gr d ms r rs (Table p q) =
|
||||||
return (r,tnk)
|
let pv = identS ('p':show (length rs))
|
||||||
type2metaValue d r (Table p q) = do
|
(ms',r',t) = type2metaTerm gr d ms r ((r'-r,pv):rs) q
|
||||||
ts <- getAllParamValues p
|
count = case allParamValues gr p of
|
||||||
(r,vs) <- mapAccumM (\r _ -> type2metaValue d r q) r ts
|
Ok ts -> length ts
|
||||||
tnk <- newEvaluatedThunk (VV p vs)
|
Bad msg -> error msg
|
||||||
return (r, tnk)
|
in (ms',(r'-r)*count,T (TTyped p) [(PV pv,t)])
|
||||||
type2metaValue d r ty@(QC q) = do
|
type2metaTerm gr d ms r rs ty@(QC q) =
|
||||||
tnk <- newMeta (Just ty) 0
|
let i = Map.size ms + 1
|
||||||
return (r, tnk)
|
in (Map.insert i ty ms,r,Meta i)
|
||||||
|
|
||||||
value2pmcfg (VSusp tnk env vs k) lins = do
|
value2pmcfg (VSusp tnk env vs k) lins = do
|
||||||
st <- getMeta tnk
|
st <- getMeta tnk
|
||||||
case st of
|
case st of
|
||||||
|
Unevaluated _ t -> do v <- eval env t vs
|
||||||
|
value2pmcfg v lins
|
||||||
Evaluated v -> do v <- apply v vs
|
Evaluated v -> do v <- apply v vs
|
||||||
value2pmcfg v lins
|
value2pmcfg v lins
|
||||||
Unbound (Just (QC q)) _ -> do (m,ps) <- lookupParams q
|
Unbound (Just (QC q)) _ -> do (m,ps) <- lookupParams q
|
||||||
@@ -92,16 +101,22 @@ value2pmcfg (VR as) lins = do
|
|||||||
tnk <- newEvaluatedThunk v
|
tnk <- newEvaluatedThunk v
|
||||||
return (lins,(lbl,tnk):as)
|
return (lins,(lbl,tnk):as)
|
||||||
value2pmcfg v lins = do
|
value2pmcfg v lins = do
|
||||||
case value2lin v of
|
lin <- value2lin v
|
||||||
Just lin -> return (lin:lins,VR [])
|
return (lin:lins,VR [])
|
||||||
Nothing -> do t <- value2term 0 v
|
|
||||||
evalError ("the term" <+> ppTerm Unqualified 0 t $$
|
|
||||||
"cannot be evaluated at compile time.")
|
|
||||||
|
|
||||||
value2lin (VStr s) = Just [SymKS s]
|
value2lin (VStr s) = return [SymKS s]
|
||||||
value2lin (VSymCat d r) = Just [SymCat d r]
|
value2lin (VSymCat d r rs) = do rs <- forM rs $ \(i,tnk) -> do
|
||||||
value2lin (VC vs) = fmap concat (mapM value2lin vs)
|
v <- force tnk []
|
||||||
value2lin _ = Nothing
|
j <- case v of
|
||||||
|
VMeta tnk _ _ -> do st <- getMeta tnk
|
||||||
|
case st of
|
||||||
|
Unbound _ j -> return j
|
||||||
|
return (i,j)
|
||||||
|
return [SymCat d r rs]
|
||||||
|
value2lin (VC vs) = fmap concat (mapM value2lin vs)
|
||||||
|
value2lin v = do t <- value2term 0 v
|
||||||
|
evalError ("the term" <+> ppTerm Unqualified 0 t $$
|
||||||
|
"cannot be evaluated at compile time.")
|
||||||
|
|
||||||
mapAccumM f a [] = return (a,[])
|
mapAccumM f a [] = return (a,[])
|
||||||
mapAccumM f a (x:xs) = do (a, y) <- f a x
|
mapAccumM f a (x:xs) = do (a, y) <- f a x
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ instance Binary Literal where
|
|||||||
_ -> decodingError
|
_ -> decodingError
|
||||||
|
|
||||||
instance Binary Symbol where
|
instance Binary Symbol where
|
||||||
put (SymCat n l) = putWord8 0 >> put (n,l)
|
put (SymCat d r rs) = putWord8 0 >> put (d,r,rs)
|
||||||
put (SymLit n l) = putWord8 1 >> put (n,l)
|
put (SymLit n l) = putWord8 1 >> put (n,l)
|
||||||
put (SymVar n l) = putWord8 2 >> put (n,l)
|
put (SymVar n l) = putWord8 2 >> put (n,l)
|
||||||
put (SymKS ts) = putWord8 3 >> put ts
|
put (SymKS ts) = putWord8 3 >> put ts
|
||||||
@@ -321,7 +321,7 @@ instance Binary Symbol where
|
|||||||
put SymALL_CAPIT = putWord8 10
|
put SymALL_CAPIT = putWord8 10
|
||||||
get = do tag <- getWord8
|
get = do tag <- getWord8
|
||||||
case tag of
|
case tag of
|
||||||
0 -> liftM2 SymCat get get
|
0 -> liftM3 SymCat get get get
|
||||||
1 -> liftM2 SymLit get get
|
1 -> liftM2 SymLit get get
|
||||||
2 -> liftM2 SymVar get get
|
2 -> liftM2 SymVar get get
|
||||||
3 -> liftM SymKS get
|
3 -> liftM SymKS get
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ import GF.Infra.Location
|
|||||||
import GF.Data.Operations
|
import GF.Data.Operations
|
||||||
|
|
||||||
import PGF2(BindType(..))
|
import PGF2(BindType(..))
|
||||||
import PGF2.Transactions(Symbol)
|
import PGF2.Transactions(Symbol,LIndex)
|
||||||
|
|
||||||
import Data.Array.IArray(Array)
|
import Data.Array.IArray(Array)
|
||||||
import Data.Array.Unboxed(UArray)
|
import Data.Array.Unboxed(UArray)
|
||||||
@@ -391,6 +391,7 @@ data Term =
|
|||||||
|
|
||||||
| Alts Term [(Term, Term)] -- ^ alternatives by prefix: @pre {t ; s\/c ; ...}@
|
| Alts Term [(Term, Term)] -- ^ alternatives by prefix: @pre {t ; s\/c ; ...}@
|
||||||
| Strs [Term] -- ^ conditioning prefix strings: @strs {s ; ...}@
|
| Strs [Term] -- ^ conditioning prefix strings: @strs {s ; ...}@
|
||||||
|
| TSymCat Int LIndex [(LIndex,Ident)]
|
||||||
deriving (Show, Eq, Ord)
|
deriving (Show, Eq, Ord)
|
||||||
|
|
||||||
-- | Patterns
|
-- | Patterns
|
||||||
|
|||||||
@@ -234,6 +234,7 @@ ppTerm q d (Typed e t) = '<' <> ppTerm q 0 e <+> ':' <+> ppTerm q 0 t <> '>'
|
|||||||
ppTerm q d (ImplArg e) = braces (ppTerm q 0 e)
|
ppTerm q d (ImplArg e) = braces (ppTerm q 0 e)
|
||||||
ppTerm q d (ELincat cat t) = prec d 4 ("lincat" <+> cat <+> ppTerm q 5 t)
|
ppTerm q d (ELincat cat t) = prec d 4 ("lincat" <+> cat <+> ppTerm q 5 t)
|
||||||
ppTerm q d (ELin cat t) = prec d 4 ("lin" <+> cat <+> ppTerm q 5 t)
|
ppTerm q d (ELin cat t) = prec d 4 ("lin" <+> cat <+> ppTerm q 5 t)
|
||||||
|
ppTerm q d (TSymCat i r rs) = pp '<' <> pp i <> pp ',' <> ppLinFun pp r rs <> pp '>'
|
||||||
|
|
||||||
ppEquation q (ps,e) = hcat (map (ppPatt q 2) ps) <+> "->" <+> ppTerm q 0 e
|
ppEquation q (ps,e) = hcat (map (ppPatt q 2) ps) <+> "->" <+> ppTerm q 0 e
|
||||||
|
|
||||||
@@ -356,16 +357,31 @@ ppLit (PGF2.LStr s) = pp (show s)
|
|||||||
ppLit (PGF2.LInt n) = pp n
|
ppLit (PGF2.LInt n) = pp n
|
||||||
ppLit (PGF2.LFlt d) = pp d
|
ppLit (PGF2.LFlt d) = pp d
|
||||||
|
|
||||||
ppSymbol (PGF2.SymCat d r) = pp '<' <> pp d <> pp ',' <> pp r <> pp '>'
|
ppSymbol (PGF2.SymCat d r rs)= pp '<' <> pp d <> pp ',' <> ppLinFun ppIntVar r rs <> pp '>'
|
||||||
ppSymbol (PGF2.SymLit d r) = pp '{' <> pp d <> pp ',' <> pp r <> pp '}'
|
ppSymbol (PGF2.SymLit d r) = pp '{' <> pp d <> pp ',' <> pp r <> pp '}'
|
||||||
ppSymbol (PGF2.SymVar d r) = pp '<' <> pp d <> pp ',' <> pp '$' <> pp r <> pp '>'
|
ppSymbol (PGF2.SymVar d r) = pp '<' <> pp d <> pp ',' <> pp '$' <> pp r <> pp '>'
|
||||||
ppSymbol (PGF2.SymKS t) = doubleQuotes (pp t)
|
ppSymbol (PGF2.SymKS t) = doubleQuotes (pp t)
|
||||||
ppSymbol PGF2.SymNE = pp "nonExist"
|
ppSymbol PGF2.SymNE = pp "nonExist"
|
||||||
ppSymbol PGF2.SymBIND = pp "BIND"
|
ppSymbol PGF2.SymBIND = pp "BIND"
|
||||||
ppSymbol PGF2.SymSOFT_BIND = pp "SOFT_BIND"
|
ppSymbol PGF2.SymSOFT_BIND = pp "SOFT_BIND"
|
||||||
ppSymbol PGF2.SymSOFT_SPACE= pp "SOFT_SPACE"
|
ppSymbol PGF2.SymSOFT_SPACE = pp "SOFT_SPACE"
|
||||||
ppSymbol PGF2.SymCAPIT = pp "CAPIT"
|
ppSymbol PGF2.SymCAPIT = pp "CAPIT"
|
||||||
ppSymbol PGF2.SymALL_CAPIT = pp "ALL_CAPIT"
|
ppSymbol PGF2.SymALL_CAPIT = pp "ALL_CAPIT"
|
||||||
ppSymbol (PGF2.SymKP syms alts) = pp "pre" <+> braces (hsep (punctuate (pp ';') (hsep (map ppSymbol syms) : map ppAlt alts)))
|
ppSymbol (PGF2.SymKP syms alts) = pp "pre" <+> braces (hsep (punctuate (pp ';') (hsep (map ppSymbol syms) : map ppAlt alts)))
|
||||||
|
|
||||||
|
ppLinFun ppParam r rs
|
||||||
|
| r == 0 && not (null rs) = hcat (intersperse (pp '+') ( map ppTerm rs))
|
||||||
|
| otherwise = hcat (intersperse (pp '+') (pp r : map ppTerm rs))
|
||||||
|
where
|
||||||
|
ppTerm (i,p)
|
||||||
|
| i == 1 = ppParam p
|
||||||
|
| otherwise = pp i <> pp '*' <> ppParam p
|
||||||
|
|
||||||
|
ppIntVar p
|
||||||
|
| i == 0 = pp (chars !! j)
|
||||||
|
| otherwise = pp (chars !! j : show i)
|
||||||
|
where
|
||||||
|
chars = "ijklmnopqr"
|
||||||
|
(i,j) = p `divMod` (length chars)
|
||||||
|
|
||||||
ppAlt (syms,ps) = hsep (map ppSymbol syms) <+> pp '/' <+> hsep (map (doubleQuotes . pp) ps)
|
ppAlt (syms,ps) = hsep (map ppSymbol syms) <+> pp '/' <+> hsep (map (doubleQuotes . pp) ps)
|
||||||
|
|||||||
@@ -153,8 +153,9 @@ setAbstractFlag name value = Transaction $ \c_db c_revision c_exn ->
|
|||||||
|
|
||||||
type Token = String
|
type Token = String
|
||||||
type LIndex = Int
|
type LIndex = Int
|
||||||
|
type Param = Int
|
||||||
data Symbol
|
data Symbol
|
||||||
= SymCat {-# UNPACK #-} !Int {-# UNPACK #-} !LIndex
|
= SymCat {-# UNPACK #-} !Int {-# UNPACK #-} !LIndex [(LIndex,Param)]
|
||||||
| SymLit {-# UNPACK #-} !Int {-# UNPACK #-} !LIndex
|
| SymLit {-# UNPACK #-} !Int {-# UNPACK #-} !LIndex
|
||||||
| SymVar {-# UNPACK #-} !Int {-# UNPACK #-} !Int
|
| SymVar {-# UNPACK #-} !Int {-# UNPACK #-} !Int
|
||||||
| SymKS Token
|
| SymKS Token
|
||||||
|
|||||||
Reference in New Issue
Block a user