module STGGcode where -- (stgGcode) where
import Util.Extra(pos2Int)
import Maybe
import Id
import State
import PosCode
import Gcode
import GcodeLow(con0,cap0,caf)
import STGState
import STGBuild
import ForeignCode(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 = fromJust (lookup var2 (zip (map snd posargs) [1..]))
in unitS (STARTFUN (pos2Int pos) fun : needstack 1 [ SELECTOR_EVAL, SELECT no ])
else -- Ugly duplication of code
setFun (fromEnum fun) >>>
pushEnv (zip (map (fromEnum.snd) args) (map Arg [1..])) >>>
gExp exp >>>= \ exp ->
popEnv >>>
maxDepth >>>= \ d ->
unitS (STARTFUN (pos2Int pos) fun : needstack d ( exp ++ [RETURN_EVAL]))
gBindingTop (fun,PosLambda pos _ env args exp) =
setFun (fromEnum fun) >>>
pushEnv (zip (map (fromEnum.snd) args) (map Arg [1..])) >>>
gExp exp >>>= \ exp ->
popEnv >>>
maxDepth >>>= \ d ->
unitS (STARTFUN (pos2Int pos) fun : needstack d (exp ++ [RETURN_EVAL]))
gBindingTop (fun,PosPrimitive pos fn) =
setFun (fromEnum fun) >>>
gArity (fromEnum fun) >>>= \ (Just arity) ->
unitS (STARTFUN (pos2Int pos) fun: concatMap ( \ p -> [PUSH_ARG p, EVAL, POP 1] ) [1 .. arity] ++
[PRIMITIVE, DATA_CLABEL (fromEnum fn), RETURN_EVAL ])
gBindingTop (fun,PosForeign pos fn _ str c ie) =
setFun (fromEnum fun) >>>
gArity (fromEnum fun) >>>= \ (Just arity) ->
makeForeign str arity fn c ie >>>
case ie of
Imported ->
unitS
(STARTFUN (pos2Int pos) fun:
concatMap ( \ p -> [PUSH_ARG p, EVAL, POP 1] ) [1 .. arity] ++
[ PRIMITIVE , DATA_FLABEL (fromEnum 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' _ _ _ 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 -> (fromEnum v,HeapLate)) addId
newEnv = addEnv:env
size = length addId
in
-- strace ("STGGCode PosExpLet addLate " ++ show (map fst addLate) ++ " addId " ++ show addId) $
(pushStack (map fromEnum 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 (fromEnum c)])
gExp (PosExpFatBar esc exp1 exp2) =
pushDH >>>
pushFail >>>= \ fail ->
gUnique >>>= \ after ->
gExp exp1 >>>= \ exp1 ->
popFail >>>
popDH >>>
gExp exp2 >>>= \ exp2 ->
unitS (exp1 ++ JUMP (fromEnum after) : LABEL fail : exp2 ++ [LABEL (fromEnum 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 (fromEnum false): exp2 ++ JUMP (fromEnum after):LABEL (fromEnum false):exp3 ++ [LABEL (fromEnum 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 (fromEnum.snd) args)) >>>
gUnique >>>= \ u ->
gExp exp >>>= \ exp ->
decDepth nargs >>>
popEnv >>>
unitS ((GALT_CON (fromEnum con), fromEnum u), LABEL (fromEnum u) : UNPACK nargs : exp ++ [SLIDE nargs,JUMP (fromEnum c)])
gAlt c (PosAltInt pos i _ exp) =
cloneDH >>>
gUnique >>>= \ u ->
decDepth 1 >>> -- POP 1 remove one element
gExp exp >>>= \ (exp) ->
unitS ((GALT_INT i, fromEnum u), LABEL (fromEnum u) : POP 1 : exp ++ [JUMP (fromEnum c)])
gAtom (PosExpThunk pos _ [e]) =
gAtom e
gAtom (PosCon pos i) =
incDepth >>> unitS [PUSH_GLB con0 (fromEnum i)]
gAtom (PosVar pos i) =
gWhere (fromEnum i) >>>= \ w ->
case w of
Nothing -> incDepth >>>
gArity (fromEnum i) >>>= \ a ->
if isJust a && fromJust a == 0 then
unitS [PUSH_GLB caf (fromEnum i)]
else
unitS [PUSH_GLB cap0 (fromEnum i)]
Just (Arg i) -> incDepth >>> unitS [PUSH_ARG (fromEnum i)]
Just (Stack i) -> incDepth >>> unitS [PUSH (fromEnum 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
|