@@ -5,11 +5,12 @@ import qualified ProjectM36.TypeConstructorDef as TCD
5import qualified ProjectM36.TypeConstructor as TC
5import qualified ProjectM36.TypeConstructor as TC
6import qualified ProjectM36.DataConstructorDef as DCD
6import qualified ProjectM36.DataConstructorDef as DCD
7import ProjectM36.Error
7import ProjectM36.Error
8−import ProjectM36.Attribute
8+import qualified ProjectM36.Attribute as A
9import qualified Data.Vector as V
9import qualified Data.Vector as V
10import qualified Data.Set as S
10import qualified Data.Set as S
11import qualified Data.List as L
11import qualified Data.List as L
12import Data.Maybe (isJust)
12import Data.Maybe (isJust)
13+import Data.Either (rights)
13import Control.Monad.Writer
14import Control.Monad.Writer
14import qualified Data.Map as M
15import qualified Data.Map as M
15--import Debug.Trace
16--import Debug.Trace
@@ -205,7 +206,7 @@ resolveTypeInAtom _ atom = Right atom
205-- Example: "Nothing" does not specify the the argument in "Maybe a", so allow delayed resolution in the tuple before it is added to the relation. Note that this resolution could cause a type error. Hardly a Hindley-Milner system.
206-- Example: "Nothing" does not specify the the argument in "Maybe a", so allow delayed resolution in the tuple before it is added to the relation. Note that this resolution could cause a type error. Hardly a Hindley-Milner system.
206resolveTypesInTuple :: Attributes -> RelationTuple -> Either RelationalError RelationTuple
207resolveTypesInTuple :: Attributes -> RelationTuple -> Either RelationalError RelationTuple
207resolveTypesInTuple resolvedAttrs (RelationTuple _ tupAtoms) = do
208resolveTypesInTuple resolvedAttrs (RelationTuple _ tupAtoms) = do
208− newAtoms <- mapM (\(atom, resolvedType) -> resolveTypeInAtom resolvedType atom) (zip (V.toList tupAtoms) $ (map atomType (V.toList resolvedAttrs)))
209+ newAtoms <- mapM (\(atom, resolvedType) -> resolveTypeInAtom resolvedType atom) (zip (V.toList tupAtoms) $ (map A.atomType (V.toList resolvedAttrs)))
209 Right (RelationTuple resolvedAttrs (V.fromList newAtoms))
210 Right (RelationTuple resolvedAttrs (V.fromList newAtoms))
211-- | Validate that the type is provided with complete type variables for type constructors.
212-- | Validate that the type is provided with complete type variables for type constructors.
@@ -225,4 +226,32 @@ validateAtomType typ@(ConstructedAtomType tConsName tVarMap) tConss = do
225validateAtomType _ _ = Right ()
226validateAtomType _ _ = Right ()
227validateTuple :: RelationTuple -> TypeConstructorMapping -> Either RelationalError ()
228validateTuple :: RelationTuple -> TypeConstructorMapping -> Either RelationalError ()
228−validateTuple (RelationTuple _ atoms) tConss = mapM_ (\a -> validateAtomType (atomTypeForAtom a) tConss) atoms
229+validateTuple (RelationTuple _ atoms) tConss = mapM_ (\a -> validateAtomType (atomTypeForAtom a) tConss) atoms
231+-- | Determine if two types are equal or compatible (including special handling for AnyAtomType).
232+atomTypeVerify :: AtomType -> AtomType -> Either RelationalError AtomType
233+atomTypeVerify AnyAtomType x = Right x
234+atomTypeVerify x AnyAtomType = Right x
235+atomTypeVerify x@(ConstructedAtomType tConsNameA tVarMapA) (ConstructedAtomType tConsNameB tVarMapB) =
236+ if tConsNameA /= tConsNameB then
237+ Left (TypeConstructorNameMismatch tConsNameA tConsNameB)
238+ else if not (typeVarMapsVerify tVarMapA tVarMapB) then
239+ Left (TypeConstructorTypeVarsTypesMismatch tConsNameA tVarMapA tVarMapB)
242+atomTypeVerify x@(RelationAtomType attrs1) y@(RelationAtomType attrs2) = do
243+ _ <- mapM (\(attr1,attr2) -> let name1 = A.attributeName attr1
244+ name2 = A.attributeName attr2 in
245+ if notElem "_" [name1, name2] && name1 /= name2 then
246+ Left $ AtomTypeMismatchError x y
248+ atomTypeVerify (A.atomType attr1) (A.atomType attr2)) $ V.toList (V.zip attrs1 attrs2)
250+atomTypeVerify x y = if x == y then
253+ Left $ AtomTypeMismatchError x y
255+-- | Determine if two typeVar
256+typeVarMapsVerify :: TypeVarMap -> TypeVarMap -> Bool
257+typeVarMapsVerify a b = M.keysSet a == M.keysSet b && (length . rights) (map (\((_,v1),(_,v2)) -> atomTypeVerify v1 v2) (zip (M.toAscList a) (M.toAscList b))) == M.size a