Copyright : (c) Christian Maeder and Uni Bremen 2002-2003
Maintainer : maeder@tzi.de
Portability : non-portable (MonadState)
analyse generic var (or type var) decls
-- | add diagnostic messages
addDiags :: [Diagnosis] -> State Env ()
put $ e {envDiags = reverse ds ++ envDiags e}
appendSentences :: [Named Sentence] -> State Env ()
put $ e {sentences = reverse fs ++ sentences e}
anaStarType :: Type -> State Env (Maybe Type)
anaStarType t = do mp <- fromResult $ anaStarTypeR t . typeMap
anaInstTypes :: [Type] -> State Env [Type]
anaInstTypes ts = if null ts then return []
else do mp <- fromResult $ anaType (Nothing, head ts) . typeMap
rs <- anaInstTypes $ tail ts
anaTypeScheme :: TypeScheme -> State Env (Maybe TypeScheme)
anaTypeScheme (TypeScheme tArgs ty p) =
do tm <- gets typeMap -- save global variables
mArgs <- mapM anaTypeVarDecl tArgs
let newArgs = catMaybes mArgs
putTypeMap tm -- forget local variables
Nothing -> return Nothing
let newSc = TypeScheme newArgs newTy p
gTy <- if null newArgs then return $ generalize newSc
generalizeS :: TypeScheme -> State Env TypeScheme
addDiags $ generalizable sc
anaKind :: Kind -> State Env Kind
anaKind k = toState star $ anaKindM k
toState :: a -> (Env -> Result a) -> State Env a
fromResult :: (Env -> Result a) -> State Env (Maybe a)
-- ---------------------------------------------------------------------------
-- storing type ids with their kind and definition
-- ---------------------------------------------------------------------------
-- | store a complete type map
putTypeMap :: TypeMap -> State Env ()
putTypeMap tk = do { e <- get; put e { typeMap = tk } }
-- | store type id and check kind arity (warn on redeclared types)
addTypeId :: Bool -> TypeDefn -> Instance -> Kind -> Id -> State Env (Maybe Id)
addTypeId warn defn _ kind i =
if placeCount i <= kindArity TopLevel nk then
do addTypeKind warn defn i kind
else do addDiags [mkDiag Error "wrong arity of" i]
-- | store type as is (warn on redeclared types)
addTypeKind :: Bool -> TypeDefn -> Id -> Kind -> State Env ()
(_, v) <- toEnvState $ freshVar (posOfId i)
(TypeInfo rk [k] [] $ TypeVarDefn v) tk
_ -> putTypeMap $
Map.insert i (TypeInfo rk [k] [] d) tk
Just (TypeInfo ok ks sups defn) ->
then do let isKnownInst = k `elem` ks
insts = if isKnownInst then ks else
Result ds mDef = mergeTypeDefn defn d
if warn && isKnownInst && case (defn, d) of
(PreDatatype, DatatypeDefn _) -> False
(TypeInfo ok insts sups newDefn) tk
Nothing -> addDiags $ map (improveDiag i) ds
else addDiags $ diffKindDiag i ok rk
-- | analyse a type argument and look up a missing kind
anaTypeVarDecl :: TypeArg -> State Env (Maybe TypeArg)
anaTypeVarDecl(TypeArg t k s ps) =
Nothing -> anaTypeVarDecl(TypeArg t star s ps)
Just oldK -> addTypeVarDecl False (TypeArg t oldK s ps)
addTypeVarDecl True $ TypeArg t nk s ps
-- | add an analysed type argument (warn on redeclared types)
addTypeVarDecl :: Bool -> TypeArg -> State Env (Maybe TypeArg)
addTypeVarDecl warn ta@(TypeArg t k _ _) =
do mi <- addTypeId warn (TypeVarDefn 0) Plain k t
return $ fmap (const ta) mi
-- | compute arity from a 'Kind'
kindArity :: ApplMode -> Kind -> Int
FunKind k1 k2 _ -> case m of
TopLevel -> kindArity OnlyArg k1 +
Intersection [] _ -> case m of
ClassKind _ ck -> kindArity m ck
Downset _ _ dk _ -> kindArity m dk
Intersection (k1:_) _ -> kindArity m k1
ExtKind ek _ _ -> kindArity m ek
-- ---------------------------------------------------------------------------
-- for storing selectors and constructors
-- ---------------------------------------------------------------------------
putAssumps :: Assumps -> State Env ()
putAssumps as = do { e <- get; put e { assumps = as } }
-- | get matching information of uninstantiated identifier
findOpId :: Env -> UninstOpId -> TypeScheme -> Maybe OpInfo
findOpId e i sc = listToMaybe $ fst $ partitionOpId e i sc
-- | partition information of an uninstantiated identifier
partitionOpId :: Env -> UninstOpId -> TypeScheme -> ([OpInfo], [OpInfo])
in partition (isUnifiable (typeMap e) (counter e) sc . opType) $ opInfos l
checkUnusedTypevars :: TypeScheme -> State Env TypeScheme
checkUnusedTypevars sc@(TypeScheme tArgs t ps) = do
let ls = map snd $ leaves (< 0) t -- generic vars
if null rest then return sc
addDiags [mkDiag Warning "unused type variables" rest]
return $ TypeScheme ls t ps
-- | storing an operation
addOpId :: UninstOpId -> TypeScheme -> [OpAttr] -> OpDefn
-> State Env (Maybe UninstOpId)
addOpId i oldSc attrs defn =
do sc <- checkUnusedTypevars oldSc
ds = if placeCount i > 1 then case unalias ty of
FunType arg _ _ _ -> case unalias arg of
ProductType ts _ -> if placeCount i /= length ts then
[mkDiag Error "wrong number of places in" i]
_ -> [mkDiag Error "expected tuple argument for" i]
_ -> [mkDiag Error "expected function type for" i]
(l, r) = partitionOpId e i sc
oInfo = OpInfo sc attrs defn
do let Result es mo = foldM (mergeOpInfo tm) oInfo l
addDiags $ map (improveDiag i) es
if i `elem` map fst bList then addDiags $ [mkDiag Error
"illegal overloading of predefined identifier" i]
Nothing -> return Nothing
----------------------------------------------------------------------------
-----------------------------------------------------------------------------
addGenVarDecl :: GenVarDecl -> State Env (Maybe GenVarDecl)
addGenVarDecl(GenVarDecl v) = do mv <- addVarDecl v
return $ fmap GenVarDecl mv
addGenVarDecl(GenTypeVarDecl t) = do mt <- addTypeVarDecl True t
return $ fmap GenTypeVarDecl mt
anaGenVarDecl :: GenVarDecl -> State Env (Maybe GenVarDecl)
anaGenVarDecl(GenVarDecl v) = optAnaVarDecl v
anaGenVarDecl(GenTypeVarDecl t) =
anaTypeVarDecl t >>= (return . fmap GenTypeVarDecl)
convertTypeToKind :: Type -> State Env (Maybe Kind)
convertTypeToKind (FunType t1 FunArr t2 ps) =
do mk1 <- convertTypeToKind t1
mk2 <- convertTypeToKind t2
(Just k1, Just k2) -> case k2 of
ExtKind _ _ _ -> return Nothing
_ -> return $ Just $ FunKind k1 k2 ps
convertTypeToKind (BracketType Parens [] _) =
convertTypeToKind (BracketType Parens [t] _) =
convertTypeToKind (BracketType Parens ts ps) =
do cs <- mapM convertTypeToKind ts
do let k:ks = catMaybes cs
if all ((==rk) . rawKind) ks then
return $ Just $ Intersection (k:ks) ps
convertTypeToKind (MixfixType [t1, TypeToken t]) =
Nothing -> do return Nothing
mk1 <- convertTypeToKind t1
Just k1 -> return $ Just $ ExtKind k1 v $ tokPos t
convertTypeToKind(TypeToken t) =
if tokStr t == "Type" then return $ Just $ Intersection [] $ tokPos t
let rm = anaClassId ci cm
Nothing -> return Nothing
Just k -> return $ Just $ ClassKind ci k
optAnaVarDecl :: VarDecl -> State Env (Maybe GenVarDecl)
optAnaVarDecl vd@(VarDecl v t s q) =
let varDecl = do mvd <- anaVarDecl vd
Nothing -> return Nothing
Just nvd -> do mmvd <- addVarDecl $ makeMonomorph nvd
return $ fmap GenVarDecl mmvd
do mk <- convertTypeToKind t
Just k -> do addDiags [mkDiag Hint "is type variable" v]
tv <- anaTypeVarDecl $ TypeArg v k s q
return $ fmap GenTypeVarDecl tv
makeMonomorph :: VarDecl -> VarDecl
makeMonomorph (VarDecl v t sk ps) = VarDecl v (monoType t) sk ps
map ( \ (v, TypeArg i k _ _) ->
(v, TypeName i k 0)) $ leaves (> 0) t) t
anaVarDecl :: VarDecl -> State Env (Maybe VarDecl)
anaVarDecl(VarDecl v oldT sk ps) =
do mt <- anaStarType oldT
Just t -> Just $ VarDecl v t sk ps
-- | add a local variable with an analysed type
addVarDecl :: VarDecl -> State Env (Maybe VarDecl)
addVarDecl vd@(VarDecl v t _ _) =
do newV <- addOpId v (simpleTypeScheme t) [] VarDefn
return $ fmap (const vd) newV
getVar(VarDecl v _ _ _) = v
-- | check uniqueness of variables
checkUniqueVars :: [VarDecl] -> State Env ()
checkUniqueVars = addDiags . checkUniqueness . map getVar
-- | filter out assumption
filterAssumps :: (OpInfo -> Bool) -> Assumps -> Assumps
Map.map (OpInfos . filter p . opInfos)
-- | analyse types in typed patterns, and
-- create fresh type vars for unknown ids tagged with type MixfixType [].
anaPattern :: Pattern -> State Env Pattern
QualVar vd -> do newVd <- checkVarDecl vd
ResolvedMixTerm i pats ps -> do
l <- mapM anaPattern pats
return $ ResolvedMixTerm i l ps
return $ ApplTerm p3 p4 ps
l <- mapM anaPattern pats
TypedTerm p q ty ps -> do
let newT = case mt of Just t -> t
QualVar (VarDecl v (MixfixType []) ok qs) ->
let newVd = VarDecl v newT ok (qs ++ ps) in
_ -> do newP <- anaPattern p
return $ TypedTerm newP q newT ps
return $ AsPattern newVd p4 ps
where checkVarDecl vd@(VarDecl v t ok ps) = case t of
(tvar, c) <- toEnvState $ freshVar $ posOfId v
return $ VarDecl v (TypeName tvar star c) ok ps
_ -> do mt <- anaStarType t
Just ty -> return $ VarDecl v ty ok ps