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