Repository navigation
Description
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
frexpexponents: keep managed exponent 0; tested Windows C returns -1, but C leaves it unspecified. math.degoperation 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
gsublimits: 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
akeit0 commentedon Oct 29, 2026
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.