Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filterx introduce optimize method #421

Merged
merged 6 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 71 additions & 57 deletions lib/filterx/expr-boolalg.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ _literal_expr_truthy(FilterXExpr *expr)
return truthy;
}

static FilterXExpr *
_optimize_not(FilterXExpr *s)
{
FilterXUnaryOp *self = (FilterXUnaryOp *) s;

if (filterx_unary_op_optimize_method(s))
g_assert_not_reached();

if (!filterx_expr_is_literal(self->operand))
return NULL;

return filterx_literal_new(filterx_boolean_new(!_literal_expr_truthy(self->operand)));
}

static FilterXObject *
_eval_not(FilterXExpr *s)
{
Expand All @@ -57,20 +71,41 @@ _eval_not(FilterXExpr *s)
FilterXExpr *
filterx_unary_not_new(FilterXExpr *operand)
{
if (filterx_expr_is_literal(operand))
{
FilterXExpr *optimized = filterx_literal_new(filterx_boolean_new(!_literal_expr_truthy(operand)));
filterx_expr_unref(operand);
return optimized;
}

FilterXUnaryOp *self = g_new0(FilterXUnaryOp, 1);

filterx_unary_op_init_instance(self, "not", operand);
self->super.optimize = _optimize_not;
self->super.eval = _eval_not;
return &self->super;
}

static FilterXExpr *
_optimize_and(FilterXExpr *s)
{
FilterXBinaryOp *self = (FilterXBinaryOp *) s;

if (filterx_binary_op_optimize_method(s))
g_assert_not_reached();

if (!filterx_expr_is_literal(self->lhs))
return NULL;

if (!_literal_expr_truthy(self->lhs))
return filterx_literal_new(filterx_boolean_new(FALSE));

if (!filterx_expr_is_literal(self->rhs))
{
/* we can't optimize the AND away, but the LHS is a literal & truthy
* value. In this case we won't need to evaluate this every time in
* eval(), so unset it */
filterx_expr_unref(self->lhs);
self->lhs = NULL;
return NULL;
}

return filterx_literal_new(filterx_boolean_new(_literal_expr_truthy(self->rhs)));
}

static FilterXObject *
_eval_and(FilterXExpr *s)
{
Expand Down Expand Up @@ -108,38 +143,42 @@ _eval_and(FilterXExpr *s)
FilterXExpr *
filterx_binary_and_new(FilterXExpr *lhs, FilterXExpr *rhs)
{
FilterXExpr *optimized = NULL;
if (filterx_expr_is_literal(lhs))
{
if (!_literal_expr_truthy(lhs))
{
optimized = filterx_literal_new(filterx_boolean_new(FALSE));
goto optimize;
}

if (filterx_expr_is_literal(rhs))
{
optimized = filterx_literal_new(filterx_boolean_new(_literal_expr_truthy(rhs)));
goto optimize;
}
}

FilterXBinaryOp *self = g_new0(FilterXBinaryOp, 1);

filterx_binary_op_init_instance(self, "and", lhs, rhs);
if (filterx_expr_is_literal(lhs))

self->super.optimize = _optimize_and;
self->super.eval = _eval_and;
return &self->super;

}

static FilterXExpr *
_optimize_or(FilterXExpr *s)
{
FilterXBinaryOp *self = (FilterXBinaryOp *) s;

if (filterx_binary_op_optimize_method(s))
g_assert_not_reached();

if (!filterx_expr_is_literal(self->lhs))
return NULL;

if (_literal_expr_truthy(self->lhs))
return filterx_literal_new(filterx_boolean_new(TRUE));

if (!filterx_expr_is_literal(self->rhs))
{
/* we can't optimize the OR away (as rhs is not literal), but we do
* know that the lhs is literal and is a falsy value. In this case we
* won't need to evaluate this every time in eval(), so unset it */

filterx_expr_unref(self->lhs);
self->lhs = NULL;
return NULL;
}

self->super.eval = _eval_and;
return &self->super;

optimize:
filterx_expr_unref(lhs);
filterx_expr_unref(rhs);
return optimized;
return filterx_literal_new(filterx_boolean_new(_literal_expr_truthy(self->rhs)));
}

static FilterXObject *
Expand Down Expand Up @@ -179,36 +218,11 @@ _eval_or(FilterXExpr *s)
FilterXExpr *
filterx_binary_or_new(FilterXExpr *lhs, FilterXExpr *rhs)
{
FilterXExpr *optimized = NULL;
if (filterx_expr_is_literal(lhs))
{
if (_literal_expr_truthy(lhs))
{
optimized = filterx_literal_new(filterx_boolean_new(TRUE));
goto optimize;
}

if (filterx_expr_is_literal(rhs))
{
optimized = filterx_literal_new(filterx_boolean_new(_literal_expr_truthy(rhs)));
goto optimize;
}
}

FilterXBinaryOp *self = g_new0(FilterXBinaryOp, 1);

filterx_binary_op_init_instance(self, "or", lhs, rhs);
if (filterx_expr_is_literal(lhs))
{
filterx_expr_unref(self->lhs);
self->lhs = NULL;
}

self->super.optimize = _optimize_or;
self->super.eval = _eval_or;
return &self->super;

optimize:
filterx_expr_unref(lhs);
filterx_expr_unref(rhs);
return optimized;
}
33 changes: 19 additions & 14 deletions lib/filterx/expr-comparison.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,24 @@ _eval(FilterXExpr *s)
return filterx_boolean_new(result);
}

static FilterXExpr *
_optimize(FilterXExpr *s)
{
FilterXComparison *self = (FilterXComparison *) s;

gint compare_mode = self->operator & FCMPX_MODE_MASK;
if (filterx_expr_is_literal(self->super.lhs))
self->literal_lhs = _eval_based_on_compare_mode(self->super.lhs, compare_mode);

if (filterx_expr_is_literal(self->super.rhs))
self->literal_rhs = _eval_based_on_compare_mode(self->super.rhs, compare_mode);

if (self->literal_lhs && self->literal_rhs)
return filterx_literal_new(_eval(&self->super.super));

return NULL;
}

static void
_filterx_comparison_free(FilterXExpr *s)
{
Expand All @@ -254,23 +272,10 @@ filterx_comparison_new(FilterXExpr *lhs, FilterXExpr *rhs, gint operator)
FilterXComparison *self = g_new0(FilterXComparison, 1);

filterx_binary_op_init_instance(&self->super, "comparison", lhs, rhs);
self->super.super.optimize = _optimize;
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;
}
14 changes: 14 additions & 0 deletions lib/filterx/expr-compound.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,19 @@ _eval(FilterXExpr *s)
return result;
}

static FilterXExpr *
_optimize(FilterXExpr *s)
{
FilterXCompoundExpr *self = (FilterXCompoundExpr *) s;

for (gint i = 0; i < self->exprs->len; i++)
{
FilterXExpr **expr = (FilterXExpr **) &g_ptr_array_index(self->exprs, i);
*expr = filterx_expr_optimize(*expr);
}
return NULL;
}

static gboolean
_init(FilterXExpr *s, GlobalConfig *cfg)
{
Expand Down Expand Up @@ -220,6 +233,7 @@ filterx_compound_expr_new(gboolean return_value_of_last_expr)

filterx_expr_init_instance(&self->super);
self->super.eval = _eval;
self->super.optimize = _optimize;
self->super.init = _init;
self->super.deinit = _deinit;
self->super.free_fn = _free;
Expand Down
81 changes: 46 additions & 35 deletions lib/filterx/expr-condition.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct _FilterXConditional
FilterXExpr *false_branch;
};


static gboolean
_init(FilterXExpr *s, GlobalConfig *cfg)
{
Expand Down Expand Up @@ -68,7 +69,6 @@ _init(FilterXExpr *s, GlobalConfig *cfg)
return filterx_expr_init_method(s, cfg);
}


static void
_deinit(FilterXExpr *s, GlobalConfig *cfg)
{
Expand Down Expand Up @@ -146,6 +146,50 @@ _eval(FilterXExpr *s)
return result;
}

static void
_optimize_branches(FilterXExpr *s)
{
FilterXConditional *self = (FilterXConditional *) s;

self->condition = filterx_expr_optimize(self->condition);
self->true_branch = filterx_expr_optimize(self->true_branch);
self->false_branch = filterx_expr_optimize(self->false_branch);
}

static FilterXExpr *
_optimize(FilterXExpr *s)
{
FilterXConditional *self = (FilterXConditional *) s;

_optimize_branches(s);

if (!filterx_expr_is_literal(self->condition))
return FALSE;

FilterXObject *condition_value = filterx_expr_eval(self->condition);

g_assert(condition_value);
gboolean condition_truthy = filterx_object_truthy(condition_value);
filterx_object_unref(condition_value);

if (condition_truthy)
{
if (self->true_branch)
return filterx_expr_ref(self->true_branch);
else
return filterx_expr_ref(self->condition);
}
else
{
if (self->false_branch)
return filterx_expr_ref(self->false_branch);
else
return filterx_literal_new(filterx_boolean_new(TRUE));
}

return NULL;
}

void
filterx_conditional_set_true_branch(FilterXExpr *s, FilterXExpr *true_branch)
{
Expand All @@ -170,6 +214,7 @@ filterx_conditional_new(FilterXExpr *condition)
FilterXConditional *self = g_new0(FilterXConditional, 1);
filterx_expr_init_instance(&self->super);
self->super.eval = _eval;
self->super.optimize = _optimize;
self->super.init = _init;
self->super.deinit = _deinit;
self->super.free_fn = _free;
Expand Down Expand Up @@ -197,37 +242,3 @@ 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;
}
2 changes: 0 additions & 2 deletions lib/filterx/expr-condition.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,4 @@ 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
Loading
Loading