Skip to content

fix(abc): float and suffixed numeric operands score no condition in Ruby and Elixir #1379

Description

@dekobon

Summary

Found sweeping siblings for #1359 (grammar-dispatch §7). The
terminal-bool operand sets that ABC's unary-conditional walker consults
(src/macros/kind_sets.rs, Fitzpatrick Rule 9, #557) name Integer for
Ruby and Elixir but not the other numeric literal kinds those grammars
emit. A float or a suffixed numeric used as a bare && / || operand
scores one condition instead of two.

Python's set already names both Float and Integer, so the three
truthy-value languages disagree with each other for no reason anyone
recorded.

Reproduction

$ cat a.rb
def f
  a && 1
end
$ bca metrics --no-config -p a.rb   # abc.conditions: 2   (correct)

$ cat b.rb
def f
  a && 1.0
end
$ bca metrics --no-config -p b.rb   # abc.conditions: 1   (wrong)

a && 1r and a && 2i report 1 for the same reason. Elixir:

$ printf 'def f(a) do\n  a && 1\nend\n'    # abc.conditions: 2
$ printf 'def f(a) do\n  a && 1.0\nend\n'  # abc.conditions: 1

Python is the control and is already right:

$ printf 'def f(a):\n    return a and 1.0\n'   # abc.conditions: 2

Why the count drops rather than errors

src/metrics/abc/ruby.rs:111,134 requires the operand's kind to be in
ruby_bool_terminal_kinds!() and its parent list kind to be a
Binary*. A float / rational / complex operand is not in the set,
so the walker recurses one level, and the recursion then fails the
list-kind gate. Nothing warns; the condition is simply not counted.

Fix shape

src/macros/kind_sets.rs:

Then re-derive the comment above each macro, which currently enumerates
the operand kinds as a closed list and so is part of the contract.

Sweep

The remaining seventeen sets were checked. Lua, Tcl, iRules and the four
JS-family sets name a single Number kind that covers both integers and
floats, so they have no gap. C#, Java, Groovy, Rust, Go, C++, PHP,
Kotlin and Perl name no numeric literal at all — plausibly deliberate,
since a bare numeric is not a boolean operand in most of them, but no
comment says so and Perl at least is a truthy-value language. Worth
confirming Perl separately rather than assuming.

Tests

Per-language abc.conditions assertions for a float operand, plus the
Ruby suffixed forms. abc.conditions == cyclomatic() - 1 per space is
the cross-check .claude/rules/grammar-dispatch.md §8 asks for.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions