{-# OPTIONS_GHC -funbox-strict-fields #-} module Grin.Grin( Callable(..), Exp(..), FuncDef(..), FuncProps(..), Grin(..), TyThunk(..), Lam(..), Phase(..), BaseOp(..), Tag, updateFuncDefProps, Ty(..), TyEnv(..), TyTy(..), tyTy, Val(..), Var(..), extendTyEnv, createFuncDef, setGrinFunctions, grinFuncs, emptyGrin, tyINode, tyDNode, findArgs, findArgsType, findTyTy, gEval, grinEntryPointNames, isHole, isValUnknown, isVar, n0,n1,n2,n3, p0,p1,p2,p3, partialTag, phaseEvalInlined, properHole, tagFlipFunction, tagHole, tagInfo, TagInfo(..), tagIsFunction, tagIsPartialAp, tagIsSuspFunction, tagIsTag, tagIsWHNF, tagToFunction, tagUnfunction, v0,v1,v2,v3,lamExp,lamBind, valIsNF ) where import Control.Monad.Identity import Data.Char import Data.Monoid(Monoid(..)) import Data.List(isPrefixOf) import qualified Data.Set as Set import C.FFI import C.Prims import Cmm.Number import Doc.DocLike import Name.VConsts import Options import StringTable.Atom import Support.CanType import Support.FreeVars import Util.GMap import Util.Gen import Util.HasSize import Util.Perhaps import Util.SetLike import qualified Cmm.Op as Op import qualified Info.Info as Info import qualified Stats -- Extremely simple first order monadic code with basic type system. similar -- to GRIN except for the explicit typing on variables. Note, that certain -- haskell types become Grin values, however, nothing may be done with types other -- than examining them. (types may not be constructed at run-time) infixr 1 :->, :>>= -- The basic operations of our monad -- -- PeekVal and PokeVal differ from the primitive peek and poke in that the Val -- varients operate on node references, while the primitive versions work on -- raw memory with unboxed pointers. -- data BaseOp = Demote -- turn a node into an inode, always okay | Promote -- turn an inode into a node, the inode _must_ already be a valid node | Eval -- evaluate an inode, returns a node representing the evaluated value. Bool is whether to update the inode | Apply [Ty] -- apply a partial application to a value, returning the given type | StoreNode !Bool -- create a new node, Bool is true if it should be a direct node, the second val is the region | Redirect -- write an indirection over its first argument to point to its second one | Overwrite -- overwrite an existing node with new data (the tag must match what was used for the initial Store) | PeekVal -- read a value from a pointed to location | PokeVal -- write a value to a pointed to location | Consume -- consume a value, depending on the back end this may be used to free memory | GcTouch -- touch a value, forcing the GC to hold onto it. | Coerce Ty -- coerce one type to another, danger zone. This is for reflection/rts and not for integral conversions. | GcPush -- push some pointers onto the GC stack, returning registers representing the values on the stack | NewRegister -- create a new register | ReadRegister -- read a register | WriteRegister -- write to a register deriving(Eq,Ord,Show) data Lam = [Val] :-> Exp deriving(Eq,Ord,Show) data Exp = Exp :>>= Lam -- ^ Sequencing - the same as >>= for monads. | BaseOp { expBaseOp :: BaseOp, expArgs :: [Val] } | App { expFunction :: Atom, expArgs :: [Val], expType :: [Ty] } -- ^ Application of functions and builtins | Prim { expPrimitive :: Prim, expArgs :: [Val], expType :: [Ty] } -- ^ Primitive operation | Case { expValue :: Val, expAlts :: [Lam] } -- ^ Case statement | Return { expValues :: [Val] } -- ^ Return a value | Error { expError :: String, expType :: [Ty] } -- ^ Abort with an error message, non recoverably. | Call { expValue :: Val, expArgs :: [Val], expType :: [Ty], expJump :: Bool, -- ^ Jump is equivalent to a call except it deallocates the region it resides in before transfering control expFuncProps :: FuncProps, expInfo :: Info.Info } -- ^ Call or jump to a callable | NewRegion { expLam :: Lam, expInfo :: Info.Info } -- ^ create a new region and pass it to its argument | Alloc { expValue :: Val, expCount :: Val, expRegion :: Val, expInfo :: Info.Info } -- ^ allocate space for a number of values in the given region | Let { expDefs :: [FuncDef], expBody :: Exp, expFuncCalls :: (Set.Set Atom,Set.Set Atom), -- ^ cache expIsNormal :: Bool, -- ^ cache, True = definitely normal, False = maybe normal expNonNormal :: Set.Set Atom, -- ^ cache, a superset of functions called in non-tail call position. expInfo :: Info.Info } -- ^ A let of local functions | MkClosure { expValue :: Val, expArgs :: [Val], expRegion :: Val, expType :: [Ty], expInfo :: Info.Info } -- ^ create a closure | MkCont { expCont :: Lam, -- ^ the continuation routine expLam :: Lam, -- ^ the computation that is passed the newly created computation expInfo :: Info.Info } -- ^ Make a continuation, always allocated on region encompasing expLam | GcRoots { expValues :: [Val], -- ^ add some new variables to the GC roots for a subcomputation expBody :: Exp } deriving(Eq,Show,Ord) data Val = NodeC !Tag [Val] -- ^ Complete node, of type TyNode | Const Val -- ^ constant data, only Lit, Const and NodeC may be children. of type TyINode | Lit !Number Ty -- ^ Literal | Var !Var Ty -- ^ Variable | Unit -- ^ Empty value used as placeholder | ValPrim Prim [Val] Ty -- ^ Primitive value | Index Val Val -- ^ A pointer incremented some number of values (Index v 0) == v | Item Atom Ty -- ^ Specific named thing. function, global, region, etc.. | ValUnknown Ty -- ^ Unknown or unimportant value deriving(Eq,Ord) data Ty = TyPtr Ty -- ^ pointer to a memory location which contains its argument | TyNode -- ^ a whole node | TyINode -- ^ a whole possibly indirect node | TyAttr Ty Ty -- ^ attach an attribute to a type | TyAnd Ty Ty -- ^ boolean conjunction of types | TyOr Ty Ty -- ^ boolean disjunction of types | TyPrim Op.Ty -- ^ a basic type | TyUnit -- ^ type of Unit | TyCall Callable [Ty] [Ty] -- ^ something call,jump, or cut-to-able | TyRegion -- ^ a region | TyGcContext -- ^ the context for garbage collection | TyRegister Ty -- ^ a register contains a mutable value, the register itself cannot be addressed, -- hence they may not be returned from functions or passed as arguments. | TyComplex Ty -- ^ A complex version of a basic type | TyVector !Int Ty -- ^ A vector of a basic type | TyUnknown -- ^ an unknown possibly undefined type, All of these must be eliminated by code generation deriving(Eq,Ord) data Callable = Continuation | Function | Closure | LocalFunction | Primitive' deriving(Eq,Ord,Show) type Tag = Atom newtype Var = V Int deriving(Eq,Ord,Enum) data FuncDef = FuncDef { funcDefName :: Atom, funcDefBody :: Lam, funcDefCall :: Val, funcDefProps :: FuncProps } deriving(Eq,Ord,Show) -- Type information table (TyEnv) data TyThunk = TyNotThunk -- ^ not the thunk | TyPApp (Maybe Ty) Atom -- ^ can be applied to (possibly) an argument, and what results | TySusp Atom -- ^ can be evaluated and calls what function deriving(Eq,Show) data TyTy = TyTy { tySlots :: [Ty], tyReturn :: [Ty], tyThunk :: TyThunk, tySiblings :: Maybe [Atom] } tyTy = TyTy { tySlots = [], tyReturn = [], tySiblings = Nothing, tyThunk = TyNotThunk } newtype TyEnv = TyEnv (GMap Atom TyTy) deriving(Monoid) -- random utility values lamExp (_ :-> e) = e lamBind (b :-> _) = b isVar Var {} = True isVar _ = False tagHole = toAtom "@hole" gEval :: Val -> Exp gEval x = BaseOp Eval [x] -- | lazy node sptr_t tyINode = TyINode -- | strict node wptr_t tyDNode = TyNode createFuncDef local name body@(args :-> rest) = updateFuncDefProps FuncDef { funcDefName = name, funcDefBody = body, funcDefCall = call, funcDefProps = funcProps } where call = Item name (TyCall (if local then LocalFunction else Function) (map getType args) (getType rest)) updateFuncDefProps fd@FuncDef { funcDefBody = body@(args :-> rest) } = fd { funcDefProps = props } where props = (funcDefProps fd) { funcFreeVars = freeVars body, funcTags = freeVars body, funcType = (map getType args,getType rest) } grinFuncs grin = map (\x -> (funcDefName x, funcDefBody x)) (grinFunctions grin) setGrinFunctions xs _grin | flint && hasRepeatUnder fst xs = error $ "setGrinFunctions: grin has redundent definitions" ++ show (fsts xs) setGrinFunctions xs grin = grin { grinFunctions = map (uncurry (createFuncDef False)) xs } extendTyEnv ds (TyEnv env) = TyEnv (fromList xs `mappend` env) where xs = [ (funcDefName d,tyTy { tySlots = ss, tyReturn = r }) | d <- ds, let (ss,r) = funcType $ funcDefProps d] ++ [ (tagFlipFunction (funcDefName d),tyTy { tySlots = ss, tyReturn = r }) | d <- ds, let (ss,r) = funcType $ funcDefProps d, r == [TyNode]] -- cached info data FuncProps = FuncProps { funcInfo :: Info.Info, funcFreeVars :: Set.Set Var, funcTags :: Set.Set Tag, funcType :: ([Ty],[Ty]), funcExits :: Perhaps, -- ^ function quits the program funcCuts :: Perhaps, -- ^ function cuts to a value funcAllocs :: Perhaps, -- ^ function allocates memory funcCreates :: Perhaps, -- ^ function allocates memory and stores or returns it funcLoops :: Perhaps -- ^ function may loop } deriving(Eq,Ord,Show) funcProps = FuncProps { funcInfo = mempty, funcFreeVars = mempty, funcTags = mempty, funcType = undefined, funcExits = Maybe, funcCuts = Maybe, funcAllocs = Maybe, funcCreates = Maybe, funcLoops = Maybe } data Phase = PhaseInit | PostInlineEval | PostAeOptimize | PostDevolve deriving(Show,Eq,Ord,Enum) phaseEvalInlined e = e >= PostInlineEval data Grin = Grin { grinEntryPoints :: GMap Atom FfiExport, grinPhase :: !Phase, grinTypeEnv :: TyEnv, grinFunctions :: [FuncDef], grinSuspFunctions :: Set.Set Atom, grinPartFunctions :: Set.Set Atom, grinStats :: !Stats.Stat, grinCafs :: [(Var,Val)] } emptyGrin = Grin { grinEntryPoints = mempty, grinPhase = PhaseInit, grinTypeEnv = mempty, grinFunctions = [], grinSuspFunctions = mempty, grinPartFunctions = mempty, grinStats = mempty, grinCafs = mempty } grinEntryPointNames = keys . grinEntryPoints data TagInfo = TagPApp !Int !Atom -- partial application, number is how many more arguments needed | TagSusp !Bool !Atom -- a suspended version of the function, true if an update is required | TagDataCons -- data constructor | TagTypeCons -- type constructor | TagTypePApp !Int Tag -- type partial app | TagFunc tagInfo t = case fromAtom t of 'F':xs -> TagSusp True (toAtom $ 'f':xs) 'B':xs -> TagSusp True (toAtom $ 'b':xs) 'f':_ -> TagFunc 'b':_ -> TagFunc 'C':_ -> TagDataCons 'T':_ -> TagTypeCons 'P':is | (n@(_:_),('_':xs)) <- span isDigit is -> TagPApp (read n) (toAtom $ 'f':xs) 'Y':is | (n@(_:_),('_':xs)) <- span isDigit is -> TagTypePApp (read n) (toAtom $ 'T':xs) t -> error $ "tagInfo: bad tag " ++ t partialTag :: Tag -> Int -> Tag partialTag v c = case fromAtom v of ('f':xs) | 0 <- c -> toAtom $ 'F':xs | c > 0 -> toAtom $ 'P':show c ++ "_" ++ xs ('T':xs) | 0 <- c -> v | c > 0 -> toAtom $ 'Y':show c ++ "_" ++ xs ('b':xs) | 0 <- c -> toAtom $ 'B':xs _ -> error $ "partialTag: " ++ show (v,c) tagUnfunction :: Monad m => Tag -> m (Int, Tag) tagUnfunction t | tagIsSuspFunction t = return (0,tagFlipFunction t) | tagIsFunction t = return (0,t) | ('P':zs) <- t', (n@(_:_),'_':rs) <- span isDigit zs = return (read n, toAtom ('f':rs)) where t' = fromAtom t tagUnfunction _ = fail "Tag does not represent function" tagFlipFunction t | 'F':xs <- t' = toAtom $ 'f':xs | 'B':xs <- t' = toAtom $ 'b':xs | 'f':xs <- t' = toAtom $ 'F':xs | 'b':xs <- t' = toAtom $ 'B':xs | otherwise = error "Cannot FLIP non function." where t' = fromAtom t tagIsSuspFunction t | 'F':_ <- t' = True | 'B':_ <- t' = True | otherwise = False where t' = fromAtom t tagToFunction t | 'F':xs <- t' = return $ toAtom $ 'f':xs | 'B':xs <- t' = return $ toAtom $ 'b':xs | 'f':_ <- t' = return t | 'b':_ <- t' = return t | 'P':is <- t', ('_':xs) <- dropWhile isDigit is = return $ toAtom $ 'f':xs | otherwise = fail $ "Not Function: " ++ t' where t' = fromAtom t tagIsFunction t | 'f':_ <- t' = True | 'b':_ <- t' = True | otherwise = False where t' = fromAtom t tagIsPartialAp t | 'P':_ <- t' = True | otherwise = False where t' = fromAtom t tagIsTag t | 'P':_ <- t' = True | 'T':_ <- t' = True | 'C':_ <- t' = True | 'F':_ <- t' = True | 'B':_ <- t' = True | 'Y':_ <- t' = True | otherwise = False where t' = fromAtom t tagIsWHNF t | 'P':_ <- t' = True | 'T':_ <- t' = True | 'C':_ <- t' = True | 'Y':_ <- t' = True | otherwise = False where t' = fromAtom t valIsNF (NodeC t vs) = tagIsWHNF t && all valIsNF vs valIsNF Const {} = True valIsNF Lit {} = True valIsNF _ = False properHole x = case x of TyINode -> Const (properHole TyNode) ty@(TyPrim _) -> (Lit 0 ty) ~TyNode -> (NodeC tagHole []) isHole x = x `elem` map properHole [TyINode, TyNode] isValUnknown ValUnknown {} = True isValUnknown _ = False --------- -- Look up stuff in the typing environment. --------- findTyTy (TyEnv m) a | Just tyty <- mlookup a m = return tyty findTyTy (TyEnv m) a | ('Y':rs) <- fromAtom a, (ns,'_':rs) <- span isDigit rs = case mlookup (toAtom ('T':rs)) m of Just TyTy { tySlots = ts, tyReturn = n } -> return tyTy { tySlots = take (length ts - read ns) ts, tyReturn = n } Nothing -> fail $ "findArgsType: " ++ show a findTyTy _ a | "@hole" `isPrefixOf` fromAtom a = return tyTy { tySlots = [], tyReturn = [TyNode] } findTyTy _ a = fail $ "findArgsType: " ++ show a findArgsType m a = liftM (\tyty -> (tySlots tyty,tyReturn tyty)) (findTyTy m a) findArgs m a = case findArgsType m a of Nothing -> fail $ "findArgs: " ++ show a Just (as,_) -> return as v0 = V 0 v1 = V 1 v2 = V 2 v3 = V 3 n0 = Var v0 TyNode n1 = Var v1 TyNode n2 = Var v2 TyNode n3 = Var v3 TyNode p0 = Var v0 TyINode p1 = Var v1 TyINode p2 = Var v2 TyINode p3 = Var v3 TyINode -- CanType instances instance CanType Exp where type TypeOf Exp = [Ty] getType (_ :>>= (_ :-> e2)) = getType e2 getType (Prim _ _ ty) = ty getType App { expType = t } = t getType (BaseOp Overwrite _) = [] getType (BaseOp GcTouch _) = [] getType (BaseOp (Coerce t) _) = [t] getType (BaseOp Redirect _) = [] getType (BaseOp Promote _) = [TyNode] getType (BaseOp Demote _) = [TyINode] getType (BaseOp Eval _) = [TyNode] getType (BaseOp (StoreNode b) _) = if b then [TyNode] else [TyINode] getType (BaseOp NewRegister xs) = map (TyRegister . getType) xs getType (BaseOp WriteRegister _) = [] getType (BaseOp ReadRegister [r]) = case getType r of TyRegister t -> [t] _ -> error "Exp.getType: ReadRegister of non register" getType (BaseOp (Apply ty) _) = ty getType (BaseOp PeekVal [v]) = case getType v of TyPtr t -> [t] _ -> error "Exp.getType: PeekVal of non-pointer type" getType (BaseOp PokeVal _) = [] getType (Return v) = getType v getType (Error _ t) = t getType (Case _ []) = error "empty case" getType (Case _ ((_ :-> e):_)) = getType e getType NewRegion { expLam = _ :-> body } = getType body getType Alloc { expValue = v } = [TyPtr (getType v)] getType Let { expBody = body } = getType body getType MkCont { expLam = _ :-> rbody } = getType rbody getType Call { expType = ty } = ty getType MkClosure { expType = ty } = ty getType GcRoots { expBody = body } = getType body getType _ = error "Exp.getType: bad." instance CanType Val where type TypeOf Val = Ty getType (Var _ t) = t getType (Lit _ t) = t getType (Index v _) = getType v getType Unit = TyUnit getType (Const t) = case (getType t) of TyNode -> TyINode t -> error "Val.getType: Const of non-node" getType (NodeC {}) = TyNode getType (ValPrim _ _ ty) = ty getType (ValUnknown ty) = ty getType (Item _ ty) = ty -- FreeVars instances instance FreeVars Lam (Set.Set Var) where freeVars (x :-> y) = freeVars y Set.\\ freeVars x instance FreeVars Lam (Set.Set (Var,Ty)) where freeVars (x :-> y) = freeVars y Set.\\ freeVars x instance FreeVars Exp (Set.Set Var,Set.Set Tag) where freeVars x = (freeVars x, freeVars x) instance FreeVars Val (Set.Set Var) where freeVars (NodeC t xs) = freeVars xs freeVars (Const v) = freeVars v freeVars (Index a b) = freeVars (a,b) freeVars (Var v _) = Set.singleton v freeVars _ = Set.empty instance FreeVars Val (Set.Set (Var,Ty)) where freeVars (NodeC t xs) = freeVars xs freeVars (Const v) = freeVars v freeVars (Index a b) = freeVars (a,b) freeVars (Var v t) = Set.singleton (v,t) freeVars _ = Set.empty instance FreeVars FuncProps (Set.Set Var) where freeVars FuncProps { funcFreeVars = fv } = fv instance FreeVars FuncProps (Set.Set Tag) where freeVars FuncProps { funcTags = fv } = fv instance FreeVars FuncProps a => FreeVars FuncDef a where freeVars fd = freeVars (funcDefProps fd) instance FreeVars Exp (Set.Set Var) where freeVars (a :>>= b) = freeVars (a,b) freeVars (App a vs _) = freeVars vs freeVars (Case x xs) = freeVars (x,xs) freeVars (Return v) = freeVars v -- freeVars (Store v) = freeVars v freeVars (BaseOp _ vs) = freeVars vs freeVars (Prim _ x _) = freeVars x freeVars Error {} = Set.empty freeVars Let { expDefs = fdefs, expBody = body } = mconcat (map (funcFreeVars . funcDefProps) fdefs) `mappend` freeVars body freeVars NewRegion { expLam = l } = freeVars l freeVars Alloc { expValue = v, expCount = c, expRegion = r } = freeVars (v,c,r) freeVars Call { expValue = v, expArgs = as } = freeVars (v:as) freeVars MkClosure { expValue = v, expArgs = as, expRegion = r } = freeVars (v,as,r) freeVars MkCont { expCont = v, expLam = as} = freeVars (v,as) freeVars GcRoots { expValues = v, expBody = b } = freeVars (v,b) instance FreeVars Exp (Set.Set (Var,Ty)) where freeVars (a :>>= b) = freeVars (a,b) freeVars (App a vs _) = freeVars vs freeVars (Case x xs) = freeVars (x,xs) freeVars (Return v) = freeVars v -- freeVars (Store v) = freeVars v freeVars (BaseOp _ vs) = freeVars vs freeVars (Prim _ x _) = freeVars x freeVars Error {} = Set.empty freeVars Let { expDefs = fdefs, expBody = body } = mconcat (map (freeVars . funcDefBody) fdefs) `mappend` freeVars body freeVars NewRegion { expLam = l } = freeVars l freeVars Alloc { expValue = v, expCount = c, expRegion = r } = freeVars (v,c,r) freeVars Call { expValue = v, expArgs = as } = freeVars (v:as) freeVars MkClosure { expValue = v, expArgs = as, expRegion = r } = freeVars (v,as,r) freeVars MkCont { expCont = v, expLam = as} = freeVars (v,as) freeVars GcRoots { expValues = v, expBody = b } = freeVars (v,b) instance FreeVars Val (Set.Set Tag) where freeVars (NodeC t xs) = Set.singleton t `Set.union` freeVars xs freeVars (Index a b) = freeVars (a,b) freeVars (Const v) = freeVars v freeVars _ = Set.empty instance FreeVars Val [Tag] where freeVars v = Set.toList $ freeVars v instance FreeVars Exp [Tag] where freeVars v = Set.toList $ freeVars v instance FreeVars Lam (Set.Set Tag) where freeVars (a :-> b) = freeVars (a,b) instance FreeVars Exp (Set.Set Tag) where freeVars (a :>>= b) = freeVars (a,b) freeVars (App a vs _) = Set.singleton a `Set.union` freeVars vs freeVars (Case x xs) = freeVars (x,xs) freeVars (Return v) = freeVars v -- freeVars (Store v) = freeVars v freeVars (BaseOp _ vs) = freeVars vs freeVars (Prim _ x _) = freeVars x freeVars Error {} = Set.empty freeVars Let { expDefs = fdefs, expBody = body } = mconcat (map (funcTags . funcDefProps) fdefs) `mappend` freeVars body freeVars NewRegion { expLam = l } = freeVars l freeVars Alloc { expValue = v, expCount = c, expRegion = r } = freeVars (v,c,r) freeVars Call { expValue = v, expArgs = as } = freeVars (v:as) freeVars MkClosure { expValue = v, expArgs = as, expRegion = r } = freeVars (v,as,r) freeVars MkCont { expCont = v, expLam = as} = freeVars (v,as) freeVars GcRoots { expValues = v, expBody = b } = freeVars (v,b) instance FreeVars Lam (GSet Var) where freeVars (x :-> y) = freeVars y \\ freeVars x instance FreeVars Exp (GSet Var,GSet Tag) where freeVars x = (freeVars x, freeVars x) instance FreeVars Val (GSet Var) where freeVars (NodeC t xs) = freeVars xs freeVars (Const v) = freeVars v freeVars (Index a b) = freeVars (a,b) freeVars (Var v _) = singleton v freeVars _ = sempty instance FreeVars FuncProps (GSet Var) where freeVars FuncProps { funcFreeVars = fv } = fromDistinctAscList $ toList fv instance FreeVars FuncProps (GSet Tag) where freeVars FuncProps { funcTags = fv } = fromDistinctAscList $ toList fv instance FreeVars Exp (GSet Var) where freeVars (a :>>= b) = freeVars (a,b) freeVars (App a vs _) = freeVars vs freeVars (Case x xs) = freeVars (x,xs) freeVars (Return v) = freeVars v -- freeVars (Store v) = freeVars v freeVars (BaseOp _ vs) = freeVars vs freeVars (Prim _ x _) = freeVars x freeVars Error {} = sempty freeVars Let { expDefs = fdefs, expBody = body } = mconcat (map (fromDistinctAscList . toList . funcFreeVars . funcDefProps) fdefs) `mappend` freeVars body freeVars NewRegion { expLam = l } = freeVars l freeVars Alloc { expValue = v, expCount = c, expRegion = r } = freeVars (v,c,r) freeVars Call { expValue = v, expArgs = as } = freeVars (v:as) freeVars MkClosure { expValue = v, expArgs = as, expRegion = r } = freeVars (v,as,r) freeVars MkCont { expCont = v, expLam = as} = freeVars (v,as) freeVars GcRoots { expValues = v, expBody = b } = freeVars (v,b) instance FreeVars Exp [Var] where freeVars e = toList $ (freeVars e :: GSet Var) instance FreeVars Val [Var] where freeVars e = toList $ (freeVars e :: GSet Var) instance FreeVars Lam [Var] where freeVars e = toList $ (freeVars e :: GSet Var) instance FreeVars Val (GSet Tag) where freeVars (NodeC t xs) = singleton t `union` freeVars xs freeVars (Index a b) = freeVars (a,b) freeVars (Const v) = freeVars v freeVars _ = sempty instance FreeVars Lam (GSet Tag) where freeVars (a :-> b) = freeVars (a,b) instance FreeVars Exp (GSet Tag) where freeVars (a :>>= b) = freeVars (a,b) freeVars (App a vs _) = singleton a `union` freeVars vs freeVars (Case x xs) = freeVars (x,xs) freeVars (Return v) = freeVars v -- freeVars (Store v) = freeVars v freeVars (BaseOp _ vs) = freeVars vs freeVars (Prim _ x _) = freeVars x freeVars Error {} = sempty freeVars Let { expDefs = fdefs, expBody = body } = unions (map (fromDistinctAscList . toList . funcTags . funcDefProps) fdefs) `mappend` freeVars body freeVars NewRegion { expLam = l } = freeVars l freeVars Alloc { expValue = v, expCount = c, expRegion = r } = freeVars (v,c,r) freeVars Call { expValue = v, expArgs = as } = freeVars (v:as) freeVars MkClosure { expValue = v, expArgs = as, expRegion = r } = freeVars (v,as,r) freeVars MkCont { expCont = v, expLam = as} = freeVars (v,as) freeVars GcRoots { expValues = v, expBody = b } = freeVars (v,b) -- Show instances instance Show Var where showsPrec _ (V n) xs = 'v':shows n xs instance Show Ty where showsPrec n (TyComplex ty) = showParen (n >= 9) $ text "Complex" <+> showsPrec 10 ty showsPrec n (TyVector v ty) = showParen (n >= 9) $ showsPrec 10 ty <> text "*" <> tshow v showsPrec n (TyAttr t1 t2) = showParen (n >= 9) $ showsPrec 10 t1 <> text "#" <> showsPrec 10 t2 showsPrec n (TyAnd t1 t2) = showParen (n >= 9) $ showsPrec 10 t1 <> text " && " <> showsPrec 10 t2 showsPrec n (TyOr t1 t2) = showParen (n >= 9) $ showsPrec 10 t1 <> text " || " <> showsPrec 10 t2 showsPrec _ t = showString (f t) where f TyNode = "N" f TyINode = "I" f (TyPtr t) = '&':show t f (TyUnit) = "()" f (TyPrim t) = show t f TyRegion = "M" f TyGcContext = "GC" f (TyRegister t) = 'r':show t f (TyCall c as rt) = show c <> tupled (map show as) <+> "->" <+> show rt f TyUnknown = "?" f _ = "BADTYPE" instance Show Val where -- showsPrec _ s | Just st <- fromVal s = text $ show (st::String) showsPrec _ (NodeC t []) = parens $ (fromAtom t) showsPrec _ (NodeC t vs) = parens $ (fromAtom t) <+> hsep (map shows vs) showsPrec _ (Index v o) = shows v <> char '[' <> shows o <> char ']' showsPrec _ (Var (V i) t) | TyINode <- t = text "ni" <> tshow i | TyNode <- t = text "nd" <> tshow i | TyRegion <- t = text "m" <> tshow i | TyRegister ty <- t = text "r" <> tshow (Var (V i) ty) | TyGcContext <- t = text "gc" <> tshow i | TyPtr t' <- t = text "p" <> shows (Var (V i) t') | TyPrim Op.TyBool <- t = char 'b' <> tshow i | TyPrim (Op.TyBits _ Op.HintFloat) <- t = char 'f' <> tshow i | TyPrim (Op.TyBits _ Op.HintCharacter) <- t = char 'c' <> tshow i | TyPrim (Op.TyBits (Op.Bits 8) _) <- t = char 'o' <> tshow i -- octet | TyPrim (Op.TyBits (Op.Bits 16) _) <- t = char 'h' <> tshow i -- half | TyPrim (Op.TyBits (Op.Bits 32) _) <- t = char 'w' <> tshow i -- word | TyPrim (Op.TyBits (Op.Bits 64) _) <- t = char 'd' <> tshow i -- doubleword | TyPrim (Op.TyBits (Op.Bits 128) _) <- t = char 'q' <> tshow i -- quadword | TyPrim (Op.TyBits (Op.BitsArch Op.BitsPtr) _) <- t = text "bp" <> tshow i | TyPrim (Op.TyBits (Op.BitsArch Op.BitsMax) _) <- t = text "bm" <> tshow i | TyPrim (Op.TyBits _ _) <- t = char 'l' <> tshow i | otherwise = char 'v' <> tshow i showsPrec _ (Lit i _) = tshow i showsPrec _ Unit = showString "()" showsPrec _ (Const v) = char '&' <> shows v showsPrec _ (Item a ty) = tshow a <> text "::" <> tshow ty showsPrec _ (ValUnknown ty) = text "?::" <> tshow ty showsPrec _ (ValPrim aprim xs _) = tshow aprim <> tupled (map tshow xs) -- misc instances instance TypeNames Ty where tIntzh = TyPrim (Op.bits32) tEnumzh = TyPrim (Op.bits16) tCharzh = TyPrim (Op.bits32) instance Intjection Var where toIntjection i = V (fromIntegral i) fromIntjection (V i) = fromIntegral i newtype instance GSet Var = GSetVar (IntjectionSet Var) deriving(Monoid,IsEmpty,HasSize,Collection,Unionize,SetLike,Eq,Ord) newtype instance GMap Var v = GMapVar (IntjectionMap Var v) deriving(Monoid,IsEmpty,HasSize,Collection,Unionize,SetLike,MapLike,Eq,Ord)