From a1758bd4a838d8eba250912a7d98043a0a086dda Mon Sep 17 00:00:00 2001 From: Jungyeom Kim Date: Mon, 3 Feb 2025 10:39:37 +0900 Subject: [PATCH] Hotfix for Math domain --- src/main/scala/esmeta/ty/IntTy.scala | 14 ++++++++++---- src/main/scala/esmeta/ty/MathTy.scala | 20 ++++++++++++++------ src/main/scala/esmeta/ty/Sign.scala | 5 +++++ src/main/scala/esmeta/ty/package.scala | 6 ++++-- src/main/scala/esmeta/ty/util/Parser.scala | 4 ++-- src/test/scala/esmeta/ty/MathTinyTest.scala | 4 +++- 6 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/main/scala/esmeta/ty/IntTy.scala b/src/main/scala/esmeta/ty/IntTy.scala index ea1a6bbf22..1075e69c97 100644 --- a/src/main/scala/esmeta/ty/IntTy.scala +++ b/src/main/scala/esmeta/ty/IntTy.scala @@ -5,6 +5,8 @@ import esmeta.interpreter.Interpreter import esmeta.state.{Math, Number} import esmeta.util.Flat +import scala.math.BigInt + sealed trait IntTy extends TyElem with Lattice[IntTy] { import IntTy.* @@ -75,7 +77,7 @@ sealed trait IntTy extends TyElem with Lattice[IntTy] { case _ => Top def **(that: => IntTy): IntTy = - single(this, that, (l, r) => scala.math.pow(l.toDouble, r.toDouble).toLong) + single(this, that, (l, r) => l.pow(r.toInt)) def &(that: => IntTy): IntTy = single(this, that, _ & _) @@ -122,6 +124,10 @@ sealed trait IntTy extends TyElem with Lattice[IntTy] { case IntSetTy(set) => set.contains(value) case IntSignTy(sign) => sign.contains(value) + def contains(value: BigInt): Boolean = this.canon match + case IntSetTy(set) => set.contains(value) + case IntSignTy(sign) => sign.contains(value) + def isNonPos: Boolean = this.canon match case IntSignTy(sign) => sign.isNonPos case s => s.toSignTy.isNonPos @@ -157,7 +163,7 @@ sealed trait IntTy extends TyElem with Lattice[IntTy] { case IntSignTy(sign) => sign.isZero case IntSetTy(set) => true - def getSingle: Flat[Long] = + def getSingle: Flat[BigInt] = import esmeta.util.* this.canon match case IntSetTy(set) => Flat(set) @@ -180,7 +186,7 @@ sealed trait IntTy extends TyElem with Lattice[IntTy] { case _ => None } -case class IntSetTy(set: Set[Long]) extends IntTy +case class IntSetTy(set: Set[BigInt]) extends IntTy case class IntSignTy(sign: Sign) extends IntTy object IntTy { @@ -204,7 +210,7 @@ object IntTy { * @return * a singleton set if the result is a singleton, otherwise Top */ - def single(l: IntTy, r: IntTy, f: (Long, Long) => Long) = + def single(l: IntTy, r: IntTy, f: (BigInt, BigInt) => BigInt) = import esmeta.util (l.getSingle, r.getSingle) match case (util.One(lv), util.One(rv)) => IntSetTy(Set(f(lv, rv))) diff --git a/src/main/scala/esmeta/ty/MathTy.scala b/src/main/scala/esmeta/ty/MathTy.scala index 8392bafc86..707dd397fa 100644 --- a/src/main/scala/esmeta/ty/MathTy.scala +++ b/src/main/scala/esmeta/ty/MathTy.scala @@ -170,10 +170,18 @@ sealed trait MathTy extends TyElem with Lattice[MathTy] { case _ => Top /** inclusion check */ - def contains(math: Math): Boolean = this.canon match - case MathSignTy(sign) => sign.contains(math.decimal) - case MathIntTy(int) => math.decimal.isWhole && int.contains(math.toInt) - case MathSetTy(set) => set.contains(math) + def contains(math: Math): Boolean = + import scala.math.BigInt + this.canon match + case MathSignTy(sign) => sign.contains(math.decimal) + case MathIntTy(int) => + math.decimal.isWhole && int.contains(math.decimal.toBigInt) + case MathSetTy(set) => set.contains(math) + + def contains(bint: esmeta.state.BigInt): Boolean = this.canon match + case MathSignTy(sign) => sign.contains(bint.bigInt) + case MathIntTy(int) => int.contains(bint.bigInt) + case MathSetTy(set) => set.exists(_.decimal == bint.bigInt) /** get single value */ def getSingle: Flat[Math] = @@ -261,7 +269,7 @@ sealed trait MathTy extends TyElem with Lattice[MathTy] { else this case MathSetTy(set) => if (set.forall(_.decimal.isWhole)) - MathIntTy(set.map(x => x.decimal.toLong)) + MathIntTy(set.map(x => x.decimal.toBigInt)) else this case i @ MathIntTy(_) => i @@ -302,7 +310,7 @@ object MathSetTy: def apply(seq: Math*): MathSetTy = MathSetTy(seq.toSet) object MathIntTy: - def apply(ints: Iterable[Long]): MathIntTy = MathIntTy(IntSetTy(ints.toSet)) + def apply(ints: Iterable[BigInt]): MathIntTy = MathIntTy(IntSetTy(ints.toSet)) object MathTy extends Parser.From(Parser.mathTy) { // Top & Bot diff --git a/src/main/scala/esmeta/ty/Sign.scala b/src/main/scala/esmeta/ty/Sign.scala index 2a38bf1434..a159040bac 100644 --- a/src/main/scala/esmeta/ty/Sign.scala +++ b/src/main/scala/esmeta/ty/Sign.scala @@ -61,6 +61,11 @@ case class Sign(neg: Boolean, zero: Boolean, pos: Boolean) else if value < 0 then neg else pos + def contains(value: BigInt): Boolean = + if value == 0 then zero + else if value < 0 then neg + else pos + def isZero: Boolean = this match case Sign(false, true, false) => true case _ => false diff --git a/src/main/scala/esmeta/ty/package.scala b/src/main/scala/esmeta/ty/package.scala index 34d4a4e4f8..59f4cc1cea 100644 --- a/src/main/scala/esmeta/ty/package.scala +++ b/src/main/scala/esmeta/ty/package.scala @@ -7,6 +7,8 @@ import esmeta.util.* import esmeta.util.Appender.* import esmeta.util.BaseUtils.* +import scala.math.BigInt + /** type elements */ trait TyElem { override def toString: String = toString(false, false) @@ -108,10 +110,10 @@ def EnumT(xs: String*): ValueTy = EnumT(xs.toSet) lazy val MathT: ValueTy = ValueTy(math = MathTy.Top) lazy val ExtMathT: ValueTy = MathT || InfinityT lazy val IntT: ValueTy = ValueTy(math = MathTy.Int) -def IntT(set: Set[Long]): ValueTy = +def IntT(set: Set[BigInt]): ValueTy = if (set.isEmpty) BotT else ValueTy(math = MathIntTy(IntSetTy(set))) -def IntT(ds: Long*): ValueTy = IntT(ds.toSet) +def IntT(ds: BigInt*): ValueTy = IntT(ds.toSet) lazy val NonPosIntT: ValueTy = ValueTy(math = MathTy.NonPosInt) lazy val NonNegIntT: ValueTy = ValueTy(math = MathTy.NonNegInt) lazy val NegIntT: ValueTy = ValueTy(math = MathTy.NegInt) diff --git a/src/main/scala/esmeta/ty/util/Parser.scala b/src/main/scala/esmeta/ty/util/Parser.scala index a3698739a1..8b1b34e080 100644 --- a/src/main/scala/esmeta/ty/util/Parser.scala +++ b/src/main/scala/esmeta/ty/util/Parser.scala @@ -206,7 +206,7 @@ trait Parsers extends BasicParsers { lazy val intSignTy = "Int" ~> "[" ~> sign <~ "]" ^^ { case s => IntSignTy(s) } lazy val intSetTy = - "Int" ~> "[" ~> rep1sep(long, ",") <~ "]" ^^ { + "Int" ~> "[" ~> rep1sep(bigInt, ",") <~ "]" ^^ { case ds => IntSetTy(ds.toSet) } lazy val intTop = "Int" ^^^ IntSignTy(Sign.Top) @@ -250,7 +250,7 @@ trait Parsers extends BasicParsers { case s ~ n => (IntSignTy(s), n) } lazy val intSetTy = - ("NumberInt" ~> "[" ~> rep1sep(long, ",") <~ "]") ~ nan ^^ { + ("NumberInt" ~> "[" ~> rep1sep(bigInt, ",") <~ "]") ~ nan ^^ { case ds ~ n => (IntSetTy(ds.toSet), n) } lazy val intTop = "NumberInt" ~> nan ^^ { diff --git a/src/test/scala/esmeta/ty/MathTinyTest.scala b/src/test/scala/esmeta/ty/MathTinyTest.scala index cff27cd3a9..51a2629961 100644 --- a/src/test/scala/esmeta/ty/MathTinyTest.scala +++ b/src/test/scala/esmeta/ty/MathTinyTest.scala @@ -15,7 +15,9 @@ class MathTinyTest extends TyTest { IntSetTy(Set(1L, 2L)), ), MathSignTy(Sign(false, true, false)).canon -> MathIntTy(IntSetTy(Set(0))), - MathSetTy(Math(3), Math(5), Math(2)).canon -> MathIntTy(Set(3L, 5L, 2L)), + MathSetTy(Math(3), Math(5), Math(2)).canon -> MathIntTy( + Set(3, 5, 2).map(scala.math.BigInt(_)), + ), ) }