on master help sign in
merge with agentM's branch about specializing Interval.
commita330746a8e94ab4da539db45ce0415b022462fae authorJohnny Liao <dycan0716@gmail.com> dateSun 3 Jun 2018, 12:11 (8 years ago) parent890fb961a70d58
13 files changed+143−136
src/bin/ProjectM36/Server/RemoteCallTypes/Json.hs−15 src/lib/ProjectM36/Arbitrary.hs+27−16 src/lib/ProjectM36/Atom.hs+11−9 src/lib/ProjectM36/AtomType.hs+18−17 src/lib/ProjectM36/Base.hs−7 src/lib/ProjectM36/DataTypes/Basic.hs−2 src/lib/ProjectM36/DataTypes/Interval.hs+45−23 src/lib/ProjectM36/DataTypes/Primitive.hs−1 src/lib/ProjectM36/Relation/Parse/CSV.hs+37−33 src/lib/ProjectM36/RelationalExpression.hs+2−2 test/Relation/Export/CSV.hs+1−1 test/TutorialD/Interpreter.hs+2−1 test/TutorialD/Interpreter/DatabaseContextFunctionScript.hs−9
src/bin/ProjectM36/Server/RemoteCallTypes/Json.hs−15
@@ -80,15 +80,6 @@ instance ToJSON Atom where
8080 "val" .= decodeUtf8 (B64.encode i) ]
8181 toJSON atom@(BoolAtom i) = object [ "type" .= atomTypeForAtom atom,
8282 "val" .= i ]
83−
84− toJSON atom@(IntervalAtom b e i1 i2) = object [ "type" .= atomTypeForAtom atom,
85− "val" .= object [
86− "begin" .= toJSON b,
87− "end" .= toJSON e,
88− "beginopen" .= i1,
89− "endopen" .= i2
90− ]
91− ]
9283 toJSON atom@(RelationAtom i) = object [ "type" .= atomTypeForAtom atom,
9384 "val" .= i ]
9485 toJSON (ConstructedAtom dConsName atomtype atomlist) = object [
@@ -118,12 +109,6 @@ instance FromJSON Atom where
118109 Left err -> fail ("Failed to parse base64-encoded ByteString: " ++ err)
119110 Right bs -> pure (ByteStringAtom bs)
120111 BoolAtomType -> BoolAtom <$> o .: "val"
121− IntervalAtomType _ -> IntervalAtom <$>
122− ((o .: "val") >>= (.: "begin")) <*>
123− ((o .: "val") >>= (.: "end")) <*>
124− ((o .: "val") >>= (.: "beginopen")) <*>
125− ((o .: "val") >>= (.: "endopen"))
126−
127112
128113instance ToJSON Notification
129114instance FromJSON Notification
src/lib/ProjectM36/Arbitrary.hs+27−16
@@ -4,16 +4,18 @@
44module ProjectM36.Arbitrary where
55import ProjectM36.Base
66import ProjectM36.Error
7+import ProjectM36.AtomFunctionError
78import ProjectM36.AtomType
89import ProjectM36.Attribute (atomType,attributeName)
910import ProjectM36.DataConstructorDef as DCD
11+import ProjectM36.DataTypes.Interval
1012import qualified Data.Vector as V
1113import Data.Text (Text,pack)
1214import Test.QuickCheck
1315import qualified Data.ByteString.Char8 as B
1416import Data.Time
1517import Control.Monad.Reader
16−
18+import Debug.Trace
1719arbitrary' :: AtomType -> WithTCMap Gen (Either RelationalError Atom)
1820arbitrary' IntegerAtomType =
1921 Right . IntegerAtom <$> lift (arbitrary :: Gen Integer)
@@ -45,23 +47,14 @@ arbitrary' ByteStringAtomType =
4547
4648arbitrary' BoolAtomType =
4749 Right . BoolAtom <$> lift (arbitrary :: Gen Bool)
48−
49−arbitrary' (IntervalAtomType atomTy) = do
50− tcMap <- ask
51− eitherAtomTypeA <- lift $ runReaderT (arbitrary' atomTy) tcMap
52− eitherAtomTypeB <- lift $ runReaderT (arbitrary' atomTy) tcMap
53− case (eitherAtomTypeA,eitherAtomTypeB) of
54− (Right a, Right b) -> do
55− l <- lift $ (arbitrary :: Gen Bool)
56− r <- lift $ (arbitrary :: Gen Bool)
57− pure $ Right $ IntervalAtom a b l r
58− (Left err,_) -> pure $ Left err
59− (Right _, Left err) -> pure $ Left err
60−
61−arbitrary' constructedAtomType@(ConstructedAtomType tcName tvMap) = do
50+arbitrary' constructedAtomType@(ConstructedAtomType tcName tvMap)
51+ | traceShow constructedAtomType False = undefined
52+ --special-casing for Interval type
53+ | isIntervalAtomType constructedAtomType = createArbitraryInterval (intervalSubType constructedAtomType)
54+ | otherwise = do
6255 tcMap <- ask
6356 let maybeTCons = findTypeConstructor tcName tcMap
64− let eitherTCons = maybeToRight (NoSuchTypeConstructorName tcName) maybeTCons
57+ let eitherTCons = traceShowId $ maybeToRight (NoSuchTypeConstructorName tcName) maybeTCons
6558 let eitherDCDefs = snd <$> eitherTCons
6659 let eitherGenDCDef = elements <$> eitherDCDefs
6760 case eitherGenDCDef of
@@ -121,3 +114,21 @@ arbitraryRelation attris range = do
121114 Right tupleList -> pure $ Right $ Relation attris $ RelationTupleSet tupleList
122115
123116type WithTCMap a = ReaderT TypeConstructorMapping a
117+
118+createArbitraryInterval :: AtomType -> WithTCMap Gen (Either RelationalError Atom)
119+createArbitraryInterval subType = if supportsInterval subType then do
120+ eBegin <- arbitrary' subType
121+ eEnd <- arbitrary' subType
122+ beginopen <- lift (arbitrary :: Gen Bool)
123+ endopen <- lift (arbitrary :: Gen Bool)
124+ case eBegin of
125+ Left err -> pure (Left err)
126+ Right begin ->
127+ case eEnd of
128+ Left err -> pure (Left err)
129+ Right end ->
130+ case createInterval begin end beginopen endopen of
131+ Left _ -> createArbitraryInterval subType
132+ Right val -> pure (Right val)
133+ else
134+ pure $ Left (ProjectM36.Error.AtomFunctionUserError (AtomTypeDoesNotSupportIntervalError (prettyAtomType subType)))
src/lib/ProjectM36/Atom.hs+11−9
@@ -1,10 +1,8 @@
11module ProjectM36.Atom where
22import ProjectM36.Base
33import ProjectM36.Error
4+import ProjectM36.DataTypes.Interval
45import qualified Data.Text as T
5−--import Data.Time.Calendar
6−--import Data.Time.Clock
7−--import Data.ByteString (ByteString)
86import Data.Monoid
97
108relationForAtom :: Atom -> Either RelationalError Relation
@@ -20,14 +18,18 @@ atomToText (DayAtom i) = (T.pack . show) i
2018atomToText (DateTimeAtom i) = (T.pack . show) i
2119atomToText (ByteStringAtom i) = (T.pack . show) i
2220atomToText (BoolAtom i) = (T.pack . show) i
23−atomToText (IntervalAtom b e bo be) = beginp <> begin <> "," <> end <> endp
24− where beginp = if bo then "(" else "["
25− begin = atomToText b
26− end = atomToText e
27− endp = if be then ")" else "]"
2821
2922atomToText (RelationAtom i) = (T.pack . show) i
30−atomToText (ConstructedAtom dConsName _ atoms) = dConsName <> dConsArgs
23+atomToText (ConstructedAtom dConsName typ atoms)
24+ | isIntervalAtomType typ = case atoms of --special handling for printing intervals
25+ (b:e:(BoolAtom bo):(BoolAtom be):[]) ->
26+ let beginp = if bo then "(" else "["
27+ begin = atomToText b
28+ end = atomToText e
29+ endp = if be then ")" else "]" in
30+ beginp <> begin <> "," <> end <> endp
31+ _ -> "invalid interval"
32+ | otherwise = dConsName <> dConsArgs
3133 where
3234 parensAtomToText a@(ConstructedAtom _ _ []) = atomToText a
3335 parensAtomToText a@ConstructedAtom{} = "(" <> atomToText a <> ")"
src/lib/ProjectM36/AtomType.hs+18−17
@@ -105,9 +105,10 @@ resolveTypeConstructorTypeVars (ADTypeConstructor tConsName _) (ConstructedAtomT
105105 Right pVarMap'
106106 else
107107 Left (TypeConstructorTypeVarsMismatch expectedPVarNames (M.keysSet pVarMap'))
108−resolveTypeConstructorTypeVars (TypeVariable tvName) typ _ = Right (M.singleton tvName typ)
108+resolveTypeConstructorTypeVars (TypeVariable tvName) typ _ = case typ of
109+ TypeVariableType nam -> Left (TypeConstructorTypeVarMissing nam)
110+ _ -> Right (M.singleton tvName typ)
109111resolveTypeConstructorTypeVars (ADTypeConstructor tConsName []) typ tConss = case findTypeConstructor tConsName tConss of
110− --resolve ADT constructor to primitive type, if necessary
111112 Just (PrimitiveTypeConstructorDef _ _, _) -> Right M.empty
112113 _ -> Left (TypeConstructorAtomTypeMismatch tConsName typ)
113114
@@ -138,32 +139,36 @@ validateTypeConstructorDef tConsDef dConsList = execWriter $ do
138139 pure ()
139140
140141
142+atomTypeForTypeConstructor :: TypeConstructor -> TypeConstructorMapping -> TypeVarMap -> Either RelationalError AtomType
143+atomTypeForTypeConstructor = atomTypeForTypeConstructorValidate False
144+
141145-- | Create an atom type iff all type variables are provided.
142146-- Either Int Text -> ConstructedAtomType "Either" {Int , Text}
143−atomTypeForTypeConstructor :: TypeConstructor -> TypeConstructorMapping -> TypeVarMap -> Either RelationalError AtomType
144−atomTypeForTypeConstructor (PrimitiveTypeConstructor _ aType) _ _ = Right aType
145−atomTypeForTypeConstructor (TypeVariable tvname) _ tvMap = case M.lookup tvname tvMap of
146− Nothing -> Right (TypeVariableType tvname)
147+atomTypeForTypeConstructorValidate :: Bool -> TypeConstructor -> TypeConstructorMapping -> TypeVarMap -> Either RelationalError AtomType
148+atomTypeForTypeConstructorValidate _ (PrimitiveTypeConstructor _ aType) _ _ = Right aType
149+atomTypeForTypeConstructorValidate validate (TypeVariable tvname) _ tvMap = case M.lookup tvname tvMap of
150+ Nothing -> if validate then
151+ Left (TypeConstructorTypeVarMissing tvname)
152+ else
153+ pure (TypeVariableType tvname)
147154 Just typ -> Right typ
148−atomTypeForTypeConstructor (RelationAtomTypeConstructor attrExprs) tConsMap tvMap = do
155+atomTypeForTypeConstructorValidate _ (RelationAtomTypeConstructor attrExprs) tConsMap tvMap = do
149156 resolvedAtomTypes <- mapM (\expr -> atomTypeForAttributeExpr expr tConsMap tvMap) attrExprs
150157 let attrs = zipWith Attribute (map AE.attributeName attrExprs) resolvedAtomTypes
151158 pure (RelationAtomType (A.attributesFromList attrs))
152−atomTypeForTypeConstructor tCons tConss tvMap = case findTypeConstructor (TC.name tCons) tConss of
159+atomTypeForTypeConstructorValidate val tCons tConss tvMap = case findTypeConstructor (TC.name tCons) tConss of
153160 Nothing -> Left (NoSuchTypeConstructorError (TC.name tCons))
154161 Just (PrimitiveTypeConstructorDef _ aType, _) -> Right aType
155162 Just (tConsDef, _) -> do
156− tConsArgTypes <- mapM (\tConsArg -> atomTypeForTypeConstructor tConsArg tConss tvMap) (TC.arguments tCons)
163+ tConsArgTypes <- mapM (\tConsArg -> atomTypeForTypeConstructorValidate val tConsArg tConss tvMap) (TC.arguments tCons)
157164 let pVarNames = TCD.typeVars tConsDef
158165 tConsArgs = M.fromList (zip pVarNames tConsArgTypes)
159− case TC.name tCons of
160− "Interval" -> Right (IntervalAtomType (head tConsArgTypes))
161− _ -> Right (ConstructedAtomType (TC.name tCons) tConsArgs)
166+ Right (ConstructedAtomType (TC.name tCons) tConsArgs)
162167
163168
164169atomTypeForAttributeExpr :: AttributeExprBase a -> TypeConstructorMapping -> TypeVarMap -> Either RelationalError AtomType
165170atomTypeForAttributeExpr (NakedAttributeExpr attr) _ _ = pure (A.atomType attr)
166−atomTypeForAttributeExpr (AttributeAndTypeNameExpr _ tCons _) tConsMap tvMap = atomTypeForTypeConstructor tCons tConsMap tvMap
171+atomTypeForAttributeExpr (AttributeAndTypeNameExpr _ tCons _) tConsMap tvMap = atomTypeForTypeConstructorValidate True tCons tConsMap tvMap
167172
168173--reconcile the atom-in types with the type constructors
169174isValidAtomTypeForTypeConstructor :: AtomType -> TypeConstructor -> TypeConstructorMapping -> Either RelationalError ()
@@ -276,7 +281,6 @@ atomTypeVerify x@(RelationAtomType attrs1) y@(RelationAtomType attrs2) = do
276281 else
277282 atomTypeVerify (A.atomType attr1) (A.atomType attr2)) $ V.toList (V.zip attrs1 attrs2)
278283 return x
279−atomTypeVerify (IntervalAtomType typA) (IntervalAtomType typB) = atomTypeVerify typA typB
280284atomTypeVerify x y = if x == y then
281285 Right x
282286 else
@@ -294,7 +298,6 @@ prettyAtomType (ConstructedAtomType tConsName typeVarMap) = tConsName `T.append`
294298 showTypeVars (tyVarName, aType) = " (" `T.append` tyVarName `T.append` "::" `T.append` prettyAtomType aType `T.append` ")"
295299-- it would be nice to have the original ordering, but we don't have access to the type constructor here- maybe the typevarmap should be also positional (ordered map?)
296300prettyAtomType (TypeVariableType x) = x
297−prettyAtomType (IntervalAtomType tv) = "Interval " <> prettyAtomType tv
298301prettyAtomType aType = T.take (T.length fullName - T.length "AtomType") fullName
299302 where fullName = (T.pack . show) aType
300303
@@ -319,7 +322,6 @@ resolveTypeVariables expectedArgTypes actualArgTypes = do
319322
320323resolveTypeVariable :: AtomType -> AtomType -> TypeVarMap
321324resolveTypeVariable (TypeVariableType tv) typ = M.singleton tv typ
322−resolveTypeVariable (IntervalAtomType ityp) typ = resolveTypeVariable ityp typ
323325resolveTypeVariable (ConstructedAtomType _ _) (ConstructedAtomType _ actualTvMap) = actualTvMap
324326resolveTypeVariable _ _ = M.empty
325327
@@ -330,7 +332,6 @@ resolveFunctionReturnValue funcName tvMap (ConstructedAtomType tCons retMap) = d
330332 pure (ConstructedAtomType tCons (M.intersection tvMap retMap))
331333 else
332334 Left (AtomFunctionTypeVariableResolutionError funcName (fst (head (M.toList diff))))
333−resolveFunctionReturnValue funcName tvMap (IntervalAtomType tv) = IntervalAtomType <$> resolveFunctionReturnValue funcName tvMap tv
334335resolveFunctionReturnValue funcName tvMap (TypeVariableType tvName) = case M.lookup tvName tvMap of
335336 Nothing -> Left (AtomFunctionTypeVariableResolutionError funcName tvName)
336337 Just typ -> pure typ
src/lib/ProjectM36/Base.hs−7
@@ -35,13 +35,10 @@ data Atom = IntegerAtom Integer |
3535 DateTimeAtom UTCTime |
3636 ByteStringAtom ByteString |
3737 BoolAtom Bool |
38− IntervalAtom Atom Atom OpenInterval OpenInterval |
3938 RelationAtom Relation |
4039 ConstructedAtom DataConstructorName AtomType [Atom]
4140 deriving (Eq, Show, Binary, Typeable, NFData, Generic)
4241
43−type OpenInterval = Bool
44−
4542instance Hashable Atom where
4643 hashWithSalt salt (ConstructedAtom dConsName _ atoms) = salt `hashWithSalt` atoms
4744 `hashWithSalt` dConsName --AtomType is not hashable
@@ -53,7 +50,6 @@ instance Hashable Atom where
5350 hashWithSalt salt (DateTimeAtom dt) = salt `hashWithSalt` dt
5451 hashWithSalt salt (ByteStringAtom bs) = salt `hashWithSalt` bs
5552 hashWithSalt salt (BoolAtom b) = salt `hashWithSalt` b
56− hashWithSalt salt (IntervalAtom a1 a2 bo be) = salt `hashWithSalt` a1 `hashWithSalt` a2 `hashWithSalt` bo `hashWithSalt` be
5753 hashWithSalt salt (RelationAtom r) = salt `hashWithSalt` r
5854
5955instance Binary UTCTime where
@@ -76,7 +72,6 @@ data AtomType = IntAtomType |
7672 DateTimeAtomType |
7773 ByteStringAtomType |
7874 BoolAtomType |
79− IntervalAtomType AtomType |
8075 RelationAtomType Attributes |
8176 ConstructedAtomType TypeConstructorName TypeVarMap |
8277 TypeVariableType TypeVarName
@@ -614,7 +609,6 @@ attrTypeVars (Attribute _ aType) = case aType of
614609 DateTimeAtomType -> S.empty
615610 ByteStringAtomType -> S.empty
616611 BoolAtomType -> S.empty
617− (IntervalAtomType atomtyp) -> atomTypeVars atomtyp
618612 (RelationAtomType attrs) -> S.unions (map attrTypeVars (V.toList attrs))
619613 (ConstructedAtomType _ tvMap) -> M.keysSet tvMap
620614 (TypeVariableType nam) -> S.singleton nam
@@ -638,7 +632,6 @@ atomTypeVars DayAtomType = S.empty
638632atomTypeVars DateTimeAtomType = S.empty
639633atomTypeVars ByteStringAtomType = S.empty
640634atomTypeVars BoolAtomType = S.empty
641−atomTypeVars (IntervalAtomType aType) = atomTypeVars aType
642635atomTypeVars (RelationAtomType attrs) = S.unions (map attrTypeVars (V.toList attrs))
643636atomTypeVars (ConstructedAtomType _ tvMap) = M.keysSet tvMap
644637atomTypeVars (TypeVariableType nam) = S.singleton nam
src/lib/ProjectM36/DataTypes/Basic.hs−2
@@ -1,8 +1,6 @@
11-- wraps up primitives plus other basic data types
22module ProjectM36.DataTypes.Basic where
33import ProjectM36.DataTypes.Primitive
4−import ProjectM36.DataTypes.Day
5−import ProjectM36.DataTypes.DateTime
64import ProjectM36.DataTypes.Either
75import ProjectM36.DataTypes.Maybe
86import ProjectM36.DataTypes.List
src/lib/ProjectM36/DataTypes/Interval.hs+45−23
@@ -6,7 +6,25 @@ import ProjectM36.AtomType
66import ProjectM36.DataTypes.Primitive
77import ProjectM36.AtomFunctionError
88import qualified Data.HashSet as HS
9+import qualified Data.Map as M
10+import Control.Monad (when)
911
12+type OpenInterval = Bool
13+
14+intervalSubType :: AtomType -> AtomType
15+intervalSubType typ = if isIntervalAtomType typ then
16+ case typ of
17+ ConstructedAtomType _ tvMap ->
18+ case M.lookup "a" tvMap of
19+ Nothing -> err
20+ Just typ' -> typ'
21+ _ -> err
22+ else
23+ err
24+ where
25+ err = error "intervalSubType on non-interval type"
26+
27+
1028-- in lieu of typeclass support, we just hard-code the types which can be part of an interval
1129supportsInterval :: AtomType -> Bool
1230supportsInterval typ = case typ of
@@ -18,7 +36,6 @@ supportsInterval typ = case typ of
1836 DateTimeAtomType -> True
1937 ByteStringAtomType -> False
2038 BoolAtomType -> False
21− IntervalAtomType _ -> False
2239 RelationAtomType _ -> False
2340 ConstructedAtomType _ _ -> False --once we support an interval-style typeclass, we might enable this
2441 TypeVariableType _ -> False
@@ -33,7 +50,6 @@ supportsOrdering typ = case typ of
3350 DateTimeAtomType -> True
3451 ByteStringAtomType -> False
3552 BoolAtomType -> False
36− IntervalAtomType _ -> False
3753 RelationAtomType _ -> False
3854 ConstructedAtomType _ _ -> False --once we support an interval-style typeclass, we might enable this
3955 TypeVariableType _ -> False
@@ -67,7 +83,11 @@ createInterval atom1 atom2 bopen eopen = do
6783 else
6884 Right valid
6985 LT -> Right valid
70− where valid = IntervalAtom atom1 atom2 bopen eopen
86+ where valid = ConstructedAtom "Interval" iType [atom1, atom2, BoolAtom bopen, BoolAtom eopen]
87+ iType = intervalAtomType (atomTypeForAtom atom1)
88+
89+intervalAtomType :: AtomType -> AtomType
90+intervalAtomType typ = ConstructedAtomType "Interval" (M.singleton "a" typ)
7191
7292intervalAtomFunctions :: AtomFunctions
7393intervalAtomFunctions = HS.fromList [
@@ -76,7 +96,7 @@ intervalAtomFunctions = HS.fromList [
7696 TypeVariableType "a",
7797 BoolAtomType,
7898 BoolAtomType,
79− IntervalAtomType (TypeVariableType "a")],
99+ intervalAtomType (TypeVariableType "a")],
80100 atomFuncBody = compiledAtomFunctionBody $ \(atom1:atom2:BoolAtom bopen:BoolAtom eopen:_) -> do
81101 let aType = atomTypeForAtom atom1
82102 if supportsInterval aType then
@@ -86,31 +106,33 @@ intervalAtomFunctions = HS.fromList [
86106 },
87107 AtomFunction {
88108 atomFuncName = "interval_overlaps",
89− atomFuncType = [IntervalAtomType (TypeVariableType "a"),
90− IntervalAtomType (TypeVariableType "a"),
109+ atomFuncType = [intervalAtomType (TypeVariableType "a"),
110+ intervalAtomType (TypeVariableType "a"),
91111 BoolAtomType],
92− atomFuncBody = compiledAtomFunctionBody $ \(i1@IntervalAtom{}:i2@IntervalAtom{}:_) ->
112+ atomFuncBody = compiledAtomFunctionBody $ \(i1@ConstructedAtom{}:i2@ConstructedAtom{}:_) ->
93113 BoolAtom <$> intervalOverlaps i1 i2
94114 }]
95−
96−
115+
116+isIntervalAtomType :: AtomType -> Bool
117+isIntervalAtomType (ConstructedAtomType nam tvMap) =
118+ nam == "Interval" && M.keys tvMap == ["a"] && case M.lookup "a" tvMap of
119+ Nothing -> False
120+ Just subType -> supportsInterval subType || subType == TypeVariableType "a"
121+isIntervalAtomType _ = False
122+
97123intervalOverlaps :: Atom -> Atom -> Either AtomFunctionError Bool
98−intervalOverlaps (IntervalAtom i1start i1end i1startopen i1endopen) (IntervalAtom i2start i2end i2startopen i2endopen) = do
99− cmp1 <- atomCompare i1start i2end
100− cmp2 <- atomCompare i2start i1end
101− let startcmp = if i1startopen || i2endopen then oplt else oplte
102− endcmp = if i2startopen || i1endopen then oplt else oplte
103− oplte op = op == LT || op == EQ
104− oplt op = op == LT
105− pure (startcmp cmp1 && endcmp cmp2)
124+intervalOverlaps (ConstructedAtom dCons1 typ1 (i1start:i1end:(BoolAtom i1startopen):(BoolAtom i1endopen):[])) (ConstructedAtom dCons2 typ2 (i2start:i2end:(BoolAtom i2startopen):(BoolAtom i2endopen):[])) = do
125+ when (dCons1 /= "Interval" || dCons2 /= "Interval" || not (isIntervalAtomType typ1) || not (isIntervalAtomType typ2)) (Left AtomFunctionTypeMismatchError)
126+ cmp1 <- atomCompare i1start i2end
127+ cmp2 <- atomCompare i2start i1end
128+ let startcmp = if i1startopen || i2endopen then oplt else oplte
129+ endcmp = if i2startopen || i1endopen then oplt else oplte
130+ oplte op = op == LT || op == EQ
131+ oplt op = op == LT
132+ pure (startcmp cmp1 && endcmp cmp2)
106133intervalOverlaps _ _ = Left AtomFunctionTypeMismatchError
107134
108135intervalTypeConstructorMapping :: TypeConstructorMapping
109−--intervalTypeConstructorMapping = [(ADTypeConstructorDef "Interval" ["a"], [])]
110−intervalTypeConstructorMapping = [(ADTypeConstructorDef "Interval" ["a"],
111− [DataConstructorDef "Interval" [DataConstructorDefTypeVarNameArg "a",
112− DataConstructorDefTypeVarNameArg "a",
113− ]])
114− ]
136+intervalTypeConstructorMapping = [(ADTypeConstructorDef "Interval" ["a"], [])]
115137
116138
src/lib/ProjectM36/DataTypes/Primitive.hs−1
@@ -37,6 +37,5 @@ atomTypeForAtom (DayAtom _) = DayAtomType
3737atomTypeForAtom (DateTimeAtom _) = DateTimeAtomType
3838atomTypeForAtom (ByteStringAtom _) = ByteStringAtomType
3939atomTypeForAtom (BoolAtom _) = BoolAtomType
40−atomTypeForAtom (IntervalAtom a _ _ _) = IntervalAtomType (atomTypeForAtom a)
4140atomTypeForAtom (RelationAtom (Relation attrs _)) = RelationAtomType attrs
4241atomTypeForAtom (ConstructedAtom _ aType _) = aType
src/lib/ProjectM36/Relation/Parse/CSV.hs+37−33
@@ -4,6 +4,7 @@ import ProjectM36.Base
44import ProjectM36.Error
55import ProjectM36.Relation
66import ProjectM36.AtomType
7+import ProjectM36.DataTypes.Interval
78import qualified ProjectM36.Attribute as A
89
910import Data.Csv.Parser
@@ -82,42 +83,45 @@ parseCSVAtomP _ _ BoolAtomType = do
8283 case readMaybe bString of
8384 Nothing -> fail ("invalid BoolAtom string: " ++ bString)
8485 Just b -> pure (Right (BoolAtom b))
85−parseCSVAtomP attrName tConsMap (IntervalAtomType iType) = do
86− begin <- (APT.char '[' >> pure False) <|> (APT.char '(' >> pure True)
87− eBeginv <- parseCSVAtomP attrName tConsMap iType
88− case eBeginv of
89− Left err -> pure (Left err)
90− Right beginv -> do
91− _ <- APT.char ','
92− eEndv <- parseCSVAtomP attrName tConsMap iType
93− case eEndv of
94− Left err -> pure (Left err)
95− Right endv -> do
96− let end = (APT.char ']' >> pure False) <|>
97− (APT.char ')' >> pure True)
98− Right . IntervalAtom beginv endv begin <$> end
99−parseCSVAtomP attrName tConsMap typ@(ConstructedAtomType _ tvmap) = do
100− dConsName <- capitalizedIdentifier
101− APT.skipSpace
86+parseCSVAtomP attrName tConsMap typ@(ConstructedAtomType _ tvmap)
87+ | isIntervalAtomType typ = do
88+ begin <- (APT.char '[' >> pure False) <|> (APT.char '(' >> pure True)
89+ let iType = intervalSubType typ
90+ eBeginv <- parseCSVAtomP attrName tConsMap iType
91+ case eBeginv of
92+ Left err -> pure (Left err)
93+ Right beginv -> do
94+ _ <- APT.char ','
95+ eEndv <- parseCSVAtomP attrName tConsMap iType
96+ case eEndv of
97+ Left err -> pure (Left err)
98+ Right endv -> do
99+ end <- (APT.char ']' >> pure False) <|>
100+ (APT.char ')' >> pure True)
101+ pure (Right (ConstructedAtom "Interval" typ [beginv, endv,
102+ BoolAtom begin, BoolAtom end]))
103+ | otherwise = do
104+ dConsName <- capitalizedIdentifier
105+ APT.skipSpace
102106 --we need to look up the name right away in order to determine the types of the following arguments
103107 -- grab the data constructor
104− case findDataConstructor dConsName tConsMap of
105− Nothing -> pure (Left (NoSuchDataConstructorError dConsName))
106− Just (_, dConsDef) ->
108+ case findDataConstructor dConsName tConsMap of
109+ Nothing -> pure (Left (NoSuchDataConstructorError dConsName))
110+ Just (_, dConsDef) ->
107111 -- identify the data constructor's expected atom type args
108− case resolvedAtomTypesForDataConstructorDefArgs tConsMap tvmap dConsDef of
109− Left err -> pure (Left err)
110− Right argAtomTypes -> do
111− atomArgs <- mapM (\argTyp -> let parseNextAtom = parseCSVAtomP attrName tConsMap argTyp <* APT.skipSpace in
112− case argTyp of
113− ConstructedAtomType _ _ ->
114− parens parseNextAtom <|>
115− parseNextAtom
116− _ -> parseNextAtom
117− ) argAtomTypes
118− case lefts atomArgs of
119− [] -> pure (Right (ConstructedAtom dConsName typ (rights atomArgs)))
120− errs -> pure (Left (someErrors errs))
112+ case resolvedAtomTypesForDataConstructorDefArgs tConsMap tvmap dConsDef of
113+ Left err -> pure (Left err)
114+ Right argAtomTypes -> do
115+ atomArgs <- mapM (\argTyp -> let parseNextAtom = parseCSVAtomP attrName tConsMap argTyp <* APT.skipSpace in
116+ case argTyp of
117+ ConstructedAtomType _ _ ->
118+ parens parseNextAtom <|>
119+ parseNextAtom
120+ _ -> parseNextAtom
121+ ) argAtomTypes
122+ case lefts atomArgs of
123+ [] -> pure (Right (ConstructedAtom dConsName typ (rights atomArgs)))
124+ errs -> pure (Left (someErrors errs))
121125parseCSVAtomP attrName _ (RelationAtomType _) = pure (Left (RelationValuedAttributesNotSupportedError [attrName]))
122126parseCSVAtomP _ _ (TypeVariableType x) = pure (Left (TypeConstructorTypeVarMissing x))
123127
src/lib/ProjectM36/RelationalExpression.hs+2−2
@@ -514,7 +514,7 @@ evalDatabaseContextIOExpr mScriptSession currentContext (AddAtomFunction funcNam
514514 pure $ case eCompiledFunc of
515515 Left err -> Left (ScriptError err)
516516 Right compiledFunc -> do
517− funcAtomType <- mapM (\funcTypeArg -> atomTypeForTypeConstructor funcTypeArg (typeConstructorMapping currentContext) M.empty) adjustedAtomTypeCons
517+ funcAtomType <- mapM (\funcTypeArg -> atomTypeForTypeConstructorValidate False funcTypeArg (typeConstructorMapping currentContext) M.empty) adjustedAtomTypeCons
518518 let updatedFuncs = HS.insert newAtomFunc atomFuncs
519519 newContext = currentContext { atomFunctions = updatedFuncs }
520520 newAtomFunc = AtomFunction { atomFuncName = funcName,
@@ -896,7 +896,7 @@ verifyAtomExprTypes rel cons@ConstructedAtomExpr{} expectedType = runExceptT $ d
896896-- | Look up the type's name and create a new attribute.
897897evalAttrExpr :: TypeConstructorMapping -> AttributeExpr -> Either RelationalError Attribute
898898evalAttrExpr aTypes (AttributeAndTypeNameExpr attrName tCons ()) = do
899− aType <- atomTypeForTypeConstructor tCons aTypes M.empty
899+ aType <- atomTypeForTypeConstructorValidate True tCons aTypes M.empty
900900 validateAtomType aType aTypes
901901 Right (Attribute attrName aType)
902902
test/Relation/Export/CSV.hs+1−1
@@ -57,7 +57,7 @@ testCSVExport = TestCase $ do
5757 Attribute "bytestringattr" ByteStringAtomType,
5858 Attribute "listintegerattr" (listAtomType IntegerAtomType),
5959 Attribute "listtextattr" (listAtomType TextAtomType),
60− Attribute "intervalattr" (IntervalAtomType DateTimeAtomType)
60+ Attribute "intervalattr" (intervalAtomType DateTimeAtomType)
6161 ]
6262 sampleByteString = "\1\0\244\34\150"
6363 relOrErr = mkRelationFromList attrs [
test/TutorialD/Interpreter.hs+2−1
@@ -10,6 +10,7 @@ import ProjectM36.Error
1010import ProjectM36.DatabaseContext
1111import ProjectM36.AtomFunctions.Primitive
1212import ProjectM36.DataTypes.Either
13+import ProjectM36.DataTypes.Interval
1314import ProjectM36.DateExamples
1415import ProjectM36.Base hiding (Finite)
1516import ProjectM36.TransactionGraph
@@ -578,7 +579,7 @@ testIntervalType = TestCase $ do
578579 executeTutorialD sessionId dbconn "x:=relation{a Interval Integer}"
579580 eX <- executeRelationalExpr sessionId dbconn (RelationVariable "x" ())
580581 let expectedIntervalInt = mkRelationFromList expectedAttrs []
581− expectedAttrs = A.attributesFromList [Attribute "a" (ConstructedAtomType "Interval" (M.singleton "a" IntegerAtomType))]
582+ expectedAttrs = A.attributesFromList [Attribute "a" (intervalAtomType IntegerAtomType)]
582583 assertEqual "Interval Int attribute" expectedIntervalInt eX
583584
584585testArbitraryRelation :: Test
test/TutorialD/Interpreter/DatabaseContextFunctionScript.hs−9
@@ -14,9 +14,6 @@ main = do
1414 ])
1515 if errors tcounts + failures tcounts > 0 then exitFailure else exitSuccess
1616
17−{-
18−adddatabasecontextfunction "addtruerv" DatabaseContext -> DatabaseContext """(\[] ctx -> execState (evalDatabaseContextExpr (Assign "true2" (ExistingRelation relationTrue))) ctx) :: [Atom] -> DatabaseContext -> DatabaseContext"""
19−-}
2017testBasicDBCFunction :: Test
2118testBasicDBCFunction = TestCase $ do
2219 (sess, conn) <- dateExamplesConnection emptyNotificationCallback
@@ -43,9 +40,6 @@ testExceptionDBCFunction = TestCase $ do
4340 expectTutorialDErr sess conn (\err -> "UnhandledExceptionError" `T.isPrefixOf` err) "execute bomb()"
4441
4542
46−{-
47−adddatabasecontextfunction "multiArgFunc" Int -> Text -> DatabaseContext -> DatabaseContext """(\(age:name:_) ctx -> execState (evalDatabaseContextExpr (Assign "person" (MakeRelationFromExprs Nothing [TupleExpr (fromList [("name", NakedAtomExpr name), ("age", NakedAtomExpr age)])]))) ctx)"""
48−-}
4943testDBCFunctionWithAtomArguments :: Test
5044testDBCFunctionWithAtomArguments = TestCase $ do
5145 --test function with creation of a relvar with some arguments
@@ -60,7 +54,4 @@ testDBCFunctionWithAtomArguments = TestCase $ do
6054 assertEqual "person relation" expectedPerson result
6155 expectTutorialDErr sess conn (T.isPrefixOf "AtomTypeMismatchError") "execute multiArgFunc(\"fail\", \"fail\")"
6256
63−{-
64−adddatabasecontextfunction "addperson" Int -> Text -> DatabaseContext -> DatabaseContext """(\(age:name:_) ctx -> let newrel = MakeRelationFromExprs Nothing [TupleExpr (fromList [("name", name),("age",age))]] in if isRight (runState (executeRelationalExpr (RelationVariable "person" ()) ctx)) then execState (executeContextExpr (Insert "person" newrel)) ctx else execState (executeContextExpr (Assign "person" newrel)) ctx) :: [Atom] -> DatabaseContext -> DatabaseContext"""
65−-}
6657