Improve numeric handling - #6
Merged
Merged
Conversation
Apply C# numeric promotion before selecting and calling Udon operators, so small integer operands are converted to the types expected by the externs. Share unary and binary promotion rules between checking and code generation. Promote small integer unary operands to int, uint negation to long, and mixed signed integer/uint operands to long. Reject incompatible numeric pairs and invalid shift operands instead of emitting unusable calls. Convert char through int for floating-point and decimal conversions, since the direct Convert overloads do not support those conversions. Add code-generation checks and SDK smoke coverage for promoted result types and signed/uint comparisons in both operand orders. Extend the emulator's UInt32-to-Int64 conversion support. Honor DOTNET_ROOT in the test reference lookup so these tests can also run with a configured Windows .NET runtime.
Lower uint, long and ulong remainder to division, multiplication and subtraction when a remainder extern is unavailable. Route division by zero through generated exception handling so user code can catch it. Keep this contribution within C# 9, as required by Unity 2022.3. Support wide remainder compound assignments and ulong complement using XOR. Retain ordinary Int32 shift emulation for C# 9 operator tests. Add codegen and SDK smoke cases for negative remainders, wide values and caught exceptions. The long.MinValue overflow case is covered by the separate fix long remainder overflow commit.
Preserve sbyte, byte, short and ushort metadata constants as their declared heap types instead of initializing their slots with boxed Int32 values. A numerically correct value with the wrong boxed type can fail at a Udon extern call or when the value is consumed through object. Add typed HeapInit variants, serialize their metadata kinds, and decode those kinds to the corresponding CLR types in the Unity importer. Keep the emulator's existing Int32 representation for small integer values. Inspect generated heap initializers directly in the compiler regression test, since emulator values alone cannot detect this type mismatch. Add SDK smoke assertions for both the values and their actual boxed types.
Validate predefined numeric compound assignments instead of accepting any numeric target merely because the result can be narrowed back to it. When result narrowing is needed, require the right operand to convert implicitly to the target type, with the shift exception and fitting int constant conversions handled explicitly. Add separate compilation checks for invalid operator and operand pairs, including byte += long, byte += 300 and char += int. List each source body in an array so one shared checking path exercises every rejection case; the assertion includes the rejected body to identify a failure. Change the existing char test from c += 1 to c += (char)1. C# has no implicit int-to-char constant conversion, so the original expression was invalid. The explicit cast keeps the intended test: promote both operands to int for addition, then convert the compound assignment result to char.
Accept fitting signed integer constants as unsigned compound-assignment operands and perform the operation in the selected unsigned type. Avoid converting a large unsigned left operand to a signed type before arithmetic. Recognize unary signs and parentheses when reading integer literals, so a case such as sbyte a = 1; a += (-1) remains valid. Apply the corresponding constant-aware operand selection in checking and code generation. Add an unchecked wrapping regression starting at ulong.MaxValue with +=, -= and *=, plus a compilation check for the parenthesized negative constant. The boundary value exposes an erroneous signed conversion.
Raise a catchable OverflowException for long.MinValue % -1, matching Unity Mono, instead of returning zero from the lowered remainder operation. Keep this check separate from the DivideByZeroException path. Update the compiler and SDK smoke tests to catch the overflow and verify that execution reaches the catch body. Adjust the SDK expected result to match the new sentinel value rather than the previously expected zero.
Retain the numeric operand types selected by semantic checking and pass that information through to code generation. Re-inferring an operator from an Int32 constant heap slot can otherwise discard the constant conversion that made an unsigned operation valid. Evaluate integral constant expressions used for operator binding, including const locals and fields, parentheses, unary/binary operations and integral casts. Track const local values separately from ordinary initialized locals, bound recursive evaluation, and preserve integer width for shift evaluation. Merge the recorded promotions across checked files and retain fallback promotion for synthesized operations that have no checked expression. Add regressions using a const field, a const local and arithmetic constant expressions with ulong operations and comparisons. Also check byte compound assignment with a const local and a masked constant shift. These tests cover the supported binding cases, not every C# constant-expression form.
Write positive and negative floating-point infinity as Infinity and -Infinity in compiler-generated heap metadata. Rust's Debug formatting uses inf and -inf, which Unity 2022.3 Mono's invariant-culture Parse rejects. The compiler owns this interchange format; keep the Unity importer unchanged. Preserve the existing finite-value and NaN formatting for both Single and Double. Previously generated inf metadata must be regenerated with the updated compiler. Add a serialization regression covering both types, both infinities, NaN, a finite value and signed zeros. Add eight Unity decoder cases checking the emitted spellings and exact boxed types through the existing importer.
Collaborator
|
thanks! LGTM! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Improve numeric handling to more closely match C# 9 behavior.
uint,long, andulong, preserving exception behavior.Environment
Notes
This pull request was prepared with assistance from OpenAI Codex (GPT-6), including implementation, test preparation, and investigation.
Please feel free to revise the code, tests, commit organization, or wording to better match the project's coding style and conventions.