diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2024-01-07 12:19:17 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2024-01-07 12:19:17 -0500 |
commit | 4a36bb92a5bbdc41965a6d2c6eae6cdca5983474 (patch) | |
tree | 1f2767e349ece3229a8da22ba58d905309e99dfa /src/expr.c | |
parent | 70acbc194fa1cc4972293d4e3affee5ba6fe5539 (diff) | |
download | bfs-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.c | 37 |
1 files changed, 36 insertions, 1 deletions
@@ -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; |