@@ -5,11 +5,12 @@ import qualified ProjectM36.TypeConstructorDef as TCD
55import qualified ProjectM36.TypeConstructor as TC
66import qualified ProjectM36.DataConstructorDef as DCD
77import ProjectM36.Error
8−import ProjectM36.Attribute
8+import qualified ProjectM36.Attribute as A
99import qualified Data.Vector as V
1010import qualified Data.Set as S
1111import qualified Data.List as L
1212import Data.Maybe (isJust)
13+import Data.Either (rights)
1314import Control.Monad.Writer
1415import qualified Data.Map as M
1516--import Debug.Trace
@@ -205,7 +206,7 @@ resolveTypeInAtom _ atom = Right atom
205206-- 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.
206207resolveTypesInTuple :: Attributes -> RelationTuple -> Either RelationalError RelationTuple
207208resolveTypesInTuple 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)))
209210 Right (RelationTuple resolvedAttrs (V.fromList newAtoms))
210211
211212-- | Validate that the type is provided with complete type variables for type constructors.
@@ -225,4 +226,32 @@ validateAtomType typ@(ConstructedAtomType tConsName tVarMap) tConss = do
225226validateAtomType _ _ = Right ()
226227
227228validateTuple :: 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
230+
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)
240+ else
241+ Right x
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
247+ else
248+ atomTypeVerify (A.atomType attr1) (A.atomType attr2)) $ V.toList (V.zip attrs1 attrs2)
249+ return x
250+atomTypeVerify x y = if x == y then
251+ Right x
252+ else
253+ Left $ AtomTypeMismatchError x y
254+
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