summaryrefslogtreecommitdiffstats
path: root/src/expr.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2024-01-07 12:19:17 -0500
committerTavian Barnes <tavianator@tavianator.com>2024-01-07 12:19:17 -0500
commit4a36bb92a5bbdc41965a6d2c6eae6cdca5983474 (patch)
tree1f2767e349ece3229a8da22ba58d905309e99dfa /src/expr.c
parent70acbc194fa1cc4972293d4e3affee5ba6fe5539 (diff)
downloadbfs-4a36bb92a5bbdc41965a6d2c6eae6cdca5983474.tar.xz
expr: Make expressions variadic
Rather than only unary/binary expressions, we now support an arbitrary number of children. The optimizer has been re-written almost completely and now supports optimal reordering of longer expression chains, rather than just arm-swapping. Fixes #85.
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/src/expr.c b/src/expr.c
index 2002fc7..3e0033f 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -23,7 +23,12 @@ struct bfs_expr *bfs_expr_new(struct bfs_ctx *ctx, bfs_eval_fn *eval_fn, size_t
expr->argc = argc;
expr->argv = argv;
expr->probability = 0.5;
- SLIST_PREPEND(&ctx->expr_list, expr);
+ SLIST_PREPEND(&ctx->expr_list, expr, freelist);
+
+ if (bfs_expr_is_parent(expr)) {
+ SLIST_INIT(&expr->children);
+ }
+
return expr;
}
@@ -34,6 +39,36 @@ bool bfs_expr_is_parent(const struct bfs_expr *expr) {
|| expr->eval_fn == eval_comma;
}
+struct bfs_expr *bfs_expr_children(const struct bfs_expr *expr) {
+ if (bfs_expr_is_parent(expr)) {
+ return expr->children.head;
+ } else {
+ return NULL;
+ }
+}
+
+void bfs_expr_append(struct bfs_expr *expr, struct bfs_expr *child) {
+ bfs_assert(bfs_expr_is_parent(expr));
+
+ SLIST_APPEND(&expr->children, child);
+
+ if (!child->pure) {
+ expr->pure = false;
+ }
+
+ expr->persistent_fds += child->persistent_fds;
+ if (expr->ephemeral_fds < child->ephemeral_fds) {
+ expr->ephemeral_fds = child->ephemeral_fds;
+ }
+}
+
+void bfs_expr_extend(struct bfs_expr *expr, struct bfs_exprs *children) {
+ while (!SLIST_EMPTY(children)) {
+ struct bfs_expr *child = SLIST_POP(children);
+ bfs_expr_append(expr, child);
+ }
+}
+
bool bfs_expr_never_returns(const struct bfs_expr *expr) {
// Expressions that never return are vacuously both always true and always false
return expr->always_true && expr->always_false;