[project @ 2000-10-27 13:50:25 by sewardj]
[ghc-hetmet.git] / ghc / compiler / stgSyn / StgInterp.lhs
index 08ef24d..8e98946 100644 (file)
@@ -7,11 +7,8 @@
 
 module StgInterp ( 
     ClosureEnv, ItblEnv,
-
-    linkIModules,      -- :: ItblEnv -> ClosureEnv -> [[UnlinkedIBind]] -> 
-                       --      ([LinkedIBind], ItblEnv, ClosureEnv)
-
-    runStgI  -- tmp, for testing
+    linkIModules,
+    stgToInterpSyn,
  ) where
 
 {- -----------------------------------------------------------------------------
@@ -32,7 +29,16 @@ module StgInterp (
 
 #include "HsVersions.h"
 
-#ifdef GHCI
+#if __GLASGOW_HASKELL__ <= 408
+
+import Panic ( panic )
+type ItblEnv = ()
+type ClosureEnv = ()
+linkIModules   = panic "StgInterp.linkIModules: this hsc was not built with an interpreter"
+stgToInterpSyn = panic "StgInterp.linkIModules: this hsc was not built with an interpreter"
+
+#else
+
 import Linker
 import Id              ( Id, idPrimRep )
 import Outputable
@@ -63,18 +69,17 @@ import CTypes
 import FastString
 import GlaExts         ( Int(..) )
 import Module          ( moduleNameFS )
-#endif
 
-import TyCon           ( TyCon, isDataTyCon, tyConFamilySize, tyConDataCons )
+import TyCon           ( TyCon, isDataTyCon, tyConDataCons, tyConFamilySize )
 import Class           ( Class, classTyCon )
 import InterpSyn
 import StgSyn
 import Addr
 import RdrName         ( RdrName, rdrNameModule, rdrNameOcc )
-import OccName         ( occNameString )
 import FiniteMap
 import Panic           ( panic )
-import PrelAddr
+import OccName         ( occNameString )
+
 
 -- ---------------------------------------------------------------------------
 -- Environments needed by the linker
@@ -87,18 +92,15 @@ type ClosureEnv = FiniteMap RdrName HValue
 -- Run our STG program through the interpreter
 -- ---------------------------------------------------------------------------
 
+#if 0
+-- To be nuked at some point soon.
 runStgI :: [TyCon] -> [Class] -> [StgBinding] -> IO Int
 
-#ifndef GHCI
-runStgI              = panic "StgInterp.runStgI: not implemented"
-linkIModules  = panic "StgInterp.linkIModules: not implemented"
-#else
-
 -- 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 (stg2IBinds emptyUniqSet) stgbinds
+       let unlinked_binds = concatMap (translateBind emptyUniqSet) stgbinds
             
 {-
         let dbg_txt 
@@ -128,14 +130,26 @@ runStgI tycons classes stgbinds
                            emptyUFM{-initial de-}
                     )
         return result
+#endif
 
 -- ---------------------------------------------------------------------------
 -- Convert STG to an unlinked interpretable
 -- ---------------------------------------------------------------------------
 
-stg2IBinds :: UniqSet Id -> StgBinding -> [UnlinkedIBind]
-stg2IBinds ie (StgNonRec v e)  = [IBind v (rhs2expr ie e)]
-stg2IBinds ie (StgRec vs_n_es) = [IBind v (rhs2expr ie' e) | (v,e) <- vs_n_es]
+-- visible from outside
+stgToInterpSyn :: [StgBinding] 
+              -> [TyCon] -> [Class] 
+              -> IO ([UnlinkedIBind], ItblEnv)
+stgToInterpSyn binds local_tycons local_classes
+ = do let ibinds = concatMap (translateBind emptyUniqSet) binds
+      let tycs   = local_tycons ++ map classTyCon local_classes
+      itblenv <- mkITbls tycs
+      return (ibinds, itblenv)
+
+
+translateBind :: UniqSet Id -> StgBinding -> [UnlinkedIBind]
+translateBind ie (StgNonRec v e)  = [IBind v (rhs2expr ie e)]
+translateBind ie (StgRec vs_n_es) = [IBind v (rhs2expr ie' e) | (v,e) <- vs_n_es]
   where ie' = addListToUniqSet ie (map fst vs_n_es)
 
 isRec (StgNonRec _ _) = False
@@ -336,12 +350,12 @@ stg2expr ie stgexpr
 
         StgLet binds@(StgNonRec v e) body
           -> mkNonRec (repOfStgExpr stgexpr) 
-               (head (stg2IBinds ie binds)) 
+               (head (translateBind ie binds)) 
                (stg2expr (addOneToUniqSet ie v) body)
 
         StgLet binds@(StgRec bs) body
            -> mkRec (repOfStgExpr stgexpr) 
-               (stg2IBinds ie binds) 
+               (translateBind ie binds) 
                (stg2expr (addListToUniqSet ie (map fst bs)) body)
 
         other 
@@ -401,25 +415,29 @@ repOfArg (StgTypeArg ty) = pprPanic "repOfArg" (ppr ty)
 
 id2VaaRep var = (var, repOfId var)
 
+
 -- ---------------------------------------------------------------------------
--- Link an interpretable into something we can run
+-- Link interpretables into something we can run
 -- ---------------------------------------------------------------------------
 
-linkIModules :: ItblEnv -> ClosureEnv -> [([TyCon],[UnlinkedIBind])] -> 
-       IO ([LinkedIBind], ItblEnv, ClosureEnv)
-linkIModules ie ce mods = do
-  let (tyconss, bindss) = unzip mods
-      tycons = concat tyconss
+linkIModules :: ClosureEnv -- incoming global closure env; returned updated
+            -> ItblEnv    -- incoming global itbl env; returned updated
+            -> [([UnlinkedIBind], ItblEnv)]
+            -> IO ([LinkedIBind], ItblEnv, ClosureEnv)
+linkIModules gce gie mods = do
+  let (bindss, ies) = unzip mods
       binds  = concat bindss
       top_level_binders = map (toRdrName.binder) binds
-
-  new_ie <- mkITbls (concat tyconss)
-  let new_ce = addListToFM ce (zip top_level_binders new_rhss)
+      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, final_ie, final_ce) = linkIBinds new_ie new_ce binds
+    ---vvvvvvvvv---------------------------------------^^^^^^^^^-- circular
+      new_binds = linkIBinds final_gie new_gce binds
+
+  return (new_binds, final_gie, new_gce)
 
-  return (new_binds, final_ie, final_ce)
 
 -- We're supposed to augment the environments with the values of any
 -- external functions/info tables we need as we go along, but that's a
@@ -427,35 +445,11 @@ linkIModules ie ce 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.
 
--- Make info tables for the data decls in this module
-mkITbls :: [TyCon] -> IO ItblEnv
-mkITbls [] = return emptyFM
-mkITbls (tc:tcs) = do itbls  <- mkITbl tc
-                      itbls2 <- mkITbls tcs
-                      return (itbls `plusFM` itbls2)
-
-mkITbl :: TyCon -> IO ItblEnv
-mkITbl tc
---   | trace ("TYCON: " ++ showSDoc (ppr tc)) False
---   = error "?!?!"
-   | not (isDataTyCon tc) 
-   = return emptyFM
-   | n == length dcs  -- paranoia; this is an assertion.
-   = make_constr_itbls dcs
-     where
-        dcs = tyConDataCons tc
-        n   = tyConFamilySize tc
-
-
-linkIBinds :: ItblEnv -> ClosureEnv -> [UnlinkedIBind] -> 
-   ([LinkedIBind], ItblEnv, ClosureEnv)
-linkIBinds ie ce binds
-  = (new_binds, ie, ce) 
-  where new_binds = map (linkIBind ie ce) binds
-
-linkIBinds' ie ce binds 
-  = new_binds where (new_binds, ie, ce) = linkIBinds ie ce binds
+linkIBinds :: ItblEnv -> ClosureEnv -> [UnlinkedIBind] -> [LinkedIBind]
+linkIBinds ie ce binds = map (linkIBind ie ce) binds
 
 linkIBind ie ce (IBind bndr expr) = IBind bndr (linkIExpr ie ce expr)
 
@@ -497,10 +491,10 @@ linkIExpr ie ce expr = case expr of
    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)
+   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)
+   RecI    binds expr -> RecI (linkIBinds ie ce binds) (linkIExpr ie ce expr)
    
    LitI i -> LitI i
    LitF i -> LitF i
@@ -1056,6 +1050,25 @@ indexIntOffClosure con (I# offset)
 --- Manufacturing of info tables for DataCons defined in this module ---
 ------------------------------------------------------------------------
 
+-- Make info tables for the data decls in this module
+mkITbls :: [TyCon] -> IO ItblEnv
+mkITbls [] = return emptyFM
+mkITbls (tc:tcs) = do itbls  <- mkITbl tc
+                      itbls2 <- mkITbls tcs
+                      return (itbls `plusFM` itbls2)
+
+mkITbl :: TyCon -> IO ItblEnv
+mkITbl tc
+--   | trace ("TYCON: " ++ showSDoc (ppr tc)) False
+--   = error "?!?!"
+   | not (isDataTyCon tc) 
+   = return emptyFM
+   | n == length dcs  -- paranoia; this is an assertion.
+   = make_constr_itbls dcs
+     where
+        dcs = tyConDataCons tc
+        n   = tyConFamilySize tc
+
 cONSTR :: Int
 cONSTR = 1  -- as defined in ghc/includes/ClosureTypes.h
 
@@ -1221,6 +1234,6 @@ load addr = do x <- peek addr
 
 foreign import "strncpy" strncpy :: Addr -> ByteArray# -> CInt -> IO ()
 
-#endif /* ndef GHCI */
+#endif /* #if __GLASGOW_HASKELL__ <= 408 */
 \end{code}