8000 refactor: handle any json number by peter-jerry-ye · Pull Request #2370 · moonbitlang/core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

refactor: handle any json number #2370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 8, 2025
Merged

refactor: handle any json number #2370

merged 4 commits into from
Jul 8, 2025

Conversation

peter-jerry-ye
Copy link
Collaborator
@peter-jerry-ye peter-jerry-ye commented Jun 27, 2025

Closes #1366

This implementation will introduce new field in Json::Number to hold the representation of the Json number that can't be put into a Double.

The current implementation will decide during parsing, to use the repr : String? to hold the representations, if:

  • it's an integer (not written with exponential or decimal point) that can't be safely represented by the Double
  • it's a double that failed parsing

The corresponding value will be +/- inf, which aligns with the behavior of Json.parse in JS.

The implementation of Eq will compare only the number part and ignore the representation part.

Copy link
peter-jerry-ye-code-review bot commented Jun 27, 2025
Inconsistent pattern matching for Number variant across codebase

Category
Correctness
Code Snippet
Lines 67, 89: guard json is Number(n, ..) &&
Lines 53, 62: match n { Number(n) => ints_result.push(n.to_int())
Recommendation
Update all pattern matching to use consistent syntax: Number(n, ..) instead of Number(n) to handle the new repr field
Reasoning
The old pattern matching syntax Number(n) will fail to compile with the new Number variant that has two fields. All pattern matches need to use the destructuring syntax Number(n, ..) to ignore the repr field when not needed.

Redundant integer parsing and conversion in lex_number_end

Category
Performance
Code Snippet
Lines 158-168: let parsed_int = try? @strconv.parse_int64(s)
match parsed_int {
Ok(i) if i <= 9007199254740991 && i >= -9007199254740991 =>
return (i.to_double(), None)
Recommendation
Consider parsing directly as double first and only fall back to string representation for special cases (infinity/out-of-range), avoiding the double parsing overhead for most numbers
Reasoning
The current implementation parses integers first as Int64, then converts to Double, which adds unnecessary overhead. Most JSON numbers can be parsed directly as Double, with special handling only needed for edge cases.

Magic number constants should be extracted as named constants

Category
Maintainability
Code Snippet
Lines 159: if i <= 9007199254740991 && i >= -9007199254740991 =>
Lines 194: self < 0xFFEFFFFFFFFFFFFFL.reinterpret_as_double()
Recommendation
Extract these as named constants like max_safe_integer = 9007199254740991L and max_finite_double = 0xFFEFFFFFFFFFFFFFL.reinterpret_as_double()
Reasoning
Magic numbers reduce code readability and maintainability. Named constants make the intent clear and prevent errors when these values need to be updated or reused elsewhere.

@coveralls
Copy link
Collaborator
coveralls commented Jun 27, 2025

Pull Request Test Coverage Report for Build 252

Details

  • 26 of 28 (92.86%) changed or added relevant lines in 6 files are covered.
  • 1 unchanged line in 1 file lost coverage.
  • Overall coverage decreased (-0.04%) to 89.151%

Changes Missing Coverage Covered Lines Changed/Added Lines %
json/lex_number.mbt 11 13 84.62%
Files with Coverage Reduction New Missed Lines %
json/lex_number.mbt 1 94.92%
Totals Coverage Status
Change from base Build 239: -0.04%
Covered Lines: 3476
Relevant Lines: 3899

💛 - Coveralls

@FlyCloudC
Copy link
Contributor

What should be the expected results of the following two expressions?

@json.parse("1e2") == @json.parse("100")

@json.parse("1000000000000000000001") == 
@json.parse("1000000000000000000002")

@peter-jerry-ye
Copy link
Collaborator Author

If we are lucky enough, the first should be equal, and the second would not be equal. Currently the parsing doesn't consider the safe max integer.

One thing we can do is to decide whether it is floating. If it's not, only convert the number that is safe.

But anyway, you are handling Double, so take caution.

@peter-jerry-ye peter-jerry-ye marked this pull request as ready for review July 4, 2025 07:10
@peter-jerry-ye peter-jerry-ye requested a review from bobzhang July 4, 2025 07:10
@peter-jerry-ye peter-jerry-ye force-pushed the migrate-json branch 2 times, most recently from 6f03124 to 2724e15 Compare July 4, 2025 07:27
@bobzhang
Copy link
Contributor
bobzhang commented Jul 7, 2025

let's get this landed in the next release, we can make some time for the AI to upgrade most packages

@peter-jerry-ye peter-jerry-ye force-pushed the migrate-json branch 2 times, most recently from 9491cfb to 78782d4 Compare July 8, 2025 02:20
@peter-jerry-ye peter-jerry-ye enabled auto-merge (rebase) July 8, 2025 02:21
@peter-jerry-ye peter-jerry-ye merged commit 653aa03 into main Jul 8, 2025
10 of 14 checks passed
@peter-jerry-ye peter-jerry-ye deleted the migrate-json branch July 8, 2025 02:25
(Array(a_arr), Array(b_arr)) => a_arr == b_arr
(Object(a_obj), Object(b_obj)) => a_obj == b_obj
_ => false
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

match a {
Null => b is Null
...
}

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.

Extend JSON to include Int64, UInt64, Arbitrary(String)
4 participants
0