packages feed

dvda-0.1: Dvda/HSSyntax.hs

{-# OPTIONS_GHC -Wall #-}

module Dvda.HSSyntax ( writeHSSource
                     ) where

import Data.IntMap ( Key )
import Data.List ( intersperse )
import qualified Data.Vector.Unboxed as V
import qualified Data.IntMap as IM
import qualified Data.Text.Lazy as T

import Dvda.GExpr ( GExpr(..) )
import Dvda.Graph ( FunGraph(..) )
import Dvda.BinUn ( BinOp(..), UnOp(..) )
import qualified Dvda.Config as Config


-- assign a scalar
sassign :: Key -> String
sassign k = Config.nameHSVar k ++ " = "

hBinary :: BinOp -> String
hBinary Add = "(+)"
hBinary Sub = "(-)"
hBinary Mul = "(*)"
hBinary Div = "(/)"
hBinary Pow = "(**)"
hBinary LogBase = "logBase"

hUnary :: UnOp -> String
hUnary Abs    = "abs"
hUnary Neg    = "negate"
hUnary Signum = "signum"
hUnary Exp    = "exp"
hUnary Sqrt   = "sqrt"
hUnary Log    = "log"
hUnary Sin    = "sin"
hUnary Cos    = "cos"
hUnary Tan    = "tan"
hUnary ASin   = "asin"
hUnary ACos   = "acos"
hUnary ATan   = "atan"
hUnary Sinh   = "sinh"
hUnary Cosh   = "cosh"
hUnary Tanh   = "tanh"
hUnary ASinh  = "asinh"
hUnary ATanh  = "atanh"
hUnary ACosh  = "acosh"

pretty :: (Show a, V.Unbox a) => (Int, GExpr a) -> String
pretty (_, (GBinary _ op kx ky)) = hBinary op ++ " " ++ Config.nameHSVar kx ++ " " ++ Config.nameHSVar ky
pretty (_, (GUnary _ op kx)) = hUnary op ++ " " ++ Config.nameHSVar kx
pretty (_, (GSingleton _ x)) = show x
pretty (_, (GScale _ kx ky)) = "scale " ++ Config.nameHSVar kx ++ " " ++ Config.nameHSVar ky
pretty (_, (GDot _ _ kx ky)) = "dot " ++ Config.nameHSVar kx ++ " " ++ Config.nameHSVar ky
--pretty (k, (GConst _ vec)) = Config.nameHSConst k
pretty (_, (GConst _ vec)) = show vec -- Config.nameHSConst k
pretty (_, (GSym _ _)) = error "GSym shouldn't be handled here"

writeAssignment :: (Show a, V.Unbox a) => (Key, GExpr a) -> String
writeAssignment (k, gexpr@(GSym _ _)) = "-- " ++ Config.nameHSVar k ++ ": " ++ show gexpr
writeAssignment (k, gexpr) = sassign k ++ pretty (k,gexpr) ++ " -- " ++ show gexpr

writeHSSource :: (V.Unbox a, Show a, Show b, Show c) => FunGraph a b c -> String -> String
writeHSSource (FunGraph _ im (insT,ins) (outsT,outs)) hash =
  init $ unlines $
  [ "-- {-# OPTIONS_GHC -Wall #-}"
  , "{-# Language GADTs #-}"
  , "{-# Language FlexibleContexts #-}"
  , "{-# Language TypeOperators #-}"
  , "{-# Language TypeFamilies #-}"
  , ""
  , "module " ++ Config.nameHSModule hash ++ " ( " ++ Config.nameHSFunction hash ++ " ) where"
  , ""
  , "import Data.Array.Repa"
  , "import Data.Vector.Unboxed as V"
  , "import Dvda"
  , ""
--  , "-- constants:"
--  , constants
--  , ""
--  , Config.nameHSFunction hash ++ " :: Floating a => " 
--  , spaces ++ rewriteType (show insT) ++ " -> " 
--  , spaces ++ rewriteType (show outsT)
  , Config.nameHSFunction hash ++ " :: " ++ rewriteType (show insT) ++ " ->"
  , spaces ++ rewriteType (show outsT)
  , Config.nameHSFunction hash ++ " ( " ++ inputs ++ " ) = " ++ outputs
  , "  where"
  , init $ unlines $ map ("    " ++) body 
  ]
    where
      spaces = replicate ((length (Config.nameHSFunction hash)) + 4) ' '
      inputs  = concat $ intersperse " :* " (map Config.nameHSVar ins)
      outputs = concat $ intersperse " :* " (map Config.nameHSVar outs)
      body = map writeAssignment (IM.toList im)


intercalate :: String -> [String] -> String
intercalate _ [] = []
intercalate _ [x] = x
intercalate int (x:xs) = (x++int) ++ intercalate int xs

rewriteType :: String -> String
rewriteType typeString = final
  where
    text = T.pack typeString
    -- "Z :* ((Z :. 5) :* ((Z :. 3) :. 5))"
    
    cleaned = T.filter (\x -> not (elem x "() ")) text
    -- "Z:*Z:.5:*Z:.3:.5"
    
    grouped :: [T.Text]
    grouped = T.splitOn (T.pack ":*") cleaned
    -- ["Z", "Z:.5", "Z:.3:.5"]
    
    
    grouped' :: [[T.Text]]
    grouped' = map (T.splitOn (T.pack ":.")) grouped
    -- [["Z"], ["Z","5"], ["Z","3","5"]]

    counted :: [Int]
    counted = map (\x -> length x - 1) grouped'
    -- [0, 1, 2]

    addExpr = map (\x -> "(Expr DIM" ++ show x ++ " Double)")  counted
    -- ["(Expr DIM0 Double)", "(Expr DIM1 Double)", "(Expr DIM2 Double)"]
    
    final = "( " ++ (intercalate " :* " addExpr) ++ " )"
    -- "( (Expr DIM0 Double) :* (Expr DIM1 Double) :* (Expr DIM2 Double) )"


-- rewriteType :: String -> String
-- rewriteType typeString = final
--   where
--     text = T.pack typeString
--     -- "Z :* ((Z :. 5) :* ((Z :. 3) :. 5))"
--     
--     cleaned = T.filter (\x -> not (elem x "() ")) text
--     -- "Z:*Z:.5:*Z:.3:.5"
--     
--     grouped = T.splitOn (T.pack ":*") cleaned
--     -- ["Z", "Z:.5", "Z:.3:.5"]
--     
--     addExpr = map (\x -> T.append "(Expr (" (T.append x ") a)"))  grouped
--     -- ["(Expr (Z) a)", "(Expr (Z:.5) a)", "(Expr (Z:.3:.5) a)"]
--     
--     final = "( " ++ T.unpack (T.intercalate " :* " addExpr) ++ " )"
--     -- "( (Expr (Z) a) :* (Expr (Z:.5) a) :* (Expr (Z:.3:.5) a) )"