@@ -1,4 +1,4 @@
1−{-# LANGUAGE GADTs #-}
1+{-# LANGUAGE GADTs,OverloadedStrings #-}
2module TutorialD.Interpreter where
2module TutorialD.Interpreter where
3import ProjectM36.Base
3import ProjectM36.Base
4import ProjectM36.Relation
4import ProjectM36.Relation
@@ -29,6 +29,8 @@ import System.Directory (getHomeDirectory)
29import qualified Data.UUID as U
29import qualified Data.UUID as U
30import Data.UUID.V4 (nextRandom)
30import Data.UUID.V4 (nextRandom)
31import qualified Data.Vector as V
31import qualified Data.Vector as V
32+import qualified Data.Text as T
33+import qualified Data.Text.IO as TIO
34List of Tutorial D operators:
36List of Tutorial D operators:
@@ -70,7 +72,9 @@ uuidP = do
71--used in projection
73--used in projection
72attributeList :: Parser [AttributeName]
74attributeList :: Parser [AttributeName]
73−attributeList = sepBy identifier comma
76+ attrs <- sepBy identifier comma
77+ return $ map T.pack attrs
75makeRelation :: Parser RelationalExpr
79makeRelation :: Parser RelationalExpr
76makeRelation = do
80makeRelation = do
@@ -94,7 +98,7 @@ attributeAndType = do
94 attrTypeName <- identifier
98 attrTypeName <- identifier
95 --convert type name into type
99 --convert type name into type
96 case tutDTypeToAtomType attrTypeName of
100 case tutDTypeToAtomType attrTypeName of
97− Just t -> return $ Attribute attrName t
101+ Just t -> return $ Attribute (T.pack attrName) t
98 Nothing -> fail (attrTypeName ++ " is not a valid type name.")
102 Nothing -> fail (attrTypeName ++ " is not a valid type name.")
100tupleP :: Parser RelationTuple
104tupleP :: Parser RelationTuple
@@ -113,7 +117,7 @@ tupleAtomP = do
113 case tutDTypeToAtomType attrType of
117 case tutDTypeToAtomType attrType of
114 Nothing -> fail (attrType ++ " is not a valid type name.")
118 Nothing -> fail (attrType ++ " is not a valid type name.")
115 Just typeA -> if typeA == atomTypeForAtom atom then
119 Just typeA -> if typeA == atomTypeForAtom atom then
116− return $ (attributeName, atom)
120+ return $ (T.pack attributeName, atom)
118 fail "type mismatch in tuple generation"
122 fail "type mismatch in tuple generation"
@@ -132,7 +136,7 @@ atomTypeToTutDType atomType = case atomType of
132 _ -> Nothing
136 _ -> Nothing
134relVarP :: Parser RelationalExpr
138relVarP :: Parser RelationalExpr
135−relVarP = liftA RelationVariable identifier
139+relVarP = liftA (RelationVariable . T.pack) identifier
137relTerm = parens relExpr
141relTerm = parens relExpr
138 <|> makeRelation
142 <|> makeRelation
@@ -149,7 +153,7 @@ assignP = do
149 reservedOp ":="
153 reservedOp ":="
150 return relVarName
154 return relVarName
151 expr <- relExpr
155 expr <- relExpr
152− return $ Assign relVarName expr
156+ return $ Assign (T.pack relVarName) expr
154renameClause = do
158renameClause = do
155 oldAttr <- identifier
159 oldAttr <- identifier
@@ -161,7 +165,7 @@ renameP :: Parser (RelationalExpr -> RelationalExpr)
161renameP = do
165renameP = do
162 reservedOp "rename"
166 reservedOp "rename"
163 (oldAttr, newAttr) <- braces renameClause
167 (oldAttr, newAttr) <- braces renameClause
164− return $ Rename oldAttr newAttr
168+ return $ Rename (T.pack oldAttr) (T.pack newAttr)
166whereClauseP = do
170whereClauseP = do
167 reservedOp "where"
171 reservedOp "where"
@@ -178,14 +182,14 @@ groupP :: Parser (RelationalExpr -> RelationalExpr)
178groupP = do
182groupP = do
179 reservedOp "group"
183 reservedOp "group"
180 (groupAttrList, groupAttrName) <- parens groupClause
184 (groupAttrList, groupAttrName) <- parens groupClause
181− return $ Group (S.fromList groupAttrList) groupAttrName
185+ return $ Group (S.fromList groupAttrList) (T.pack groupAttrName)
183--in "Time and Relational Theory" (2014), Date's Tutorial D grammar for ungroup takes one attribute, while in previous books, it take multiple arguments. Let us assume that nested ungroups are the same as multiple attributes.
187--in "Time and Relational Theory" (2014), Date's Tutorial D grammar for ungroup takes one attribute, while in previous books, it take multiple arguments. Let us assume that nested ungroups are the same as multiple attributes.
184ungroupP :: Parser (RelationalExpr -> RelationalExpr)
188ungroupP :: Parser (RelationalExpr -> RelationalExpr)
185ungroupP = do
189ungroupP = do
186 reservedOp "ungroup"
190 reservedOp "ungroup"
187 rvaAttrName <- identifier
191 rvaAttrName <- identifier
188− return $ Ungroup rvaAttrName
192+ return $ Ungroup (T.pack rvaAttrName)
190relOperators = [
194relOperators = [
191 [Postfix projectOp],
195 [Postfix projectOp],
@@ -220,7 +224,7 @@ insertP = do
220 reservedOp "insert"
224 reservedOp "insert"
221 relvar <- identifier
225 relvar <- identifier
222 expr <- relExpr
226 expr <- relExpr
223− return $ Insert relvar expr
227+ return $ Insert (T.pack relvar) expr
225defineP :: Parser DatabaseExpr
229defineP :: Parser DatabaseExpr
226defineP = do
230defineP = do
@@ -229,20 +233,20 @@ defineP = do
229 reservedOp "::"
233 reservedOp "::"
230 return relVarName
234 return relVarName
231 attributeSet <- makeAttributes
235 attributeSet <- makeAttributes
232− return $ Define relVarName attributeSet
236+ return $ Define (T.pack relVarName) attributeSet
234undefineP :: Parser DatabaseExpr
238undefineP :: Parser DatabaseExpr
235undefineP = do
239undefineP = do
236 reservedOp "undefine"
240 reservedOp "undefine"
237 relVarName <- identifier
241 relVarName <- identifier
238− return $ Undefine relVarName
242+ return $ Undefine (T.pack relVarName)
240deleteP :: Parser DatabaseExpr
244deleteP :: Parser DatabaseExpr
241deleteP = do
245deleteP = do
242 reservedOp "delete"
246 reservedOp "delete"
243 relVarName <- identifier
247 relVarName <- identifier
244 predicate <- option TruePredicate (reservedOp "where" *> restrictionPredicateP)
248 predicate <- option TruePredicate (reservedOp "where" *> restrictionPredicateP)
245− return $ Delete relVarName predicate
249+ return $ Delete (T.pack relVarName) predicate
247updateP :: Parser DatabaseExpr
251updateP :: Parser DatabaseExpr
248updateP = do
252updateP = do
@@ -250,7 +254,7 @@ updateP = do
250 relVarName <- identifier
254 relVarName <- identifier
251 predicate <- option TruePredicate (reservedOp "where" *> restrictionPredicateP <* spaces)
255 predicate <- option TruePredicate (reservedOp "where" *> restrictionPredicateP <* spaces)
252 attributeAssignments <- liftM M.fromList $ parens (sepBy attributeAssignment comma)
256 attributeAssignments <- liftM M.fromList $ parens (sepBy attributeAssignment comma)
253− return $ Update relVarName attributeAssignments predicate
257+ return $ Update (T.pack relVarName) (M.mapKeys T.pack $ attributeAssignments) predicate
255constraintP :: Parser DatabaseExpr
259constraintP :: Parser DatabaseExpr
256constraintP = do
260constraintP = do
@@ -259,7 +263,7 @@ constraintP = do
259 subset <- relExpr
263 subset <- relExpr
260 reservedOp "in"
264 reservedOp "in"
261 superset <- relExpr
265 superset <- relExpr
262− return $ AddInclusionDependency (InclusionDependency constraintName subset superset)
266+ return $ AddInclusionDependency (InclusionDependency (T.pack constraintName) subset superset)
264attributeAssignment :: Parser (String, Atom)
268attributeAssignment :: Parser (String, Atom)
265attributeAssignment = do
269attributeAssignment = do
@@ -270,21 +274,21 @@ attributeAssignment = do
271parseString :: String -> Either RelationalError DatabaseExpr
275parseString :: String -> Either RelationalError DatabaseExpr
272parseString str = case parse (multipleDatabaseExpr <* eof) "" str of
276parseString str = case parse (multipleDatabaseExpr <* eof) "" str of
273− Left err -> Left $ ParseError (show err)
277+ Left err -> Left $ ParseError (T.pack (show err))
274 Right r -> Right r
278 Right r -> Right r
276--operators which only rely on database context reading
280--operators which only rely on database context reading
277data ContextOperator where
281data ContextOperator where
278 ShowRelation :: RelationalExpr -> ContextOperator
282 ShowRelation :: RelationalExpr -> ContextOperator
279 ShowRelationType :: RelationalExpr -> ContextOperator
283 ShowRelationType :: RelationalExpr -> ContextOperator
280− ShowConstraint :: String -> ContextOperator
284+ ShowConstraint :: StringType -> ContextOperator
281 ShowPlan :: DatabaseExpr -> ContextOperator
285 ShowPlan :: DatabaseExpr -> ContextOperator
282 Quit :: ContextOperator
286 Quit :: ContextOperator
283 deriving (Show)
287 deriving (Show)
285--operators which manipulate a transaction graph
289--operators which manipulate a transaction graph
286data GraphOperator where
290data GraphOperator where
287− JumpToHead :: String -> GraphOperator
291+ JumpToHead :: HeadName -> GraphOperator
288 JumpToTransaction :: U.UUID -> GraphOperator
292 JumpToTransaction :: U.UUID -> GraphOperator
289 Branch :: HeadName -> GraphOperator
293 Branch :: HeadName -> GraphOperator
290 Commit :: GraphOperator
294 Commit :: GraphOperator
@@ -318,13 +322,13 @@ showConstraintsP :: Parser ContextOperator
318showConstraintsP = do
322showConstraintsP = do
319 reservedOp ":constraints"
323 reservedOp ":constraints"
320 constraintName <- option "" identifier
324 constraintName <- option "" identifier
321− return $ ShowConstraint constraintName
325+ return $ ShowConstraint (T.pack constraintName)
323jumpToHeadP :: Parser GraphOperator
327jumpToHeadP :: Parser GraphOperator
324jumpToHeadP = do
328jumpToHeadP = do
325 reservedOp ":jumphead"
329 reservedOp ":jumphead"
326 headid <- identifier
330 headid <- identifier
327− return $ JumpToHead headid
331+ return $ JumpToHead (T.pack headid)
329jumpToTransactionP :: Parser GraphOperator
333jumpToTransactionP :: Parser GraphOperator
330jumpToTransactionP = do
334jumpToTransactionP = do
@@ -336,7 +340,7 @@ branchTransactionP :: Parser GraphOperator
336branchTransactionP = do
340branchTransactionP = do
337 reservedOp ":branch"
341 reservedOp ":branch"
338 branchName <- identifier
342 branchName <- identifier
339− return $ Branch branchName
343+ return $ Branch (T.pack branchName)
341commitTransactionP :: Parser GraphOperator
345commitTransactionP :: Parser GraphOperator
342commitTransactionP = do
346commitTransactionP = do
@@ -372,32 +376,32 @@ contextOps = typeP
372interpreterOps :: Parser (Either ContextOperator GraphOperator)
376interpreterOps :: Parser (Either ContextOperator GraphOperator)
373interpreterOps = liftM Left contextOps <|> liftM Right transactionGraphOps
377interpreterOps = liftM Left contextOps <|> liftM Right transactionGraphOps
375−showRelationAttributes :: Relation -> String
379+showRelationAttributes :: Relation -> T.Text
376−showRelationAttributes rel = "{" ++ concat (L.intersperse ", " $ map showAttribute attrs) ++ "}"
380+showRelationAttributes rel = "{" `T.append` T.concat (L.intersperse ", " $ map showAttribute attrs) `T.append` "}"
378− showAttribute (Attribute name atomType) = name ++ " " ++ case atomTypeToTutDType atomType of
382+ showAttribute (Attribute name atomType) = name `T.append` " " `T.append` case atomTypeToTutDType atomType of
379− Just t -> show t
383+ Just t -> T.pack (show t)
380− Nothing -> "unknown"
384+ Nothing -> T.pack "unknown"
381 attrs = V.toList $ attributes rel
385 attrs = V.toList $ attributes rel
383data TutorialDOperatorResult = QuitResult |
387data TutorialDOperatorResult = QuitResult |
384− DisplayResult String |
388+ DisplayResult StringType |
385− DisplayErrorResult String |
389+ DisplayErrorResult StringType |
386 QuietSuccessResult |
390 QuietSuccessResult |
387 NoActionResult --refactor to make this dead- there should be only one parser
391 NoActionResult --refactor to make this dead- there should be only one parser
389evalContextOp :: DatabaseContext -> ContextOperator -> TutorialDOperatorResult
393evalContextOp :: DatabaseContext -> ContextOperator -> TutorialDOperatorResult
390evalContextOp context (ShowRelationType expr) = case runState (typeForRelationalExpr expr) context of
394evalContextOp context (ShowRelationType expr) = case runState (typeForRelationalExpr expr) context of
391 (Right rel, _) -> DisplayResult $ showRelationAttributes rel
395 (Right rel, _) -> DisplayResult $ showRelationAttributes rel
392− (Left err, _) -> DisplayErrorResult $ show err
396+ (Left err, _) -> DisplayErrorResult $ T.pack (show err)
394evalContextOp context (ShowRelation expr) = do
398evalContextOp context (ShowRelation expr) = do
395 case runState (evalRelationalExpr expr) context of
399 case runState (evalRelationalExpr expr) context of
396− (Left err, _) -> DisplayErrorResult $ show err
400+ (Left err, _) -> DisplayErrorResult $ T.pack (show err)
397 (Right rel, _) -> DisplayResult $ showRelation rel
401 (Right rel, _) -> DisplayResult $ showRelation rel
399evalContextOp context (ShowConstraint name) = do
403evalContextOp context (ShowConstraint name) = do
400− DisplayResult $ show filteredDeps
404+ DisplayResult $ T.pack (show filteredDeps)
402 deps = inclusionDependencies context
406 deps = inclusionDependencies context
403 filteredDeps = case name of
407 filteredDeps = case name of
@@ -405,7 +409,7 @@ evalContextOp context (ShowConstraint name) = do
405 name2 -> HS.filter (\(InclusionDependency n _ _) -> n == name2) deps
409 name2 -> HS.filter (\(InclusionDependency n _ _) -> n == name2) deps
407evalContextOp context (ShowPlan dbExpr) = do
411evalContextOp context (ShowPlan dbExpr) = do
408− DisplayResult $ show plan
412+ DisplayResult $ T.pack (show plan)
410 plan = evalState (applyStaticDatabaseOptimization dbExpr) context
414 plan = evalState (applyStaticDatabaseOptimization dbExpr) context
@@ -500,20 +504,20 @@ interpretNO context tutdstring = case parseString tutdstring of
500-- for interpreter-specific operations
504-- for interpreter-specific operations
501interpretOps :: U.UUID -> DisconnectedTransaction -> TransactionGraph -> String -> (DisconnectedTransaction, TransactionGraph, TutorialDOperatorResult)
505interpretOps :: U.UUID -> DisconnectedTransaction -> TransactionGraph -> String -> (DisconnectedTransaction, TransactionGraph, TutorialDOperatorResult)
502interpretOps newUUID trans@(DisconnectedTransaction _ context) transGraph instring = case parse interpreterOps "" instring of
506interpretOps newUUID trans@(DisconnectedTransaction _ context) transGraph instring = case parse interpreterOps "" instring of
503− Left err -> (trans, transGraph, NoActionResult)
507+ Left _ -> (trans, transGraph, NoActionResult)
504 Right ops -> case ops of
508 Right ops -> case ops of
505 Left contextOp -> (trans, transGraph, (evalContextOp context contextOp))
509 Left contextOp -> (trans, transGraph, (evalContextOp context contextOp))
506 Right graphOp -> case evalGraphOp newUUID trans transGraph graphOp of
510 Right graphOp -> case evalGraphOp newUUID trans transGraph graphOp of
507− Left err -> (trans, transGraph, DisplayErrorResult $ show err)
511+ Left err -> (trans, transGraph, DisplayErrorResult $ T.pack (show err))
508 Right (newDiscon, newGraph, result) -> (newDiscon, newGraph, result)
512 Right (newDiscon, newGraph, result) -> (newDiscon, newGraph, result)
510−promptText :: DisconnectedTransaction -> TransactionGraph -> String
514+promptText :: DisconnectedTransaction -> TransactionGraph -> StringType
511−promptText (DisconnectedTransaction parentUUID _) graph = "TutorialD (" ++ transInfo ++ "): "
515+promptText (DisconnectedTransaction parentUUID _) graph = "TutorialD (" `T.append` transInfo `T.append` "): "
513 transInfo = case transactionForUUID parentUUID graph of
517 transInfo = case transactionForUUID parentUUID graph of
514 Left _ -> "unknown"
518 Left _ -> "unknown"
515 Right parentTrans -> case headNameForTransaction parentTrans graph of
519 Right parentTrans -> case headNameForTransaction parentTrans graph of
516− Nothing -> show $ transactionUUID parentTrans
520+ Nothing -> T.pack (show $ transactionUUID parentTrans)
517 Just headName -> headName
521 Just headName -> headName
519reprLoop :: DisconnectedTransaction -> TransactionGraph -> IO ()
523reprLoop :: DisconnectedTransaction -> TransactionGraph -> IO ()
@@ -521,7 +525,7 @@ reprLoop currentTransaction@(DisconnectedTransaction currentParentUUID currentCo
521 homeDirectory <- getHomeDirectory
525 homeDirectory <- getHomeDirectory
522 let settings = defaultSettings {historyFile = Just (homeDirectory ++ "/.tutd_history")}
526 let settings = defaultSettings {historyFile = Just (homeDirectory ++ "/.tutd_history")}
524− maybeLine <- runInputT settings $ getInputLine (promptText currentTransaction graph)
528+ maybeLine <- runInputT settings $ getInputLine (T.unpack (promptText currentTransaction graph))
526 let roloop = reprLoop currentTransaction graph
530 let roloop = reprLoop currentTransaction graph
527 case maybeLine of
531 case maybeLine of
@@ -530,12 +534,12 @@ reprLoop currentTransaction@(DisconnectedTransaction currentParentUUID currentCo
530 newUUID <- nextRandom
534 newUUID <- nextRandom
531 case interpretOps newUUID currentTransaction graph line of
535 case interpretOps newUUID currentTransaction graph line of
532 (_, _, QuitResult) -> return ()
536 (_, _, QuitResult) -> return ()
533− (_, _, DisplayErrorResult err) -> hPutStrLn stderr ("ERR: " ++ err) >> roloop
537+ (_, _, DisplayErrorResult err) -> TIO.hPutStrLn stderr ("ERR: " `T.append` err) >> roloop
534 (updatedTrans, updatedGraph, DisplayResult out) -> do
538 (updatedTrans, updatedGraph, DisplayResult out) -> do
535− putStrLn out
539+ TIO.putStrLn out
536 reprLoop updatedTrans updatedGraph
540 reprLoop updatedTrans updatedGraph
537 (updatedTrans, updatedGraph, QuietSuccessResult) -> do
541 (updatedTrans, updatedGraph, QuietSuccessResult) -> do
538− putStrLn "Done."
542+ TIO.putStrLn "Done."
539 reprLoop updatedTrans updatedGraph
543 reprLoop updatedTrans updatedGraph
540 (_, _, NoActionResult) -> do
544 (_, _, NoActionResult) -> do
541 let (value, contextup) = interpret currentContext line
545 let (value, contextup) = interpret currentContext line
@@ -543,7 +547,7 @@ reprLoop currentTransaction@(DisconnectedTransaction currentParentUUID currentCo
543 case value of
547 case value of
544 Nothing -> reprLoop updatedTransaction graph
548 Nothing -> reprLoop updatedTransaction graph
545 Just err -> do
549 Just err -> do
546− hPutStrLn stderr ("ERR:" ++ show err)
550+ TIO.hPutStrLn stderr ("ERR:" `T.append` T.pack (show err))
547 reprLoop currentTransaction graph
551 reprLoop currentTransaction graph
549restrictionPredicateP :: Parser RestrictionPredicateExpr
553restrictionPredicateP :: Parser RestrictionPredicateExpr
@@ -569,18 +573,19 @@ restrictionAttributeEqualityP = do
569 attributeName <- identifier
573 attributeName <- identifier
570 reservedOp "="
574 reservedOp "="
571 atom <- stringAtomP <|> intAtomP
575 atom <- stringAtomP <|> intAtomP
572− return $ AttributeEqualityPredicate attributeName atom
576+ return $ AttributeEqualityPredicate (T.pack attributeName) atom
574quotedChar = noneOf "\""
578quotedChar = noneOf "\""
575 <|> try (string "\"\"" >> return '"')
579 <|> try (string "\"\"" >> return '"')
577−stringAtomP = liftA StringAtom (string "\"" *> many quotedChar <* string "\"")
581+stringAtomP = liftA (StringAtom . T.pack) (string "\"" *> many quotedChar <* string "\"")
579intAtomP = do
583intAtomP = do
580 intstr <- many digit
584 intstr <- many digit
581 return $ IntAtom (read intstr)
585 return $ IntAtom (read intstr)
583--used by :dumpGraph
587--used by :dumpGraph
584displayTransactionGraph :: TransactionGraph -> String
589displayTransactionGraph :: TransactionGraph -> String
585displayTransactionGraph (TransactionGraph _ transSet) = L.intercalate "\n" $ S.foldr (\(Transaction tUUID pUUID _ ) acc -> acc ++ [show tUUID ++ " " ++ show pUUID]) [] transSet
590displayTransactionGraph (TransactionGraph _ transSet) = L.intercalate "\n" $ S.foldr (\(Transaction tUUID pUUID _ ) acc -> acc ++ [show tUUID ++ " " ++ show pUUID]) [] transSet