{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE ScopedTypeVariables #-} -- |Convert an Haskell pattern to the corresponding `ByPattern` channel identifier module Data.Pattern.Transform (byPattern, byPattern_) where import qualified Data.Flat.Bits as V import Data.Int import qualified Data.Map as M import Data.Pattern.Types import Data.Pattern.Util import Data.Word import ZM hiding (Name) -- |Convert an Haskell pattern to the corresponding `ByPattern` channel identifier -- or throw an error if conversion fails byPattern :: forall a. Model a => IPattern -> ByPattern a byPattern = either error id . byPattern_ -- |Convert an Haskell pattern to the corresponding `ByPattern` channel identifier byPattern_ :: forall a. Model a => IPattern -> Either String (ByPattern a) byPattern_ pat = let tm = absTypeModel (Proxy :: Proxy a) ctMap = typeTree tm solveCons t = let Just ct = M.lookup t ctMap in (ct,t) conv (PCon n ps) (ct,t) = case constructorInfo (convert n) ct of Nothing -> err ["Constructor '"++ n ++"' not present in",show t] Just (bs,ts) | length ts == length ps -> Right (MatchValue . map boolToBit $ bs) : concatMap (uncurry conv) (zip ps $ map solveCons ts) | otherwise -> err ["Constructor",n,"has",show (length ts),"parameters, found",show (length ps)] conv (PName (PInt i)) (_,t) | t==word8Type = val (fromIntegral i::Word8) | t==word16Type = val (fromIntegral i::Word16) | t==word32Type = val (fromIntegral i::Word32) | t==word64Type = val (fromIntegral i::Word64) | t==wordType = val (fromIntegral i::Word) | t==int8Type = val (fromIntegral i::Int8) | t==int16Type = val (fromIntegral i::Int16) | t==int32Type = val (fromIntegral i::Int32) | t==int64Type = val (fromIntegral i::Int64) | t==intType = val (fromIntegral i::Int) | t==integerType = val (fromIntegral i::Integer) | otherwise = terr t i conv (PName (PRat r)) (_,t)| t==floatType = val (fromRational r::Float) | t==doubleType = val (fromRational r::Double) | otherwise = terr t r conv (PName (PChar c)) (_,t) | t == charType = val c | otherwise = terr t c conv (PName (PString s)) (_,t) | t == stringType = val s | otherwise = terr t s conv (PName PWild) (_,t) = [Right $ MatchAny t] conv (PName (PVar v)) _ = err ["Variables are not allowed in patterns, use wildcards (_) only, found:",v] --conv p _ = error (show p) in ByPattern . optPattern <$> collectErrors (conv pat (solveCons (typeName tm))) where val a = [Right . MatchValue . map boolToBit . V.toBools . V.bits $ a] err ls = [Left . unwords $ ls] terr expType r = err ["Type mismatch: expected",show expType,"type, found",show r] boolToBit False = V0 boolToBit True = V1