@@ -1,661 +1,83 @@
1{-# LANGUAGE GADTs,OverloadedStrings #-}
1{-# LANGUAGE GADTs,OverloadedStrings #-}
2module TutorialD.Interpreter where
2module TutorialD.Interpreter where
3+import TutorialD.Interpreter.Base
4+import TutorialD.Interpreter.RODatabaseContextOperator
5+import TutorialD.Interpreter.DatabaseExpr
6+import TutorialD.Interpreter.TransactionGraphOperator
3import ProjectM36.Base
7import ProjectM36.Base
4−import ProjectM36.Relation
5−import ProjectM36.Tuple
6−import ProjectM36.TupleSet
7−import ProjectM36.Error
8−import qualified ProjectM36.Attribute as A
9−import ProjectM36.RelationalExpression
10−import ProjectM36.Relation.Show.Term
11−import ProjectM36.StaticOptimizer
12import ProjectM36.Transaction
8import ProjectM36.Transaction
13−import ProjectM36.Transaction.Show
14−import ProjectM36.Atom
15import Text.Parsec
9import Text.Parsec
16import Text.Parsec.String
10import Text.Parsec.String
17−import Text.Parsec.Expr
18−import Text.Parsec.Language
19−import qualified Text.Parsec.Token as Token
20−import qualified Data.Set as S
21−import qualified Data.HashSet as HS
22−import qualified Data.Map as M
23−import qualified Data.List as L
24−import Control.Applicative (liftA, (<*), (*>), (<$>))
25import Control.Monad.State
11import Control.Monad.State
26import System.Console.Haskeline
12import System.Console.Haskeline
27import System.IO
13import System.IO
28import System.Directory (getHomeDirectory)
14import System.Directory (getHomeDirectory)
29import qualified Data.UUID as U
15import qualified Data.UUID as U
30import Data.UUID.V4 (nextRandom)
16import Data.UUID.V4 (nextRandom)
31−import qualified Data.Vector as V
32import qualified Data.Text as T
17import qualified Data.Text as T
33import qualified Data.Text.IO as TIO
18import qualified Data.Text.IO as TIO
19+import Control.Applicative ((<*))
36−List of Tutorial D operators:
22+context ops are read-only operations which only operate on the database context (relvars and constraints)
37−show relation expression type :: relexpr -> context -> opresult
23+database ops are read-write operations which change the database context (such as relvar assignment)
38−show relvar :: relvar name -> context -> opresult
24+graph ops are read-write operations which change the transaction graph
40−show graph :: graph -> DisconnectedTransaction -> opresult
41−show constraints :: context -> opresult
42−jump to head :: head name -> graph -> DisconnectedTransaction (graph unchanged)
43−jump to UUID :: uuid -> graph -> DisconnectedTransaction (graph unchanged)
44−branch :: uuid -> branch name -> graph -> (DisconnectedTransation, graph)
45−commit :: uuid -> DisconnectedTransaction -> graph -> (DisconnectedTransaction, graph)
46−rollback :: DisconnectedTransaction -> graph -> (DisconnectedTransaction, graph)
50−lexer :: Token.TokenParser ()
51−lexer = Token.makeTokenParser tutD
52− where tutD = emptyDef {
53− Token.reservedOpNames = ["join", "where", "union", "group", "ungroup"],
54− Token.reservedNames = [],
55− Token.identStart = letter <|> char '_',
56− Token.opLetter = oneOf ":!#$%&*+./<=>?\\^|-~", -- remove "@" so it can be used as attribute marker without spaces
57− Token.identLetter = alphaNum <|> char '_' <|> char '#'} -- # needed for Date examples
59−parens = Token.parens lexer
60−reservedOp = Token.reservedOp lexer
61−reserved = Token.reserved lexer
62−braces = Token.braces lexer
63−identifier = Token.identifier lexer
64−comma = Token.comma lexer
65−semi = Token.semi lexer
67−uuidP :: Parser U.UUID
69− uuidStr <- many (alphaNum <|> char '-')
70− case U.fromString uuidStr of
71− Nothing -> fail "Invalid uuid string"
72− Just uuid -> return uuid
75−attributeList :: Parser [AttributeName]
77− attrs <- sepBy identifier comma
78− return $ map T.pack attrs
80−makeRelation :: Parser RelationalExpr
82− reservedOp "relation"
83− attrs <- (try makeAttributes <|> return A.emptyAttributes)
84− if not (A.null attrs) then do
85− return $ MakeStaticRelation attrs emptyTupleSet
87− tuples <- braces (sepBy tupleP comma)
88− return $ MakeStaticRelation (tupleAttributes (head tuples)) (HS.fromList tuples)
90−--used in relation creation
91−makeAttributes :: Parser Attributes
93− attrList <- braces (sepBy attributeAndType comma)
94− return $ A.attributesFromList attrList
96−attributeAndType :: Parser Attribute
98− attrName <- identifier
99− attrTypeName <- identifier
100− --convert type name into type
101− case tutDTypeToAtomType attrTypeName of
102− Just t -> return $ Attribute (T.pack attrName) t
103− Nothing -> fail (attrTypeName ++ " is not a valid type name.")
105−tupleP :: Parser RelationTuple
108− attrAssocs <- braces (sepBy tupleAtomP comma)
109− let attrs = A.attributesFromList $ map (\(attrName, atom) -> Attribute attrName (atomTypeForAtom atom)) attrAssocs
110− let atoms = V.fromList $ map snd attrAssocs
111− return $ mkRelationTuple attrs atoms
113−tupleAtomP :: Parser (AttributeName, Atom)
115− attributeName <- identifier
116− attrType <- identifier
117− atom <- parens (stringAtomP <|> intAtomP)
118− case tutDTypeToAtomType attrType of
119− Nothing -> fail (attrType ++ " is not a valid type name.")
120− Just typeA -> if typeA == atomTypeForAtom atom then
121− return $ (T.pack attributeName, atom)
123− fail "type mismatch in tuple generation"
125−--convert Tutorial D type to AtomType
126−tutDTypeToAtomType :: String -> Maybe AtomType
127−tutDTypeToAtomType tutDType = case tutDType of
128− "char" -> Just StringAtomType
129− "int" -> Just IntAtomType
132−atomTypeToTutDType :: AtomType -> Maybe T.Text
133−atomTypeToTutDType atomType = case atomType of
134− StringAtomType -> Just "char"
135− IntAtomType -> Just "int"
136− RelationAtomType attrs -> Just $ "relation" `T.append` showRelationAttributes attrs
139−relVarP :: Parser RelationalExpr
140−relVarP = liftA (RelationVariable . T.pack) identifier
142−relTerm = parens relExpr
147− attrs <- braces attributeList
148− return $ Project (S.fromList attrs)
150−assignP :: Parser DatabaseExpr
152− relVarName <- try $ do
153− relVarName <- identifier
157− return $ Assign (T.pack relVarName) expr
160− oldAttr <- identifier
162− newAttr <- identifier
163− return $ (oldAttr, newAttr)
165−renameP :: Parser (RelationalExpr -> RelationalExpr)
168− (oldAttr, newAttr) <- braces renameClause
169− return $ Rename (T.pack oldAttr) (T.pack newAttr)
173− boolExpr <- restrictionPredicateP
174− return $ Restrict boolExpr
177− attrs <- braces attributeList
179− newAttrName <- identifier
180− return $ (attrs, newAttrName)
182−groupP :: Parser (RelationalExpr -> RelationalExpr)
185− (groupAttrList, groupAttrName) <- parens groupClause
186− return $ Group (S.fromList groupAttrList) (T.pack groupAttrName)
188−--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.
189−ungroupP :: Parser (RelationalExpr -> RelationalExpr)
191− reservedOp "ungroup"
192− rvaAttrName <- identifier
193− return $ Ungroup (T.pack rvaAttrName)
195−extendP :: Parser (RelationalExpr -> RelationalExpr)
198− tupleExpr <- braces tupleExpressionP
199− return $ Extend tupleExpr
202−rewrite summarize as extend as evaluate
204−summarize SP per (SP{SNO}) add (sum(@QTY) as SUMQ) === ((SP rename {QTY as _}) group ({_} as x)) : {QTY:=sum(@x)}{S#,QTY}
206−summarize rX per (relExpr) add (func(@attr) as funcd) === ((rX rename {attr as _}) group ({_} as _)) : {QTY:=sum(@_)}{relExpr, _}
209−summarizeP :: Parser (RelationalExpr -> RelationalExpr)
212− -- "summarize in Tutorial D requires the heading of the per relation to be a subset of that of the relation to be summarized"
213− perExpr <- parens relExpr
215− (funcAtomExpr, newAttrName) <- parens summaryP
216− --rewrite summarize as extend
217− --return $ Summarize funcAtomExpr newAttrName perExpr
219−summaryP :: Parser (AtomExpr, AttributeName)
223− attrName <- identifier
224− return (expr, T.pack attrName)
228− [Postfix projectOp],
230− [Postfix whereClauseP],
233− [Infix (reservedOp "join" >> return Join) AssocLeft],
234− [Infix (reservedOp "union" >> return Union) AssocLeft],
235− [Infix (reservedOp "=" >> return Equals) AssocNone],
239−relExpr :: Parser RelationalExpr
240−relExpr = buildExpressionParser relOperators relTerm
242−databaseExpr :: Parser DatabaseExpr
243−databaseExpr = insertP
251−multipleDatabaseExpr :: Parser DatabaseExpr
252−multipleDatabaseExpr = do
253− exprs <- sepBy1 databaseExpr semi
254− return $ MultipleExpr exprs
256−insertP :: Parser DatabaseExpr
259− relvar <- identifier
261− return $ Insert (T.pack relvar) expr
263−defineP :: Parser DatabaseExpr
265− relVarName <- try $ do
266− relVarName <- identifier
269− attributeSet <- makeAttributes
270− return $ Define (T.pack relVarName) attributeSet
272−undefineP :: Parser DatabaseExpr
274− reservedOp "undefine"
275− relVarName <- identifier
276− return $ Undefine (T.pack relVarName)
278−deleteP :: Parser DatabaseExpr
281− relVarName <- identifier
282− predicate <- option TruePredicate (reservedOp "where" *> restrictionPredicateP)
283− return $ Delete (T.pack relVarName) predicate
285−updateP :: Parser DatabaseExpr
288− relVarName <- identifier
289− predicate <- option TruePredicate (reservedOp "where" *> restrictionPredicateP <* spaces)
290− attributeAssignments <- liftM M.fromList $ parens (sepBy attributeAssignment comma)
291− return $ Update (T.pack relVarName) (M.mapKeys T.pack $ attributeAssignments) predicate
293−constraintP :: Parser DatabaseExpr
295− reservedOp "constraint"
296− constraintName <- identifier
300− return $ AddInclusionDependency (InclusionDependency (T.pack constraintName) subset superset)
302−attributeAssignment :: Parser (String, Atom)
303−attributeAssignment = do
304− attrName <- identifier
306− atom <- stringAtomP <|> intAtomP
307− return $ (attrName, atom)
309−parseString :: String -> Either RelationalError DatabaseExpr
310−parseString str = case parse (multipleDatabaseExpr <* eof) "" str of
311− Left err -> Left $ ParseError (T.pack (show err))
314−--operators which only rely on database context reading
315−data ContextOperator where
316− ShowRelation :: RelationalExpr -> ContextOperator
317− ShowRelationType :: RelationalExpr -> ContextOperator
318− ShowConstraint :: StringType -> ContextOperator
319− ShowPlan :: DatabaseExpr -> ContextOperator
320− Quit :: ContextOperator
323−--operators which manipulate a transaction graph
324−data GraphOperator where
325− JumpToHead :: HeadName -> GraphOperator
326− JumpToTransaction :: U.UUID -> GraphOperator
327− Branch :: HeadName -> GraphOperator
328− Commit :: GraphOperator
329− Rollback :: GraphOperator
330− ShowGraph :: GraphOperator
332−typeP :: Parser ContextOperator
336− return $ ShowRelationType expr
338−showRelP :: Parser ContextOperator
340− reservedOp ":showexpr"
342− return $ ShowRelation expr
344−showPlanP :: Parser ContextOperator
346− reservedOp ":showplan"
347− expr <- databaseExpr
348− return $ ShowPlan expr
350−quitP :: Parser ContextOperator
355−showConstraintsP :: Parser ContextOperator
356−showConstraintsP = do
357− reservedOp ":constraints"
358− constraintName <- option "" identifier
359− return $ ShowConstraint (T.pack constraintName)
361−jumpToHeadP :: Parser GraphOperator
363− reservedOp ":jumphead"
364− headid <- identifier
365− return $ JumpToHead (T.pack headid)
367−jumpToTransactionP :: Parser GraphOperator
368−jumpToTransactionP = do
371− return $ JumpToTransaction uuid
373−branchTransactionP :: Parser GraphOperator
374−branchTransactionP = do
375− reservedOp ":branch"
376− branchName <- identifier
377− return $ Branch (T.pack branchName)
379−commitTransactionP :: Parser GraphOperator
380−commitTransactionP = do
381− reservedOp ":commit"
384−rollbackTransactionP :: Parser GraphOperator
385−rollbackTransactionP = do
386− reservedOp ":rollback"
389−showGraphP :: Parser GraphOperator
391− reservedOp ":showgraph"
394−transactionGraphOps :: Parser GraphOperator
395−transactionGraphOps = do
397− <|> jumpToTransactionP
398− <|> branchTransactionP
399− <|> commitTransactionP
400− <|> rollbackTransactionP
403−contextOps :: Parser ContextOperator
406− <|> showConstraintsP
410−interpreterOps :: Parser (Either ContextOperator GraphOperator)
411−interpreterOps = liftM Left contextOps <|> liftM Right transactionGraphOps
413−showRelationAttributes :: Attributes -> T.Text
414−showRelationAttributes attrs = "{" `T.append` T.concat (L.intersperse ", " $ map showAttribute attrsL) `T.append` "}"
416− showAttribute (Attribute name atomType) = name `T.append` " " `T.append` case atomTypeToTutDType atomType of
418− Nothing -> "unknown"
419− attrsL = V.toList attrs
421−data TutorialDOperatorResult = QuitResult |
422− DisplayResult StringType |
423− DisplayErrorResult StringType |
424− QuietSuccessResult |
425− NoActionResult --refactor to make this dead- there should be only one parser
427−evalContextOp :: DatabaseContext -> ContextOperator -> TutorialDOperatorResult
428−evalContextOp context (ShowRelationType expr) = case runState (typeForRelationalExpr expr) context of
429− (Right rel, _) -> DisplayResult $ showRelationAttributes (attributes rel)
430− (Left err, _) -> DisplayErrorResult $ T.pack (show err)
432−evalContextOp context (ShowRelation expr) = do
433− case runState (evalRelationalExpr expr) context of
434− (Left err, _) -> DisplayErrorResult $ T.pack (show err)
435− (Right rel, _) -> DisplayResult $ showRelation rel
437−evalContextOp context (ShowConstraint name) = do
438− DisplayResult $ T.pack (show filteredDeps)
440− deps = inclusionDependencies context
441− filteredDeps = case name of
443− name2 -> HS.filter (\(InclusionDependency n _ _) -> n == name2) deps
445−evalContextOp context (ShowPlan dbExpr) = do
446− DisplayResult $ T.pack (show plan)
448− plan = evalState (applyStaticDatabaseOptimization dbExpr) context
450−evalContextOp _ (Quit) = QuitResult
452−-- returns the new "current" transaction, updated graph, and tutorial d result
453−-- the current transaction is not part of the transaction graph until it is committed
454−evalGraphOp :: U.UUID -> DisconnectedTransaction -> TransactionGraph -> GraphOperator -> Either RelationalError (DisconnectedTransaction, TransactionGraph, TutorialDOperatorResult)
456−--affects only disconncted transaction
457−evalGraphOp _ _ graph (JumpToTransaction jumpUUID) = case transactionForUUID jumpUUID graph of
458− Left err -> Left err
459− Right parentTrans -> Right (newTrans, graph, QuietSuccessResult)
461− newTrans = DisconnectedTransaction jumpUUID (transactionContext parentTrans)
463−-- switch from one head to another
464−-- affects only disconnectedtransaction
465−evalGraphOp _ _ graph (JumpToHead headName) =
466− case transactionForHead headName graph of
467− Just newHeadTransaction -> let disconnectedTrans = newDisconnectedTransaction (transactionUUID newHeadTransaction) (transactionContext newHeadTransaction) in
468− Right (disconnectedTrans, graph, QuietSuccessResult)
469− Nothing -> Left $ NoSuchHeadNameError headName
470−-- add new head pointing to branchPoint
471−-- repoint the disconnected transaction to the new branch commit (with a potentially different disconnected context)
472−-- affects transactiongraph and the disconnectedtransaction is recreated based off the branch
474−evalGraphOp newUUID discon@(DisconnectedTransaction parentUUID disconContext) graph (Branch newBranchName) = case transactionForUUID parentUUID graph of
475− Nothing -> (discon, graph, DisplayErrorResult "Failed to find parent transaction.")
476− Just parentTrans -> case addBranch newBranchName parentTrans graph of
477− Nothing -> (discon, graph, DisplayErrorResult "Failed to add branch.")
478− Just newGraph -> (newDiscon, newGraph, DisplayResult "Branched.")
480− newDiscon = DisconnectedTransaction (transactionUUID parentTrans) disconContext
482−
26+data ParsedOperation = RODatabaseContextOp RODatabaseContextOperator |
483−-- create a new commit and add it to the heads
27+ DatabaseExprOp DatabaseExpr |
484−-- technically, the new head could be added to an existing commit, but by adding a new commit, the new head is unambiguously linked to a new commit (with a context indentical to its parent)
28+ GraphOp TransactionGraphOperator
485−evalGraphOp newUUID (DisconnectedTransaction parentUUID disconContext) graph (Branch newBranchName) = case transactionForUUID parentUUID graph of
486− Left err -> Left err
487− Right parentTrans -> case addBranch newUUID newBranchName parentTrans graph of
488− Left err -> Left err
489− Right (_, newGraph) -> Right (newDiscon, newGraph, QuietSuccessResult)
491− newDiscon = DisconnectedTransaction newUUID disconContext
493−-- add the disconnected transaction to the graph
30+interpreterParserP :: Parser ParsedOperation
494−-- affects graph and disconnectedtransaction- the new disconnectedtransaction's parent is the freshly committed transaction
31+interpreterParserP = liftM RODatabaseContextOp (roDatabaseContextOperatorP <* eof) <|>
495−evalGraphOp newTransUUID discon@(DisconnectedTransaction parentUUID context) graph Commit = case transactionForUUID parentUUID graph of
32+ liftM GraphOp (transactionGraphOpP <* eof) <|>
496− Left err -> Left err
33+ liftM DatabaseExprOp (databaseExprOpP <* eof)
497− Right parentTransaction -> case headNameForTransaction parentTransaction graph of
498− Nothing -> Left $ TransactionIsNotAHeadError parentUUID
499− Just headName -> case maybeUpdatedGraph of
501− Right (_, updatedGraph) -> Right (newDisconnectedTrans, updatedGraph, QuietSuccessResult)
503− newDisconnectedTrans = newDisconnectedTransaction newTransUUID context
504− maybeUpdatedGraph = addDisconnectedTransaction newTransUUID headName discon graph
506−-- refresh the disconnected transaction, return the same graph
507−evalGraphOp _ (DisconnectedTransaction parentUUID _) graph Rollback = case transactionForUUID parentUUID graph of
508− Left err -> Left err
509− Right parentTransaction -> Right (newDiscon, graph, QuietSuccessResult)
511− newDiscon = newDisconnectedTransaction parentUUID (transactionContext parentTransaction)
513−--display transaction graph as relation
514−evalGraphOp _ discon graph ShowGraph = do
515− graphStr <- graphAsRelation discon graph
516− return (discon, graph, DisplayResult $ showRelation graphStr)
518−--shouldn't this be Either RelationalError DatabaseContext?
519−interpret :: DatabaseContext -> String -> (Maybe RelationalError, DatabaseContext)
520−interpret context tutdstring = case parseString tutdstring of
521− Left err -> (Just err, context)
522− Right parsed -> runState (evaluator parsed) context
525− optExpr <- applyStaticDatabaseOptimization expr
528− Left err -> return $ Just err
529− Right optExprA -> evalContextExpr optExprA
532−interpretNO :: DatabaseContext -> String -> (Maybe RelationalError, DatabaseContext)
533−interpretNO context tutdstring = case parseString tutdstring of
534− Left err -> (Just err, context)
535− Right parsed -> runState (evalContextExpr parsed) context
537−-- for interpreter-specific operations
538−interpretOps :: U.UUID -> DisconnectedTransaction -> TransactionGraph -> String -> (DisconnectedTransaction, TransactionGraph, TutorialDOperatorResult)
539−interpretOps newUUID trans@(DisconnectedTransaction _ context) transGraph instring = case parse interpreterOps "" instring of
540− Left _ -> (trans, transGraph, NoActionResult)
541− Right ops -> case ops of
542− Left contextOp -> (trans, transGraph, (evalContextOp context contextOp))
543− Right graphOp -> case evalGraphOp newUUID trans transGraph graphOp of
544− Left err -> (trans, transGraph, DisplayErrorResult $ T.pack (show err))
545− Right (newDiscon, newGraph, result) -> (newDiscon, newGraph, result)
547promptText :: DisconnectedTransaction -> TransactionGraph -> StringType
35promptText :: DisconnectedTransaction -> TransactionGraph -> StringType
548promptText (DisconnectedTransaction parentUUID _) graph = "TutorialD (" `T.append` transInfo `T.append` "): "
36promptText (DisconnectedTransaction parentUUID _) graph = "TutorialD (" `T.append` transInfo `T.append` "): "
550− transInfo = case transactionForUUID parentUUID graph of
38+ transInfo = case transactionForUUID parentUUID graph of
551 Left _ -> "unknown"
39 Left _ -> "unknown"
552 Right parentTrans -> case headNameForTransaction parentTrans graph of
40 Right parentTrans -> case headNameForTransaction parentTrans graph of
553 Nothing -> T.pack (show $ transactionUUID parentTrans)
41 Nothing -> T.pack (show $ transactionUUID parentTrans)
554 Just headName -> headName
42 Just headName -> headName
44+interpret :: U.UUID -> DisconnectedTransaction -> TransactionGraph -> String -> (TutorialDOperatorResult, DisconnectedTransaction, TransactionGraph)
45+interpret freshUUID discon@(DisconnectedTransaction parentUUID context) graph inputString = case parse interpreterParserP "" inputString of
46+ Left err -> (DisplayErrorResult (T.pack $ show err), discon, graph)
47+ Right (RODatabaseContextOp execOp) -> (evalRODatabaseContextOp context execOp, discon, graph)
48+ Right (DatabaseExprOp execOp) -> case evalDatabaseExpr True context execOp of
49+ Left err -> (DisplayErrorResult $ T.pack (show err), discon, graph)
50+ Right context' -> (QuietSuccessResult, DisconnectedTransaction parentUUID context', graph)
51+ Right (GraphOp execOp) -> case evalGraphOp freshUUID discon graph execOp of
52+ Left err -> (DisplayErrorResult $ T.pack (show err), discon, graph)
53+ Right (discon', graph', result') -> (result', discon', graph')
556reprLoop :: DisconnectedTransaction -> TransactionGraph -> IO ()
57reprLoop :: DisconnectedTransaction -> TransactionGraph -> IO ()
557−reprLoop currentTransaction@(DisconnectedTransaction currentParentUUID currentContext) graph = do
58+reprLoop currentTransaction graph = do
558 homeDirectory <- getHomeDirectory
59 homeDirectory <- getHomeDirectory
559 let settings = defaultSettings {historyFile = Just (homeDirectory ++ "/.tutd_history")}
60 let settings = defaultSettings {historyFile = Just (homeDirectory ++ "/.tutd_history")}
561 maybeLine <- runInputT settings $ getInputLine (T.unpack (promptText currentTransaction graph))
62 maybeLine <- runInputT settings $ getInputLine (T.unpack (promptText currentTransaction graph))
563 let roloop = reprLoop currentTransaction graph
64 let roloop = reprLoop currentTransaction graph
564 case maybeLine of
65 case maybeLine of
565 Nothing -> return ()
66 Nothing -> return ()
566− Just line -> do
67+ Just line -> do
567 newUUID <- nextRandom
68 newUUID <- nextRandom
568− case interpretOps newUUID currentTransaction graph line of
69+ case interpret newUUID currentTransaction graph line of
569− (_, _, QuitResult) -> return ()
70+ (QuitResult, _, _) -> return ()
570− (_, _, DisplayErrorResult err) -> TIO.hPutStrLn stderr ("ERR: " `T.append` err) >> roloop
71+ (DisplayErrorResult err, _, _) -> TIO.hPutStrLn stderr ("ERR: " `T.append` err) >> roloop
571− (updatedTrans, updatedGraph, DisplayResult out) -> do
72+ (DisplayResult out, updatedTrans, updatedGraph) -> do
572 TIO.putStrLn out
73 TIO.putStrLn out
573 reprLoop updatedTrans updatedGraph
74 reprLoop updatedTrans updatedGraph
574− (updatedTrans, updatedGraph, QuietSuccessResult) -> do
75+ (QuietSuccessResult, updatedTrans, updatedGraph) -> do
575 TIO.putStrLn "Done."
76 TIO.putStrLn "Done."
576 reprLoop updatedTrans updatedGraph
77 reprLoop updatedTrans updatedGraph
577− (_, _, NoActionResult) -> do
578− let (value, contextup) = interpret currentContext line
579− let updatedTransaction = DisconnectedTransaction currentParentUUID contextup
581− Nothing -> reprLoop updatedTransaction graph
583− TIO.hPutStrLn stderr ("ERR:" `T.append` T.pack (show err))
584− reprLoop currentTransaction graph
586−restrictionPredicateP :: Parser RestrictionPredicateExpr
587−restrictionPredicateP = buildExpressionParser predicateOperators predicateTerm
589− predicateOperators = [
590− [Prefix (reservedOp "not" >> return NotPredicate)],
591− [Infix (reservedOp "and" >> return AndPredicate) AssocLeft],
592− [Infix (reservedOp "or" >> return OrPredicate) AssocLeft]
594− predicateTerm = parens restrictionPredicateP
595− <|> try restrictionAttributeEqualityP
596− <|> try relationalBooleanExpr
599−relationalBooleanExpr :: Parser RestrictionPredicateExpr
600−relationalBooleanExpr = do
602− return $ RelationalExprPredicate relexpr
604−restrictionAttributeEqualityP :: Parser RestrictionPredicateExpr
605−restrictionAttributeEqualityP = do
606− attributeName <- identifier
608− atomexpr <- atomExprP
609− return $ AttributeEqualityPredicate (T.pack attributeName) atomexpr
611−quotedChar = noneOf "\""
612− <|> try (string "\"\"" >> return '"')
614−stringAtomP = liftA (StringAtom . T.pack) (string "\"" *> many quotedChar <* string "\"")
617− intstr <- many1 digit
618− return $ IntAtom (read intstr)
620--used by :dumpGraph
79--used by :dumpGraph
622displayTransactionGraph :: TransactionGraph -> String
81displayTransactionGraph :: TransactionGraph -> String
623displayTransactionGraph (TransactionGraph _ transSet) = L.intercalate "\n" $ S.foldr (\(Transaction tUUID pUUID _ ) acc -> acc ++ [show tUUID ++ " " ++ show pUUID]) [] transSet
82displayTransactionGraph (TransactionGraph _ transSet) = L.intercalate "\n" $ S.foldr (\(Transaction tUUID pUUID _ ) acc -> acc ++ [show tUUID ++ " " ++ show pUUID]) [] transSet
626−multiTupleExpressionP :: Parser [TupleExpr]
627−multiTupleExpressionP = sepBy tupleExpressionP comma
629−tupleExpressionP :: Parser TupleExpr
630−tupleExpressionP = attributeTupleExpressionP
632−attributeTupleExpressionP :: Parser TupleExpr
633−attributeTupleExpressionP = do
634− newAttr <- identifier
637− return $ AttributeTupleExpr (T.pack newAttr) atom
639−atomExprP :: Parser AtomExpr
640−atomExprP = try functionAtomExprP <|>
641− attributeAtomExprP <|>
645−attributeAtomExprP :: Parser AtomExpr
646−attributeAtomExprP = do
648− attrName <- identifier
649− return $ AttributeAtomExpr (T.pack attrName)
651−nakedAtomExprP :: Parser AtomExpr
652−nakedAtomExprP = NakedAtomExpr <$> (stringAtomP <|> intAtomP)
654−functionAtomExprP :: Parser AtomExpr
655−functionAtomExprP = do
656− funcName <- identifier
657− argList <- parens (sepBy atomExprP comma)
658− return $ FunctionAtomExpr (T.pack funcName) argList
660−relationalAtomExprP :: Parser AtomExpr
661−relationalAtomExprP = RelationAtomExpr <$> relExpr