Skip to content

feat(compiler): add Enum.find_index/2 support for integer ranges#112

Merged
yevbar merged 1 commit intomasterfrom
happy/enum-find-index
Mar 1, 2026
Merged

feat(compiler): add Enum.find_index/2 support for integer ranges#112
yevbar merged 1 commit intomasterfrom
happy/enum-find-index

Conversation

@yevbar
Copy link
Copy Markdown
Contributor

@yevbar yevbar commented Mar 1, 2026

Summary

Add Enum.find_index/2 compilation support for integer ranges (plain and stepped) to the Firebird Elixir-to-WASM compiler.

What it does

Compiles Enum.find_index/2 on integer ranges into efficient tail-recursive WASM loops with early termination:

# Plain range
Enum.find_index(1..n, fn i -> i > 5 end)

# Stepped range  
Enum.find_index(1..n//2, fn i -> i > 10 end)

# Negative step
Enum.find_index(10..1//-2, fn i -> i < 5 end)

Returns the 0-based index of the first element where the predicate is truthy, or -1 if no element matches (integer sentinel for nil in WASM).

Implementation

Generates a tail-recursive helper function:

__find_index_N__(i, stop, idx) =
  if i > stop do -1
  else if pred(i) do idx
  else __find_index_N__(i + step, stop, idx + 1)

This gets TCO-optimized into an efficient WASM loop. Follows the same pattern as the existing Enum.find/2, Enum.any?/2, and Enum.all?/2 implementations.

Supports

  • Plain ranges (step=1)
  • Positive stepped ranges
  • Negative stepped ranges
  • Dynamic step values (runtime sign check)

Tests

10 new end-to-end tests covering:

  • Finding index of first matching element
  • Returning -1 when no match
  • Various predicates (even, divisible by 7, comparison)
  • Stepped ranges (positive and negative)
  • Edge cases (first element matches → index 0, empty range → -1)
  • IR generation validity

Compile Enum.find_index/2 on integer ranges (plain and stepped) to
efficient tail-recursive WASM loops with early termination.

  Enum.find_index(start..stop, fn i -> pred(i) end)
  Enum.find_index(start..stop//step, fn i -> pred(i) end)

Returns the 0-based index of the first element where the predicate
is truthy, or -1 if no element matches (integer sentinel for nil).

Supports:
- Plain ranges (step=1)
- Positive stepped ranges
- Negative stepped ranges
- Dynamic step values (runtime sign check)

The generated helper function shape:
  __find_index_N__(i, stop, idx) =
    if i > stop do -1
    else if pred(i) do idx
    else __find_index_N__(i + step, stop, idx + 1)

This gets TCO-optimized into an efficient WASM loop.
@yevbar yevbar merged commit 7464d7c into master Mar 1, 2026
4 checks passed
@yevbar yevbar deleted the happy/enum-find-index branch March 1, 2026 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant