on master help sign in
refactor RelationalExpr to allow for TransGraphRelationalExpr
commit61548c9bf3cdc03113f0ed1eb4b85ae1195d0f2b authorAgentM <agentm@themactionfaction.com> dateTue 6 Sep 2016, 22:16 (10 years ago) parent20a004d
2 files changed+47−284
src/bin/TutorialD/Interpreter/RelationalExpr.hs+44−43 src/bin/TutorialD/Interpreter/TransGraphRelationalOperator.hs+3−241
src/bin/TutorialD/Interpreter/RelationalExpr.hs+44−43
@@ -12,6 +12,12 @@ import Data.List (sort)
1212import Control.Applicative (liftA)
1313import ProjectM36.MiscUtils
1414
15+class RelationalMarkerExpr a where
16+ parseMarkerP :: Parser a
17+
18+instance RelationalMarkerExpr () where
19+ parseMarkerP = pure ()
20+
1521--used in projection
1622attributeListP :: Parser AttributeNames
1723attributeListP = do
@@ -20,23 +26,19 @@ attributeListP = do
2026 attrs <- sepBy identifier comma
2127 pure $ constructor (S.fromList attrs)
2228
23−makeRelationP :: Parser RelationalExpr
29+makeRelationP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
2430makeRelationP = do
2531 reserved "relation"
2632 attrExprs <- try (liftA Just makeAttributeExprsP) <|> pure Nothing
2733 tupleExprs <- braces (sepBy tupleExprP comma) <|> pure []
28− pure $ MakeRelationFromExprs attrExprs tupleExprs
34+ pure $ MakeRelationFromExprs attrExprs tupleExprs
2935
3036--used in relation creation
31−makeAttributeExprsP :: Parser [AttributeExpr]
37+makeAttributeExprsP :: RelationalMarkerExpr a => Parser [AttributeExprBase a]
3238makeAttributeExprsP = braces (sepBy attributeAndTypeNameP comma)
3339
34−attributeAndTypeNameP :: Parser AttributeExpr
35−attributeAndTypeNameP = do
36− attrName <- identifier
37− --convert type name into type
38− typeCons <- typeConstructorP
39− return $ AttributeAndTypeNameExpr attrName typeCons ()
40+attributeAndTypeNameP :: RelationalMarkerExpr a => Parser (AttributeExprBase a)
41+attributeAndTypeNameP = AttributeAndTypeNameExpr <$> identifier <*> typeConstructorP <*> parseMarkerP
4042
4143--abstract data type parser- in this context, the type constructor must not include any type arguments
4244--Either Text Int
@@ -46,7 +48,7 @@ adTypeConstructorP = do
4648 tConsArgs <- many typeConstructorArgP
4749 pure $ ADTypeConstructor tConsName tConsArgs
4850
49−tupleExprP :: Parser TupleExpr
51+tupleExprP :: RelationalMarkerExpr a => Parser (TupleExprBase a)
5052tupleExprP = do
5153 reservedOp "tuple"
5254 attrAssocs <- braces (sepBy tupleAtomExprP comma)
@@ -57,13 +59,13 @@ tupleExprP = do
5759 else
5860 pure (TupleExpr (M.fromList attrAssocs))
5961
60−tupleAtomExprP :: Parser (AttributeName, AtomExpr)
62+tupleAtomExprP :: RelationalMarkerExpr a => Parser (AttributeName, AtomExprBase a)
6163tupleAtomExprP = do
6264 attributeName <- identifier
6365 atomExpr <- atomExprP
6466 pure $ (attributeName, atomExpr)
6567
66−projectP :: Parser (RelationalExpr -> RelationalExpr)
68+projectP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
6769projectP = do
6870 attrs <- braces attributeListP
6971 pure $ Project attrs
@@ -75,17 +77,14 @@ renameClauseP = do
7577 newAttr <- identifier
7678 pure $ (oldAttr, newAttr)
7779
78−renameP :: Parser (RelationalExpr -> RelationalExpr)
80+renameP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
7981renameP = do
8082 reservedOp "rename"
8183 (oldAttr, newAttr) <- braces renameClauseP
8284 return $ Rename oldAttr newAttr
8385
84−whereClauseP :: Parser (RelationalExpr -> RelationalExpr)
85−whereClauseP = do
86− reservedOp "where"
87− boolExpr <- restrictionPredicateP
88− return $ Restrict boolExpr
86+whereClauseP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
87+whereClauseP = reservedOp "where" *> (Restrict <$> restrictionPredicateP)
8988
9089groupClauseP :: Parser (AttributeNames, T.Text)
9190groupClauseP = do
@@ -94,26 +93,26 @@ groupClauseP = do
9493 newAttrName <- identifier
9594 return $ (attrs, newAttrName)
9695
97−groupP :: Parser (RelationalExpr -> RelationalExpr)
96+groupP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
9897groupP = do
9998 reservedOp "group"
10099 (groupAttrList, groupAttrName) <- parens groupClauseP
101100 pure $ Group groupAttrList groupAttrName
102101
103102--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.
104−ungroupP :: Parser (RelationalExpr -> RelationalExpr)
103+ungroupP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
105104ungroupP = do
106105 reservedOp "ungroup"
107106 rvaAttrName <- identifier
108107 pure $ Ungroup rvaAttrName
109108
110−extendP :: Parser (RelationalExpr -> RelationalExpr)
109+extendP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
111110extendP = do
112111 reservedOp ":"
113112 tupleExpr <- braces extendTupleExpressionP
114113 return $ Extend tupleExpr
115114
116−relOperators :: [[Operator Parser RelationalExpr]]
115+relOperators :: RelationalMarkerExpr a => [[Operator Parser (RelationalExprBase a)]]
117116relOperators = [
118117 [Postfix projectP],
119118 [Postfix renameP],
@@ -127,18 +126,18 @@ relOperators = [
127126 [Postfix extendP]
128127 ]
129128
130−relExprP :: Parser RelationalExpr
129+relExprP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
131130relExprP = makeExprParser relTerm relOperators
132131
133−relVarP :: Parser RelationalExpr
134−relVarP = RelationVariable <$> identifier <*> pure ()
132+relVarP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
133+relVarP = RelationVariable <$> identifier <*> parseMarkerP
135134
136−relTerm :: Parser RelationalExpr
135+relTerm :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
137136relTerm = parens relExprP
138137 <|> makeRelationP
139138 <|> relVarP
140139
141−restrictionPredicateP :: Parser RestrictionPredicateExpr
140+restrictionPredicateP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
142141restrictionPredicateP = makeExprParser predicateTerm predicateOperators
143142 where
144143 predicateOperators = [
@@ -152,40 +151,40 @@ restrictionPredicateP = makeExprParser predicateTerm predicateOperators
152151 <|> try relationalBooleanExprP
153152
154153
155−relationalBooleanExprP :: Parser RestrictionPredicateExpr
154+relationalBooleanExprP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
156155relationalBooleanExprP = do
157156 relexpr <- relExprP
158157 return $ RelationalExprPredicate relexpr
159158
160−restrictionAttributeEqualityP :: Parser RestrictionPredicateExpr
159+restrictionAttributeEqualityP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
161160restrictionAttributeEqualityP = do
162161 attributeName <- identifier
163162 reservedOp "="
164163 atomexpr <- atomExprP
165164 return $ AttributeEqualityPredicate attributeName atomexpr
166165
167−restrictionAtomExprP :: Parser RestrictionPredicateExpr --atoms which are of type "boolean"
166+restrictionAtomExprP :: RelationalMarkerExpr a=> Parser (RestrictionPredicateExprBase a) --atoms which are of type "boolean"
168167restrictionAtomExprP = do
169168 _ <- char '^' -- not ideal, but allows me to continue to use a context-free grammar
170169 AtomExprPredicate <$> atomExprP
171170
172−multiTupleExpressionP :: Parser [ExtendTupleExpr]
171+multiTupleExpressionP :: RelationalMarkerExpr a => Parser [ExtendTupleExprBase a]
173172multiTupleExpressionP = sepBy extendTupleExpressionP comma
174173
175−extendTupleExpressionP :: Parser ExtendTupleExpr
174+extendTupleExpressionP :: RelationalMarkerExpr a => Parser (ExtendTupleExprBase a)
176175extendTupleExpressionP = attributeExtendTupleExpressionP
177176
178−attributeExtendTupleExpressionP :: Parser ExtendTupleExpr
177+attributeExtendTupleExpressionP :: RelationalMarkerExpr a => Parser (ExtendTupleExprBase a)
179178attributeExtendTupleExpressionP = do
180179 newAttr <- identifier
181180 reservedOp ":="
182181 atom <- atomExprP
183182 return $ AttributeExtendTupleExpr newAttr atom
184183
185−atomExprP :: Parser AtomExpr
184+atomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
186185atomExprP = consumeAtomExprP True
187186
188−consumeAtomExprP :: Bool -> Parser AtomExpr
187+consumeAtomExprP :: RelationalMarkerExpr a => Bool -> Parser (AtomExprBase a)
189188consumeAtomExprP consume = try functionAtomExprP <|>
190189 try (parens (constructedAtomExprP True)) <|>
191190 constructedAtomExprP consume <|>
@@ -193,20 +192,21 @@ consumeAtomExprP consume = try functionAtomExprP <|>
193192 nakedAtomExprP <|>
194193 relationalAtomExprP
195194
196−attributeAtomExprP :: Parser AtomExpr
195+attributeAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
197196attributeAtomExprP = do
198197 _ <- string "@"
199198 attrName <- identifier
200199 return $ AttributeAtomExpr attrName
201200
202−nakedAtomExprP :: Parser AtomExpr
201+nakedAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
203202nakedAtomExprP = NakedAtomExpr <$> atomP
204203
205−constructedAtomExprP :: Bool -> Parser AtomExpr
204+constructedAtomExprP :: RelationalMarkerExpr a => Bool -> Parser (AtomExprBase a)
206205constructedAtomExprP consume = do
207206 dConsName <- capitalizedIdentifier
208207 dConsArgs <- if consume then sepBy (consumeAtomExprP False) spaceConsumer else pure []
209− pure $ ConstructedAtomExpr dConsName dConsArgs ()
208+ marker <- parseMarkerP
209+ pure $ ConstructedAtomExpr dConsName dConsArgs marker
210210
211211-- used only for primitive type parsing ?
212212atomP :: Parser Atom
@@ -215,13 +215,14 @@ atomP = stringAtomP <|>
215215 intAtomP <|>
216216 boolAtomP
217217
218−functionAtomExprP :: Parser AtomExpr
218+functionAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
219219functionAtomExprP = do
220220 funcName <- identifier
221221 argList <- parens (sepBy atomExprP comma)
222− return $ FunctionAtomExpr funcName argList ()
222+ marker <- parseMarkerP
223+ return $ FunctionAtomExpr funcName argList marker
223224
224−relationalAtomExprP :: Parser AtomExpr
225+relationalAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
225226relationalAtomExprP = RelationAtomExpr <$> relExprP
226227
227228stringAtomP :: Parser Atom
@@ -240,5 +241,5 @@ boolAtomP = do
240241 val <- char 't' <|> char 'f'
241242 return $ BoolAtom (val == 't')
242243
243−relationAtomExprP :: Parser AtomExpr
244+relationAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
244245relationAtomExprP = RelationAtomExpr <$> makeRelationP
src/bin/TutorialD/Interpreter/TransGraphRelationalOperator.hs+3−241
@@ -1,30 +1,18 @@
11{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
2+{-# OPTIONS_GHC -fno-warn-orphans #-}
23module TutorialD.Interpreter.TransGraphRelationalOperator where
3−import ProjectM36.Base
44import ProjectM36.TransGraphRelationalExpression
55import ProjectM36.TransactionGraph
6−import ProjectM36.MiscUtils
76import qualified ProjectM36.Client as C
87
98import TutorialD.Interpreter.Base
10−import TutorialD.Interpreter.Types
9+import TutorialD.Interpreter.RelationalExpr
1110
1211import Text.Megaparsec
1312import Text.Megaparsec.Text
14−import Text.Megaparsec.Expr
1513
16−import Control.Applicative
17−import qualified Data.Set as S
18−import qualified Data.Map as M
1914import qualified Data.Text as T
20−import Data.List (sort)
2115
22−class RelationalMarkerExpr a where
23− parseMarkerP :: Parser a
24−
25−instance RelationalMarkerExpr () where
26− parseMarkerP = pure ()
27−
2816instance RelationalMarkerExpr TransactionIdLookup where
2917 parseMarkerP = string "@" *> transactionIdLookupP
3018
@@ -40,233 +28,7 @@ transGraphRelationalOpP = showTransGraphRelationalOpP
4028showTransGraphRelationalOpP :: Parser TransGraphRelationalOperator
4129showTransGraphRelationalOpP = do
4230 reservedOp ":showtransgraphexpr"
43− ShowTransGraphRelation <$> relExprP
44−
45−--used in projection
46−attributeListP :: Parser AttributeNames
47−attributeListP = do
48− but <- try (string "all but " <* spaceConsumer) <|> string ""
49− let constructor = if but == "" then AttributeNames else InvertedAttributeNames
50− attrs <- sepBy identifier comma
51− pure $ constructor (S.fromList attrs)
52−
53−makeRelationP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
54−makeRelationP = do
55− reserved "relation"
56− attrExprs <- try (liftA Just makeAttributeExprsP) <|> pure Nothing
57− tupleExprs <- braces (sepBy tupleExprP comma) <|> pure []
58− pure $ MakeRelationFromExprs attrExprs tupleExprs
59−
60−--used in relation creation
61−makeAttributeExprsP :: RelationalMarkerExpr a => Parser [AttributeExprBase a]
62−makeAttributeExprsP = braces (sepBy attributeAndTypeNameP comma)
63−
64−attributeAndTypeNameP :: RelationalMarkerExpr a => Parser (AttributeExprBase a)
65−attributeAndTypeNameP = AttributeAndTypeNameExpr <$> identifier <*> typeConstructorP <*> parseMarkerP
66−
67−--abstract data type parser- in this context, the type constructor must not include any type arguments
68−--Either Text Int
69−adTypeConstructorP :: Parser TypeConstructor
70−adTypeConstructorP = do
71− tConsName <- capitalizedIdentifier
72− tConsArgs <- many typeConstructorArgP
73− pure $ ADTypeConstructor tConsName tConsArgs
74−
75−tupleExprP :: RelationalMarkerExpr a => Parser (TupleExprBase a)
76−tupleExprP = do
77− reservedOp "tuple"
78− attrAssocs <- braces (sepBy tupleAtomExprP comma)
79− --detect duplicate attribute names
80− let dupAttrNames = dupes (sort (map fst attrAssocs))
81− if length dupAttrNames /= 0 then
82− fail ("Attribute names duplicated: " ++ show dupAttrNames)
83− else
84− pure (TupleExpr (M.fromList attrAssocs))
85−
86−tupleAtomExprP :: RelationalMarkerExpr a => Parser (AttributeName, AtomExprBase a)
87−tupleAtomExprP = do
88− attributeName <- identifier
89− atomExpr <- atomExprP
90− pure $ (attributeName, atomExpr)
91−
92−projectP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
93−projectP = do
94− attrs <- braces attributeListP
95− pure $ Project attrs
96−
97−renameClauseP :: Parser (T.Text, T.Text)
98−renameClauseP = do
99− oldAttr <- identifier
100− reservedOp "as"
101− newAttr <- identifier
102− pure $ (oldAttr, newAttr)
103−
104−renameP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
105−renameP = do
106− reservedOp "rename"
107− (oldAttr, newAttr) <- braces renameClauseP
108− return $ Rename oldAttr newAttr
109−
110−whereClauseP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
111−whereClauseP = reservedOp "where" *> (Restrict <$> restrictionPredicateP)
112−
113−groupClauseP :: Parser (AttributeNames, T.Text)
114−groupClauseP = do
115− attrs <- braces attributeListP
116− reservedOp "as"
117− newAttrName <- identifier
118− return $ (attrs, newAttrName)
119−
120−groupP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
121−groupP = do
122− reservedOp "group"
123− (groupAttrList, groupAttrName) <- parens groupClauseP
124− pure $ Group groupAttrList groupAttrName
125−
126−--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.
127−ungroupP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
128−ungroupP = do
129− reservedOp "ungroup"
130− rvaAttrName <- identifier
131− pure $ Ungroup rvaAttrName
132−
133−extendP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
134−extendP = do
135− reservedOp ":"
136− tupleExpr <- braces extendTupleExpressionP
137− return $ Extend tupleExpr
138−
139−relOperators :: RelationalMarkerExpr a => [[Operator Parser (RelationalExprBase a)]]
140−relOperators = [
141− [Postfix projectP],
142− [Postfix renameP],
143− [Postfix whereClauseP],
144− [Postfix groupP],
145− [Postfix ungroupP],
146− [InfixL (reservedOp "join" >> return Join)],
147− [InfixL (reservedOp "union" >> return Union)],
148− [InfixL (reservedOp "minus" >> return Difference)],
149− [InfixN (reservedOp "=" >> return Equals)],
150− [Postfix extendP]
151− ]
152−
153−relExprP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
154−relExprP = makeExprParser relTerm relOperators
155−
156−relVarP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
157−relVarP = RelationVariable <$> identifier <*> parseMarkerP
158−
159−relTerm :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
160−relTerm = parens relExprP
161− <|> makeRelationP
162− <|> relVarP
163−
164−restrictionPredicateP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
165−restrictionPredicateP = makeExprParser predicateTerm predicateOperators
166− where
167− predicateOperators = [
168− [Prefix (reservedOp "not" >> return NotPredicate)],
169− [InfixL (reservedOp "and" >> return AndPredicate)],
170− [InfixL (reservedOp "or" >> return OrPredicate)]
171− ]
172− predicateTerm = parens restrictionPredicateP
173− <|> try restrictionAtomExprP
174− <|> try restrictionAttributeEqualityP
175− <|> try relationalBooleanExprP
176−
177−
178−relationalBooleanExprP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
179−relationalBooleanExprP = do
180− relexpr <- relExprP
181− return $ RelationalExprPredicate relexpr
182−
183−restrictionAttributeEqualityP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
184−restrictionAttributeEqualityP = do
185− attributeName <- identifier
186− reservedOp "="
187− atomexpr <- atomExprP
188− return $ AttributeEqualityPredicate attributeName atomexpr
189−
190−restrictionAtomExprP :: RelationalMarkerExpr a=> Parser (RestrictionPredicateExprBase a) --atoms which are of type "boolean"
191−restrictionAtomExprP = do
192− _ <- char '^' -- not ideal, but allows me to continue to use a context-free grammar
193− AtomExprPredicate <$> atomExprP
194−
195−multiTupleExpressionP :: RelationalMarkerExpr a => Parser [ExtendTupleExprBase a]
196−multiTupleExpressionP = sepBy extendTupleExpressionP comma
197−
198−extendTupleExpressionP :: RelationalMarkerExpr a => Parser (ExtendTupleExprBase a)
199−extendTupleExpressionP = attributeExtendTupleExpressionP
200−
201−attributeExtendTupleExpressionP :: RelationalMarkerExpr a => Parser (ExtendTupleExprBase a)
202−attributeExtendTupleExpressionP = do
203− newAttr <- identifier
204− reservedOp ":="
205− atom <- atomExprP
206− return $ AttributeExtendTupleExpr newAttr atom
207−
208−atomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
209−atomExprP = consumeAtomExprP True
210−
211−consumeAtomExprP :: RelationalMarkerExpr a => Bool -> Parser (AtomExprBase a)
212−consumeAtomExprP consume = try functionAtomExprP <|>
213− try (parens (constructedAtomExprP True)) <|>
214− constructedAtomExprP consume <|>
215− attributeAtomExprP <|>
216− nakedAtomExprP <|>
217− relationalAtomExprP
218−
219−attributeAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
220−attributeAtomExprP = do
221− _ <- string "@"
222− attrName <- identifier
223− return $ AttributeAtomExpr attrName
224−
225−nakedAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
226−nakedAtomExprP = NakedAtomExpr <$> atomP
227−
228−constructedAtomExprP :: RelationalMarkerExpr a => Bool -> Parser (AtomExprBase a)
229−constructedAtomExprP consume = do
230− dConsName <- capitalizedIdentifier
231− dConsArgs <- if consume then sepBy (consumeAtomExprP False) spaceConsumer else pure []
232− marker <- parseMarkerP
233− pure $ ConstructedAtomExpr dConsName dConsArgs marker
234−
235−-- used only for primitive type parsing ?
236−atomP :: Parser Atom
237−atomP = stringAtomP <|>
238− doubleAtomP <|>
239− intAtomP <|>
240− boolAtomP
241−
242−functionAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
243−functionAtomExprP = do
244− funcName <- identifier
245− argList <- parens (sepBy atomExprP comma)
246− marker <- parseMarkerP
247− return $ FunctionAtomExpr funcName argList marker
248−
249−relationalAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
250−relationalAtomExprP = RelationAtomExpr <$> relExprP
251−
252−stringAtomP :: Parser Atom
253−stringAtomP = liftA TextAtom quotedString
254−
255−doubleAtomP :: Parser Atom
256−doubleAtomP = DoubleAtom <$> (try float)
257−
258−intAtomP :: Parser Atom
259−intAtomP = do
260− i <- integer
261− return $ IntAtom (fromIntegral i)
262−
263−boolAtomP :: Parser Atom
264−boolAtomP = do
265− val <- char 't' <|> char 'f'
266− return $ BoolAtom (val == 't')
267−
268−relationAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
269−relationAtomExprP = RelationAtomExpr <$> makeRelationP
31+ ShowTransGraphRelation <$> relExprP
27032
27133evalTransGraphRelationalOp :: C.SessionId -> C.Connection -> TransGraphRelationalOperator -> IO TutorialDOperatorResult
27234evalTransGraphRelationalOp sessionId conn (ShowTransGraphRelation expr) = do