module STGBuild(stgExpPush,stgBodyPush) where
import Util.Extra
import Maybe
import Id
import State
import PosCode
import Gcode
import GcodeLow(con0,cap0,caf)
import STGState(Where(Arg,Stack,Heap,HeapLate,Direct),Thread(Thread)
,updTOS,popEnv,updHeap,getExtra,incDepthIf,gArity
,lateWhere,gWhereAbs)
stgExpPush :: PosExp -> State a Thread [Gcode] Thread
stgExpPush exp = unitS fst =>>> buildExp True exp
stgBodyPush :: (Id,PosLambda) -> State a Thread ([Gcode],(Int,Where)) Thread
stgBodyPush exp = buildBody True exp
buildBody pu (fun,PosLambda pos _ _ _ exp) =
buildExp pu exp >>>= \ (build,ptr) ->
updTOS pu fun >>>
unitS (build,(fromEnum fun,ptr))
buildExp :: Bool -> PosExp -> State a Thread ([Gcode],Where) Thread
buildExp pu (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' _ _ depth' heap' depthstack' fs')
= mapS (buildBody False) 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
in
-- strace ("STGGBuild PosExpLet addLate " ++ show (map fst addLate) ++ " addId " ++ show addId) $
(buildExp pu exp >>>= \ (eBuild,ptr) ->
popEnv >>>
unitS (concat bBuild ++ eBuild,ptr)
) down (Thread prof' fun' maxDepth' failstack' state' newEnv (addLate:lateenv) depth' heap' depthstack' fs')
buildExp pu (PosExpThunk _ _ (tag@(PosCon _ v):args)) =
-- Should evaluate strict arguments
mapS (buildExp False) args >>>= \ build_ptr ->
incDepthIf pu >>>= \ sp ->
case unzip build_ptr of
(build,ptr) ->
-- strace ("buildExp " ++ show pu ++ " " ++ show ptr) $
getExtra (fromEnum v) >>>= \ (e,extra) ->
updHeap (1+e+length ptr) >>>= \ hp ->
-- strace ("buildExp " ++ show pu ++ " " ++ show hp) $
unitS (concat build ++ pushHeapIf True pu
(HEAP_CON (fromEnum v) : extra ++ (zipWith (heapPtr sp) [hp+1+e .. ] ptr))
,Heap hp
)
buildExp pu (PosExpThunk _ _ (tag@(PosVar _ v):args)) =
mapS (buildExp False) args >>>= \ build_ptr ->
buildAp pu (fromEnum v) build_ptr
buildExp pu (PosExpThunk pos _ [e]) =
buildExp pu e
buildExp pu (PosCon pos i) =
oneHeap True pu (HEAP_GLB con0 (fromEnum i))
-- gArity i >>>= \ a ->
-- if isJust a && fromJust a == 0 then
-- oneHeap True pu (HEAP_GLB con0 i)
-- else
-- -- Can only happen with a constructor wrapped in NTBuiltin
-- oneHeap True pu (HEAP_GLB profconstructor i)
buildExp pu (PosVar pos i) =
incDepthIf pu >>>= \ sp ->
gWhereAbs (fromEnum i) >>>= \ w ->
case w of
Nothing -> gArity (fromEnum i) >>>= \ a ->
if isJust a && fromJust a == 0 then
oneHeap False pu (HEAP_GLB caf (fromEnum i))
else
oneHeap True pu (HEAP_GLB cap0 (fromEnum i))
Just (Arg i) -> oneHeap False pu (HEAP_ARG i)
Just (Stack i) -> -- Could be improved if we knew if Stack i is evaluated !!!
if pu then
updHeap 1 >>>= \ hp -> unitS ([PUSH_HEAP,HEAP (sp-i)], Heap hp)
else
unitS ([],Stack i)
Just (Heap i) -> -- Could be improved if we knew if Heap i is evaluated !!!
if pu then
updHeap 1 >>>= \ hp -> unitS ([PUSH_HEAP,HEAP_OFF (i-hp)], Heap hp)
else
unitS ([],Heap i)
Just (HeapLate) -> lateWhere (fromEnum i) >>>= \ lw ->
if pu then
updHeap 1 >>>= \ hp -> unitS ([PUSH_HEAP,case lw of
Stack i -> HEAP (sp-i)
Heap i -> HEAP_OFF (i-hp)
Direct g -> g],Heap hp)
else
unitS ([],lw)
buildExp pu (PosInt pos i) = oneHeap True pu (HEAP_INT i)
buildExp pu (PosChar pos i) = oneHeap True pu (HEAP_CHAR i)
buildExp pu (PosFloat pos f) = oneHeap True pu (HEAP_FLOAT f )
buildExp pu (PosDouble pos d) = oneHeap True pu (HEAP_DOUBLE d)
-- \#ifdef DBGTRANS
-- buildExp pu (PosInteger pos i) = oneHeap True pu (HEAP_INT (fromInteger i))
-- \#else
buildExp pu (PosInteger pos i) = oneHeap True pu (HEAP_INTEGER i)
-- \#endif
buildExp pu (PosString pos s) = oneHeap False pu (HEAP_STRING s)
buildExp pu (PosExpCase pos exp alts) =
error ("buildExp Case " ++ strPos pos)
buildExp pu (PosExpFatBar esc exp1 exp2) =
error ("buildExp FatBar ")
buildExp pu (PosExpFail) =
error ("buildExp Fail ")
buildExp pu (PosExpIf pos _ exp1 exp2 exp3) =
error ("buildExp If " ++ strPos pos)
buildExp pu (PosExpThunk pos _ [PosPrim _ STRING _,PosString _ s]) =
error ("buildExp STRING " ++ strPos pos)
buildExp pu (PosExpThunk pos _ [PosPrim _ SEQ _,a1,a2]) =
error ("buildExp SEQ " ++ strPos pos)
buildExp pu (PosExpThunk pos _ (PosPrim _ p _:args)) =
error ("buildExp Prim " ++ strPos pos)
buildExp pu (PosExpApp pos (fun:args)) =
error ("buildExp App " ++ strPos pos)
buildAp :: Bool -> Int -> [([Gcode],Where)]
-> State a Thread ([Gcode],Where) Thread
buildAp pu v build_ptr =
incDepthIf pu >>>= \ sp ->
case unzip build_ptr of
(build,ptr) ->
getExtra (toEnum v) >>>= \ (e,extra) ->
gArity v >>>= \(Just arity) -> -- Always a global here!
let nargs = length ptr
in
updHeap (1+e+nargs) >>>= \ hp ->
unitS (concat build ++ (if nargs == arity
then pushHeapIf False pu (HEAP_VAP (toEnum v):extra)
else pushHeapIf True pu (HEAP_CAP (toEnum v) (arity-nargs):extra)
) ++ zipWith (heapPtr sp) [hp+1+e .. ] ptr
,Heap hp
)
oneHeap :: Bool -> Bool -> Gcode -> State a Thread ([Gcode],Where) Thread
oneHeap True True ptr =
updHeap 1 >>>= \ hp -> unitS ([PUSH_HEAP,EVALUATED,ptr], Heap hp)
oneHeap False True ptr =
updHeap 1 >>>= \ hp -> unitS ([PUSH_HEAP,ptr], Heap hp)
oneHeap _ False ptr = unitS ([] , Direct ptr)
pushHeapIf True True gs = PUSH_HEAP : EVALUATED : gs
pushHeapIf False True gs = PUSH_HEAP : gs
pushHeapIf _ False gs = gs
heapPtr sp hp (Arg a) = PUSH_ARG a
heapPtr sp hp (Stack i) = HEAP (sp-i)
heapPtr sp hp (Heap i) = HEAP_OFF (i-hp)
heapPtr sp hp (Direct ins) = ins
|