{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Futhark.Internalise.TypesValues
(
BoundInTypes
, boundInTypes
, internaliseReturnType
, internaliseEntryReturnType
, internaliseParamTypes
, internaliseType
, internalisePrimType
, internalisedTypeSize
, internalisePrimValue
)
where
import Control.Monad.State
import Control.Monad.Reader
import Data.List
import qualified Data.Map.Strict as M
import qualified Data.Set as S
import Data.Maybe
import Data.Monoid ((<>))
import qualified Language.Futhark as E
import Futhark.Representation.SOACS as I
import Futhark.Internalise.Monad
internaliseUniqueness :: E.Uniqueness -> I.Uniqueness
internaliseUniqueness E.Nonunique = I.Nonunique
internaliseUniqueness E.Unique = I.Unique
newtype BoundInTypes = BoundInTypes (S.Set VName)
deriving (Semigroup, Monoid)
boundInTypes :: [E.TypeParam] -> BoundInTypes
boundInTypes = BoundInTypes . S.fromList . mapMaybe isTypeParam
where isTypeParam (E.TypeParamDim v _) = Just v
isTypeParam _ = Nothing
internaliseParamTypes :: BoundInTypes
-> M.Map VName VName
-> [E.TypeBase (E.DimDecl VName) ()]
-> InternaliseM ([[I.TypeBase ExtShape Uniqueness]],
ConstParams)
internaliseParamTypes (BoundInTypes bound) pnames ts =
runInternaliseTypeM $ withDims (bound' <> M.map (Free . Var) pnames) $
mapM internaliseTypeM ts
where bound' = M.fromList (zip (S.toList bound)
(map (Free . Var) $ S.toList bound))
internaliseReturnType :: E.TypeBase (E.DimDecl VName) ()
-> InternaliseM ([I.TypeBase ExtShape Uniqueness],
ConstParams)
internaliseReturnType t = do
(ts', cm') <- internaliseEntryReturnType t
return (concat ts', cm')
internaliseEntryReturnType :: E.TypeBase (E.DimDecl VName) ()
-> InternaliseM ([[I.TypeBase ExtShape Uniqueness]],
ConstParams)
internaliseEntryReturnType t = do
let ts = case E.isTupleRecord t of Just tts -> tts
_ -> [t]
runInternaliseTypeM $ mapM internaliseTypeM ts
internaliseType :: E.TypeBase () ()
-> InternaliseM [I.TypeBase I.ExtShape Uniqueness]
internaliseType =
fmap fst . runInternaliseTypeM . internaliseTypeM . E.vacuousShapeAnnotations
newId :: InternaliseTypeM Int
newId = do (i,cm) <- get
put (i + 1, cm)
return i
internaliseDim :: E.DimDecl VName
-> InternaliseTypeM ExtSize
internaliseDim d =
case d of
E.AnyDim -> Ext <$> newId
E.ConstDim n -> return $ Free $ intConst I.Int32 $ toInteger n
E.NamedDim name -> namedDim name
where namedDim (E.QualName _ name) = do
subst <- liftInternaliseM $ asks $ M.lookup name . envSubsts
is_dim <- lookupDim name
case (is_dim, subst) of
(Just dim, _) -> return dim
(Nothing, Just [v]) -> return $ I.Free v
_ -> do
let fname = nameFromString $ pretty name ++ "f"
(i,cm) <- get
case find ((==fname) . fst) cm of
Just (_, known) -> return $ I.Free $ I.Var known
Nothing -> do new <- liftInternaliseM $ newVName $ baseString name
put (i, (fname,new):cm)
return $ I.Free $ I.Var new
internaliseTypeM :: E.StructType
-> InternaliseTypeM [I.TypeBase ExtShape Uniqueness]
internaliseTypeM orig_t =
case orig_t of
E.Prim bt -> return [I.Prim $ internalisePrimType bt]
E.TypeVar{} ->
fail "internaliseTypeM: cannot handle type variable."
E.Record ets ->
concat <$> mapM (internaliseTypeM . snd) (E.sortFields ets)
E.Array _ u et shape -> do
dims <- internaliseShape shape
ets <- internaliseElemType et
return [I.arrayOf et' (Shape dims) $ internaliseUniqueness u | et' <- ets ]
E.Arrow{} -> fail $ "internaliseTypeM: cannot handle function type: " ++ pretty orig_t
E.Enum{} -> return [I.Prim $ I.IntType I.Int8]
where internaliseElemType E.ArrayPolyElem{} =
fail "internaliseElemType: cannot handle type variable."
internaliseElemType (E.ArrayPrimElem bt) =
return [I.Prim $ internalisePrimType bt]
internaliseElemType (E.ArrayRecordElem elemts) =
concat <$> mapM (internaliseRecordElem . snd) (E.sortFields elemts)
internaliseElemType E.ArrayEnumElem{} =
return [I.Prim $ I.IntType I.Int8]
internaliseRecordElem (E.RecordArrayElem et) =
internaliseElemType et
internaliseRecordElem (E.RecordArrayArrayElem et shape) =
internaliseTypeM $ E.Array mempty Nonunique et shape
internaliseShape = mapM internaliseDim . E.shapeDims
internalisedTypeSize :: E.TypeBase dim () -> InternaliseM Int
internalisedTypeSize = fmap length . internaliseType . E.removeShapeAnnotations
internalisePrimType :: E.PrimType -> I.PrimType
internalisePrimType (E.Signed t) = I.IntType t
internalisePrimType (E.Unsigned t) = I.IntType t
internalisePrimType (E.FloatType t) = I.FloatType t
internalisePrimType E.Bool = I.Bool
internalisePrimValue :: E.PrimValue -> I.PrimValue
internalisePrimValue (E.SignedValue v) = I.IntValue v
internalisePrimValue (E.UnsignedValue v) = I.IntValue v
internalisePrimValue (E.FloatValue v) = I.FloatValue v
internalisePrimValue (E.BoolValue b) = I.BoolValue b