module Feldspar.Compiler.Imperative.Frontend where
import Feldspar.Compiler.Imperative.Representation
import Feldspar.Range
import Feldspar.Core.Types (Length)
toBlock :: Program () -> Block ()
toBlock (BlockProgram b) = b
toBlock p = Block [] p
toProg :: Block () -> Program ()
toProg (Block [] p) = p
toProg e = BlockProgram e
copyProg :: Maybe (Expression ())-> [Expression ()] -> Program ()
copyProg _ [] = error "copyProg: missing source parameter."
copyProg Nothing _ = Empty
copyProg (Just outExp) inExp
| outExp == head inExp
&& null (tail inExp) = Empty
| otherwise = call "copy" (map ValueParameter (outExp:inExp))
mkInitialize :: String -> Maybe (Expression ()) -> Expression () -> Program ()
mkInitialize _ Nothing _ = Empty
mkInitialize name (Just arr) len = Assign arr $ fun (typeof arr) name [arr, sz, len]
where
sz | isArray t' = binop (NumType Unsigned S32) "-" (litI32 0) t
| otherwise = t
t = SizeOf t'
t' = go $ typeof arr
go (ArrayType _ e) = e
go (Pointer typ) = go typ
go _ = error $ "Feldspar.Compiler.Imperative.Frontend." ++ name ++ ": invalid type of array " ++ show arr ++ "::" ++ show (typeof arr)
initArray :: Maybe (Expression ()) -> Expression () -> Program ()
initArray = mkInitialize "initArray"
setLength :: Maybe (Expression ()) -> Expression () -> Program ()
setLength = mkInitialize "setLength"
freeArray :: Variable () -> Program ()
freeArray arr = call "freeArray" [ValueParameter $ varToExpr arr]
freeArrays :: [Declaration ()] -> [Program ()]
freeArrays defs = map freeArray arrays
where
arrays = filter (isArray . typeof) $ map dVar defs
arrayLength :: Expression () -> Expression ()
arrayLength arr
| Just r <- chaseArray arr = litI32 $ fromIntegral (upperBound r)
| otherwise = FunctionCall (Function "getLength" (NumType Unsigned S32) Prefix) [arr]
chaseArray :: Expression t-> Maybe (Range Length)
chaseArray = go []
where go :: [String] -> Expression t -> Maybe (Range Length)
go [] (ConstExpr (ArrayConst l)) = Just (singletonRange $ fromIntegral $ length l)
go [] (VarExpr (Variable (ArrayType r _) _)) | isSingleton r = Just r
go [] (VarExpr (Variable (NativeArray (Just r) _) _)) = Just (singletonRange r)
go ss (StructField e s) = go (s:ss) e
go ss (AddrOf e) = go ss e
go (s:_) (VarExpr (Variable (StructType _ fields) _))
| Just (ArrayType r _) <- lookup s fields
, isSingleton r = Just r
| Just (NativeArray (Just r) _) <- lookup s fields
= Just (singletonRange r)
go _ _ = Nothing
iVarInit :: Expression () -> Program ()
iVarInit var = call "ivar_init" [ValueParameter var]
iVarGet :: Expression () -> Expression () -> Program ()
iVarGet loc ivar
| isArray typ = call "ivar_get_array" [ValueParameter loc, ValueParameter ivar]
| otherwise = call "ivar_get" [TypeParameter typ, ValueParameter (AddrOf loc), ValueParameter ivar]
where
typ = typeof loc
iVarPut :: Expression () -> Expression () -> Program ()
iVarPut ivar msg
| isArray typ = call "ivar_put_array" [ValueParameter ivar, ValueParameter msg]
| otherwise = call "ivar_put" [TypeParameter typ, ValueParameter ivar, ValueParameter (AddrOf msg)]
where
typ = typeof msg
iVarDestroy :: Variable () -> Program ()
iVarDestroy v = call "ivar_destroy" [ValueParameter $ AddrOf $ varToExpr v]
freeIVars :: [Declaration ()] -> [Program ()]
freeIVars defs = map iVarDestroy ivars
where
ivars = filter (isIVar . typeof) $ map dVar defs
spawn :: String -> [Variable ()] -> Program ()
spawn taskName vs = call spawnName allParams
where
spawnName = "spawn" ++ show (length vs)
taskParam = FunParameter taskName
typeParams = map (TypeParameter . typeof) vs
varParams = map (ValueParameter . mkv) vs
where mkv v = let v' = VarExpr $ Variable (typeof v) (vName v)
in if isPointer $ typeof v then AddrOf v' else v'
allParams = taskParam : concat (zipWith (\a b -> [a,b]) typeParams varParams)
run :: String -> [Variable ()] -> Program ()
run taskName vs = call runName allParams
where
runName = "run" ++ show (length vs)
typeParams = map (TypeParameter . typeof) vs
taskParam = FunParameter taskName
allParams = taskParam : typeParams
intWidth :: Type -> Maybe Integer
intWidth (NumType _ S8) = Just 8
intWidth (NumType _ S16) = Just 16
intWidth (NumType _ S32) = Just 32
intWidth (NumType _ S40) = Just 40
intWidth (NumType _ S64) = Just 64
intWidth _ = Nothing
intSigned :: Type -> Maybe Bool
intSigned (NumType Unsigned _) = Just False
intSigned (NumType Signed _) = Just True
intSigned _ = Nothing
litF :: Float -> Expression t
litF n = ConstExpr (FloatConst n)
litD :: Double -> Expression t
litD n = ConstExpr (DoubleConst n)
litB :: Bool -> Expression ()
litB b = ConstExpr (BoolConst b)
litC :: Constant () -> Constant () -> Expression ()
litC r i = ConstExpr (ComplexConst r i)
litI :: Type -> Integer -> Expression ()
litI t n = ConstExpr (IntConst n t)
litI32 :: Integer -> Expression ()
litI32 = litI (NumType Unsigned S32)
isArray :: Type -> Bool
isArray ArrayType{} = True
isArray (Pointer t) = isArray t
isArray _ = False
isNativeArray :: Type -> Bool
isNativeArray NativeArray{} = True
isNativeArray (Pointer t) = isNativeArray t
isNativeArray _ = False
isIVar :: Type -> Bool
isIVar IVarType{} = True
isIVar _ = False
isPointer :: Type -> Bool
isPointer Pointer{} = True
isPointer _ = False
isVarExpr :: Expression () -> Bool
isVarExpr VarExpr{} = True
isVarExpr _ = False
containsNativeArray :: Type -> Bool
containsNativeArray t = any (isNativeArray . snd) $ flattenStructs t
flattenStructs :: Type -> [(Expression () -> Expression (), Type)]
flattenStructs (StructType _ fts) = [(\ e -> af $ StructField e fname, t') | (fname,t) <- fts, (af, t') <- flattenStructs t]
flattenStructs t = [(id, t)]
hasReference ArrayType{} = True
hasReference NativeArray{} = True
hasReference Pointer{} = True
hasReference IVarType{} = True
hasReference (StructType _ fs) = any (hasReference . snd) fs
hasReference t = False
dVar :: Declaration () -> Variable ()
dVar (Declaration v _) = v
vName :: Variable t -> String
vName Variable{..} = varName
lName :: Expression t -> String
lName (VarExpr v@Variable{}) = vName v
lName (ArrayElem e _) = lName e
lName (StructField e _) = lName e
lName (AddrOf e) = lName e
lName e = error $ "Feldspar.Compiler.Imperative.Frontend.lName: invalid location: " ++ show e
varToExpr :: Variable t -> Expression t
varToExpr = VarExpr
binop :: Type -> String -> Expression () -> Expression () -> Expression ()
binop t n e1 e2 = fun' Infix t n [e1, e2]
fun :: Type -> String -> [Expression ()] -> Expression ()
fun = fun' Prefix
fun' :: FunctionMode -> Type -> String -> [Expression ()] -> Expression ()
fun' m t n = FunctionCall (Function n t m)
call :: String -> [ActualParameter ()] -> Program ()
call = ProcedureCall
for :: Bool -> String -> Expression () -> Expression () -> Block () -> Program ()
for _ _ _ _ (Block [] (Sequence [Empty])) = Empty
for p s e i b = ParLoop p (Variable (NumType Unsigned S32) s) e i b
while :: Block () -> Expression () -> Block () -> Program ()
while p e = SeqLoop e p