@@ -63,12 +63,9 @@ export class Z3ExpressionTransformer {
6363
6464 /**
6565 * Transforms the given expression to a TypeScript expression.
66- * @param normalizeUndefined if undefined values should be normalized to null
6766 * @returns
6867 */
69- transform ( expr : Expression , normalizeUndefined = true ) : string {
70- // let assertion = '';
71- // let checkStrings: Record<string, string> = {};
68+ transform ( expr : Expression ) : string {
7269 switch ( expr . $type ) {
7370 case StringLiteral :
7471 case NumberLiteral :
@@ -78,7 +75,7 @@ export class Z3ExpressionTransformer {
7875 return this . boolean ( expr as BooleanLiteral ) ;
7976
8077 case ArrayExpr :
81- return this . array ( expr as ArrayExpr , normalizeUndefined ) ;
78+ return this . array ( expr as ArrayExpr ) ;
8279
8380 case NullExpr :
8481 return this . null ( ) ;
@@ -90,17 +87,17 @@ export class Z3ExpressionTransformer {
9087 return this . reference ( expr as ReferenceExpr ) ;
9188
9289 case InvocationExpr :
93- return this . invocation ( expr as InvocationExpr , normalizeUndefined ) ;
90+ return this . invocation ( expr as InvocationExpr ) ;
9491
9592 case MemberAccessExpr :
96- return this . memberAccess ( expr as MemberAccessExpr , normalizeUndefined ) ;
93+ return this . memberAccess ( expr as MemberAccessExpr ) ;
9794
9895 case UnaryExpr :
99- return this . unary ( expr as UnaryExpr , normalizeUndefined ) ;
96+ return this . unary ( expr as UnaryExpr ) ;
10097
10198 case BinaryExpr :
10299 // eslint-disable-next-line no-case-declarations
103- const assertion = this . binary ( expr as BinaryExpr , normalizeUndefined ) ;
100+ const assertion = this . binary ( expr as BinaryExpr ) ;
104101 if ( [ '&&' , '||' ] . includes ( expr . operator ) ) return assertion ;
105102 // eslint-disable-next-line no-case-declarations
106103 const checkString =
@@ -124,7 +121,7 @@ export class Z3ExpressionTransformer {
124121 return this . options . thisExprContext ?? 'input' ;
125122 }
126123
127- private memberAccess ( expr : MemberAccessExpr , normalizeUndefined : boolean ) {
124+ private memberAccess ( expr : MemberAccessExpr ) {
128125 if ( ! expr . member . ref ) {
129126 throw new Z3ExpressionTransformerError ( `Unresolved MemberAccessExpr` ) ;
130127 }
@@ -137,16 +134,11 @@ export class Z3ExpressionTransformer {
137134 }
138135 return expr . member . ref . name ;
139136 } else {
140- if ( normalizeUndefined ) {
141- // normalize field access to null instead of undefined to avoid accidentally use undefined in filter
142- return `(${ this . transform ( expr . operand , normalizeUndefined ) } ?.${ expr . member . ref . name } ?? null)` ;
143- } else {
144- return `${ this . transform ( expr . operand , normalizeUndefined ) } ?.${ expr . member . ref . name } ` ;
145- }
137+ return `${ this . transform ( expr . operand ) } ?.${ expr . member . ref . name } ` ;
146138 }
147139 }
148140
149- private invocation ( expr : InvocationExpr , normalizeUndefined : boolean ) {
141+ private invocation ( expr : InvocationExpr ) {
150142 if ( ! expr . function . ref ) {
151143 throw new Z3ExpressionTransformerError ( `Unresolved InvocationExpr` ) ;
152144 }
@@ -164,7 +156,7 @@ export class Z3ExpressionTransformer {
164156 }
165157
166158 const args = expr . args . map ( ( arg ) => arg . value ) ;
167- return handler . value . call ( this , args , normalizeUndefined ) ;
159+ return handler . value . call ( this , args ) ;
168160 }
169161
170162 // #region function invocation handlers
@@ -183,7 +175,7 @@ export class Z3ExpressionTransformer {
183175
184176 @func ( 'length' )
185177 private _length ( args : Expression [ ] ) {
186- const field = this . transform ( args [ 0 ] , false ) ; // TODO: false for inverse here?
178+ const field = this . transform ( args [ 0 ] ) ;
187179 const min = getLiteral < number > ( args [ 1 ] ) ;
188180 const max = getLiteral < number > ( args [ 2 ] ) ;
189181 let result : string ;
@@ -198,81 +190,81 @@ export class Z3ExpressionTransformer {
198190 }
199191
200192 @func ( 'contains' )
201- private _contains ( args : Expression [ ] , normalizeUndefined : boolean ) {
202- const field = this . transform ( args [ 0 ] , false ) ;
193+ private _contains ( args : Expression [ ] ) {
194+ const field = this . transform ( args [ 0 ] ) ;
203195 const caseInsensitive = getLiteral < boolean > ( args [ 2 ] ) === true ;
204196 let result : string ;
205197 if ( caseInsensitive ) {
206- result = `${ field } ?.toLowerCase().includes(${ this . transform ( args [ 1 ] , normalizeUndefined ) } ?.toLowerCase())` ;
198+ result = `${ field } ?.toLowerCase().includes(${ this . transform ( args [ 1 ] ) } ?.toLowerCase())` ;
207199 } else {
208- result = `${ field } ?.includes(${ this . transform ( args [ 1 ] , normalizeUndefined ) } )` ;
200+ result = `${ field } ?.includes(${ this . transform ( args [ 1 ] ) } )` ;
209201 }
210202 return this . ensureBoolean ( result ) ;
211203 }
212204
213205 @func ( 'startsWith' )
214- private _startsWith ( args : Expression [ ] , normalizeUndefined : boolean ) {
215- const field = this . transform ( args [ 0 ] , false ) ;
216- const result = `${ field } ?.startsWith(${ this . transform ( args [ 1 ] , normalizeUndefined ) } )` ;
206+ private _startsWith ( args : Expression [ ] ) {
207+ const field = this . transform ( args [ 0 ] ) ;
208+ const result = `${ field } ?.startsWith(${ this . transform ( args [ 1 ] ) } )` ;
217209 return this . ensureBoolean ( result ) ;
218210 }
219211
220212 @func ( 'endsWith' )
221- private _endsWith ( args : Expression [ ] , normalizeUndefined : boolean ) {
222- const field = this . transform ( args [ 0 ] , false ) ;
223- const result = `${ field } ?.endsWith(${ this . transform ( args [ 1 ] , normalizeUndefined ) } )` ;
213+ private _endsWith ( args : Expression [ ] ) {
214+ const field = this . transform ( args [ 0 ] ) ;
215+ const result = `${ field } ?.endsWith(${ this . transform ( args [ 1 ] ) } )` ;
224216 return this . ensureBoolean ( result ) ;
225217 }
226218
227219 @func ( 'regex' )
228220 private _regex ( args : Expression [ ] ) {
229- const field = this . transform ( args [ 0 ] , false ) ;
221+ const field = this . transform ( args [ 0 ] ) ;
230222 const pattern = getLiteral < string > ( args [ 1 ] ) ;
231223 return `new RegExp(${ JSON . stringify ( pattern ) } ).test(${ field } )` ;
232224 }
233225
234226 @func ( 'email' )
235227 private _email ( args : Expression [ ] ) {
236- const field = this . transform ( args [ 0 ] , false ) ;
228+ const field = this . transform ( args [ 0 ] ) ;
237229 return `z.string().email().safeParse(${ field } ).success` ;
238230 }
239231
240232 @func ( 'datetime' )
241233 private _datetime ( args : Expression [ ] ) {
242- const field = this . transform ( args [ 0 ] , false ) ;
234+ const field = this . transform ( args [ 0 ] ) ;
243235 return `z.string().datetime({ offset: true }).safeParse(${ field } ).success` ;
244236 }
245237
246238 @func ( 'url' )
247239 private _url ( args : Expression [ ] ) {
248- const field = this . transform ( args [ 0 ] , false ) ;
240+ const field = this . transform ( args [ 0 ] ) ;
249241 return `z.string().url().safeParse(${ field } ).success` ;
250242 }
251243
252244 @func ( 'has' )
253- private _has ( args : Expression [ ] , normalizeUndefined : boolean ) {
254- const field = this . transform ( args [ 0 ] , false ) ;
255- const result = `${ field } ?.includes(${ this . transform ( args [ 1 ] , normalizeUndefined ) } )` ;
245+ private _has ( args : Expression [ ] ) {
246+ const field = this . transform ( args [ 0 ] ) ;
247+ const result = `${ field } ?.includes(${ this . transform ( args [ 1 ] ) } )` ;
256248 return this . ensureBoolean ( result ) ;
257249 }
258250
259251 @func ( 'hasEvery' )
260- private _hasEvery ( args : Expression [ ] , normalizeUndefined : boolean ) {
261- const field = this . transform ( args [ 0 ] , false ) ;
262- const result = `${ this . transform ( args [ 1 ] , normalizeUndefined ) } ?.every((item) => ${ field } ?.includes(item))` ;
252+ private _hasEvery ( args : Expression [ ] ) {
253+ const field = this . transform ( args [ 0 ] ) ;
254+ const result = `${ this . transform ( args [ 1 ] ) } ?.every((item) => ${ field } ?.includes(item))` ;
263255 return this . ensureBoolean ( result ) ;
264256 }
265257
266258 @func ( 'hasSome' )
267- private _hasSome ( args : Expression [ ] , normalizeUndefined : boolean ) {
268- const field = this . transform ( args [ 0 ] , false ) ;
269- const result = `${ this . transform ( args [ 1 ] , normalizeUndefined ) } ?.some((item) => ${ field } ?.includes(item))` ;
259+ private _hasSome ( args : Expression [ ] ) {
260+ const field = this . transform ( args [ 0 ] ) ;
261+ const result = `${ this . transform ( args [ 1 ] ) } ?.some((item) => ${ field } ?.includes(item))` ;
270262 return this . ensureBoolean ( result ) ;
271263 }
272264
273265 @func ( 'isEmpty' )
274266 private _isEmpty ( args : Expression [ ] ) {
275- const field = this . transform ( args [ 0 ] , false ) ;
267+ const field = this . transform ( args [ 0 ] ) ;
276268 const result = `(!${ field } || ${ field } ?.length === 0)` ;
277269 return this . ensureBoolean ( result ) ;
278270 }
@@ -304,8 +296,8 @@ export class Z3ExpressionTransformer {
304296 return 'null' ;
305297 }
306298
307- private array ( expr : ArrayExpr , normalizeUndefined : boolean ) {
308- return `[${ expr . items . map ( ( item ) => this . transform ( item , normalizeUndefined ) ) . join ( ', ' ) } ]` ;
299+ private array ( expr : ArrayExpr ) {
300+ return `[${ expr . items . map ( ( item ) => this . transform ( item ) ) . join ( ', ' ) } ]` ;
309301 }
310302
311303 private literal ( expr : LiteralExpr ) {
@@ -320,41 +312,35 @@ export class Z3ExpressionTransformer {
320312 return `z3.Bool.val(${ expr . value } )` ;
321313 }
322314
323- private unary ( expr : UnaryExpr , normalizeUndefined : boolean ) : string {
324- return `(${ expr . operator } ${ this . transform ( expr . operand , normalizeUndefined ) } )` ;
315+ private unary ( expr : UnaryExpr ) : string {
316+ return `(${ expr . operator } ${ this . transform ( expr . operand ) } )` ;
325317 }
326318
327319 private isModelType ( expr : Expression ) {
328320 return isDataModel ( expr . $resolvedType ?. decl ) ;
329321 }
330322
331- private binary ( expr : BinaryExpr , normalizeUndefined : boolean ) : string {
323+ private binary ( expr : BinaryExpr ) : string {
332324 if ( /* expr.left.$type === 'ReferenceExpr' && */ expr . right . $type === 'StringLiteral' ) return 'true' ;
333325
334- let left = this . transform ( expr . left , normalizeUndefined ) ;
335- let right = isBooleanLiteral ( expr . right )
336- ? `${ expr . right . value } `
337- : this . transform ( expr . right , normalizeUndefined ) ;
326+ let left = this . transform ( expr . left ) ;
327+ let right = isBooleanLiteral ( expr . right ) ? `${ expr . right . value } ` : this . transform ( expr . right ) ;
338328 // if (isMemberAccessExpr(expr.left) && !isAuthInvocation(expr.left)) {
339329 // left = `args.${left}`;
340330 // }
341331 // if (isMemberAccessExpr(expr.right) && !isAuthInvocation(expr.right)) {
342332 // right = `args.${right}`;
343333 // }
344334 // if (this.isModelType(expr.left)) {
345- // left = `(${left}.id ?? null )`;
335+ // left = `(${left}.id)`;
346336 // }
347337 // if (this.isModelType(expr.right)) {
348- // right = `(${right}.id ?? null )`;
338+ // right = `(${right}.id)`;
349339 // }
350340 if ( this . isModelType ( expr . left ) && this . isModelType ( expr . right ) ) {
351341 // comparison between model type values, map to id comparison
352- left = isAuthInvocation ( expr . left )
353- ? `(${ left } ?.id ?? null)`
354- : `((args.${ left } ?.id || args.${ left } Id) ?? null)` ;
355- right = isAuthInvocation ( expr . right )
356- ? `(${ right } .id ?? null)`
357- : `((args.${ right } ?.id || args.${ right } Id) ?? null)` ;
342+ left = isAuthInvocation ( expr . left ) ? `(${ left } ?.id)` : `((args.${ left } ?.id || args.${ left } Id))` ;
343+ right = isAuthInvocation ( expr . right ) ? `(${ right } .id)` : `((args.${ right } ?.id || args.${ right } Id))` ;
358344 let assertion = `${ left } ${ expr . operator } ${ right } ` ;
359345
360346 // only args values need implies
@@ -369,8 +355,8 @@ export class Z3ExpressionTransformer {
369355 }
370356
371357 if ( isAuthInvocation ( expr . left ) || isAuthInvocation ( expr . right ) ) {
372- left = isAuthInvocation ( expr . left ) ? `(${ left } ?.id ?? null )` : left ;
373- right = isAuthInvocation ( expr . right ) ? `(${ right } .id ?? null )` : right ;
358+ left = isAuthInvocation ( expr . left ) ? `(${ left } ?.id)` : left ;
359+ right = isAuthInvocation ( expr . right ) ? `(${ right } .id)` : right ;
374360 const assertion = `${ left } ${ expr . operator } ${ right } ` ;
375361 if ( this . needAuthCheck ( expr ) ) {
376362 return this . withAuth ( expr , assertion ) ;
@@ -414,14 +400,7 @@ export class Z3ExpressionTransformer {
414400 . with ( '<=' , ( ) => `${ left } .le(${ right } )` )
415401 . with ( '>' , ( ) => `${ left } .gt(${ right } )` )
416402 . with ( '>=' , ( ) => `${ left } .ge(${ right } )` )
417- . with (
418- 'in' ,
419- ( ) =>
420- `(${ this . transform ( expr . right , false ) } ?.includes(${ this . transform (
421- expr . left ,
422- normalizeUndefined
423- ) } ) ?? false)`
424- )
403+ . with ( 'in' , ( ) => `(${ this . transform ( expr . right ) } ?.includes(${ this . transform ( expr . left ) } ) ?? false)` )
425404 // .with(P.union('==', '!='), () => {
426405 // if (isThisExpr(expr.left) || isThisExpr(expr.right)) {
427406 // // map equality comparison with `this` to id comparison
@@ -441,20 +420,20 @@ export class Z3ExpressionTransformer {
441420 // return _default;
442421 // }
443422 // })
444- . with ( P . union ( '?' , '!' , '^' ) , ( op ) => this . collectionPredicate ( expr , op , normalizeUndefined ) )
423+ . with ( P . union ( '?' , '!' , '^' ) , ( op ) => this . collectionPredicate ( expr , op ) )
445424 . otherwise ( ( ) => _default )
446425 ) ;
447426 }
448427
449- private collectionPredicate ( expr : BinaryExpr , operator : '?' | '!' | '^' , normalizeUndefined : boolean ) {
450- const operand = this . transform ( expr . left , normalizeUndefined ) ;
428+ private collectionPredicate ( expr : BinaryExpr , operator : '?' | '!' | '^' ) {
429+ const operand = this . transform ( expr . left ) ;
451430 const innerTransformer = new Z3ExpressionTransformer ( {
452431 ...this . options ,
453432 isPostGuard : false ,
454433 fieldReferenceContext : '_item' ,
455434 thisExprContext : '_item' ,
456435 } ) ;
457- const predicate = innerTransformer . transform ( expr . right , normalizeUndefined ) ;
436+ const predicate = innerTransformer . transform ( expr . right ) ;
458437
459438 return match ( operator )
460439 . with ( '?' , ( ) => `!!((${ operand } )?.some((_item: any) => ${ predicate } ))` )
0 commit comments