@@ -25,7 +25,7 @@ use crate::{
25
25
BinaryOp , EntityType , ExpressionConstructionError , Literal , Name , Pattern , SlotId , UnaryOp ,
26
26
Unknown , Var ,
27
27
} ,
28
- parser:: { cst, cst_to_ast :: construct_exprs_extended_has , Loc } ,
28
+ parser:: { cst, Loc } ,
29
29
} ;
30
30
31
31
#[ cfg( feature = "tolerant-ast" ) ]
@@ -183,7 +183,49 @@ pub trait ExprBuilder: Clone {
183
183
/// Create an `Expr` which tests for the existence of a given
184
184
/// non-empty list of attributes on a given `Entity` or record.
185
185
fn extended_has_attr ( self , expr : Self :: Expr , attrs : & NonEmpty < SmolStr > ) -> Self :: Expr {
186
- construct_exprs_extended_has :: < Self > ( expr, attrs, None )
186
+ let ( first, rest) = attrs. split_first ( ) ;
187
+ let has_expr = Self :: new ( )
188
+ . with_maybe_source_loc ( self . loc ( ) )
189
+ . has_attr ( expr. clone ( ) , first. to_owned ( ) ) ;
190
+ let get_expr = Self :: new ( )
191
+ . with_maybe_source_loc ( self . loc ( ) )
192
+ . get_attr ( expr, first. to_owned ( ) ) ;
193
+ // Foldl on the attribute list
194
+ // It produces the following for `principal has contactInfo.address.zip`
195
+ // Expr.and
196
+ // (Expr.and
197
+ // (Expr.hasAttr (Expr.var .principal) "contactInfo")
198
+ // (Expr.hasAttr
199
+ // (Expr.getAttr (Expr.var .principal) "contactInfo")
200
+ // "address"))
201
+ // (Expr.hasAttr
202
+ // (Expr.getAttr
203
+ // (Expr.getAttr (Expr.var .principal) "contactInfo")
204
+ // "address")
205
+ // "zip")
206
+ // This is sound. However, the evaluator has to recur multiple times to the
207
+ // left-most node to evaluate the existence of the first attribute. The
208
+ // desugared expression should be the following to avoid the issue above,
209
+ // Expr.and
210
+ // Expr.hasAttr (Expr.var .principal) "contactInfo"
211
+ // (Expr.and
212
+ // (Expr.hasAttr (Expr.getAttr (Expr.var .principal) "contactInfo")"address")
213
+ // (Expr.hasAttr ..., "zip"))
214
+ rest. iter ( )
215
+ . fold ( ( has_expr, get_expr) , |( has_expr, get_expr) , attr| {
216
+ (
217
+ Self :: new ( ) . with_maybe_source_loc ( self . loc ( ) ) . and (
218
+ has_expr,
219
+ Self :: new ( )
220
+ . with_maybe_source_loc ( self . loc ( ) )
221
+ . has_attr ( get_expr. clone ( ) , attr. to_owned ( ) ) ,
222
+ ) ,
223
+ Self :: new ( )
224
+ . with_maybe_source_loc ( self . loc ( ) )
225
+ . get_attr ( get_expr, attr. to_owned ( ) ) ,
226
+ )
227
+ } )
228
+ . 0
187
229
}
188
230
189
231
/// Create a 'like' expression.
0 commit comments