1
0
forked from GitHub/gf-core

Adding a new experimental partial evalutator

GF.Compile.Compute.ConcreteNew + two new modules contain a new
partial evaluator intended to solve some performance problems with the old
partial evalutator in GF.Compile.Compute.ConcreteLazy. It has been around for
a while, but is now complete enough to compile the RGL and the Phrasebook.

The old partial evaluator is still used by default. The new one can be activated
in two ways:

  - by using the command line option -new-comp when invoking GF.
  - by using cabal configure -fnew-comp to make -new-comp the default. In this
    case you can also use the command line option -old-comp to revert to the old
    partial evaluator.

In the GF shell, the cc command uses the old evaluator regardless of -new-comp
for now, but you can use "cc -new ..." to invoke the new evaluator.

With -new-comp, computations happen in GF.Compile.GeneratePMCFG instead of
GF.Compile.Optimize. This is implemented by testing the flag optNewComp in
both modules, to omit calls to the old partial evaluator from GF.Compile.Optimize
and add calls to the new partial evaluator in GF.Compile.GeneratePMCFG.
This also means that -new-comp effectively implies -noexpand.

In GF.Compile.CheckGrammar, there is a check that restricted inheritance is used
correctly. However, when -noexpand is used, this check causes unexpected errors,
so it has been converted to generate warnings, for now.

-new-comp no longer enables the new type checker in
GF.Compile.Typeckeck.ConcreteNew.

The GF version number has been bumped to 3.3.10-darcs
This commit is contained in:
hallgren
2012-11-13 14:09:15 +00:00
parent 468464faca
commit 27e675910a
12 changed files with 659 additions and 125 deletions

View File

@@ -1,5 +1,5 @@
name: gf
version: 3.3.3-darcs
version: 3.3.10-darcs
cabal-version: >= 1.8
build-type: Custom
@@ -10,7 +10,7 @@ synopsis: Grammatical Framework
description: GF, Grammatical Framework, is a programming language for multilingual grammar applications
homepage: http://www.grammaticalframework.org/
bug-reports: http://code.google.com/p/grammatical-framework/issues/list
tested-with: GHC==6.12.3, GHC==7.0.4
tested-with: GHC==6.12.3, GHC==7.0.4, GHC==7.4.2
data-dir: src
data-files: www/*.html
@@ -45,6 +45,10 @@ flag server
Description: Include --server mode
Default: True
flag new-comp
Description: Make -new-comp the default
Default: False
library
build-depends: base >= 4.2 && <5,
array,
@@ -117,6 +121,9 @@ executable gf
other-modules: GFServer
hs-source-dirs: src/server src/server/transfer src/example-based
if flag(new-comp)
cpp-options: -DNEW_COMP
build-tools: happy
--, alex>=2 && <3 -- tricky to install in Ubuntu 12.04
if os(windows)
@@ -177,10 +184,15 @@ executable gf
GF.Compile.ToAPI
GF.Compile.TypeCheck.Abstract
GF.Compile.TypeCheck.Concrete
GF.Compile.TypeCheck.ConcreteNew
GF.Compile.TypeCheck.TC
GF.Compile.Compute.Abstract
GF.Compile.Compute.Concrete
GF.Compile.Compute.ConcreteNew1
GF.Compile.Compute.ConcreteNew
GF.Compile.Compute.AppPredefined
GF.Compile.Compute.Value
GF.Compile.Compute.Predef
GF.Compile.Optimize
GF.Compile.SubExOpt
GF.Compile.GetGrammar

View File

@@ -78,7 +78,7 @@ checkRestrictedInheritance sgr (name,mo) = checkIn (ppLocation (msrc mo) NoLoc <
(f,cs) <- allDeps, incld f, let is = filter illegal cs, not (null is)]
case illegals of
[] -> return ()
cs -> checkError (text "In inherited module" <+> ppIdent i <> text ", dependence of excluded constants:" $$
cs -> checkWarn (text "In inherited module" <+> ppIdent i <> text ", dependence of excluded constants:" $$
nest 2 (vcat [ppIdent f <+> text "on" <+> fsep (map ppIdent is) | (f,is) <- cs]))
allDeps = concatMap (allDependencies (const True) . jments . snd) mos
@@ -176,7 +176,7 @@ checkInfo opts sgr (m,mo) c info = do
CncCat mty mdef mpr mpmcfg -> do
mty <- case mty of
Just (L loc typ) -> chIn loc "linearization type of" $
(if flag optNewComp opts
(if False --flag optNewComp opts
then do (typ,_) <- CN.checkLType gr typ typeType
typ <- computeLType gr [] typ
return (Just (L loc typ))
@@ -217,17 +217,17 @@ checkInfo opts sgr (m,mo) c info = do
(pty', pde') <- case (pty,pde) of
(Just (L loct ty), Just (L locd de)) -> do
ty' <- chIn loct "operation" $
(if flag optNewComp opts
(if False --flag optNewComp opts
then CN.checkLType gr ty typeType >>= return . CN.normalForm gr . fst
else checkLType gr [] ty typeType >>= computeLType gr [] . fst)
(de',_) <- chIn locd "operation" $
(if flag optNewComp opts
(if False -- flag optNewComp opts
then CN.checkLType gr de ty'
else checkLType gr [] de ty')
return (Just (L loct ty'), Just (L locd de'))
(Nothing , Just (L locd de)) -> do
(de',ty') <- chIn locd "operation" $
(if flag optNewComp opts
(if False -- flag optNewComp opts
then CN.inferLType gr de
else inferLType gr [] de)
return (Just (L locd ty'), Just (L locd de'))

View File

@@ -1,108 +1,338 @@
-- | Functions for computing the values of terms in the concrete syntax, in
-- | preparation for PMCFG generation.
module GF.Compile.Compute.ConcreteNew
( normalForm
, Value(..), Env, eval, apply, value2term
) where
import GF.Grammar hiding (Env, VGen, VApp, VRecType)
import GF.Grammar.Lookup
import GF.Grammar.Predef
import GF.Data.Operations
import Data.List (intersect)
import GF.Grammar.Lookup(lookupResDef,allParamValues)
import GF.Grammar.Predef(cPredef,cErrorType,cTok,cStr)
import GF.Grammar.PatternMatch(matchPattern)
import GF.Grammar.Lockfield(unlockRecord,lockLabel,isLockLabel)
import GF.Compile.Compute.Value
import GF.Compile.Compute.Predef(predefs)
import GF.Data.Str(Str,glueStr,str2strings,str,sstr,plusStr,strTok)
import GF.Data.Operations(Err,err,maybeErr,combinations)
import GF.Data.Utilities(mapSnd,mapBoth,apBoth,apSnd)
import Control.Monad(liftM,liftM2,mplus)
import Data.List (findIndex,intersect,isInfixOf,nub)
import Data.Char (isUpper,toUpper,toLower)
import Text.PrettyPrint
import qualified Data.ByteString.Char8 as BS
import qualified Data.Map as Map
import Debug.Trace(trace)
-- * Main entry points
normalForm :: SourceGrammar -> Term -> Term
normalForm gr t = value2term gr [] (eval gr [] t)
data Value
= VApp QIdent [Value]
| VGen Int [Value]
| VMeta MetaId Env [Value]
| VClosure Env Term
| VInt Int
| VFloat Double
| VString String
| VSort Ident
| VImplArg Value
| VTblType Value Value
| VRecType [(Label,Value)]
| VRec [(Label,Value)]
| VTbl Type [Value]
-- | VC Value Value
| VPatt Patt
| VPattType Value
| VFV [Value]
| VAlts Value [(Value, Value)]
| VError String
deriving Show
type Env = [(Ident,Value)]
normalForm gr = nfx gr []
nfx gr env = value2term gr [] . eval gr env
eval :: SourceGrammar -> Env -> Term -> Value
eval gr env (Vr x) = case lookup x env of
Just v -> v
Nothing -> error ("Unknown variable "++showIdent x)
eval gr env (Q x)
| x == (cPredef,cErrorType) -- to be removed
= let varP = identC (BS.pack "P")
in eval gr [] (mkProd [(Implicit,varP,typeType)] (Vr varP) [])
| fst x == cPredef = VApp x []
| otherwise = case lookupResDef gr x of
Ok t -> eval gr [] t
Bad err -> error err
eval gr env (QC x) = VApp x []
eval gr env (App e1 e2) = apply gr env e1 [eval gr env e2]
eval gr env (Meta i) = VMeta i env []
eval gr env t@(Prod _ _ _ _) = VClosure env t
eval gr env t@(Abs _ _ _) = VClosure env t
eval gr env (EInt n) = VInt n
eval gr env (EFloat f) = VFloat f
eval gr env (K s) = VString s
eval gr env Empty = VString ""
eval gr env (Sort s)
| s == cTok = VSort cStr -- to be removed
| otherwise = VSort s
eval gr env (ImplArg t) = VImplArg (eval gr env t)
eval gr env (Table p res) = VTblType (eval gr env p) (eval gr env res)
eval gr env (RecType rs) = VRecType [(l,eval gr env ty) | (l,ty) <- rs]
eval gr env t@(ExtR t1 t2) =
let error = VError (show (text "The term" <+> ppTerm Unqualified 0 t <+> text "is not reducible"))
in case (eval gr env t1, eval gr env t2) of
(VRecType rs1, VRecType rs2) -> case intersect (map fst rs1) (map fst rs2) of
[] -> VRecType (rs1 ++ rs2)
_ -> error
(VRec rs1, VRec rs2) -> case intersect (map fst rs1) (map fst rs2) of
[] -> VRec (rs1 ++ rs2)
_ -> error
_ -> error
eval gr env (FV ts) = VFV (map (eval gr env) ts)
eval gr env t = error ("unimplemented: eval "++show t)
eval gr env t = value (gr,env) t
apply gr env t [] = eval gr env t
apply gr env (Q x) vs
| fst x == cPredef = VApp x vs -- hmm
| otherwise = case lookupResDef gr x of
Ok t -> apply gr [] t vs
Bad err -> error err
apply gr env (App t1 t2) vs = apply gr env t1 (eval gr env t2 : vs)
apply gr env (Abs b x t) (v:vs) = case (b,v) of
(Implicit,VImplArg v) -> apply gr ((x,v):env) t vs
(Explicit, v) -> apply gr ((x,v):env) t vs
apply gr env t vs = error ("apply "++show t)
apply gr env = apply' (gr,env)
--------------------------------------------------------------------------------
-- * Environments
type CompleteEnv = (SourceGrammar,Env)
ext b (gr,env) = (gr,b:env)
var env x = maybe unbound id (lookup x (snd env))
where unbound = bug ("Unknown variable: "++showIdent x)
-- * Computing values
-- | Computing the value of a top-level term
value0 gr t = eval gr [] t
-- | Computing the value of a term
value :: CompleteEnv -> Term -> Value
value env t0 =
case t0 of
Vr x -> var env x
Q x@(m,f)
| m == cPredef -> if f==cErrorType -- to be removed
then let p = identC (BS.pack "P")
in value0 (fst env) (mkProd [(Implicit,p,typeType)] (Vr p) [])
else VApp x []
| otherwise -> err bug (value0 (fst env)) (lookupResDef (fst env) x)
QC x -> VCApp x []
App e1 e2 -> apply' env e1 [value env e2]
Let (x,(oty,t)) body -> value (ext (x,value env t) env) body
Meta i -> VMeta i (snd env) []
Prod bt x t1 t2 -> VProd bt (value env t1) x (Bind $ \ vx -> value (ext (x,vx) env) t2)
Abs bt x t -> VAbs bt x (Bind $ \ vx -> value (ext (x,vx) env) t)
EInt n -> VInt n
EFloat f -> VFloat f
K s -> VString s
Empty -> VString ""
Sort s | s == cTok -> VSort cStr -- to be removed
| otherwise -> VSort s
ImplArg t -> VImplArg (value env t)
Table p res -> VTblType (value env p) (value env res)
RecType rs -> VRecType [(l,value env ty) | (l,ty) <- rs]
t@(ExtR t1 t2) -> extR t (both (value env) (t1,t2))
FV ts -> vfv (map (value env) ts)
R as -> VRec [(lbl,value env t)|(lbl,(oty,t))<-as]
T i cs -> valueTable env i cs
V ty ts -> VV ty (map (value env) ts)
C t1 t2 -> vconcat (both (value env) (t1,t2))
S t1 t2 -> select (fst env) (both (value env) (t1,t2))
P t l -> --maybe (bug $ "project "++show l++" from "++show v) id $
maybe (VP v l) id $
proj l v where v = (value env t)
Alts t tts -> VAlts (value env t) (mapBoth (value env) tts)
Strs ts -> VStrs (map (value env) ts)
Glue t1 t2 -> glue (both (value env) (t1,t2))
ELin c r -> unlockVRec c (value env r)
t -> ppbug (text "value"<+>ppTerm Unqualified 10 t $$ text (show t))
vconcat vv@(v1,v2) =
case vv of
(VError _,_) -> v1
(VString "",_) -> v2
(_,VError _) -> v2
(_,VString "") -> v1
_ -> VC v1 v2
proj l v | isLockLabel l = return (VRec [])
---- a workaround 18/2/2005: take this away and find the reason
---- why earlier compilation destroys the lock field
proj l v =
case v of
VFV vs -> liftM vfv (mapM (proj l) vs)
VRec rs -> lookup l rs
VExtR v1 v2 -> proj l v2 `mplus` proj l v1 -- hmm
_ -> return (ok1 VP v l)
ok1 f v1@(VError {}) _ = v1
ok1 f v1 v2 = f v1 v2
ok2 f v1@(VError {}) _ = v1
ok2 f _ v2@(VError {}) = v2
ok2 f v1 v2 = f v1 v2
unlockVRec ::Ident -> Value -> Value
unlockVRec c v =
case v of
-- VClosure env t -> err bug (VClosure env) (unlockRecord c t)
VAbs bt x (Bind f) -> VAbs bt x (Bind $ \ v -> unlockVRec c (f v))
VRec rs -> plusVRec rs lock
_ -> VExtR v (VRec lock) -- hmm
-- _ -> bug $ "unlock non-record "++show v
where
lock = [(lockLabel c,VRec [])]
-- suspicious, but backwards compatible
plusVRec rs1 rs2 = VRec ([(l,v)|(l,v)<-rs1,l `notElem` ls2] ++ rs2)
where ls2 = map fst rs2
extR t vv =
case vv of
(VFV vs,v2) -> vfv [extR t (v1,v2)|v1<-vs]
(v1,VFV vs) -> vfv [extR t (v1,v2)|v2<-vs]
(VRecType rs1, VRecType rs2) ->
case intersect (map fst rs1) (map fst rs2) of
[] -> VRecType (rs1 ++ rs2)
ls -> error $ text "clash"<+>text (show ls)
(VRec rs1, VRec rs2) -> plusVRec rs1 rs2
(v1 , VRec [(l,_)]) | isLockLabel l -> v1 -- hmm
(VS (VV t vs) s,v2) -> VS (VV t [extR t (v1,v2)|v1<-vs]) s
(v1,v2) -> ok2 VExtR v1 v2 -- hmm
-- (v1,v2) -> error $ text "not records" $$ text (show v1) $$ text (show v2)
where
error explain = ppbug $ text "The term" <+> ppTerm Unqualified 0 t
<+> text "is not reducible" $$ explain
glue vv = case vv of
(VFV vs,v2) -> vfv [glue (v1,v2)|v1<-vs]
(v1,VFV vs) -> vfv [glue (v1,v2)|v2<-vs]
(VString s1,VString s2) -> VString (s1++s2)
(v1,VAlts d vs) -> VAlts (glx d) [(glx v,c) | (v,c) <- vs]
where glx v2 = glue (v1,v2)
(v1@(VAlts {}),v2) ->
--err (const (ok2 VGlue v1 v2)) id $
err bug id $
do y' <- strsFromValue v2
x' <- strsFromValue v1
return $ vfv [foldr1 VC (map VString (str2strings (glueStr v u))) | v <- x', u <- y']
(VC va vb,v2) -> VC va (glue (vb,v2))
(v1,VC va vb) -> VC (glue (va,va)) vb
(VS (VV ty vs) vb,v2) -> VS (VV ty [glue (v,v2)|v<-vs]) vb
(v1,VS (VV ty vs) vb) -> VS (VV ty [glue (v1,v)|v<-vs]) vb
-- (v1,v2) -> ok2 VGlue v1 v2
(v1,v2) -> bug vv
where
bug vv = ppbug $ text "glue"<+>text (show vv)
-- | to get a string from a value that represents a sequence of terminals
strsFromValue :: Value -> Err [Str]
strsFromValue t = case t of
VString s -> return [str s]
VC s t -> do
s' <- strsFromValue s
t' <- strsFromValue t
return [plusStr x y | x <- s', y <- t']
{-
VGlue s t -> do
s' <- strsFromValue s
t' <- strsFromValue t
return [glueStr x y | x <- s', y <- t']
-}
VAlts d vs -> do
d0 <- strsFromValue d
v0 <- mapM (strsFromValue . fst) vs
c0 <- mapM (strsFromValue . snd) vs
let vs' = zip v0 c0
return [strTok (str2strings def) vars |
def <- d0,
vars <- [[(str2strings v, map sstr c) | (v,c) <- zip vv c0] |
vv <- combinations v0]
]
VFV ts -> mapM strsFromValue ts >>= return . concat
VStrs ts -> mapM strsFromValue ts >>= return . concat
_ -> fail "cannot get Str from value"
vfv vs = case nub vs of
[v] -> v
vs -> VFV vs
select gr vv =
case vv of
(v1,VFV vs) -> vfv [select gr (v1,v2)|v2<-vs]
(VFV vs,v2) -> vfv [select gr (v1,v2)|v1<-vs]
(v1@(VV pty rs),v2) ->
err (const (VS v1 v2)) id $
do ats <- allParamValues gr pty
let vs = map (value0 gr) ats
i <- maybeErr "no match" $ findIndex (==v2) vs
return (rs!!i)
(v1@(VT i cs),v2) ->
err bug (valueMatch gr) $ matchPattern cs (value2term gr [] v2)
(VS (VV pty rs) v12,v2) -> VS (VV pty [select gr (v11,v2)|v11<-rs]) v12
(v1,v2) -> ok2 VS v1 v2
valueMatch gr (Bind f,env') = f (mapSnd (value0 gr) env')
valueTable env@(gr,bs) i cs =
case i of
TComp ty -> VV ty (map (value env.snd) cs)
_ -> err keep id convert
where
keep _ = VT i (err bug id $ mapM valueCase cs)
valueCase (p,t) = do p' <- inlinePattMacro p
return (p',Bind $ \ bs' -> value (gr,bs'++bs) t)
convert = do ty <- getTableType i
let pty = nfx gr bs ty
vs <- allParamValues gr pty
cs' <- mapM valueCase cs
sts <- mapM (matchPattern cs') vs
return $ VV pty (map (valueMatch gr) sts)
inlinePattMacro p = case p of
PM qc -> do EPatt p' <- lookupResDef gr qc
inlinePattMacro p'
_ -> composPattOp inlinePattMacro p
apply' env t [] = value env t
apply' env t vs =
case t of
QC x -> VCApp x vs
Q x@(m,f) | m==cPredef -> let constr = --trace ("predef "++show x) .
VApp x
in maybe constr id (Map.lookup f predefs) vs
| otherwise -> err bug (\t->apply' (fst env,[]) t vs)
(lookupResDef (fst env) x)
App t1 t2 -> apply' env t1 (value env t2 : vs)
-- Abs b x t -> beta env b x t vs
_ -> vapply (value env t) vs
vapply v [] = v
vapply v vs =
case v of
VError {} -> v
-- VClosure env (Abs b x t) -> beta gr env b x t vs
VAbs bt _ (Bind f) -> vbeta bt f vs
VS (VV t fs) s -> VS (VV t [vapply f vs|f<-fs]) s
v -> bug $ "vapply "++show v++" "++show vs
vbeta bt f (v:vs) =
case (bt,v) of
(Implicit,VImplArg v) -> vapply (f v) vs
(Explicit, v) -> vapply (f v) vs
{-
beta env b x t (v:vs) =
case (b,v) of
(Implicit,VImplArg v) -> apply' (ext (x,v) env) t vs
(Explicit, v) -> apply' (ext (x,v) env) t vs
-}
-- tr s f vs = trace (s++" "++show vs++" = "++show r) r where r = f vs
-- | Convert a value back to a term
value2term :: SourceGrammar -> [Ident] -> Value -> Term
value2term gr xs (VApp f vs) = foldl App (Q f) (map (value2term gr xs) vs)
value2term gr xs (VGen j vs) = foldl App (Vr (reverse xs !! j)) (map (value2term gr xs) vs)
value2term gr xs (VMeta j env vs) = foldl App (Meta j) (map (value2term gr xs) vs)
value2term gr xs (VClosure env (Prod bt x t1 t2)) = Prod bt x (value2term gr xs (eval gr env t1))
(value2term gr (x:xs) (eval gr ((x,VGen (length xs) []) : env) t2))
value2term gr xs (VClosure env (Abs bt x t)) = Abs bt x (value2term gr (x:xs) (eval gr ((x,VGen (length xs) []) : env) t))
value2term gr xs (VInt n) = EInt n
value2term gr xs (VFloat f) = EFloat f
value2term gr xs (VString s) = if null s then Empty else K s
value2term gr xs (VSort s) = Sort s
value2term gr xs (VImplArg v) = ImplArg (value2term gr xs v)
value2term gr xs (VTblType p res) = Table (value2term gr xs p) (value2term gr xs res)
value2term gr xs (VRecType rs) = RecType [(l,value2term gr xs v) | (l,v) <- rs]
value2term gr xs (VFV vs) = FV (map (value2term gr xs) vs)
value2term gr xs v = error ("unimplemented: value2term "++show v)
value2term gr xs v0 =
case v0 of
VApp f vs -> foldl App (Q f) (map v2t vs)
VCApp f vs -> foldl App (QC f) (map v2t vs)
VGen j vs -> foldl App (Vr (reverse xs !! j)) (map v2t vs)
VMeta j env vs -> foldl App (Meta j) (map v2t vs)
-- VClosure env (Prod bt x t1 t2) -> Prod bt x (v2t (eval gr env t1))
-- (nf gr (push x (env,xs)) t2)
-- VClosure env (Abs bt x t) -> Abs bt x (nf gr (push x (env,xs)) t)
VProd bt v x (Bind f) -> Prod bt x (v2t v) (v2t' x f)
VAbs bt x (Bind f) -> Abs bt x (v2t' x f)
VInt n -> EInt n
VFloat f -> EFloat f
VString s -> if null s then Empty else K s
VSort s -> Sort s
VImplArg v -> ImplArg (v2t v)
VTblType p res -> Table (v2t p) (v2t res)
VRecType rs -> RecType [(l,v2t v) | (l,v) <- rs]
VRec as -> R [(l,(Nothing,v2t v))|(l,v) <- as]
VV t vs -> V t (map v2t vs)
VT i cs -> T i (map nfcase cs)
VFV vs -> FV (map v2t vs)
VC v1 v2 -> C (v2t v1) (v2t v2)
VS v1 v2 -> S (v2t v1) (v2t v2)
VP v l -> P (v2t v) l
VAlts v vvs -> Alts (v2t v) (mapBoth v2t vvs)
VStrs vs -> Strs (map v2t vs)
-- VGlue v1 v2 -> Glue (v2t v1) (v2t v2)
VExtR v1 v2 -> ExtR (v2t v1) (v2t v2)
VError err -> Error err
_ -> bug ("value2term "++show v0)
where
v2t = value2term gr xs
v2t' x f = value2term gr (x:xs) (f (gen xs))
pushs xs e = foldr push e xs
push x (env,xs) = ((x,gen xs):env,x:xs)
gen xs = VGen (length xs) []
nfcase (p,Bind f) = (p,value2term gr xs' (f env'))
where (env',xs') = pushs (pattVars p) ([],xs)
-- nf gr (env,xs) = value2term gr xs . eval gr env
pattVars = nub . pv
where
pv p = case p of
PV i -> [i]
PAs i p -> i:pv p
_ -> collectPattOp pv p
---
both = apBoth
bug msg = ppbug (text msg)
ppbug doc = error $ render $
hang (text "Internal error in Compute.ConcreteNew2:") 4 doc

View File

@@ -0,0 +1,108 @@
module GF.Compile.Compute.ConcreteNew1
( normalForm
, Value(..), Env, eval, apply, value2term
) where
import GF.Grammar hiding (Env, VGen, VApp, VRecType)
import GF.Grammar.Lookup
import GF.Grammar.Predef
import GF.Data.Operations
import Data.List (intersect)
import Text.PrettyPrint
import qualified Data.ByteString.Char8 as BS
normalForm :: SourceGrammar -> Term -> Term
normalForm gr t = value2term gr [] (eval gr [] t)
data Value
= VApp QIdent [Value]
| VGen Int [Value]
| VMeta MetaId Env [Value]
| VClosure Env Term
| VInt Int
| VFloat Double
| VString String
| VSort Ident
| VImplArg Value
| VTblType Value Value
| VRecType [(Label,Value)]
| VRec [(Label,Value)]
| VTbl Type [Value]
-- | VC Value Value
| VPatt Patt
| VPattType Value
| VFV [Value]
| VAlts Value [(Value, Value)]
| VError String
deriving Show
type Env = [(Ident,Value)]
eval :: SourceGrammar -> Env -> Term -> Value
eval gr env (Vr x) = case lookup x env of
Just v -> v
Nothing -> error ("Unknown variable "++showIdent x)
eval gr env (Q x)
| x == (cPredef,cErrorType) -- to be removed
= let varP = identC (BS.pack "P")
in eval gr [] (mkProd [(Implicit,varP,typeType)] (Vr varP) [])
| fst x == cPredef = VApp x []
| otherwise = case lookupResDef gr x of
Ok t -> eval gr [] t
Bad err -> error err
eval gr env (QC x) = VApp x []
eval gr env (App e1 e2) = apply gr env e1 [eval gr env e2]
eval gr env (Meta i) = VMeta i env []
eval gr env t@(Prod _ _ _ _) = VClosure env t
eval gr env t@(Abs _ _ _) = VClosure env t
eval gr env (EInt n) = VInt n
eval gr env (EFloat f) = VFloat f
eval gr env (K s) = VString s
eval gr env Empty = VString ""
eval gr env (Sort s)
| s == cTok = VSort cStr -- to be removed
| otherwise = VSort s
eval gr env (ImplArg t) = VImplArg (eval gr env t)
eval gr env (Table p res) = VTblType (eval gr env p) (eval gr env res)
eval gr env (RecType rs) = VRecType [(l,eval gr env ty) | (l,ty) <- rs]
eval gr env t@(ExtR t1 t2) =
let error = VError (show (text "The term" <+> ppTerm Unqualified 0 t <+> text "is not reducible"))
in case (eval gr env t1, eval gr env t2) of
(VRecType rs1, VRecType rs2) -> case intersect (map fst rs1) (map fst rs2) of
[] -> VRecType (rs1 ++ rs2)
_ -> error
(VRec rs1, VRec rs2) -> case intersect (map fst rs1) (map fst rs2) of
[] -> VRec (rs1 ++ rs2)
_ -> error
_ -> error
eval gr env (FV ts) = VFV (map (eval gr env) ts)
eval gr env t = error ("unimplemented: eval "++show t)
apply gr env t [] = eval gr env t
apply gr env (Q x) vs
| fst x == cPredef = VApp x vs -- hmm
| otherwise = case lookupResDef gr x of
Ok t -> apply gr [] t vs
Bad err -> error err
apply gr env (App t1 t2) vs = apply gr env t1 (eval gr env t2 : vs)
apply gr env (Abs b x t) (v:vs) = case (b,v) of
(Implicit,VImplArg v) -> apply gr ((x,v):env) t vs
(Explicit, v) -> apply gr ((x,v):env) t vs
apply gr env t vs = error ("apply "++show t)
value2term :: SourceGrammar -> [Ident] -> Value -> Term
value2term gr xs (VApp f vs) = foldl App (Q f) (map (value2term gr xs) vs)
value2term gr xs (VGen j vs) = foldl App (Vr (reverse xs !! j)) (map (value2term gr xs) vs)
value2term gr xs (VMeta j env vs) = foldl App (Meta j) (map (value2term gr xs) vs)
value2term gr xs (VClosure env (Prod bt x t1 t2)) = Prod bt x (value2term gr xs (eval gr env t1))
(value2term gr (x:xs) (eval gr ((x,VGen (length xs) []) : env) t2))
value2term gr xs (VClosure env (Abs bt x t)) = Abs bt x (value2term gr (x:xs) (eval gr ((x,VGen (length xs) []) : env) t))
value2term gr xs (VInt n) = EInt n
value2term gr xs (VFloat f) = EFloat f
value2term gr xs (VString s) = if null s then Empty else K s
value2term gr xs (VSort s) = Sort s
value2term gr xs (VImplArg v) = ImplArg (value2term gr xs v)
value2term gr xs (VTblType p res) = Table (value2term gr xs p) (value2term gr xs res)
value2term gr xs (VRecType rs) = RecType [(l,value2term gr xs v) | (l,v) <- rs]
value2term gr xs (VFV vs) = FV (map (value2term gr xs) vs)
value2term gr xs v = error ("unimplemented: value2term "++show v)

View File

@@ -0,0 +1,88 @@
-- | Implementations of predefined functions
module GF.Compile.Compute.Predef where
import Text.PrettyPrint(render,hang,text)
import qualified Data.Map as Map
import Data.List (isInfixOf)
import Data.Char (isUpper,toLower,toUpper)
import GF.Data.Utilities (mapSnd,apBoth)
import GF.Compile.Compute.Value
import GF.Infra.Ident (Ident)
import GF.Grammar.Predef
predefs :: Map.Map Ident ([Value]->Value)
predefs = Map.fromList $ mapSnd strictf
[(cDrop,apISS drop),(cTake,apISS take),(cTk,apISS tk),(cDp,apISS dp),
(cEqStr,apSSB (==)),(cOccur,apSSB occur),(cOccurs,apSSB occurs),
(cToUpper,apSS (map toUpper)),(cToLower,apSS (map toLower)),
(cIsUpper,apSB (all isUpper)),(cLength,apSS' (VInt . length)),
(cPlus,apIII (+)),(cEqInt,apIIB (==)),(cLessInt,apIIB (<)),
(cShow,unimpl),(cRead,unimpl),(cToStr,unimpl),(cMapStr,unimpl),
(cEqVal,unimpl),(cError,apSS' VError)]
--- add more functions!!!
where
unimpl = bug "unimplemented predefined function"
tk i s = take (max 0 (length s - i)) s
dp i s = drop (max 0 (length s - i)) s
occur s t = isInfixOf s t
occurs s t = any (`elem` t) s
apIII f vs = case vs of
[VInt i1, VInt i2] -> VInt (f i1 i2)
_ -> bug $ "f::Int->Int->Int got "++show vs
apIIB f vs = case vs of
[VInt i1, VInt i2] -> boolV (f i1 i2)
_ -> bug $ "f::Int->Int->Bool got "++show vs
apISS f vs = case vs of
[VInt i, VString s] -> string (f i s)
_ -> bug $ "f::Int->Str->Str got "++show vs
apSSB f vs = case vs of
[VString s1, VString s2] -> boolV (f s1 s2)
_ -> bug $ "f::Str->Str->Bool got "++show vs
apSB f vs = case vs of
[VString s] -> boolV (f s)
_ -> bug $ "f::Str->Bool got "++show vs
apSS f vs = case vs of
[VString s] -> string (f s)
_ -> bug $ "f::Str->Str got "++show vs
apSS' f vs = case vs of
[VString s] -> f s
_ -> bug $ "f::Str->_ got "++show vs
boolV b = VCApp (cPredef,if b then cPTrue else cPFalse) []
strictf f vs = case normvs vs of
Left err -> VError err
Right vs -> f vs
normvs = mapM (strict . norm)
norm v =
case v of
VC v1 v2 -> case apBoth norm (v1,v2) of
(VString s1,VString s2) -> VString (s1++" "++s2)
(v1,v2) -> VC v1 v2
_ -> v
strict v = case v of
VError err -> Left err
_ -> Right v
string s = case words s of
[] -> VString ""
ss -> foldr1 VC (map VString ss)
---
bug msg = ppbug (text msg)
ppbug doc = error $ render $
hang (text "Internal error in Compute.Predef:") 4 doc

View File

@@ -0,0 +1,44 @@
module GF.Compile.Compute.Value where
import GF.Grammar.Grammar(Label,Type,TInfo,MetaId,Patt,QIdent)
import PGF.Data(BindType)
import GF.Infra.Ident(Ident)
import Text.Show.Functions
-- | Self-contained (not quite) representation of values
data Value
= VApp QIdent [Value] -- from Q, always Predef.x, has a built-in value
| VCApp QIdent [Value] -- from QC, constructors
| VGen Int [Value] -- for lambda bound variables, possibly applied
| VMeta MetaId Env [Value]
-- | VClosure Env Term -- used in Typecheck.ConcreteNew
| VAbs BindType Ident Binding -- used in Compute.ConcreteNew
| VProd BindType Value Ident Binding -- used in Compute.ConcreteNew
| VInt Int
| VFloat Double
| VString String
| VSort Ident
| VImplArg Value
| VTblType Value Value
| VRecType [(Label,Value)]
| VRec [(Label,Value)]
| VV Type [Value]
| VT TInfo [(Patt,Bind Env)]
| VC Value Value
| VS Value Value
| VP Value Label
| VPatt Patt
| VPattType Value
| VFV [Value]
| VAlts Value [(Value, Value)]
| VStrs [Value]
-- | VGlue Value Value -- hmm
| VExtR Value Value -- hmm
| VError String
deriving (Eq,Show)
type Binding = Bind Value
data Bind a = Bind (a->Value) deriving Show
instance Eq (Bind a) where x==y = False
type Env = [(Ident,Value)]

View File

@@ -23,8 +23,8 @@ import GF.Grammar.Predef
import GF.Data.BacktrackM
import GF.Data.Operations
import GF.Data.Utilities (updateNthM, updateNth)
import System.IO
import GF.Compile.Compute.ConcreteNew(normalForm)
import System.IO(hPutStr,hPutStrLn,stderr)
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.List as List
@@ -71,7 +71,7 @@ addPMCFG opts gr am cm seqs id (GF.Grammar.CncFun mty@(Just (cat,cont,val)) mlin
pmcfgEnv0 = emptyPMCFGEnv
b = runCnvMonad gr (unfactor term >>= convertTerm opts CNil val) (pargs,[])
b = convert opts gr term val pargs
(seqs1,b1) = addSequencesB seqs b
pmcfgEnv1 = foldBM addRule
pmcfgEnv0
@@ -104,7 +104,7 @@ addPMCFG opts gr am cm seqs id (GF.Grammar.CncCat mty@(Just (L _ lincat)) mdef@(
pmcfgEnv0 = emptyPMCFGEnv
b = runCnvMonad gr (unfactor term >>= convertTerm opts CNil lincat) ([parg],[])
b = convert opts gr term lincat [parg]
(seqs1,b1) = addSequencesB seqs b
pmcfgEnv1 = foldBM addRule
pmcfgEnv0
@@ -121,12 +121,34 @@ addPMCFG opts gr am cm seqs id (GF.Grammar.CncCat mty@(Just (L _ lincat)) mdef@(
addPMCFG opts gr am cm seqs id info = return (seqs, info)
convert opts gr term val pargs =
runCnvMonad gr conv (pargs,[])
where
conv = convertTerm opts CNil val =<< unfactor term'
term' = if flag optNewComp opts
then normalForm gr (recordExpand val term) -- new evaluator
else term -- old evaluator is invoked from GF.Compile.Optimize
recordExpand :: Type -> Term -> Term
recordExpand typ trm =
case typ of
RecType tys -> expand trm
where
n = length tys
expand trm =
case trm of
FV ts -> FV (map expand ts)
R rs | length rs==n -> trm
_ -> R [assign lab (P trm lab) | (lab,_) <- tys]
_ -> trm
unfactor :: Term -> CnvMonad Term
unfactor t = CM (\gr c -> c (unfac gr t))
where
unfac gr t =
case t of
T (TTyped ty) [(PV x,u)] -> V ty [restore x v (unfac gr u) | v <- err bug id (allParamValues gr ty)]
T (TTyped ty) _ -> ppbug $ text "unfactor"<+>ppTerm Unqualified 10 t
_ -> composSafeOp (unfac gr) t
where
restore x u t = case t of
@@ -329,9 +351,16 @@ convertTerm opts sel ctype (Alts s alts)
strings (K s) = [s]
strings (C u v) = strings u ++ strings v
strings (Strs ss) = concatMap strings ss
strings Empty = [] -- ??
strings t = bug $ "strings "++show t
convertTerm opts sel@(CProj l _) ctype (ExtR t1 t2@(R rs2))
| l `elem` map fst rs2 = convertTerm opts sel ctype t2
| otherwise = convertTerm opts sel ctype t1
convertTerm opts CNil ctype t = do v <- evalTerm CNil t
return (CPar v)
convertTerm _ _ _ t = ppbug (text "convertTerm" <+> parens (ppTerm Unqualified 0 t))
convertTerm _ sel _ t = ppbug (text "convertTerm" <+> sep [parens (text (show sel)),ppTerm Unqualified 10 t])
convertArg :: Options -> Term -> Int -> Path -> CnvMonad (Value [Symbol])
convertArg opts (RecType rs) nr path =
@@ -460,7 +489,7 @@ evalTerm path (V pt ts) = case path of
(CSel trm path) -> do vs <- getAllParamValues pt
case lookup trm (zip vs ts) of
Just t -> evalTerm path t
Nothing -> bug "evalTerm: missing value"
Nothing -> ppbug $ text "evalTerm: missing value:"<+>ppTerm Unqualified 0 trm $$ text "among:"<+>fsep (map (ppTerm Unqualified 10) vs)
CNil -> do ts <- mapM (evalTerm path) ts
return (V pt ts)
evalTerm path (S term sel) = do v <- evalTerm CNil sel
@@ -468,10 +497,12 @@ evalTerm path (S term sel) = do v <- evalTerm CNil sel
evalTerm path (FV terms) = variants terms >>= evalTerm path
evalTerm path (EInt n) = return (EInt n)
evalTerm path t = ppbug (text "evalTerm" <+> parens (ppTerm Unqualified 0 t))
--evalTerm path t = ppbug (text "evalTerm" <+> sep [parens (text (show path)),parens (text (show t))])
getVarIndex (IA _ i) = i
getVarIndex (IAV _ _ i) = i
getVarIndex (IC s) | isDigit (BS.last s) = (read . BS.unpack . snd . BS.spanEnd isDigit) s
getVarIndex x = bug ("getVarIndex "++show x)
----------------------------------------------------------------------
-- GrammarEnv
@@ -545,4 +576,4 @@ mkArray lst = listArray (0,length lst-1) lst
mkSetArray map = array (0,Map.size map-1) [(v,k) | (k,v) <- Map.toList map]
bug msg = ppbug (text msg)
ppbug doc = error $ render $ text "Internal error:" <+> doc
ppbug = error . render . hang (text "Internal error in GeneratePMCFG:") 4

View File

@@ -86,7 +86,7 @@ evalInfo opts sgr m c info = do
return $ CncFun mt pde' ppr' mpmcfg -- only cat in type actually needed
ResOper pty pde
| OptExpand `Set.member` optim -> do
| not new && OptExpand `Set.member` optim -> do
pde' <- case pde of
Just (L loc de) -> do de <- computeConcrete gr de
return (Just (L loc (factor param c 0 de)))
@@ -95,6 +95,8 @@ evalInfo opts sgr m c info = do
_ -> return info
where
new = flag optNewComp opts -- computations moved to GF.Compile.GeneratePMCFG
gr = prependModule sgr m
optim = flag optOptimizations opts
param = OptParametrize `Set.member` optim
@@ -107,13 +109,17 @@ partEval opts gr (context, val) trm = errIn (render (text "partial evaluation" <
args = map Vr vars
subst = [(v, Vr v) | v <- vars]
trm1 = mkApp trm args
trm2 <- computeTerm gr subst trm1
trm3 <- if rightType trm2
then computeTerm gr subst trm2
else recordExpand val trm2 >>= computeTerm gr subst
trm2 <- if new then return trm1 else computeTerm gr subst trm1
trm3 <- if new
then return trm2
else if rightType trm2
then computeTerm gr subst trm2 -- compute twice??
else recordExpand val trm2 >>= computeTerm gr subst
trm4 <- checkPredefError gr trm3
return $ mkAbs [(Explicit,v) | v <- vars] trm4
where
new = flag optNewComp opts -- computations moved to GF.Compile.GeneratePMCFG
-- don't eta expand records of right length (correct by type checking)
rightType (R rs) = case val of
RecType ts -> length rs == length ts

View File

@@ -4,7 +4,7 @@ import GF.Grammar hiding (Env, VGen, VApp, VRecType)
import GF.Grammar.Lookup
import GF.Grammar.Predef
import GF.Grammar.Lockfield
import GF.Compile.Compute.ConcreteNew
import GF.Compile.Compute.ConcreteNew1
import GF.Compile.Compute.AppPredefined
import GF.Infra.CheckM
import GF.Infra.UseIO
@@ -245,7 +245,7 @@ tcPatt gr scope (PAlt p1 p2) ty0 = do
tcPatt gr scope p1 ty0
tcPatt gr scope p2 ty0
return scope
tcPatt gr scope p ty = error ("tcPatt "++show p)
tcPatt gr scope p ty = unimplemented ("tcPatt "++show p)
inferRecFields gr scope rs =
@@ -479,6 +479,8 @@ tcError msg = TcM (\ms msgs -> TcFail (msg : msgs))
tcWarn :: Message -> TcM ()
tcWarn msg = TcM (\ms msgs -> TcOk () ms ((text "Warning:" <+> msg) : msgs))
unimplemented str = fail ("Unimplemented: "++str)
runTcM :: TcM a -> Check a
runTcM f = case unTcM f IntMap.empty [] of
TcOk x _ msgs -> do checkWarnings msgs; return x

View File

@@ -15,6 +15,9 @@ buildInfo =
#endif
#ifdef SERVER_MODE
++" server"
#endif
#ifdef NEW_COMP
++" new-comp"
#endif
where
details = either (const no_info) info darcs_info

View File

@@ -1,3 +1,4 @@
{-# LANGUAGE CPP #-}
module GF.Infra.Option
(
-- * Option types
@@ -256,11 +257,7 @@ defaultFlags = Flags {
optPreprocessors = [],
optEncoding = "latin1",
optPMCFG = True,
-- #ifdef CC_LAZY
-- optOptimizations = Set.fromList [OptStem,OptCSE],
-- #else
optOptimizations = Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize],
-- #endif
optOptimizePGF = False,
optMkIndexPGF = False,
optCFGTransforms = Set.fromList [CFGRemoveCycles, CFGBottomUpFilter,
@@ -273,7 +270,12 @@ defaultFlags = Flags {
optWarnings = [],
optDump = [],
optTagsOnly = False,
optNewComp = False
optNewComp =
#ifdef NEW_COMP
True
#else
False
#endif
}
-- Option descriptions
@@ -352,6 +354,7 @@ optDescr =
Option [] ["cse"] (onOff (toggleOptimize OptCSE) True) "Perform common sub-expression elimination (default on).",
Option [] ["cfg"] (ReqArg cfgTransform "TRANS") "Enable or disable specific CFG transformations. TRANS = merge, no-merge, bottomup, no-bottomup, ...",
Option [] ["new-comp"] (NoArg (set $ \o -> o{optNewComp = True})) "Use the new experimental compiler.",
Option [] ["old-comp"] (NoArg (set $ \o -> o{optNewComp = False})) "Use old trusty compiler.",
dumpOption "source" Source,
dumpOption "rebuild" Rebuild,
dumpOption "extend" Extend,

View File

@@ -18,6 +18,7 @@ import GF.Grammar.ShowTerm
import GF.Grammar.Lookup (allOpers,allOpersTo)
import GF.Compile.Rename(renameSourceTerm)
import GF.Compile.Compute.Concrete (computeConcrete,checkPredefError)
import qualified GF.Compile.Compute.ConcreteNew as CN(normalForm)
import GF.Compile.TypeCheck.Concrete (inferLType,ppType)
import GF.Infra.Dependencies(depGraph)
import GF.Infra.CheckM
@@ -177,13 +178,16 @@ execute1 opts gfenv0 s0 =
pOpts style q ("-qual" :ws) = pOpts style Qualified ws
pOpts style q ws = (style,q,unwords ws)
(style,q,s) = pOpts TermPrintDefault Qualified ws
(style,q,s) = pOpts TermPrintDefault Qualified ws'
(new,ws') = case ws of
"-new":ws' -> (True,ws')
_ -> (False,ws)
case runP pExp (encodeUnicode utf8 s) of
Left (_,msg) -> putStrLn msg
Right t -> case checkComputeTerm sgr (codeTerm (decodeUnicode utf8 . BS.pack) t) of
Ok x -> putStrLn $ showTerm sgr style q x
Bad s -> putStrLn $ s
Right t -> putStrLn . err id (showTerm sgr style q)
. checkComputeTerm' new sgr
$ codeTerm (decodeUnicode utf8 . BS.pack) t
continue gfenv
show_deps ws = do
@@ -319,11 +323,14 @@ execute1 opts gfenv0 s0 =
printException e = maybe (print e) (putStrLn . ioErrorText) (fromException e)
checkComputeTerm sgr t = do
checkComputeTerm = checkComputeTerm' False
checkComputeTerm' new sgr t = do
mo <- maybe (Bad "no source grammar in scope") return $ greatestResource sgr
((t,_),_) <- runCheck $ do t <- renameSourceTerm sgr mo t
inferLType sgr [] t
t1 <- computeConcrete sgr t
t1 <- if new
then return (CN.normalForm sgr t)
else computeConcrete sgr t
checkPredefError sgr t1
fetchCommand :: GFEnv -> IO String