module CommonTypes (module Options, module CommonTypes) where import Options import UU.Scanner.Position(Pos) import qualified Data.Map as Map import Data.Map(Map) import Data.Set(Set) import qualified Data.Set as Set import Data.Monoid(mappend,Monoid) import Data.Char import Pretty type Blocks = Map BlockInfo [([String], Pos)] type BlockInfo = (BlockKind, Maybe NontermIdent) data BlockKind = BlockImport | BlockPragma | BlockMain | BlockData | BlockRec | BlockOther deriving (Eq, Ord, Show) instance PP Identifier where pp = text . getName data Type = Haskell String | NT Identifier [String] Bool -- True: deforested nonterminal, False: nonterminal type | Self -- reference to the enclosing nonterminal type deriving (Eq) data ComplexType = List Type | Tuple [(Identifier, Type)] | Maybe Type | Either Type Type | Map Type Type | IntMap Type | OrdSet Type | IntSet instance Show ComplexType where show (List t ) = "[" ++ show t ++ "]" show (Tuple ts) = "(" ++ showList [ show n ++ ": " ++ show t | (n,t) <- ts ] "" ++ ")" show (Maybe t ) = "Maybe " ++ show t show (Either t1 t2) = "Either " ++ show t1 ++ " " ++ show t2 show (Map t1 t2) = "Map " ++ show t1 ++ " " ++ show t2 show (IntMap t1) = "IntMap " ++ show t1 show (OrdSet t1) = "Set" ++ show t1 show IntSet = "IntSet" instance Show Type where show = typeToHaskellString Nothing [] type Attributes = Map Identifier Type type TypeSyns = [(NontermIdent,ComplexType)] type ParamMap = Map NontermIdent [Identifier] type AttrNames = [(Identifier,Type,(String,String,String))] type UseMap = Map NontermIdent (Map Identifier (String,String,String)) type PragmaMap = Map NontermIdent (Map ConstructorIdent (Set Identifier)) type AttrMap = Map NontermIdent (Map ConstructorIdent (Set (Identifier,Identifier))) type UniqueMap = Map NontermIdent (Map ConstructorIdent (Map Identifier Identifier)) type Derivings = Map NontermIdent (Set Identifier) type ClassContext = [(Identifier, [String])] type ContextMap = Map NontermIdent ClassContext type QuantMap = Map NontermIdent [String] type Strings = [String] type ConstructorIdent = Identifier type AttrOrderMap = Map NontermIdent (Map ConstructorIdent (Set Dependency)) type VisitIdentifier = Int type StateIdentifier = Int data Dependency = Dependency Occurrence Occurrence deriving (Eq,Ord,Show) data Occurrence = OccAttr Identifier Identifier | OccRule Identifier deriving (Eq,Ord,Show) data ConstructorType = DataConstructor | RecordConstructor deriving (Eq,Ord,Show) type AttrEnv = ( [Identifier] , [(Identifier,Identifier)] ) nullIdent, _LHS, _SELF, _LOC, _INST, _INST', _FIELD, _FIRST, _LAST :: Identifier nullIdent = identifier "" _LHS = identifier "lhs" _SELF = identifier "SELF" _LOC = identifier "loc" _INST = identifier "inst" _INST' = identifier "inst'" _FIELD = identifier "field" _FIRST = identifier "first__" _LAST = identifier "last__" idLateBindingAttr :: Identifier idLateBindingAttr = identifier "lateSemDict" lateBindingTypeNm :: String -> String lateBindingTypeNm modNm = "Late_" ++ modNm ++ "_" lateBindingFieldNm :: String -> String lateBindingFieldNm modNm = "late_" ++ modNm ++ "_" lateBindingType :: String -> Type lateBindingType modNm = Haskell (lateBindingTypeNm modNm) lateSemNtLabel :: NontermIdent -> String lateSemNtLabel nt = "mk_" ++ getName nt lateSemConLabel :: NontermIdent -> ConstructorIdent -> String lateSemConLabel nt con = "mk_" ++ getName nt ++ "_" ++ getName con sdtype :: NontermIdent -> String sdtype nt = "T_"++getName nt mkNtType :: Identifier -> [String] -> Type mkNtType nt args | take 2 (getName nt) == "T_" = let nt' = Ident (drop 2 (getName nt)) (getPos nt) in NT nt' args True | otherwise = NT nt args False cataname :: String -> Identifier -> String cataname pre name = pre++getName name conname :: Bool -> NontermIdent -> ConstructorIdent -> String conname ren nt con | ren = capitalize (getName nt) ++ "_" ++ getName con | otherwise = getName con capitalize :: String -> String capitalize [] = [] capitalize (c:cs) = toUpper c : cs semname :: String -> NontermIdent -> ConstructorIdent -> String semname pre nt con = pre ++ (getName nt ++ "_" ++ getName con) recordFieldname :: NontermIdent -> ConstructorIdent -> Identifier -> String recordFieldname nt con nm = getName nm ++ "_" ++ getName nt ++ "_" ++ getName con lhsname :: Options -> Bool -> Identifier -> String lhsname opts isIn = attrname opts isIn _LHS attrname :: Options -> Bool -> Identifier -> Identifier -> String attrname opts isIn field attr | field == _LOC = locname opts attr | field == _INST = instname attr | field == _INST' = inst'name attr | field == _FIELD = fieldname attr | otherwise = let direction | isIn = "I" | otherwise = "O" pref = if clean opts then 'a' else '_' in pref : getName field ++ direction ++ getName attr locname :: Options -> Identifier -> String locname opts v = (if clean opts then 'l' else '_') : getName v instname, inst'name, fieldname :: Identifier -> String instname v = getName v ++ "_val_" inst'name v = getName v ++ "_inst_" fieldname v = getName v++"_" typeToAGString :: Type -> String typeToAGString tp = case tp of Haskell t -> t NT nt tps for -> formatNonterminalToHaskell for (getName nt) (map (\s -> "{" ++ s ++ "}") tps) Self -> error "Self type is not allowed here." removeDeforested :: Type -> Type removeDeforested (NT nt args _) = NT nt args False removeDeforested tp = tp forceDeforested :: Type -> Type forceDeforested (NT nt args _) = NT nt args True forceDeforested tp = tp typeToHaskellString :: Maybe NontermIdent -> [String] -> Type -> String typeToHaskellString mbNt params tp = case tp of Haskell t -> filter (/= '@') t -- Apparently haskell types can contain @ to refer to -- a type parameter, removing @ makes it backwards compatible NT nt tps for | nt == _SELF -> formatNonterminalToHaskell for (maybe "?SELF?" getName mbNt) params | otherwise -> formatNonterminalToHaskell for (getName nt) tps Self -> maybe "?SELF?" getName mbNt formatNonterminalToHaskell :: Bool -> String -> [String] -> String formatNonterminalToHaskell for nt tps = unwords ((pref ++ nt) : tps) where pref | for = "T_" | otherwise = "" ind :: String -> String ind s = replicate 3 ' ' ++ s _NOCASE :: Identifier _NOCASE = identifier "nocase" hasPragma :: PragmaMap -> NontermIdent -> ConstructorIdent -> Identifier -> Bool hasPragma mp nt con nm = nm `Set.member` Map.findWithDefault Set.empty con (Map.findWithDefault Map.empty nt mp) isNonterminal :: Type -> Bool isNonterminal (NT _ _ _) = True isNonterminal _ = False isSELFNonterminal :: Type -> Bool -- isSELFNonterminal (NT nt _ _) | nt == _SELF = True isSELFNonterminal Self = True isSELFNonterminal _ = False extractNonterminal :: Type -> NontermIdent extractNonterminal (NT n _ _) = n extractNonterminal _ = error "Must be NT" nontermArgs :: Type -> [String] nontermArgs tp = case tp of NT _ args _ -> args _ -> [] deforestedNt :: Identifier -> Maybe Identifier deforestedNt nm | take 2 (getName nm) == "T_" = Just (Ident (drop 2 (getName nm)) (getPos nm)) | otherwise = Nothing data StateCtx = NoneVis | OneVis !Int | ManyVis deriving (Eq, Show, Ord) data ChildKind = ChildSyntax -- This child is defined by syntax | ChildAttr -- This child is defined by an attribute | ChildReplace Type -- This child replaces a child with type Type deriving (Eq, Show) -- Given a map that represents a relation, returns the transitive closure of this relation closeMap :: Ord a => Map a (Set a) -> Map a (Set a) closeMap mp0 = close (Map.keysSet mp0) mp0 where rev = revDeps mp0 close todo mp0' = case Set.minView todo of Nothing -> mp0' Just (k, todo1) -> let find x = Map.findWithDefault Set.empty x mp0' vals0 = find k valsL = Set.toList vals0 vals1 = foldr Set.union vals0 $ map find valsL in if Set.size vals0 == Set.size vals1 then close todo1 mp0' -- note: monotonically increasing set else let mp1 = Map.insert k vals1 mp0' refs = Map.findWithDefault Set.empty k rev todo2 = Set.union refs todo1 in close todo2 mp1 revDeps :: Ord a => Map a (Set a) -> Map a (Set a) revDeps mp = Map.fromListWith Set.union [ (a,Set.singleton k) | (k,s) <- Map.assocs mp, a <- Set.toList s ] data HigherOrderInfo = HigherOrderInfo { hoNtDeps :: Set NontermIdent , hoNtRevDeps :: Set NontermIdent , hoAcyclic :: Bool } data VisitKind = VisitPure Bool -- ordered or not | VisitMonadic deriving (Eq,Ord) isLazyKind :: VisitKind -> Bool isLazyKind (VisitPure False) = True isLazyKind _ = False instance Show VisitKind where show (VisitPure False) = "Lazy" show (VisitPure True) = "Ordered" show VisitMonadic = "Monadic" unionWithMappend :: (Monoid a, Ord k) => Map k a -> Map k a -> Map k a unionWithMappend = Map.unionWith mappend data FormatMode = FormatDo | FormatLetDecl | FormatLetLine deriving (Eq, Ord, Show)