Skip to content

Decide numeric text policy separately from Lua 5.2 semantic fixes #378

Closed

Description

@akeit0

Decision to make

Keep invariant .NET-style implicit number text as Lua-CSharp's default, or adopt Lua 5.2's default C build format (%.14g) and canonical inf/nan words? This is a category C configuration/embedding decision, separate from Lua language/library semantic fixes.

Recommendation: keep the current invariant managed default for now. MoonSharp's number ToString uses .NET invariant formatting, so C# applications have a reasonable expectation here. Do not copy culture-sensitive conversion paths. Exact output parity with the default C build should be an explicit requirement, not an incidental change to a correctness PR.

Observable differences

Expression Existing default / semantic drafts Separate proposed policy
tostring(1/3) 0.3333333333333333 0.33333333333333
table.concat({1/3,1e20}, ',') 0.3333333333333333,1E+20 0.33333333333333,1e+20
positive infinity as implicit text Infinity inf
tonumber(1e14,10) after explicit-base semantic fix 1e14 nil (intermediate scientific notation)
numeric %q after quoted-string semantic fix quotes managed text quotes proposed text

Affected implicit paths: tostring, numeric __tostring results, %s, numeric %q, concatenation, table.concat, numeric gsub replacements, and numeric-to-string coercion for explicit-base tonumber. Public C# LuaValue.ToString() can remain host-oriented in either policy.

Reducing implicit precision changes persisted text, snapshots, protocols and hashes without changing the underlying double. For finite serialization, request %.17g or %a; handle special values explicitly. Implicit text is not a serialization guarantee.

Explicit formatting is a separate concern

Correct finite printf precision, flags, argument conversion, padding and numeric %q result type are semantic alignment changes and can proceed independently. Special-value spellings for explicit %f/%e/%g/%a belong to this policy discussion; C libraries may emit forms such as -nan(ind), so one Windows binary does not define universal spelling. Managed integer formatting keeps its documented 64-bit range.

Other platform differences kept out of semantic PRs

  • Non-finite frexp exponents: keep managed exponent 0; tested Windows C returns -1, but C leaves it unspecified.
  • math.deg operation order: keep existing managed multiplication; reference division can differ by one ULP.
  • Fractional bit32 words: reuse existing managed round-to-even normalization; Lua leaves precise normalization unspecified.
  • Negative gsub limits: document the managed unsigned-limit convention instead of promising every C cast behavior.
  • Random generator identity remains .NET's; fixing Lua argument/seed semantics does not require C's random sequence.

No new compatibility-profile framework is needed just to enumerate these differences. If real applications require both numeric-text profiles, prefer an immutable state-creation policy shared through the existing platform/global-state abstractions so coroutines agree.

Review/acceptance

  • Decide implicit precision/exponent policy and migration/versioning.
  • Decide special-value presentation, including explicit printf, separately from finite printf semantics.
  • Keep all Lua-facing numeric conversion paths consistent.
  • Document before/after examples and persisted-text impact in the self-contained breaking-changes guide.
  • Do not merge the separate numeric-text draft until the default policy is chosen.

Primary evidence: Lua 5.2 configurable number format, MoonSharp DynValue numeric formatting, Lua 5.2 bit32 normalization.

Prepared drafts and validation

The five semantic drafts are #379–#383; the isolated numeric-text proposal is #384. All remain unmerged. Preparation documents are kept locally, outside their code diffs.

The semantic stack passes 1,589 tests on each .NET 8/10 and all four library targets. In 14,128 byte-mode comparisons, the 41 retained differences are 36 numeric-text results, 3 non-finite frexp exponents and 2 one-ULP deg results. The numeric-text proposal passes 1,590 tests per runtime and leaves only those 5 deferred math differences. Exact C NaN payload spellings are not a portable target. MoonSharp 2.0.0 was checked on .NET 10: tostring(1/3) prints 0.3333333333333333, tostring(1/0) prints Infinity, and tostring(0/0) prints NaN.

Activity

  1. akeit0 commented on Oct 29, 2026

    @akeit0
    CollaboratorAuthor

    Resolved by #393, merged into main. LuaPlatform.NumberFormat keeps invariant DotNet formatting as the default and offers opt-in Lua 5.2 C-locale numeric text with portable signed inf/nan. The implementation covers numeric conversion and I/O paths, preserves public LuaValue.ToString(), and documents precision and Windows CRT differences in both READMEs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions