-- | Export information from the final state of the type constraint solver. -- module Type.Export ( squidExport ) where import Type.Exp import Type.Base import Type.Class import Type.State import Type.Scheme import Type.Plug import Type.Util import Type.Plate.Trans import Type.Plate.FreeVars import Type.Context import Data.Array.MArray import qualified Data.Map as Map import Data.Map (Map) import qualified Data.Set as Set import Data.Set (Set) import qualified Shared.Var as Var import Shared.Var (Var, NameSpace(..)) import Shared.Error import Util import qualified Debug.Trace ----- debug = True trace s = when debug $ traceM s stage = "Type.Export" -- | Export some stuff from the constraint solver state. squidExport :: Set Var -- ^ The vars for the bindings we want types for. -> SquidM ( Map Var Type -- Type schemes. , Map Var (InstanceInfo Type Type) -- How each instantiation was done. , Set Var -- Which vars were quantified, ie which vars are ports. , Map Var (Map Var Type) -- The substition from the "contra-variant vars are ports" -- rewriting process. , Map Var [Var]) -- The constraints acting on each region. squidExport vsTypesPlease = do trace $ "== Export ====================================\n" % " vsTypesPlease = " % vsTypesPlease % "\n" -- Export types for the requested vars. types <- exportTypes vsTypesPlease -- Export the instantiation table. inst <- exportInst -- The port table was already plugged by Scheme.generaliseType portTable <- gets statePortTable quantVars <- gets stateQuantifiedVars -- Build a map of the constraints acting on each region vsRegionClasses <- exportRegionConstraints return ( types , inst , quantVars , portTable , vsRegionClasses) -- | Export the type for this variable. -- If no type is in the graph for this var then return Nothing. -- exportVarType :: Var -> SquidM (Maybe Type) exportVarType v = do trace $ "* Export.exportVarType: " % v % "\n" mEx <- extractType True v return mEx -- exportTypes :: Set Var -> SquidM (Map Var Type) exportTypes vsTypesPlease = do -- these are the type that were asked for by the slurper. let vsPlease = Set.toList vsTypesPlease Just ts <- liftM sequence $ mapM exportVarType vsPlease return $ Map.fromList $ zip vsPlease ts -- | Process this type to make it an exportable format. -- plug classids. -- trim closures. -- bottom-out non-port effect/closure variables. -- exportType :: Type -> SquidM Type exportType t = do tPlug <- plugClassIds [] t quantVars <- gets stateQuantifiedVars let tFinal = finaliseT quantVars tPlug case kindOfType tFinal of -- trim exported closures. -- There's no point exporting this junk and making the Core stages -- have to trim it themselves. KClosure -> return $ trimClosureC tFinal KData -> return $ trimClosureT tFinal _ -> return $ packType tFinal exportMaybeType :: Maybe Type -> SquidM (Maybe Type) exportMaybeType mt = case mt of Nothing -> return Nothing Just t -> do t' <- exportType t return $ Just t' ----- -- | Build a map of all the instantiations -- exportInst :: SquidM (Map Var (InstanceInfo Type Type)) exportInst = do inst <- gets stateInst vts <- mapM exportInstInfo $ Map.toList inst return $ Map.fromList vts exportInstInfo :: (Var, InstanceInfo Var Type) -> SquidM (Var, InstanceInfo Type Type) exportInstInfo (v, ii) = case ii of InstanceLambda v1 v2 mt -> do mt' <- exportMaybeType mt return $ (v, InstanceLambda v1 v2 mt) InstanceLet v1 v2 vs t -> do Just ts <- liftM sequence $ mapM exportVarType vs -- HACKS: When we take the type to use for an insantiation we want the ungeneralised -- one, but the eq class will already have been updated with the generalied -- scheme. We should really have separate classes for this, but assuming we're -- only dealing with rank-1 types we can just take the scheme and chop off the foralls. -- -- See test/Typing/Closure/GetInc1 for an example that runs into this problem. let chopForalls tt = case tt of TForall vks t -> chopForalls t _ -> tt let ts_hacked = map chopForalls ts t' <- exportType t return $ (v, InstanceLet v1 v2 ts_hacked t') InstanceLetRec vUse vDef Nothing -> do Just tDef <- exportVarType vDef return $ (v, InstanceLetRec vUse vDef (Just tDef)) -------------------------------------------------------------------------------- -- | Build a map of the constraints acting on each region -- exportRegionConstraints :: SquidM (Map Var [Var]) exportRegionConstraints = do graph <- gets stateGraph classes <- liftIO $ getElems $ graphClass graph pairs <- liftM catMaybes $ mapM slurpRegionConstraintVars classes return $ Map.fromList pairs -- | If this is a region class then build a map of the constraints acting on it. slurpRegionConstraintVars :: Class -> SquidM (Maybe (Var, [Var])) slurpRegionConstraintVars c -- got a region class | Class { classKind = KRegion } <- c = do -- extract the vars for all the fetters acting on this class vars <- liftM catMaybes $ mapM slurpFetterVar $ Set.toList $ classBackRef c -- get the name of this class name <- makeClassName (classId c) return $ Just (name, nub vars) -- not a region class | otherwise = return $ Nothing -- | If there is a fetter in this class then return its var. slurpFetterVar :: ClassId -> SquidM (Maybe Var) slurpFetterVar cid = do Just c <- lookupClass cid let xx | ClassFetter { classFetter = f } <- c , FConstraint v ts <- f = Just v | otherwise = Nothing return xx