Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 85 additions & 85 deletions spec.emu
Original file line number Diff line number Diff line change
Expand Up @@ -229,52 +229,53 @@ location: https://tc39.es/proposal-amount/
</emu-alg>
</emu-clause>

<emu-clause id="sec-amount-createformatterobject" type="abstract operation">
<h1>CreateFormatterObject (
_roundingMode_: a String,
_minFractionDigits_: a non-negative integer or *undefined*,
_maxFractionDigits_: a non-negative integer or *undefined*,
_minSignificantDigits_: a positive integer or *undefined*,
_maxSignificantDigits_: a positive integer or *undefined*,
_roundingPriority_: a String or *undefined*
): an Object
<emu-clause id="sec-amount-renderamountvaluewithprecision" type="abstract operation">
<h1>
RenderAmountValueWithPrecision (
_mv_: a mathematical value or ~negative-zero~,
_opts_: an Amount Options Record,
): a String
</h1>
<dl class="header">
<dt>description</dt>
<dd>It creates an object with the internal slots required by <emu-xref href="#sec-formatnumerictostring">FormatNumericToString</emu-xref>, configured according to the given rounding and digit options.</dd>
<dd>It rounds _mv_ according to the precision options of _opts_, which must specify either a number of fraction digits or a number of significant digits, and renders the result in canonical exponential notation with the digit count implied by those options. The sign of _mv_ is preserved, and a negative value that rounds to zero is rendered as negative zero.</dd>
</dl>
<emu-alg>
1. Let _formatter_ be OrdinaryObjectCreate(*null*, « [[MinimumFractionDigits]], [[MinimumIntegerDigits]], [[MinimumSignificantDigits]], [[MaximumFractionDigits]], [[MaximumSignificantDigits]], [[RoundingIncrement]], [[RoundingMode]], [[RoundingType]], [[TrailingZeroDisplay]] »).
1. Set _formatter_.[[RoundingMode]] to _roundingMode_.
1. Set _formatter_.[[MinimumIntegerDigits]] to 1.
1. Set _formatter_.[[RoundingIncrement]] to 1.
1. Set _formatter_.[[TrailingZeroDisplay]] to *"auto"*.
1. If _minSignificantDigits_ is not *undefined* or _maxSignificantDigits_ is not *undefined*, let _hasSD_ be *true*; else let _hasSD_ be *false*.
1. If _minFractionDigits_ is not *undefined* or _maxFractionDigits_ is not *undefined*, let _hasFD_ be *true*; else let _hasFD_ be *false*.
1. If _hasSD_ is *true*, then
1. If _minSignificantDigits_ is not *undefined*, let _resolvedMinSD_ be _minSignificantDigits_; else let _resolvedMinSD_ be 1.
1. If _maxSignificantDigits_ is not *undefined*, let _resolvedMaxSD_ be _maxSignificantDigits_; else let _resolvedMaxSD_ be 21.
1. Set _formatter_.[[MinimumSignificantDigits]] to _resolvedMinSD_.
1. Set _formatter_.[[MaximumSignificantDigits]] to _resolvedMaxSD_.
1. Else,
1. Set _formatter_.[[MinimumSignificantDigits]] to 1.
1. Set _formatter_.[[MaximumSignificantDigits]] to 21.
1. If _hasFD_ is *true*, then
1. If _minFractionDigits_ is not *undefined*, let _resolvedMinFD_ be _minFractionDigits_; else let _resolvedMinFD_ be 0.
1. If _maxFractionDigits_ is not *undefined*, let _resolvedMaxFD_ be _maxFractionDigits_; else let _resolvedMaxFD_ be 100.
1. Set _formatter_.[[MinimumFractionDigits]] to _resolvedMinFD_.
1. Set _formatter_.[[MaximumFractionDigits]] to _resolvedMaxFD_.
1. If _mv_ is ~negative-zero~, then
1. Let _sign_ be ~negative~.
1. Let _x_ be 0.
1. Else if _mv_ &lt; 0, then
1. Let _sign_ be ~negative~.
1. Let _x_ be -_mv_.
1. Else,
1. Set _formatter_.[[MinimumFractionDigits]] to 0.
1. Set _formatter_.[[MaximumFractionDigits]] to 100.
1. If _hasSD_ is *true* and _hasFD_ is *true*, then
1. If _roundingPriority_ is *"morePrecision"*, set _formatter_.[[RoundingType]] to ~more-precision~; else set _formatter_.[[RoundingType]] to ~less-precision~.
1. Else if _hasSD_ is *true*, then
1. Set _formatter_.[[RoundingType]] to ~significant-digits~.
1. Let _sign_ be ~positive~.
1. Let _x_ be _mv_.
1. Let _fractionDigits_ be _opts_.[[FractionDigits]].
1. Let _significantDigits_ be _opts_.[[SignificantDigits]].
1. If _x_ = 0, then
1. Let _r_ be 0.
1. If _fractionDigits_ is not *undefined*, let _digitCount_ be _fractionDigits_ + 1; else let _digitCount_ be _significantDigits_.
1. Else,
1. Set _formatter_.[[RoundingType]] to ~fraction-digits~.
1. Return _formatter_.
1. Let _unsignedRoundingMode_ be GetUnsignedRoundingMode(_opts_.[[RoundingMode]], _sign_).
1. If _fractionDigits_ is not *undefined*, then
1. Let _r1_ be the largest mathematical value such that _r1_ ≤ _x_ and _r1_ × 10<sup>_fractionDigits_</sup> is an integer.
1. Let _r2_ be the smallest mathematical value such that _r2_ ≥ _x_ and _r2_ × 10<sup>_fractionDigits_</sup> is an integer.
1. Let _r_ be ApplyUnsignedRoundingMode(_x_, _r1_, _r2_, _unsignedRoundingMode_).
1. If _r_ = 0, let _digitCount_ be _fractionDigits_ + 1; else let _digitCount_ be the number of digits in the decimal representation of _r_ × 10<sup>_fractionDigits_</sup>.
1. Else,
1. Assert: _significantDigits_ is not *undefined*.
1. Let _r1_ be the largest mathematical value such that _r1_ ≤ _x_ and _r1_ is the product of an integer in the inclusive interval from 10<sup>_significantDigits_ - 1</sup> to 10<sup>_significantDigits_</sup> - 1 and an integer power of 10.
1. Let _r2_ be the smallest mathematical value such that _r2_ ≥ _x_ and _r2_ is the product of an integer in the inclusive interval from 10<sup>_significantDigits_ - 1</sup> to 10<sup>_significantDigits_</sup> - 1 and an integer power of 10.
1. Let _r_ be ApplyUnsignedRoundingMode(_x_, _r1_, _r2_, _unsignedRoundingMode_).
1. Let _e_ be the unique integer such that 10<sup>_e_</sup> ≤ _r_ &lt; 10<sup>_e_ + 1</sup>.
1. Let _digitCount_ be max(_significantDigits_, _e_ + 1).
1. If _sign_ is ~negative~, then
1. If _r_ = 0, set _r_ to ~negative-zero~; else set _r_ to -_r_.
1. Return RenderInExponentialNotation(_r_, _digitCount_).
</emu-alg>
<emu-note type="editor">
<p>The rounding steps restate those of ECMA-402 <emu-xref href="#sec-torawfixed">ToRawFixed</emu-xref>, with a rounding increment of 1, and <emu-xref href="#sec-torawprecision">ToRawPrecision</emu-xref>. We intend to extract them into operations that ECMA-402 calls too.</p>
</emu-note>
</emu-clause>

<emu-clause id="sec-amount-unit-conversion-data">
Expand Down Expand Up @@ -334,6 +335,34 @@ location: https://tc39.es/proposal-amount/
</emu-note>
</emu-clause>

<emu-clause id="sec-amount-renderamountvalue" type="abstract operation">
<h1>
RenderAmountValue (
_v_: a Number, a BigInt, or a String,
): a String
</h1>
<dl class="header">
<dt>description</dt>
<dd>It renders a stored Amount value in canonical exponential notation, or as *"NaN"*, *"Infinity"*, or *"-Infinity"* for non-finite Numbers. Negative zero keeps its sign.</dd>
</dl>
<emu-alg>
1. If _v_ is a String, return _v_.
1. If _v_ is a Number, then
1. If _v_ is *NaN*, return *"NaN"*.
1. If _v_ is *+&infin;*<sub>𝔽</sub>, return *"Infinity"*.
1. If _v_ is *-&infin;*<sub>𝔽</sub>, return *"-Infinity"*.
1. Let _decimalStr_ be Number::toString(_v_, 10).
1. Let _intlMV_ be ! ToIntlMathematicalValue(_decimalStr_).
1. Let _mv_ be _intlMV_.[[Value]].
1. If _v_ is *-0*<sub>𝔽</sub>, set _mv_ to ~negative-zero~.
1. Return RenderInExponentialNotation(_mv_, _intlMV_.[[StringDigitCount]]).
1. Assert: _v_ is a BigInt.
1. Let _digits_ be BigInt::toString(_v_, 10).
1. Let _intlMV_ be ! ToIntlMathematicalValue(_digits_).
1. Return RenderInExponentialNotation(_intlMV_.[[Value]], _intlMV_.[[StringDigitCount]]).
</emu-alg>
</emu-clause>

<emu-clause id="sec-amount-getunitconversionfactor" type="abstract operation">
<h1>GetUnitConversionFactor (
_unit_: a String
Expand Down Expand Up @@ -411,33 +440,30 @@ location: https://tc39.es/proposal-amount/
1. If _value_ is a String, then
1. Let _parsed_ be ParseText(_value_, |StrFiniteNumericLiteral|).
1. If _parsed_ is not a Parse Node, throw a *RangeError* exception.
1. Set _value_ to the StringIntlMV of _parsed_.
1. Else if _value_ is not a Number or a BigInt, then
1. Throw a *TypeError* exception.
1. Let _validatedOpts_ be ? GetAmountOptions(_options_).
1. Let _roundingMode_ be _validatedOpts_.[[RoundingMode]].
1. Let _fractionDigits_ be _validatedOpts_.[[FractionDigits]].
1. Let _significantDigits_ be _validatedOpts_.[[SignificantDigits]].
1. Let _unit_ be _validatedOpts_.[[Unit]].
1. If _fractionDigits_ is not *undefined* or _significantDigits_ is not *undefined*, then
1. If _value_ is a finite Number or _value_ is not a Number, then
1. Let _formatter_ be CreateFormatterObject(_roundingMode_, _fractionDigits_, _fractionDigits_, _significantDigits_, _significantDigits_, *undefined*).
1. If _value_ is an Intl MV Record, let _intlMV_ be _value_; else let _intlMV_ be ! ToIntlMathematicalValue(_value_).
1. Let _fmt_ be FormatNumericToString(_formatter_, _intlMV_.[[Value]], 0, 0).
1. Let _fmtParsed_ be ParseText(_fmt_.[[FormattedString]], |StringNumericLiteral|).
1. Assert: _fmtParsed_ is an instance of |StringNumericLiteral|.
1. Let _fmtIntlMV_ be the StringIntlMV of _fmtParsed_.
1. Set _value_ to RenderInExponentialNotation(_fmtIntlMV_.[[Value]], _fmtIntlMV_.[[StringDigitCount]]).
1. Else if _value_ is an Intl MV Record, then
1. Let _mv_ be _value_.[[Value]].
1. If _value_.[[StringDigitCount]] ≥ 1, then
1. Let _digitCount_ be _value_.[[StringDigitCount]].
1. If _value_ is a Number and _value_ is not finite, then
1. Let _stored_ be _value_.
1. Else,
1. If _value_ is a String, let _intlMV_ be the StringIntlMV of _parsed_; else let _intlMV_ be ! ToIntlMathematicalValue(_value_).
1. If _fractionDigits_ is not *undefined* or _significantDigits_ is not *undefined*, then
1. Let _stored_ be RenderAmountValueWithPrecision(_intlMV_.[[Value]], _validatedOpts_).
1. Else if _value_ is a String, then
1. Let _mv_ be _intlMV_.[[Value]].
1. If _intlMV_.[[StringDigitCount]] ≥ 1, then
1. Let _digitCount_ be _intlMV_.[[StringDigitCount]].
1. Else,
1. Assert: _mv_ is an integer.
1. Let _digitCount_ be the count of digits in the decimal representation of _mv_.
1. Let _stored_ be RenderInExponentialNotation(_mv_, _digitCount_).
1. Else,
1. Assert: _mv_ is an integer.
1. Let _digitCount_ be the count of digits in the decimal representation of _mv_.
1. Set _value_ to RenderInExponentialNotation(_mv_, _digitCount_).
1. Let _stored_ be _value_.
1. Let _O_ be OrdinaryObjectCreate(%Amount.prototype%, « [[AmountValue]], [[Unit]] »).
1. Set _O_.[[AmountValue]] to _value_.
1. Set _O_.[[AmountValue]] to _stored_.
1. Set _O_.[[Unit]] to _unit_.
1. Return _O_.
</emu-alg>
Expand All @@ -447,9 +473,6 @@ location: https://tc39.es/proposal-amount/
<emu-note>
<p>A String argument must denote a finite mathematical value. *"NaN"*, *"Infinity"*, *"+Infinity"*, *"-Infinity"*, and *""* are rejected, as are Strings with leading or trailing white space or other extraneous contents.</p>
</emu-note>
<emu-note type="editor">
<p>We intend to move ECMA-402 FormatNumericToString and its dependent operations to ECMA-262, possibly renamed.</p>
</emu-note>
</emu-clause>
</emu-clause>
</emu-clause>
Expand Down Expand Up @@ -489,26 +512,7 @@ location: https://tc39.es/proposal-amount/
1. Perform ? RequireInternalSlot(_O_, [[AmountValue]]).
1. Let _v_ be _O_.[[AmountValue]].
1. Let _u_ be _O_.[[Unit]].
1. If _v_ is a String, then
1. Let _valueStr_ be _v_.
1. Else if _v_ is a Number, then
1. If _v_ is *NaN*, then
1. Let _valueStr_ be *"NaN"*.
1. Else if _v_ is *+&infin;*<sub>𝔽</sub>, then
1. Let _valueStr_ be *"Infinity"*.
1. Else if _v_ is *-&infin;*<sub>𝔽</sub>, then
1. Let _valueStr_ be *"-Infinity"*.
1. Else,
1. Let _decimalStr_ be Number::toString(_v_, 10).
1. Let _intlMV_ be ! ToIntlMathematicalValue(_decimalStr_).
1. Let _mv_ be _intlMV_.[[Value]].
1. If _v_ is *-0*<sub>𝔽</sub>, set _mv_ to ~negative-zero~.
1. Let _valueStr_ be RenderInExponentialNotation(_mv_, _intlMV_.[[StringDigitCount]]).
1. Else,
1. Assert: _v_ is a BigInt.
1. Let _digits_ be BigInt::toString(_v_, 10).
1. Let _intlMV_ be ! ToIntlMathematicalValue(_digits_).
1. Let _valueStr_ be RenderInExponentialNotation(_intlMV_.[[Value]], _intlMV_.[[StringDigitCount]]).
1. Let _valueStr_ be RenderAmountValue(_v_).
1. If _u_ is *undefined*, return the string-concatenation of *"["*, _valueStr_, and *" ~]"*.
1. Return the string-concatenation of *"["*, _valueStr_, *" "*, _u_, and *"]"*.
</emu-alg>
Expand Down Expand Up @@ -544,12 +548,8 @@ location: https://tc39.es/proposal-amount/
1. Let _significantDigits_ be _opts_.[[SignificantDigits]].
1. If _fractionDigits_ is not *undefined* or _significantDigits_ is not *undefined*, let _needsRounding_ be *true*, else let _needsRounding_ be *false*.
1. If _convertedValue_ is a finite Number and _needsRounding_ is *true*, then
1. Let _roundingMode_ be _opts_.[[RoundingMode]].
1. Let _formatter_ be CreateFormatterObject(_roundingMode_, _fractionDigits_, _fractionDigits_, _significantDigits_, _significantDigits_, *undefined*).
1. Let _intlMV_ be ! ToIntlMathematicalValue(_convertedValue_).
1. Let _formatted_ be FormatNumericToString(_formatter_, _intlMV_.[[Value]], 0, 0).
1. Let _formattedMV_ be ! ToIntlMathematicalValue(_formatted_.[[FormattedString]]).
1. Set _result_.[[AmountValue]] to RenderInExponentialNotation(_formattedMV_.[[Value]], _formattedMV_.[[StringDigitCount]]).
1. Set _result_.[[AmountValue]] to RenderAmountValueWithPrecision(_intlMV_.[[Value]], _opts_).
1. Else,
1. Set _result_.[[AmountValue]] to _convertedValue_.
1. Set _result_.[[Unit]] to _targetUnit_.
Expand Down
Loading