STGGcode

Plain source file: STGGcode.hs (Apr 24, 2001)

STGGcode is imported by: Main.

module STGGcode where -- (stgGcode) where

import Extra(strace,pair,isJust,dropJust)
import State
import IntState hiding (IdKind)
import PosCode
import SyntaxPos
import Gcode
import GcodeLow(con0,cap0,caf,fun,extra)
import StrPos
import STGState
import STGBuild
import Foreign(ImpExp(..))

stgGcode prof state code = 
  case {- mapS -} gBindingTop code () (Thread prof 0 0 [] state [] [] 0 0 [] ([],Nothing)) of
    (bs,(Thread prof fun _ _ state _ _ _ _ _ (fs,_))) -> (bs,state,fs)
  
gBindingTop (fun,PosLambda pos [] args@[arg] exp@(PosExpCase cpos (PosVar vpos var) [PosAltCon apoc con posargs (PosVar vpos2 var2)])) =
    gOnly con >>>= \ only ->
    if only && any ((var2 ==).snd) posargs then -- Selector function
      let no = dropJust (lookup var2 (zip (map snd posargs) [1..]))
      in unitS (STARTFUN pos fun : needstack 1 [ SELECTOR_EVAL, SELECT no ])
    else     -- Ugly duplication of code
      setFun fun >>>
      pushEnv (zip (map snd args) (map Arg [1..])) >>>
      gExp exp >>>= \ exp ->
      popEnv >>>
      maxDepth >>>= \ d ->
      unitS (STARTFUN pos fun : needstack d ( exp ++ [RETURN_EVAL]))
gBindingTop (fun,PosLambda pos env args exp) =
    setFun fun >>>
    pushEnv (zip (map snd args) (map Arg [1..])) >>>
    gExp exp >>>= \ exp ->
    popEnv >>>
    maxDepth >>>= \ d ->
    unitS (STARTFUN pos fun : needstack d (exp ++ [RETURN_EVAL]))
gBindingTop (fun,PosPrimitive pos fn) =
    setFun fun >>>
    gArity fun >>>= \ (Just arity) ->
    unitS (STARTFUN pos fun: concatMap ( \ p -> [PUSH_ARG p, EVAL, POP 1] ) [1 .. arity] ++
	   [PRIMITIVE, DATA_CLABEL fn, RETURN_EVAL ])
gBindingTop (fun,PosForeign pos fn str c ie) =
    setFun fun >>>
    gArity fun >>>= \ (Just arity) ->
    makeForeign str arity fn c ie >>>
    case ie of
      Imported ->
        unitS
          (STARTFUN pos fun:
           concatMap ( \ p -> [PUSH_ARG p, EVAL, POP 1] ) [1 .. arity] ++
           [ PRIMITIVE , DATA_FLABEL fn, RETURN_EVAL ])
      Exported ->
        unitS []

gExp (PosExpLet pos bindings exp) =
   \ down (Thread prof fun maxDepth failstack state env lateenv depth heap depthstack fs) ->
    let (bBuild_bEnv,Thread prof' fun' maxDepth' failstack' state' env' _ depth' heap' depthstack' fs')
            = mapS stgBodyPush bindings
                   down (Thread prof fun maxDepth failstack state newEnv (addLate:lateenv) depth heap depthstack fs)
                   
        (bBuild,addLate) = unzip bBuild_bEnv
        addId = map fst bindings
	addEnv = map ( \ v -> (v,HeapLate)) addId
        newEnv = addEnv:env
        size = length addId
    in
--      strace ("STGGCode PosExpLet addLate " ++ show (map fst addLate) ++ " addId " ++ show addId) $
      (pushStack addId >>>
       gExp exp >>>= \ eBuild ->
       popEnv >>>
       decDepth size >>>
       unitS (concat bBuild ++ eBuild ++ [SLIDE size])
       ) down (Thread prof' fun' maxDepth' failstack' state' env lateenv depth heap' depthstack' fs')

gExp (PosExpCase pos exp alts) =
  gExp exp >>>= \ exp ->
  getFail >>>= \ fd ->
  pushDH >>>
  gUnique >>>= \ c ->
  mapS (gAlt c) alts >>>= \ alts ->
  popDH >>>
  case unzip alts of
    (il,alts) -> 
      unitS (exp ++ EVAL : CASE il fd : concat alts ++ [LABEL c])

gExp (PosExpFatBar esc exp1 exp2) =
  pushDH >>>
  pushFail >>>= \ fail ->
  gUnique >>>= \ after ->
  gExp exp1 >>>= \ exp1 ->
  popFail >>>
  popDH >>>
  gExp exp2 >>>= \ exp2 ->
  unitS (exp1 ++ JUMP after : LABEL fail : exp2 ++ [LABEL after])

gExp (PosExpFail) =
  getFail >>>= \ (Just (fail,d)) ->
  unitS [POP d, JUMP fail]

gExp (PosExpIf  pos exp1 exp2 exp3) =
  gUnique >>>= \ false ->
  gUnique >>>= \ after ->
  pushDH >>>
  gExp exp1 >>>= \ exp1 ->
  cloneDH >>>
  gExp exp2 >>>= \ exp2 ->
  popDH >>>
  gExp exp3 >>>= \ exp3 ->
  unitS (exp1 ++ EVAL:JUMPFALSE false: exp2 ++ JUMP after:LABEL false:exp3 ++ [LABEL after]) -- DAVID

gExp (PosExpThunk pos [PosPrim _ STRING,PosString _ s]) =
  incDepth >>>
  unitS [PUSH_STRING s, PRIM STRING]

gExp (PosExpThunk pos [PosPrim _ SEQ,a1,a2]) =
  gExp a1 >>>= \ a1 ->
  decDepth 1 >>>
  gExp a2 >>>= \ a2 ->
  unitS (a1 ++ EVAL : POP 1 : a2)

gExp (PosExpThunk pos (PosPrim _ p:args)) = -- must be right number of arguments
   mapS ( \ a -> gExp a >>>= \ a -> unitS (a ++ [EVAL])) (reverse args) >>>= \ args ->
   decDepth (length args - 1) >>>
   unitS (concat args ++ [PRIM p])

gExp (PosExpApp pos (fun:args)) =
  mapS gAtom (reverse args) >>>= \ args ->
  gExp fun >>>= \ fun ->
  decDepth (length args) >>>
  unitS (concat args ++ fun ++ [EVAL,APPLY (length args)])

gExp exp@(PosExpThunk _ (tag@(PosCon _ v):args)) = -- Should evaluate strict arguments (already done ?) !!! 
  stgExpPush exp

gExp exp@(PosExpThunk _ (tag@(PosVar _ v):args)) =
-- #ifdef DBGTRANS
--  gState >>>= \state ->
--  let vid = tidIS state v in
--  if False {-vid `elem` [t_ap n | n <- [1..10]]-} then 
--    -- expensive test - change!
--    {- this has been removed already by Jan;
--       the idea was probably to make the ap combinators strict in
--       their arguments to make them more efficient -} 
--      mapS (\a -> gExp a >>>= \a' -> unitS (a' ++ [EVAL])) args >>>= \args' ->
--      getExtra v >>>= \(_, extra) ->
--      unitS (concat args' ++ [PUSH_HEAP, HEAP_VAP v] ++ extra
--	      ++ map HEAP (reverse [1..length args]) ++ [SLIDE (length args)])
--  else
--      stgExpPush exp
--  #else
  stgExpPush exp
-- #endif

gExp atom =
  gAtom atom

gAlt c (PosAltCon pos con args exp) = 
  let nargs = length args
  in 
    cloneDH >>>
    decDepth 1 >>> -- UNPACK remove one element
    pushStack (reverse (map snd args)) >>>
    gUnique >>>= \ u -> 
    gExp exp >>>= \ exp ->
    decDepth nargs >>>
    popEnv >>>
    unitS ((GALT_CON con,u), LABEL u : UNPACK nargs : exp ++ [SLIDE nargs,JUMP c])
gAlt c (PosAltInt pos i      exp) =
  cloneDH >>>
  gUnique >>>= \ u -> 
  decDepth 1 >>> -- POP 1 remove one element
  gExp exp >>>= \ (exp) ->
  unitS ((GALT_INT i,u), LABEL u : POP 1 : exp ++ [JUMP c])

gAtom (PosExpThunk pos [e]) =
  gAtom e
gAtom (PosCon pos i) =
  incDepth >>> unitS [PUSH_GLB con0 i]
gAtom (PosVar pos i) =
  gWhere i >>>= \ w ->
  case w of
    Nothing -> incDepth >>>
		 gArity i >>>= \ a ->
		   if isJust a && dropJust a == 0 then 
		     unitS [PUSH_GLB caf i]
		   else
		     unitS [PUSH_GLB cap0 i]
    Just (Arg i) -> incDepth >>> unitS [PUSH_ARG i]
    Just (Stack i) -> incDepth >>> unitS [PUSH i]
gAtom (PosInt pos i) = incDepth >>> unitS [PUSH_INT i]
gAtom (PosChar pos i) = incDepth >>> unitS [PUSH_CHAR i]
gAtom (PosFloat pos f) = incDepth >>> unitS [PUSH_FLOAT f]
gAtom (PosDouble pos d) = incDepth >>> unitS [PUSH_DOUBLE d]
-- #ifdef DBGTRANS
-- gAtom (PosInteger pos i) = incDepth >>> unitS [PUSH_INT (fromInteger i)]
-- #else
gAtom (PosInteger pos i) = incDepth >>> unitS [PUSH_INTEGER i]
-- #endif
gAtom atom = stgExpPush atom

Index

(HTML for this module was generated on May 15, 2003. About the conversion tool.)