packages feed

dumb-cas-0.2.1.1: CAS/Dumb/Symbols/PatternGenerator.hs

-- |
-- Module      : CAS.Dumb.Symbols.PatternGenerator
-- Copyright   : (c) Justus Sagemüller 2017
-- License     : GPL v3
-- 
-- Maintainer  : (@) jsag $ hvl.no
-- Stability   : experimental
-- Portability : portable
-- 

{-# LANGUAGE TemplateHaskell     #-}
{-# LANGUAGE PatternSynonyms     #-}
{-# LANGUAGE QuasiQuotes         #-}
{-# LANGUAGE CPP                 #-}

module CAS.Dumb.Symbols.PatternGenerator (makeSymbols, makeQualifiedSymbols) where

import CAS.Dumb.Tree
import CAS.Dumb.Symbols

import Language.Haskell.TH
import Data.Char


makeSymbols :: Name   -- ^ Desired type of the symbols.
            -> [Char] -- ^ The letters you want as symbols.
            -> DecsQ
makeSymbols t = makeQualifiedSymbols t ""

plainTVinf :: Name -> TyVarBndr
#if MIN_VERSION_template_haskell(2,17,0)
                                Specificity
plainTVinf n = PlainTV n inferredSpec
#else
plainTVinf = PlainTV
#endif

conPnoTA :: Name -> [Pat] -> Pat
#if MIN_VERSION_template_haskell(2,18,0)
conPnoTA n pats = ConP n [] pats
#else
conPnoTA = ConP
#endif

makeQualifiedSymbols
            :: Name   -- ^ Desired type of the symbols.
            -> String -- ^ Prefix for the generated Haskell names.
            -> [Char] -- ^ The letters you want as symbols.
            -> DecsQ
makeQualifiedSymbols casType namePrefix = fmap concat . mapM mkSymbol
 where mkSymbol c
        | isLower (head idfyer) = return
         [ SigD symbName $ ForallT [plainTVinf γ, plainTVinf s¹, plainTVinf s², plainTVinf ζ] [] typeName
        -- c :: casType γ s² s¹ ζ
         , ValD (VarP symbName)
                (NormalB . AppE (ConE 'Symbol)
                         . AppE (ConE 'PrimitiveSymbol)
                         $ LitE (CharL c) )
                []
        -- c = Symbol $ StringSymbol "c"
         ]
#if __GLASGOW_HASKELL__ > 801
        | isUpper (head idfyer) = return
         [ PatSynSigD symbName (ForallT [] [] $ ForallT [] [] typeName)
        -- pattern c :: casType γ s² s¹ ζ
         , PatSynD symbName
                   (PrefixPatSyn [])
                   ImplBidir
                   ('Symbol `conPnoTA` ['PrimitiveSymbol `conPnoTA` [LitP $ CharL c]])
        -- pattern c = Symbol (StringSymbol ['c'])
         ] 
#endif
        | otherwise = error
             $ "Can only make symbols out of lower- or uppercase letters, which '"
                                ++ [c] ++ "' is not."
        where idfyer = namePrefix ++ [c]
              symbName = mkName idfyer
              typeName = ConT casType`AppT`VarT γ`AppT`VarT s²`AppT`VarT s¹`AppT`VarT ζ
              [γ,s²,s¹,ζ] = mkName <$> ["γ","s²","s¹","ζ"]