Skip to content

Spell NaN and infinite float literals in every target language [patch] - #205

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/159-nonfinite-float-literals
Oct 12, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/159-nonfinite-float-literals

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #159

What changed

#147 fixed non-finite double literals but not float ones. A NaN or infinite float was still written as its round-trip text. That came out as NaNf or -Infinityf in C#, and as the undefined names NaN or -Infinity in Python, C++, C, Rust and Go. The import check only looked for doubles, so a file whose only non-finite literal was a float never got <math.h>, <limits> or Go's "math".

  • LanguageGeneratorBase gains a SpellNonFiniteSingle(float) hook. It defaults to the double spelling, which is already correct for C (NAN and INFINITY are float constants), Python and JavaScript.

  • Four generators override it with their single-precision spelling:

    Target NaN +∞
    C# float.NaN float.PositiveInfinity
    C++ std::numeric_limits<float>::quiet_NaN() std::numeric_limits<float>::infinity()
    Rust f32::NAN f32::INFINITY
    Go float32(math.NaN()) float32(math.Inf(1))
  • ContainsNonFiniteDouble is renamed to ContainsNonFiniteLiteral and now counts float literals too. Its three callers (C, C++ and Go) now add the import for a file whose only non-finite literal is a float.

  • The Go const exclusion from Go: constant field/local initialised to NaN or ±Infinity is emitted as const X = math.NaN(), which does not compile #160 already covered floats, so a constant float set to NaN is still written as a var.

Tests (NonFiniteDoubleLiteralTests)

  • ANonFiniteFloatIsSpelledInTheTargetLanguage: 21 rows, NaN, +∞ and −∞ for each of the seven generators.
  • AFileHoldingANonFiniteFloatImportsItsSpelling: C, C++ and Go each import their header or package exactly once.
  • GeneratedCFloats_Compile, GeneratedCppFloats_Compile, GeneratedGoFloats_Compile, GeneratedRustFloats_Compile: each compiles a file of float functions returning NaN, +∞ and −∞, plus an inferred float local holding +∞. The C and C++ builds use -Werror.

With the generator changes reverted, 25 of these fail: every spelling row except JavaScript's, all three import rows, and all four compile tests. With the changes, the full suite passes (1143/1143).

The generated C# is still not compiled in tests, which is tracked in #162, so the C# rows check the spelling only.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CkCrYLchcFZxtGF9DyXZHi


Generated by Claude Code

The fix for non-finite doubles (#147) left floats on the round-trip text,
so a NaN or infinite float came out as `NaNf`/`-Infinityf` in C# and as the
undefined names `NaN`/`-Infinity` in Python, C++, C, Rust and Go. The
import check also only looked at doubles, so a file whose only non-finite
literal was a float never pulled in <math.h>, <limits> or Go's "math".

LanguageGeneratorBase gains a SpellNonFiniteSingle hook that defaults to
the double spelling (right for C, Python and JavaScript). C#, C++, Rust and
Go override it with their single-precision forms: float.NaN,
std::numeric_limits<float>, f32::NAN and float32(math.NaN()).
ContainsNonFiniteDouble becomes ContainsNonFiniteLiteral and also counts
float literals.

Fixes #159

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CkCrYLchcFZxtGF9DyXZHi
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 6153a81 into main Oct 12, 2026
15 checks passed
@matt-edmondson
matt-edmondson deleted the fix/159-nonfinite-float-literals branch October 12, 2026 23:12
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.

NaN/±Infinity float literals are emitted as undefined names (NaNf, -Infinity) in every target except JavaScript

2 participants