1
0
forked from GitHub/gf-core

gf works with the new gfcc format

This commit is contained in:
aarne
2007-10-05 12:54:29 +00:00
parent 2b5b099813
commit 122546b9d6
12 changed files with 118 additions and 185 deletions

View File

@@ -19,8 +19,12 @@ import GF.Canon.AbsGFC
import qualified GF.Canon.GFC as GFC
import qualified GF.Canon.Look as Look
import qualified GF.Canon.Subexpressions as Sub
import qualified GF.Canon.GFCC.AbsGFCC as C
import qualified GF.Canon.GFCC.PrintGFCC as Pr
import qualified GF.GFCC.Macros as CM
import qualified GF.GFCC.AbsGFCC as C
import qualified GF.GFCC.DataGFCC as D
import GF.GFCC.OptimizeGFCC
import GF.Canon.GFC
import GF.Canon.Share
import qualified GF.Grammar.Abstract as A
@@ -42,56 +46,71 @@ import Debug.Trace ----
-- the main function: generate GFCC from GFCM.
prCanon2gfcc :: CanonGrammar -> String
prCanon2gfcc = Pr.printTree . mkCanon2gfcc
prCanon2gfcc = D.printGFCC . mkCanon2gfcc
-- this variant makes utf8 conversion; used in back ends
mkCanon2gfcc :: CanonGrammar -> C.Grammar
mkCanon2gfcc = canon2gfcc . reorder . utf8Conv . canon2canon . normalize
mkCanon2gfcc :: CanonGrammar -> D.GFCC
mkCanon2gfcc =
-- canon2gfcc . reorder abs . utf8Conv . canon2canon abs
optGFCC . canon2gfcc . reorder . utf8Conv . canon2canon . normalize
-- this variant makes no utf8 conversion; used in ShellState
mkCanon2gfccNoUTF8 :: CanonGrammar -> C.Grammar
mkCanon2gfccNoUTF8 = canon2gfcc . reorder . canon2canon . normalize
mkCanon2gfccNoUTF8 :: CanonGrammar -> D.GFCC
mkCanon2gfccNoUTF8 = optGFCC . canon2gfcc . reorder . canon2canon . normalize
-- This is needed to reorganize the grammar. GFCC has its own back-end optimization.
-- This is needed to reorganize the grammar.
-- GFCC has its own back-end optimization.
-- But we need to have the canonical order in tables, created by valOpt
normalize :: CanonGrammar -> CanonGrammar
normalize = share . unoptimizeCanon . Sub.unSubelimCanon where
share = M.MGrammar . map (shareModule valOpt) . M.modules --- allOpt
-- Generate GFCC from GFCM.
-- this assumes a grammar translated by canon2canon
-- this assumes a grammar normalized and transformed by canon2canon
canon2gfcc :: CanonGrammar -> C.Grammar
canon2gfcc :: CanonGrammar -> D.GFCC
canon2gfcc cgr@(M.MGrammar ((a,M.ModMod abm):cms)) =
C.Grm (C.Hdr (i2i a) cs) (C.Abs adefs) cncs where
cs = map (i2i . fst) cms
adefs = [C.Fun f' (mkType ty) (C.Tr (C.AC f') []) |
(f,GFC.AbsFun ty _) <- tree2list (M.jments abm), let f' = i2i f]
cncs = [C.Cnc (i2i lang) (concr m) | (lang,M.ModMod m) <- cms]
concr mo = cats mo ++ lindefs mo ++
optConcrete
[C.Lin (i2i f) (mkTerm tr) |
(f,GFC.CncFun _ _ tr _) <- tree2list (M.jments mo)]
cats mo = [C.Lin (i2ic c) (mkCType ty) |
(c,GFC.CncCat ty _ _) <- tree2list (M.jments mo)]
lindefs mo = [C.Lin (i2id c) (mkTerm tr) |
(c,GFC.CncCat _ tr _) <- tree2list (M.jments mo)]
D.GFCC an cns abs cncs
where
an = (i2i a)
cns = map (i2i . fst) cms
abs = D.Abstr aflags funs cats catfuns
aflags = Map.fromAscList [] ---- flags
lfuns = [(f', (mkType ty,CM.primNotion)) | ---- defs
(f,GFC.AbsFun ty _) <- tree2list (M.jments abm), let f' = i2i f]
funs = Map.fromAscList lfuns
lcats = [(i2i c,[]) | ---- context
(c,GFC.AbsCat _ _) <- tree2list (M.jments abm)]
cats = Map.fromAscList lcats
catfuns = Map.fromAscList
[(cat,[f | (f, (C.DTyp _ c _,_)) <- lfuns, c==cat]) | (cat,_) <- lcats]
cncs = Map.fromList [mkConcr (i2i lang) mo | (lang,M.ModMod mo) <- cms]
mkConcr lang mo = (lang,D.Concr flags lins opers lincats lindefs printnames)
where
flags = Map.fromAscList [] ---- flags
opers = Map.fromAscList [] -- opers will be created as optimization
lins = Map.fromAscList
[(i2i f, mkTerm tr) | (f,GFC.CncFun _ _ tr _) <- tree2list (M.jments mo)]
lincats = Map.fromAscList
[(i2i c, mkCType ty) | (c,GFC.CncCat ty _ _) <- tree2list (M.jments mo)]
lindefs = Map.fromAscList
[(i2i c, mkTerm tr) | (c,GFC.CncCat _ tr _) <- tree2list (M.jments mo)]
printnames = Map.fromAscList [] ---- printnames
i2i :: Ident -> C.CId
i2i (IC c) = C.CId c
i2ic (IC c) = C.CId ("__" ++ c) -- for lincat of category symbols
i2id (IC c) = C.CId ("_d" ++ c) -- for lindef of category symbols
mkType :: A.Type -> C.Type
mkType t = case GM.catSkeleton t of
Ok (cs,c) -> C.Typ (map (i2i . snd) cs) (i2i $ snd c)
Ok (cs,c) -> CM.cftype (map (i2i . snd) cs) (i2i $ snd c)
mkCType :: CType -> C.Term
mkCType t = case t of
TInts i -> C.C $ fromInteger i
-- record parameter alias - created in gfc preprocessing
RecType [Lbg (L (IC "_")) i, Lbg (L (IC "__")) t] -> C.RP (mkCType i) (mkCType t)
RecType rs -> C.R [mkCType t | Lbg _ t <- rs]
RecType rs -> C.R [mkCType t | Lbg _ t <- rs]
Table pt vt -> C.R $ replicate (getI (mkCType pt)) $ mkCType vt
TStr -> C.S []
where
@@ -109,9 +128,6 @@ mkTerm tr = case tr of
R rs -> C.R [mkTerm t | Ass _ t <- rs]
P t l -> C.P (mkTerm t) (C.C (mkLab l))
LI x -> C.BV $ i2i x
T _ [Cas [PV x] t] -> C.L (i2i x) (mkTerm t)
T _ cs -> error $ "improper optimization for gfcc in" +++ A.prt tr
V _ cs -> C.R [mkTerm t | t <- cs]
S t p -> C.P (mkTerm t) (mkTerm p)
@@ -401,102 +417,3 @@ unlockTyp = filter notlock where
prtTrace tr n = n ----trace ("-- ERROR" +++ A.prt tr +++ show n +++ show tr) n
prTrace tr n = trace ("-- OBSERVE" +++ A.prt tr +++ show n +++ show tr) n
-- back-end optimization:
-- suffix analysis followed by common subexpression elimination
optConcrete :: [C.CncDef] -> [C.CncDef]
optConcrete defs = subex
[C.Lin f (optTerm t) | C.Lin f t <- defs]
-- analyse word form lists into prefix + suffixes
-- suffix sets can later be shared by subex elim
optTerm :: C.Term -> C.Term
optTerm tr = case tr of
C.R ts@(_:_:_) | all isK ts -> mkSuff $ optToks [s | C.K (C.KS s) <- ts]
C.R ts -> C.R $ map optTerm ts
C.P t v -> C.P (optTerm t) v
C.L x t -> C.L x (optTerm t)
_ -> tr
where
optToks ss = prf : suffs where
prf = pref (head ss) (tail ss)
suffs = map (drop (length prf)) ss
pref cand ss = case ss of
s1:ss2 -> if isPrefixOf cand s1 then pref cand ss2 else pref (init cand) ss
_ -> cand
isK t = case t of
C.K (C.KS _) -> True
_ -> False
mkSuff ("":ws) = C.R (map (C.K . C.KS) ws)
mkSuff (p:ws) = C.W p (C.R (map (C.K . C.KS) ws))
-- common subexpression elimination; see ./Subexpression.hs for the idea
subex :: [C.CncDef] -> [C.CncDef]
subex js = errVal js $ do
(tree,_) <- appSTM (getSubtermsMod js) (Map.empty,0)
return $ addSubexpConsts tree js
type TermList = Map.Map C.Term (Int,Int) -- number of occs, id
type TermM a = STM (TermList,Int) a
addSubexpConsts :: TermList -> [C.CncDef] -> [C.CncDef]
addSubexpConsts tree lins =
let opers = sortBy (\ (C.Lin f _) (C.Lin g _) -> compare f g)
[C.Lin (fid id) trm | (trm,(_,id)) <- list]
in map mkOne $ opers ++ lins
where
mkOne (C.Lin f trm) = (C.Lin f (recomp f trm))
recomp f t = case Map.lookup t tree of
Just (_,id) | fid id /= f -> C.F $ fid id -- not to replace oper itself
_ -> case t of
C.R ts -> C.R $ map (recomp f) ts
C.S ts -> C.S $ map (recomp f) ts
C.W s t -> C.W s (recomp f t)
C.P t p -> C.P (recomp f t) (recomp f p)
C.RP t p -> C.RP (recomp f t) (recomp f p)
C.L x t -> C.L x (recomp f t)
_ -> t
fid n = C.CId $ "_" ++ show n
list = Map.toList tree
getSubtermsMod :: [C.CncDef] -> TermM TermList
getSubtermsMod js = do
mapM (getInfo collectSubterms) js
(tree0,_) <- readSTM
return $ Map.filter (\ (nu,_) -> nu > 1) tree0
where
getInfo get (C.Lin f trm) = do
get trm
return ()
collectSubterms :: C.Term -> TermM ()
collectSubterms t = case t of
C.R ts -> do
mapM collectSubterms ts
add t
C.RP u v -> do
collectSubterms v
add t
C.S ts -> do
mapM collectSubterms ts
add t
C.W s u -> do
collectSubterms u
add t
C.P p u -> do
collectSubterms p
collectSubterms u
add t
_ -> return ()
where
add t = do
(ts,i) <- readSTM
let
((count,id),next) = case Map.lookup t ts of
Just (nu,id) -> ((nu+1,id), i)
_ -> ((1, i ), i+1)
writeSTM (Map.insert t (count,id) ts, next)

View File

@@ -5,13 +5,16 @@ import GF.Canon.CanonToGFCC
import GF.Canon.Look
import GF.Data.ErrM
import GF.Infra.Option
import qualified GF.Canon.GFCC.AbsGFCC as C
import qualified GF.GFCC.Macros as M
import qualified GF.GFCC.DataGFCC as D
import qualified GF.GFCC.AbsGFCC as C
import qualified GF.JavaScript.AbsJS as JS
import qualified GF.JavaScript.PrintJS as JS
import Control.Monad (mplus)
import Data.Maybe (fromMaybe)
import qualified Data.Map as Map
prCanon2js :: Options -> CanonGrammar -> String
prCanon2js opts gr = gfcc2js start $ mkCanon2gfcc gr
@@ -20,29 +23,37 @@ prCanon2js opts gr = gfcc2js start $ mkCanon2gfcc gr
`mplus` getOptVal grOpts gStartCat)
grOpts = errVal noOptions $ lookupOptionsCan gr
gfcc2js :: String -> C.Grammar -> String
gfcc2js start (C.Grm (C.Hdr n _) as cs) =
JS.printTree $ JS.Program $ abstract2js start n as ++ concatMap (concrete2js n) cs
gfcc2js :: String -> D.GFCC -> String
gfcc2js start gfcc =
JS.printTree $ JS.Program $ abstract2js start n as ++
concatMap (concrete2js n) cs
where
n = D.absname gfcc
as = D.abstract gfcc
cs = Map.assocs (D.concretes gfcc)
abstract2js :: String -> C.CId -> C.Abstract -> [JS.Element]
abstract2js start (C.CId n) (C.Abs ds) =
abstract2js :: String -> C.CId -> D.Abstr -> [JS.Element]
abstract2js start (C.CId n) ds =
[JS.ElStmt $ JS.SDeclOrExpr $ JS.Decl [JS.DInit a (new "Abstract" [JS.EStr start])]]
++ concatMap (absdef2js a) ds
++ concatMap (absdef2js a) (Map.assocs (D.funs ds))
where a = JS.Ident n
absdef2js :: JS.Ident -> C.AbsDef -> [JS.Element]
absdef2js a (C.Fun (C.CId f) (C.Typ args (C.CId cat)) _) =
absdef2js :: JS.Ident -> (C.CId,(C.Type,C.Exp)) -> [JS.Element]
absdef2js a (C.CId f,(typ,_)) =
let (args,C.CId cat) = M.catSkeleton typ in
[JS.ElStmt $ JS.SDeclOrExpr $ JS.DExpr $ JS.ECall (JS.EMember (JS.EVar a) (JS.Ident "addType"))
[JS.EStr f, JS.EArray [JS.EStr x | C.CId x <- args], JS.EStr cat]]
concrete2js :: C.CId -> C.Concrete -> [JS.Element]
concrete2js (C.CId a) (C.Cnc (C.CId c) ds) =
concrete2js :: C.CId -> (C.CId,D.Concr) -> [JS.Element]
concrete2js (C.CId a) (C.CId c, cnc) =
[JS.ElStmt $ JS.SDeclOrExpr $ JS.Decl [JS.DInit l (new "Concrete" [JS.EVar (JS.Ident a)])]]
++ concatMap (cncdef2js l) ds
where l = JS.Ident c
where
l = JS.Ident c
ds = Map.assocs $ D.lins cnc
cncdef2js :: JS.Ident -> C.CncDef -> [JS.Element]
cncdef2js l (C.Lin (C.CId f) t) =
cncdef2js :: JS.Ident -> (C.CId,C.Term) -> [JS.Element]
cncdef2js l (C.CId f, t) =
[JS.ElStmt $ JS.SDeclOrExpr $ JS.DExpr $ JS.ECall (JS.EMember (JS.EVar l) (JS.Ident "addRule")) [JS.EStr f, JS.EFun [children] [JS.SReturn (term2js l t)]]]
term2js :: JS.Ident -> C.Term -> JS.Expr