@@ -162,6 +162,18 @@ pub enum IrExpression<'a> {
162162 /// Literal map (object) with IR expression values.
163163 /// Used to preserve pipe bindings inside object literals during ingest.
164164 LiteralMap ( Box < ' a , IrLiteralMapExpr < ' a > > ) ,
165+ /// Logical NOT expression (!expr).
166+ /// Used to preserve pipe bindings inside negation expressions during ingest.
167+ Not ( Box < ' a , NotExpr < ' a > > ) ,
168+ /// Unary operator expression (+expr or -expr).
169+ /// Used to preserve pipe bindings inside unary expressions during ingest.
170+ Unary ( Box < ' a , UnaryExpr < ' a > > ) ,
171+ /// Typeof expression (typeof expr).
172+ /// Used to preserve pipe bindings inside typeof expressions during ingest.
173+ Typeof ( Box < ' a , TypeofExpr < ' a > > ) ,
174+ /// Void expression (void expr).
175+ /// Used to preserve pipe bindings inside void expressions during ingest.
176+ Void ( Box < ' a , VoidExpr < ' a > > ) ,
165177}
166178
167179impl < ' a > IrExpression < ' a > {
@@ -222,6 +234,14 @@ impl<'a> IrExpression<'a> {
222234 IrExpression :: LiteralArray ( _) => ExpressionKind :: LiteralArray ,
223235 // LiteralMap is an object literal with IR expression values
224236 IrExpression :: LiteralMap ( _) => ExpressionKind :: LiteralMap ,
237+ // Not is a logical NOT expression
238+ IrExpression :: Not ( _) => ExpressionKind :: Not ,
239+ // Unary is a unary operator expression (+/-)
240+ IrExpression :: Unary ( _) => ExpressionKind :: Unary ,
241+ // Typeof is a typeof expression
242+ IrExpression :: Typeof ( _) => ExpressionKind :: Typeof ,
243+ // Void is a void expression
244+ IrExpression :: Void ( _) => ExpressionKind :: Void ,
225245 }
226246 }
227247}
@@ -656,6 +676,35 @@ impl<'a> IrExpression<'a> {
656676 allocator,
657677 ) )
658678 }
679+ IrExpression :: Not ( e) => IrExpression :: Not ( Box :: new_in (
680+ NotExpr {
681+ expr : Box :: new_in ( e. expr . clone_in ( allocator) , allocator) ,
682+ source_span : e. source_span ,
683+ } ,
684+ allocator,
685+ ) ) ,
686+ IrExpression :: Unary ( e) => IrExpression :: Unary ( Box :: new_in (
687+ UnaryExpr {
688+ operator : e. operator ,
689+ expr : Box :: new_in ( e. expr . clone_in ( allocator) , allocator) ,
690+ source_span : e. source_span ,
691+ } ,
692+ allocator,
693+ ) ) ,
694+ IrExpression :: Typeof ( e) => IrExpression :: Typeof ( Box :: new_in (
695+ TypeofExpr {
696+ expr : Box :: new_in ( e. expr . clone_in ( allocator) , allocator) ,
697+ source_span : e. source_span ,
698+ } ,
699+ allocator,
700+ ) ) ,
701+ IrExpression :: Void ( e) => IrExpression :: Void ( Box :: new_in (
702+ VoidExpr {
703+ expr : Box :: new_in ( e. expr . clone_in ( allocator) , allocator) ,
704+ source_span : e. source_span ,
705+ } ,
706+ allocator,
707+ ) ) ,
659708 }
660709 }
661710}
@@ -1238,6 +1287,61 @@ pub enum IrBinaryOperator {
12381287 NullishCoalesceAssignment ,
12391288}
12401289
1290+ /// Unary operators for IR expressions.
1291+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
1292+ pub enum IrUnaryOperator {
1293+ /// Unary plus (+)
1294+ Plus ,
1295+ /// Unary minus (-)
1296+ Minus ,
1297+ }
1298+
1299+ /// Logical NOT expression (!expr).
1300+ ///
1301+ /// Used to preserve pipe bindings inside negation expressions like `!(x | async)`.
1302+ #[ derive( Debug ) ]
1303+ pub struct NotExpr < ' a > {
1304+ /// The operand expression.
1305+ pub expr : Box < ' a , IrExpression < ' a > > ,
1306+ /// Source span.
1307+ pub source_span : Option < Span > ,
1308+ }
1309+
1310+ /// Unary operator expression (+expr or -expr).
1311+ ///
1312+ /// Used to preserve pipe bindings inside unary expressions like `+(x | pipe)`.
1313+ #[ derive( Debug ) ]
1314+ pub struct UnaryExpr < ' a > {
1315+ /// The unary operator.
1316+ pub operator : IrUnaryOperator ,
1317+ /// The operand expression.
1318+ pub expr : Box < ' a , IrExpression < ' a > > ,
1319+ /// Source span.
1320+ pub source_span : Option < Span > ,
1321+ }
1322+
1323+ /// Typeof expression (typeof expr).
1324+ ///
1325+ /// Used to preserve pipe bindings inside typeof expressions.
1326+ #[ derive( Debug ) ]
1327+ pub struct TypeofExpr < ' a > {
1328+ /// The operand expression.
1329+ pub expr : Box < ' a , IrExpression < ' a > > ,
1330+ /// Source span.
1331+ pub source_span : Option < Span > ,
1332+ }
1333+
1334+ /// Void expression (void expr).
1335+ ///
1336+ /// Used to preserve pipe bindings inside void expressions.
1337+ #[ derive( Debug ) ]
1338+ pub struct VoidExpr < ' a > {
1339+ /// The operand expression.
1340+ pub expr : Box < ' a , IrExpression < ' a > > ,
1341+ /// Source span.
1342+ pub source_span : Option < Span > ,
1343+ }
1344+
12411345// ============================================================================
12421346// Expression Transformation
12431347// ============================================================================
@@ -1372,6 +1476,18 @@ pub fn transform_expressions_in_expression<'a, F>(
13721476 transform_expressions_in_expression ( & mut e. true_expr , transform, flags) ;
13731477 transform_expressions_in_expression ( & mut e. false_expr , transform, flags) ;
13741478 }
1479+ IrExpression :: Not ( e) => {
1480+ transform_expressions_in_expression ( & mut e. expr , transform, flags) ;
1481+ }
1482+ IrExpression :: Unary ( e) => {
1483+ transform_expressions_in_expression ( & mut e. expr , transform, flags) ;
1484+ }
1485+ IrExpression :: Typeof ( e) => {
1486+ transform_expressions_in_expression ( & mut e. expr , transform, flags) ;
1487+ }
1488+ IrExpression :: Void ( e) => {
1489+ transform_expressions_in_expression ( & mut e. expr , transform, flags) ;
1490+ }
13751491 // These expressions have no internal expressions
13761492 IrExpression :: LexicalRead ( _)
13771493 | IrExpression :: Reference ( _)
@@ -1525,6 +1641,18 @@ pub fn visit_expressions_in_expression<'a, F>(
15251641 visit_expressions_in_expression ( & e. true_expr , visitor, flags) ;
15261642 visit_expressions_in_expression ( & e. false_expr , visitor, flags) ;
15271643 }
1644+ IrExpression :: Not ( e) => {
1645+ visit_expressions_in_expression ( & e. expr , visitor, flags) ;
1646+ }
1647+ IrExpression :: Unary ( e) => {
1648+ visit_expressions_in_expression ( & e. expr , visitor, flags) ;
1649+ }
1650+ IrExpression :: Typeof ( e) => {
1651+ visit_expressions_in_expression ( & e. expr , visitor, flags) ;
1652+ }
1653+ IrExpression :: Void ( e) => {
1654+ visit_expressions_in_expression ( & e. expr , visitor, flags) ;
1655+ }
15281656 // These expressions have no internal expressions
15291657 IrExpression :: LexicalRead ( _)
15301658 | IrExpression :: Reference ( _)
@@ -2504,6 +2632,18 @@ pub fn vars_used_by_ir_expression(expr: &IrExpression<'_>) -> u32 {
25042632 + vars_used_by_ir_expression ( & ternary. false_expr )
25052633 }
25062634
2635+ // Not expression: vars used by inner expression
2636+ IrExpression :: Not ( not) => vars_used_by_ir_expression ( & not. expr ) ,
2637+
2638+ // Unary expression: vars used by inner expression
2639+ IrExpression :: Unary ( unary) => vars_used_by_ir_expression ( & unary. expr ) ,
2640+
2641+ // Typeof expression: vars used by inner expression
2642+ IrExpression :: Typeof ( typeof_expr) => vars_used_by_ir_expression ( & typeof_expr. expr ) ,
2643+
2644+ // Void expression: vars used by inner expression
2645+ IrExpression :: Void ( void_expr) => vars_used_by_ir_expression ( & void_expr. expr ) ,
2646+
25072647 // All other expressions don't directly consume variable slots
25082648 IrExpression :: LexicalRead ( _)
25092649 | IrExpression :: Reference ( _)
0 commit comments