1
1
use crate :: ast:: * ;
2
2
use partiql_common:: pretty:: {
3
- pretty_list, pretty_parenthesized_doc, pretty_prefixed_doc, pretty_seperated ,
4
- pretty_seperated_doc, pretty_seq, pretty_seq_doc, PrettyDoc , PRETTY_INDENT_MINOR_NEST ,
5
- PRETTY_INDENT_SUBORDINATE_CLAUSE_NEST ,
3
+ pretty_bracketed_doc , pretty_list, pretty_parenthesized_doc, pretty_prefixed_doc,
4
+ pretty_seperated , pretty_seperated_doc, pretty_seq, pretty_seq_doc, pretty_surrounded_doc ,
5
+ PrettyDoc , PRETTY_INDENT_MINOR_NEST , PRETTY_INDENT_SUBORDINATE_CLAUSE_NEST ,
6
6
} ;
7
7
use pretty:: { DocAllocator , DocBuilder } ;
8
+ use std:: borrow:: Cow ;
8
9
impl < T > PrettyDoc for AstNode < T >
9
10
where
10
11
T : PrettyDoc ,
@@ -316,9 +317,8 @@ impl PrettyDoc for Expr {
316
317
Expr :: Sexp ( inner) => inner. pretty_doc ( arena) ,
317
318
Expr :: Path ( inner) => inner. pretty_doc ( arena) ,
318
319
Expr :: Call ( inner) => inner. pretty_doc ( arena) ,
319
-
320
320
Expr :: CallAgg ( inner) => inner. pretty_doc ( arena) ,
321
-
321
+ Expr :: GraphMatch ( inner ) => inner . pretty_doc ( arena ) ,
322
322
Expr :: Query ( inner) => {
323
323
let inner = inner. pretty_doc ( arena) . group ( ) ;
324
324
arena
@@ -329,9 +329,6 @@ impl PrettyDoc for Expr {
329
329
Expr :: Error => {
330
330
unreachable ! ( ) ;
331
331
}
332
- Expr :: GraphMatch ( _inner) => {
333
- todo ! ( "inner.pretty_doc(arena)" )
334
- }
335
332
}
336
333
. group ( )
337
334
}
@@ -1000,6 +997,238 @@ impl PrettyDoc for Join {
1000
997
}
1001
998
}
1002
999
1000
+ impl PrettyDoc for GraphMatch {
1001
+ fn pretty_doc < ' b , D , A > ( & ' b self , arena : & ' b D ) -> DocBuilder < ' b , D , A >
1002
+ where
1003
+ D : DocAllocator < ' b , A > ,
1004
+ D :: Doc : Clone ,
1005
+ A : Clone ,
1006
+ {
1007
+ let head = arena. intersperse (
1008
+ [ self . expr . pretty_doc ( arena) , arena. text ( "MATCH" ) ] ,
1009
+ arena. space ( ) ,
1010
+ ) ;
1011
+ let patterns = self . graph_expr . pretty_doc ( arena) ;
1012
+ let match_expr = arena. intersperse ( [ head, patterns] , arena. space ( ) ) ;
1013
+
1014
+ let parens_needed = self . graph_expr . node . patterns . len ( ) > 1 ;
1015
+ if parens_needed {
1016
+ pretty_parenthesized_doc ( match_expr, arena)
1017
+ } else {
1018
+ match_expr
1019
+ }
1020
+ }
1021
+ }
1022
+
1023
+ impl PrettyDoc for GraphMatchExpr {
1024
+ fn pretty_doc < ' b , D , A > ( & ' b self , arena : & ' b D ) -> DocBuilder < ' b , D , A >
1025
+ where
1026
+ D : DocAllocator < ' b , A > ,
1027
+ D :: Doc : Clone ,
1028
+ A : Clone ,
1029
+ {
1030
+ let selector = self . selector . clone ( ) . map ( |s| {
1031
+ let parts: Vec < Cow < ' _ , str > > = match s {
1032
+ GraphMatchSelector :: AnyShortest => vec ! [ "ANY" . into( ) , "SHORTEST" . into( ) ] ,
1033
+ GraphMatchSelector :: AllShortest => vec ! [ "ALL" . into( ) , "SHORTEST" . into( ) ] ,
1034
+ GraphMatchSelector :: Any => vec ! [ "ANY" . into( ) ] ,
1035
+ GraphMatchSelector :: AnyK ( k) => vec ! [ "ANY" . into( ) , k. to_string( ) . into( ) ] ,
1036
+ GraphMatchSelector :: ShortestK ( k) => vec ! [ "SHORTEST" . into( ) , k. to_string( ) . into( ) ] ,
1037
+ GraphMatchSelector :: ShortestKGroup ( k) => {
1038
+ vec ! [ "SHORTEST" . into( ) , k. to_string( ) . into( ) , "GROUP" . into( ) ]
1039
+ }
1040
+ } ;
1041
+
1042
+ arena. intersperse ( parts, arena. space ( ) ) . group ( )
1043
+ } ) ;
1044
+ let patterns = pretty_list ( & self . patterns , PRETTY_INDENT_MINOR_NEST , arena) ;
1045
+ if let Some ( selector) = selector {
1046
+ arena. intersperse ( [ selector, patterns] , arena. softline ( ) )
1047
+ } else {
1048
+ patterns
1049
+ }
1050
+ . group ( )
1051
+ }
1052
+ }
1053
+
1054
+ impl PrettyDoc for GraphMatchPattern {
1055
+ fn pretty_doc < ' b , D , A > ( & ' b self , arena : & ' b D ) -> DocBuilder < ' b , D , A >
1056
+ where
1057
+ D : DocAllocator < ' b , A > ,
1058
+ D :: Doc : Clone ,
1059
+ A : Clone ,
1060
+ {
1061
+ let pattern = pretty_seperated (
1062
+ arena. nil ( ) . append ( arena. space ( ) ) ,
1063
+ & self . parts ,
1064
+ PRETTY_INDENT_MINOR_NEST ,
1065
+ arena,
1066
+ ) ;
1067
+ let mut doc = if let Some ( r) = & self . restrictor {
1068
+ match r {
1069
+ GraphMatchRestrictor :: Trail => arena. text ( "TRAIL" ) ,
1070
+ GraphMatchRestrictor :: Acyclic => arena. text ( "ACYCLIC" ) ,
1071
+ GraphMatchRestrictor :: Simple => arena. text ( "SIMPLE" ) ,
1072
+ }
1073
+ . append ( arena. space ( ) )
1074
+ } else {
1075
+ arena. nil ( )
1076
+ } ;
1077
+
1078
+ let pattern = if let Some ( v) = & self . variable {
1079
+ arena. intersperse (
1080
+ [ arena. text ( & v. value ) , arena. text ( "=" ) , pattern] ,
1081
+ arena. space ( ) ,
1082
+ )
1083
+ } else {
1084
+ pattern
1085
+ } ;
1086
+ doc = doc. append ( pattern) ;
1087
+
1088
+ let brackets =
1089
+ self . restrictor . is_some ( ) || self . quantifier . is_some ( ) || self . prefilter . is_some ( ) ;
1090
+
1091
+ if brackets {
1092
+ let doc = if let Some ( filter) = & self . prefilter {
1093
+ arena. intersperse (
1094
+ [ doc, arena. text ( "WHERE" ) , filter. pretty_doc ( arena) ] ,
1095
+ arena. space ( ) ,
1096
+ )
1097
+ } else {
1098
+ doc
1099
+ } ;
1100
+ let bracketed = pretty_bracketed_doc ( doc, arena) ;
1101
+ if let Some ( postfix) = & self . quantifier {
1102
+ arena. concat ( [ bracketed, postfix. pretty_doc ( arena) ] )
1103
+ } else {
1104
+ bracketed
1105
+ }
1106
+ } else {
1107
+ doc
1108
+ }
1109
+ . group ( )
1110
+ }
1111
+ }
1112
+
1113
+ impl PrettyDoc for GraphMatchPatternPart {
1114
+ fn pretty_doc < ' b , D , A > ( & ' b self , arena : & ' b D ) -> DocBuilder < ' b , D , A >
1115
+ where
1116
+ D : DocAllocator < ' b , A > ,
1117
+ D :: Doc : Clone ,
1118
+ A : Clone ,
1119
+ {
1120
+ match self {
1121
+ GraphMatchPatternPart :: Node ( n) => n. pretty_doc ( arena) ,
1122
+ GraphMatchPatternPart :: Edge ( e) => e. pretty_doc ( arena) ,
1123
+ GraphMatchPatternPart :: Pattern ( p) => p. pretty_doc ( arena) ,
1124
+ }
1125
+ }
1126
+ }
1127
+
1128
+ impl PrettyDoc for GraphMatchNode {
1129
+ fn pretty_doc < ' b , D , A > ( & ' b self , arena : & ' b D ) -> DocBuilder < ' b , D , A >
1130
+ where
1131
+ D : DocAllocator < ' b , A > ,
1132
+ D :: Doc : Clone ,
1133
+ A : Clone ,
1134
+ {
1135
+ let mut spec = arena. nil ( ) ;
1136
+ if let Some ( r) = & self . variable {
1137
+ spec = spec. append ( arena. text ( & r. value ) ) ;
1138
+ }
1139
+ if let Some ( l) = & self . label {
1140
+ debug_assert_eq ! ( l. len( ) , 1 ) ; // TODO
1141
+ spec = spec. append ( arena. text ( ":" ) ) . append ( arena. text ( & l[ 0 ] . value ) ) ;
1142
+ }
1143
+ if let Some ( r) = & self . prefilter {
1144
+ let parts = [ spec, arena. text ( "WHERE" ) , r. pretty_doc ( arena) ] ;
1145
+ spec = arena. intersperse ( parts, arena. space ( ) ) . into ( ) ;
1146
+ }
1147
+ pretty_surrounded_doc ( spec, "(" , ")" , arena)
1148
+ }
1149
+ }
1150
+
1151
+ impl PrettyDoc for GraphMatchEdge {
1152
+ fn pretty_doc < ' b , D , A > ( & ' b self , arena : & ' b D ) -> DocBuilder < ' b , D , A >
1153
+ where
1154
+ D : DocAllocator < ' b , A > ,
1155
+ D :: Doc : Clone ,
1156
+ A : Clone ,
1157
+ {
1158
+ let mut spec = None ;
1159
+ if let Some ( r) = & self . variable {
1160
+ spec = spec
1161
+ . unwrap_or_else ( || arena. nil ( ) )
1162
+ . append ( arena. text ( & r. value ) )
1163
+ . into ( ) ;
1164
+ }
1165
+ if let Some ( l) = & self . label {
1166
+ debug_assert_eq ! ( l. len( ) , 1 ) ; // TODO
1167
+ spec = spec
1168
+ . unwrap_or_else ( || arena. nil ( ) )
1169
+ . append ( arena. text ( ":" ) )
1170
+ . append ( arena. text ( & l[ 0 ] . value ) )
1171
+ . into ( ) ;
1172
+ }
1173
+ if let Some ( r) = & self . prefilter {
1174
+ let parts = [
1175
+ spec. unwrap_or_else ( || arena. nil ( ) ) ,
1176
+ arena. text ( "WHERE" ) ,
1177
+ r. pretty_doc ( arena) ,
1178
+ ] ;
1179
+ spec = arena. intersperse ( parts, arena. space ( ) ) . into ( ) ;
1180
+ }
1181
+
1182
+ let mut edge = if let Some ( spec) = spec {
1183
+ let ( prefix, suffix) = match self . direction {
1184
+ GraphMatchDirection :: Right => ( "-[" , "]->" ) ,
1185
+ GraphMatchDirection :: Left => ( "<-[" , "]-" ) ,
1186
+ GraphMatchDirection :: Undirected => ( "~[" , "]~" ) ,
1187
+ GraphMatchDirection :: UndirectedOrRight => ( "~[" , "]~>" ) ,
1188
+ GraphMatchDirection :: LeftOrUndirected => ( "<~[" , "]~" ) ,
1189
+ GraphMatchDirection :: LeftOrRight => ( "<-[" , "]->" ) ,
1190
+ GraphMatchDirection :: LeftOrUndirectedOrRight => ( "-[" , "]-" ) ,
1191
+ } ;
1192
+ pretty_surrounded_doc ( spec, prefix, suffix, arena)
1193
+ } else {
1194
+ let edge = match self . direction {
1195
+ GraphMatchDirection :: Right => "->" ,
1196
+ GraphMatchDirection :: Left => "<-" ,
1197
+ GraphMatchDirection :: Undirected => "~" ,
1198
+ GraphMatchDirection :: UndirectedOrRight => "~>" ,
1199
+ GraphMatchDirection :: LeftOrUndirected => "<~" ,
1200
+ GraphMatchDirection :: LeftOrRight => "<->" ,
1201
+ GraphMatchDirection :: LeftOrUndirectedOrRight => "-" ,
1202
+ } ;
1203
+ arena. text ( edge)
1204
+ } ;
1205
+ if let Some ( q) = & self . quantifier {
1206
+ edge = arena. concat ( [ edge, q. pretty_doc ( arena) ] ) ;
1207
+ }
1208
+ edge. group ( )
1209
+ }
1210
+ }
1211
+
1212
+ impl PrettyDoc for GraphMatchQuantifier {
1213
+ fn pretty_doc < ' b , D , A > ( & ' b self , arena : & ' b D ) -> DocBuilder < ' b , D , A >
1214
+ where
1215
+ D : DocAllocator < ' b , A > ,
1216
+ D :: Doc : Clone ,
1217
+ A : Clone ,
1218
+ {
1219
+ let GraphMatchQuantifier { lower, upper } = & self ;
1220
+ match ( lower, upper) {
1221
+ ( 0 , None ) => arena. text ( "*" ) ,
1222
+ ( 1 , None ) => arena. text ( "+" ) ,
1223
+ ( l, u) => {
1224
+ let l = Cow :: Owned ( l. to_string ( ) ) ;
1225
+ let u = u. map ( |u| Cow :: Owned ( u. to_string ( ) ) ) . unwrap_or ( "" . into ( ) ) ;
1226
+ pretty_surrounded_doc ( arena. concat ( [ l, "," . into ( ) , u] ) , "{" , "}" , arena)
1227
+ }
1228
+ }
1229
+ }
1230
+ }
1231
+
1003
1232
impl PrettyDoc for Let {
1004
1233
fn pretty_doc < ' b , D , A > ( & ' b self , _arena : & ' b D ) -> DocBuilder < ' b , D , A >
1005
1234
where
0 commit comments