{-# LANGUAGE CPP, DeriveDataTypeable #-} module Language.Java.Paragon.TypeCheck.Actors where --import Data.List (intersect) import Language.Java.Paragon.Syntax import Language.Java.Paragon.Pretty import Language.Java.Paragon.Interaction import Language.Java.Paragon.Monad.Uniq #ifdef BASE4 import Data.Data #else import Data.Generics (Data(..),Typeable(..)) #endif -- An actor id is either known and unique (Fresh), or -- it is an alias of some actor. If we know statically -- which actor(s) it can represent, we list that. -- Otherwise an empty list means it could be an alias -- of any other actor. data ActorId = Fresh Int String | Instance (Name ()) Int | Unknown Int | ActorTPVar (Ident ()) deriving (Show, Eq, Ord, Data, Typeable) instance Pretty ActorId where pretty (Fresh k s) = text s <> text ('#':show k) pretty (Instance n k) = pretty n <> text ('#':'#':show k) pretty (Unknown k) = text ('@':show k) pretty (ActorTPVar i) = pretty i infix 5 `unifies`, `unify` -- Precondition: No ActorTPVars unifies :: ActorId -> ActorId -> Bool -- If we have the exact (fresh) ids, we can tell exactly unifies (Fresh x _) (Fresh y _) = x == y -- If we have two fresh instance ids, they could be aliases of the same instance unifies (Instance n1 _) (Instance n2 _) = n1 == n2 unifies (Unknown _) _ = True unifies _ (Unknown _) = True unifies _ _ = False -- If either side is an alias, check if it could represent the fresh side. --unifies (Unknown x xs) (Fresh y) = null xs || y `elem` xs --unifies (Fresh x) (Unknown y ys) = null ys || x `elem` ys -- If both are aliases, check if they could represent the same fresh actor. --unifies (Unknown x xs) (Unknown y ys) = null xs || null ys || (not . null) (xs `intersect` ys) unify :: [ActorId] -> [ActorId] -> Bool unify xs ys = all (uncurry unifies) $ zip xs ys {- equals :: ActorId -> ActorId -> Bool equals (Fresh x) (Fresh y) = x == y equals (Unknown x _) (Unknown y _) = x == y equals _ _ = False reprs :: ActorId -> [Int] reprs (Fresh x) = [x] reprs (Unknown x xs) = x:xs -} getId :: ActorId -> Int getId (Fresh x _) = x getId (Unknown x ) = x getId _ = panic "getId" "Trying to get ActorId of ActorTPVar, which should have been instantiated" {- reprName :: ActorId -> Name reprName (Fresh _ n) = n reprName (Unknown _ _ n) = n -} newUnknown :: Uniq -> IO ActorId newUnknown u = do uniq <- getUniq u return $ Unknown uniq newFresh :: Uniq -> String -> IO ActorId newFresh u str = do uniq <- getUniq u return $ Fresh uniq str newInstance :: Uniq -> Name () -> IO ActorId newInstance u n = do uniq <- getUniq u return $ Instance n uniq