Skip to content
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

Upgrade exponentiation to unified operator #7153

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

cometkim
Copy link
Member

@cometkim cometkim commented Nov 9, 2024

Also make its output to use ES7 exponentiation (**) operator.

** is more concise, faster than Math.pow(),
works well with all numeric types include bigint.

We were already using it for bigint, now for int and float too.

let int32_pow ?comment (e1 : t) (e2 : t) : J.expression =
match (e1.expression_desc, e2.expression_desc) with
| Number (Int {i = i1}), Number (Int {i = i2}) ->
int ?comment (Ext_int.int32_pow i1 i2)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Have you checked that this is semantically equivalent to js power, or whatever Pow does below?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is different from js pow, especially when overflow. If I leave js pow out, wouldn't it cause undefined behavior in ReScript, like values ​​greater than max_int?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, seems it is already possible by n ** n

Copy link
Collaborator

Choose a reason for hiding this comment

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

The intended question is: does the case with constants behave exactly like when 2 variables with the same constant values are passed?

Copy link
Member Author

Choose a reason for hiding this comment

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

added more tests to verify it

compiler/syntax/src/res_parens.ml Show resolved Hide resolved
Also make its output to use ES7 exponentiation (`**`) operator.

`**` is more concise, faster than `Math.pow()`,
works well with all numeric types include bigint.

We were already using it for bigint, now for int and float too.
@cometkim
Copy link
Member Author

cometkim commented Nov 10, 2024

I think (x ** y | 0) is not very same as the current behavior of %mul, which uses Math.imul() for ints

The problem is that to match the semantics we need to perform the modulo operation ourselves, which is quite expensive at runtime.

@cometkim
Copy link
Member Author

Well, I guess I'll have to propose new int semantics to fix it, but that would be a pretty breaking change.

It seems very weird now that all other operations use int32 coercion, but only multiplication has a different behavior.

@cristianoc
Copy link
Collaborator

I think (x ** y | 0) is not very same as the current behavior of %mul, which uses Math.imul() for ints

The problem is that to match the semantics we need to perform the modulo operation ourselves, which is quite expensive at runtime.

What is the difference, in short?

@cristianoc
Copy link
Collaborator

Oh you mean (x * y) | 0 vs Math.imul(x, y)?

@cometkim
Copy link
Member Author

(discussing in rescript-lang/rfcs#1)

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