bool needs_resolving;//!< Needs pass2 resolution.
bool needs_async; //!< Node and all child nodes are guaranteed to not
///< require asynchronous expansion.
- bool pure; //!< has no external side effects
- bool has_pure_children; //!< as the sticker says
+ bool pure; //!< has no external side effects, true for BOX, LITERAL, and some functions
+ bool can_purify; //!< if the xlat has a pure function with pure arguments.
} xlat_flags_t;
/*
node->flags = func->flags;
xlat_flags_merge(&node->flags, &args->flags);
+ /*
+ * If the function is pure, AND it's arguments are pure,
+ * then remember that we need to call a pure function.
+ */
+ node->flags.can_purify = func->flags.pure && args->flags.pure;
+
return node;
}
}
node->flags = node->alternate[0]->flags;
+ /*
+ * If the first argument is pure, then we can purify this
+ * node. If the first argument isn't pure, but the
+ * second one is, then we can still purify the second
+ * argument.
+ */
+ node->flags.can_purify |= node->alternate[0]->flags.pure;
+
/*
* Allow the RHS to be empty as a special case.
*/
goto error;
}
xlat_flags_merge(&node->flags, &node->alternate[1]->flags);
+ node->flags.can_purify |= node->alternate[1]->flags.pure;
done:
xlat_exp_insert_tail(head, node);
/*
* Check we have all the required arguments
*/
- if ((node->type == XLAT_FUNC) && (xlat_validate_function_args(node) < 0)) goto error;
+ if (node->type == XLAT_FUNC) {
+ if (xlat_validate_function_args(node) < 0) goto error;
+
+ node->flags.can_purify = node->call.func->flags.pure && node->call.args->flags.pure;
+ }
if (!fr_sbuff_next_if_char(in, ')')) {
fr_strerror_const("Missing closing brace");
xlat_exp_set_type(node, XLAT_ONE_LETTER);
xlat_exp_set_name_buffer_shallow(node, str);
- node->flags.pure = true; /* value boxes are always pure */
- node->flags.needs_async = false; /* value boxes are always non-async */
+ /*
+ * %% is pure. Everything else is not.
+ */
+ node->flags.pure = (node->fmt[0] == '%');
+ node->flags.needs_async = false;
xlat_exp_insert_tail(head, node);
continue;
if (xlat_resolve(node->call.args, xr_rules) < 0) return -1;
node->flags = node->call.func->flags;
xlat_flags_merge(&node->flags, &node->call.args->flags);
+
+ node->flags.can_purify = node->call.func->flags.pure && node->call.args->flags.pure;
break;
/*
*/
xlat_flags_merge(&node->flags, &node->call.args->flags);
+ node->flags.can_purify = node->call.func->flags.pure && node->call.args->flags.pure;
+
/*
* Add the freshly resolved function
* to the bootstrap tree.