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

Normative: Add new BigInt primitive #1515

Open
wants to merge 41 commits into
base: master
from

Conversation

Projects
None yet
7 participants
@caiolima
Copy link
Contributor

commented Apr 23, 2019

This PR is include changes to integrate tc39/proposal-bigint into ECMA262 text. It contains changes on:

  1. Grammar to support BigInt literals.
  2. Abstract Operations to consider this new primitive.
  3. Semantics of arithmetic expressions to support BigInts.
  4. The specification of BigInt objects, including the constructor and BigInt.prototype.
  5. Including BigInt64Array and BigUint64Array as new types of TypedArray.
  6. Changes on DataView operations to support new types.

Proposal author: Daniel Ehrenberg and Brendan Eich

Show resolved Hide resolved spec.html
@annevk

This comment has been minimized.

Copy link
Member

commented Apr 24, 2019

Should this land after #1135?

@littledan

This comment has been minimized.

Copy link
Member

commented Apr 24, 2019

@annevk Yes.

Show resolved Hide resolved spec.html Outdated
Show resolved Hide resolved spec.html Outdated
Show resolved Hide resolved spec.html
@jmdyck

This comment has been minimized.

Copy link
Collaborator

commented Apr 26, 2019

I've got a bunch of suggested changes. I think it might be best to submit them as a PR against caiolima:big-int.

@littledan

This comment has been minimized.

Copy link
Member

commented Apr 26, 2019

@jmdyck That's great to hear. Looking forward to seeing your PR.

@jmdyck

This comment has been minimized.

Copy link
Collaborator

commented Apr 29, 2019

Done: caiolima#3

@littledan
Copy link
Member

left a comment

LGTM!

It'd be great to have reviews from the editors for this PR ahead of the June 2019 TC39 meeting, where Caio and I plan to propose BigInt for Stage 4. cc @ljharb @zenparsing

@caiolima

This comment has been minimized.

Copy link
Contributor Author

commented May 2, 2019

@littledan FYI, there are new changes from caiolima#4.

jmdyck added a commit to jmdyck/ecma262 that referenced this pull request May 28, 2019

Editorial: Define + use StringToNumber and NumericValue
Formerly, the procedure for applying ToNumber to the String type
was spread over three widely-separated prose paragraphs
in two different clauses.

This commit brings all that together, expresses it as an actual algorithm,
and gives it the name StringToNumber.

Similarly for the value of a NumericLiteral, here expressed as
the syntax-directed operation NumericValue.

This commit should provide better integration-points for PR tc39#1515 (BigInt).

@ljharb ljharb force-pushed the caiolima:big-int branch from 383d96d to 43cda21 Jun 6, 2019

@caiolima caiolima force-pushed the caiolima:big-int branch from 43cda21 to 5fd98ab Jun 14, 2019

@ljharb

This comment has been minimized.

Copy link
Member

commented Jul 4, 2019

@caiolima i've merged #1135; can you rebase this?

jmdyck added a commit to jmdyck/ecma262 that referenced this pull request Jul 5, 2019

Editorial: Define + use StringToNumber and NumericValue
Formerly, the procedure for applying ToNumber to the String type
was spread over three widely-separated prose paragraphs
in two different clauses.

This commit brings all that together, expresses it as an actual algorithm,
and gives it the name StringToNumber.

Similarly for the value of a NumericLiteral, here expressed as
the syntax-directed operation NumericValue.

This commit should provide better integration-points for PR tc39#1515 (BigInt).

caiolima and others added some commits Apr 16, 2019

Normative: Add new BigInt type
This PR includes changes over current ECMA262 spec text to include
a new primitive type called BigInt. This includes all changes necessary
to integrate this new primitive in the language. It also includes
changes on TypedArray, introducing `BigInt64Array` and `BigUint64Array`
Relocate new property-clauses
(Specifically, properties of DataView.prototype
and the BigInt constructor.)

When sibling clauses specify the properties of an object,
we usually list them in alphabetical order.
Move some new abstract op clauses.
In the "Type Conversion" clause, rather than simply
putting all the new abstract operations at the end,
move them to more logical locations.

jmdyck and others added some commits Apr 28, 2019

Rename "BitwiseOp" as "BigIntBitwiseOp"
.. for symmetry with NumberBitwiseOp.

Also, add an 'aoid' attribute to the clause.
Change "may not" to "cannot".
The problem with "may not" is that it can be read as "might or might not",
which is not the intended interpretation.
Replace "ToString Applied to the BigInt Type" with "BigIntToString"
A named abstract operation is better.

(I'll propose the symmetric change for Number.)
Rename 'NumericLiteralBase' to 'NonDecimalIntegerLiteral'
It more clearly expresses what it is,
and it fits nicely with 'DecimalIntegerLiteral'.
In "Numeric Type Operations" table, split "Value and Purpose" into 3 …
…columns

Tease apart different kinds of info,
add some info, reduce some repetition.
Delete some blank lines.
We don't usually put a blank line before an <emu-alg>.
Change several '?' to '!'
ToInt32 and ToUint32 applied to a Number always return normally.

::add, ::subtract, ::unaryMinus, and ::bitwiseNOT always return normally.
Add ::toString() as a numeric type operation.
Rename (and relocate)
    NumberToString as Number::toString,
    BigIntToString as BigInt::toString
Minor internal tweaks to Foo::toString
Use consistent parameter name _x_.

In BigInt::toString, invoke BigInt::toString directly,
rather than via ToString.
Typo getbituint64 -> getbiguint64 in ID/anchor
This change fixes the permalink for the DataView.prototype.getBigUint64
section such that the link URL has #sec-dataview.prototype.getbiguint64
as its fragment ID, as expected.

Without this change, the link URL in that section permalink otherwise
unexpectedly has the fragment ID #sec-dataview.prototype.getbituint64
(`getbit` rather than `getbig`).

@caiolima caiolima force-pushed the caiolima:big-int branch from c0a1357 to 1716862 Jul 5, 2019

@caiolima

This comment has been minimized.

Copy link
Contributor Author

commented Jul 5, 2019

@caiolima i've merged #1135; can you rebase this?

@ljharb done.

Many expressions and built-in functions, via <emu-xref href="#sec-tostring" title></emu-xref>
</td>
<td>
String

This comment has been minimized.

Copy link
@ljharb

ljharb Jul 5, 2019

Member

might this also throw, if say the bigint is quite large?

This comment has been minimized.

Copy link
@caiolima

caiolima Jul 9, 2019

Author Contributor

It can, from an implementation point of view, but from the spec side, I don't think so. IIUC, there is no limit on size of Strings and BigInts on spec. Given that, I don't think we can throw when there is a very large BigInt, but I might be missing something here.


<emu-clause id="sec-ecmascript-language-types-number-type">
<h1>The Number Type</h1>
<p>The Number type has exactly 18437736874454810627<sub>ℝ</sub> (that is, <emu-eqn>2<sub>ℝ</sub><sup>64<sub>ℝ</sub></sup> - 2<sub>ℝ</sub><sup>53<sub>ℝ</sub></sup> + 3<sub>ℝ</sub></emu-eqn>) values, representing the double-precision 64-bit format IEEE 754-2008 values as specified in the IEEE Standard for Binary Floating-Point Arithmetic, except that the 9007199254740990<sub>ℝ</sub> (that is, <emu-eqn>2<sub>ℝ</sub><sup>53<sub>ℝ</sub></sup> - 2<sub>ℝ</sub></emu-eqn>) distinct &ldquo;Not-a-Number&rdquo; values of the IEEE Standard are represented in ECMAScript as a single special *NaN* value. (Note that the *NaN* value is produced by the program expression `NaN`.) In some implementations, external code might be able to detect a difference between various Not-a-Number values, but such behaviour is implementation-dependent; to ECMAScript code, all *NaN* values are indistinguishable from each other.</p>

This comment has been minimized.

Copy link
@ljharb

ljharb Jul 5, 2019

Member

all NaN values are indistinguishable from each other.

I believe this is incorrect, due to a lack of canonicalization on TypedArrays (despite the next paragraph, this still somewhat stands alone)

This comment has been minimized.

Copy link
@caiolima

caiolima Jul 9, 2019

Author Contributor

I'm not an expert on NaN, but this is part of current text on spec. Maybe we should fix this on a separated PR. WDYT?

<li>If _base_ &lt; 0 and _base_ is finite and _exponent_ is finite and _exponent_ is not an integer, the result is *NaN*.</li>
</ul>
<emu-note>
<p>The result of _base_ `**` _exponent_ when _base_ is *1* or *-1* and _exponent_ is *+Infinity* or *-Infinity* differs from IEEE 754-2008. The first edition of ECMAScript specified a result of *NaN* for this operation, whereas later versions of IEEE 754-2008 specified *1*. The historical ECMAScript behaviour is preserved for compatibility reasons.</p>

This comment has been minimized.

Copy link
@ljharb

ljharb Jul 5, 2019

Member

commenting here to note the interaction with #1609

<emu-clause id="sec-numeric-types-bigint-unaryMinus">
<h1>BigInt::unaryMinus ( _x_ )</h1>
<p>The abstract operation BigInt::unaryMinus with an argument _x_ of type BigInt returns the result of negating _x_.</p>
<emu-note>There is only one *0n* value; `-0n` is the same as *0n*.</emu-note>

This comment has been minimized.

Copy link
@ljharb

ljharb Jul 5, 2019

Member

instead of a note, can this be an explicit algorithm step?

This comment has been minimized.

Copy link
@caiolima

caiolima Jul 9, 2019

Author Contributor

I have no strong opinion here, but I', not sure how to transform this note into an algorithm step. Would it be something like the code below?

...
Return 0n if _x_ is 0n.
...

This comment has been minimized.

Copy link
@ljharb

ljharb Jul 9, 2019

Member

yes, something like that seems great - most numeric methods have special early-return cases for zeroes, infinities, and NaN.

Show resolved Hide resolved spec.html
spec.html Outdated
@@ -33840,7 +34919,7 @@ <h1>%TypedArray%.prototype.sort ( _comparefn_ )</h1>
<p>The following version of SortCompare is used by %TypedArray%`.prototype.sort`. It performs a numeric comparison rather than the string comparison used in <emu-xref href="#sec-array.prototype.sort"></emu-xref>. SortCompare has access to the _comparefn_ and _buffer_ values of the current invocation of the `sort` method.</p>
<p>When the TypedArray SortCompare abstract operation is called with two arguments _x_ and _y_, the following steps are taken:</p>
<emu-alg>
1. Assert: Both Type(_x_) and Type(_y_) is Number.
1. Assert: Both Type(_x_) and Type(_y_) is Number or both are BigInt.

This comment has been minimized.

Copy link
@ljharb

ljharb Jul 5, 2019

Member
Suggested change
1. Assert: Both Type(_x_) and Type(_y_) is Number or both are BigInt.
1. Assert: Both Type(_x_) and Type(_y_) are Number or both are BigInt.
spec.html Outdated
@@ -34029,6 +35108,7 @@ <h1>_TypedArray_ ( _typedArray_ )</h1>
1. Else,
1. Let _data_ be ? AllocateArrayBuffer(_bufferConstructor_, _byteLength_).
1. If IsDetachedBuffer(_srcData_) is *true*, throw a *TypeError* exception.
1. If one of _srcType_ and _elementType_ contains the substring `"Big"` and the other does not, throw a *TypeError* exception.

This comment has been minimized.

Copy link
@ljharb

ljharb Jul 5, 2019

Member

ditto here

spec.html Outdated
1. Return ? TypedArrayCreate(_constructor_, _argumentList_).
1. Let _result_ be ? TypedArrayCreate(_constructor_, _argumentList_).
1. Assert: _result_ has a [[TypedArrayName]] internal slot.
1. If _result_.[[TypedArrayName]] contains the substring `"Big"` and _exemplar_.[[TypedArrayName]] does not contain the substring `"Big"`, or vice versa, throw a *TypeError* exception.

This comment has been minimized.

Copy link
@ljharb

ljharb Jul 5, 2019

Member

and here - at the very least, let's make an abstract operation instead of repeating this check multiple times

@@ -35274,21 +36358,21 @@ <h1>GetValueFromBuffer ( _arrayBuffer_, _byteIndex_, _type_, _isTypedArray_, _or
1. If IsSharedArrayBuffer(_arrayBuffer_) is *true*, then
1. Let _execution_ be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
1. Let _eventList_ be the [[EventList]] field of the element in _execution_.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
1. If _isTypedArray_ is *true* and _type_ is `"Int8"`, `"Uint8"`, `"Int16"`, `"Uint16"`, `"Int32"`, or `"Uint32"`, let _noTear_ be *true*; otherwise let _noTear_ be *false*.
1. If _isTypedArray_ is *true* and _type_ is `"Int8"`, `"Uint8"`, `"Int16"`, `"Uint16"`, `"Int32"`, or `"Uint32"` or if _type_ is `"BigInt64"` or `"BigUint64"` and _order_ is not `"Init"` or `"Unordered"`, let _noTear_ be *true*; otherwise let _noTear_ be *false*.

This comment has been minimized.

Copy link
@ljharb

ljharb Jul 5, 2019

Member
Suggested change
1. If _isTypedArray_ is *true* and _type_ is `"Int8"`, `"Uint8"`, `"Int16"`, `"Uint16"`, `"Int32"`, or `"Uint32"` or if _type_ is `"BigInt64"` or `"BigUint64"` and _order_ is not `"Init"` or `"Unordered"`, let _noTear_ be *true*; otherwise let _noTear_ be *false*.
1. If _isTypedArray_ is *true* and _type_ is `"Int8"`, `"Uint8"`, `"Int16"`, `"Uint16"`, `"Int32"`, or `"Uint32"`, or if _type_ is `"BigInt64"` or `"BigUint64"` and _order_ is not `"Init"` or `"Unordered"`, let _noTear_ be *true*; otherwise let _noTear_ be *false*.

this might be clearer if it was split up - or perhaps moved to an abstract operation.

1. If IsSharedArrayBuffer(_arrayBuffer_) is *true*, then
1. Let _execution_ be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
1. Let _eventList_ be the [[EventList]] field of the element in _execution_.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
1. If _isTypedArray_ is *true* and _type_ is `"Int8"`, `"Uint8"`, `"Int16"`, `"Uint16"`, `"Int32"`, or `"Uint32"`, let _noTear_ be *true*; otherwise let _noTear_ be *false*.
1. If _isTypedArray_ is *true* and _type_ is `"Int8"`, `"Uint8"`, `"Int16"`, `"Uint16"`, `"Int32"`, or `"Uint32"`, or if _type_ is `"BigInt64"` or `"BigUint64"` and _order_ is not `"Init"` or `"Unordered"`, let _noTear_ be *true*; otherwise let _noTear_ be *false*.

This comment has been minimized.

Copy link
@ljharb

ljharb Jul 5, 2019

Member

the repetition of this complex line makes me want an abstract operation for this even more

@@ -34798,6 +34798,22 @@ <h1>%TypedArray%.prototype.set ( _array_ [ , _offset_ ] )</h1>
</emu-alg>
</emu-clause>

<emu-clause id="sec-is-compatible-typed-array-type" aoid="IsCompatibleTypedArrayType">
<h1>IsCompatibleTypedArrayType ( _type_ , _otherType_ )</h1>

This comment has been minimized.

Copy link
@ljharb

ljharb Jul 9, 2019

Member

what does "is compatible" mean? why would Uint8ClampedArray and Float32Array be "compatible"?

This comment has been minimized.

Copy link
@caiolima

caiolima Jul 10, 2019

Author Contributor

I agree this name is not quite good. I'm changing this to IsCopyableTypedArrayType and use Types instead of the constructor name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.