on master help sign in
more expressifying of the parser
commita74026442be1eb966441163fd9a58dd9e50fd2fe authorAgentM <agentm@themactionfaction.com> dateSun 7 Feb 2016, 17:58 (11 years ago) parent8b18689
7 files changed+124−66
ProjectM36/AtomType.hs+27−5 ProjectM36/Base.hs+10−6 ProjectM36/Client.hs+2−2 ProjectM36/Error.hs+4−3 ProjectM36/Key.hs+2−2 ProjectM36/RelationalExpression.hs+18−8 TutorialD/Interpreter/RelationalExpr.hs+61−40
ProjectM36/AtomType.hs+27−5
@@ -22,15 +22,37 @@ typesAsRelation aTypes = mkRelationFromTuples attrs tuples
2222 mkDataConsRelation dConsMap = case mkRelationFromTuples subAttrs $ map (\(dConsName, dConsTypeNames) -> RelationTuple subAttrs (V.singleton $ stringAtom $ T.intercalate " " (dConsName:dConsTypeNames))) (M.toList dConsMap) of
2323 Left err -> error ("mkRelationFromTuples pooped " ++ show err)
2424 Right rel -> Atom rel
25−
25+{-
2626-- | Scan all type constructors for the proper data constructor
27−dataConstructorForName :: DataConstructorName -> AtomTypes -> Either RelationalError (DataConstructorName, [AtomTypeName])
28−dataConstructorForName dConsName aTypes = M.foldrWithKey typeFolder defaultErr aTypes
27+dataConstructorTypeNamesForName :: DataConstructorName -> AtomTypes -> Either RelationalError [AtomTypeName]
28+dataConstructorTypeNamesForName dConsName aTypes = M.foldrWithKey typeFolder defaultErr aTypes
2929 where
30− defaultErr = Left (NoSuchDataConstructor dConsName)
30+ defaultErr = Left (NoSuchDataConstructorError dConsName)
3131 typeFolder _ (_, AtomConstructor dConsMap) accum = if isRight accum then
3232 accum
3333 else
3434 case M.lookup dConsName dConsMap of
3535 Nothing -> accum
36− Just aTypeNames -> Right (dConsName, aTypeNames)
36+ Just aTypeNames -> Right (dConsName, aTypeNames)
37+-}
38+-- fix mostly-duplicated fold code
39+-- | Scan the atom types and return the resultant ConstructedAtomType or error.
40+atomAndArgsTypesForDataConstructorName :: DataConstructorName -> AtomTypes -> Either RelationalError (AtomType, [AtomType])
41+atomAndArgsTypesForDataConstructorName dConsName aTypes = M.foldrWithKey typeFolder defaultErr aTypes
42+ where
43+ defaultErr = Left (NoSuchDataConstructorError dConsName)
44+ typeFolder _ (aType, AtomConstructor dConsMap) accum = if isRight accum then
45+ accum
46+ else
47+ case M.lookup dConsName dConsMap of
48+ Nothing -> accum
49+ Just aArgsTypeNames -> do --convert aTypeNames into AtomTypes
50+ aArgsTypes <- mapM (\tName -> atomTypeForTypeConstructor tName aTypes) aArgsTypeNames
51+ Right (aType, aArgsTypes)
52+
53+atomTypeForTypeConstructor :: TypeConstructorName -> AtomTypes -> Either RelationalError AtomType
54+atomTypeForTypeConstructor tConsName aTypes = case M.lookup tConsName aTypes of
55+ Nothing -> Left (NoSuchTypeConstructorError tConsName)
56+ Just (aType, _) -> Right aType
57+
58+
ProjectM36/Base.hs+10−6
@@ -230,6 +230,8 @@ type RelVarName = StringType
230230
231231-- | A relational expression represents query (read) operations on a database.
232232data RelationalExpr where
233+ --- | Create a relation from attribute and atom expressions.
234+ MakeRelationFromAtomExprs :: [AttributeExpr] -> [AtomExpr] -> RelationalExpr
233235 --- | Create and reference a relation from attributes and a tuple set.
234236 MakeStaticRelation :: Attributes -> RelationTupleSet -> RelationalExpr
235237 --- | Reference an existing relation in Haskell-space.
@@ -256,7 +258,7 @@ data RelationalExpr where
256258 --- | Returns the true relation iff
257259 Equals :: RelationalExpr -> RelationalExpr -> RelationalExpr
258260 NotEquals :: RelationalExpr -> RelationalExpr -> RelationalExpr
259− Extend :: TupleExpr -> RelationalExpr -> RelationalExpr
261+ Extend :: ExtendTupleExpr -> RelationalExpr -> RelationalExpr
260262 --Summarize :: AtomExpr -> AttributeName -> RelationalExpr -> RelationalExpr -> RelationalExpr -- a special case of Extend
261263 deriving (Show,Eq, Generic)
262264
@@ -395,10 +397,11 @@ data AtomExpr = AttributeAtomExpr AttributeName |
395397instance Binary AtomExpr
396398
397399-- | A tuple expression declares what action to take when extending a relation.
398−data TupleExpr = AttributeTupleExpr AttributeName AtomExpr
399− deriving (Show, Eq, Generic)
400−
401−instance Binary TupleExpr
400+data ExtendTupleExpr = AttributeExtendTupleExpr AttributeName AtomExpr
401+ deriving (Show, Eq, Generic, Binary)
402+
403+-- | Used in tuple creation when creating a relation.
404+data TupleExpr = TupleExpr Attributes [AtomExpr]
402405
403406--enumerates the list of functions available to be run as part of tuple expressions
404407type AtomFunctions = HS.HashSet AtomFunction
@@ -436,4 +439,5 @@ data PersistenceStrategy = NoPersistence | -- ^ no filesystem persistence/memory
436439 CrashSafePersistence FilePath -- ^ full fsync to disk (flushes kernel and physical drive buffers to ensure that the transaction is on non-volatile storage)
437440 deriving (Show, Read)
438441
439−
442+data AttributeExpr = AttributeAndAtomExpr AttributeName AtomExpr |
443+ AttributeAndTypeName AttributeName TypeConstructorName
ProjectM36/Client.hs+2−2
@@ -256,7 +256,7 @@ createSessionAtCommit_ commitUUID newSessionId (InProcessConnection _ _ sessions
256256 let freshDiscon = DisconnectedTransaction commitUUID (transactionContext transaction)
257257 keyDuplication <- STMMap.lookup newSessionId sessions
258258 case keyDuplication of
259− Just _ -> pure $ Left (SessionIdInUse newSessionId)
259+ Just _ -> pure $ Left (SessionIdInUseError newSessionId)
260260 Nothing -> do
261261 STMMap.insert (Session freshDiscon) newSessionId sessions
262262 pure $ Right newSessionId
@@ -312,7 +312,7 @@ remoteCall (RemoteProcessConnection localNode serverProcessId) arg = runProcessR
312312sessionForSessionId :: SessionId -> Sessions -> STM (Either RelationalError Session)
313313sessionForSessionId sessionId sessions = do
314314 maybeSession <- STMMap.lookup sessionId sessions
315− pure $ maybe (Left $ NoSuchSession sessionId) Right maybeSession
315+ pure $ maybe (Left $ NoSuchSessionError sessionId) Right maybeSession
316316
317317-- | Execute a relational expression in the context of the session and connection. Relational expressions are queries and therefore cannot alter the database.
318318executeRelationalExpr :: SessionId -> Connection -> RelationalExpr -> IO (Either RelationalError Relation)
ProjectM36/Error.hs+4−3
@@ -29,13 +29,14 @@ data RelationalError = NoSuchAttributeNamesError (S.Set AttributeName)
2929 | NoSuchHeadNameError HeadName
3030 | TransactionIsNotAHeadError U.UUID
3131 | TransactionGraphCycleError U.UUID
32− | SessionIdInUse U.UUID
33− | NoSuchSession U.UUID
32+ | SessionIdInUseError U.UUID
33+ | NoSuchSessionError U.UUID
3434 | NoSuchTupleExprFunctionError AtomFunctionName
3535 | AtomTypeMismatchError AtomType AtomType
3636 | AtomTypeNameInUseError AtomTypeName
3737 | AtomTypeNameNotInUseError AtomTypeName
38− | NoSuchDataConstructor DataConstructorName
38+ | NoSuchDataConstructorError DataConstructorName
39+ | NoSuchTypeConstructorError TypeConstructorName
3940 | InvalidAtomTypeName AtomTypeName
4041 | AtomTypeNotSupported AttributeName --used by persistent driver
4142 | AtomOperatorNotSupported T.Text --used by persistent driver
ProjectM36/Key.hs+2−2
@@ -26,8 +26,8 @@ inclusionDependencyForKey attrNames relExpr = --InclusionDependency name (exprCo
2626 InclusionDependency equalityExpr (ExistingRelation relationFalse)
2727 where
2828 projectedOnKeys expr = Project attrNames expr
29− exprAsSubRelation expr = Extend (AttributeTupleExpr "a" (RelationAtomExpr expr)) (ExistingRelation relationTrue)
30− exprCount expr = projectionForCount (Extend (AttributeTupleExpr "b" (FunctionAtomExpr "count" [AttributeAtomExpr "a"])) (exprAsSubRelation expr))
29+ exprAsSubRelation expr = Extend (AttributeExtendTupleExpr "a" (RelationAtomExpr expr)) (ExistingRelation relationTrue)
30+ exprCount expr = projectionForCount (Extend (AttributeExtendTupleExpr "b" (FunctionAtomExpr "count" [AttributeAtomExpr "a"])) (exprAsSubRelation expr))
3131 projectionForCount expr = Project (AttributeNames $ S.fromList ["b"]) expr
3232 equalityExpr = NotEquals (exprCount relExpr) (exprCount (projectedOnKeys relExpr))
3333
ProjectM36/RelationalExpression.hs+18−8
@@ -477,7 +477,7 @@ tupleExprCheckNewAttrName attrName rel = if isRight $ attributeForName attrName
477477
478478tupleExpressionProcessor :: Relation -> TupleExpr -> DatabaseContext -> Either RelationalError (Attributes, RelationTuple -> RelationTuple)
479479tupleExpressionProcessor relIn
480− (AttributeTupleExpr newAttrName atomExpr) context = do
480+ (AttributeExtendTupleExpr newAttrName atomExpr) context = do
481481 _ <- tupleExprCheckNewAttrName newAttrName relIn
482482 atomExprType <- typeFromAtomExpr (attributes relIn) context atomExpr
483483 _ <- verifyAtomExprTypes relIn context atomExpr atomExprType
@@ -500,10 +500,10 @@ evalAtomExpr tupIn context (FunctionAtomExpr funcName arguments) = do
500500evalAtomExpr _ context (RelationAtomExpr relExpr) = do
501501 relAtom <- evalState (evalRelationalExpr relExpr) context
502502 return $ Atom relAtom
503−evalAtomExpr _ context (ConstructedAtomExpr dConsName dConsArgs) = do
504− --type-checking presumed!
505− dataConstructorForName
506−
503+evalAtomExpr tupIn context cons@(ConstructedAtomExpr dConsName dConsArgs) = do
504+ aType <- typeFromAtomExpr (tupleAttributes tupIn) context cons
505+ argAtoms <- mapM (evalAtomExpr tupIn context) dConsArgs
506+ pure (ConstructedAtom dConsName aType argAtoms)
507507
508508typeFromAtomExpr :: Attributes -> DatabaseContext -> AtomExpr -> Either RelationalError AtomType
509509typeFromAtomExpr attrs _ (AttributeAtomExpr attrName) = A.atomTypeForAttributeName attrName attrs
@@ -515,9 +515,17 @@ typeFromAtomExpr _ context (FunctionAtomExpr funcName _) = do
515515typeFromAtomExpr _ context (RelationAtomExpr relExpr) = do
516516 relType <- evalState (typeForRelationalExpr relExpr) context
517517 return $ RelationAtomType (attributes relType)
518−typeFromAtomExpr _ context (ConstructedAtomExpr dConsName dConsArgs) = do
519−
518+-- grab the type of the data constructor, then validate that the args match the expected types
519+typeFromAtomExpr attrs context (ConstructedAtomExpr dConsName dConsArgs) = do
520+ (tConsType, dConsArgTypes) <- atomAndArgsTypesForDataConstructorName dConsName (atomTypes context)
521+ argsTypes <- mapM (typeFromAtomExpr attrs context) dConsArgs
522+ --validate that the argument types match
523+ if argsTypes /= dConsArgTypes then
524+ Left $ AtomTypeMismatchError intAtomType intAtomType --fix error message
525+ else
526+ pure tConsType
520527
528+-- | Validae that the
521529verifyAtomExprTypes :: Relation -> DatabaseContext -> AtomExpr -> AtomType -> Either RelationalError AtomType
522530verifyAtomExprTypes relIn _ (AttributeAtomExpr attrName) expectedType = do
523531 attrType <- A.atomTypeForAttributeName attrName (attributes relIn)
@@ -540,7 +548,9 @@ verifyAtomExprTypes _ context (RelationAtomExpr relationExpr) expectedType = do
540548 case runState (typeForRelationalExpr relationExpr) context of
541549 (Left err, _) -> Left err
542550 (Right relType, _) -> atomTypeVerify expectedType (RelationAtomType (attributes relType))
543−verifyAtomExprTypes _ context (ConstructedAtomExpr dConsName dConsArgs) = do
551+verifyAtomExprTypes rel context cons@(ConstructedAtomExpr _ _) expectedType = do
552+ cType <- typeFromAtomExpr (attributes rel) context cons
553+ atomTypeVerify expectedType cType
544554
545555
546556
TutorialD/Interpreter/RelationalExpr.hs+61−40
@@ -22,6 +22,8 @@ import TutorialD.Interpreter.DataTypes.Interval
2222
2323import Data.Time.Calendar (Day)
2424
25+--nuke this
26+{-
2527atomTypeP :: Parser AtomType
2628atomTypeP = (reserved "char" *> return stringAtomType) <|>
2729 (reserved "int" *> return intAtomType) <|>
@@ -31,7 +33,8 @@ atomTypeP = (reserved "char" *> return stringAtomType) <|>
3133 (reserved "bool" *> return boolAtomType) <|>
3234 (reserved "bytestring" *> return byteStringAtomType) <|>
3335 (RelationAtomType <$> (reserved "relation" *> makeAttributesP))
34−
36+-}
37+
3538--used in projection
3639attributeListP :: Parser AttributeNames
3740attributeListP = do
@@ -41,35 +44,49 @@ attributeListP = do
4144 return $ constructor (S.fromList (map T.pack attrs))
4245
4346makeRelationP :: Parser RelationalExpr
44−makeRelationP = ExistingRelation <$> relationP
47+makeRelationP = do
48+ reserved "relation"
49+ attrs <- (try makeAttributesP <|> return A.emptyAttributes)
50+ if not (A.null attrs) then do
51+ case mkRelation attrs emptyTupleSet of
52+ Left err -> fail (show err)
53+ Right rel -> pure (ExistingRelation rel)
54+ else do -- empty attributes
55+ tupleExprs <- try (braces (sepBy tupleExprP comma)) <|> pure []
56+ pure $ MakeRelationFromAtomExprs attrs
57+
58+
59+makeAttributeExprsP :: Parser [AttributeExpr]
60+makeAttributeExprsP = do
61+ attrList <- bra
4562
4663--used in relation creation
47−makeAttributesP :: Parser Attributes
48−makeAttributesP = do
49− attrList <- braces (sepBy attributeAndTypeP comma)
64+makeAttributeExprsP :: Parser [AttributeExprs]
65+makeAttributeExprsP = do
66+ attrList <- braces (sepBy attributeAndTypeNameP comma)
5067 return $ A.attributesFromList attrList
5168
52−attributeAndTypeP :: Parser Attribute
53−attributeAndTypeP = do
69+
70+attributeAndTypeNameP :: Parser AttributeExpr
71+attributeAndTypeNameP = do
5472 attrName <- identifier
5573 --convert type name into type
56− atomType <- atomTypeP
57− return $ Attribute (T.pack attrName) atomType
74+ atomType <- identifier
75+ return $ AttributeAndTypeNameExpr (T.pack attrName) atomType
5876
59−tupleP :: Parser RelationTuple
60−tupleP = do
77+tupleExprP :: Parser TupleExpr
78+tupleExprP = do
6179 reservedOp "tuple"
62− attrAssocs <- braces (sepBy tupleAtomP comma)
63− let attrs = A.attributesFromList $ map (\(attrName, atom) -> Attribute attrName (atomTypeForAtom atom)) attrAssocs
64− let atoms = V.fromList $ map snd attrAssocs
65− return $ mkRelationTuple attrs atoms
80+ attrAssocs <- braces (sepBy tupleAtomExprP comma)
81+ let attrs = A.attributesFromList $ map fst attrAssocs
82+ pure (TupleExpr attrs (map snd attrAssocs))
6683
67−tupleAtomP :: Parser (AttributeName, Atom)
68−tupleAtomP = do
84+tupleAtomExprP :: Parser (AttributeName, AtomExpr)
85+tupleAtomExprP = do
6986 attributeName <- identifier
70− atom <- atomP
71− return $ (T.pack attributeName, atom)
72−
87+ atomExpr <- atomExprP
88+ return $ (T.pack attributeName, atomExpr)
89+
7390projectP :: Parser (RelationalExpr -> RelationalExpr)
7491projectP = do
7592 attrs <- braces attributeListP
@@ -117,7 +134,7 @@ ungroupP = do
117134extendP :: Parser (RelationalExpr -> RelationalExpr)
118135extendP = do
119136 reservedOp ":"
120− tupleExpr <- braces tupleExpressionP
137+ tupleExpr <- braces extendTupleExpressionP
121138 return $ Extend tupleExpr
122139
123140{-
@@ -202,24 +219,25 @@ restrictionAtomExprP = do
202219 _ <- char '^' -- not ideal, but allows me to continue to use a context-free grammar
203220 AtomExprPredicate <$> atomExprP
204221
205−multiTupleExpressionP :: Parser [TupleExpr]
206−multiTupleExpressionP = sepBy tupleExpressionP comma
222+multiTupleExpressionP :: Parser [ExtendTupleExpr]
223+multiTupleExpressionP = sepBy extendTupleExpressionP comma
207224
208−tupleExpressionP :: Parser TupleExpr
209−tupleExpressionP = attributeTupleExpressionP
225+extendTupleExpressionP :: Parser ExtendTupleExpr
226+extendTupleExpressionP = attributeExtendTupleExpressionP
210227
211−attributeTupleExpressionP :: Parser TupleExpr
212−attributeTupleExpressionP = do
228+attributeExtendTupleExpressionP :: Parser ExtendTupleExpr
229+attributeExtendTupleExpressionP = do
213230 newAttr <- identifier
214231 reservedOp ":="
215232 atom <- atomExprP
216− return $ AttributeTupleExpr (T.pack newAttr) atom
233+ return $ AttributeExtendTupleExpr (T.pack newAttr) atom
217234
218235atomExprP :: Parser AtomExpr
219236atomExprP = try functionAtomExprP <|>
220237 attributeAtomExprP <|>
221238 nakedAtomExprP <|>
222− relationalAtomExprP
239+ relationalAtomExprP <|>
240+ constructedAtomP
223241
224242attributeAtomExprP :: Parser AtomExpr
225243attributeAtomExprP = do
@@ -237,7 +255,7 @@ constructedAtomP = do
237255 dConsName <- identifier
238256 dConsArgs <- sepBy atomExprP spaces
239257 reserved "]"
240− pure $ AtomConstructor dConsName dConsArgs
258+ pure $ ConstructedAtomExpr (T.pack dConsName) dConsArgs
241259
242260atomP :: Parser Atom
243261atomP = dateTimeAtomP <|>
@@ -250,9 +268,8 @@ atomP = dateTimeAtomP <|>
250268 doubleAtomP <|>
251269 intAtomP <|>
252270 boolAtomP <|>
253− relationAtomP <|>
254− constructedAtomP
255−
271+ relationAtomP
272+
256273functionAtomExprP :: Parser AtomExpr
257274functionAtomExprP = do
258275 funcName <- identifier
@@ -271,13 +288,15 @@ maybeTextAtomP = do
271288 maybeText <- try $ ((Just . T.pack <$> (reserved "Just" *> quotedString)) <|>
272289 (reserved "Nothing" *> return Nothing)) <* reserved "::maybe char"
273290 return $ Atom maybeText
274−
291+
292+--refactor to use polymorphic runtime constructors
275293maybeIntAtomP :: Parser Atom
276294maybeIntAtomP = do
277295 maybeInt <- try $ ((Just . fromIntegral <$> (reserved "Just" *> integer)) <|>
278296 (reserved "Nothing" *> return Nothing)) <* reserved "::maybe int"
279297 return $ Atom (maybeInt :: Maybe Int)
280−
298+
299+--refactor to use constructors
281300dateAtomP :: Parser Atom
282301dateAtomP = do
283302 dateString' <- try $ do
@@ -287,10 +306,10 @@ dateAtomP = do
287306 case parseTimeM False defaultTimeLocale "%Y-%m-%d" dateString' of
288307 Just todaytime -> return $ Atom (todaytime :: Day)
289308 Nothing -> fail "Failed to parse date"
290−
309+
291310doubleAtomP :: Parser Atom
292311doubleAtomP = Atom <$> (try float)
293−
312+
294313intAtomP :: Parser Atom
295314intAtomP = do
296315 i <- integer
@@ -301,9 +320,10 @@ boolAtomP = do
301320 val <- char 't' <|> char 'f'
302321 return $ Atom (val == 't')
303322
304−relationAtomP :: Parser Atom
305−relationAtomP = Atom <$> relationP
323+relationAtomExprP :: Parser AtomExpr
324+relationAtomExprP = RelationAtomExpr <$> relationExprP
306325
326+-- deprecated for removal- use constructors
307327byteStringAtomP :: Parser Atom
308328byteStringAtomP = do
309329 byteString' <- try $ do
@@ -314,6 +334,7 @@ byteStringAtomP = do
314334 Left err -> fail err
315335 Right bsVal -> return $ Atom bsVal
316336
337+{-
317338--relation constructor -- no choice but to propagate relation-construction errors as parse errors. Perhaps this could be improved in the future
318339relationP :: Parser Relation
319340relationP = do
@@ -329,4 +350,4 @@ relationP = do
329350 case mkRelationFromTuples tupleAttrs tuples of
330351 Left err -> fail (show err)
331352 Right rel -> return rel
332−
353+-}