Add 56-bit SWAR (SIMD Within A Register) acceleration to skip_length/2
and byte_size_remaining_at/2, processing 8 ASCII bytes per iteration
instead of one. Uses the Mycroft zero-byte detection algorithm to
validate that 7+1 bytes are all ASCII with no \r in a single guard.
This mirrors the approach taken in OTP's string module
(OTP https://github.com/erlang/otp/pull/10948).
Before function signatures showed arguments as: arg, tuple, tuples.
Now they appear as: definition, definitions.
Guards has been improved and standardized, along with variable names.
When merging URIs where the base has `path: ""`, the internal `:+` marker
used to track the join point between base and relative paths was being
converted to a literal "+" in the output.
* Implement gradual function domains and tighten function application
Add fun_domain/1 to compute function domains for static, dynamic, and mixed function types, including explicit :badfun and {:badarity, ...} outcomes when domain extraction is not well-defined.
Refine gradual function application internals by separating static and dynamic normalization paths, documenting behavior for purely dynamic and mixed cases, and clarifying domain/compatibility handling.
Expand descr tests with gradual-application edge cases and a dedicated fun_domain test suite covering static, dynamic, mixed, and arity-error scenarios.
* Refactor function application and domain handling
* Remove fun_domain, recover coverage via fun_apply tests
fun_domain was only used in tests; its behavior is fully observable
through fun_apply (wrong-domain arg → :badarg, right-domain → :ok).
Removed it and converted the domain tests to fun_apply assertions,
adding a few previously uncovered cases along the way: pure non-fun
badfun, union-arg-type enforcement, 2-arity, mixed-arity badarity
for both static and dynamic unions, and the mixed static+dynamic
gradual domain case.
* Remove dead helpers introduced alongside fun_domain
fun_single_arity, fun_single_arity_pair, fun_non_empty_arities_of,
and fun_non_empty_arities are now unreachable. Also revert
dynamic_fun_top? to the simpler map == %{} check — the semantic
emptiness scan added in the refactor was only needed to handle
the same edge cases fun_domain was handling.
* Move mixed-arity badarity check to static side of fun_normalize_both
fun_normalize itself stays simple (no arity cross-check). The check
for other non-empty arities now lives in fun_normalize_both via
fun_other_non_empty_arities/2, and only fires for the static
component. This means:
- union(fun/1, fun/2) applied with 1 arg → {:badarity, [1, 2]}
(static: we know one branch will always fail at runtime)
- union(dynamic_fun/1, dynamic_fun/2) applied with 1 arg →
{:ok, dynamic(integer())} (dynamic: picks matching-arity arrows,
wraps in dynamic() to reflect that the other branch may fail)
* Add tests for mixed-arity union behavior
Static union: badarity regardless of which arity is called with,
with the called arity listed first followed by the others.
Dynamic union: picks the matching-arity arrows and wraps in dynamic(),
gives badarity only when no arity matches at all, and falls back to
dynamic() when the arg is outside the domain but dynamically compatible.