module Vectorise.Convert (fromVect) where import Vectorise.Monad import Vectorise.Builtins import Vectorise.Type.Type import CoreSyn import TyCon import Type import TypeRep import FastString -- | Build an expression that calls the vectorised version of some -- function from a `Closure`. -- -- For example -- @ -- \(x :: Double) -> -- \(y :: Double) -> -- ($v_foo $: x) $: y -- @ -- -- We use the type of the original binding to work out how many -- outer lambdas to add. -- fromVect :: Type -- ^ The type of the original binding. -> CoreExpr -- ^ Expression giving the closure to use, eg @$v_foo@. -> VM CoreExpr -- Convert the type to the core view if it isn't already. fromVect ty expr | Just ty' <- coreView ty = fromVect ty' expr -- For each function constructor in the original type we add an outer -- lambda to bind the parameter variable, and an inner application of it. fromVect (FunTy arg_ty res_ty) expr = do arg <- newLocalVar (fsLit "x") arg_ty varg <- toVect arg_ty (Var arg) varg_ty <- vectType arg_ty vres_ty <- vectType res_ty apply <- builtin applyVar body <- fromVect res_ty $ Var apply `mkTyApps` [varg_ty, vres_ty] `mkApps` [expr, varg] return $ Lam arg body -- If the type isn't a function then it's time to call on the closure. fromVect ty expr = identityConv ty >> return expr -- TODO: What is this really doing? toVect :: Type -> CoreExpr -> VM CoreExpr toVect ty expr = identityConv ty >> return expr -- | Check that we have the vectorised versions of all the -- type constructors in this type. identityConv :: Type -> VM () identityConv ty | Just ty' <- coreView ty = identityConv ty' identityConv (TyConApp tycon tys) = do mapM_ identityConv tys identityConvTyCon tycon identityConv _ = noV -- | Check that we have the vectorised version of this type constructor. identityConvTyCon :: TyCon -> VM () identityConvTyCon tc | isBoxedTupleTyCon tc = return () | isUnLiftedTyCon tc = return () | otherwise = do tc' <- maybeV (lookupTyCon tc) if tc == tc' then return () else noV