addClassDecl :: RawKind -> Kind -> Id -> State Env ()
-- check with merge
addClassDecl rk kind ci =
    if ci == universeId then
       addDiags [mkDiag Warning "void universe class declaration" ci]
    else do
       e <- get
       let cm = classMap e
           tm = typeMap e
           tvs = localTypeVars e
       case Map.lookup ci tm of
         Just _ -> addDiags [mkDiag Error "class name already a type" ci]
         Nothing -> case Map.lookup ci tvs of
             Just _ -> addDiags
                 [mkDiag Error "class name already a type variable" ci]
             Nothing -> case Map.lookup ci cm of
                 Nothing -> do
                   addSymbol $ idToClassSymbol ci rk
                   putClassMap $ Map.insert ci
                     (ClassInfo rk $ Set.singleton kind) cm
                 Just (ClassInfo ork superClasses) ->
                   let Result ds mk = minRawKind (showDoc ci "") rk ork
                   in case mk of
                   Nothing -> addDiags ds
                   Just nk ->
                     if cyclicClassId cm ci kind then
                        addDiags [mkDiag Error "cyclic class" ci]
                     else do
                       addSymbol $ idToClassSymbol ci nk
                       if newKind cm kind superClasses then do
                         addDiags [mkDiag Warning "refined class" ci]
                         putClassMap $ Map.insert ci
                           (ClassInfo nk $ addNewKind cm kind superClasses) cm
                        else addDiags [mkDiag Warning "unchanged class" ci]
addClassDecl :: RawKind -> Kind -> Id -> State Env ()
addClassDecl rk kind ci =
    if ci == universeId then
       addDiags [mkDiag Warning "void universe class declaration" ci]
    else do
       e <- get
       let cm = classMap e
           tm = typeMap e
           tvs = localTypeVars e
       case Map.lookup ci tm of
         Just _ -> addDiags [mkDiag Error "class name already a type" ci]
         Nothing -> case Map.lookup ci tvs of
             Just _ -> addDiags
                 [mkDiag Error "class name already a type variable" ci]
             Nothing -> case Map.lookup ci cm of
                 Nothing -> do
                   addSymbol $ idToClassSymbol ci rk
                   putClassMap $ Map.insert ci
                     (ClassInfo rk $ Set.singleton kind) cm
                 Just (ClassInfo ork superClasses) ->
                   let Result ds mk = minRawKind (showDoc ci "") rk ork
                   in case mk of
                   Nothing -> addDiags ds
                   Just nk ->
                     if cyclicClassId cm ci kind then
                        addDiags [mkDiag Error "cyclic class" ci]
                     else do
                       addSymbol $ idToClassSymbol ci nk
                       if newKind cm kind superClasses then do
                         addDiags [mkDiag Warning "refined class" ci]
                         putClassMap $ Map.insert ci
                           (ClassInfo nk $ addNewKind cm kind superClasses) cm
                        else addDiags [mkDiag Warning "unchanged class" ci]
addClassDecl rk kind ci =
    if ci == universeId then
       addDiags [mkDiag Warning "void universe class declaration" ci]
    else do
       e <- get
       let cm = classMap e
           tm = typeMap e
           tvs = localTypeVars e
       case Map.lookup ci tm of
         Just _ -> addDiags [mkDiag Error "class name already a type" ci]
         Nothing -> case Map.lookup ci tvs of
             Just _ -> addDiags
                 [mkDiag Error "class name already a type variable" ci]
             Nothing -> case Map.lookup ci cm of
                 Nothing -> do
                   addSymbol $ idToClassSymbol ci rk
                   putClassMap $ Map.insert ci
                     (ClassInfo rk $ Set.singleton kind) cm
                 Just (ClassInfo ork superClasses) ->
                   let Result ds mk = minRawKind (showDoc ci "") rk ork
                   in case mk of
                   Nothing -> addDiags ds
                   Just nk ->
                     if cyclicClassId cm ci kind then
                        addDiags [mkDiag Error "cyclic class" ci]
                     else do
                       addSymbol $ idToClassSymbol ci nk
                       if newKind cm kind superClasses then do
                         addDiags [mkDiag Warning "refined class" ci]
                         putClassMap $ Map.insert ci
                           (ClassInfo nk $ addNewKind cm kind superClasses) cm
                        else addDiags [mkDiag Warning "unchanged class" ci]