Sublogic.hs revision 1a38107941725211e7c3f051f7a8f5e12199f03a
{-# LANGUAGE DeriveDataTypeable #-}
{- |
Module : $Header$
Description : HasCASL's sublogics
Copyright : (c) Sonja Groening, C. Maeder, and Uni Bremen 2002-2006
License : GPLv2 or higher, see LICENSE.txt
Maintainer : Christian.Maeder@dfki.de
Stability : experimental
Portability : portable
This module provides the sublogic functions (as required by Logic.hs) for
HasCASL. The functions allow to compute the minimal sublogic needed by a
given element, to check whether an item is part of a given sublogic, and --
not yet -- to project an element into a given sublogic.
-}
module HasCASL.Sublogic
( -- * datatypes
Sublogic (..)
, Formulas (..)
, Classes (..)
-- * functions for SemiLatticeWithTop instance
, topLogic
, sublogic_max
-- * combining sublogics restrictions
, sublogic_min
, sublogicUp
, need_hol
-- * further sublogic constants
, bottom
, noSubtypes
, noClasses
, totalFuns
, caslLogic
-- * functions for Logic instance
-- ** sublogic to string converstion
, sublogic_name
-- ** list of all sublogics
, sublogics_all
-- ** checks if element is in given sublogic
, in_basicSpec
, in_sentence
, in_symbItems
, in_symbMapItems
, in_env
, in_morphism
, in_symbol
-- * computes the sublogic of a given element
, sl_basicSpec
, sl_sentence
, sl_symbItems
, sl_symbMapItems
, sl_env
, sl_morphism
, sl_symbol
) where
import Data.Data
import qualified Data.Map as Map
import qualified Data.Set as Set
import Common.AS_Annotation
import Common.Id
import HasCASL.As
import HasCASL.AsUtils
import HasCASL.Le as Le
import HasCASL.Builtin
import HasCASL.FoldTerm
-- | formula kinds of HasCASL sublogics
data Formulas
= Atomic -- ^ atomic logic
| Horn -- ^ positive conditional logic
| GHorn -- ^ generalized positive conditional logic
| FOL -- ^ first-order logic
| HOL -- ^ higher-order logic
deriving (Show, Eq, Ord, Typeable, Data)
data Classes = NoClasses | SimpleTypeClasses | ConstructorClasses
deriving (Show, Eq, Ord, Typeable, Data)
-- | HasCASL sublogics
data Sublogic = Sublogic
{ has_sub :: Bool -- ^ subsorting
, has_part :: Bool -- ^ partiality
, has_eq :: Bool -- ^ equality
, has_pred :: Bool -- ^ predicates
, type_classes :: Classes
, has_polymorphism :: Bool
, has_type_constructors :: Bool
, has_products :: Bool
, which_logic :: Formulas
} deriving (Show, Eq, Ord, Typeable, Data)
-- * special sublogic elements
-- | top element
topLogic :: Sublogic
topLogic = Sublogic
{ has_sub = True
, has_part = True
, has_eq = True
, has_pred = True
, type_classes = ConstructorClasses
, has_polymorphism = True
, has_type_constructors = True
, has_products = True
, which_logic = HOL
}
-- | top sublogic without subtypes
noSubtypes :: Sublogic
noSubtypes = topLogic { has_sub = False }
-- | top sublogic without type classes
noClasses :: Sublogic
noClasses = topLogic { type_classes = NoClasses }
-- | top sublogic without partiality
totalFuns :: Sublogic
totalFuns = topLogic { has_part = False }
caslLogic :: Sublogic
caslLogic = noClasses
{ has_polymorphism = False
, has_type_constructors = False
, has_products = False
, which_logic = FOL
}
-- | bottom sublogic
bottom :: Sublogic
bottom = Sublogic
{ has_sub = False
, has_part = False
, has_eq = False
, has_pred = False
, type_classes = NoClasses
, has_polymorphism = False
, has_type_constructors = False
, has_products = False
, which_logic = Atomic
}
{- the following are used to add a needed feature to a given
sublogic via sublogic_max, i.e. (sublogic_max given needs_part)
will force partiality in addition to what features given already
has included -}
-- | minimal sublogic with partiality
need_part :: Sublogic
need_part = bottom { has_part = True }
-- | minimal sublogic with equality
need_eq :: Sublogic
need_eq = bottom { has_eq = True }
-- | minimal sublogic with predicates
need_pred :: Sublogic
need_pred = bottom { has_pred = True }
-- | minimal sublogic with subsorting
need_sub :: Sublogic
need_sub = need_pred { has_sub = True }
-- | minimal sublogic with polymorhism
need_polymorphism :: Sublogic
need_polymorphism = bottom { has_polymorphism = True }
-- | minimal sublogic with simple type classes
simpleTypeClasses :: Sublogic
simpleTypeClasses = need_polymorphism { type_classes = SimpleTypeClasses }
-- | minimal sublogic with constructor classes
constructorClasses :: Sublogic
constructorClasses = need_polymorphism { type_classes = ConstructorClasses }
-- | minimal sublogic with type constructors
need_type_constructors :: Sublogic
need_type_constructors = bottom { has_type_constructors = True,
has_products = True }
need_product_type_constructor :: Sublogic
need_product_type_constructor = bottom { has_products = True }
need_horn :: Sublogic
need_horn = bottom { which_logic = Horn }
need_ghorn :: Sublogic
need_ghorn = bottom { which_logic = GHorn }
need_fol :: Sublogic
need_fol = bottom { which_logic = FOL }
need_hol :: Sublogic
need_hol = need_pred { which_logic = HOL }
-- | make sublogic consistent w.r.t. illegal combinations
sublogicUp :: Sublogic -> Sublogic
sublogicUp s' = let s = if has_type_constructors s'
then s' { has_products = True } else s'
in if which_logic s == HOL || has_sub s then
s { has_pred = True } else s
-- | generate a list of all sublogics for HasCASL
sublogics_all :: [Sublogic]
sublogics_all = let bools = [False, True] in
[ Sublogic
{ has_sub = sub
, has_part = part
, has_eq = eq
, has_pred = pre
, type_classes = tyCl
, has_polymorphism = poly
, has_type_constructors = tyCon
, has_products = prods || tyCon
, which_logic = logic
}
| (tyCl, poly) <- [(NoClasses, False), (NoClasses, True),
(SimpleTypeClasses, True), (ConstructorClasses, True)]
, tyCon <- bools
, prods <- bools
, sub <- bools
, part <- bools
, eq <- bools
, pre <- bools
, logic <- [Atomic, Horn, GHorn, FOL, HOL]
, pre || logic /= HOL && not sub
]
-- | conversion functions to String
formulas_name :: Bool -> Formulas -> String
formulas_name hasPred f = case f of
HOL -> "HOL"
FOL -> if hasPred then "FOL" else "FOAlg"
_ -> case f of
Atomic -> if hasPred then "Atom" else "Eq"
_ -> (case f of
GHorn -> ("G" ++)
_ -> id) $ if hasPred then "Horn" else "Cond"
-- | the sublogic name as a singleton string list
sublogic_name :: Sublogic -> String
sublogic_name x =
(if has_sub x then "Sub" else "")
++ (if has_part x then "P" else "")
++ (case type_classes x of
NoClasses -> if has_polymorphism x then "Poly" else ""
SimpleTypeClasses -> "TyCl"
ConstructorClasses -> "CoCl")
++ (if has_type_constructors x then "TyCons" else "")
++ (if has_products x then "Prods" else "")
++ formulas_name (has_pred x) (which_logic x)
++ (if has_eq x then "=" else "")
-- * join functions
sublogic_join :: (Bool -> Bool -> Bool)
-> (Classes -> Classes -> Classes)
-> (Formulas -> Formulas -> Formulas)
-> Sublogic -> Sublogic -> Sublogic
sublogic_join joinB joinC joinF a b = Sublogic
{ has_sub = joinB (has_sub a) $ has_sub b
, has_part = joinB (has_part a) $ has_part b
, has_eq = joinB (has_eq a) $ has_eq b
, has_pred = joinB (has_pred a) $ has_pred b
, type_classes = joinC (type_classes a) $ type_classes b
, has_polymorphism = joinB (has_polymorphism a) $ has_polymorphism b
, has_type_constructors =
joinB (has_type_constructors a) $ has_type_constructors b
, has_products = has_products a || has_products b
|| has_type_constructors a
|| has_type_constructors b
, which_logic = joinF (which_logic a) $ which_logic b
}
sublogic_max :: Sublogic -> Sublogic -> Sublogic
sublogic_max = sublogic_join max max max
sublogic_min :: Sublogic -> Sublogic -> Sublogic
sublogic_min = sublogic_join min min min
-- | compute union sublogic from a list of sublogics
comp_list :: [Sublogic] -> Sublogic
comp_list = foldl sublogic_max bottom
-- Functions to analyse formulae
{- ---------------------------------------------------------------------------
These functions are based on Till Mossakowski's paper "Sublanguages of
CASL", which is CoFI Note L-7. The functions implement an adaption of
the reduced grammar given there for formulae in a specific expression
logic by, checking whether a formula would match the productions from the
grammar. Which function checks for which nonterminal from the paper is
given as a comment before each function.
They are adapted for HasCASL, especially HasCASLs abstract syntax (As.hs)
--------------------------------------------------------------------------- -}
-- Atomic Logic (subsection 3.4 of the paper)
isPredication :: Term -> Bool
isPredication = foldTerm FoldRec
{ foldQualVar = \ _ _ -> True
, foldQualOp = \ _ b (PolyId i _ _) t _ _ _ ->
b /= Fun && notElem (i, t) bList
, foldApplTerm = \ _ b1 b2 _ -> b1 && b2
, foldTupleTerm = \ _ bs _ -> and bs
, foldTypedTerm = \ _ b q _ _ -> q /= InType && b
, foldAsPattern = \ _ _ _ _ -> False
, foldQuantifiedTerm = \ _ _ _ _ _ -> False
, foldLambdaTerm = \ _ _ _ _ _ -> False
, foldCaseTerm = \ _ _ _ _ -> False
, foldLetTerm = \ _ _ _ _ _ -> False
, foldResolvedMixTerm = \ _ i _ bs _ ->
notElem i (map fst bList) && and bs
, foldTermToken = \ _ _ -> True
, foldMixTypeTerm = \ _ q _ _ -> q /= InType
, foldMixfixTerm = const and
, foldBracketTerm = \ _ _ bs _ -> and bs
, foldProgEq = \ _ _ _ _ -> False
}
-- FORMULA, P-ATOM
is_atomic_t :: Term -> Bool
is_atomic_t term = case term of
QuantifiedTerm q _ t _ | is_atomic_q q && is_atomic_t t -> True
-- P-Conjunction and ExEq
ApplTerm (QualOp _ (PolyId i _ _) t _ _ _) arg _
| (case arg of
TupleTerm ts@[_, _] _ ->
i == andId && t == logType && all is_atomic_t ts
|| i == exEq && t == eqType
_ -> False) || i == defId && t == defType
-> True
QualOp _ (PolyId i _ _) t _ _ _
| i == trueId && t == unitTypeScheme -> True
_ -> isPredication term
-- QUANTIFIER
is_atomic_q :: Quantifier -> Bool
is_atomic_q q = case q of
Universal -> True
_ -> False
-- Positive Conditional Logic (subsection 3.2 in the paper)
-- FORMULA
is_horn_t :: Term -> Bool
is_horn_t term = case term of
QuantifiedTerm q _ f _ -> is_atomic_q q && is_horn_t f
ApplTerm (QualOp _ (PolyId i _ _) t _ _ _) (TupleTerm [t1, t2] _) _
| i == implId && t == logType && is_horn_p_conj t1 && is_horn_a t2
-> True
_ -> is_atomic_t term
-- P-CONJUNCTION
is_horn_p_conj :: Term -> Bool
is_horn_p_conj term = case term of
ApplTerm (QualOp _ (PolyId i _ _) t _ _ _) (TupleTerm ts@[_, _] _) _
| i == andId && t == logType && all is_horn_a ts
-> True
_ -> is_atomic_t term
-- ATOM
is_horn_a :: Term -> Bool
is_horn_a term = case term of
QualOp _ (PolyId i _ _) t _ _ _
| i == trueId && t == unitTypeScheme -> True
ApplTerm (QualOp _ (PolyId i _ _) t _ _ _) arg _
| (case arg of
TupleTerm [_, _] _ -> isEq i && t == eqType
_ -> False) || i == defId && t == defType
-> True
_ -> is_atomic_t term
-- P-ATOM
is_horn_p_a :: Term -> Bool
is_horn_p_a term = case term of
QualOp _ (PolyId i _ _) t _ _ _
| i == trueId && t == unitTypeScheme -> True
ApplTerm (QualOp _ (PolyId i _ _) t _ _ _) arg _
| (case arg of
TupleTerm [_, _] _ -> i == exEq && t == eqType
_ -> False) || i == defId && t == defType
-> True
_ -> is_atomic_t term
-- Generalized Positive Conditional Logic (subsection 3.3 of the paper)
-- FORMULA, ATOM
is_ghorn_t :: Term -> Bool
is_ghorn_t term = case term of
QuantifiedTerm q _ t _ -> is_atomic_q q && is_ghorn_t t
ApplTerm (QualOp _ (PolyId i _ _) t _ _ _) arg _
| (case arg of
TupleTerm f@[f1, f2] _ ->
t == logType &&
(i == andId && (is_ghorn_c_conj f || is_ghorn_f_conj f)
|| i == implId && is_ghorn_prem f1 && is_ghorn_conc f2
|| i == eqvId && is_ghorn_prem f1 && is_ghorn_prem f2)
|| t == eqType && isEq i
_ -> False) || t == defType && i == defId
-> True
_ -> is_atomic_t term
-- C-CONJUNCTION
is_ghorn_c_conj :: [Term] -> Bool
is_ghorn_c_conj = all is_ghorn_conc
-- F-CONJUNCTION
is_ghorn_f_conj :: [Term] -> Bool
is_ghorn_f_conj = all is_ghorn_t
-- P-CONJUNCTION
is_ghorn_p_conj :: [Term] -> Bool
is_ghorn_p_conj = all is_ghorn_prem
-- PREMISE
is_ghorn_prem :: Term -> Bool
is_ghorn_prem term = case term of
ApplTerm (QualOp _ (PolyId i _ _) t _ _ _) (TupleTerm ts@[_, _] _) _ ->
i == andId && t == logType && is_ghorn_p_conj ts
_ -> is_horn_p_a term
-- CONCLUSION
is_ghorn_conc :: Term -> Bool
is_ghorn_conc term = case term of
ApplTerm (QualOp _ (PolyId i _ _) t _ _ _) (TupleTerm ts@[_, _] _) _ ->
i == andId && t == logType && is_ghorn_c_conj ts
_ -> is_horn_a term
is_fol_t :: Term -> Bool
is_fol_t t = case t of
LambdaTerm {} -> False
CaseTerm {} -> False
LetTerm {} -> False
_ -> True
{- FOL:
no lambda/let/case,
no higher types (i.e. all types are basic, tuples, or tuple -> basic)
-}
-- | compute logic of a formula by checking all logics in turn
get_logic :: Term -> Sublogic
get_logic t
| is_atomic_t t = bottom
| is_horn_t t = need_horn
| is_ghorn_t t = need_ghorn
| is_fol_t t = need_fol
| otherwise = need_hol
{- Functions to compute minimal sublogic for a given element; these work
by recursing into all subelements -}
sl_basicSpec :: BasicSpec -> Sublogic
sl_basicSpec (BasicSpec l) =
sublogicUp $ comp_list $ map (sl_basicItem . item) l
sl_basicItem :: BasicItem -> Sublogic
sl_basicItem bIt = case bIt of
SigItems l -> sl_sigItems l
ProgItems l _ -> comp_list $ map (sl_progEq . item) l
ClassItems _ l _ -> comp_list $ map (sl_classItem . item) l
GenVarItems l _ -> comp_list $ map sl_genVarDecl l
FreeDatatype l _ -> comp_list $ map (sl_datatypeDecl . item) l
GenItems l _ -> comp_list $ map (sl_sigItems . item) l
AxiomItems l m _ ->
comp_list $ map sl_genVarDecl l ++ map (sl_term . item) m
Internal l _ -> comp_list $ map (sl_basicItem . item) l
sl_sigItems :: SigItems -> Sublogic
sl_sigItems sIt = case sIt of
TypeItems i l _ ->
comp_list $ sl_instance i : map (sl_typeItem . item) l
OpItems b l _ ->
comp_list $ sl_opBrand b : map (sl_opItem . item) l
sl_opBrand :: OpBrand -> Sublogic
sl_opBrand o = case o of
Pred -> need_pred
_ -> bottom
sl_instance :: Instance -> Sublogic
sl_instance i = case i of
Instance -> simpleTypeClasses
_ -> bottom
sl_classItem :: ClassItem -> Sublogic
sl_classItem (ClassItem c l _) =
comp_list $ sl_classDecl c : map (sl_basicItem . item) l
sl_classDecl :: ClassDecl -> Sublogic
sl_classDecl (ClassDecl _ k _) = case k of
ClassKind _ -> simpleTypeClasses
FunKind {} -> constructorClasses
-- don't check the variance or kind of builtin type constructors
sl_Variance :: Variance -> Sublogic
sl_Variance v = case v of
NonVar -> bottom
_ -> need_sub
sl_AnyKind :: (a -> Sublogic) -> AnyKind a -> Sublogic
sl_AnyKind f k = case k of
ClassKind i -> f i
FunKind v k1 k2 _ ->
comp_list [sl_Variance v, sl_AnyKind f k1, sl_AnyKind f k2]
sl_Rawkind :: RawKind -> Sublogic
sl_Rawkind = sl_AnyKind (const bottom)
sl_kind :: Kind -> Sublogic
sl_kind = sl_AnyKind $
\ i -> if i == universeId then bottom else simpleTypeClasses
sl_typeItem :: TypeItem -> Sublogic
sl_typeItem tyIt = case tyIt of
TypeDecl l k _ -> comp_list $ sl_kind k : map sl_typePattern l
SubtypeDecl l _ _ -> comp_list $ need_sub : map sl_typePattern l
IsoDecl l _ -> comp_list $ need_sub : map sl_typePattern l
SubtypeDefn tp _ t term _ -> comp_list
[ need_sub
, sl_typePattern tp
, sl_type t
, sl_term $ item term ]
AliasType tp (Just k) ts _ -> comp_list
[ sl_kind k
, sl_typePattern tp
, sl_typeScheme ts ]
AliasType tp Nothing ts _ ->
sublogic_max (sl_typePattern tp) $ sl_typeScheme ts
Datatype dDecl -> sl_datatypeDecl dDecl
sl_typePattern :: TypePattern -> Sublogic
sl_typePattern tp = case tp of
TypePattern _ l _ -> comp_list $ map sl_typeArg l
-- non-empty args --> type constructor!
MixfixTypePattern l -> comp_list $ map sl_typePattern l
BracketTypePattern _ l _ -> comp_list $ map sl_typePattern l
TypePatternArg _ _ -> need_polymorphism
_ -> bottom
sl_type :: Type -> Sublogic
sl_type = sl_BasicFun
sl_Basictype :: Type -> Sublogic
sl_Basictype ty = case getTypeAppl ty of
(TypeName tid _ _, _) | isProductId tid -> need_product_type_constructor
_ -> case ty of
TypeName _ k v -> sublogic_max
(if v /= 0 then need_polymorphism else bottom) $ sl_Rawkind k
KindedType t k _ -> comp_list $ sl_Basictype t : map sl_kind (Set.toList k)
ExpandedType _ t -> sl_Basictype t
TypeAbs v t _ -> comp_list
[ need_type_constructors
, sl_typeArg v
, sl_Basictype t ]
BracketType Parens [t] _ -> sl_Basictype t
_ -> case getTypeAppl ty of
(TypeName ide _ _, args) -> comp_list $
(if isArrow ide || ide == lazyTypeId then need_hol else
need_type_constructors) : map sl_Basictype args
(_, []) -> bottom
(t, args) -> comp_list $ sl_Basictype t : map sl_Basictype args
sl_BasicProd :: Type -> Sublogic
sl_BasicProd ty = case getTypeAppl ty of
(TypeName ide _ _, tyArgs@(_ : _ : _))
| isProductIdWithArgs ide $ length tyArgs
-> comp_list $ map sl_Basictype tyArgs
_ -> sl_Basictype ty
isAnyUnitType :: Type -> Bool
isAnyUnitType ty = case ty of
BracketType Parens [] _ -> True
TypeToken t -> tokStr t == unitTypeS
_ -> ty == unitType
sl_BasicFun :: Type -> Sublogic
sl_BasicFun ty = case getTypeAppl ty of
(TypeName ide _ _, [arg, res]) | isArrow ide -> comp_list
[ if isPartialArrow ide then
if isAnyUnitType res then need_pred else need_part
else bottom
, sl_BasicProd arg
, sl_Basictype res ]
_ -> sl_Basictype ty
-- FOL, no higher types, all types are basic, tuples, or tuple -> basic
sl_typeScheme :: TypeScheme -> Sublogic
sl_typeScheme (TypeScheme l t _) = comp_list $ sl_type t : map sl_typeArg l
sl_opItem :: OpItem -> Sublogic
sl_opItem o = case o of
OpDecl l t m _ -> comp_list $
sl_typeScheme t : map sl_opId l ++ map sl_opAttr m
OpDefn i v ts t _ -> comp_list $
[ sl_opId i
, sl_typeScheme ts
, sl_term t
] ++ map sl_varDecl (concat v)
sl_partiality :: Partiality -> Sublogic
sl_partiality p = case p of
Partial -> need_part
Total -> bottom
sl_opAttr :: OpAttr -> Sublogic
sl_opAttr a = case a of
UnitOpAttr t _ -> sl_term t
_ -> need_eq
sl_datatypeDecl :: DatatypeDecl -> Sublogic
sl_datatypeDecl (DatatypeDecl t k l c _) = comp_list $
[ if null c then bottom else simpleTypeClasses
, sl_typePattern t
, sl_kind k ] ++ map (sl_alternative . item) l
sl_alternative :: Alternative -> Sublogic
sl_alternative a = case a of
Constructor _ l p _ ->
comp_list $ sl_partiality p : map sl_component (concat l)
Subtype l _ -> comp_list $ need_sub : map sl_type l
sl_component :: Component -> Sublogic
sl_component s = case s of
Selector _ p t _ _ -> sublogic_max (sl_partiality p) $ sl_type t
NoSelector t -> sl_type t
sl_term :: Term -> Sublogic
sl_term t = sublogic_max (get_logic t) $ sl_t t
{- typed in- or as-terms would also indicate subtyping
but we rely on the subtypes in the signature -}
sl_t :: Term -> Sublogic
sl_t trm = case trm of
QualVar vd -> sl_varDecl vd
QualOp b i@(PolyId ri _ _) t _ _ _ ->
if elem ri $ map fst bList then sl_opId i else
comp_list
[ sl_opBrand b
, sl_opId i
, sl_typeScheme t ]
ApplTerm t1 t2 _ -> case getAppl trm of
Just (i, _, arg) | elem i $ map fst bList -> comp_list (map sl_t arg)
_ -> sublogic_max (sl_t t1) $ sl_t t2
TupleTerm l _ -> comp_list $ map sl_t l
TypedTerm t _ ty _ -> sublogic_max (sl_t t) $ sl_type ty
QuantifiedTerm _ l t _ -> comp_list $ sl_t t : map sl_genVarDecl l
LambdaTerm l p t _ ->
comp_list $ sl_partiality p : sl_t t : map sl_t l
CaseTerm t l _ -> comp_list $ sl_t t : map sl_progEq l ++ map sl_progEq l
LetTerm _ l t _ -> comp_list $ sl_t t : map sl_progEq l
MixTypeTerm _ t _ -> sl_type t
MixfixTerm l -> comp_list $ map sl_t l
BracketTerm _ l _ -> comp_list $ map sl_t l
AsPattern vd p2 _ -> sublogic_max (sl_varDecl vd) $ sl_t p2
_ -> bottom
sl_progEq :: ProgEq -> Sublogic
sl_progEq (ProgEq p t _) = sublogic_max (sl_t p) (sl_t t)
sl_varDecl :: VarDecl -> Sublogic
sl_varDecl (VarDecl _ t _ _) = sl_type t
sl_varKind :: VarKind -> Sublogic
sl_varKind vk = case vk of
VarKind k -> sl_kind k
Downset t -> sublogic_max need_sub $ sl_type t
_ -> bottom
sl_typeArg :: TypeArg -> Sublogic
sl_typeArg (TypeArg _ _ k _ _ _ _) =
sublogic_max need_polymorphism (sl_varKind k)
sl_genVarDecl :: GenVarDecl -> Sublogic
sl_genVarDecl g = case g of
GenVarDecl v -> sl_varDecl v
GenTypeVarDecl v -> sl_typeArg v
isEq :: Id -> Bool
isEq = (`elem` [exEq, eqId])
sl_opId :: PolyId -> Sublogic
sl_opId (PolyId i tys _)
| isEq i = need_eq
| elem i [botId, defId, resId] = need_part
| elem i $ map fst bList = bottom
| otherwise = comp_list $ map sl_typeArg tys
sl_symbItems :: SymbItems -> Sublogic
sl_symbItems (SymbItems k l _ _) = comp_list $ sl_symbKind k : map sl_symb l
sl_symbMapItems :: SymbMapItems -> Sublogic
sl_symbMapItems (SymbMapItems k l _ _) =
comp_list $ sl_symbKind k : map sl_symbOrMap l
sl_symbKind :: SymbKind -> Sublogic
sl_symbKind k = case k of
SyKpred -> need_pred
SyKclass -> simpleTypeClasses
_ -> bottom
sl_symb :: Symb -> Sublogic
sl_symb s = case s of
Symb _ Nothing _ -> bottom
Symb _ (Just l) _ -> sl_symbType l
sl_symbType :: SymbType -> Sublogic
sl_symbType (SymbType t) = sl_typeScheme t
sl_symbOrMap :: SymbOrMap -> Sublogic
sl_symbOrMap m = case m of
SymbOrMap s Nothing _ -> sl_symb s
SymbOrMap s (Just t) _ -> sublogic_max (sl_symb s) $ sl_symb t
{- the maps have no influence since all sorts,ops,preds in them
must also appear in the signatures, so any features needed by
them will be included by just checking the signatures -}
sl_env :: Env -> Sublogic
sl_env e = sublogicUp $ comp_list $
(if Map.null $ classMap e then bottom else simpleTypeClasses)
: map sl_typeInfo (Map.elems $ typeMap e)
++ map sl_opInfos (Map.elems $ assumps e)
sl_typeInfo :: TypeInfo -> Sublogic
sl_typeInfo t =
sublogic_max (if Set.null $ superTypes t then bottom else need_sub)
$ sl_typeDefn $ typeDefn t
sl_typeDefn :: TypeDefn -> Sublogic
sl_typeDefn d = case d of
DatatypeDefn de -> sl_dataEntry de
AliasTypeDefn t -> sl_type t
_ -> bottom
sl_dataEntry :: DataEntry -> Sublogic
sl_dataEntry (DataEntry _ _ _ l _ m) =
comp_list $ map sl_typeArg l ++ map sl_altDefn (Set.toList m)
sl_opInfos :: Set.Set OpInfo -> Sublogic
sl_opInfos = comp_list . map sl_opInfo . Set.toList
sl_opInfo :: OpInfo -> Sublogic
sl_opInfo o = comp_list $ sl_typeScheme (opType o) : sl_opDefn (opDefn o)
: map sl_opAttr (Set.toList $ opAttrs o)
sl_opDefn :: OpDefn -> Sublogic
sl_opDefn o = case o of
NoOpDefn b -> sl_opBrand b
SelectData l _ -> comp_list $ map sl_constrInfo $ Set.toList l
Definition b t -> sublogic_max (sl_opBrand b) $ sl_term t
_ -> bottom
sl_constrInfo :: ConstrInfo -> Sublogic
sl_constrInfo = sl_typeScheme . Le.constrType
sl_sentence :: Sentence -> Sublogic
sl_sentence s = sublogicUp $ case s of
Formula t -> sl_term t
ProgEqSen _ ts pq -> sublogic_max (sl_typeScheme ts) $ sl_progEq pq
DatatypeSen l -> comp_list $ map sl_dataEntry l
{- a missing constructor identifier also indicates subtyping
but checking super types is enough for subtype detection -}
sl_altDefn :: AltDefn -> Sublogic
sl_altDefn (Construct _ l p m) = comp_list $ sl_partiality p :
map sl_type l ++ map sl_selector (concat m)
sl_selector :: Selector -> Sublogic
sl_selector (Select _ t p) = sublogic_max (sl_type t) $ sl_partiality p
sl_morphism :: Morphism -> Sublogic
sl_morphism m = sublogic_max (sl_env $ msource m) $ sl_env $ mtarget m
sl_symbol :: Symbol -> Sublogic
sl_symbol (Symbol _ t) = sl_symbolType t
sl_symbolType :: SymbolType -> Sublogic
sl_symbolType s = case s of
OpAsItemType t -> sl_typeScheme t
ClassAsItemType _ -> simpleTypeClasses
_ -> bottom
-- | check if the second sublogic is contained in the first sublogic
sl_in :: Sublogic -> Sublogic -> Bool
sl_in given new = sublogic_max given new == given
in_x :: Sublogic -> a -> (a -> Sublogic) -> Bool
in_x l x f = sl_in l (f x)
in_basicSpec :: Sublogic -> BasicSpec -> Bool
in_basicSpec l x = in_x l x sl_basicSpec
in_sentence :: Sublogic -> Sentence -> Bool
in_sentence l x = in_x l x sl_sentence
in_symbItems :: Sublogic -> SymbItems -> Bool
in_symbItems l x = in_x l x sl_symbItems
in_symbMapItems :: Sublogic -> SymbMapItems -> Bool
in_symbMapItems l x = in_x l x sl_symbMapItems
in_env :: Sublogic -> Env -> Bool
in_env l x = in_x l x sl_env
in_morphism :: Sublogic -> Morphism -> Bool
in_morphism l x = in_x l x sl_morphism
in_symbol :: Sublogic -> Symbol -> Bool
in_symbol l x = in_x l x sl_symbol