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

Fixed bugs for Test262 #118

Merged
merged 4 commits into from
Dec 1, 2022
Merged
Show file tree
Hide file tree
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
19 changes: 18 additions & 1 deletion src/main/resources/manuals/d711ba960cd12b76/bugfix.patch
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
diff --git a/spec.html b/spec.html
index 5a4af52..5d516a1 100644
index 5a4af52..3753675 100644
--- a/spec.html
+++ b/spec.html
@@ -7200,7 +7200,7 @@
Expand Down Expand Up @@ -110,6 +110,23 @@ index 5a4af52..5d516a1 100644
1. [id="step-assignmentexpression-evaluation-lgcl-nullish-getvalue"] Let _lval_ be ? GetValue(_lref_).
1. If _lval_ is neither *undefined* nor *null*, return _lval_.
1. If IsAnonymousFunctionDefinition(|AssignmentExpression|) is *true* and IsIdentifierRef of |LeftHandSideExpression| is *true*, then
@@ -33723,12 +33723,12 @@ THH:mm:ss.sss
1. Let _searchStr_ be ? ToString(_searchString_).
1. Let _numPos_ be ? ToNumber(_position_).
1. Assert: If _position_ is *undefined*, then _numPos_ is *NaN*.
- 1. If _numPos_ is *NaN*, let _pos_ be +∞; otherwise, let _pos_ be ! ToIntegerOrInfinity(_numPos_).
+ 1. If _numPos_ is *NaN*, let _pos_ be +∞; otherwise, let _pos_ be ! ToIntegerOrInfinity(_numPos_).
1. Let _len_ be the length of _S_.
- 1. Let _start_ be the result of clamping _pos_ between 0 and _len_.
- 1. If _searchStr_ is the empty String, return 𝔽(_start_).
1. Let _searchLen_ be the length of _searchStr_.
- 1. For each non-negative integer _i_ starting with _start_ such that _i_ ≤ _len_ - _searchLen_, in descending order, do
+ 1. Let _start_ be the result of clamping _pos_ between 0 and _len_ - _searchLen_.
+ 1. If _searchStr_ is the empty String, return 𝔽(_start_).
+ 1. For each integer _i_ such that 0 ≤ _i_ ≤ _start_, in descending order, do
1. Let _candidate_ be the substring of _S_ from _i_ to _i_ + _searchLen_.
1. If _candidate_ is the same sequence of code units as _searchStr_, return 𝔽(_i_).
1. Return *-1*<sub>𝔽</sub>.
@@ -34371,7 +34371,7 @@ THH:mm:ss.sss
1. Let _resultString_ be the substring of _s_ from _position_ to _nextIndex_.
1. Set _position_ to _nextIndex_.
Expand Down
28 changes: 16 additions & 12 deletions src/main/resources/manuals/default/test262/filtered.json
Original file line number Diff line number Diff line change
Expand Up @@ -332,14 +332,14 @@
"built-ins/GeneratorPrototype/throw/try-finally-within-try",
"built-ins/Map/prototype/clear/map-data-list-is-preserved",
"built-ins/Map/prototype/delete/does-not-break-iterators",
"built-ins/Map/prototype/entries/returns-iterator-empty",
"built-ins/Map/prototype/entries/returns-iterator",
"built-ins/Map/prototype/keys/returns-iterator-empty",
"built-ins/Map/prototype/entries/returns-iterator-empty",
"built-ins/Map/prototype/keys/returns-iterator",
"built-ins/Map/prototype/values/returns-iterator-empty",
"built-ins/Map/prototype/keys/returns-iterator-empty",
"built-ins/Map/prototype/values/returns-iterator",
"built-ins/MapIteratorPrototype/next/iteration-mutable",
"built-ins/Map/prototype/values/returns-iterator-empty",
"built-ins/MapIteratorPrototype/next/iteration",
"built-ins/MapIteratorPrototype/next/iteration-mutable",
"built-ins/Number/prototype/S15.7.3.1_A3",
"built-ins/Number/prototype/S15.7.4_A1",
"built-ins/Object/S15.2.1.1_A2_T12",
Expand All @@ -364,13 +364,13 @@
"built-ins/Promise/all/iter-arg-is-string-resolve",
"built-ins/Promise/allSettled/iter-arg-is-string-resolve",
"built-ins/Promise/any/iter-arg-is-empty-string-reject",
"built-ins/Set/prototype/entries/returns-iterator-empty",
"built-ins/Set/prototype/entries/returns-iterator",
"built-ins/Set/prototype/values/returns-iterator-empty",
"built-ins/Set/prototype/entries/returns-iterator-empty",
"built-ins/Set/prototype/values/returns-iterator",
"built-ins/Set/prototype/values/returns-iterator-empty",
"built-ins/Set/prototype/values/values-iteration-mutable",
"built-ins/SetIteratorPrototype/next/iteration-mutable",
"built-ins/SetIteratorPrototype/next/iteration",
"built-ins/SetIteratorPrototype/next/iteration-mutable",
"built-ins/String/S15.5.2.1_A1_T1",
"built-ins/String/S15.5.2.1_A1_T10",
"built-ins/String/S15.5.2.1_A1_T11",
Expand Down Expand Up @@ -522,9 +522,13 @@
"language/expressions/generators/dstr/dflt-ary-ptrn-elision-step-err",
"language/expressions/generators/dstr/dflt-ary-ptrn-rest-id-elision-next-err",
"language/expressions/generators/dstr/dflt-ary-ptrn-rest-id-iter-step-err",
"language/expressions/generators/named-strict-error-reassign-fn-name-in-body",
"language/expressions/generators/named-strict-error-reassign-fn-name-in-body-in-arrow",
"language/expressions/generators/named-strict-error-reassign-fn-name-in-body-in-eval",
"language/expressions/generators/named-strict-error-reassign-fn-name-in-body",
"language/expressions/greater-than-or-equal/bigint-and-number-extremes",
"language/expressions/greater-than/bigint-and-number-extremes",
"language/expressions/less-than-or-equal/bigint-and-number-extremes",
"language/expressions/less-than/bigint-and-number-extremes",
"language/expressions/logical-assignment/lgcl-and-assignment-operator-lhs-before-rhs",
"language/expressions/logical-assignment/lgcl-nullish-assignment-operator-lhs-before-rhs",
"language/expressions/logical-assignment/lgcl-or-assignment-operator-lhs-before-rhs",
Expand Down Expand Up @@ -647,13 +651,13 @@
"language/statements/for-of/dstr/var-ary-ptrn-rest-id-elision-next-err",
"language/statements/for-of/dstr/var-ary-ptrn-rest-id-iter-step-err",
"language/statements/for-of/generator-next-error",
"language/statements/for-of/map-contract-expand",
"language/statements/for-of/map",
"language/statements/for-of/map-contract",
"language/statements/for-of/map-expand-contract",
"language/statements/for-of/map-contract-expand",
"language/statements/for-of/map-expand",
"language/statements/for-of/map",
"language/statements/for-of/set-expand",
"language/statements/for-of/map-expand-contract",
"language/statements/for-of/set",
"language/statements/for-of/set-expand",
"language/statements/for/dstr/const-ary-ptrn-elision-step-err",
"language/statements/for/dstr/const-ary-ptrn-rest-id-elision-next-err",
"language/statements/for/dstr/const-ary-ptrn-rest-id-iter-step-err",
Expand Down
6 changes: 4 additions & 2 deletions src/main/scala/esmeta/compiler/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -259,13 +259,15 @@ class Compiler(
},
),
)
case ForEachIntegerStep(x, start, cond, ascending, body) =>
case ForEachIntegerStep(x, low, high, ascending, body) =>
val (start, end) = if (ascending) (low, high) else (high, low)
val (i, iExpr) = compileWithExpr(x)
fb.addInst(ILet(i, compile(fb, start)))
fb.addInst(
ILoop(
"foreach-int",
compile(fb, cond),
if (ascending) not(lessThan(compile(fb, end), iExpr))
else not(lessThan(iExpr, compile(fb, end))),
fb.newScope {
compile(fb, body)
val op = if (ascending) add(_, _) else sub(_, _)
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/esmeta/lang/Step.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ case class ForEachStep(
// for-each steps for integers
case class ForEachIntegerStep(
variable: Variable,
start: Expression,
cond: Condition,
low: Expression,
high: Expression,
ascending: Boolean,
body: Step,
) extends Step
Expand Down
26 changes: 18 additions & 8 deletions src/main/scala/esmeta/lang/util/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,22 @@ trait Parsers extends IndentParsers {

// for-each steps for integers
lazy val forEachIntStep: PL[ForEachIntegerStep] =
lazy val ascending: Parser[Boolean] =
("ascending" ^^^ true | "descending" ^^^ false)
lazy val interval: Parser[(Expression, Expression)] =
("starting with" ~> expr) ~ ("such that" ~ variable ~> (
"≤" ^^^ { (x: CalcExpression) => x } |
"<" ^^^ { BinaryExpression(_, BinaryExpressionOperator.Sub, one) }
) ~ calcExpr) ^^ {
case l ~ (f ~ h) => (l, f(h))
} | "such that" ~> calcExpr ~ ("≤" ~ variable ~ "≤" ~> calcExpr) ^^ {
case l ~ h => (l, h)
}
lazy val ascending: Parser[Boolean] = opt(
", in" ~> ("ascending" ^^^ true | "descending" ^^^ false) <~ "order,",
) ^^ { _.getOrElse(true) }
("for each" ~ "(non-negative )?integer".r ~> variable) ~
("starting with" ~> expr) ~
("such that" ~> cond) ~
(", in" ~> ascending <~ "order,") ~
(opt("do") ~> step) ^^ {
case x ~ start ~ cond ~ asc ~ body =>
ForEachIntegerStep(x, start, cond, asc, body)
interval ~ ascending ~ (opt("do") ~> step) ^^ {
case x ~ (low, high) ~ asc ~ body =>
ForEachIntegerStep(x, low, high, asc, body)
}

// for-each steps for array index property
Expand Down Expand Up @@ -1266,4 +1273,7 @@ trait Parsers extends IndentParsers {
// helper for creating expressions, conditions
private def getRefExpr(r: Reference): Expression = ReferenceExpression(r)
private def getExprCond(e: Expression): Condition = ExpressionCondition(e)

// literal for mathematical one
private val one = DecimalMathValueLiteral(1)
}
6 changes: 3 additions & 3 deletions src/main/scala/esmeta/lang/util/Stringifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ class Stringifier(detail: Boolean, location: Boolean) {
if (!ascending) app >> "in reverse List order, "
if (body.isInstanceOf[BlockStep]) app >> "do"
app >> body
case ForEachIntegerStep(x, start, cond, ascending, body) =>
app >> First("for each integer ") >> x >> " starting with " >> start
app >> " such that " >> cond >> ", in "
case ForEachIntegerStep(x, low, high, ascending, body) =>
app >> First("for each integer ") >> x >> " such that " >> low
app >> " ≤ " >> x >> " ≤ " >> high >> ", in "
app >> (if (ascending) "ascending" else "descending") >> " order, "
if (body.isInstanceOf[BlockStep]) app >> "do"
app >> body
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/esmeta/lang/util/UnitWalker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ trait UnitWalker extends BasicUnitWalker {
walk(cond)
case ForEachStep(ty, elem, expr, ascending, body) =>
walkOpt(ty, walk); walk(elem); walk(expr); walk(body)
case ForEachIntegerStep(x, start, cond, ascending, body) =>
walk(x); walk(start); walk(cond); walk(body)
case ForEachIntegerStep(x, low, high, ascending, body) =>
walk(x); walk(low); walk(high); walk(body)
case ForEachArrayIndexStep(key, array, start, ascending, body) =>
walk(key); walk(array); walk(start); walk(body)
case ForEachParseNodeStep(x, expr, body) =>
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/esmeta/lang/util/Walker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ trait Walker extends BasicWalker {
ascending,
walk(body),
)
case ForEachIntegerStep(x, start, cond, ascending, body) =>
case ForEachIntegerStep(x, low, high, ascending, body) =>
ForEachIntegerStep(
walk(x),
walk(start),
walk(cond),
walk(low),
walk(high),
ascending,
walk(body),
)
Expand Down
115 changes: 78 additions & 37 deletions src/main/scala/esmeta/state/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package esmeta.state
import esmeta.state.util.*
import esmeta.util.BaseUtils.*
import esmeta.ir.Global
import java.math.MathContext.UNLIMITED
import java.math.MathContext.{UNLIMITED, DECIMAL128}

/** IR state elements */
trait StateElem {
Expand Down Expand Up @@ -64,58 +64,99 @@ val POS_INF = Number(Double.PositiveInfinity)
val NEG_INF = Number(Double.NegativeInfinity)

/** conversion number to string */
def toStringHelper(m: Double, radix: Int = 10): String = {
def toStringHelper(x: Double, radix: Int = 10): String = {
// get sign
def getSign(n: Int): Char = if (n - 1 > 0) '+' else '-'

// get string of number
def getStr(number: Long, radix: Int): String =
def getStr(number: scala.math.BigInt, radix: Int): String =
var str = ""
var sLong = number
while (sLong > 0) { str += getRadixString(sLong % radix); sLong /= radix }
var s = number
while (s > 0) { str += getRadixString(s % radix); s /= radix }
str.reverse

// get radix string of number
def getRadixString(d: Long): String =
def getRadixString(d: scala.math.BigInt): String =
if (d < 10) d.toString else ('a' + (d - 10)).toChar.toString

def INT(n: Int): BigDecimal = BigDecimal(n, UNLIMITED)
def DOUBLE(n: Double): BigDecimal = BigDecimal(n, UNLIMITED)

if (m.isNaN) "NaN"
else if (m == 0) "0"
else if (m < 0) "-" + toStringHelper(-m, radix)
else if (m.isPosInfinity) "Infinity"
// 1. If _x_ is *NaN*, return the String *"NaN"*.
if (x.isNaN) "NaN"
// 2. If _x_ is *+0*<sub>𝔽</sub> or *-0*<sub>𝔽</sub>, return the String
// *"0"*.
else if (x == 0) "0"
// 3. If _x_ < *-0*<sub>𝔽</sub>, return the string-concatenation of *"-"* and
// toStringHelper(-_x_).
else if (x < 0) "-" + toStringHelper(-x, radix)
// 4. If _x_ is *+∞*<sub>𝔽</sub>, return the String *"Infinity"*.
else if (x.isPosInfinity) "Infinity"
else {
var s = DOUBLE(m)
var n = 0
while (s % radix == INT(0) || s % 1 != INT(0)) {
if (s % radix == INT(0)) { s /= radix; n += 1 }
else { s *= radix; n -= 1 }
}
while (
(((s - (s % radix)) / radix) * INT(radix).pow(n + 1)).toDouble == m
) {
s = (s - (s % radix)) / radix
n = n + 1
}
var sLong = s.toLong
var k = 0
while (s >= INT(1)) { s /= radix; k += 1 }
n += k
// 5. Otherwise, let _n_, _k_, and _s_ be integers such that _k_ >= 1,
// _radix_<sup>_k_ - 1</sup> <= _s_ < _radix_<sup>_k_</sup>, 𝔽(_s_ *
// _radix_<sup>_n_ - _k_</sup>) is _x_, and _k_ is as small as possible.
val (n: Int, k: Int, s: scala.math.BigInt) =
var S = BigDecimal(x, UNLIMITED)
var N = 0
while (S % radix == 0) { S /= radix; N += 1 }
while (S % 1 != 0) { S *= radix; N -= 1 }
var RK = BigDecimal(radix, UNLIMITED)
var K = 1
while (S >= RK) { RK *= radix; K += 1 }
(N + K, K, S.toBigInt)

if (k <= n && n <= 21) {
getStr(sLong, radix) + ("0" * (n - k))
// * the code units of the _k_ digits of the decimal representation of
// _s_ (in order, with no leading zeroes)
getStr(s, radix) +
// * _n_ - _k_ occurrences of the code unit 0x0030 (DIGIT ZERO)
"0" * (n - k)
} else if (0 < n && n <= 21) {
val str = getStr(sLong, radix)
str.substring(0, n) + '.' + str.substring(n)
val str = getStr(s, radix)
// * the code units of the most significant _n_ digits of the decimal
// representation of _s_
str.substring(0, n) +
// * the code unit 0x002E (FULL STOP)
'.' +
// * the code units of the remaining _k_ - _n_ digits of the decimal
// representation of _s_
str.substring(n)
} else if (-6 < n && n <= 0) {
"0." + ("0" * (-n)) + getStr(sLong, radix)
// * the code unit 0x0030 (DIGIT ZERO)
"0" +
// * the code unit 0x002E (FULL STOP)
"." +
// * -_n_ occurrences of the code unit 0x0030 (DIGIT ZERO)
"0" * -n +
// * the code units of the _k_ digits of the decimal representation of _s_
getStr(s, radix)
} else if (k == 1) {
getStr(sLong, radix) + "e" + getSign(n) + math.abs(n - 1).toString
// * the code unit of the single digit of _s_
getStr(s, radix) +
// * the code unit 0x0065 (LATIN SMALL LETTER E)
"e" +
// * the code unit 0x002B (PLUS SIGN) or the code unit 0x002D
// (HYPHEN-MINUS) according to whether _n_ - 1 is positive or negative
getSign(n) +
// * the code units of the decimal representation of the integer abs(_n_
// - 1) (with no leading zeroes)
math.abs(n - 1)
} else {
val str = getStr(sLong, radix)
str.substring(0, 1) + '.' + str
.substring(1) + 'e' + getSign(n) + math.abs(n - 1).toString
val str = getStr(s, radix)
// * the code units of the most significant digit of the decimal
// representation of _s_
str.substring(0, 1) +
// * the code unit 0x002E (FULL STOP)
'.' +
// * the code units of the remaining _k_ - 1 digits of the decimal
// representation of _s_
str.substring(1) +
// * the code unit 0x0065 (LATIN SMALL LETTER E)
'e' +
// * the code unit 0x002B (PLUS SIGN) or the code unit 0x002D
// (HYPHEN-MINUS) according to whether _n_ - 1 is positive or negative
getSign(n) +
// * the code units of the decimal representation of the integer abs(_n_
// - 1) (with no leading zeroes)
math.abs(n - 1)
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/esmeta/state/util/Stringifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import esmeta.cfg.*
import esmeta.state.{*, given}
import esmeta.ir.{Func => IRFunc, *, given}
import esmeta.es.*
import esmeta.util.BaseUtils.*
import esmeta.util.Appender.{given, *}

/** stringifier for state elements */
Expand Down Expand Up @@ -152,7 +153,7 @@ class Stringifier(detail: Boolean, location: Boolean) {
// simple values
given svRule: Rule[SimpleValue] = (app, sv) =>
sv match
case Number(n) => app >> n >> "f"
case Number(n) => app >> toStringHelper(n)
case BigInt(n) => app >> n >> "n"
case Str(str) => app >> "\"" >> str >> "\""
case Bool(bool) => app >> bool
Expand Down
Loading