{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Clash.Netlist.Id
( IdType (..)
, mkBasicId'
, stripDollarPrefixes
)
where
import Clash.Annotations.Primitive (HDL (..))
import Data.Char (isAsciiLower,isAsciiUpper,isDigit)
import Data.Text as Text
data IdType = Basic | Extended
mkBasicId'
:: HDL
-> Bool
-> Text
-> Text
mkBasicId' hdl tupEncode = stripMultiscore hdl . stripLeading hdl . zEncode hdl tupEncode
where
stripLeading VHDL = Text.dropWhile (`elem` ('_':['0'..'9']))
stripLeading _ = Text.dropWhile (`elem` ('$':['0'..'9']))
stripMultiscore VHDL
= Text.concat
. Prelude.map (\cs -> case Text.head cs of
'_' -> "_"
_ -> cs
)
. Text.group
stripMultiscore _ = id
stripDollarPrefixes :: Text -> Text
stripDollarPrefixes = stripWorkerPrefix . stripSpecPrefix . stripConPrefix
. stripWorkerPrefix . stripDictFunPrefix
where
stripDictFunPrefix t = case Text.stripPrefix "$f" t of
Just k -> takeWhileEnd (/= '_') k
Nothing -> t
stripWorkerPrefix t = case Text.stripPrefix "$w" t of
Just k -> k
Nothing -> t
stripConPrefix t = case Text.stripPrefix "$c" t of
Just k -> k
Nothing -> t
stripSpecPrefix t = case Text.stripPrefix "$s" t of
Just k -> k
Nothing -> t
type UserString = Text
type EncodedString = Text
zEncode :: HDL -> Bool -> UserString -> EncodedString
zEncode hdl False cs = go (uncons cs)
where
go Nothing = empty
go (Just (c,cs')) = append (encodeDigitCh hdl c) (go' $ uncons cs')
go' Nothing = empty
go' (Just (c,cs')) = append (encodeCh hdl c) (go' $ uncons cs')
zEncode hdl True cs = case maybeTuple cs of
Just (n,cs') -> append n (go' (uncons cs'))
Nothing -> go (uncons cs)
where
go Nothing = empty
go (Just (c,cs')) = append (encodeDigitCh hdl c) (go' $ uncons cs')
go' Nothing = empty
go' (Just (c,cs')) = case maybeTuple (cons c cs') of
Just (n,cs2) -> append n (go' $ uncons cs2)
Nothing -> append (encodeCh hdl c) (go' $ uncons cs')
encodeDigitCh :: HDL -> Char -> EncodedString
encodeDigitCh _ c | isDigit c = Text.empty
encodeDigitCh hdl c = encodeCh hdl c
encodeCh :: HDL -> Char -> EncodedString
encodeCh hdl c | unencodedChar hdl c = singleton c
| otherwise = Text.empty
unencodedChar :: HDL -> Char -> Bool
unencodedChar hdl c =
or [ isAsciiLower c
, isAsciiUpper c
, isDigit c
, if hdl == VHDL then c == '_' else c `elem` ['_','$']
]
maybeTuple :: UserString -> Maybe (EncodedString,UserString)
maybeTuple "(# #)" = Just ("Unit",empty)
maybeTuple "()" = Just ("Unit",empty)
maybeTuple (uncons -> Just ('(',uncons -> Just ('#',cs))) =
case countCommas 0 cs of
(n,uncons -> Just ('#',uncons -> Just (')',cs'))) -> Just (pack ("Tup" ++ show (n+1)),cs')
_ -> Nothing
maybeTuple (uncons -> Just ('(',cs)) =
case countCommas 0 cs of
(n,uncons -> Just (')',cs')) -> Just (pack ("Tup" ++ show (n+1)),cs')
_ -> Nothing
maybeTuple _ = Nothing
countCommas :: Int -> UserString -> (Int,UserString)
countCommas n (uncons -> Just (',',cs)) = countCommas (n+1) cs
countCommas n cs = (n,cs)