[project @ 2000-12-15 17:38:45 by sewardj]
[ghc-hetmet.git] / ghc / compiler / ghci / StgInterp.lhs
index 1bf01da..8428814 100644 (file)
@@ -6,9 +6,26 @@
 \begin{code}
 
 module StgInterp ( 
-    ClosureEnv, ItblEnv,
-    linkIModules,
-    stgToInterpSyn,
+
+    ClosureEnv, ItblEnv, 
+    filterNameMap,      -- :: [ModuleName] -> FiniteMap Name a 
+                       -- -> FiniteMap Name a
+
+    linkIModules,      -- :: ItblEnv -> ClosureEnv
+                       -- -> [([UnlinkedIBind], ItblEnv)]
+                       -- -> IO ([LinkedIBind], ItblEnv, ClosureEnv)
+
+    iExprToHValue,     --  :: ItblEnv -> ClosureEnv 
+                       --  -> UnlinkedIExpr -> HValue
+
+    stgBindsToInterpSyn,-- :: [StgBinding] 
+                       -- -> [TyCon] -> [Class] 
+                       -- -> IO ([UnlinkedIBind], ItblEnv)
+
+    stgExprToInterpSyn, -- :: StgExpr
+                       -- -> IO UnlinkedIExpr
+
+    interp             -- :: LinkedIExpr -> HValue
  ) where
 
 {- -----------------------------------------------------------------------------
@@ -25,10 +42,14 @@ module StgInterp (
    - converting string literals to Addr# is horrible and introduces
      a memory leak.  See if something can be done about this.
 
+   - lots of assumptions about word size vs. double size etc.
+
 ----------------------------------------------------------------------------- -}
 
 #include "HsVersions.h"
 
+
+
 import Linker
 import Id              ( Id, idPrimRep )
 import Outputable
@@ -39,18 +60,15 @@ import Literal              ( Literal(..) )
 import Type            ( Type, typePrimRep, deNoteType, repType, funResultTy )
 import DataCon         ( DataCon, dataConTag, dataConRepArgTys )
 import ClosureInfo     ( mkVirtHeapOffsets )
-import Name            ( toRdrName )
+import Module          ( ModuleName, moduleName )
+import RdrName
+import Name            hiding (filterNameEnv)
+import Util
 import UniqFM
 import UniqSet
 
-import {-# SOURCE #-} MCI_make_constr
+--import {-# SOURCE #-} MCI_make_constr
 
-import IOExts          ( unsafePerformIO ) -- ToDo: remove
-import PrelGHC         --( unsafeCoerce#, dataToTag#,
-                       --  indexPtrOffClosure#, indexWordOffClosure# )
-import PrelAddr        ( Addr(..) )
-import PrelFloat       ( Float(..), Double(..) )
-import Bits
 import FastString
 import GlaExts         ( Int(..) )
 import Module          ( moduleNameFS )
@@ -59,81 +77,94 @@ import TyCon                ( TyCon, isDataTyCon, tyConDataCons, tyConFamilySize )
 import Class           ( Class, classTyCon )
 import InterpSyn
 import StgSyn
-import Addr
-import RdrName         ( RdrName, rdrNameModule, rdrNameOcc )
 import FiniteMap
-import Panic           ( panic )
 import OccName         ( occNameString )
+import ErrUtils                ( showPass, dumpIfSet_dyn )
+import CmdLineOpts     ( DynFlags, DynFlag(..) )
+import Panic           ( panic )
 
+import IOExts
+import Addr
+import Bits
 import Foreign
 import CTypes
 
+import IO
+
+import PrelGHC         --( unsafeCoerce#, dataToTag#,
+                       --  indexPtrOffClosure#, indexWordOffClosure# )
+import PrelAddr        ( Addr(..) )
+import PrelFloat       ( Float(..), Double(..) )
+
+
+#if 1
+interp = panic "interp"
+stgExprToInterpSyn = panic "stgExprToInterpSyn"
+stgBindsToInterpSyn = panic "stgBindsToInterpSyn"
+iExprToHValue = panic "iExprToHValue"
+linkIModules = panic "linkIModules"
+filterNameMap = panic "filterNameMap"
+type ItblEnv    = FiniteMap Name (Ptr StgInfoTable)
+type ClosureEnv = FiniteMap Name HValue
+data StgInfoTable = StgInfoTable {
+   ptrs :: Word16,
+   nptrs :: Word16,
+   srtlen :: Word16,
+   tipe :: Word16,
+   code0, code1, code2, code3, code4, code5, code6, code7 :: Word8
+}
+
+#else
+
 -- ---------------------------------------------------------------------------
 -- Environments needed by the linker
 -- ---------------------------------------------------------------------------
 
-type ItblEnv    = FiniteMap RdrName (Ptr StgInfoTable)
-type ClosureEnv = FiniteMap RdrName HValue
+type ItblEnv    = FiniteMap Name (Ptr StgInfoTable)
+type ClosureEnv = FiniteMap Name HValue
 emptyClosureEnv = emptyFM
 
+-- remove all entries for a given set of modules from the environment
+filterNameMap :: [ModuleName] -> FiniteMap Name a -> FiniteMap Name a
+filterNameMap mods env 
+   = filterFM (\n _ -> moduleName (nameModule n) `notElem` mods) env
+
 -- ---------------------------------------------------------------------------
--- Run our STG program through the interpreter
+-- Turn an UnlinkedIExpr into a value we can run, for the interpreter
 -- ---------------------------------------------------------------------------
 
-#if 0
--- To be nuked at some point soon.
-runStgI :: [TyCon] -> [Class] -> [StgBinding] -> IO Int
-
--- the bindings need to have a binding for stgMain, and the
--- body of it had better represent something of type Int# -> Int#
-runStgI tycons classes stgbinds
-   = do 
-       let unlinked_binds = concatMap (translateBind emptyUniqSet) stgbinds
-            
-{-
-        let dbg_txt 
-               = "-------------------- Unlinked Binds --------------------\n" 
-                 ++ showSDoc (vcat (map (\bind -> pprIBind bind $$ char ' ')
-                        unlinked_binds))
-
-        hPutStr stderr dbg_txt
--}
-        (linked_binds, ie, ce) <-
-               linkIModules emptyFM emptyFM [(tycons,unlinked_binds)]
-
-        let dbg_txt 
-               = "-------------------- Linked Binds --------------------\n" 
-                 ++ showSDoc (vcat (map (\bind -> pprIBind bind $$ char ' ') 
-                       linked_binds))
-
-        hPutStr stderr dbg_txt
-
-        let stgMain
-               = case [rhs | IBind v rhs <- linked_binds, showSDoc (ppr v) == "stgMain"] of
-                    (b:_) -> b
-                    []    -> error "\n\nCan't find `stgMain'.  Giving up.\n\n"  
-
-        let result 
-               = I# (evalI (AppII stgMain (LitI 0#))
-                           emptyUFM{-initial de-}
-                    )
-        return result
-#endif
+iExprToHValue :: ItblEnv -> ClosureEnv -> UnlinkedIExpr -> IO HValue
+iExprToHValue ie ce expr
+   = do linked_expr <- linkIExpr ie ce expr
+       return (interp linked_expr)
 
 -- ---------------------------------------------------------------------------
 -- Convert STG to an unlinked interpretable
 -- ---------------------------------------------------------------------------
 
 -- visible from outside
-stgToInterpSyn :: [StgBinding] 
-              -> [TyCon] -> [Class] 
-              -> IO ([UnlinkedIBind], ItblEnv)
-stgToInterpSyn binds local_tycons local_classes
- = do let ibinds = concatMap (translateBind emptyUniqSet) binds
+stgBindsToInterpSyn :: DynFlags
+                   -> [StgBinding] 
+                   -> [TyCon] -> [Class] 
+                   -> IO ([UnlinkedIBind], ItblEnv)
+stgBindsToInterpSyn dflags binds local_tycons local_classes
+ = do showPass dflags "StgToInterp"
+      let ibinds = concatMap (translateBind emptyUniqSet) binds
       let tycs   = local_tycons ++ map classTyCon local_classes
+      dumpIfSet_dyn dflags Opt_D_dump_InterpSyn
+        "Convert To InterpSyn" (vcat (map pprIBind ibinds))
       itblenv <- mkITbls tycs
       return (ibinds, itblenv)
 
+stgExprToInterpSyn :: DynFlags
+                  -> StgExpr
+                  -> IO UnlinkedIExpr
+stgExprToInterpSyn dflags expr
+ = do showPass dflags "StgToInterp"
+      let iexpr = stg2expr emptyUniqSet expr
+      dumpIfSet_dyn dflags Opt_D_dump_InterpSyn
+       "Convert To InterpSyn" (pprIExpr iexpr)
+      return iexpr
 
 translateBind :: UniqSet Id -> StgBinding -> [UnlinkedIBind]
 translateBind ie (StgNonRec v e)  = [IBind v (rhs2expr ie e)]
@@ -150,7 +181,8 @@ rhs2expr ie (StgRhsClosure ccs binfo srt fvs uflag args rhs)
         rhsExpr = stg2expr (addListToUniqSet ie args) rhs
         rhsRep  = repOfStgExpr rhs
         mkLambdas [] = rhsExpr
-        mkLambdas (v:vs) = mkLam (repOfId v) rhsRep v (mkLambdas vs)
+       mkLambdas [v] = mkLam (repOfId v) rhsRep v rhsExpr
+        mkLambdas (v:vs) = mkLam (repOfId v) RepP v (mkLambdas vs)
 rhs2expr ie (StgRhsCon ccs dcon args)
    = conapp2expr ie dcon args
 
@@ -158,7 +190,7 @@ conapp2expr :: UniqSet Id -> DataCon -> [StgArg] -> UnlinkedIExpr
 conapp2expr ie dcon args
    = mkConApp con_rdrname reps exprs
      where
-       con_rdrname = toRdrName dcon
+       con_rdrname = getName dcon
         exprs       = map (arg2expr ie) inHeapOrder
         reps        = map repOfArg inHeapOrder
         inHeapOrder = toHeapOrder args
@@ -170,18 +202,14 @@ conapp2expr ie dcon args
              in
                  rearranged
 
-foreign label "PrelBase_Izh_con_info" prelbase_Izh_con_info :: Addr
-
 -- Handle most common cases specially; do the rest with a generic
 -- mechanism (deferred till later :)
-mkConApp :: RdrName -> [Rep] -> [UnlinkedIExpr] -> UnlinkedIExpr
+mkConApp :: Name -> [Rep] -> [UnlinkedIExpr] -> UnlinkedIExpr
 mkConApp nm []               []         = ConApp    nm
 mkConApp nm [RepI]           [a1]       = ConAppI   nm a1
 mkConApp nm [RepP]           [a1]       = ConAppP   nm a1
 mkConApp nm [RepP,RepP]      [a1,a2]    = ConAppPP  nm a1 a2
-mkConApp nm [RepP,RepP,RepP] [a1,a2,a3] = ConAppPPP nm a1 a2 a3
-mkConApp nm reps args
-   = pprPanic "StgInterp.mkConApp: unhandled reps" (hsep (map ppr reps))
+mkConApp nm reps args  = ConAppGen nm args
 
 mkLam RepP RepP = LamPP
 mkLam RepI RepP = LamIP
@@ -221,6 +249,9 @@ primRep2Rep primRep
        ArrayRep      -> RepP
        ByteArrayRep  -> RepP
 
+       FloatRep      -> RepF
+       DoubleRep     -> RepD
+
         other -> pprPanic "primRep2Rep" (ppr other)
 
 repOfStgExpr :: StgExpr -> Rep
@@ -294,10 +325,11 @@ lit2expr lit
                -- Addr#.  So, copy the string into C land and introduce a 
                -- memory leak at the same time.
                  let n = I# l in
-                 case unsafePerformIO (do a <- mallocBytes (n+1); 
-                                          strncpy a ba (fromIntegral n); 
-                                          pokeByteOff a n '\0'
-                                          case a of { Ptr a -> return a })
+                -- CAREFUL!  Chars are 32 bits in ghc 4.09+
+                 case unsafePerformIO (do a@(Ptr addr) <- mallocBytes (n+1)
+                                          strncpy a ba (fromIntegral n)
+                                          writeCharOffAddr addr n '\0'
+                                          return addr)
                  of  A# a -> LitI (addr2Int# a)
 
                _ -> error "StgInterp.lit2expr: unhandled string constant type"
@@ -319,19 +351,23 @@ stg2expr ie stgexpr
            |  repOfStgExpr scrut /= RepP
            -> mkCasePrim (repOfStgExpr stgexpr) 
                          bndr (stg2expr ie scrut) 
-                              (map doPrimAlt alts) 
-                              (def2expr def)
+                              (map (doPrimAlt ie') alts) 
+                              (def2expr ie' def)
+           | otherwise ->
+               pprPanic "stg2expr(StgCase,prim)" (ppr (repOfStgExpr scrut) $$ (case scrut of (StgApp v _) -> ppr v <+> ppr (idType v) <+> ppr (idPrimRep v)) $$ ppr stgexpr)
+          where ie' = addOneToUniqSet ie bndr
 
         StgCase scrut live liveR bndr srt (StgAlgAlts tycon alts def)
            |  repOfStgExpr scrut == RepP
            -> mkCaseAlg (repOfStgExpr stgexpr) 
                         bndr (stg2expr ie scrut) 
-                             (map doAlgAlt alts) 
-                             (def2expr def)
+                             (map (doAlgAlt ie') alts) 
+                             (def2expr ie' def)
+          where ie' = addOneToUniqSet ie bndr
+
 
         StgPrimApp op args res_ty
-           -> mkPrimOp (repOfStgExpr stgexpr)
-                       op (map (arg2expr ie) args)
+           -> mkPrimOp (repOfStgExpr stgexpr) op (map (arg2expr ie) args)
 
         StgConApp dcon args
            -> conapp2expr ie dcon args
@@ -346,12 +382,16 @@ stg2expr ie stgexpr
                (translateBind ie binds) 
                (stg2expr (addListToUniqSet ie (map fst bs)) body)
 
-        other 
+       -- treat let-no-escape just like let.
+       StgLetNoEscape _ _ binds body
+          -> stg2expr ie (StgLet binds body)
+
+        other
            -> pprPanic "stg2expr" (ppr stgexpr)
      where
-        doPrimAlt (lit,rhs) 
+        doPrimAlt ie (lit,rhs) 
            = AltPrim (lit2expr lit) (stg2expr ie rhs)
-        doAlgAlt (dcon,vars,uses,rhs) 
+        doAlgAlt ie (dcon,vars,uses,rhs) 
            = AltAlg (dataConTag dcon - 1) 
                     (map id2VaaRep (toHeapOrder vars)) 
                        (stg2expr (addListToUniqSet ie vars) rhs)
@@ -362,8 +402,8 @@ stg2expr ie stgexpr
              in
                  rearranged
 
-        def2expr StgNoDefault         = Nothing
-        def2expr (StgBindDefault rhs) = Just (stg2expr ie rhs)
+        def2expr ie StgNoDefault         = Nothing
+        def2expr ie (StgBindDefault rhs) = Just (stg2expr ie rhs)
 
         mkAppChain ie result_rep so_far []
            = panic "mkAppChain"
@@ -380,8 +420,13 @@ mkCaseAlg  RepP = CaseAlgP
 
 -- any var that isn't in scope is turned into a Native
 mkVar ie rep var
-  | var `elementOfUniqSet` ie = case rep of { RepI -> VarI; RepP -> VarP } $ var
-  | otherwise = Native (toRdrName var)
+  | var `elementOfUniqSet` ie = 
+       (case rep of
+          RepI -> VarI
+          RepF -> VarF
+          RepD -> VarD
+          RepP -> VarP)  var
+  | otherwise = Native (getName var)
 
 mkRec RepI = RecI
 mkRec RepP = RecP
@@ -408,21 +453,30 @@ id2VaaRep var = (var, repOfId var)
 -- Link interpretables into something we can run
 -- ---------------------------------------------------------------------------
 
-linkIModules :: ClosureEnv -- incoming global closure env; returned updated
-            -> ItblEnv    -- incoming global itbl env; returned updated
+GLOBAL_VAR(cafTable, [], [HValue])
+
+addCAF :: HValue -> IO ()
+addCAF x = do xs <- readIORef cafTable; writeIORef cafTable (x:xs)
+
+linkIModules :: ItblEnv    -- incoming global itbl env; returned updated
+            -> ClosureEnv -- incoming global closure env; returned updated
             -> [([UnlinkedIBind], ItblEnv)]
             -> IO ([LinkedIBind], ItblEnv, ClosureEnv)
-linkIModules gce gie mods = do
+linkIModules gie gce mods = do
   let (bindss, ies) = unzip mods
       binds  = concat bindss
-      top_level_binders = map (toRdrName.binder) binds
+      top_level_binders = map (getName.binder) binds
       final_gie = foldr plusFM gie ies
   
-  let {-rec-}
-      new_gce = addListToFM gce (zip top_level_binders new_rhss)
-      new_rhss = map (\b -> evalP (bindee b) emptyUFM) new_binds
-    ---vvvvvvvvv---------------------------------------^^^^^^^^^-- circular
-      new_binds = linkIBinds final_gie new_gce binds
+  (new_binds, new_gce) <-
+    fixIO (\ ~(new_binds, new_gce) -> do
+
+      new_binds <- linkIBinds final_gie new_gce binds
+
+      let new_rhss = map (\b -> evalP (bindee b) emptyUFM) new_binds
+      let new_gce = addListToFM gce (zip top_level_binders new_rhss)
+
+      return (new_binds, new_gce))
 
   return (new_binds, final_gie, new_gce)
 
@@ -433,119 +487,208 @@ linkIModules gce gie mods = do
 -- up and not cache them in the source symbol tables.  The interpreted
 -- code will still be referenced in the source symbol tables.
 
--- JRS 001025: above comment is probably out of date ... interpret
--- with care.
-
-linkIBinds :: ItblEnv -> ClosureEnv -> [UnlinkedIBind] -> [LinkedIBind]
-linkIBinds ie ce binds = map (linkIBind ie ce) binds
+linkIBinds :: ItblEnv -> ClosureEnv -> [UnlinkedIBind] -> IO [LinkedIBind]
+linkIBinds ie ce binds = mapM (linkIBind ie ce) binds
 
-linkIBind ie ce (IBind bndr expr) = IBind bndr (linkIExpr ie ce expr)
+linkIBind ie ce (IBind bndr expr)
+   = do expr <- linkIExpr ie ce expr
+       return (IBind bndr expr)
 
+linkIExpr :: ItblEnv -> ClosureEnv -> UnlinkedIExpr -> IO LinkedIExpr
 linkIExpr ie ce expr = case expr of
 
-   CaseAlgP  bndr expr alts dflt -> 
-       CaseAlgP bndr (linkIExpr ie ce expr) (linkAlgAlts ie ce alts)
-                       (linkDefault ie ce dflt)
-
-   CaseAlgI  bndr expr alts dflt ->
-       CaseAlgI bndr (linkIExpr ie ce expr) (linkAlgAlts ie ce alts)
-                       (linkDefault ie ce dflt)
-
-   CasePrimP bndr expr alts dflt ->
-       CasePrimP bndr (linkIExpr ie ce expr) (linkPrimAlts ie ce alts)
-                       (linkDefault ie ce dflt)
-
-   CasePrimI bndr expr alts dflt ->
-       CasePrimI bndr (linkIExpr ie ce expr) (linkPrimAlts ie ce alts)
-                       (linkDefault ie ce dflt)
+   CaseAlgP  bndr expr alts dflt -> linkAlgCase ie ce bndr expr alts dflt CaseAlgP
+   CaseAlgI  bndr expr alts dflt -> linkAlgCase ie ce bndr expr alts dflt CaseAlgI
+   CaseAlgF  bndr expr alts dflt -> linkAlgCase ie ce bndr expr alts dflt CaseAlgF
+   CaseAlgD  bndr expr alts dflt -> linkAlgCase ie ce bndr expr alts dflt CaseAlgD
+
+   CasePrimP  bndr expr alts dflt -> linkPrimCase ie ce bndr expr alts dflt CasePrimP
+   CasePrimI  bndr expr alts dflt -> linkPrimCase ie ce bndr expr alts dflt CasePrimI
+   CasePrimF  bndr expr alts dflt -> linkPrimCase ie ce bndr expr alts dflt CasePrimF
+   CasePrimD  bndr expr alts dflt -> linkPrimCase ie ce bndr expr alts dflt CasePrimD
+
+   ConApp con -> lookupNullaryCon ie con
+
+   ConAppI con arg0 -> do
+       con' <- lookupCon ie con
+       arg' <- linkIExpr ie ce arg0
+       return (ConAppI con' arg')
+
+   ConAppP con arg0 -> do
+       con' <- lookupCon ie con
+       arg' <- linkIExpr ie ce arg0
+       return (ConAppP con' arg')
+
+   ConAppPP con arg0 arg1 -> do
+       con' <- lookupCon ie con
+       arg0' <- linkIExpr ie ce arg0
+       arg1' <- linkIExpr ie ce arg1
+       return (ConAppPP con' arg0' arg1')
+
+   ConAppGen con args -> do
+       con <- lookupCon ie con
+       args <- mapM (linkIExpr ie ce) args
+       return (ConAppGen con args)
    
-   ConApp con -> 
-       ConApp (lookupCon ie con)
-
-   ConAppI   con arg0 -> 
-       ConAppI (lookupCon ie con) (linkIExpr ie ce arg0)
-
-   ConAppP   con arg0 ->
-       ConAppP (lookupCon ie con) (linkIExpr ie ce arg0)
+   PrimOpI op args -> linkPrimOp ie ce PrimOpI op args
+   PrimOpP op args -> linkPrimOp ie ce PrimOpP op args
+   
+   NonRecP bind expr  -> linkNonRec ie ce NonRecP bind expr
+   NonRecI bind expr  -> linkNonRec ie ce NonRecI bind expr
+   NonRecF bind expr  -> linkNonRec ie ce NonRecF bind expr
+   NonRecD bind expr  -> linkNonRec ie ce NonRecD bind expr
 
-   ConAppPP  con arg0 arg1 -> 
-       ConAppPP (lookupCon ie con) (linkIExpr ie ce arg0) (linkIExpr ie ce arg1)
+   RecP binds expr  -> linkRec ie ce RecP binds expr
+   RecI binds expr  -> linkRec ie ce RecI binds expr
+   RecF binds expr  -> linkRec ie ce RecF binds expr
+   RecD binds expr  -> linkRec ie ce RecD binds expr
 
-   ConAppPPP con arg0 arg1 arg2 -> 
-       ConAppPPP (lookupCon ie con) (linkIExpr ie ce arg0) 
-                       (linkIExpr ie ce arg1) (linkIExpr ie ce arg2)
-   
-   PrimOpI op args -> PrimOpI op (map (linkIExpr ie ce) args)
-   PrimOpP op args -> PrimOpP op (map (linkIExpr ie ce) args)
-   
-   NonRecP bind expr  -> NonRecP (linkIBind ie ce bind) (linkIExpr ie ce expr)
-   RecP    binds expr -> RecP (linkIBinds ie ce binds) (linkIExpr ie ce expr)
-   
-   NonRecI bind expr  -> NonRecI (linkIBind ie ce bind) (linkIExpr ie ce expr)
-   RecI    binds expr -> RecI (linkIBinds ie ce binds) (linkIExpr ie ce expr)
-   
-   LitI i -> LitI i
-   LitF i -> LitF i
-   LitD i -> LitD i
+   LitI i -> return (LitI i)
+   LitF i -> return (LitF i)
+   LitD i -> return (LitD i)
 
    Native var -> lookupNative ce var
    
    VarP v -> lookupVar ce VarP v
    VarI v -> lookupVar ce VarI v
+   VarF v -> lookupVar ce VarF v
+   VarD v -> lookupVar ce VarD v
+   
+   LamPP  bndr expr -> linkLam ie ce LamPP bndr expr
+   LamPI  bndr expr -> linkLam ie ce LamPI bndr expr
+   LamPF  bndr expr -> linkLam ie ce LamPF bndr expr
+   LamPD  bndr expr -> linkLam ie ce LamPD bndr expr
+   LamIP  bndr expr -> linkLam ie ce LamIP bndr expr
+   LamII  bndr expr -> linkLam ie ce LamII bndr expr
+   LamIF  bndr expr -> linkLam ie ce LamIF bndr expr
+   LamID  bndr expr -> linkLam ie ce LamID bndr expr
+   LamFP  bndr expr -> linkLam ie ce LamFP bndr expr
+   LamFI  bndr expr -> linkLam ie ce LamFI bndr expr
+   LamFF  bndr expr -> linkLam ie ce LamFF bndr expr
+   LamFD  bndr expr -> linkLam ie ce LamFD bndr expr
+   LamDP  bndr expr -> linkLam ie ce LamDP bndr expr
+   LamDI  bndr expr -> linkLam ie ce LamDI bndr expr
+   LamDF  bndr expr -> linkLam ie ce LamDF bndr expr
+   LamDD  bndr expr -> linkLam ie ce LamDD bndr expr
    
-   LamPP  bndr expr -> LamPP bndr (linkIExpr ie ce expr)
-   LamPI  bndr expr -> LamPI bndr (linkIExpr ie ce expr)
-   LamIP  bndr expr -> LamIP bndr (linkIExpr ie ce expr)
-   LamII  bndr expr -> LamII bndr (linkIExpr ie ce expr)
+   AppPP  fun arg -> linkApp ie ce AppPP fun arg
+   AppPI  fun arg -> linkApp ie ce AppPI fun arg
+   AppPF  fun arg -> linkApp ie ce AppPF fun arg
+   AppPD  fun arg -> linkApp ie ce AppPD fun arg
+   AppIP  fun arg -> linkApp ie ce AppIP fun arg
+   AppII  fun arg -> linkApp ie ce AppII fun arg
+   AppIF  fun arg -> linkApp ie ce AppIF fun arg
+   AppID  fun arg -> linkApp ie ce AppID fun arg
+   AppFP  fun arg -> linkApp ie ce AppFP fun arg
+   AppFI  fun arg -> linkApp ie ce AppFI fun arg
+   AppFF  fun arg -> linkApp ie ce AppFF fun arg
+   AppFD  fun arg -> linkApp ie ce AppFD fun arg
+   AppDP  fun arg -> linkApp ie ce AppDP fun arg
+   AppDI  fun arg -> linkApp ie ce AppDI fun arg
+   AppDF  fun arg -> linkApp ie ce AppDF fun arg
+   AppDD  fun arg -> linkApp ie ce AppDD fun arg
    
-   AppPP  fun arg -> AppPP (linkIExpr ie ce fun) (linkIExpr ie ce arg)
-   AppPI  fun arg -> AppPI (linkIExpr ie ce fun) (linkIExpr ie ce arg)
-   AppIP  fun arg -> AppIP (linkIExpr ie ce fun) (linkIExpr ie ce arg)
-   AppII  fun arg -> AppII (linkIExpr ie ce fun) (linkIExpr ie ce arg)
+linkAlgCase ie ce bndr expr alts dflt con
+   = do expr <- linkIExpr ie ce expr
+       alts <- mapM (linkAlgAlt ie ce) alts
+       dflt <- linkDefault ie ce dflt
+       return (con bndr expr alts dflt)
+
+linkPrimCase ie ce bndr expr alts dflt con
+   = do expr <- linkIExpr ie ce expr
+       alts <- mapM (linkPrimAlt ie ce) alts
+       dflt <- linkDefault ie ce dflt
+       return (con bndr expr alts dflt)
+
+linkAlgAlt ie ce (AltAlg tag args rhs) 
+  = do rhs <- linkIExpr ie ce rhs
+       return (AltAlg tag args rhs)
+
+linkPrimAlt ie ce (AltPrim lit rhs) 
+  = do rhs <- linkIExpr ie ce rhs
+       lit <- linkIExpr ie ce lit
+       return (AltPrim lit rhs)
+
+linkDefault ie ce Nothing = return Nothing
+linkDefault ie ce (Just expr) 
+   = do expr <- linkIExpr ie ce expr
+       return (Just expr)
+
+linkNonRec ie ce con bind expr 
+   = do expr <- linkIExpr ie ce expr
+       bind <- linkIBind ie ce bind
+        return (con bind expr)
+
+linkRec ie ce con binds expr 
+   = do expr <- linkIExpr ie ce expr
+       binds <- linkIBinds ie ce binds
+        return (con binds expr)
+
+linkLam ie ce con bndr expr
+   = do expr <- linkIExpr ie ce expr
+        return (con bndr expr)
+
+linkApp ie ce con fun arg
+   = do fun <- linkIExpr ie ce fun
+        arg <- linkIExpr ie ce arg
+       return (con fun arg)
+
+linkPrimOp ie ce con op args
+   = do args <- mapM (linkIExpr ie ce) args
+       return (con op args)
 
 lookupCon ie con = 
   case lookupFM ie con of
-    Just (Ptr addr) -> addr
-    Nothing   -> 
+    Just (Ptr addr) -> return addr
+    Nothing   -> do
        -- try looking up in the object files.
-       case {-HACK!!!-}
-               unsafePerformIO (lookupSymbol (rdrNameToCLabel con "con_info")) of
-           Just addr -> addr
-           Nothing   -> pprPanic "linkIExpr" (ppr con)
+        m <- lookupSymbol (nameToCLabel con "con_info")
+       case m of
+           Just addr -> return addr
+           Nothing   -> pprPanic "linkIExpr" (ppr con)
+
+-- nullary constructors don't have normal _con_info tables.
+lookupNullaryCon ie con =
+  case lookupFM ie con of
+    Just (Ptr addr) -> return (ConApp addr)
+    Nothing -> do
+       -- try looking up in the object files.
+       m <- lookupSymbol (nameToCLabel con "closure")
+       case m of
+           Just (A# addr) -> return (Native (unsafeCoerce# addr))
+           Nothing   -> pprPanic "lookupNullaryCon" (ppr con)
+
 
 lookupNative ce var =
-  case lookupFM ce var of
-    Just e  -> Native e
-    Nothing -> 
-        -- try looking up in the object files.
-       let lbl = (rdrNameToCLabel var "closure")
-           addr = unsafePerformIO (lookupSymbol lbl) in
-       case {- trace (lbl ++ " -> " ++ show addr) $ -} addr of
-           Just (A# addr) -> Native (unsafeCoerce# addr)
-           Nothing   -> pprPanic "linkIExpr" (ppr var)
+  unsafeInterleaveIO (do
+      case lookupFM ce var of
+       Just e  -> return (Native e)
+       Nothing -> do
+           -- try looking up in the object files.
+           let lbl = (nameToCLabel var "closure")
+           m <- lookupSymbol lbl
+           case m of
+               Just (A# addr)
+                   -> do addCAF (unsafeCoerce# addr)
+                         return (Native (unsafeCoerce# addr))
+               Nothing   -> pprPanic "linkIExpr" (ppr var)
+  )
 
 -- some VarI/VarP refer to top-level interpreted functions; we change
 -- them into Natives here.
 lookupVar ce f v =
-  case lookupFM ce (toRdrName v) of
-       Nothing -> f v
-       Just e  -> Native e
+  unsafeInterleaveIO (
+       case lookupFM ce (getName v) of
+           Nothing -> return (f v)
+           Just e  -> return (Native e)
+  )
 
 -- HACK!!!  ToDo: cleaner
-rdrNameToCLabel :: RdrName -> String{-suffix-} -> String
-rdrNameToCLabel rn suffix = 
+nameToCLabel :: Name -> String{-suffix-} -> String
+nameToCLabel n suffix =
   _UNPK_(moduleNameFS (rdrNameModule rn)) 
   ++ '_':occNameString(rdrNameOcc rn) ++ '_':suffix
-
-linkAlgAlts ie ce = map (linkAlgAlt ie ce)
-linkAlgAlt ie ce (AltAlg tag args rhs) = AltAlg tag args (linkIExpr ie ce rhs)
-
-linkPrimAlts ie ce = map (linkPrimAlt ie ce)
-linkPrimAlt ie ce (AltPrim lit rhs)
-   = AltPrim (linkIExpr ie ce lit) (linkIExpr ie ce rhs)
-
-linkDefault ie ce Nothing = Nothing
-linkDefault ie ce (Just expr) = Just (linkIExpr ie ce expr)
+  where rn = toRdrName n
 
 -- ---------------------------------------------------------------------------
 -- The interpreter proper
@@ -560,6 +703,9 @@ linkDefault ie ce (Just expr) = Just (linkIExpr ie ce expr)
 -- Evaluator for things of boxed (pointer) representation
 -- ---------------------------------------------------------------------------
 
+interp :: LinkedIExpr -> HValue
+interp iexpr = unsafeCoerce# (evalP iexpr emptyUFM)
+
 evalP :: LinkedIExpr -> UniqFM boxed -> boxed
 
 {-
@@ -586,8 +732,8 @@ evalP (VarP v) de
 -- always has pointer rep.
 evalP (AppIP e1 e2) de  = unsafeCoerce# (evalP e1 de) (evalI e2 de)
 evalP (AppPP e1 e2) de  = unsafeCoerce# (evalP e1 de) (evalP e2 de)
-evalP (AppFP e1 e2) de  = unsafeCoerce# (evalF e1 de) (evalI e2 de)
-evalP (AppDP e1 e2) de  = unsafeCoerce# (evalD e1 de) (evalP e2 de)
+evalP (AppFP e1 e2) de  = unsafeCoerce# (evalP e1 de) (evalF e2 de)
+evalP (AppDP e1 e2) de  = unsafeCoerce# (evalP e1 de) (evalD e2 de)
 
 -- Lambdas always return P-rep, but we need to do different things
 -- depending on both the argument and result representations.
@@ -639,49 +785,49 @@ evalP (CasePrimP bndr expr alts def) de
    = case helper_casePrim bndr expr alts def de of
         (rhs, de') -> evalP rhs de'
 
-{-
--- ConApp can only be handled by evalP
-evalP (ConApp itbl args) se de
-   = loop args
-     where
-        -- This appalling hack suggested (gleefully) by SDM
-        -- It is not well typed (needless to say?)
-        loop :: [Expr] -> boxed
-        loop [] 
-           = trace "loop-empty" (
-             case itbl of A# addr# -> unsafeCoerce# (mci_make_constr addr#)
-             )
-        loop (a:as) 
-           = trace "loop-not-empty" (
-             case repOf a of
-                RepI -> case evalI a de of i# -> loop as i#
-                RepP -> let p = evalP a de in loop as p                
-             )
--}
+evalP (ConApp (A# itbl)) de
+   = mci_make_constr0 itbl
 
 evalP (ConAppI (A# itbl) a1) de
    = case evalI a1 de of i1 -> mci_make_constrI itbl i1
 
-evalP (ConApp (A# itbl)) de
-   = mci_make_constr itbl
-
 evalP (ConAppP (A# itbl) a1) de
-   = let p1 = evalP a1 de
-     in  mci_make_constrP itbl p1
+   = evalP (ConAppGen (A# itbl) [a1]) de
+--   = let p1 = evalP a1 de
+--     in  mci_make_constrP itbl p1
 
 evalP (ConAppPP (A# itbl) a1 a2) de
    = let p1 = evalP a1 de
          p2 = evalP a2 de
      in  mci_make_constrPP itbl p1 p2
 
-evalP (ConAppPPP (A# itbl) a1 a2 a3) de
-   = let p1 = evalP a1 de
-         p2 = evalP a2 de
-         p3 = evalP a3 de
-     in  mci_make_constrPPP itbl p1 p2 p3
-
-
-
+evalP (ConAppGen itbl args) de
+   = let c = case itbl of A# a# -> mci_make_constr a# in
+     c `seq` loop c 1#{-leave room for hdr-} args
+     where
+        loop :: a{-closure-} -> Int# -> [LinkedIExpr] -> a
+        loop c off [] = c
+        loop c off (a:as)
+           = case repOf a of
+                RepP -> let c' = setPtrOffClosure c off (evalP a de)
+                       in c' `seq` loop c' (off +# 1#) as
+                RepI -> case evalI a de of { i# -> 
+                       let c' = setIntOffClosure c off i#
+                       in c' `seq` loop c' (off +# 1#) as }
+               RepF -> case evalF a de of { f# -> 
+                       let c' = setFloatOffClosure c off f# 
+                       in c' `seq` loop c' (off +# 1#) as }
+               RepD -> case evalD a de of { d# -> 
+                       let c' = setDoubleOffClosure c off d#
+                       in c' `seq` loop c' (off +# 2#) as }
+
+evalP (PrimOpP IntEqOp [e1,e2]) de 
+    = case evalI e1 de of 
+         i1# -> case evalI e2 de of 
+                   i2# -> unsafeCoerce# (i1# ==# i2#)
+
+evalP (PrimOpP primop _) de
+   = error ("evalP: unhandled primop: " ++ showSDoc (ppr primop))
 evalP other de
    = error ("evalP: unhandled case: " ++ showExprTag other)
 
@@ -692,10 +838,12 @@ evalP other de
 -- Evaluate something which has an unboxed Int rep
 evalI :: LinkedIExpr -> UniqFM boxed -> Int#
 
+{-
 evalI expr de
 --   | trace ("evalI: " ++ showExprTag expr) False
    | trace ("evalI:\n" ++ showSDoc (pprIExpr expr) ++ "\n") False
    = error "evalI: ?!?!"
+-}
 
 evalI (LitI i#) de = i#
 
@@ -735,6 +883,10 @@ evalI (CasePrimI bndr expr alts def) de
 
 evalI (PrimOpI IntAddOp [e1,e2]) de  = evalI e1 de +# evalI e2 de
 evalI (PrimOpI IntSubOp [e1,e2]) de  = evalI e1 de -# evalI e2 de
+evalI (PrimOpI DataToTagOp [e1]) de  = dataToTag# (evalP e1 de)
+
+evalI (PrimOpI primop _) de
+   = error ("evalI: unhandled primop: " ++ showSDoc (ppr primop))
 
 --evalI (NonRec (IBind v e) b) de
 --   = evalI b (augment de v (eval e de))
@@ -749,10 +901,12 @@ evalI other de
 -- Evaluate something which has an unboxed Int rep
 evalF :: LinkedIExpr -> UniqFM boxed -> Float#
 
+{-
 evalF expr de
 --   | trace ("evalF: " ++ showExprTag expr) False
    | trace ("evalF:\n" ++ showSDoc (pprIExpr expr) ++ "\n") False
    = error "evalF: ?!?!"
+-}
 
 evalF (LitF f#) de = f#
 
@@ -803,10 +957,12 @@ evalF other de
 -- Evaluate something which has an unboxed Int rep
 evalD :: LinkedIExpr -> UniqFM boxed -> Double#
 
+{-
 evalD expr de
 --   | trace ("evalD: " ++ showExprTag expr) False
    | trace ("evalD:\n" ++ showSDoc (pprIExpr expr) ++ "\n") False
    = error "evalD: ?!?!"
+-}
 
 evalD (LitD d#) de = d#
 
@@ -896,11 +1052,18 @@ repOf (NonRecI _ _)    = RepI
 repOf (NonRecF _ _)    = RepF
 repOf (NonRecD _ _)    = RepD
 
+repOf (RecP _ _)       = RepP
+repOf (RecI _ _)       = RepI
+repOf (RecF _ _)       = RepF
+repOf (RecD _ _)       = RepD
+
 repOf (LitI _)         = RepI
 repOf (LitF _)         = RepF
 repOf (LitD _)         = RepD
 
-repOf (VarP _)         = RepI
+repOf (Native _)       = RepP
+
+repOf (VarP _)         = RepP
 repOf (VarI _)         = RepI
 repOf (VarF _)         = RepF
 repOf (VarD _)         = RepD
@@ -914,7 +1077,7 @@ repOf (ConApp _)       = RepP
 repOf (ConAppI _ _)    = RepP
 repOf (ConAppP _ _)    = RepP
 repOf (ConAppPP _ _ _) = RepP
-repOf (ConAppPPP _ _ _ _) = RepP
+repOf (ConAppGen _ _)  = RepP
 
 repOf (CaseAlgP _ _ _ _) = RepP
 repOf (CaseAlgI _ _ _ _) = RepI
@@ -967,11 +1130,15 @@ helper_casePrim :: Var -> LinkedIExpr -> [LinkedAltPrim] -> Maybe LinkedIExpr
                    -> (LinkedIExpr, UniqFM boxed)
 helper_casePrim bndr expr alts def de
    = case repOf expr of
-        -- Umm, can expr have any other rep?  Yes ...
-        -- CharRep, DoubleRep, FloatRep.  What about string reps?
         RepI -> case evalI expr de of 
                    i# -> (select_altPrim alts def (LitI i#), 
                           addToUFM de bndr (unsafeCoerce# (I# i#)))
+        RepF -> case evalF expr de of 
+                   f# -> (select_altPrim alts def (LitF f#), 
+                          addToUFM de bndr (unsafeCoerce# (F# f#)))
+        RepD -> case evalD expr de of 
+                   d# -> (select_altPrim alts def (LitD d#), 
+                          addToUFM de bndr (unsafeCoerce# (D# d#)))
 
 
 augment_from_constr :: UniqFM boxed -> a -> ([(Id,Rep)],Int) -> UniqFM boxed
@@ -982,6 +1149,8 @@ augment_from_constr de con ((v,rep):vs,offset)
             = case rep of
                  RepP -> indexPtrOffClosure con offset
                  RepI -> unsafeCoerce# (I# (indexIntOffClosure con offset))
+                 RepF -> unsafeCoerce# (F# (indexFloatOffClosure con offset))
+                 RepD -> unsafeCoerce# (D# (indexDoubleOffClosure con offset))
      in
          augment_from_constr (addToUFM de v v_binding) con 
                              (vs,offset + repSizeW rep)
@@ -1023,6 +1192,9 @@ select_altPrim ((AltPrim lit rhs):alts) def literal
 
 eqLits (LitI i1#) (LitI i2#) = i1# ==# i2#
 
+-- ----------------------------------------------------------------------
+-- Grotty inspection and creation of closures
+-- ----------------------------------------------------------------------
 
 -- a is a constructor
 indexPtrOffClosure :: a -> Int -> b
@@ -1033,6 +1205,26 @@ indexIntOffClosure :: a -> Int -> Int#
 indexIntOffClosure con (I# offset)
    = case wordToInt (W# (indexWordOffClosure# con offset)) of I# i# -> i#
 
+indexFloatOffClosure :: a -> Int -> Float#
+indexFloatOffClosure con (I# offset)
+   = unsafeCoerce# (indexWordOffClosure# con offset) 
+       -- TOCK TOCK TOCK! Those GHC developers are crazy.
+
+indexDoubleOffClosure :: a -> Int -> Double#
+indexDoubleOffClosure con (I# offset)
+   = unsafeCoerce# (panic "indexDoubleOffClosure")
+
+setPtrOffClosure :: a -> Int# -> b -> a
+setPtrOffClosure a i b = case setPtrOffClosure# a i b of (# c #) -> c
+
+setIntOffClosure :: a -> Int# -> Int# -> a
+setIntOffClosure a i b = case setWordOffClosure# a i (int2Word# b) of (# c #) -> c
+
+setFloatOffClosure :: a -> Int# -> Float# -> a
+setFloatOffClosure a i b = case setWordOffClosure# a i (unsafeCoerce# b) of (# c #) -> c
+
+setDoubleOffClosure :: a -> Int# -> Double# -> a
+setDoubleOffClosure a i b = unsafeCoerce# (panic "setDoubleOffClosure")
 
 ------------------------------------------------------------------------
 --- Manufacturing of info tables for DataCons defined in this module ---
@@ -1081,7 +1273,7 @@ make_constr_itbls cons
         mk_dirret_itbl (dcon, conNo)
            = mk_itbl dcon conNo mci_constr_entry
 
-        mk_itbl :: DataCon -> Int -> Addr -> IO (RdrName,ItblPtr)
+        mk_itbl :: DataCon -> Int -> Addr -> IO (Name,ItblPtr)
         mk_itbl dcon conNo entry_addr
            = let (tot_wds, ptr_wds, _) 
                     = mkVirtHeapOffsets typePrimRep (dataConRepArgTys dcon)
@@ -1112,11 +1304,11 @@ make_constr_itbls cons
                  entry_addr_w = fromIntegral (addrToInt entry_addr)
              in
                  do addr <- malloc
-                    putStrLn ("SIZE of itbl is " ++ show (sizeOf itbl))
-                    putStrLn ("# ptrs  of itbl is " ++ show ptrs)
-                    putStrLn ("# nptrs of itbl is " ++ show nptrs)
+                    --putStrLn ("SIZE of itbl is " ++ show (sizeOf itbl))
+                    --putStrLn ("# ptrs  of itbl is " ++ show ptrs)
+                    --putStrLn ("# nptrs of itbl is " ++ show nptrs)
                     poke addr itbl
-                    return (toRdrName dcon, addr `plusPtr` 8)
+                    return (getName dcon, addr `plusPtr` 8)
 
 
 byte :: Int -> Word32 -> Word32
@@ -1136,16 +1328,16 @@ vecret_entry 6 = mci_constr7_entry
 vecret_entry 7 = mci_constr8_entry
 
 -- entry point for direct returns for created constr itbls
-foreign label "mci_constr_entry" mci_constr_entry :: Addr
+foreign label "stg_mci_constr_entry" mci_constr_entry :: Addr
 -- and the 8 vectored ones
-foreign label "mci_constr1_entry" mci_constr1_entry :: Addr
-foreign label "mci_constr2_entry" mci_constr2_entry :: Addr
-foreign label "mci_constr3_entry" mci_constr3_entry :: Addr
-foreign label "mci_constr4_entry" mci_constr4_entry :: Addr
-foreign label "mci_constr5_entry" mci_constr5_entry :: Addr
-foreign label "mci_constr6_entry" mci_constr6_entry :: Addr
-foreign label "mci_constr7_entry" mci_constr7_entry :: Addr
-foreign label "mci_constr8_entry" mci_constr8_entry :: Addr
+foreign label "stg_mci_constr1_entry" mci_constr1_entry :: Addr
+foreign label "stg_mci_constr2_entry" mci_constr2_entry :: Addr
+foreign label "stg_mci_constr3_entry" mci_constr3_entry :: Addr
+foreign label "stg_mci_constr4_entry" mci_constr4_entry :: Addr
+foreign label "stg_mci_constr5_entry" mci_constr5_entry :: Addr
+foreign label "stg_mci_constr6_entry" mci_constr6_entry :: Addr
+foreign label "stg_mci_constr7_entry" mci_constr7_entry :: Addr
+foreign label "stg_mci_constr8_entry" mci_constr8_entry :: Addr
 
 
 
@@ -1227,5 +1419,7 @@ load addr = do x <- peek addr
 -----------------------------------------------------------------------------q
 
 foreign import "strncpy" strncpy :: Ptr a -> ByteArray# -> CInt -> IO ()
+#endif
+
 \end{code}