FreeVar

Plain source file: FreeVar.hs (Jun 16, 2000)

FreeVar is imported by: Main.

module FreeVar(freeVar) where

import State
import PosCode
import SyntaxPos
import Extra(singletonSet,emptySet,unionSet,removeSet,strPos,noPos,Pos(..),pair,dropJust)
import IntState
import IdKind
--------- ===========

data FreeDown =
  FreeDown
    Bool			-- Strict
    Bool			-- keep Case

data FreeThread =
  FreeThread
    [[Int]]			-- envs
    IntState

freeVar keepcase code state = 
  case (mapS freeBindingTop code) (FreeDown True keepcase) (FreeThread [] state) of
    (f_code,FreeThread envs state) -> (map snd f_code,state)

-------

freeString pos string =
  unitS (emptySet,PosExpLambda pos [] [] (PosExpThunk pos [PosPrim pos STRING,PosString pos string]))

freeLambda pos _ args exp =
  freeStrict True $
     freePushEnv (map snd args) >>>
     freeExp exp >>>= \ (expF,exp) ->
     freePopEnv >>>
     let envs = removeSet expF (map snd args)
     in unitS (envs,PosExpLambda pos (map (pair pos) envs) args exp)

freeBindingTop (fun,body) =
  freeBindingLow True fun body

freeBinding (fun,body@(PosLambda pos envs [] exp)) =
  freeBindingLow False fun body
freeBinding (fun,body@(PosLambda pos envs (_:_) exp)) =
  freeBindingLow True fun body
freeBinding (fun,body@(PosPrimitive pos fn)) =
  freeBindingLow True fun body
freeBinding (fun,body@(PosForeign pos fn t c ie)) =
  freeBindingLow True fun body

freeBindingLow strict fun (PosLambda pos envs args exp) =
  freeStrict strict $
  freePushEnv (map snd args) >>>
  freeExp exp >>>= \ (expF,exp) ->
  freePopEnv >>>
  let envs  = removeSet expF (map snd args)
      envsL = removeSet envs (singletonSet fun)
  in unitS (envsL,(fun,PosLambda pos (map (pair pos) envs) args exp))
freeBindingLow strict fun (PosPrimitive pos fn) =
  unitS (emptySet,(fun,PosPrimitive pos fn))
freeBindingLow strict fun (PosForeign pos fn t c ie) =
  unitS (emptySet,(fun,PosForeign pos fn t c ie))

freeExp (PosExpLambda pos envs args exp)  = freeLambda pos envs args exp
freeExp (PosExpDict exp)    = freeExp exp -- not needed any more
freeExp (PosExpLet pos bindings exp)    =
  freePushEnv (map fst bindings) >>>
  mapS freeBinding bindings >>>= \ f_bindings ->
  case unzip f_bindings of 
    (bindingFs,bindings) ->
      freeExp exp >>>= \ (expF,exp) ->
        freePopEnv >>>
        let free = removeSet (foldr unionSet expF bindingFs) (map fst bindings)
	in unitS (free,PosExpLet pos bindings exp)
freeExp e@(PosExpCase pos exp alts) =
  freeQStrict >>>= \ strict ->
  if strict
  then
    mapS freeAlt alts >>>= \ f_alts ->
    case unzip f_alts of
      (altFs,alts) ->
	 freeExp exp >>>= \ (expF,exp) ->
         let free = foldr unionSet expF altFs
         in unitS (free,PosExpCase pos exp alts)
  else freeLambda pos [] [] e
freeExp e@(PosExpFatBar b e1 e2) =
  freeQStrict >>>= \ strict ->
  if strict
  then
    freeExp e1 >>>= \ (e1F,e1) ->
    freeExp e2 >>>= \ (e2F,e2) ->
    unitS (unionSet e1F e2F, PosExpFatBar b e1 e2)
  else freeLambda noPos [] [] e
freeExp (PosExpFail) = unitS (emptySet,PosExpFail)
freeExp e@(PosExpIf pos c e1 e2)       =
  freeQStrict >>>= \ strict ->
  if strict
  then
    freeExp c >>>= \ (cF,c) ->
    freeExp e1 >>>= \ (e1F,e1) ->
    freeExp e2 >>>= \ (e2F,e2) ->
    unitS (unionSet cF (unionSet e1F e2F), PosExpIf pos c e1 e2)
  else freeLambda pos [] [] e
freeExp (PosExpApp pos (econ@(PosCon cpos con):args)) =
  freeArity con >>>= \ arity ->
  let available = length args
  in if available < arity
     then freeNewArgs (arity-available) >>>= \ nargs ->
	  freeLambda pos [] (map (pair pos) nargs) (PosExpThunk pos (econ:args ++ map (PosVar pos) nargs))
     else if available == arity -- Yes I'm paranoid !!!
	  then freeExp (PosExpThunk pos (econ:args))
	  else error ("Too many arguments to constructor " ++ " wants " ++ show arity
			 ++ " but got " ++ show available)
freeExp (PosExpApp pos (f:es)) =
  freeExp f >>>= \ (fF,f) ->
  freeStrict False (mapS freeExp es) >>>= \ f_es ->
  case unzip f_es of
    (eFs,es) ->
      unitS (foldr unionSet fF eFs, posExpApp pos (f:es))

freeExp e@(PosExpThunk pos (c@(PosCon _ con):es)) = -- A con with correct number of arguments
  freeQStrict >>>= \ strict ->
  freeConStrict con >>>= \ conStrict ->
  if strict || not (or conStrict)
  then
    freeStrict False (mapS freeExp es) >>>= \ f_es ->
    case unzip f_es of
      (eFs,es) ->
        unitS (foldr unionSet emptySet eFs, PosExpThunk pos (c:es))
  else freeLambda pos [] [] e
freeExp (PosExpThunk pos (f:es)) = -- A primitive/con with correct number of arguments
  freeStrict False (mapS freeExp es) >>>= \ f_es ->
  case unzip f_es of
    (eFs,es) ->
      unitS (foldr unionSet emptySet eFs, PosExpThunk pos (f:es))
freeExp con@(PosCon pos _) = freeExp (PosExpApp pos [con])
freeExp exp@(PosVar pos i) = freeIdent exp i
freeExp (PosString pos string) = freeString pos string
freeExp exp = unitS (emptySet,exp)

freeAlt (PosAltCon pos con args exp) =
  freePushEnv (map snd args) >>>
  freeExp exp >>>= \ (expF,exp) ->
  freePopEnv >>>
  unitS (removeSet expF (map snd args),PosAltCon pos con args exp)
freeAlt (PosAltInt pos int      exp) =
  freeExp exp >>>= \ (expF,exp) ->
  unitS (expF,PosAltInt pos int  exp)

freeIdent exp ident down up@(FreeThread envs state) =
  if any (ident `elem`) envs 
  then ((singletonSet ident,exp),up)
  else ((emptySet,exp),up)

-------------

freePushEnv envs' down up@(FreeThread envs state) =
  FreeThread (envs':envs) state

freePopEnv down up@(FreeThread (_:envs) state) =
  FreeThread envs state

freeArity con down up@(FreeThread envs state) =
  case  lookupIS state con of
    Just conInfo -> (arityVI conInfo,up)

freeQStrict down@(FreeDown strict keepcase) up =
  (strict || keepcase,up)

freeStrict strict free down@(FreeDown _ keepcase) up =
  free (FreeDown strict keepcase) up

freeNewArgs n down  up@(FreeThread envs state) =
 case mkArgs [] state n of
   (args,state) -> (args,(FreeThread envs state))
 where
  mkArgs a state 0 = (a,state)
  mkArgs a state n = case uniqueIS state of (u,state) -> mkArgs (u:a) state (n-1)

freeConStrict con  down up@(FreeThread envs state) =
  ((strictI . dropJust . lookupIS state) con, up)

Index

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