Skip to content

Commit

Permalink
add Boolean.toByte operation
Browse files Browse the repository at this point in the history
  • Loading branch information
ross-weir committed Nov 8, 2023
1 parent 75f301a commit aaaa68a
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ trait LogicalOps extends Base { self: Scalan =>
override def applySeq(x: Boolean): Int = if (x) 1 else 0
}

/** Boolean to Byte conversion unary operation. */
val BooleanToByte = new UnOp[Boolean, Byte]("ToByte") {
override def applySeq(x: Boolean): Byte = if (x) 1.toByte else 0.toByte
}

/** Extension methods over `Ref[Boolean]`. */
implicit class RepBooleanOps(value: Ref[Boolean]) {
def &&(y: Ref[Boolean]): Ref[Boolean] = And(value, y)
Expand All @@ -40,6 +45,7 @@ trait LogicalOps extends Base { self: Scalan =>

def unary_!() : Ref[Boolean] = Not(value)
def toInt: Ref[Int] = BooleanToInt(value)
def toByte: Ref[Byte] = BooleanToByte(value)
}


Expand Down
14 changes: 7 additions & 7 deletions interpreter/shared/src/main/scala/sigmastate/types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ object SType {
}

implicit class STypeOps(val tpe: SType) extends AnyVal {
def isBoolean: Boolean = tpe.isInstanceOf[SBoolean.type]
def isCollectionLike: Boolean = tpe.isInstanceOf[SCollection[_]]
def isCollection: Boolean = tpe.isInstanceOf[SCollectionType[_]]
def isOption: Boolean = tpe.isInstanceOf[SOption[_]]
Expand Down Expand Up @@ -918,13 +919,12 @@ case object SBoolean extends SPrimType with SEmbeddable with SLogical with SProd
override val reprClass: RClass[_] = RClass(classOf[Boolean])

val ToByte = "toByte"
protected override def getMethods() = super.getMethods()
/* TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
++ Seq(
SMethod(this, ToByte, SFunc(this, SByte), 1)
.withInfo(PropertyCall, "Convert true to 1 and false to 0"),
)
*/

lazy val ToByteMethod: SMethod = SMethod(
this, ToByte, SFunc(this, SByte), 1, FixedCost(JitCost(1)))
.withInfo(PropertyCall, "Convert true to 1 and false to 0")

protected override def getMethods() = super.getMethods() ++ Seq(ToByteMethod)
}

/** Descriptor of ErgoTree type `Byte` - 8-bit signed integer. */
Expand Down
4 changes: 4 additions & 0 deletions sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,10 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
else
error(s"The type of $obj is expected to be Collection to select 'size' property", obj.sourceContext.toOption)

case Select(obj, SBoolean.ToByte, _) if obj.tpe.isBoolean =>
val bool = eval(obj.asBoolValue)
bool.toByte

// Rule: proof.isProven --> IsValid(proof)
case Select(p, SSigmaProp.IsProven, _) if p.tpe == SSigmaProp =>
eval(SigmaPropIsProven(p.asSigmaProp))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
// The following table should be made dependent on HF activation
val methods = Table(
("typeId", "methods", "CanHaveMethods"),
(SBoolean.typeId, Seq.empty[MInfo], true),
(SByte.typeId, Seq.empty[MInfo], false),
(SShort.typeId, Seq.empty[MInfo], false),
(SInt.typeId, Seq.empty[MInfo], false),
Expand All @@ -232,6 +231,10 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
), true)
},

{
import SBoolean._
(SBoolean.typeId, Seq(MInfo(1, ToByteMethod)), true)
},
{ // SBigInt inherit methods from SNumericType.methods
// however they are not resolvable via SBigInt.typeId
import SNumericType._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,14 @@ class TestingInterpreterSpecification extends CompilerTestingCommons
|}""".stripMargin)
}

property("Evaluate boolean casting ops") {
testEval(
"""{
| val bool: Boolean = true
| bool.toByte == 1.toByte && false.toByte == 0.toByte
}""".stripMargin)
}

property("Evaluate numeric casting ops") {
def testWithCasting(castSuffix: String): Unit = {
testEval(s"OUTPUTS.size.toByte.$castSuffix == 0.$castSuffix")
Expand Down

0 comments on commit aaaa68a

Please sign in to comment.