Skip to content

Commit 1b952e8

Browse files
agilotvkuncak
authored andcommitted
Add FP types and literals
1 parent 6a46636 commit 1b952e8

File tree

2 files changed

+67
-10
lines changed

2 files changed

+67
-10
lines changed

src/main/scala/inox/ast/Expressions.scala

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package inox
44
package ast
55

6+
import scala.collection.immutable
67
import scala.collection.immutable.BitSet
78

89
/** Expression definitions for Pure Scala.
@@ -229,6 +230,42 @@ trait Expressions { self: Trees =>
229230
def getType(using Symbols): Type = RealType()
230231
}
231232

233+
/** $encodingof a floating point literal */
234+
sealed case class FPLiteral(exponent: Int, significand: Int, value: BitSet) extends Literal[BitSet] {
235+
override def getType(using Symbols) = FPType(exponent, significand)
236+
def toBV: BVLiteral = BVLiteral(true, value, exponent + significand)
237+
}
238+
239+
object FPLiteral {
240+
def fromBV(exponent: Int, significand: Int, bv: BVLiteral) = FPLiteral(exponent, significand, bv.value)
241+
}
242+
243+
object Float32Literal {
244+
def apply(value: Float): FPLiteral = FPLiteral.fromBV(8, 24, Int32Literal(java.lang.Float.floatToIntBits(value)))
245+
246+
def unapply(e: Expr): Option[Float] = e match {
247+
case f @ FPLiteral(8, 24, b) if b.maxOption.getOrElse(-1) < 32 =>
248+
f.toBV match {
249+
case Int32Literal(i) => Some(java.lang.Float.intBitsToFloat(i))
250+
case _ => None
251+
}
252+
case _ => None
253+
}
254+
}
255+
256+
object Float64Literal {
257+
def apply(value: Double): FPLiteral = FPLiteral.fromBV(11, 53, Int64Literal(java.lang.Double.doubleToLongBits(value)))
258+
259+
def unapply(e: Expr): Option[Double] = e match {
260+
case f @ FPLiteral(11, 53, b) if b.maxOption.getOrElse(-1) < 64 =>
261+
f.toBV match {
262+
case Int64Literal(i) => Some(java.lang.Double.longBitsToDouble(i))
263+
case _ => None
264+
}
265+
case _ => None
266+
}
267+
}
268+
232269
/** $encodingof a boolean literal '''true''' or '''false''' */
233270
sealed case class BooleanLiteral(value: Boolean) extends Literal[Boolean] {
234271
def getType(using Symbols): Type = BooleanType()
@@ -397,25 +434,25 @@ trait Expressions { self: Trees =>
397434
/** $encodingof `... + ...` */
398435
sealed case class Plus(lhs: Expr, rhs: Expr) extends Expr with CachingTyped {
399436
override protected def computeType(using Symbols): Type =
400-
getIntegerType(lhs, rhs) `orElse` getRealType(lhs, rhs) `orElse` getBVType(lhs, rhs)
437+
getIntegerType(lhs, rhs) `orElse` getRealType(lhs, rhs) `orElse` getBVType(lhs, rhs) `orElse` getFPType(lhs, rhs)
401438
}
402439

403440
/** $encodingof `... - ...` */
404441
sealed case class Minus(lhs: Expr, rhs: Expr) extends Expr with CachingTyped {
405442
override protected def computeType(using Symbols): Type =
406-
getIntegerType(lhs, rhs) `orElse` getRealType(lhs, rhs) `orElse` getBVType(lhs, rhs)
443+
getIntegerType(lhs, rhs) `orElse` getRealType(lhs, rhs) `orElse` getBVType(lhs, rhs) `orElse` getFPType(lhs, rhs)
407444
}
408445

409446
/** $encodingof `- ...` */
410447
sealed case class UMinus(expr: Expr) extends Expr with CachingTyped {
411448
override protected def computeType(using Symbols): Type =
412-
getIntegerType(expr) `orElse` getRealType(expr) `orElse` getBVType(expr)
449+
getIntegerType(expr) `orElse` getRealType(expr) `orElse` getBVType(expr) `orElse` getFPType(expr)
413450
}
414451

415452
/** $encodingof `... * ...` */
416453
sealed case class Times(lhs: Expr, rhs: Expr) extends Expr with CachingTyped {
417454
override protected def computeType(using Symbols): Type =
418-
getIntegerType(lhs, rhs) `orElse` getRealType(lhs, rhs) `orElse` getBVType(lhs, rhs)
455+
getIntegerType(lhs, rhs) `orElse` getRealType(lhs, rhs) `orElse` getBVType(lhs, rhs) `orElse` getFPType(lhs, rhs)
419456
}
420457

421458
/** $encodingof `... / ...`
@@ -431,7 +468,7 @@ trait Expressions { self: Trees =>
431468
*/
432469
sealed case class Division(lhs: Expr, rhs: Expr) extends Expr with CachingTyped {
433470
override protected def computeType(using Symbols): Type =
434-
getIntegerType(lhs, rhs) `orElse` getRealType(lhs, rhs) `orElse` getBVType(lhs, rhs)
471+
getIntegerType(lhs, rhs) `orElse` getRealType(lhs, rhs) `orElse` getBVType(lhs, rhs) `orElse` getFPType(lhs, rhs)
435472
}
436473

437474
/** $encodingof `... % ...` (can return negative numbers)
@@ -440,7 +477,7 @@ trait Expressions { self: Trees =>
440477
*/
441478
sealed case class Remainder(lhs: Expr, rhs: Expr) extends Expr with CachingTyped {
442479
override protected def computeType(using Symbols): Type =
443-
getIntegerType(lhs, rhs) `orElse` getBVType(lhs, rhs)
480+
getIntegerType(lhs, rhs) `orElse` getBVType(lhs, rhs) `orElse` getFPType(lhs, rhs)
444481
}
445482

446483
/** $encodingof `... mod ...` (cannot return negative numbers)
@@ -458,7 +495,8 @@ trait Expressions { self: Trees =>
458495
getIntegerType(lhs, rhs).isTyped ||
459496
getRealType(lhs, rhs).isTyped ||
460497
getBVType(lhs, rhs).isTyped ||
461-
getCharType(lhs, rhs).isTyped
498+
getCharType(lhs, rhs).isTyped ||
499+
getFPType(lhs, rhs).isTyped
462500
) BooleanType() else Untyped
463501
}
464502

@@ -468,7 +506,8 @@ trait Expressions { self: Trees =>
468506
getIntegerType(lhs, rhs).isTyped ||
469507
getRealType(lhs, rhs).isTyped ||
470508
getBVType(lhs, rhs).isTyped ||
471-
getCharType(lhs, rhs).isTyped
509+
getCharType(lhs, rhs).isTyped ||
510+
getFPType(lhs, rhs).isTyped
472511
) BooleanType() else Untyped
473512
}
474513

@@ -478,7 +517,8 @@ trait Expressions { self: Trees =>
478517
getIntegerType(lhs, rhs).isTyped ||
479518
getRealType(lhs, rhs).isTyped ||
480519
getBVType(lhs, rhs).isTyped ||
481-
getCharType(lhs, rhs).isTyped
520+
getCharType(lhs, rhs).isTyped ||
521+
getFPType(lhs, rhs).isTyped
482522
) BooleanType() else Untyped
483523
}
484524

@@ -488,7 +528,8 @@ trait Expressions { self: Trees =>
488528
getIntegerType(lhs, rhs).isTyped ||
489529
getRealType(lhs, rhs).isTyped ||
490530
getBVType(lhs, rhs).isTyped ||
491-
getCharType(lhs, rhs).isTyped
531+
getCharType(lhs, rhs).isTyped ||
532+
getFPType(lhs, rhs).isTyped
492533
) BooleanType() else Untyped
493534
}
494535

src/main/scala/inox/ast/Types.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,17 @@ trait Types { self: Trees =>
7676
object Int32Type extends BVTypeExtractor(true, 32)
7777
object Int64Type extends BVTypeExtractor(true, 64)
7878

79+
sealed case class FPType(exponent: Int, significand: Int) extends Type
80+
81+
abstract class FPTypeExtractor(exponent: Int, significand: Int) {
82+
def apply(): FPType = FPType(exponent, significand)
83+
84+
def unapply(tpe: FPType): Boolean = tpe.exponent == exponent && tpe.significand == significand
85+
}
86+
87+
object Float32Type extends FPTypeExtractor(8, 24)
88+
object Float64Type extends FPTypeExtractor(11, 53)
89+
7990
sealed case class TypeParameter(id: Identifier, flags: Seq[Flag]) extends Type {
8091
def freshen = TypeParameter(id.freshen, flags).copiedFrom(this)
8192

@@ -231,6 +242,11 @@ trait Types { self: Trees =>
231242
case _ => Untyped
232243
}
233244

245+
protected def getFPType(tpe: Typed, tpes: Typed*)(using Symbols): Type = tpe.getType match {
246+
case f: FPType => checkAllTypes(tpes, f, f)
247+
case _ => Untyped
248+
}
249+
234250
protected final def getCharType(tpe: Typed, tpes: Typed*)(using Symbols): Type =
235251
checkAllTypes(tpe +: tpes, CharType(), CharType())
236252

0 commit comments

Comments
 (0)