Skip to content

Commit

Permalink
Merge pull request #421 from bazsi/filterx-introduce-optimize-method
Browse files Browse the repository at this point in the history
Filterx introduce optimize method
  • Loading branch information
alltilla authored Jan 2, 2025
2 parents 1a76519 + 626a2cf commit 32e9237
Show file tree
Hide file tree
Showing 24 changed files with 407 additions and 145 deletions.
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

0 comments on commit 32e9237

Please sign in to comment.