Skip to content

Commit

Permalink
fix: use BigInt instead of Long for integer types (#272)
Browse files Browse the repository at this point in the history
Co-authored-by: Jungyeom Kim <[email protected]>
  • Loading branch information
d01c2 and kimjg1119 authored Feb 6, 2025
1 parent 9c4de48 commit d561909
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 15 deletions.
14 changes: 10 additions & 4 deletions src/main/scala/esmeta/ty/IntTy.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.*

Expand Down Expand Up @@ -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, _ & _)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand All @@ -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)))
Expand Down
20 changes: 14 additions & 6 deletions src/main/scala/esmeta/ty/MathTy.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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] =
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/main/scala/esmeta/ty/Sign.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions src/main/scala/esmeta/ty/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/esmeta/ty/util/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 ^^ {
Expand Down
4 changes: 3 additions & 1 deletion src/test/scala/esmeta/ty/MathTinyTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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(_)),
),
)
}

Expand Down

0 comments on commit d561909

Please sign in to comment.