@@ -1,7 +1,6 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2module ProjectM36.AtomType where
2module ProjectM36.AtomType where
3import ProjectM36.Base
3import ProjectM36.Base
4−import ProjectM36.Relation
5import ProjectM36.DataTypes.Primitive
4import ProjectM36.DataTypes.Primitive
6import qualified ProjectM36.TypeConstructorDef as TCD
5import qualified ProjectM36.TypeConstructorDef as TCD
7import qualified ProjectM36.TypeConstructor as TC
6import qualified ProjectM36.TypeConstructor as TC
@@ -9,30 +8,14 @@ import qualified ProjectM36.DataConstructorDef as DCD
9import qualified Data.Text as T
8import qualified Data.Text as T
10import ProjectM36.Error
9import ProjectM36.Error
11import ProjectM36.Attribute
10import ProjectM36.Attribute
12−import ProjectM36.Atom
13import qualified Data.Vector as V
11import qualified Data.Vector as V
14import qualified Data.Set as S
12import qualified Data.Set as S
15import qualified Data.List as L
13import qualified Data.List as L
16import Data.Maybe (isJust)
14import Data.Maybe (isJust)
17import Control.Monad.Writer
15import Control.Monad.Writer
18import qualified Data.Map as M
16import qualified Data.Map as M
19−--import Debug.Trace
17+import Debug.Trace
21−typesAsRelation :: TypeConstructorMapping -> Either RelationalError Relation
22−typesAsRelation types = mkRelationFromTuples attrs tuples
24− attrs = attributesFromList [Attribute "TypeConstructor" textAtomType,
25− Attribute "DataConstructors" dConsType]
26− subAttrs = attributesFromList [Attribute "DataConstructor" textAtomType]
27− dConsType = RelationAtomType subAttrs
28− tuples = map mkTypeConsDescription types
30− mkTypeConsDescription (tCons, dConsList) = RelationTuple attrs (V.fromList [textAtom (TCD.name tCons), mkDataConsRelation dConsList])
32− mkDataConsRelation dConsList = case mkRelationFromTuples subAttrs $ map (\dCons -> RelationTuple subAttrs (V.singleton $ textAtom $ T.intercalate " " ((DCD.name dCons):(map (T.pack . show) (DCD.fields dCons))))) dConsList of
33− Left err -> error ("mkRelationFromTuples pooped " ++ show err)
34− Right rel -> Atom rel
36findDataConstructor :: DataConstructorName -> TypeConstructorMapping -> Maybe (TypeConstructorDef, DataConstructorDef)
19findDataConstructor :: DataConstructorName -> TypeConstructorMapping -> Maybe (TypeConstructorDef, DataConstructorDef)
37findDataConstructor dName tConsList = foldr tConsFolder Nothing tConsList
20findDataConstructor dName tConsList = foldr tConsFolder Nothing tConsList
@@ -89,6 +72,7 @@ atomTypeForDataConstructor tConss dConsName atomArgTypes = do
89 Just (tCons, dCons) -> do
72 Just (tCons, dCons) -> do
90 --validate that the type constructor arguments are fulfilled in the data constructor
73 --validate that the type constructor arguments are fulfilled in the data constructor
91 typeVars <- resolveDataConstructorTypeVars dCons atomArgTypes tConss
74 typeVars <- resolveDataConstructorTypeVars dCons atomArgTypes tConss
92 pure (ConstructedAtomType (TCD.name tCons) typeVars)
76 pure (ConstructedAtomType (TCD.name tCons) typeVars)
94-- | Walks the data and type constructors to extract the type variable map.
78-- | Walks the data and type constructors to extract the type variable map.
@@ -96,6 +80,9 @@ resolveDataConstructorTypeVars :: DataConstructorDef -> [AtomType] -> TypeConstr
96resolveDataConstructorTypeVars dCons aTypeArgs tConss = do
80resolveDataConstructorTypeVars dCons aTypeArgs tConss = do
97 maps <- mapM (\(dCons',aTypeArg) -> resolveDataConstructorArgTypeVars dCons' aTypeArg tConss) (zip (DCD.fields dCons) aTypeArgs)
81 maps <- mapM (\(dCons',aTypeArg) -> resolveDataConstructorArgTypeVars dCons' aTypeArg tConss) (zip (DCD.fields dCons) aTypeArgs)
98 --if any two maps have the same key and different values- bail!
82 --if any two maps have the same key and different values- bail!
84+ foldr typeVarMapFolder (Right M.empty) maps
85+ --if the data constructor cannot complete a type constructor variables (ex. "Nothing" could be Maybe Int or Maybe Text, etc.), then fill that space with AnyAtomType which is resolved when the relation is constructed- the relation must contain all resolved atom types.
99 pure (M.unions maps)
86 pure (M.unions maps)
101-- | Attempt to match the data constructor argument to a type constructor type variable.
88-- | Attempt to match the data constructor argument to a type constructor type variable.
@@ -147,6 +134,7 @@ dupes (x:y:xs) = dupes(x:[y]) ++ dupes(xs)
147-- | Create an atom type iff all type variables are provided.
134-- | Create an atom type iff all type variables are provided.
148-- Either Int Text -> ConstructedAtomType "Either" {Int , Text}
135-- Either Int Text -> ConstructedAtomType "Either" {Int , Text}
149atomTypeForTypeConstructor :: TypeConstructor -> TypeConstructorMapping -> Either RelationalError AtomType
136atomTypeForTypeConstructor :: TypeConstructor -> TypeConstructorMapping -> Either RelationalError AtomType
137+atomTypeForTypeConstructor (PrimitiveTypeConstructor _ aType) _ = Right aType
150atomTypeForTypeConstructor tCons tConss = case findTypeConstructor (TC.name tCons) tConss of
138atomTypeForTypeConstructor tCons tConss = case findTypeConstructor (TC.name tCons) tConss of
151 Nothing -> Left (NoSuchTypeConstructorError (TC.name tCons))
139 Nothing -> Left (NoSuchTypeConstructorError (TC.name tCons))
152 Just (tConsDef, _) -> do
140 Just (tConsDef, _) -> do
@@ -166,4 +154,44 @@ findTypeConstructor name tConsList = foldr tConsFolder Nothing tConsList
166 Just (tCons, dConsList)
154 Just (tCons, dConsList)
158+resolveAtomType :: AtomType -> AtomType -> Either RelationalError AtomType
159+resolveAtomType orig@(ConstructedAtomType dConsName resolvedTypeVarMap) (ConstructedAtomType _ unresolvedTypeVarMap) = do
160+ _ <- resolveAtomTypesInTypeVarMap resolvedTypeVarMap unresolvedTypeVarMap
162+resolveAtomType typeFromRelation unresolvedType = if typeFromRelation == unresolvedType then
163+ Right typeFromRelation
165+ Left (AtomTypeMismatchError typeFromRelation unresolvedType)
167+-- this could be optimized to reduce new tuple creation- if anyatomtype does not appear, just return the original typevarmap
168+resolveAtomTypesInTypeVarMap :: TypeVarMap -> TypeVarMap -> Either RelationalError TypeVarMap
169+resolveAtomTypesInTypeVarMap resolvedTypeMap unresolvedTypeMap = do
170+ let lookup key tMap = case M.lookup key tMap of
171+ Nothing -> Left (TypeConstructorTypeVarMissing key)
172+ Just val -> Right val
173+ let resolveTypePair unresKey AnyAtomType = do
174+ resType <- lookup unresKey resolvedTypeMap
175+ pure (unresKey, resType)
176+ resolveTypePair unresKey subType@(ConstructedAtomType _ _) = do --recurse
177+ resType <- lookup unresKey resolvedTypeMap
178+ resAType <- resolveAtomType resType subType
179+ pure (unresKey, resAType)
180+ resolveTypePair unresKey unresV = pure (unresKey, unresV)
181+ mapM_ (uncurry resolveTypePair) (M.toList unresolvedTypeMap)
182+ pure resolvedTypeMap
184+-- | See notes at `resolveTypesInTuple`. The typeFromRelation must not include any wildcards.
185+resolveTypeInAtom :: AtomType -> Atom -> Either RelationalError Atom
186+resolveTypeInAtom typeFromRelation atomIn@(ConstructedAtom dConsName _ args) = do
187+ newType <- resolveAtomType typeFromRelation (atomTypeForAtom atomIn)
188+ pure (ConstructedAtom dConsName newType args)
189+resolveTypeInAtom _ atom = Right atom
191+-- | When creating a tuple, the data constructor may not complete the type constructor arguments, so the wildcard "AnyAtomType" fills in the type constructor's argument. The tuple type must be resolved before it can be part of a relation, however.
192+-- 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.
193+resolveTypesInTuple :: Attributes -> RelationTuple -> Either RelationalError RelationTuple
194+resolveTypesInTuple resolvedAttrs (RelationTuple _ tupAtoms) = do
195+ newAtoms <- mapM (\(atom, resolvedType) -> resolveTypeInAtom resolvedType atom) (zip (V.toList tupAtoms) (map atomType (V.toList resolvedAttrs)))
196+ Right (RelationTuple resolvedAttrs (V.fromList newAtoms))