diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 8c639191a..a0407ad97 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -767,5 +767,9 @@ trait SigmaDslBuilder { /** Returns a number decoded from provided big-endian bytes array. */ def fromBigEndianBytes[T](bytes: Coll[Byte])(implicit cT: RType[T]): T + + def some[T](value: T)(implicit cT: RType[T]): Option[T] + + def none[T]()(implicit cT: RType[T]): Option[T] } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index dc85205b3..74ca9cdd3 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1835,13 +1835,28 @@ case object SGlobalMethods extends MonoTypeMethods { Colls.fromArray(w.toBytes) } + lazy val someMethod = SMethod(this, "some", + SFunc(Array(SGlobal, tT), SOption(tT), Array(paramT)), 8, FixedCost(JitCost(5)), Seq(tT)) // todo: cost + .withIRInfo(MethodCallIrBuilder, + javaMethodOf[SigmaDslBuilder, Any, RType[_]]("some"), + { mtype => Array(mtype.tRange) }) + .withInfo(MethodCall, "", + ArgInfo("value", "value to be serialized")) + + lazy val noneMethod = SMethod(this, "none", + SFunc(Array(SGlobal, tT), SOption(tT), Array(paramT)), 9, FixedCost(JitCost(5))) // todo: cost + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + protected override def getMethods() = super.getMethods() ++ { if (VersionContext.current.isV6SoftForkActivated) { Seq( groupGeneratorMethod, xorMethod, serializeMethod, - fromBigEndianBytesMethod + fromBigEndianBytesMethod, + someMethod, + noneMethod ) } else { Seq( diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 2ae4f7370..2259bcca5 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -245,6 +245,14 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => DataSerializer.serialize(value.asInstanceOf[SType#WrappedType], tpe, w) Colls.fromArray(w.toBytes) } + + override def some[T](value: T)(implicit cT: RType[T]): Option[T] = { + Some(value) + } + + override def none[T]()(implicit cT: RType[T]): Option[T] = { + None + } } /** Default singleton instance of Global object, which implements global ErgoTree functions. */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala index 660ccc93c..c1d1db40a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1174,6 +1174,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val bytes = asRep[Coll[Byte]](argsV(0)) val cT = stypeToElem(method.stype.tRange.withSubstTypes(typeSubst)) g.fromBigEndianBytes(bytes)(cT) + case SGlobalMethods.someMethod.name => + val value = asRep[tT.WrappedType](argsV(0)) + val cT = stypeToElem(typeSubst.apply(tT)).asInstanceOf[Elem[tT.WrappedType]] + g.some(value)(cT) case _ => throwError() } case (x: Ref[tNum], _: SNumericTypeMethods) => method.name match { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 11a306447..d8a7a297b 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -117,6 +117,8 @@ import scalan._ def xor(l: Ref[Coll[Byte]], r: Ref[Coll[Byte]]): Ref[Coll[Byte]] def serialize[T](value: Ref[T]): Ref[Coll[Byte]] def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] + def some[T](value: Ref[T])(implicit cT: Elem[T]): Ref[WOption[T]] + def none[T]()(implicit cT: Elem[T]): Ref[WOption[T]] }; trait CostModelCompanion; trait BigIntCompanion; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 2c87b0b13..de4370da5 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1978,6 +1978,20 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { true, false, cT)) } + override def some[T](value: Ref[T])(implicit cT: Elem[T]): Ref[WOption[T]] = { + asRep[WOption[T]](mkMethodCall(self, + SigmaDslBuilderClass.getMethod("some", classOf[Sym], classOf[Elem[T]]), + Array[AnyRef](value, cT, Map(tT -> Evaluation.rtypeToSType(cT.sourceType))), + true, false, element[WOption[T]])) + } + + override def none[T]()(implicit cT: Elem[T]): Ref[WOption[T]] = { + asRep[WOption[T]](mkMethodCall(self, + SigmaDslBuilderClass.getMethod("none", classOf[Elem[T]]), + Array[AnyRef](cT, Map(tT -> Evaluation.rtypeToSType(cT.sourceType))), + true, false, element[WOption[T]])) + } + } implicit object LiftableSigmaDslBuilder @@ -2151,6 +2165,21 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](bytes, cT), true, true, cT, Map(tT -> Evaluation.rtypeToSType(cT.sourceType)))) } + + def some[T](value: Ref[T])(implicit cT: Elem[T]): Ref[WOption[T]] = { + asRep[WOption[T]](mkMethodCall(source, + SigmaDslBuilderClass.getMethod("some", classOf[Sym], classOf[Elem[T]]), + Array[AnyRef](value, cT), + true, true, element[WOption[T]], Map(tT -> Evaluation.rtypeToSType(cT.sourceType)))) + } + + def none[T]()(implicit cT: Elem[T]): Ref[WOption[T]] = { + asRep[WOption[T]](mkMethodCall(source, + SigmaDslBuilderClass.getMethod("none", classOf[Elem[T]]), + Array[AnyRef](cT), + true, true, element[WOption[T]], Map(tT -> Evaluation.rtypeToSType(cT.sourceType)))) + } + } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 22810c125..16817e08a 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -1734,4 +1734,25 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Global.some") { + val ext: Seq[VarBinding] = Seq( + (intVar1, IntConstant(0)) + ) + def someTest(): Assertion = { + test("some", env, ext, + """{ + | val xo = Global.some[Int](5) + | xo.get == 5 + |}""".stripMargin, + null + ) + } + + if (VersionContext.current.isV6SoftForkActivated) { + someTest() + } else { + an[Exception] should be thrownBy someTest() + } + } + }