module PosAtom(posAtom) where import IntState import Id import PosCode -- hiding (isPosAtom) import State import TokenId(tidPos,tunknown) import Util.Extra(unionSet,removeSet,pair) import TokenId(visible) import SyntaxPos import Maybe -- isPosAtom x = True -- A (not so) small lie data AtomDown = AtomDown TokenId -- current function [Id] -- current env data AtomState = AtomState IntState PosCode posAtom :: IntState -> [(Id,PosLambda)] -> ([(Id,PosLambda)],IntState) posAtom state code = case (mapS atomTopBinding code) (AtomDown tunknown []) (AtomState state []) of (code,AtomState state _) -> (concat code,state) atomTopBinding (fun,PosLambda pos int [] args exp) = atomTid fun >=> atomEnv (map snd args) >=> atomExp exp >>>= \ exp -> atomTop >>>= \ bs -> unitS ((fun,PosLambda pos int [] args exp):bs) atomTopBinding (fun,PosPrimitive pos fn) = unitS [(fun,PosPrimitive pos fn)] atomTopBinding (fun,PosForeign pos fn ar t c ie) = unitS [(fun,PosForeign pos fn ar t c ie)] atomBinding (fun,PosLambda pos int envs [] exp) = -- no functions left atomExp exp >>>= \ exp -> flattenExp fun pos int envs exp atomBinding (fun,PosPrimitive pos fn) = unitS [(fun,PosPrimitive pos fn)] atomBinding (fun,PosForeign pos fn ar t c ie) = unitS [(fun,PosForeign pos fn ar t c ie)] -- Forgot why I do this! The isPosAtom used was forced to be true due to local definition? flattenExp fun pos int envs exp = unitS [(fun,PosLambda pos int envs [] exp)] -- !!! envs might be too large !!! {- --flattenExp fun pos envs (PosExpLet _ bindings' exp) = -- flattenExp fun pos envs exp >>>= \ bindings -> -- unitS (bindings' ++ bindings) flattenExp fun pos envs exp@(PosExpThunk _ (f:es)) | isntPrim f = unitS [(fun,PosLambda pos envs [] exp)] -- !!! envs might be too large !!! flattenExp fun pos envs exp = if isPosAtom exp then unitS [(fun,PosLambda pos envs [] exp)] -- !!! envs might be too large !!! else atomAddG pos exp >>>= \ exp -> unitS [(fun,exp)] -} atomExp (PosExpLet rec pos bindings exp) = atomEnv (map fst bindings) >=> unitS (PosExpLet rec pos . concat) =>>> mapS atomBinding bindings =>>> atomExp exp atomExp (PosExpCase pos exp alts) = unitS (PosExpCase pos) =>>> atomExp exp =>>> mapS atomAlt alts atomExp (PosExpFatBar b e1 e2) = unitS (PosExpFatBar b) =>>> atomExp e1 =>>> atomExp e2 atomExp (PosExpFail) = unitS PosExpFail atomExp (PosExpIf pos g c e1 e2) = unitS (PosExpIf pos g) =>>> atomExp c =>>> atomExp e1 =>>> atomExp e2 atomExp (PosExpApp pos (f:es)) = -- First doesn't need to be an atom in byte-code back-end atomExp f >>>= \ f -> mapS ensureAtom es >>>= \ a_b -> case unzip a_b of (as,bs) -> mapS atomBinding (concat bs) >>>= \ bs -> unitS (posExpLet pos (concat bs) (posExpApp pos (f:as))) atomExp (PosExpThunk pos ap (f@(PosCon _ con):es)) = mapS atomExp es >>>= \ es -> atomStrict con >>>= \ s -> if and s then mapS ensureAtom es >>>= \ a_b -> case unzip a_b of (as,bs) -> mapS atomBinding (concat bs) >>>= \ bs -> unitS (posExpLet pos (concat bs) (foldr posStrict (PosExpThunk pos ap (f:as)) (zip s as) )) else unitS (PosExpThunk pos ap (f:es)) atomExp (PosExpThunk pos ap (f@(PosPrim _ _ _):es)) = mapS atomExp es >>>= \ es -> -- Byte code back-end can handle arbitrary arguments to byte code instructions unitS (PosExpThunk pos ap (f:es)) atomExp (PosExpThunk pos ap (f:es)) = -- First is a function mapS atomExp es >>>= \ es -> -- Byte code back-end can handle arbitrary arguments in thunks unitS (PosExpThunk pos ap (f:es)) {- mapS ensureAtom es >>>= \ a_b -> case unzip a_b of (as,bs) -> mapS atomBinding (concat bs) >>>= \ bs -> unitS (posExpLet pos (concat bs) (PosExpThunk pos (f:as))) -} atomExp e = unitS e atomAlt (PosAltCon pos con args exp) = unitS (PosAltCon pos con args) =>>> (atomEnv (map snd args) >=> atomExp exp) atomAlt (PosAltInt pos int b exp) = unitS (PosAltInt pos int b) =>>> atomExp exp posStrict (True,PosExpThunk _ _ [atom]) e = posStrict (True,atom) e posStrict (True,a@(PosVar pos v)) e = PosExpThunk pos False [PosPrim pos SEQ v, a, e] posStrict a e = e ensureAtom exp = if isPosAtom exp then unitS (exp,[]) else atomAdd (getPos exp) exp atomTop down up@(AtomState state bs) = (bs,AtomState state []) atomAdd pos exp down@(AtomDown tid env) up@(AtomState state bs) = case uniqueIS state of (u,state) -> ((PosVar pos u,[(u,PosLambda pos LamFLNone (map (pair pos) (filter (`elem` env) (freePosExp exp))) [] exp)]) ,AtomState (addIS u (InfoName u (visible (reverse ("ATOM" ++ show u))) 0 (tidPos tid pos) True) state) bs --PHtprof ) {- atomAddG pos exp down@(AtomDown tid env) up@(AtomState state bs) = case uniqueIS state of (u,state) -> let newenv = filter (`elem` env) (freePosExp exp) pnewenv = map (pair pos) newenv in (PosLambda pos pnewenv [] (PosExpThunk pos (PosVar pos u: map (uncurry PosVar) pnewenv)) ,AtomState (addIS u (InfoName u (visible (reverse ("ATOM" ++ show u))) (length pnewenv) (tidPos tid pos) True) state) --PHtprof ((u,PosLambda pos [] pnewenv exp): bs) ) -} atomStrict con down@(AtomDown tid env) up@(AtomState state bs) = ((strictI . fromJust . lookupIS state) con, up) atomTid fun down@(AtomDown tid env) up@(AtomState state bs) = let tid = (profI . fromJust . lookupIS state) fun in seq tid (AtomDown tid env,up) atomEnv :: [Id] -> AtomDown -> AtomState -> (AtomDown,AtomState) atomEnv newenv down@(AtomDown tid env) up@(AtomState state bs) = (AtomDown tid (newenv ++ env),up) ---------------------------------- freePosLambda (PosLambda pos int env arg exp) = map snd env -- Don't need to go deeper freePosLambda (PosPrimitive pos p) = [] freePosLambda (PosForeign pos p ar t c ie) = [] freePosExp (PosExpLet rec pos bindings exp) = foldr unionSet (freePosExp exp) (map (freePosLambda . snd) bindings) `removeSet` map fst bindings freePosExp (PosExpCase pos cExp alts) = foldr unionSet (freePosExp cExp) (map freePosAlt alts) freePosExp (PosExpApp pos es) = foldr unionSet [] (map freePosExp es) freePosExp (PosExpThunk pos ap es) = foldr unionSet [] (map freePosExp es) freePosExp (PosExpFatBar b exp1 exp2) = freePosExp exp1 `unionSet` freePosExp exp2 freePosExp (PosExpFail) = [] freePosExp (PosExpIf pos g cExp tExp eExp) = (freePosExp cExp `unionSet` freePosExp tExp `unionSet` freePosExp eExp) freePosExp (PosVar pos v) = [v] freePosExp (PosCon pos c) = [] freePosExp (PosInt pos v) = [] freePosExp (PosChar pos v) = [] freePosExp (PosFloat pos v) = [] freePosExp (PosDouble pos v) = [] freePosExp (PosInteger pos v) = [] freePosExp (PosString pos v) = [] freePosExp (PosPrim pos prim v) = [] freePosAlt (PosAltCon pos con args exp) = freePosExp exp `removeSet` (map snd args) freePosAlt (PosAltInt pos int b exp) = freePosExp exp