From 8619f825f02793cfd1b01b1bacf33a656555fcdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20V=C3=A1rady?= Date: Sat, 23 Nov 2024 01:11:23 +0100 Subject: [PATCH 1/9] filterx: remove default actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > If you don’t specify an action for a rule, Bison supplies a default: > $$ = $1. Signed-off-by: László Várady --- lib/filterx/filterx-grammar.ym | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/filterx/filterx-grammar.ym b/lib/filterx/filterx-grammar.ym index 1d4da691e..c0e8894b0 100644 --- a/lib/filterx/filterx-grammar.ym +++ b/lib/filterx/filterx-grammar.ym @@ -187,10 +187,10 @@ stmt ; stmt_expr - : expr { $$ = $1; } - | conditional { $$ = $1; } - | assignment { $$ = $1; } - | declaration { $$ = $1; } + : expr + | conditional + | assignment + | declaration ; plus_assignment @@ -211,7 +211,7 @@ assignment | expr '[' expr ']' KW_ASSIGN expr { $$ = filterx_set_subscript_new($1, $3, $6); } | expr '[' ']' KW_ASSIGN expr { $$ = filterx_set_subscript_new($1, NULL, $5); } | generator_assignment - | plus_assignment { $$ = $1; } + | plus_assignment ; @@ -364,8 +364,8 @@ declaration ; expr - : expr_value { $$ = $1; } - | function_call { $$ = $1; } + : expr_value + | function_call | KW_NOT expr { $$ = filterx_unary_not_new($2); } | expr KW_OR expr { $$ = filterx_binary_or_new($1, $3); } | expr KW_AND expr { $$ = filterx_binary_and_new($1, $3); } @@ -388,17 +388,17 @@ expr | expr KW_TAV_NE expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AND_VALUE_BASED | FCMPX_NE ); } | expr '+' expr { $$ = filterx_operator_plus_new($1, $3); } | '(' expr ')' { $$ = $2; } - | ternary { $$ = $1; } - | default { $$ = $1; } + | ternary + | default | KW_ISSET '(' expr ')' { $$ = filterx_isset_new($3); } | KW_DROP { $$ = filterx_expr_drop_msg(); } | KW_DONE { $$ = filterx_expr_done(); } - | regexp_match { $$ = $1; } + | regexp_match ; expr_value : literal - | variable { $$ = $1; } + | variable | template { $$ = construct_template_expr($1); } ; @@ -577,7 +577,7 @@ regexp_match ; conditional - : if { $$ = $1; } + : if | if KW_ELSE block { FilterXExpr *tailing_if = filterx_conditional_find_tail($1); From 6903cd27bb1b625e04d0589661b88082799cb42b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20V=C3=A1rady?= Date: Sat, 23 Nov 2024 01:34:07 +0100 Subject: [PATCH 2/9] filterx: categorize operators in grammar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: László Várady --- lib/filterx/filterx-grammar.ym | 66 ++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/lib/filterx/filterx-grammar.ym b/lib/filterx/filterx-grammar.ym index c0e8894b0..7775cd264 100644 --- a/lib/filterx/filterx-grammar.ym +++ b/lib/filterx/filterx-grammar.ym @@ -122,6 +122,10 @@ construct_template_expr(LogTemplate *template) %type declaration %type expr %type expr_value +%type expr_operator +%type boolalg_operator +%type comparison_operator +%type arithmetic_operator %type expr_generator %type expr_generator_unchecked %type expr_plus_generator @@ -366,36 +370,52 @@ declaration expr : expr_value | function_call - | KW_NOT expr { $$ = filterx_unary_not_new($2); } - | expr KW_OR expr { $$ = filterx_binary_or_new($1, $3); } - | expr KW_AND expr { $$ = filterx_binary_and_new($1, $3); } - /* TODO extract lvalues */ - | expr '.' identifier { $$ = filterx_getattr_new($1, filterx_config_frozen_string(configuration, $3)); free($3); } - | expr '[' expr ']' { $$ = filterx_get_subscript_new($1, $3); } - | expr KW_TA_LT expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_LT); } - | expr KW_TA_LE expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_LT | FCMPX_EQ); } - | expr KW_TA_EQ expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_EQ); } - | expr KW_TA_NE expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_NE ); } - | expr KW_TA_GE expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_EQ | FCMPX_GT); } - | expr KW_TA_GT expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_GT); } - | expr KW_STR_LT expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_LT); } - | expr KW_STR_LE expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_LT | FCMPX_EQ); } - | expr KW_STR_EQ expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_EQ); } - | expr KW_STR_NE expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_NE ); } - | expr KW_STR_GE expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_EQ | FCMPX_GT); } - | expr KW_STR_GT expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_GT); } - | expr KW_TAV_EQ expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AND_VALUE_BASED | FCMPX_EQ); } - | expr KW_TAV_NE expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AND_VALUE_BASED | FCMPX_NE ); } - | expr '+' expr { $$ = filterx_operator_plus_new($1, $3); } + | expr_operator | '(' expr ')' { $$ = $2; } - | ternary - | default | KW_ISSET '(' expr ')' { $$ = filterx_isset_new($3); } | KW_DROP { $$ = filterx_expr_drop_msg(); } | KW_DONE { $$ = filterx_expr_done(); } + ; + +expr_operator + : boolalg_operator + | comparison_operator + | arithmetic_operator + | ternary + | default + /* TODO extract lvalues */ + | expr '.' identifier { $$ = filterx_getattr_new($1, filterx_config_frozen_string(configuration, $3)); free($3); } + | expr '[' expr ']' { $$ = filterx_get_subscript_new($1, $3); } + ; + +boolalg_operator + : KW_NOT expr { $$ = filterx_unary_not_new($2); } + | expr KW_OR expr { $$ = filterx_binary_or_new($1, $3); } + | expr KW_AND expr { $$ = filterx_binary_and_new($1, $3); } + ; + +comparison_operator + : expr KW_TA_LT expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_LT); } + | expr KW_TA_LE expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_LT | FCMPX_EQ); } + | expr KW_TA_EQ expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_EQ); } + | expr KW_TA_NE expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_NE ); } + | expr KW_TA_GE expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_EQ | FCMPX_GT); } + | expr KW_TA_GT expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_GT); } + | expr KW_STR_LT expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_LT); } + | expr KW_STR_LE expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_LT | FCMPX_EQ); } + | expr KW_STR_EQ expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_EQ); } + | expr KW_STR_NE expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_NE ); } + | expr KW_STR_GE expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_EQ | FCMPX_GT); } + | expr KW_STR_GT expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_GT); } + | expr KW_TAV_EQ expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AND_VALUE_BASED | FCMPX_EQ); } + | expr KW_TAV_NE expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AND_VALUE_BASED | FCMPX_NE ); } | regexp_match ; +arithmetic_operator + : expr '+' expr { $$ = filterx_operator_plus_new($1, $3); } + ; + expr_value : literal | variable From 6ebedd43907f6d825a7dc31a9c7e9dffbafafe46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20V=C3=A1rady?= Date: Sat, 23 Nov 2024 03:03:00 +0100 Subject: [PATCH 3/9] filterx: add filterx_boolean_get_value() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: László Várady --- lib/filterx/object-primitive.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/filterx/object-primitive.h b/lib/filterx/object-primitive.h index f68ff48ea..41898b881 100644 --- a/lib/filterx/object-primitive.h +++ b/lib/filterx/object-primitive.h @@ -82,6 +82,14 @@ filterx_double_unwrap(FilterXObject *s, gdouble *value) return TRUE; } +static inline gboolean +filterx_boolean_get_value(FilterXObject *s) +{ + FilterXPrimitive *self = (FilterXPrimitive *) s; + + return !!gn_as_int64(&self->value); +} + /* NOTE: Consider using filterx_object_extract_boolean() to also support message_value. */ static inline gboolean filterx_boolean_unwrap(FilterXObject *s, gboolean *value) From 1367954961339b842bc72de5f2ae64bc17631861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20V=C3=A1rady?= Date: Sat, 23 Nov 2024 03:04:27 +0100 Subject: [PATCH 4/9] filterx: optimize boolalg operators for literal operands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: László Várady --- lib/filterx/expr-boolalg.c | 78 ++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 16 deletions(-) diff --git a/lib/filterx/expr-boolalg.c b/lib/filterx/expr-boolalg.c index 2b588358e..4fd3c903d 100644 --- a/lib/filterx/expr-boolalg.c +++ b/lib/filterx/expr-boolalg.c @@ -22,6 +22,19 @@ */ #include "filterx/expr-boolalg.h" #include "filterx/object-primitive.h" +#include "filterx/expr-literal.h" + +static inline gboolean +_literal_expr_truthy(FilterXExpr *expr) +{ + FilterXObject *result = filterx_expr_eval(expr); + g_assert(result); + + gboolean truthy = filterx_object_truthy(result); + filterx_object_unref(result); + + return truthy; +} static FilterXObject * _eval_not(FilterXExpr *s) @@ -44,6 +57,9 @@ _eval_not(FilterXExpr *s) FilterXExpr * filterx_unary_not_new(FilterXExpr *operand) { + if (filterx_expr_is_literal(operand)) + return filterx_literal_new(filterx_boolean_new(!_literal_expr_truthy(operand))); + FilterXUnaryOp *self = g_new0(FilterXUnaryOp, 1); filterx_unary_op_init_instance(self, operand); @@ -59,17 +75,20 @@ _eval_and(FilterXExpr *s) /* we only evaluate our rhs if lhs is true, e.g. we do fast circuit * evaluation just like most languages */ - FilterXObject *result = filterx_expr_eval(self->lhs); - if (!result) - return NULL; + if (self->lhs) + { + FilterXObject *result = filterx_expr_eval(self->lhs); + if (!result) + return NULL; - gboolean lhs_truthy = filterx_object_truthy(result); - filterx_object_unref(result); + gboolean lhs_truthy = filterx_object_truthy(result); + filterx_object_unref(result); - if (!lhs_truthy) - return filterx_boolean_new(FALSE); + if (!lhs_truthy) + return filterx_boolean_new(FALSE); + } - result = filterx_expr_eval(self->rhs); + FilterXObject *result = filterx_expr_eval(self->rhs); if (!result) return NULL; @@ -85,9 +104,21 @@ _eval_and(FilterXExpr *s) FilterXExpr * filterx_binary_and_new(FilterXExpr *lhs, FilterXExpr *rhs) { + if (filterx_expr_is_literal(lhs)) + { + if (!_literal_expr_truthy(lhs)) + return filterx_literal_new(filterx_boolean_new(FALSE)); + + if (filterx_expr_is_literal(rhs)) + return filterx_literal_new(filterx_boolean_new(_literal_expr_truthy(rhs))); + } + FilterXBinaryOp *self = g_new0(FilterXBinaryOp, 1); filterx_binary_op_init_instance(self, lhs, rhs); + if (filterx_expr_is_literal(lhs)) + self->lhs = NULL; + self->super.eval = _eval_and; return &self->super; } @@ -100,17 +131,20 @@ _eval_or(FilterXExpr *s) /* we only evaluate our rhs if lhs is false, e.g. we do fast circuit * evaluation just like most languages */ - FilterXObject *result = filterx_expr_eval(self->lhs); - if (!result) - return NULL; + if (self->lhs) + { + FilterXObject *result = filterx_expr_eval(self->lhs); + if (!result) + return NULL; - gboolean lhs_truthy = filterx_object_truthy(result); - filterx_object_unref(result); + gboolean lhs_truthy = filterx_object_truthy(result); + filterx_object_unref(result); - if (lhs_truthy) - return filterx_boolean_new(TRUE); + if (lhs_truthy) + return filterx_boolean_new(TRUE); + } - result = filterx_expr_eval(self->rhs); + FilterXObject *result = filterx_expr_eval(self->rhs); if (!result) return NULL; @@ -126,9 +160,21 @@ _eval_or(FilterXExpr *s) FilterXExpr * filterx_binary_or_new(FilterXExpr *lhs, FilterXExpr *rhs) { + if (filterx_expr_is_literal(lhs)) + { + if (_literal_expr_truthy(lhs)) + return filterx_literal_new(filterx_boolean_new(TRUE)); + + if (filterx_expr_is_literal(rhs)) + return filterx_literal_new(filterx_boolean_new(_literal_expr_truthy(rhs))); + } + FilterXBinaryOp *self = g_new0(FilterXBinaryOp, 1); filterx_binary_op_init_instance(self, lhs, rhs); + if (filterx_expr_is_literal(lhs)) + self->lhs = NULL; + self->super.eval = _eval_or; return &self->super; } From 7e6a75b4d5a4b8b698ac875d39142485e039fdd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20V=C3=A1rady?= Date: Sat, 23 Nov 2024 03:11:46 +0100 Subject: [PATCH 5/9] filterx-comparison: extract _eval_based_on_compare_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: László Várady --- lib/filterx/expr-comparison.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/filterx/expr-comparison.c b/lib/filterx/expr-comparison.c index 2b4e5a226..7eae03072 100644 --- a/lib/filterx/expr-comparison.c +++ b/lib/filterx/expr-comparison.c @@ -187,6 +187,13 @@ _evaluate_type_and_value_based(FilterXObject *lhs, FilterXObject *rhs, gint oper return _evaluate_type_aware(lhs, rhs, operator); } +static inline FilterXObject * +_eval_based_on_compare_mode(FilterXExpr *expr, gint compare_mode) +{ + gboolean typed_eval_needed = compare_mode & FCMPX_TYPE_AWARE || compare_mode & FCMPX_TYPE_AND_VALUE_BASED; + return typed_eval_needed ? filterx_expr_eval_typed(expr) : filterx_expr_eval(expr); +} + static FilterXObject * _eval(FilterXExpr *s) { @@ -194,15 +201,12 @@ _eval(FilterXExpr *s) gint compare_mode = self->operator & FCMPX_MODE_MASK; gint operator = self->operator & FCMPX_OP_MASK; - gboolean typed_eval_needed = compare_mode & FCMPX_TYPE_AWARE || compare_mode & FCMPX_TYPE_AND_VALUE_BASED; - FilterXObject *lhs_object = typed_eval_needed ? filterx_expr_eval_typed(self->super.lhs) : filterx_expr_eval( - self->super.lhs); + FilterXObject *lhs_object = _eval_based_on_compare_mode(self->super.lhs, compare_mode); if (!lhs_object) return NULL; - FilterXObject *rhs_object = typed_eval_needed ? filterx_expr_eval_typed(self->super.rhs) : filterx_expr_eval( - self->super.rhs); + FilterXObject *rhs_object = _eval_based_on_compare_mode(self->super.rhs, compare_mode); if (!rhs_object) { filterx_object_unref(lhs_object); From 690d4358df1afd09ed3de5af6c929e6bfd9685f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20V=C3=A1rady?= Date: Sat, 23 Nov 2024 03:32:33 +0100 Subject: [PATCH 6/9] filterx: optimize comparison operators for literal operands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: László Várady --- lib/filterx/expr-comparison.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/filterx/expr-comparison.c b/lib/filterx/expr-comparison.c index 7eae03072..b40802b6d 100644 --- a/lib/filterx/expr-comparison.c +++ b/lib/filterx/expr-comparison.c @@ -33,6 +33,7 @@ #include "filterx/object-message-value.h" #include "filterx/filterx-object-istype.h" #include "filterx/filterx-ref.h" +#include "filterx/expr-literal.h" #include "object-primitive.h" #include "generic-number.h" #include "parse-number.h" @@ -42,6 +43,8 @@ typedef struct _FilterXComparison { FilterXBinaryOp super; gint operator; + FilterXObject *literal_lhs; + FilterXObject *literal_rhs; } FilterXComparison; static void @@ -202,11 +205,13 @@ _eval(FilterXExpr *s) gint compare_mode = self->operator & FCMPX_MODE_MASK; gint operator = self->operator & FCMPX_OP_MASK; - FilterXObject *lhs_object = _eval_based_on_compare_mode(self->super.lhs, compare_mode); + FilterXObject *lhs_object = self->literal_lhs ? filterx_object_ref(self->literal_lhs) + : _eval_based_on_compare_mode(self->super.lhs, compare_mode); if (!lhs_object) return NULL; - FilterXObject *rhs_object = _eval_based_on_compare_mode(self->super.rhs, compare_mode); + FilterXObject *rhs_object = self->literal_rhs ? filterx_object_ref(self->literal_rhs) + : _eval_based_on_compare_mode(self->super.rhs, compare_mode); if (!rhs_object) { filterx_object_unref(lhs_object); @@ -232,6 +237,16 @@ _eval(FilterXExpr *s) return filterx_boolean_new(result); } +static void +_filterx_comparison_free(FilterXExpr *s) +{ + FilterXComparison *self = (FilterXComparison *) s; + filterx_object_unref(self->literal_lhs); + filterx_object_unref(self->literal_rhs); + + filterx_binary_op_free_method(s); +} + /* NOTE: takes the object reference */ FilterXExpr * filterx_comparison_new(FilterXExpr *lhs, FilterXExpr *rhs, gint operator) @@ -240,6 +255,22 @@ filterx_comparison_new(FilterXExpr *lhs, FilterXExpr *rhs, gint operator) filterx_binary_op_init_instance(&self->super, lhs, rhs); self->super.super.eval = _eval; + self->super.super.free_fn = _filterx_comparison_free; self->operator = operator; + + gint compare_mode = self->operator & FCMPX_MODE_MASK; + if (filterx_expr_is_literal(lhs)) + self->literal_lhs = _eval_based_on_compare_mode(lhs, compare_mode); + + if (filterx_expr_is_literal(rhs)) + self->literal_rhs = _eval_based_on_compare_mode(rhs, compare_mode); + + if (filterx_expr_is_literal(lhs) && filterx_expr_is_literal(rhs)) + { + FilterXExpr *optimized = filterx_literal_new(_eval(&self->super.super)); + filterx_expr_unref(&self->super.super); + return optimized; + } + return &self->super.super; } From 535b6819ee63cf038a74eb80e6a4ae7af0309046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20V=C3=A1rady?= Date: Sat, 23 Nov 2024 04:20:25 +0100 Subject: [PATCH 7/9] filterx: optimize ternary operator for literal operands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: László Várady --- lib/filterx/expr-condition.c | 35 ++++++++++++++++++++++++++++++++++ lib/filterx/expr-condition.h | 2 ++ lib/filterx/filterx-grammar.ym | 24 ++++++++++++++++++----- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/lib/filterx/expr-condition.c b/lib/filterx/expr-condition.c index 8473a49c8..75011631d 100644 --- a/lib/filterx/expr-condition.c +++ b/lib/filterx/expr-condition.c @@ -22,6 +22,7 @@ */ #include "filterx/expr-condition.h" +#include "filterx/expr-literal.h" #include "filterx/object-primitive.h" #include "scratch-buffers.h" @@ -182,3 +183,37 @@ filterx_conditional_find_tail(FilterXExpr *s) } return s; } + +FilterXExpr * +filterx_literal_conditional(FilterXExpr *condition, FilterXExpr *true_branch, FilterXExpr *false_branch) +{ + g_assert(filterx_expr_is_literal(condition)); + + FilterXObject *condition_value = filterx_expr_eval(condition); + g_assert(condition_value); + + FilterXExpr *optimized = NULL; + + if (filterx_object_truthy(condition_value)) + { + if (true_branch) + optimized = true_branch; + else + optimized = filterx_expr_ref(condition); + + filterx_expr_unref(false_branch); + } + else + { + if (false_branch) + optimized = false_branch; + else + optimized = filterx_literal_new(filterx_boolean_new(TRUE)); + + filterx_expr_unref(true_branch); + } + + filterx_object_unref(condition_value); + filterx_expr_unref(condition); + return optimized; +} diff --git a/lib/filterx/expr-condition.h b/lib/filterx/expr-condition.h index cd463f8ea..8b602de07 100644 --- a/lib/filterx/expr-condition.h +++ b/lib/filterx/expr-condition.h @@ -31,4 +31,6 @@ void filterx_conditional_set_false_branch(FilterXExpr *s, FilterXExpr *false_bra FilterXExpr *filterx_conditional_find_tail(FilterXExpr *s); FilterXExpr *filterx_conditional_new(FilterXExpr *condition); +FilterXExpr *filterx_literal_conditional(FilterXExpr *condition, FilterXExpr *true_branch, FilterXExpr *false_branch); + #endif diff --git a/lib/filterx/filterx-grammar.ym b/lib/filterx/filterx-grammar.ym index 7775cd264..ff581f50e 100644 --- a/lib/filterx/filterx-grammar.ym +++ b/lib/filterx/filterx-grammar.ym @@ -634,15 +634,29 @@ ternary : expr '?' expr ':' expr { filterx_expr_set_location($1, lexer, &@1); - $$ = filterx_conditional_new($1); - filterx_conditional_set_true_branch($$, $3); - filterx_conditional_set_false_branch($$, $5); + if (filterx_expr_is_literal($1)) + { + $$ = filterx_literal_conditional($1, $3, $5); + } + else + { + $$ = filterx_conditional_new($1); + filterx_conditional_set_true_branch($$, $3); + filterx_conditional_set_false_branch($$, $5); + } } | expr '?' ':' expr { filterx_expr_set_location($1, lexer, &@1); - $$ = filterx_conditional_new($1); - filterx_conditional_set_false_branch($$, $4); + if (filterx_expr_is_literal($1)) + { + $$ = filterx_literal_conditional($1, NULL, $4); + } + else + { + $$ = filterx_conditional_new($1); + filterx_conditional_set_false_branch($$, $4); + } } ; From 44f5fef9a6e15003b48a4c17b9f188bb4bf56245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20V=C3=A1rady?= Date: Sat, 23 Nov 2024 04:27:43 +0100 Subject: [PATCH 8/9] filterx: optimize null coalesce operator for literal operands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: László Várady --- lib/filterx/expr-null-coalesce.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/filterx/expr-null-coalesce.c b/lib/filterx/expr-null-coalesce.c index 479130507..e1cdf3b95 100644 --- a/lib/filterx/expr-null-coalesce.c +++ b/lib/filterx/expr-null-coalesce.c @@ -23,6 +23,7 @@ */ #include "filterx/expr-null-coalesce.h" +#include "filterx/expr-literal.h" #include "filterx/object-null.h" #include "filterx/filterx-eval.h" #include "filterx/object-message-value.h" @@ -61,6 +62,19 @@ _eval(FilterXExpr *s) FilterXExpr * filterx_null_coalesce_new(FilterXExpr *lhs, FilterXExpr *rhs) { + if (filterx_expr_is_literal(lhs)) + { + FilterXObject *lhs_object = filterx_expr_eval(lhs); + if (!lhs_object || filterx_object_is_type(lhs_object, &FILTERX_TYPE_NAME(null))) + { + filterx_object_unref(lhs_object); + return rhs; + } + + filterx_object_unref(lhs_object); + return lhs; + } + FilterXNullCoalesce *self = g_new0(FilterXNullCoalesce, 1); filterx_binary_op_init_instance(&self->super, lhs, rhs); self->super.super.eval = _eval; From adf1cd21a6398fc3bffe9433555131c4b9c9c23a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20V=C3=A1rady?= Date: Sat, 23 Nov 2024 04:42:49 +0100 Subject: [PATCH 9/9] filterx: optimize plus operator for literal operands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: László Várady --- lib/filterx/expr-plus.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/filterx/expr-plus.c b/lib/filterx/expr-plus.c index a3aaec7b8..2eb349c0a 100644 --- a/lib/filterx/expr-plus.c +++ b/lib/filterx/expr-plus.c @@ -23,11 +23,14 @@ #include "expr-plus.h" #include "object-string.h" #include "filterx-eval.h" +#include "filterx/expr-literal.h" #include "scratch-buffers.h" typedef struct FilterXOperatorPlus { FilterXBinaryOp super; + FilterXObject *literal_lhs; + FilterXObject *literal_rhs; } FilterXOperatorPlus; static FilterXObject * @@ -35,11 +38,13 @@ _eval(FilterXExpr *s) { FilterXOperatorPlus *self = (FilterXOperatorPlus *) s; - FilterXObject *lhs_object = filterx_expr_eval_typed(self->super.lhs); + FilterXObject *lhs_object = self->literal_lhs ? filterx_object_ref(self->literal_lhs) + : filterx_expr_eval_typed(self->super.lhs); if (!lhs_object) return NULL; - FilterXObject *rhs_object = filterx_expr_eval(self->super.rhs); + FilterXObject *rhs_object = self->literal_rhs ? filterx_object_ref(self->literal_rhs) + : filterx_expr_eval(self->super.rhs); if (!rhs_object) { filterx_object_unref(lhs_object); @@ -52,11 +57,36 @@ _eval(FilterXExpr *s) return res; } +static void +_filterx_operator_plus_free(FilterXExpr *s) +{ + FilterXOperatorPlus *self = (FilterXOperatorPlus *) s; + filterx_object_unref(self->literal_lhs); + filterx_object_unref(self->literal_rhs); + + filterx_binary_op_free_method(s); +} + FilterXExpr * filterx_operator_plus_new(FilterXExpr *lhs, FilterXExpr *rhs) { FilterXOperatorPlus *self = g_new0(FilterXOperatorPlus, 1); filterx_binary_op_init_instance(&self->super, lhs, rhs); self->super.super.eval = _eval; + self->super.super.free_fn = _filterx_operator_plus_free; + + if (filterx_expr_is_literal(lhs)) + self->literal_lhs = filterx_expr_eval_typed(lhs); + + if (filterx_expr_is_literal(rhs)) + self->literal_rhs = filterx_expr_eval(rhs); + + if (filterx_expr_is_literal(lhs) && filterx_expr_is_literal(rhs)) + { + FilterXExpr *optimized = filterx_literal_new(_eval(&self->super.super)); + filterx_expr_unref(&self->super.super); + return optimized; + } + return &self->super.super; }