chr-lang-0.1.0.0: src/CHR/Language/GTerm/AST.hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TupleSections #-}
-------------------------------------------------------------------------------------------
--- Generic terms describing constraints, providing interpretation to AST of your choice
-------------------------------------------------------------------------------------------
module CHR.Language.GTerm.AST
( GTm(..)
, GTermAs(..)
, GTermAsState(..)
, emptyGTermAsState
, gtermasVar
, gtermasFail
)
where
import Data.Char
import Data.Typeable
import GHC.Generics
import Control.Monad.Except
import Control.Monad.State
-- import qualified Data.Map as Map
import qualified Data.HashMap.Strict as MapH
import CHR.Pretty as PP
import CHR.Utils
import CHR.Data.Lens
import CHR.Types
import qualified CHR.Data.Lookup as Lk
-- import CHR.Types.Core
-------------------------------------------------------------------------------------------
--- Supporting types
-------------------------------------------------------------------------------------------
data GTermAsState
= GTermAsState
{ _gtermasNmToVarMp :: NmToVarMp
}
emptyGTermAsState :: GTermAsState
emptyGTermAsState = GTermAsState emptyNmToVarMp
-------------------------------------------------------------------------------------------
--- Lens
-------------------------------------------------------------------------------------------
mkLabel ''GTermAsState
-------------------------------------------------------------------------------------------
--- Term language/AST
-------------------------------------------------------------------------------------------
-- | Terms
data GTm
= GTm_Var String -- ^ variable (to be substituted)
| GTm_Int Integer -- ^ int value (for arithmetic)
| GTm_Str String -- ^ string value
| GTm_Con String [GTm] -- ^ general term structure
| GTm_Nil -- ^ special case: list nil
| GTm_Cns GTm GTm -- ^ special case: list cons
deriving (Show, Eq, Ord, Typeable, Generic)
instance PP GTm where
pp (GTm_Var v ) = pp v -- "v" >|< v
pp (GTm_Con c [] ) = pp c
pp (GTm_Con c@(h:_) [a1,a2])
| not (isAlpha h) = ppParens $ a1 >#< c >#< a2
pp (GTm_Con c as ) = ppParens $ c >#< ppSpaces as
pp (GTm_Nil ) = pp "[]"
pp (GTm_Cns h t ) = "[" >|< h >#< ":" >#< t >|< "]"
pp (GTm_Int i ) = pp i
pp (GTm_Str s ) = pp $ show s
-------------------------------------------------------------------------------------------
--- Term interpretation in context of CHR
-------------------------------------------------------------------------------------------
-- | Interpretation monad, which is partial
type GTermAsM = StateT GTermAsState (Either PP_Doc)
-- | Term interpretation in context of CHR
class GTermAs cnstr guard bprio prio tm
| cnstr -> guard bprio prio tm
, guard -> cnstr bprio prio tm
, bprio -> cnstr guard prio tm
, prio -> cnstr guard bprio tm
, tm -> cnstr guard bprio prio
where
--
asTm :: GTm -> GTermAsM tm
-- | as list, if matches/possible. Only to be invoked for GTm_Cns
asTmList :: GTm -> GTermAsM ([tm], Maybe tm)
asTmList (GTm_Cns h GTm_Nil ) = asTm h >>= \h -> return ([h], Nothing)
asTmList (GTm_Cns h t@(GTm_Cns _ _)) = asTm h >>= \h -> asTmList t >>= \(t,mt) -> return ((h:t),mt)
asTmList (GTm_Cns h t ) = asTm h >>= \h -> asTm t >>= \t -> return ([h], Just t)
asTmList _ = panic "GTermAs.asTmList: should not happen, not intended to be called with non GTm_Cns"
--
asHeadConstraint :: GTm -> GTermAsM cnstr
--
asBodyConstraint :: GTm -> GTermAsM cnstr
--
asGuard :: GTm -> GTermAsM guard
--
asHeadBacktrackPrio :: GTm -> GTermAsM bprio
--
asAltBacktrackPrio :: GTm -> GTermAsM bprio
--
asRulePrio :: GTm -> GTermAsM prio
--
gtermasVar :: String -> GTermAsM IVar
gtermasVar s = modL gtermasNmToVarMp $ \m -> maybe (let i = Lk.size m in (i, Lk.insert s i m)) (,m) $ Lk.lookup s m
-- insertLookupWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> (Maybe a, Map k a)
-- | Fail the interpretation
gtermasFail :: GTm -> String -> GTermAsM a
gtermasFail t m = throwError $ "GTerm interpretation failure" >-< indent 2 ("why :" >#< m >-< "term:" >#< t)