Skip to content

Commit

Permalink
Support numbers with exponential syntax outside of bigints/bigdecimals
Browse files Browse the repository at this point in the history
  • Loading branch information
kubukoz committed Oct 3, 2023
1 parent 078fa1a commit ce5eaa5
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 21 deletions.
39 changes: 19 additions & 20 deletions modules/core/src/main/scala/playground/QueryCompilerVisitor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,22 @@ object QueryCompilerVisitor {

object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {

private def checkRange[A, B](
pc: QueryCompiler[A]
private def checkRange[B](
pc: QueryCompiler[BigDecimal]
)(
tag: String
)(
matchToRange: A => Option[B]
matchToRange: PartialFunction[BigDecimal, B]
) = (pc, QueryCompiler.pos).tupled.emap { case (i, range) =>
matchToRange(i)
.toRightIor(
Either
.catchOnly[ArithmeticException](matchToRange.lift(i).toRight(()))
.leftWiden[Any]
.flatten
.leftMap(_ =>
CompilationError
.error(NumberOutOfRange(i.toString, tag), range)
)
.toIor
.toIorNec
}

Expand All @@ -85,12 +89,12 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
.typeCheck(NodeKind.Bool) { case b @ BooleanLiteral(_) => b }
.map(_.value.value)
case PUnit => struct(shapeId, hints, Vector.empty, _ => ())
case PLong => checkRange(integer)("int")(_.toLongOption)
case PInt => checkRange(integer)("int")(_.toIntOption)
case PShort => checkRange(integer)("short")(_.toShortOption)
case PByte => checkRange(integer)("byte")(_.toByteOption)
case PFloat => checkRange(integer)("float")(_.toFloatOption)
case PDouble => checkRange(integer)("double")(_.toDoubleOption)
case PLong => checkRange(number)("int")(_.toLongExact)
case PInt => checkRange(number)("int")(_.toIntExact)
case PShort => checkRange(number)("short")(_.toShortExact)
case PByte => checkRange(number)("byte")(_.toByteExact)
case PFloat => checkRange(number)("float") { case i if i.isDecimalFloat => i.toFloat }
case PDouble => checkRange(number)("double") { case i if i.isDecimalDouble => i.toDouble }
case PDocument => document
case PBlob =>
(string, QueryCompiler.pos).tupled.emap { case (s, range) =>
Expand All @@ -101,14 +105,8 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
.toIor
.toIorNec
}
case PBigDecimal =>
checkRange(integer)("bigdecimal") { s =>
Either.catchNonFatal(BigDecimal(s)).toOption
}
case PBigInt =>
checkRange(integer)("bigint") { s =>
Either.catchNonFatal(BigInt(s)).toOption
}
case PBigDecimal => number
case PBigInt => checkRange(number)("bigint")(_.toBigIntExact.get)
case PUUID =>
stringLiteral.emap { s =>
Either
Expand Down Expand Up @@ -137,9 +135,10 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
}
}

private val integer: QueryCompiler[String] = QueryCompiler
private val number: QueryCompiler[BigDecimal] = QueryCompiler
.typeCheck(NodeKind.IntLiteral) { case i @ IntLiteral(_) => i }
.map(_.value.value)
.map(BigDecimal(_))

def collection[C[_], A](
shapeId: ShapeId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,15 @@ object CompilationTests extends SimpleIOSuite with Checkers {
)
}

pureTest("int with exponential syntax - in range") {
assertNoDiff(
compile {
WithSource.liftId(IntLiteral("1e2").mapK(WithSource.liftId))
}(Schema.int),
Ior.right(100),
)
}

pureTest("short") {
assertNoDiff(
compile {
Expand All @@ -282,6 +291,15 @@ object CompilationTests extends SimpleIOSuite with Checkers {
)
}

pureTest("short with exponential syntax - in range") {
assertNoDiff(
compile {
WithSource.liftId(IntLiteral("1e2").mapK(WithSource.liftId))
}(Schema.short),
Ior.right(100.toShort),
)
}

pureTest("byte") {
assertNoDiff(
compile {
Expand All @@ -299,8 +317,17 @@ object CompilationTests extends SimpleIOSuite with Checkers {
)
}

pureTest("float") {
pureTest("byte with exponential syntax - in range") {
assertNoDiff(
compile {
WithSource.liftId(IntLiteral("1e2").mapK(WithSource.liftId))
}(Schema.byte),
Ior.right(100.toByte),
)
}

pureTest("float") {
assert.same(
compile {
WithSource.liftId(Float.MaxValue.mapK(WithSource.liftId))
}(Schema.float),
Expand All @@ -316,6 +343,15 @@ object CompilationTests extends SimpleIOSuite with Checkers {
)
}

pureTest("float - exponential syntax") {
assertNoDiff(
compile {
WithSource.liftId(IntLiteral("0.1e0").mapK(WithSource.liftId))
}(Schema.float),
Ior.right(0.1f),
)
}

pureTest("double") {
assertNoDiff(
compile {
Expand All @@ -334,6 +370,15 @@ object CompilationTests extends SimpleIOSuite with Checkers {
)
}

pureTest("double - exponential syntax") {
assertNoDiff(
compile {
WithSource.liftId(IntLiteral("0.1e0").mapK(WithSource.liftId))
}(Schema.double),
Ior.right(0.1),
)
}

test("bigint - OK") {
forall { (bi: BigInt) =>
assertNoDiff(
Expand All @@ -353,6 +398,15 @@ object CompilationTests extends SimpleIOSuite with Checkers {
)
}

pureTest("bigint - exponential syntax") {
assertNoDiff(
compile {
WithSource.liftId(IntLiteral("1e2").mapK(WithSource.liftId))
}(Schema.bigint),
Ior.right(BigInt(100)),
)
}

test("bigdecimal - OK") {
forall { (bd: BigDecimal) =>
assertNoDiff(
Expand All @@ -372,6 +426,15 @@ object CompilationTests extends SimpleIOSuite with Checkers {
)
}

pureTest("bigdecimal - exponential syntax") {
assertNoDiff(
compile {
WithSource.liftId(IntLiteral("1e2").mapK(WithSource.liftId))
}(Schema.bigdecimal),
Ior.right(BigDecimal(100)),
)
}

pureTest("boolean") {
assertNoDiff(
compile {
Expand Down

0 comments on commit ce5eaa5

Please sign in to comment.