Skip to content

bigInt comparision #6097

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 17 commits into from
Mar 26, 2023
Merged

bigInt comparision #6097

merged 17 commits into from
Mar 26, 2023

Conversation

jmagaram
Copy link
Contributor

@jmagaram jmagaram commented Mar 26, 2023

Support bigInt comparison. Fix for #6096
Some comments and questions:

  • The different syntax compared to ReScript really was tough. I didn't realize there was a <> or =.
  • A CodeSpace might have been easier for setting up the environment. I got the error "No config found for file jscomp/runtime/caml_obj.ml. Try calling dune build. Compiler version mismatch: this project seems to be compiled with version 4.06 of the OCaml compiler, but the running ocamllsp supports OCaml version 4.14. OCaml language support will not work properly until this problem is fixed. And I couldn't figure out how to fix this. and so had lots of red squiggly errors though things seemed to compile and tests pass.
  • I wasn't sure if comparing different types is a legal operation in OCaml. So all the tests compare bigInt with bigInt even though in JavaScript you can compare bigInt with float.
  • In compare there is a clause about if b == Obj.repr Js.null || Caml_option.isNested b. I didn't understand this. Just added bigInt as another condition.
  • In equal did not understand the part about b_type = "number" || b_type = "bigint" || b_type = "undefined". Confused about why this isn't parallel to the checks on a_type that include string and boolean.
  • For my tests I couldn't access parts of the Obj module directly like lessthan - just could get to compare (global namespace somehow) and the operators. But my tests look similar to the other compare tests, so probably ok.
  • I didn't want to mess up the existing compare tests so I put mine in a separate file.
  • There is a lot of "number" in the code. So maybe other places need work to support BigInt? It was too much for me to get my head around.

@cristianoc
Copy link
Collaborator

cristianoc commented Mar 26, 2023

This is a good opportunity to convert to .res syntax. Sorry that wasted some time.
bsc -format file.ml >file.res

Then the 2 functions that show up in the output, we don't want them. If you make them private they won't.

@cristianoc
Copy link
Collaborator

@cristianoc
Copy link
Collaborator

  • I wasn't sure if comparing different types is a legal operation in OCaml. So all the tests compare bigInt with bigInt even though in JavaScript you can compare bigInt with float.

Once they're converted to ReScript this is less confusing. This is just a ReScript file, and we really only care about the generated JS, which goes into a library shipped with the compiler. So their idea is: whatever gives the desired JS is good.
Equivalently, tests can do whatever necessary so the generated .js code performs the desired test on the compiler output.

@cristianoc
Copy link
Collaborator

In general, we want to limit the number of tests in the compiler. For test running speed and maintenance reasons.
These would be a bit much for such a small change, but since there were so few tests about compare, it seems just about right to me.

@cristianoc
Copy link
Collaborator

cristianoc commented Mar 26, 2023

  • In compare there is a clause about if b == Obj.repr Js.null || Caml_option.isNested b. I didn't understand this. Just added bigInt as another condition.

If such a condition is not already there for number and string, then it's very unlikely that it will be needed for bigint.

@jmagaram
Copy link
Contributor Author

For the main file I converted to ReScript and did the same with the mli. Is that what you want? The resi doesn't mention the helper functions and neither did the mli so I don't know what needs to be private.

@jmagaram
Copy link
Contributor Author

jmagaram commented Mar 26, 2023

The test file could be res too. But it looks weird. This doesn't look like a LIST or an ARRAY. Not sure what it is supposed to be.

let suites: Mt.pair_suites = \"@"(
  isLessThan("123 and 555555", bigint("123"), bigint("555555")),
  \"@"(
    isEqual("98765 and 98765", bigint("98765"), bigint("98765")),
    isEqual("same instance", five, five),
  ),
)

Left this as-is after automatic conversion. Tests seem to run.

Copy link
Collaborator

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

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

Left some small comments.
Not sure why the code generated by compare has changed so much, let me take a look and get back.

@@ -42,11 +42,20 @@ function compare(a, b) {
}
var a_type = typeof a;
var b_type = typeof b;
var exit = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

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

There are all these exit now. Let me take a look at the changes in the source and see what might have caused this.

function notequal(a, b) {
if (typeof a === "number" && typeof b === "number") {
if (canNumericCompare(a, b)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's better inlined.
I suspect this will be inlined again once canNumericCompare is made a private function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure it is re-building. I changed it to == number or == string or == bigint but the javascript is the same. What command to build with rescript? make lib not doing it. I have the reScript extension on my computer and installed Rescript into package.json.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Need to go to sleep. Do you think I need tests related to comparing bigInt and float? In JavaScript you can type bigInt < 3.0 but I think ReScript prevents this unless you do an unsafe cast. Will look at this in the morning.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I can take it from here. Thanks for this!

@cristianoc
Copy link
Collaborator

The test file could be res too. But it looks weird. This doesn't look like a LIST or an ARRAY. Not sure what it is supposed to be.

let suites: Mt.pair_suites = \"@"(
  isLessThan("123 and 555555", bigint("123"), bigint("555555")),
  \"@"(
    isEqual("98765 and 98765", bigint("98765"), bigint("98765")),
    isEqual("same instance", five, five),
  ),
)

Left this as-is after automatic conversion. Tests seem to run.

I think it's OK. That's a custom infix operator. It's going to be defined somewhere.
One can just define it with a human function name instead.

Copy link
Collaborator

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

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

You removed .ml but forgot to remove .mli

Copy link
Collaborator

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

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

OK found what was causing the code to change that much.
After this, it should be pretty much ready to merge.

Thanks for doing this!!!

| ("bigint", "bigint")
| ("number", "number") =>
Pervasives.compare((Obj.magic(a): float), (Obj.magic(b): float))
| ("bigint", _) | ("number", _) =>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you remove this change?
The type system does not let us compare bigint and int.
The only reason to care about this is this change complicates the generated code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry not totally understanding. Do you want me to take out the bigint on this line? The check above I think is essential.

   | ("bigint", "bigint")
    | ("number", "number") =>
      Pervasives.compare((Obj.magic(a): float), (Obj.magic(b): float))
>>>    | ("bigint", _) | ("number", _) =>
      if b === Obj.repr(Js.null) || Caml_option.isNested(b) {
        1
      } else {
        /* Some (Some ..) < x */

/* Some (Some ..) < x */
-1
} /* Integer < Block in OCaml runtime GPR #1195, except Some.. */
| (_, "bigint") | (_, "number") =>
Copy link
Collaborator

Choose a reason for hiding this comment

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

This too

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And this line switch back to just "number"?

        -1
      } /* Integer < Block in OCaml runtime GPR #1195, except Some.. */
>>>>    | (_, "bigint") | (_, "number") =>
      if a === Obj.repr(Js.null) || Caml_option.isNested(a) {
        -1

@cristianoc
Copy link
Collaborator

  • A CodeSpace might have been easier for setting up the environment. I got the error "No config found for file jscomp/runtime/caml_obj.ml. Try calling dune build. Compiler version mismatch: this project seems to be compiled with version 4.06 of the OCaml compiler, but the running ocamllsp supports OCaml version 4.14. OCaml language support will not work properly until this problem is fixed. And I couldn't figure out how to fix this. and so had lots of red squiggly errors though things seemed to compile and tests pass.

I think if one follows the instructions in the contributing doc these issue should not arise.
If they do, feel free to clarify the contributing docs if it's missing something or it's unclear.

@cristianoc
Copy link
Collaborator

make lib is the command to update the library files

It's done automatically every time you do make test

jmagaram and others added 4 commits March 26, 2023 00:29
Copy link
Collaborator

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

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

Should be OK now.
I'll merge a little later.

@jmagaram
Copy link
Contributor Author

jmagaram commented Mar 26, 2023

make lib is the command to update the library files

It's done automatically every time you do make test

Sorry not working for me. After I mangle the isNumberOrBigInt function it still just checks for "number" or "bigint". Have tried make lib and make test.

I'm going to bed. You can take it from here if you want. Or I'll try in the morning.

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.

2 participants