summaryrefslogtreecommitdiff
path: root/src/exper
diff options
context:
space:
mode:
authoraarne <aarne@cs.chalmers.se>2008-06-25 16:54:35 +0000
committeraarne <aarne@cs.chalmers.se>2008-06-25 16:54:35 +0000
commite9e80fc389365e24d4300d7d5390c7d833a96c50 (patch)
treef0b58473adaa670bd8fc52ada419d8cad470ee03 /src/exper
parentb96b36f43de3e2f8b58d5f539daa6f6d47f25870 (diff)
changed names of resource-1.3; added a note on homepage on release
Diffstat (limited to 'src/exper')
-rw-r--r--src/exper/Evaluate.hs461
-rw-r--r--src/exper/Optimize.hs274
2 files changed, 735 insertions, 0 deletions
diff --git a/src/exper/Evaluate.hs b/src/exper/Evaluate.hs
new file mode 100644
index 000000000..7c5fb4b6a
--- /dev/null
+++ b/src/exper/Evaluate.hs
@@ -0,0 +1,461 @@
+----------------------------------------------------------------------
+-- |
+-- Module : Evaluate
+-- Maintainer : AR
+-- Stability : (stable)
+-- Portability : (portable)
+--
+-- > CVS $Date: 2005/11/01 15:39:12 $
+-- > CVS $Author: aarne $
+-- > CVS $Revision: 1.19 $
+--
+-- Computation of source terms. Used in compilation and in @cc@ command.
+-----------------------------------------------------------------------------
+
+module GF.Compile.Evaluate (appEvalConcrete) where
+
+import GF.Data.Operations
+import GF.Grammar.Grammar
+import GF.Infra.Ident
+import GF.Data.Str
+import GF.Grammar.PrGrammar
+import GF.Infra.Modules
+import GF.Infra.Option
+import GF.Grammar.Macros
+import GF.Grammar.Lookup
+import GF.Grammar.Refresh
+import GF.Grammar.PatternMatch
+import GF.Grammar.Lockfield (isLockLabel) ----
+
+import GF.Grammar.AppPredefined
+
+import qualified Data.Map as Map
+
+import Data.List (nub,intersperse)
+import Control.Monad (liftM2, liftM)
+import Debug.Trace
+
+
+data EEnv = EEnv {
+ computd :: Map.Map (Ident,Ident) FTerm,
+ temp :: Int
+ }
+
+emptyEEnv = EEnv Map.empty 0
+
+lookupComputed :: (Ident,Ident) -> STM EEnv (Maybe FTerm)
+lookupComputed mc = do
+ env <- readSTM
+ return $ Map.lookup mc $ computd env
+
+updateComputed :: (Ident,Ident) -> FTerm -> STM EEnv ()
+updateComputed mc t = updateSTM (\e -> e{computd = Map.insert mc t (computd e)})
+
+getTemp :: STM EEnv Ident
+getTemp = do
+ env <- readSTM
+ updateSTM (\e -> e{temp = temp e + 1})
+ return $ identC ("#" ++ show (temp env))
+
+data FTerm =
+ FTC Term
+ | FTF (Term -> FTerm)
+
+prFTerm :: Integer -> FTerm -> String
+prFTerm i t = case t of
+ FTC t -> prt t
+ FTF f -> show i +++ "->" +++ prFTerm (i + 1) (f (EInt i))
+
+term2fterm t = case t of
+ Abs x b -> FTF (\t -> term2fterm (subst [(x,t)] b))
+ _ -> FTC t
+
+traceFTerm c ft = ft ----trace ("\n" ++ prt c +++ "=" +++ take 60 (prFTerm 0 ft)) ft
+
+fterm2term :: FTerm -> STM EEnv Term
+fterm2term t = case t of
+ FTC t -> return t
+ FTF f -> do
+ x <- getTemp
+ b <- fterm2term $ f (Vr x)
+ return $ Abs x b
+
+subst g t = case t of
+ Vr x -> maybe t id $ lookup x g
+ _ -> composSafeOp (subst g) t
+
+
+appFTerm :: FTerm -> [Term] -> FTerm
+appFTerm ft ts = case (ft,ts) of
+ (FTF f, x:xs) -> appFTerm (f x) xs
+ _ -> ft
+{-
+ (FTC _, []) -> ft
+ (FTC f, [a]) -> case appPredefined (App f a) of
+ Ok (t,_) -> FTC t
+ _ -> error $ "error: appFTerm" +++ prFTerm 0 ft +++ unwords (map prt ts)
+ _ -> error $ "error: appFTerm" +++ prFTerm 0 ft +++ unwords (map prt ts)
+-}
+
+apps :: Term -> (Term,[Term])
+apps t = case t of
+ App f a -> (f',xs ++ [a]) where (f',xs) = apps f
+ _ -> (t,[])
+
+appEvalConcrete gr bt = liftM fst $ appSTM (evalConcrete gr bt) emptyEEnv
+
+evalConcrete :: SourceGrammar -> BinTree Ident Info -> STM EEnv (BinTree Ident Info)
+evalConcrete gr mo = mapMTree evaldef mo where
+
+ evaldef (f,info) = case info of
+ CncFun (mt@(Just (_,ty@(cont,val)))) pde ppr ->
+ evalIn ("\nerror in linearization of function" +++ prt f +++ ":") $
+ do
+ pde' <- case pde of
+ Yes de -> do
+ liftM yes $ pEval ty de
+ _ -> return pde
+ --- ppr' <- liftM yes $ evalPrintname gr c ppr pde'
+ return $ (f, CncFun mt pde' ppr) -- only cat in type actually needed
+
+ _ -> return (f,info)
+
+ pEval (context,val) trm = do ---- errIn ("parteval" +++ prt_ trm) $ do
+ let
+ vars = map fst context
+ args = map Vr vars
+ subst = [(v, Vr v) | v <- vars]
+ trm1 = mkApp trm args
+ trm3 <- recordExpand val trm1 >>= comp subst
+ return $ mkAbs vars trm3
+
+ recordExpand typ trm = case unComputed typ of
+ RecType tys -> case trm of
+ FV rs -> return $ FV [R [assign lab (P r lab) | (lab,_) <- tys] | r <- rs]
+ _ -> return $ R [assign lab (P trm lab) | (lab,_) <- tys]
+ _ -> return trm
+
+ comp g t = case t of
+
+ Q (IC "Predef") _ -> trace ("\nPredef:\n" ++ prt t) $ return t
+
+ Q p c -> do
+ md <- lookupComputed (p,c)
+ case md of
+ Nothing -> do
+ d <- lookRes (p,c)
+ updateComputed (p,c) $ traceFTerm c $ term2fterm d
+ return d
+ Just d -> fterm2term d >>= comp g
+ App f a -> case apps t of
+ (h@(Q p c),xs) | p == IC "Predef" -> do
+ xs' <- mapM (comp g) xs
+ (t',b) <- stmErr $ appPredefined (foldl App h xs')
+ if b then return t' else comp g t'
+ (h@(Q p c),xs) -> do
+ xs' <- mapM (comp g) xs
+ md <- lookupComputed (p,c)
+ case md of
+ Just ft -> do
+ t <- fterm2term $ appFTerm ft xs'
+ comp g t
+ Nothing -> do
+ d <- lookRes (p,c)
+ let ft = traceFTerm c $ term2fterm d
+ updateComputed (p,c) ft
+ t' <- fterm2term $ appFTerm ft xs'
+ comp g t'
+ _ -> do
+ f' <- comp g f
+ a' <- comp g a
+ case (f',a') of
+ (Abs x b,_) -> comp (ext x a' g) b
+ (QC _ _,_) -> returnC $ App f' a'
+ (FV fs, _) -> mapM (\c -> comp g (App c a')) fs >>= return . variants
+ (_, FV as) -> mapM (\c -> comp g (App f' c)) as >>= return . variants
+
+ (Alias _ _ d, _) -> comp g (App d a')
+
+ (S (T i cs) e,_) -> prawitz g i (flip App a') cs e
+
+ _ -> do
+ (t',b) <- stmErr $ appPredefined (App f' a')
+ if b then return t' else comp g t'
+
+
+ Vr x -> do
+ t' <- maybe (prtRaise (
+ "context" +++ show g +++ ": no value given to variable") x) return $ lookup x g
+ case t' of
+ _ | t == t' -> return t
+ _ -> comp g t'
+
+ Abs x b -> do
+ b' <- comp (ext x (Vr x) g) b
+ return $ Abs x b'
+
+ Let (x,(_,a)) b -> do
+ a' <- comp g a
+ comp (ext x a' g) b
+
+ Prod x a b -> do
+ a' <- comp g a
+ b' <- comp (ext x (Vr x) g) b
+ return $ Prod x a' b'
+
+ P t l | isLockLabel l -> return $ R []
+ ---- a workaround 18/2/2005: take this away and find the reason
+ ---- why earlier compilation destroys the lock field
+
+
+ P t l -> do
+ t' <- comp g t
+ case t' of
+ FV rs -> mapM (\c -> comp g (P c l)) rs >>= returnC . variants
+ R r -> maybe
+ (prtRaise (prt t' ++ ": no value for label") l) (comp g . snd) $
+ lookup l r
+
+ ExtR a (R b) -> case lookup l b of ----comp g (P (R b) l) of
+ Just (_,v) -> comp g v
+ _ -> comp g (P a l)
+
+ S (T i cs) e -> prawitz g i (flip P l) cs e
+
+ _ -> returnC $ P t' l
+
+ S t@(T _ cc) v -> do
+ v' <- comp g v
+ case v' of
+ FV vs -> do
+ ts' <- mapM (comp g . S t) vs
+ return $ variants ts'
+ _ -> case matchPattern cc v' of
+ Ok (c,g') -> comp (g' ++ g) c
+ _ | isCan v' -> prtRaise ("missing case" +++ prt v' +++ "in") t
+ _ -> do
+ t' <- comp g t
+ return $ S t' v' -- if v' is not canonical
+
+ S t v -> do
+ t' <- comp g t
+ v' <- comp g v
+ case t' of
+ T _ [(PV IW,c)] -> comp g c --- an optimization
+ T _ [(PT _ (PV IW),c)] -> comp g c
+
+ T _ [(PV z,c)] -> comp (ext z v' g) c --- another optimization
+ T _ [(PT _ (PV z),c)] -> comp (ext z v' g) c
+
+ FV ccs -> mapM (\c -> comp g (S c v')) ccs >>= returnC . variants
+
+ V ptyp ts -> do
+ vs <- stmErr $ allParamValues gr ptyp
+ ps <- stmErr $ mapM term2patt vs
+ let cc = zip ps ts
+ case v' of
+ FV vs -> mapM (\c -> comp g (S t' c)) vs >>= returnC . variants
+ _ -> case matchPattern cc v' of
+ Ok (c,g') -> comp (g' ++ g) c
+ _ | isCan v' -> prtRaise ("missing case" +++ prt v' +++ "in") t
+ _ -> return $ S t' v' -- if v' is not canonical
+
+ T _ cc -> case v' of
+ FV vs -> mapM (\c -> comp g (S t' c)) vs >>= returnC . variants
+ _ -> case matchPattern cc v' of
+ Ok (c,g') -> comp (g' ++ g) c
+ _ | isCan v' -> prtRaise ("missing case" +++ prt v' +++ "in") t
+ _ -> return $ S t' v' -- if v' is not canonical
+
+ Alias _ _ d -> comp g (S d v')
+
+ S (T i cs) e -> prawitz g i (flip S v') cs e
+
+ _ -> returnC $ S t' v'
+
+ -- normalize away empty tokens
+ K "" -> return Empty
+
+ -- glue if you can
+ Glue x0 y0 -> do
+ x <- comp g x0
+ y <- comp g y0
+ case (x,y) of
+ (Alias _ _ d, y) -> comp g $ Glue d y
+ (x, Alias _ _ d) -> comp g $ Glue x d
+
+ (S (T i cs) e, s) -> prawitz g i (flip Glue s) cs e
+ (s, S (T i cs) e) -> prawitz g i (Glue s) cs e
+ (_,Empty) -> return x
+ (Empty,_) -> return y
+ (K a, K b) -> return $ K (a ++ b)
+ (_, Alts (d,vs)) -> do
+---- (K a, Alts (d,vs)) -> do
+ let glx = Glue x
+ comp g $ Alts (glx d, [(glx v,c) | (v,c) <- vs])
+ (Alts _, ka) -> checks [do
+ y' <- stmErr $ strsFromTerm ka
+---- (Alts _, K a) -> checks [do
+ x' <- stmErr $ strsFromTerm x -- this may fail when compiling opers
+ return $ variants [
+ foldr1 C (map K (str2strings (glueStr v u))) | v <- x', u <- y']
+---- foldr1 C (map K (str2strings (glueStr v (str a)))) | v <- x']
+ ,return $ Glue x y
+ ]
+ (FV ks,_) -> do
+ kys <- mapM (comp g . flip Glue y) ks
+ return $ variants kys
+ (_,FV ks) -> do
+ xks <- mapM (comp g . Glue x) ks
+ return $ variants xks
+
+ _ -> do
+ mapM_ checkNoArgVars [x,y]
+ r <- composOp (comp g) t
+ returnC r
+
+ Alts _ -> do
+ r <- composOp (comp g) t
+ returnC r
+
+ -- remove empty
+ C a b -> do
+ a' <- comp g a
+ b' <- comp g b
+ case (a',b') of
+ (Alts _, K a) -> checks [do
+ as <- stmErr $ strsFromTerm a' -- this may fail when compiling opers
+ return $ variants [
+ foldr1 C (map K (str2strings (plusStr v (str a)))) | v <- as]
+ ,
+ return $ C a' b'
+ ]
+ (Empty,_) -> returnC b'
+ (_,Empty) -> returnC a'
+ _ -> returnC $ C a' b'
+
+ -- reduce free variation as much as you can
+ FV ts -> mapM (comp g) ts >>= returnC . variants
+
+ -- merge record extensions if you can
+ ExtR r s -> do
+ r' <- comp g r
+ s' <- comp g s
+ case (r',s') of
+ (Alias _ _ d, _) -> comp g $ ExtR d s'
+ (_, Alias _ _ d) -> comp g $ Glue r' d
+
+ (R rs, R ss) -> stmErr $ plusRecord r' s'
+ (RecType rs, RecType ss) -> stmErr $ plusRecType r' s'
+ _ -> return $ ExtR r' s'
+
+ -- case-expand tables
+ -- if already expanded, don't expand again
+ T i@(TComp _) cs -> do
+ -- if there are no variables, don't even go inside
+ cs' <- if (null g) then return cs else mapPairsM (comp g) cs
+ return $ T i cs'
+
+ --- this means some extra work; should implement TSh directly
+ TSh i cs -> comp g $ T i [(p,v) | (ps,v) <- cs, p <- ps]
+
+ T i cs -> do
+ pty0 <- stmErr $ getTableType i
+ ptyp <- comp g pty0
+ case allParamValues gr ptyp of
+ Ok vs -> do
+
+ cs' <- mapM (compBranchOpt g) cs
+ sts <- stmErr $ mapM (matchPattern cs') vs
+ ts <- mapM (\ (c,g') -> comp (g' ++ g) c) sts
+ ps <- stmErr $ mapM term2patt vs
+ let ps' = ps --- PT ptyp (head ps) : tail ps
+ return $ --- V ptyp ts -- to save space, just course of values
+ T (TComp ptyp) (zip ps' ts)
+ _ -> do
+ cs' <- mapM (compBranch g) cs
+ return $ T i cs' -- happens with variable types
+
+ -- otherwise go ahead
+ _ -> composOp (comp g) t >>= returnC
+
+ lookRes (p,c) = case lookupResDefKind gr p c of
+ Ok (t,_) | noExpand p -> return t
+ Ok (t,0) -> comp [] t
+ Ok (t,_) -> return t
+ Bad s -> raise s
+
+ noExpand p = errVal False $ do
+ mo <- lookupModMod gr p
+ return $ case getOptVal (iOpts (flags mo)) useOptimizer of
+ Just "noexpand" -> True
+ _ -> False
+
+ prtRaise s t = raise (s +++ prt t)
+
+ ext x a g = (x,a):g
+
+ returnC = return --- . computed
+
+ variants ts = case nub ts of
+ [t] -> t
+ ts -> FV ts
+
+ isCan v = case v of
+ Con _ -> True
+ QC _ _ -> True
+ App f a -> isCan f && isCan a
+ R rs -> all (isCan . snd . snd) rs
+ _ -> False
+
+ compBranch g (p,v) = do
+ let g' = contP p ++ g
+ v' <- comp g' v
+ return (p,v')
+
+ compBranchOpt g c@(p,v) = case contP p of
+ [] -> return c
+ _ -> compBranch g c
+---- _ -> err (const (return c)) return $ compBranch g c
+
+ contP p = case p of
+ PV x -> [(x,Vr x)]
+ PC _ ps -> concatMap contP ps
+ PP _ _ ps -> concatMap contP ps
+ PT _ p -> contP p
+ PR rs -> concatMap (contP . snd) rs
+
+ PAs x p -> (x,Vr x) : contP p
+
+ PSeq p q -> concatMap contP [p,q]
+ PAlt p q -> concatMap contP [p,q]
+ PRep p -> contP p
+ PNeg p -> contP p
+
+ _ -> []
+
+ prawitz g i f cs e = do
+ cs' <- mapM (compBranch g) [(p, f v) | (p,v) <- cs]
+ return $ S (T i cs') e
+
+-- | argument variables cannot be glued
+checkNoArgVars :: Term -> STM EEnv Term
+checkNoArgVars t = case t of
+ Vr (IA _) -> raise $ glueErrorMsg $ prt t
+ Vr (IAV _) -> raise $ glueErrorMsg $ prt t
+ _ -> composOp checkNoArgVars t
+
+glueErrorMsg s =
+ "Cannot glue (+) term with run-time variable" +++ s ++ "." ++++
+ "Use Prelude.bind instead."
+
+stmErr :: Err a -> STM s a
+stmErr e = stm (\s -> do
+ v <- e
+ return (v,s)
+ )
+
+evalIn :: String -> STM s a -> STM s a
+evalIn msg st = stm $ \s -> case appSTM st s of
+ Bad e -> Bad $ msg ++++ e
+ Ok vs -> Ok vs
diff --git a/src/exper/Optimize.hs b/src/exper/Optimize.hs
new file mode 100644
index 000000000..93346bc70
--- /dev/null
+++ b/src/exper/Optimize.hs
@@ -0,0 +1,274 @@
+----------------------------------------------------------------------
+-- |
+-- Module : Optimize
+-- Maintainer : AR
+-- Stability : (stable)
+-- Portability : (portable)
+--
+-- > CVS $Date: 2005/09/16 13:56:13 $
+-- > CVS $Author: aarne $
+-- > CVS $Revision: 1.18 $
+--
+-- Top-level partial evaluation for GF source modules.
+-----------------------------------------------------------------------------
+
+module GF.Compile.Optimize (optimizeModule) where
+
+import GF.Grammar.Grammar
+import GF.Infra.Ident
+import GF.Infra.Modules
+import GF.Grammar.PrGrammar
+import GF.Grammar.Macros
+import GF.Grammar.Lookup
+import GF.Grammar.Refresh
+import GF.Grammar.Compute
+import GF.Compile.BackOpt
+import GF.Compile.CheckGrammar
+import GF.Compile.Update
+
+import GF.Compile.Evaluate
+
+import GF.Data.Operations
+import GF.Infra.CheckM
+import GF.Infra.Option
+
+import Control.Monad
+import Data.List
+
+-- | partial evaluation of concrete syntax. AR 6\/2001 -- 16\/5\/2003 -- 5\/2\/2005.
+-- only do this for resource: concrete is optimized in gfc form
+optimizeModule :: Options -> [(Ident,SourceModInfo)] -> (Ident,SourceModInfo) ->
+ Err (Ident,SourceModInfo)
+optimizeModule opts ms mo@(_,mi) = case mi of
+ ModMod m0@(Module mt st fs me ops js) | st == MSComplete && isModRes m0 -> do
+ mo1 <- evalModule oopts ms mo
+ return $ case optim of
+ "parametrize" -> shareModule paramOpt mo1 -- parametrization and sharing
+ "values" -> shareModule valOpt mo1 -- tables as courses-of-values
+ "share" -> shareModule shareOpt mo1 -- sharing of branches
+ "all" -> shareModule allOpt mo1 -- first parametrize then values
+ "none" -> mo1 -- no optimization
+ _ -> mo1 -- none; default for src
+ _ -> evalModule oopts ms mo
+ where
+ oopts = addOptions opts (iOpts (flagsModule mo))
+ optim = maybe "all" id $ getOptVal oopts useOptimizer
+
+evalModule :: Options -> [(Ident,SourceModInfo)] -> (Ident,SourceModInfo) ->
+ Err (Ident,SourceModInfo)
+evalModule oopts ms mo@(name,mod) = case mod of
+
+ ModMod m0@(Module mt st fs me ops js) | st == MSComplete -> case mt of
+{-
+ -- now: don't optimize resource
+
+ _ | isModRes m0 -> do
+ let deps = allOperDependencies name js
+ ids <- topoSortOpers deps
+ MGrammar (mod' : _) <- foldM evalOp gr ids
+ return $ mod'
+-}
+ MTConcrete a -> do
+-----
+ js0 <- appEvalConcrete gr js
+ js' <- mapMTree (evalCncInfo oopts gr name a) js0 ---- <- gr0 6/12/2005
+ return $ (name, ModMod (Module mt st fs me ops js'))
+
+ _ -> return $ (name,mod)
+ _ -> return $ (name,mod)
+ where
+ gr0 = MGrammar $ ms
+ gr = MGrammar $ (name,mod) : ms
+
+ evalOp g@(MGrammar ((_, ModMod m) : _)) i = do
+ info <- lookupTree prt i $ jments m
+ info' <- evalResInfo oopts gr (i,info)
+ return $ updateRes g name i info'
+
+-- | only operations need be compiled in a resource, and this is local to each
+-- definition since the module is traversed in topological order
+evalResInfo :: Options -> SourceGrammar -> (Ident,Info) -> Err Info
+evalResInfo oopts gr (c,info) = case info of
+
+ ResOper pty pde -> eIn "operation" $ do
+ pde' <- case pde of
+ Yes de | optres -> liftM yes $ comp de
+ _ -> return pde
+ return $ ResOper pty pde'
+
+ _ -> return info
+ where
+ comp = if optres then computeConcrete gr else computeConcreteRec gr
+ eIn cat = errIn ("Error optimizing" +++ cat +++ prt c +++ ":")
+ optim = maybe "all" id $ getOptVal oopts useOptimizer
+ optres = case optim of
+ "noexpand" -> False
+ _ -> True
+
+
+evalCncInfo ::
+ Options -> SourceGrammar -> Ident -> Ident -> (Ident,Info) -> Err (Ident,Info)
+evalCncInfo opts gr cnc abs (c,info) = errIn ("optimizing" +++ prt c) $ case info of
+
+ CncCat ptyp pde ppr -> do
+
+ pde' <- case (ptyp,pde) of
+ (Yes typ, Yes de) ->
+ liftM yes $ pEval ([(varStr, typeStr)], typ) de
+ (Yes typ, Nope) ->
+ liftM yes $ mkLinDefault gr typ >>= partEval noOptions gr ([(varStr, typeStr)],typ)
+ (May b, Nope) ->
+ return $ May b
+ _ -> return pde -- indirection
+
+ ppr' <- liftM yes $ evalPrintname gr c ppr (yes $ K $ prt c)
+
+ return (c, CncCat ptyp pde' ppr')
+
+ CncFun (mt@(Just (_,ty@(cont,val)))) pde ppr ->
+ eIn ("linearization in type" +++ prt (mkProd (cont,val,[])) ++++ "of function") $ do
+ pde' <- case pde of
+----- Yes de -> do
+----- liftM yes $ pEval ty de
+ _ -> return pde
+ ppr' <- liftM yes $ evalPrintname gr c ppr pde'
+ return $ (c, CncFun mt pde' ppr') -- only cat in type actually needed
+
+ _ -> return (c,info)
+ where
+ pEval = partEval opts gr
+ eIn cat = errIn ("Error optimizing" +++ cat +++ prt c +++ ":")
+
+-- | the main function for compiling linearizations
+partEval :: Options -> SourceGrammar -> (Context,Type) -> Term -> Err Term
+partEval opts gr (context, val) trm = errIn ("parteval" +++ prt_ trm) $ do
+ let vars = map fst context
+ args = map Vr vars
+ subst = [(v, Vr v) | v <- vars]
+ trm1 = mkApp trm args
+ trm3 <- if globalTable
+ then etaExpand trm1 >>= comp subst >>= outCase subst
+ else etaExpand trm1 >>= comp subst
+ return $ mkAbs vars trm3
+
+ where
+
+ globalTable = oElem showAll opts --- i -all
+
+ comp g t = {- refreshTerm t >>= -} computeTerm gr g t
+
+ etaExpand t = recordExpand val t --- >>= caseEx -- done by comp
+
+ outCase subst t = do
+ pts <- getParams context
+ let (args,ptyps) = unzip $ filter (flip occur t . fst) pts
+ if null args
+ then return t
+ else do
+ let argtyp = RecType $ tuple2recordType ptyps
+ let pvars = map (Vr . zIdent . prt) args -- gets eliminated
+ patt <- term2patt $ R $ tuple2record $ pvars
+ let t' = replace (zip args pvars) t
+ t1 <- comp subst $ T (TTyped argtyp) [(patt, t')]
+ return $ S t1 $ R $ tuple2record args
+
+ --- notice: this assumes that all lin types follow the "old JFP style"
+ getParams = liftM concat . mapM getParam
+ getParam (argv,RecType rs) = return
+ [(P (Vr argv) lab, ptyp) | (lab,ptyp) <- rs, not (isLinLabel lab)]
+ ---getParam (_,ty) | ty==typeStr = return [] --- in lindef
+ getParam (av,ty) =
+ Bad ("record type expected not" +++ prt ty +++ "for" +++ prt av)
+ --- all lin types are rec types
+
+ replace :: [(Term,Term)] -> Term -> Term
+ replace reps trm = case trm of
+ -- this is the important case
+ P _ _ -> maybe trm id $ lookup trm reps
+ _ -> composSafeOp (replace reps) trm
+
+ occur t trm = case trm of
+
+ -- this is the important case
+ P _ _ -> t == trm
+ S x y -> occur t y || occur t x
+ App f x -> occur t x || occur t f
+ Abs _ f -> occur t f
+ R rs -> any (occur t) (map (snd . snd) rs)
+ T _ cs -> any (occur t) (map snd cs)
+ C x y -> occur t x || occur t y
+ Glue x y -> occur t x || occur t y
+ ExtR x y -> occur t x || occur t y
+ FV ts -> any (occur t) ts
+ V _ ts -> any (occur t) ts
+ Let (_,(_,x)) y -> occur t x || occur t y
+ _ -> False
+
+
+-- here we must be careful not to reduce
+-- variants {{s = "Auto" ; g = N} ; {s = "Wagen" ; g = M}}
+-- {s = variants {"Auto" ; "Wagen"} ; g = variants {N ; M}} ;
+
+recordExpand :: Type -> Term -> Err Term
+recordExpand typ trm = case unComputed typ of
+ RecType tys -> case trm of
+ FV rs -> return $ FV [R [assign lab (P r lab) | (lab,_) <- tys] | r <- rs]
+ _ -> return $ R [assign lab (P trm lab) | (lab,_) <- tys]
+ _ -> return trm
+
+
+-- | auxiliaries for compiling the resource
+
+mkLinDefault :: SourceGrammar -> Type -> Err Term
+mkLinDefault gr typ = do
+ case unComputed typ of
+ RecType lts -> mapPairsM mkDefField lts >>= (return . Abs varStr . R . mkAssign)
+ _ -> prtBad "linearization type must be a record type, not" typ
+ where
+ mkDefField typ = case unComputed typ of
+ Table p t -> do
+ t' <- mkDefField t
+ let T _ cs = mkWildCases t'
+ return $ T (TWild p) cs
+ Sort "Str" -> return $ Vr varStr
+ QC q p -> lookupFirstTag gr q p
+ RecType r -> do
+ let (ls,ts) = unzip r
+ ts' <- mapM mkDefField ts
+ return $ R $ [assign l t | (l,t) <- zip ls ts']
+ _ | isTypeInts typ -> return $ EInt 0 -- exists in all as first val
+ _ -> prtBad "linearization type field cannot be" typ
+
+-- | Form the printname: if given, compute. If not, use the computed
+-- lin for functions, cat name for cats (dispatch made in evalCncDef above).
+--- We cannot use linearization at this stage, since we do not know the
+--- defaults we would need for question marks - and we're not yet in canon.
+evalPrintname :: SourceGrammar -> Ident -> MPr -> Perh Term -> Err Term
+evalPrintname gr c ppr lin =
+ case ppr of
+ Yes pr -> comp pr
+ _ -> case lin of
+ Yes t -> return $ K $ clean $ prt $ oneBranch t ---- stringFromTerm
+ _ -> return $ K $ prt c ----
+ where
+ comp = computeConcrete gr
+
+ oneBranch t = case t of
+ Abs _ b -> oneBranch b
+ R (r:_) -> oneBranch $ snd $ snd r
+ T _ (c:_) -> oneBranch $ snd c
+ V _ (c:_) -> oneBranch c
+ FV (t:_) -> oneBranch t
+ C x y -> C (oneBranch x) (oneBranch y)
+ S x _ -> oneBranch x
+ P x _ -> oneBranch x
+ Alts (d,_) -> oneBranch d
+ _ -> t
+
+ --- very unclean cleaner
+ clean s = case s of
+ '+':'+':' ':cs -> clean cs
+ '"':cs -> clean cs
+ c:cs -> c: clean cs
+ _ -> s
+