diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala index d6ed6118dc..68d69abd91 100644 --- a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala +++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala @@ -25,13 +25,13 @@ case class UnparsedErgoTree(bytes: mutable.WrappedArray[Byte], error: Validation * ErgoTreeSerializer defines top-level serialization format of the scripts. * The interpretation of the byte array depend on the first `header` byte, which uses VLQ encoding up to 30 bits. * Currently we define meaning for only first byte, which may be extended in future versions. - * 7 6 5 4 3 2 1 0 + * 7 6 5 4 3 2 1 0 * ------------------------- * | | | | | | | | | * ------------------------- * Bit 7 == 1 if the header contains more than 1 byte (default == 0) * Bit 6 - reserved for GZIP compression (should be 0) - * Bit 5 == 1 - reserved for context dependent costing (should be = 0) + * Bit 5 == 1 - reserved (should be = 0) * Bit 4 == 1 if constant segregation is used for this ErgoTree (default = 0) * (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/264) * Bit 3 == 1 if size of the whole tree is serialized after the header byte (default = 0) diff --git a/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala b/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala index 87dd20ab0c..a192a789b9 100644 --- a/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala +++ b/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala @@ -3,7 +3,7 @@ package sigmastate.lang import fastparse._ import fastparse.NoWhitespace._ import SigmaParser._ -import sigma.ast.SType +import sigma.ast.{Constant, SType} import sigma.ast.syntax.SValue import sigmastate.lang.parsers.Basic @@ -187,9 +187,9 @@ object ContractParser { def annotation[_: P] = P("@contract") - def paramDefault[_: P] = P(WL.? ~ `=` ~ WL.? ~ ExprLiteral).map(s => s.asWrappedType) + def paramDefault[_: P] = P(WL.? ~ `=` ~ WL.? ~ ExprLiteral) - def param[_: P] = P(WL.? ~ Id.! ~ ":" ~ Type ~ paramDefault.?).map(s => ContractParam(s._1, s._2, s._3)) + def param[_: P] = P(WL.? ~ Id.! ~ ":" ~ Type ~ paramDefault.?).map(s => ContractParam(s._1, s._2, s._3.map(_.value))) def params[_: P] = P("(" ~ param.rep(1, ",").? ~ ")") } diff --git a/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala b/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala index 9a412b7100..bce252d866 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala @@ -3,6 +3,7 @@ package sigmastate.lang import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks +import sigma.ast.SType.AnyOps import sigma.ast._ class ContractParserSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers { @@ -34,8 +35,8 @@ class ContractParserSpec extends AnyPropSpec with ScalaCheckPropertyChecks with parsed.name shouldBe "contractName" parsed.params should contain theSameElementsInOrderAs Seq( - ContractParam("p1", SInt, Some(IntConstant(5).asWrappedType)), - ContractParam("p2", SString, Some(StringConstant("default string").asWrappedType)), + ContractParam("p1", SInt, Some(5.asWrappedType)), + ContractParam("p2", SString, Some("default string".asWrappedType)), ContractParam("param3", SLong, None) ) } diff --git a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala index 498c3934bf..32943bca44 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala @@ -1,16 +1,15 @@ package sigmastate.lang import org.scalatest.matchers.should.Matchers -import sigma.{Coll, _} import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.{SValue, ValueOps} import sigma.ast._ import sigma.crypto.CryptoConstants import sigma.data.{CAnyValue, CSigmaDslBuilder, ProveDHTuple, ProveDlog, SigmaBoolean} import sigma.util.Extensions.BigIntegerOps +import sigma._ import sigmastate.helpers.NegativeTesting import sigmastate.interpreter.Interpreter.ScriptEnv -import sigma.ast.{Ident, MethodCallLike} import java.math.BigInteger diff --git a/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala b/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala index 8fe26a30b0..2fc7556875 100644 --- a/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala +++ b/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala @@ -9,13 +9,13 @@ import scala.scalajs.js import scala.scalajs.js.annotation.JSExportTopLevel import sigma.js.Value import sigma.ast.ErgoTree.HeaderType -import sigmastate.eval.CompiletimeIRContext +import sigma.compiler.ir.CompiletimeIRContext import sigma.ast.syntax.ValueOps /** Wrapper exported to JS. */ @JSExportTopLevel("SigmaCompiler") -class SigmaCompiler(_compiler: sigmastate.lang.SigmaCompiler) extends js.Object { +class SigmaCompiler(_compiler: sigma.compiler.SigmaCompiler) extends js.Object { /** Compiles ErgoScript code to ErgoTree. * @@ -59,7 +59,7 @@ object SigmaCompiler extends js.Object { * @return SigmaCompiler instance */ private def create(networkPrefix: Byte): SigmaCompiler = { - val compiler = sigmastate.lang.SigmaCompiler(networkPrefix) + val compiler = sigma.compiler.SigmaCompiler(networkPrefix) new SigmaCompiler(compiler) } } diff --git a/sc/js/src/test/scala/scalan/Platform.scala b/sc/js/src/test/scala/scalan/Platform.scala index 5f938111d2..697453a5d2 100644 --- a/sc/js/src/test/scala/scalan/Platform.scala +++ b/sc/js/src/test/scala/scalan/Platform.scala @@ -1,14 +1,16 @@ package scalan +import sigma.compiler.ir.IRContext + import scala.annotation.unused object Platform { /** In JS tests do nothing. The corresponding JVM method outputs graphs into files. */ - def stage[Ctx <: Scalan](scalan: Ctx)( + def stage[Ctx <: IRContext](ctx: Ctx)( @unused prefix: String, @unused testName: String, @unused name: String, - @unused sfs: Seq[() => scalan.Sym]): Unit = { + @unused sfs: Seq[() => ctx.Sym]): Unit = { } /** On JS it is no-operation. */ diff --git a/sc/jvm/src/test/scala/scalan/Platform.scala b/sc/jvm/src/test/scala/scalan/Platform.scala index 43041a92c6..7c9d48b135 100644 --- a/sc/jvm/src/test/scala/scalan/Platform.scala +++ b/sc/jvm/src/test/scala/scalan/Platform.scala @@ -3,22 +3,23 @@ package scalan import scalan.compilation.GraphVizExport import sigma.util.FileUtil import org.scalatest.Assertions +import sigma.compiler.ir.IRContext object Platform { /** Output graph given by symbols in `sfs` to files. - * @param scalan The Scalan context + * @param ctx The Scalan context * @param prefix The prefix of the directory where the graphs will be stored. * @param testName The name of the test. * @param name The name of the graph. * @param sfs A sequence of functions that return symbols of the graph roots. */ - def stage[Ctx <: Scalan](scalan: Ctx) - (prefix: String, testName: String, name: String, sfs: Seq[() => scalan.Sym]): Unit = { + def stage[Ctx <: IRContext](ctx: Ctx) + (prefix: String, testName: String, name: String, sfs: Seq[() => ctx.Sym]): Unit = { val directory = FileUtil.file(prefix, testName) - val gv = new GraphVizExport(scalan) + val gv = new GraphVizExport(ctx) implicit val graphVizConfig = gv.defaultGraphVizConfig try { - val ss = sfs.map(_.apply()).asInstanceOf[Seq[gv.scalan.Sym]] + val ss = sfs.map(_.apply()).asInstanceOf[Seq[gv.ctx.Sym]] gv.emitDepGraph(ss, directory, name)(graphVizConfig) } catch { case e: Exception => diff --git a/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala b/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala index 8568e6c1db..020e066080 100644 --- a/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala +++ b/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala @@ -2,8 +2,8 @@ package scalan.compilation import java.awt.Desktop import java.io.{File, PrintWriter} -import scalan.Scalan import scalan.core.ScalaNameUtil +import sigma.compiler.ir.IRContext import sigma.util.{FileUtil, ProcessUtil, StringUtil} import scala.annotation.unused @@ -12,8 +12,8 @@ import scala.collection.immutable.StringOps // TODO implement this outside of the cake /** Implementation of Graphviz's dot file generator. */ -class GraphVizExport[Ctx <: Scalan](val scalan: Ctx) { - import scalan._ +class GraphVizExport[Ctx <: IRContext](val ctx: Ctx) { + import ctx._ case class GraphFile(file: File, fileType: String) { def open() = { Desktop.getDesktop.open(file) diff --git a/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala b/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala index aaa1d6c424..c10c0123b0 100644 --- a/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala +++ b/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala @@ -2,7 +2,7 @@ package sigmastate import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec -import scalan.TypeDescs +import sigma.compiler.ir.{IRContext, TypeDescs} import sigma.reflection.ReflectionData.registerClassEntry import sigma.reflection.SRConstructor @@ -37,7 +37,7 @@ class InterpreterReflectionGeneratorTests extends AnyPropSpec with Matchers { } property("inner class") { - val ctx = null.asInstanceOf[scalan.Library] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only val clazz = classOf[ctx.Coll.CollElem[_, _]] registerClassEntry(clazz, constructors = Array( diff --git a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala index 1375b48d99..dd5262e700 100644 --- a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala +++ b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala @@ -1,10 +1,21 @@ package sigmastate -import scalan.{Base, TypeDescs} +import sigma.compiler.ir.{Base, TypeDescs} import sigma.reflection._ import scala.annotation.unused import scala.collection.mutable +/** Generates code for registering classes in the ReflectionData. + * It is not used in the runtime. + * + * The generated invocations of `registerClassEntry`, `mkMethod`, `mkConstructor` may + * require manual adjustments. + * + * It uses [[sigma.reflection.Platform.unknownClasses]] to collect classes which were + * accessed during runtime + * + * @see [[ReflectionData]] + */ object ReflectionGenerator { def normalizeName(name: String): String = { @@ -30,17 +41,17 @@ object ReflectionGenerator { } val knownPackages = Array( - "scalan.primitives.", + "sigma.compiler.ir.primitives.", "sigma.", "sigma.", - "special.wrappers.", + "sigma.compiler.ir.wrappers.", "sigma.ast.", "sigmastate.lang.Terms.", "sigmastate.interpreter.", "sigmastate.utxo.", "sigmastate.", - "wrappers.scala.", - "scalan.", + "sigma.compiler.ir.wrappers.scala.", + "sigma.compiler.ir.", "scala.collection.", "scala." ) diff --git a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala index faded6e28c..9eec42a4fb 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala @@ -1,12 +1,12 @@ package org.ergoplatform -import sigmastate.lang.SigmaCompiler -import sigmastate.eval.IRContext import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix import sigma.ast.SType import sigma.ast.syntax.SigmaPropValue import sigma.ast.Value import sigma.ast.syntax.ValueOps +import sigma.compiler.SigmaCompiler +import sigma.compiler.ir.IRContext object ErgoScriptPredef { import sigmastate.interpreter.Interpreter._ diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala index 484b9e2728..ffe7239c62 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala @@ -5,11 +5,11 @@ import sigma.interpreter.{CostedProverResult, ProverResult} import sigma.data.{CSigmaDslBuilder, RType} import org.ergoplatform.{ErgoBox, ErgoLikeContext} import sigma.{Coll, SigmaDslBuilder, SigmaProp} -import sigmastate.eval.IRContext import scala.util.Try import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token} import sigma.ast.{ErgoTree, EvaluatedValue, SType} +import sigma.compiler.ir.IRContext import scala.language.implicitConversions diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala index 2c31304b70..2511bef439 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala @@ -1,9 +1,9 @@ package org.ergoplatform.dsl import sigma.Coll -import sigmastate.eval.IRContext import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token} import org.ergoplatform.ErgoBox.{BoxId, NonMandatoryRegisterId, TokenId} +import sigma.compiler.ir.IRContext import sigma.interpreter.CostedProverResult class ErgoContractSpec(implicit val IR: IRContext) extends ContractSpec { diff --git a/sc/shared/src/main/scala/scalan/Scalan.scala b/sc/shared/src/main/scala/scalan/Scalan.scala deleted file mode 100644 index c2e9359261..0000000000 --- a/sc/shared/src/main/scala/scalan/Scalan.scala +++ /dev/null @@ -1,36 +0,0 @@ -package scalan - -import scalan.primitives._ -import scalan.staged.Transforming - -/** Aggregate cake with all inter-dependent modules assembled together. - * Each instance of this class contains independent IR context, thus many - * instances can be created simultaneously. - * However, the inner types declared in the traits are path-dependant. - * This in particular means that ctx1.Ref[_] and ctx2.Ref[_] are different types. - * The typical usage is to create `val ctx = new Scalan` and then import inner - * declarations using `import ctx._`. - * This way the declaration will be directly available as if they were global - * declarations. - * At the same time cake design pattern allow to `override` many methods and values - * in classed derived from `Scalan`, this is significant benefit over - * *everything is global* design. - */ -class Scalan - extends TypeDescs - with MethodCalls - with Tuples - with NumericOps - with UnBinOps - with LogicalOps - with OrderingOps - with Equal - with UniversalOps - with Functions - with IfThenElse - with Transforming - with Thunks - with Entities - with Modules - with DefRewriting - diff --git a/sc/shared/src/main/scala/scalan/primitives/UniversalOps.scala b/sc/shared/src/main/scala/scalan/primitives/UniversalOps.scala deleted file mode 100644 index eaca5821ce..0000000000 --- a/sc/shared/src/main/scala/scalan/primitives/UniversalOps.scala +++ /dev/null @@ -1,92 +0,0 @@ -package scalan.primitives - -import scalan.{Base, Scalan} - -trait UniversalOps extends Base { scalan: Scalan => - case class HashCode[A]() extends UnOp[A, Int]("hashCode") { - override def applySeq(x: A): Int = x.hashCode - } - - case class ToString[A]() extends UnOp[A, String]("toString") { - override def applySeq(x: A): String = x.toString - } - - /** Represents calculation of size in bytes of the given value. - * The descriptor value.elem can be used to decompose value into components. - */ - case class SizeOf[T](value: Ref[T]) extends BaseDef[Long] { - override def transform(t: Transformer) = SizeOf(t(value)) - } - - def sizeOf[T](value: Ref[T]): Ref[Long] = SizeOf(value) - - /** Special graph node to represent accumulation of the operation costs. - * In general, due to node sharing it is incorrect to just sum up all the `args` costs - * and add `resCost` to that value. - * Example:
- * - * val x = .. - * val y = op1(x) - * val z = op2(x) - * val res = op3(y, z) - * - * The naive summation will lead to the cost of x` is accumulated both into `cost of y` - * and into `cost of z`, so in the `cost of res` it is accumulated twice. - * To avoid this problem OpCost nodes require special handling in during evaluation. - * - * @param lambdaVar the variable of the lambda in which scope this node is created. - * This makes this node belong to the lambda body, even if it doesn't - * otherwise depend on lambda argument. - * @param costedValueId The id of the node for which this node represents cost - * @param args costs of the arguments, which are here represent dependency information. - * @param opCost operation cost, which should be added to the current scope accumulated cost - */ - case class OpCost(lambdaVar: Sym, costedValueId: Int, args: Seq[Ref[Int]], opCost: Ref[Int]) extends BaseDef[Int] { - /** When this node is mirrored (as part of mirrorLambda) we apply transformer t for all arguments - * with standard data flow semantics. - * However this is not correct to do for lambdaVar. - * Instead we use current lambda from the top of the stack, which is always points to the most nested - * lambda. - */ - override def transform(t: Transformer) = OpCost(lambdaStack.head.x, costedValueId, t(args), t(opCost)) - } - - def opCost(costedValue: Sym, args: Seq[Ref[Int]], opCost: Ref[Int]): Ref[Int] = { - val id = costedValue.node.nodeId - val lamVar = lambdaStack.head.x - OpCost(lamVar, id, args, opCost) - } - - def assertValueIdForOpCost[A,B](value: Ref[A], cost: Ref[B]): Unit = { - assert(if (cost.node.isInstanceOf[OpCost]) value.node.nodeId == cost.node.asInstanceOf[OpCost].costedValueId else true, - s"${value.node} value node id (${value.node.nodeId}) is not equal to OpCost.costedValueId (${cost.node.asInstanceOf[OpCost].costedValueId})") - } - - case class Downcast[From, To](input: Ref[From], eTo: Elem[To]) extends BaseDef[To]()(eTo) { - override def transform(t: Transformer) = Downcast(t(input), eTo) - } - case class Upcast[From, To](input: Ref[From], eTo: Elem[To]) extends BaseDef[To]()(eTo) { - override def transform(t: Transformer) = Upcast(t(input), eTo) - } - - def downcast[To:Elem](value: Ref[_]): Ref[To] = Downcast(value, element[To]) - def upcast[To:Elem](value: Ref[_]): Ref[To] = Upcast(value, element[To]) - - implicit class RepUniversalOps[A](x: Ref[A]) { - def hashCodeRep: Ref[Int] = HashCode[A]().apply(x) - def toStringRep = ToString[A]().apply(x) - } - - case class Convert[From,To](eFrom: Elem[From], eTo: Elem[To], x: Ref[Def[_]], conv: Ref[From => To]) - extends BaseDef[To]()(eTo) { - override def transform(t: Transformer) = Convert(eFrom, eTo, t(x), t(conv)) - } - - def tryConvert[From, To](eFrom: Elem[From], eTo: Elem[To], x: Ref[Def[_]], conv: Ref[From => To]): Ref[To] = { - if (x.elem <:< eFrom) - conv(asRep[From](x)) - else - Convert(eFrom, eTo, x, conv) - } - -} diff --git a/sc/shared/src/main/scala/scalan/Exceptions.scala b/sc/shared/src/main/scala/sigma/compiler/Exceptions.scala similarity index 93% rename from sc/shared/src/main/scala/scalan/Exceptions.scala rename to sc/shared/src/main/scala/sigma/compiler/Exceptions.scala index 8ab128a06e..75b1ecb6a3 100644 --- a/sc/shared/src/main/scala/scalan/Exceptions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Exceptions.scala @@ -1,4 +1,4 @@ -package scalan +package sigma.compiler /** * Can be thrown in staged method body to prevent body unfolding. diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala b/sc/shared/src/main/scala/sigma/compiler/SigmaCompiler.scala similarity index 92% rename from sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala rename to sc/shared/src/main/scala/sigma/compiler/SigmaCompiler.scala index 849167e159..942154409b 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala +++ b/sc/shared/src/main/scala/sigma/compiler/SigmaCompiler.scala @@ -1,12 +1,10 @@ -package sigmastate.lang +package sigma.compiler import fastparse.Parsed import fastparse.Parsed.Success import sigma.kiama.rewriting.Rewriter.{everywherebu, rewrite, rule} import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix -import scalan.GraphIRReflection import sigma.ast.{Exponentiate, MultiplyGroup, SCollectionMethods, SGlobalMethods, SGroupElementMethods, Value, Xor} -import sigmastate.eval.IRContext import sigmastate.interpreter.Interpreter.ScriptEnv import sigma.ast.SigmaPredef.PredefinedFuncRegistry import sigma.ast.MethodCall @@ -14,7 +12,10 @@ import sigmastate.lang.parsers.ParserException import sigma.ast._ import sigma.ast.syntax.SValue import SCollectionMethods.{ExistsMethod, ForallMethod, MapMethod} +import sigma.compiler.ir.{GraphIRReflection, IRContext} +import sigma.compiler.phases.{SigmaBinder, SigmaTyper} import sigmastate.InterpreterReflection +import sigmastate.lang.SigmaParser /** * @param networkPrefix network prefix to decode an ergo address from string (PK op) @@ -72,7 +73,8 @@ class SigmaCompiler private(settings: CompilerSettings) { val predefinedFuncRegistry = new PredefinedFuncRegistry(builder) val binder = new SigmaBinder(env, builder, networkPrefix, predefinedFuncRegistry) val bound = binder.bind(parsed) - val typer = new SigmaTyper(builder, predefinedFuncRegistry, settings.lowerMethodCalls) + val typeEnv = env.collect { case (k, v: SType) => k -> v } + val typer = new SigmaTyper(builder, predefinedFuncRegistry, typeEnv, settings.lowerMethodCalls) val typed = typer.typecheck(bound) typed } @@ -91,7 +93,12 @@ class SigmaCompiler private(settings: CompilerSettings) { /** Compiles the given typed expression. */ def compileTyped(env: ScriptEnv, typedExpr: SValue)(implicit IR: IRContext): CompilerResult[IR.type] = { - val compiledGraph = IR.buildGraph(env, typedExpr) + val placeholdersEnv = env + .collect { case (name, t: SType) => name -> t } + .zipWithIndex + .map { case ((name, t), index) => name -> ConstantPlaceholder(index, t) } + .toMap + val compiledGraph = IR.buildGraph(env ++ placeholdersEnv, typedExpr) val compiledTree = IR.buildTree(compiledGraph) CompilerResult(env, "", compiledGraph, compiledTree) } diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala b/sc/shared/src/main/scala/sigma/compiler/SigmaTemplateCompiler.scala similarity index 78% rename from sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala rename to sc/shared/src/main/scala/sigma/compiler/SigmaTemplateCompiler.scala index ec94bdfd3a..0b30f9830a 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala +++ b/sc/shared/src/main/scala/sigma/compiler/SigmaTemplateCompiler.scala @@ -1,12 +1,11 @@ -package sigmastate.lang +package sigma.compiler import fastparse.Parsed -import org.ergoplatform.sdk.ContractTemplate -import sigmastate.eval.CompiletimeIRContext -import org.ergoplatform.sdk.Parameter +import org.ergoplatform.sdk.{ContractTemplate, Parameter} import sigma.ast.SourceContext import sigma.ast.syntax.SValue -import sigmastate.interpreter.Interpreter.ScriptEnv +import sigma.compiler.ir.CompiletimeIRContext +import sigmastate.lang.{ContractParser, ParsedContractTemplate} import sigmastate.lang.parsers.ParserException /** Compiler which compiles Ergo contract templates into a [[ContractTemplate]]. */ @@ -19,13 +18,14 @@ class SigmaTemplateCompiler(networkPrefix: Byte) { * @param source The ErgoScript contract source code. * @return The contract template. */ - def compile(env: ScriptEnv, source: String): ContractTemplate = { + def compile(source: String): ContractTemplate = { ContractParser.parse(source) match { - case Parsed.Success(template, _) => { + case Parsed.Success(parsedTemplate, _) => implicit val ir = new CompiletimeIRContext - val result = sigmaCompiler.compileParsed(env, template.body) - assemble(template, result.buildTree) - } + val parEnv = parsedTemplate.signature.params.map { p => p.name -> p.tpe }.toMap + val result = sigmaCompiler.compileParsed(parEnv, parsedTemplate.body) + assemble(parsedTemplate, result.buildTree) + case f: Parsed.Failure => throw new ParserException(s"Contract template syntax error: $f", Some(SourceContext.fromParserFailure(f))) } diff --git a/sc/shared/src/main/scala/scalan/staged/AstGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/AstGraphs.scala similarity index 96% rename from sc/shared/src/main/scala/scalan/staged/AstGraphs.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/AstGraphs.scala index 7ad5c24f17..79a078ad19 100644 --- a/sc/shared/src/main/scala/scalan/staged/AstGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/AstGraphs.scala @@ -1,13 +1,15 @@ -package scalan.staged +package sigma.compiler.ir -import scala.collection._ -import scalan.Scalan -import debox.cfor -import debox.{Buffer => DBuffer, Map => DMap, Set => DSet} +import debox.{cfor, Buffer => DBuffer, Map => DMap, Set => DSet} import sigma.data.emptyDBufferOfInt +import scala.collection._ + -trait AstGraphs extends Transforming { self: Scalan => +/** Defines reusable abstraction of AstGraph, the base class for [[ProgramGraph]], + * [[Lambda]] and [[ThunkDef]]. + */ +trait AstGraphs extends Transforming { self: IRContext => /** GraphNode is created for each symbol of the AstGraph and represents graph linking structure */ case class GraphNode( diff --git a/sc/shared/src/main/scala/scalan/Base.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala similarity index 97% rename from sc/shared/src/main/scala/scalan/Base.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/Base.scala index cc29af45b9..48e3e5d09e 100644 --- a/sc/shared/src/main/scala/scalan/Base.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala @@ -1,14 +1,15 @@ -package scalan +package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer} -import sigma.data.{AVHashMap, Nullable, RType} +import sigma.compiler.ir.core.MutableLazy import sigma.data.OverloadHack.Overloaded1 -import sigma.util.StringUtil +import sigma.data.{AVHashMap, Nullable, RType} import sigma.reflection.RConstructor +import sigma.util.StringUtil import java.util.Arrays -import scala.annotation.{implicitNotFound, unused} import scala.annotation.unchecked.uncheckedVariance +import scala.annotation.{implicitNotFound, unused} import scala.collection.compat.immutable.ArraySeq import scala.collection.mutable import scala.language.implicitConversions @@ -17,7 +18,7 @@ import scala.language.implicitConversions * The Base trait houses common AST nodes. It also manages a list of encountered definitions which * allows for common sub-expression elimination (CSE). */ -abstract class Base { scalan: Scalan => +abstract class Base { thisIR: IRContext => type |[+A, +B] = Either[A, B] type RFunc[-A,+B] = Ref[Function1[A,B]] type RPair[+A, +B] = Ref[(A,B)] @@ -51,7 +52,7 @@ abstract class Base { scalan: Scalan => /** Base class for all IR nodes/operations/definitions. */ abstract class Node extends Product { - private[scalan] var _nodeId: Int = freshId + private[compiler] var _nodeId: Int = freshId /** Unique id of the graph node assigned for each new instance using * `freshId` generator. @@ -365,8 +366,8 @@ abstract class Base { scalan: Scalan => /** Most of the references are initialized when created. * These methods are used in core to assign new value for the reference.*/ - private[scalan] def assignDef[B >: T](d: Def[B]): Unit - private[scalan] def assignDefFrom[B >: T](ref: Ref[B]): Unit + private[compiler] def assignDef[B >: T](d: Def[B]): Unit + private[compiler] def assignDefFrom[B >: T](ref: Ref[B]): Unit /** Whether the underlying node is Placeholder. */ @inline final def isPlaceholder: Boolean = node.isInstanceOf[Placeholder[_]] @@ -550,10 +551,10 @@ abstract class Base { scalan: Scalan => } /** Prepend owner parameter depending on its kind. */ - private[scalan] def addOwnerParameter(ownerType: OwnerKind, params: Seq[Any]): Seq[AnyRef] = { + private[compiler] def addOwnerParameter(ownerType: OwnerKind, params: Seq[Any]): Seq[AnyRef] = { val finalParams = (ownerType match { case EntityObjectOwner(obj) => obj +: params - case ScalanOwner => scalan +: params + case ScalanOwner => thisIR +: params case NoOwner => params }) finalParams.asInstanceOf[Seq[AnyRef]] @@ -601,7 +602,7 @@ abstract class Base { scalan: Scalan => override def elem: Elem[T @uncheckedVariance] = _node.resultType override def node: Def[T] = _node - private[scalan] def assignDefInternal[B >: T](d: Def[B]): Unit = { + private[compiler] def assignDefInternal[B >: T](d: Def[B]): Unit = { assert(_node.isInstanceOf[Placeholder[_]]) assert(_node.nodeId > 0) val tab = _symbolTable @@ -612,12 +613,12 @@ abstract class Base { scalan: Scalan => _node = d.asInstanceOf[Def[T]] } - private[scalan] def assignDef[B >: T](d: Def[B]): Unit = { + private[compiler] def assignDef[B >: T](d: Def[B]): Unit = { assignDefInternal(d) updateSymbolTable(this, d) } - private[scalan] def assignDefFrom[B >: T](sym: Ref[B]): Unit = { + private[compiler] def assignDefFrom[B >: T](sym: Ref[B]): Unit = { assignDefInternal(sym.node) } @@ -670,7 +671,7 @@ abstract class Base { scalan: Scalan => } /** Should be invoked to reset IR global node counter. */ - @inline final private[scalan] def resetIdCounter() = { currId = 0 } + @inline final private[compiler] def resetIdCounter() = { currId = 0 } /** Create or find symbol (node Ref) which refers to the given node in the table of all created symbols. * The d.nodeId is the index in the _symbolTable which is DBuffer (backed by Array) @@ -825,7 +826,7 @@ abstract class Base { scalan: Scalan => * @tparam T * @return The symbol of the graph which is semantically(up to rewrites) equivalent to d */ - protected[scalan] def toExp[T](d: Def[T], newSym: => Ref[T]): Ref[T] = { + protected[compiler] def toExp[T](d: Def[T], newSym: => Ref[T]): Ref[T] = { var res = findOrCreateDefinition(d, newSym) var currSym = res var currDef = d diff --git a/sc/shared/src/main/scala/scalan/DefRewriting.scala b/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala similarity index 94% rename from sc/shared/src/main/scala/scalan/DefRewriting.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala index 114fb1b0e6..62deffad31 100644 --- a/sc/shared/src/main/scala/scalan/DefRewriting.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala @@ -1,8 +1,14 @@ -package scalan +package sigma.compiler.ir +import sigma.compiler.DelayInvokeException import sigma.data.ExactNumeric -trait DefRewriting { scalan: Scalan => +/** Defines methods to implement graph rewriting optimization rules. + * The rules are defines as a series of pattern matching with stackable overriding. + * Can be mixed in into traits to add new rules (pattern cases) and call `super` + * implementation as a fallback case. + */ +trait DefRewriting { scalan: IRContext => /** Rewrites given node to another equivalent node and returns its reference. * @param d node to be matched against rewrite patterns diff --git a/sc/shared/src/main/scala/scalan/Entities.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Entities.scala similarity index 96% rename from sc/shared/src/main/scala/scalan/Entities.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/Entities.scala index 8a32dcde10..dfaeff207c 100644 --- a/sc/shared/src/main/scala/scalan/Entities.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Entities.scala @@ -1,7 +1,7 @@ -package scalan +package sigma.compiler.ir /** A slice in the Scalan cake with base classes for various descriptors. */ -trait Entities extends TypeDescs { self: Scalan => +trait Entities extends TypeDescs { self: IRContext => /** Base class for all descriptors of staged traits. * See derived classes in `impl` packages. diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala similarity index 98% rename from sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala index 5ddcdfa946..7c7b80d39a 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1,21 +1,20 @@ -package sigmastate.eval +package sigma.compiler.ir import org.ergoplatform._ -import scalan.MutableLazy -import sigma.{SigmaException, ast} import sigma.ast.TypeCodes.LastConstantCode import sigma.ast.Value.Typed -import sigma.ast._ import sigma.ast.syntax.{SValue, ValueOps} +import sigma.ast._ +import sigma.compiler.ir.core.MutableLazy import sigma.crypto.EcPointType import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral} import sigma.data.ExactOrdering.{ByteIsExactOrdering, IntIsExactOrdering, LongIsExactOrdering, ShortIsExactOrdering} import sigma.data.{CSigmaDslBuilder, ExactIntegral, ExactNumeric, ExactOrdering, Lazy, Nullable} -import sigma.util.Extensions.ByteOps -import sigmastate.interpreter.Interpreter.ScriptEnv -import sigma.ast.{Ident, Select, Val} import sigma.exceptions.GraphBuildingException import sigma.serialization.OpCodes +import sigma.util.Extensions.ByteOps +import sigma.{SigmaException, ast} +import sigmastate.interpreter.Interpreter.ScriptEnv import scala.collection.mutable.ArrayBuffer @@ -27,7 +26,7 @@ import scala.collection.mutable.ArrayBuffer * CSE however means the original structure of source code may not be preserved in the * resulting ErgoTree. * */ -trait GraphBuilding extends SigmaLibrary { IR: IRContext => +trait GraphBuilding extends Base with DefRewriting { IR: IRContext => import AvlTree._ import BigInt._ import Box._ @@ -42,8 +41,8 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => import SigmaProp._ import WOption._ - /** Should be specified in the final cake */ - val builder: SigmaBuilder + /** Builder used to create ErgoTree nodes. */ + val builder = TransformingSigmaBuilder import builder._ val okMeasureOperationTime: Boolean = false @@ -381,6 +380,18 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => def error(msg: String) = throw new GraphBuildingException(msg, None) def error(msg: String, srcCtx: Option[SourceContext]) = throw new GraphBuildingException(msg, srcCtx) + /** Graph node to represent a placeholder of a constant in ErgoTree. + * @param id Zero based index in ErgoTree.constants array. + * @param resultType type descriptor of the constant value. + */ + case class ConstantPlaceholder[T](id: Int, resultType: Elem[T]) extends Def[T] + + /** Smart constructor method for [[ConstantPlaceholder]], should be used instead of the + * class constructor. + */ + @inline def constantPlaceholder[T](id: Int, eT: Elem[T]): Ref[T] = ConstantPlaceholder(id, eT) + + /** Translates the given typed expression to IR graph representing a function from * Context to some type T. * @param env contains values for each named constant used @@ -465,6 +476,8 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => val resV = toRep(v)(e) resV } + case sigma.ast.ConstantPlaceholder(id, tpe) => + constantPlaceholder(id, stypeToElem(tpe)) case sigma.ast.Context => ctx case Global => sigmaDslBuilder case Height => ctx.HEIGHT diff --git a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala similarity index 92% rename from sc/shared/src/main/scala/scalan/GraphIRReflection.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 0eaba9d8a3..69736a0224 100644 --- a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -1,14 +1,11 @@ -package scalan +package sigma.compiler.ir -import scalan.primitives.Thunks +import sigma.compiler.ir.primitives.Thunks +import sigma.data.RType import sigma.reflection.ReflectionData.registerClassEntry import sigma.reflection.{ReflectionData, mkConstructor, mkMethod} -import sigmastate.eval.SigmaLibrary -import sigma.Colls -import sigma.SigmaDsl -import sigma.data.RType -import special.wrappers.{OptionWrapSpec, RTypeWrapSpec} -import wrappers.scalan.WRTypes +import sigma.compiler.ir.wrappers.{OptionWrapSpec, RTypeWrapSpec} +import sigma.compiler.ir.wrappers.sigma.{SigmaDsl, WRTypes} /** Registrations of reflection metadata for graph-ir module (see README.md). * Such metadata is only used on JS platform to support reflection-like interfaces of @@ -23,8 +20,8 @@ object GraphIRReflection { /** Forces initialization of reflection data. */ val reflection = ReflectionData - { val clazz = classOf[wrappers.scala.WOptions#WOption[_]] - val ctx = null.asInstanceOf[scalan.Library] // ok! type level only + { val clazz = classOf[sigma.compiler.ir.wrappers.scala.WOptions#WOption[_]] + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "filter", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -48,8 +45,8 @@ object GraphIRReflection { registerClassEntry(classOf[TypeDescs#FuncElem[_,_]], constructors = Array( - mkConstructor(Array(classOf[Scalan], classOf[TypeDescs#Elem[_]], classOf[TypeDescs#Elem[_]])) { args => - val ctx = args(0).asInstanceOf[Scalan] + mkConstructor(Array(classOf[IRContext], classOf[TypeDescs#Elem[_]], classOf[TypeDescs#Elem[_]])) { args => + val ctx = args(0).asInstanceOf[IRContext] new ctx.FuncElem(args(1).asInstanceOf[ctx.Elem[_]], args(2).asInstanceOf[ctx.Elem[_]]) } ) @@ -57,8 +54,8 @@ object GraphIRReflection { registerClassEntry(classOf[TypeDescs#PairElem[_,_]], constructors = Array( - mkConstructor(Array(classOf[Scalan], classOf[TypeDescs#Elem[_]], classOf[TypeDescs#Elem[_]])) { args => - val ctx = args(0).asInstanceOf[Scalan] + mkConstructor(Array(classOf[IRContext], classOf[TypeDescs#Elem[_]], classOf[TypeDescs#Elem[_]])) { args => + val ctx = args(0).asInstanceOf[IRContext] new ctx.PairElem(args(1).asInstanceOf[ctx.Elem[_]], args(2).asInstanceOf[ctx.Elem[_]]) } ) @@ -66,14 +63,14 @@ object GraphIRReflection { registerClassEntry(classOf[Thunks#ThunkElem[_]], constructors = Array( - mkConstructor(Array(classOf[Scalan], classOf[TypeDescs#Elem[_]])) { args => - val ctx = args(0).asInstanceOf[Scalan] + mkConstructor(Array(classOf[IRContext], classOf[TypeDescs#Elem[_]])) { args => + val ctx = args(0).asInstanceOf[IRContext] new ctx.ThunkElem(args(1).asInstanceOf[ctx.Elem[_]]) } ) ) - { val clazz = classOf[sigma.SigmaDsl#SigmaProp] + { val clazz = classOf[sigma.compiler.ir.wrappers.sigma.SigmaDsl#SigmaProp] val ctx = null.asInstanceOf[SigmaDsl] // ok! type level only registerClassEntry(clazz, methods = Map( @@ -122,8 +119,8 @@ object GraphIRReflection { ) } - { val clazz = classOf[Colls#CollBuilder] - val ctx = null.asInstanceOf[Library] // ok! type level only + { val clazz = classOf[sigma.compiler.ir.wrappers.sigma.Colls#CollBuilder] + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "xor", Array[Class[_]](classOf[Base#Ref[_]], classOf[Base#Ref[_]])) { (obj, args) => @@ -144,8 +141,8 @@ object GraphIRReflection { } { - val clazz = classOf[Colls#Coll[_]] - val ctx = null.asInstanceOf[Library] // ok! type level only + val clazz = classOf[sigma.compiler.ir.wrappers.sigma.Colls#Coll[_]] + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "append", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -211,7 +208,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#AvlTree] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "updateOperations", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -269,7 +266,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#Box] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "value", Array[Class[_]]()) { (obj, _) => @@ -302,7 +299,7 @@ object GraphIRReflection { { val clazz = classOf[SigmaDsl#Context] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "LastBlockUtxoRootHash", Array[Class[_]]()) { (obj, args) => @@ -343,7 +340,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#GroupElement] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "exp", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -363,7 +360,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#Header] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "minerPk", Array[Class[_]]()) { (obj, args) => @@ -416,7 +413,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#PreHeader] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "minerPk", Array[Class[_]]()) { (obj, _) => @@ -445,7 +442,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#SigmaDslBuilder] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "byteArrayToLong", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -512,7 +509,7 @@ object GraphIRReflection { ) } - { val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + { val ctx = null.asInstanceOf[IRContext] // ok! type level only val clazz = classOf[ctx.WOption.WOptionElem[_, _]] registerClassEntry(clazz, constructors = Array( @@ -525,7 +522,7 @@ object GraphIRReflection { } { val clazz = classOf[WRTypes#WRType[_]] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "name", Array[Class[_]]()) { (obj, _) => @@ -535,7 +532,7 @@ object GraphIRReflection { ) } - { val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + { val ctx = null.asInstanceOf[IRContext] // ok! type level only val clazz = classOf[ctx.WRType.WRTypeElem[_, _]] registerClassEntry(clazz, constructors = Array( @@ -547,7 +544,7 @@ object GraphIRReflection { ) } - { val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + { val ctx = null.asInstanceOf[IRContext] // ok! type level only val clazz = classOf[ctx.Coll.CollElem[_, _]] registerClassEntry(clazz, constructors = Array( @@ -559,16 +556,6 @@ object GraphIRReflection { ) } - { val clazz = classOf[wrappers.special.WSpecialPredefs#WSpecialPredefCompanion] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only - registerClassEntry(clazz, - methods = Map( - mkMethod(clazz, "some", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => - obj.asInstanceOf[ctx.WSpecialPredefCompanion].some(args(0).asInstanceOf[ctx.Ref[Any]]) - } - ) - ) - } { val clazz = classOf[OptionWrapSpec] registerClassEntry(clazz, diff --git a/sc/shared/src/main/scala/scalan/Library.scala b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala similarity index 58% rename from sc/shared/src/main/scala/scalan/Library.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala index 43f20813f0..c60bc0882f 100644 --- a/sc/shared/src/main/scala/scalan/Library.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala @@ -1,19 +1,65 @@ -package scalan +package sigma.compiler.ir -import scala.language.implicitConversions -import sigma._ +import sigma.compiler.ir.core.MutableLazy +import sigma.compiler.ir.primitives._ import sigma.data.{Nullable, RType} -import special.wrappers.WrappersModule import sigma.util.MemoizedFunc - -trait Library extends Scalan - with WrappersModule +import sigma.compiler.ir.wrappers.scala.WOptionsModule +import sigma.compiler.ir.wrappers.sigma.{CollsModule, SigmaDslModule, WRTypesModule} + +/** Aggregate cake with all inter-dependent modules assembled together. + * Each instance of this class contains independent IR context, thus many + * instances can be created simultaneously. + * However, the inner types declared in the traits are path-dependant. + * This in particular means that ctx1.Ref[_] and ctx2.Ref[_] are different types. + * The typical usage is to create `val ctx = new Scalan` and then import inner + * declarations using `import ctx._`. + * This way the declaration will be directly available as if they were global + * declarations. + * At the same time cake design pattern allow to `override` many methods and values + * in classed derived from `Scalan`, this is significant benefit over + * *everything is global* design. + * + * It is not used in v5.0 interpreter and thus not part of consensus. + * Used in ErgoScript compiler only. + * + * @see CompiletimeIRContext + */ +trait IRContext + extends TypeDescs + with MethodCalls + with Tuples + with NumericOps + with UnBinOps + with LogicalOps + with OrderingOps + with Equal + with MiscOps + with Functions + with IfThenElse + with Transforming + with Thunks + with Entities + with Modules + with DefRewriting with CollsModule -{ + with SigmaDslModule + with TreeBuilding + with GraphBuilding + with WOptionsModule + with WRTypesModule { + + import Coll._ + import CollBuilder._ import WOption._ import WRType._ - import Coll._; import CollBuilder._; - import WSpecialPredef._ + + /** Pass configuration which is used to turn-off constant propagation. + * USED IN TESTS ONLY. + * @see `beginPass(noCostPropagationPass)` */ + lazy val noConstPropagationPass = new DefaultPass( + "noCostPropagationPass", + Pass.defaultPassConfig.copy(constantPropagation = false)) type LazyRep[T] = MutableLazy[Ref[T]] @@ -26,11 +72,7 @@ trait Library extends Scalan _liftElemMemo(eT).asInstanceOf[Ref[WRType[T]]] // asRep cannot be used for AnyRef } - private val _specialPredef: LazyRep[WSpecialPredefCompanionCtor] = MutableLazy(RWSpecialPredef.value) - def specialPredef: Ref[WSpecialPredefCompanionCtor] = _specialPredef.value - override protected def onReset(): Unit = { - _specialPredef.reset() _liftElemMemo.reset() super.onReset() } @@ -38,10 +80,15 @@ trait Library extends Scalan val CM = CollMethods private val CBM = CollBuilderMethods private val WOptionM = WOptionMethods - private val SPCM = WSpecialPredefCompanionMethods def colBuilder: Ref[CollBuilder] + /** Type descriptor for [[WRType]] */ + implicit lazy val wRTypeAnyElement: Elem[WRType[Any]] = wRTypeElement(AnyElement) + + /** During compilation represent a global value Global, see also SGlobal type. */ + def sigmaDslBuilder: Ref[SigmaDslBuilder] + object IsNumericToInt { def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { case ApplyUnOp(_: NumericToInt[_], x) => Nullable(x.asInstanceOf[Ref[A] forSome {type A}]) @@ -96,8 +143,6 @@ trait Library extends Scalan } case WOptionM.getOrElse(opt, _) => opt.node match { - // Rule: Some(x).getOrElse(_) ==> x - case SPCM.some(x) => x case WOptionConst(Some(x), lA) => lA.lift(x) case _ => super.rewriteDef(d) } @@ -118,3 +163,6 @@ trait Library extends Scalan } } + +/** IR context to be used by script development tools to compile ErgoScript into ErgoTree bytecode. */ +class CompiletimeIRContext extends IRContext diff --git a/sc/shared/src/main/scala/scalan/MethodCalls.scala b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala similarity index 94% rename from sc/shared/src/main/scala/scalan/MethodCalls.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala index 14212df632..876f0e9d7e 100644 --- a/sc/shared/src/main/scala/scalan/MethodCalls.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala @@ -1,13 +1,16 @@ -package scalan +package sigma.compiler.ir -import scala.annotation.{tailrec, unused} -import scala.reflect.ClassTag -import debox.{Buffer => DBuffer} -import debox.cfor +import debox.{cfor, Buffer => DBuffer} +import sigma.compiler.DelayInvokeException import sigma.reflection.RMethod import sigma.util.CollectionUtil.TraversableOps -trait MethodCalls extends Base { self: Scalan => +import scala.annotation.{tailrec, unused} + +/** Defines graph-ir representation of method calls, new object creation as well as the + * related utility methods. + */ +trait MethodCalls extends Base { self: IRContext => def delayInvoke = throw new DelayInvokeException @@ -116,7 +119,7 @@ trait MethodCalls extends Base { self: Scalan => def rewriteNonInvokableMethodCall(@unused mc: MethodCall): Ref[_] = null /** Generic helper to call the given method on the given receiver node. */ - private[scalan] def invokeMethod[A](receiver: Sym, m: RMethod, args: Array[AnyRef], + private[compiler] def invokeMethod[A](receiver: Sym, m: RMethod, args: Array[AnyRef], onInvokeSuccess: Any => A, onInvokeException: Throwable => A, onInvokeImpossible: => A): A = { diff --git a/sc/shared/src/main/scala/scalan/Modules.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala similarity index 70% rename from sc/shared/src/main/scala/scalan/Modules.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala index 989f2c524c..b58bacb5fb 100644 --- a/sc/shared/src/main/scala/scalan/Modules.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala @@ -1,6 +1,11 @@ -package scalan +package sigma.compiler.ir -trait Modules extends Base { self: Scalan => +import sigma.compiler.ir.meta.ModuleInfo + +/** Defines registration of IR modules. + * @see ModuleInfo + */ +trait Modules extends Base { self: IRContext => /** Whether staged modules should be registered when cake is constructed and initialized. */ def okRegisterModules: Boolean = false diff --git a/sc/shared/src/main/scala/scalan/staged/ProgramGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/ProgramGraphs.scala similarity index 92% rename from sc/shared/src/main/scala/scalan/staged/ProgramGraphs.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/ProgramGraphs.scala index ccb351e7a2..6f447d97f9 100644 --- a/sc/shared/src/main/scala/scalan/staged/ProgramGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/ProgramGraphs.scala @@ -1,13 +1,13 @@ -package scalan.staged +package sigma.compiler.ir -import scalan.Scalan -import debox.{Buffer => DBuffer} -import sigma.util.GraphUtil -import debox.cfor +import debox.{cfor, Buffer => DBuffer} import sigma.data.{DFunc, Nullable} +import sigma.util.GraphUtil + import scala.collection.compat.immutable.ArraySeq -trait ProgramGraphs extends AstGraphs { self: Scalan => +/** Defines implementation of [[ProgramGraph]] and related utilities. */ +trait ProgramGraphs extends AstGraphs { self: IRContext => type PGraph = ProgramGraph diff --git a/sc/shared/src/main/scala/scalan/staged/Transforming.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Transforming.scala similarity index 97% rename from sc/shared/src/main/scala/scalan/staged/Transforming.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/Transforming.scala index a64b998ff6..876f2b5db1 100644 --- a/sc/shared/src/main/scala/scalan/staged/Transforming.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Transforming.scala @@ -1,14 +1,18 @@ -package scalan.staged +package sigma.compiler.ir -import java.util -import scala.language.existentials -import scalan.Scalan -import debox.{Buffer => DBuffer} -import debox.cfor +import debox.{cfor, Buffer => DBuffer} import sigma.data.{Lazy, Nullable} import sigma.reflection.RMethod -trait Transforming { self: Scalan => +import java.util +import scala.language.existentials + +/** Implements utilites for graph transformation and rewriting. + * @see Pass + * @see MapTransformer + * @see Rewriter + */ +trait Transforming { self: IRContext => /** Descriptor of a current compiler pass. * Compiler can be configured to perform one pass after another. diff --git a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala similarity index 98% rename from sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 27f659c1ed..725e3b1d19 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -1,16 +1,14 @@ -package sigmastate.eval +package sigma.compiler.ir - -import sigma.ast._ import org.ergoplatform._ -import sigma.ast.syntax.ValueOps -import sigma.serialization.OpCodes._ -import sigma.serialization.ConstantStore -import sigma.ast.syntax._ +import sigma.ast._ +import sigma.ast.syntax.{ValueOps, _} import sigma.data.{ProveDHTuple, ProveDlog} +import sigma.serialization.ConstantStore +import sigma.serialization.OpCodes._ +import sigma.serialization.ValueCodes.OpCode import scala.collection.mutable.ArrayBuffer -import sigma.serialization.ValueCodes.OpCode /** Implementation of IR-graph to ErgoTree expression translation. * This, in a sense, is inverse to [[GraphBuilding]], however roundtrip identity is not @@ -24,17 +22,17 @@ import sigma.serialization.ValueCodes.OpCode * * @see buildTree method * */ -trait TreeBuilding extends SigmaLibrary { IR: IRContext => - import Liftables._ - import Context._ - import SigmaProp._ - import Coll._ +trait TreeBuilding extends Base { IR: IRContext => + import BigInt._ import Box._ + import Coll._ import CollBuilder._ + import Context._ + import GroupElement._ + import Liftables._ import SigmaDslBuilder._ - import BigInt._ + import SigmaProp._ import WOption._ - import GroupElement._ /** Convenience synonyms for easier pattern matching. */ private val ContextM = ContextMethods @@ -130,7 +128,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => */ object IsInternalDef { def unapply(d: Def[_]): Option[Def[_]] = d match { - case _: SigmaDslBuilder | _: CollBuilder | _: WSpecialPredefCompanion => Some(d) + case _: SigmaDslBuilder | _: CollBuilder => Some(d) case _ => None } } @@ -183,6 +181,10 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => case None => mkConstant[tpe.type](x.asInstanceOf[tpe.WrappedType], tpe) } + case Def(IR.ConstantPlaceholder(id, elem)) => + val tpe = elemToSType(elem) + mkConstantPlaceholder[tpe.type](id, tpe) + case Def(wc: LiftedConst[a,_]) => val tpe = elemToSType(s.elem) mkConstant[tpe.type](wc.constValue.asInstanceOf[tpe.WrappedType], tpe) diff --git a/sc/shared/src/main/scala/scalan/TypeDescs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala similarity index 97% rename from sc/shared/src/main/scala/scalan/TypeDescs.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala index fdef77a108..366107edca 100644 --- a/sc/shared/src/main/scala/scalan/TypeDescs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala @@ -1,18 +1,22 @@ -package scalan +package sigma.compiler.ir -import scala.language.implicitConversions -import scala.annotation.implicitNotFound -import scala.collection.immutable.ListMap - -import scala.collection.mutable import debox.cfor import scalan.core.{Contravariant, Covariant, Variance} import sigma.data.{AVHashMap, Lazy, Nullable, RType} import sigma.reflection.{RClass, RConstructor, RMethod} import sigma.util.CollectionUtil -import special.wrappers.WrapSpec +import sigma.compiler.ir.wrappers.WrapSpec + +import scala.annotation.implicitNotFound +import scala.collection.immutable.ListMap +import scala.collection.mutable +import scala.language.implicitConversions -abstract class TypeDescs extends Base { self: Scalan => +/** Defines [[Elem]] descriptor of types in IRContext together with related utilities. + * @see MethodDesc + * @see TypeDesc + */ +abstract class TypeDescs extends Base { self: IRContext => /** Helper type case method. */ @inline final def asElem[T](d: TypeDesc): Elem[T] = d.asInstanceOf[Elem[T]] @@ -267,7 +271,7 @@ abstract class TypeDescs extends Base { self: Scalan => e.invokeUnlifted(mc, dataEnv) /** Get first (and the only) constructor of the `clazz`. */ - private[scalan] final def getConstructor(clazz: RClass[_]): RConstructor[_] = { + private[compiler] final def getConstructor(clazz: RClass[_]): RConstructor[_] = { val constructors = clazz.getConstructors() if (constructors.length != 1) !!!(s"Element class $clazz has ${constructors.length} constructors, 1 expected") @@ -297,7 +301,7 @@ abstract class TypeDescs extends Base { self: Scalan => protected val elemCache = AVHashMap[RClass[_], ElemCacheEntry](1000) - private[scalan] final def cachedElem0(clazz: RClass[_], optConstructor: Nullable[RConstructor[_]], args: Seq[AnyRef]): Elem[_] = { + private[compiler] final def cachedElem0(clazz: RClass[_], optConstructor: Nullable[RConstructor[_]], args: Seq[AnyRef]): Elem[_] = { val entry = elemCache.get(clazz) match { case Nullable(entry) => entry case _ => diff --git a/sc/shared/src/main/scala/scalan/MutableLazy.scala b/sc/shared/src/main/scala/sigma/compiler/ir/core/MutableLazy.scala similarity index 96% rename from sc/shared/src/main/scala/scalan/MutableLazy.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/core/MutableLazy.scala index 5b6a579476..efaab623a3 100644 --- a/sc/shared/src/main/scala/scalan/MutableLazy.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/core/MutableLazy.scala @@ -1,4 +1,4 @@ -package scalan +package sigma.compiler.ir.core import scala.language.implicitConversions diff --git a/sc/shared/src/main/scala/scalan/core/Variance.scala b/sc/shared/src/main/scala/sigma/compiler/ir/core/Variance.scala similarity index 100% rename from sc/shared/src/main/scala/scalan/core/Variance.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/core/Variance.scala diff --git a/sc/shared/src/main/scala/scalan/ModuleInfo.scala b/sc/shared/src/main/scala/sigma/compiler/ir/meta/ModuleInfo.scala similarity index 90% rename from sc/shared/src/main/scala/scalan/ModuleInfo.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/meta/ModuleInfo.scala index 86fce48ce6..3ccdca18ac 100644 --- a/sc/shared/src/main/scala/scalan/ModuleInfo.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/meta/ModuleInfo.scala @@ -1,6 +1,4 @@ -package scalan - -import scalan.meta.SSymName +package sigma.compiler.ir.meta /** Information about generated Special library module. * Instances are created in generated code. diff --git a/sc/shared/src/main/scala/scalan/meta/SSymName.scala b/sc/shared/src/main/scala/sigma/compiler/ir/meta/SSymName.scala similarity index 62% rename from sc/shared/src/main/scala/scalan/meta/SSymName.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/meta/SSymName.scala index b0f8dae6d2..944b505250 100644 --- a/sc/shared/src/main/scala/scalan/meta/SSymName.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/meta/SSymName.scala @@ -1,17 +1,13 @@ -package scalan.meta +package sigma.compiler.ir.meta import sigma.util.StringUtil.StringUtilExtensions -case class ImportItem(packageName: String, importedNames: List[String]) - case class SSymName(packageName: String, name: String) { import SSymName._ def mkFullName = fullNameString(packageName, name) } object SSymName { - /** Wildcard character used to signify importing all names from namespace */ - val ImportAllWildcard = "*" def fullNameString(packageName: String, name: String): String = if (packageName.isNullOrEmpty) name else s"$packageName.$name" } \ No newline at end of file diff --git a/sc/shared/src/main/scala/scalan/primitives/Equal.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Equal.scala similarity index 84% rename from sc/shared/src/main/scala/scalan/primitives/Equal.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/Equal.scala index 4d64e94383..ec27fff12b 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Equal.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Equal.scala @@ -1,10 +1,11 @@ -package scalan.primitives +package sigma.compiler.ir.primitives -import scalan.{Base, Scalan} +import sigma.compiler.ir.{Base, IRContext} import scala.annotation.unused -trait Equal extends Base { self: Scalan => +/** Defines IR representation of equality operations. */ +trait Equal extends Base { self: IRContext => /** Binary operation representing structural equality between arguments. */ case class Equals[A: Elem]() extends BinOp[A, Boolean]("==") { override def applySeq(x: A, y: A): Boolean = equalValues[A](x, y) diff --git a/sc/shared/src/main/scala/scalan/primitives/Functions.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Functions.scala similarity index 97% rename from sc/shared/src/main/scala/scalan/primitives/Functions.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/Functions.scala index 9026461777..cd028de9b6 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Functions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Functions.scala @@ -1,16 +1,15 @@ -package scalan.primitives +package sigma.compiler.ir.primitives -import java.util -import scalan.staged.ProgramGraphs -import scalan.{Base, Scalan} -import debox.{Buffer => DBuffer} - -import scala.language.implicitConversions -import debox.cfor +import debox.{cfor, Buffer => DBuffer} +import sigma.compiler.ir.{Base, IRContext, ProgramGraphs} import sigma.data.{Lazy, Nullable, emptyDBufferOfInt} import sigma.util.GraphUtil -trait Functions extends Base with ProgramGraphs { self: Scalan => +import java.util +import scala.language.implicitConversions + +/** Defines IR representation of functions (Lambdas) and function application. */ +trait Functions extends Base with ProgramGraphs { self: IRContext => implicit class LambdaOps[A,B](f: Ref[A => B]) { /** Apply given function symbol to the given argument symbol. @@ -145,10 +144,6 @@ trait Functions extends Base with ProgramGraphs { self: Scalan => // emitDepGraph(roots, FileUtil.file(cwd, dir), "nested_lambda")(defaultGraphVizConfig) assert(false, s"Invalid nested lambda $l inside $this") } - case op @ OpCost(_, _, args, opCost) => - if (args.contains(opCost)) { - !!!(s"Invalid OpCost($op)") - } case _ => } } diff --git a/sc/shared/src/main/scala/scalan/primitives/IfThenElse.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/IfThenElse.scala similarity index 90% rename from sc/shared/src/main/scala/scalan/primitives/IfThenElse.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/IfThenElse.scala index 22fd2095d7..0ce94a83c1 100644 --- a/sc/shared/src/main/scala/scalan/primitives/IfThenElse.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/IfThenElse.scala @@ -1,8 +1,9 @@ -package scalan.primitives +package sigma.compiler.ir.primitives -import scalan.{Base, Scalan} +import sigma.compiler.ir.{Base, IRContext} -trait IfThenElse extends Base { self: Scalan => +/** Defines IR representation of conditional expressions `if (c) t else e`. */ +trait IfThenElse extends Base { self: IRContext => /** If c then t else e construction with standard lazy evaluation of branches. * The representation uses Thunk for each branch */ diff --git a/sc/shared/src/main/scala/scalan/primitives/LogicalOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/LogicalOps.scala similarity index 91% rename from sc/shared/src/main/scala/scalan/primitives/LogicalOps.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/LogicalOps.scala index e81b546139..183b4a8e84 100644 --- a/sc/shared/src/main/scala/scalan/primitives/LogicalOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/LogicalOps.scala @@ -1,9 +1,9 @@ -package scalan.primitives +package sigma.compiler.ir.primitives -import scalan.{Base, Scalan} +import sigma.compiler.ir.{Base, IRContext} -/** Slice in Scala cake with definitions of logical operations. */ -trait LogicalOps extends Base { self: Scalan => +/** Slice in IRContext cake with definitions of logical operations. */ +trait LogicalOps extends Base { self: IRContext => /** Logical AND binary operation. */ val And = new EndoBinOp[Boolean]("&&") { override def applySeq(x: Boolean, y: Boolean): Boolean = x && y diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscOps.scala new file mode 100644 index 0000000000..58382a279c --- /dev/null +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscOps.scala @@ -0,0 +1,44 @@ +package sigma.compiler.ir.primitives + +import sigma.compiler.ir.{Base, IRContext} + +/** Defines IR representation of miscellaneous operations that doesn't fit into any + * specific category. + */ +trait MiscOps extends Base { self: IRContext => + case class HashCode[A]() extends UnOp[A, Int]("hashCode") { + override def applySeq(x: A): Int = x.hashCode + } + + case class ToString[A]() extends UnOp[A, String]("toString") { + override def applySeq(x: A): String = x.toString + } + + case class Downcast[From, To](input: Ref[From], eTo: Elem[To]) extends BaseDef[To]()(eTo) { + override def transform(t: Transformer) = Downcast(t(input), eTo) + } + case class Upcast[From, To](input: Ref[From], eTo: Elem[To]) extends BaseDef[To]()(eTo) { + override def transform(t: Transformer) = Upcast(t(input), eTo) + } + + def downcast[To:Elem](value: Ref[_]): Ref[To] = Downcast(value, element[To]) + def upcast[To:Elem](value: Ref[_]): Ref[To] = Upcast(value, element[To]) + + implicit class RepUniversalOps[A](x: Ref[A]) { + def hashCodeRep: Ref[Int] = HashCode[A]().apply(x) + def toStringRep = ToString[A]().apply(x) + } + + case class Convert[From,To](eFrom: Elem[From], eTo: Elem[To], x: Ref[Def[_]], conv: Ref[From => To]) + extends BaseDef[To]()(eTo) { + override def transform(t: Transformer) = Convert(eFrom, eTo, t(x), t(conv)) + } + + def tryConvert[From, To](eFrom: Elem[From], eTo: Elem[To], x: Ref[Def[_]], conv: Ref[From => To]): Ref[To] = { + if (x.elem <:< eFrom) + conv(asRep[From](x)) + else + Convert(eFrom, eTo, x, conv) + } + +} diff --git a/sc/shared/src/main/scala/scalan/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala similarity index 94% rename from sc/shared/src/main/scala/scalan/primitives/NumericOps.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index 3c3d80e94d..4e732bbb5f 100644 --- a/sc/shared/src/main/scala/scalan/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -1,10 +1,10 @@ -package scalan.primitives +package sigma.compiler.ir.primitives -import scalan.{Base, Scalan} +import sigma.compiler.ir.{Base, IRContext} import sigma.data.{ExactIntegral, ExactNumeric} -/** Slice in Scala cake with definitions of numeric operations. */ -trait NumericOps extends Base { self: Scalan => +/** Slice in IRContext cake with definitions of numeric operations. */ +trait NumericOps extends Base { self: IRContext => /** Extension methods over `Ref[T]` where T is instance of ExactNumeric type-class. */ implicit class NumericOpsCls[T](x: Ref[T])(implicit val n: ExactNumeric[T]) { diff --git a/sc/shared/src/main/scala/scalan/primitives/OrderingOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/OrderingOps.scala similarity index 91% rename from sc/shared/src/main/scala/scalan/primitives/OrderingOps.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/OrderingOps.scala index 8e6f5e0134..be8f934706 100644 --- a/sc/shared/src/main/scala/scalan/primitives/OrderingOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/OrderingOps.scala @@ -1,12 +1,12 @@ -package scalan.primitives +package sigma.compiler.ir.primitives -import scalan.{Base, Scalan} +import sigma.compiler.ir.{Base, IRContext} import sigma.data.ExactOrdering import scala.language.implicitConversions -/** Slice in Scala cake with definitions of comparison operations. */ -trait OrderingOps extends Base { self: Scalan => +/** Slice in IRContext cake with definitions of comparison operations. */ +trait OrderingOps extends Base { self: IRContext => implicit def repOrderingToOrderingOps[T](x: Ref[T])(implicit n: ExactOrdering[T]) = new OrderingOpsCls(x) implicit def OrderingToOrderingOps[T](x: T)(implicit n: ExactOrdering[T], et: Elem[T]) = new OrderingOpsCls(toRep(x)) diff --git a/sc/shared/src/main/scala/scalan/primitives/Thunks.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Thunks.scala similarity index 98% rename from sc/shared/src/main/scala/scalan/primitives/Thunks.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/Thunks.scala index f9f843664d..8674918907 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Thunks.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Thunks.scala @@ -1,22 +1,22 @@ -package scalan.primitives +package sigma.compiler.ir.primitives -import scala.language.{existentials, implicitConversions} -import scalan._ -import debox.{Buffer => DBuffer, Set => DSet} -import debox.cfor +import debox.{cfor, Buffer => DBuffer, Set => DSet} import scalan.core.Covariant +import sigma.compiler.ir.IRContext import sigma.data.{AVHashMap, DFunc, Lazy, Nullable, RType} import sigma.reflection.RClass import sigma.util.GraphUtil import scala.collection.Seq +import scala.language.{existentials, implicitConversions} -/** Slice in the [[Scalan]] cake with definitions of Thunk operations. +/** Slice in the [[IRContext]] cake with definitions of Thunk operations. * See https://en.wikipedia.org/wiki/Thunk. * Thunks are used to represent lazy operations in the graph IR. + * * @see ApplyBinOpLazy, IfThenElseLazy */ -trait Thunks extends Functions { self: Scalan => +trait Thunks extends Functions { self: IRContext => type Th[+T] = Ref[Thunk[T]] diff --git a/sc/shared/src/main/scala/scalan/primitives/Tuples.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Tuples.scala similarity index 92% rename from sc/shared/src/main/scala/scalan/primitives/Tuples.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/Tuples.scala index fd201b9574..59a5d810b9 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Tuples.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Tuples.scala @@ -2,13 +2,15 @@ * Author: Alexander Slesarenko * Date: 7/25/12 */ -package scalan.primitives +package sigma.compiler.ir.primitives + +import sigma.compiler.ir.{Base, IRContext} +import sigma.data.AVHashMap -import scalan.{Base, Scalan} import scala.language.implicitConversions -import sigma.data.{AVHashMap} -trait Tuples extends Base { self: Scalan => +/** Slice in [[IRContext]] cake with definitions of pairs and tuples. */ +trait Tuples extends Base { self: IRContext => object Pair { def apply[A, B](a: Ref[A], b: Ref[B]) = zipPair[A, B]((a, b)) def unapply[A, B](p: Ref[(A, B)]) = Some(unzipPair[A, B](p)) diff --git a/sc/shared/src/main/scala/scalan/primitives/UnBinOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala similarity index 94% rename from sc/shared/src/main/scala/scalan/primitives/UnBinOps.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala index 749556bf0e..23f8bc3800 100644 --- a/sc/shared/src/main/scala/scalan/primitives/UnBinOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala @@ -1,8 +1,9 @@ -package scalan.primitives +package sigma.compiler.ir.primitives -import scalan.{Scalan, Base} +import sigma.compiler.ir.{Base, IRContext} -trait UnBinOps extends Base { self: Scalan => +/** Defines IR representation of unary and binary operations. */ +trait UnBinOps extends Base { self: IRContext => /** Base class for descriptors of unary operations. */ abstract class UnOp[A, R](val opName: String)(implicit val eResult: Elem[R]) { diff --git a/sc/shared/src/main/scala/special/wrappers/WrapSpec.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrapSpec.scala similarity index 76% rename from sc/shared/src/main/scala/special/wrappers/WrapSpec.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrapSpec.scala index dd07f1144c..b9c21227b2 100644 --- a/sc/shared/src/main/scala/special/wrappers/WrapSpec.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrapSpec.scala @@ -1,4 +1,4 @@ -package special.wrappers +package sigma.compiler.ir.wrappers /** Base type for all wrapper specification classes. * @see OptionWrapSpec as an example */ diff --git a/sc/shared/src/main/scala/special/wrappers/WrappersSpec.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersSpec.scala similarity index 91% rename from sc/shared/src/main/scala/special/wrappers/WrappersSpec.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersSpec.scala index d520ce9006..4c0c5f05eb 100644 --- a/sc/shared/src/main/scala/special/wrappers/WrappersSpec.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersSpec.scala @@ -1,7 +1,5 @@ -package special.wrappers - -import sigma.data.RType - +package sigma.compiler.ir.wrappers +import _root_.sigma.data.RType /** Base class for wrappers of such types as WOption, WRType etc. * Used in graph IR to implement method invocation. */ diff --git a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala similarity index 64% rename from sc/shared/src/main/scala/wrappers/scala/WOptions.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala index 4bd314c1de..2ed1237e6b 100644 --- a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala @@ -1,9 +1,8 @@ -package wrappers.scala { - import scalan._ +package sigma.compiler.ir.wrappers.scala { + import sigma.compiler.ir.{Base, IRContext} - import special.wrappers.WrappersModule - - trait WOptions extends Base { self: WrappersModule => + /** Defines IR representation of Option type. */ + trait WOptions extends Base { self: IRContext => trait WOption[A] extends Def[WOption[A]] { implicit def eA: Elem[A]; def isDefined: Ref[Boolean]; diff --git a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala similarity index 93% rename from sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala index 45d0a91ad6..514415d2bd 100644 --- a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala @@ -1,18 +1,21 @@ -package wrappers.scala +package sigma.compiler.ir.wrappers.scala + +import scala.language.{existentials, implicitConversions} +import sigma.compiler.ir.IRContext +import sigma.compiler.ir.wrappers.OptionWrapSpec -import scala.language.{existentials,implicitConversions} -import scalan._ -import special.wrappers.WrappersModule -import special.wrappers.OptionWrapSpec import scala.collection.compat.immutable.ArraySeq package impl { + import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- -trait WOptionsDefs extends scalan.Scalan with WOptions { - self: WrappersModule => +/** IR representation of Option type and methods. */ +trait WOptionsDefs extends Base with WOptions { + self: IRContext => class WOptionCls extends EntityObject("WOption") { // entityConst: single const for each entity @@ -235,9 +238,9 @@ class WOptionCls extends EntityObject("WOption") { registerEntityObject("WOption", WOption) } -object WOptionsModule extends scalan.ModuleInfo("wrappers.scala", "WOptions") { +object WOptionsModule extends ModuleInfo("sigma.compiler.ir.wrappers.scala", "WOptions") { val reflection = GraphIRReflection } } -trait WOptionsModule extends wrappers.scala.impl.WOptionsDefs {self: WrappersModule =>} +trait WOptionsModule extends sigma.compiler.ir.wrappers.scala.impl.WOptionsDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/special/collection/CollsUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala similarity index 93% rename from sc/shared/src/main/scala/special/collection/CollsUnit.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala index 90f0dca99e..9b4a002a14 100644 --- a/sc/shared/src/main/scala/special/collection/CollsUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala @@ -1,5 +1,6 @@ -package sigma { - import scalan._ +package sigma.compiler.ir.wrappers.sigma + +import sigma.compiler.ir.{Base, IRContext} /** Staged version of collection interfaces which is used in graph-based IR to represent * methods of Coll and CollBuilder. @@ -8,7 +9,7 @@ package sigma { * The semantics of each method is the same as in the original class, please look there * for details. */ - trait Colls extends Base { self: Library => + trait Colls extends Base { self: IRContext => trait Coll[A] extends Def[Coll[A]] { implicit def eA: Elem[A]; def length: Ref[Int]; @@ -34,5 +35,4 @@ package sigma { def xor(left: Ref[Coll[Byte]], right: Ref[Coll[Byte]]): Ref[Coll[Byte]]; def replicate[T](n: Ref[Int], v: Ref[T]): Ref[Coll[T]]; }; - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala similarity index 96% rename from sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 48548226a5..2a6a341686 100644 --- a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -1,8 +1,10 @@ -package sigma { - import scalan._ - import sigmastate.eval.SigmaLibrary +package sigma.compiler.ir.wrappers.sigma - trait SigmaDsl extends Base { self: SigmaLibrary => +import scalan._ + import sigma.compiler.ir.{Base, IRContext} + + /** IR representation of ErgoScript (Sigma) language types and methods. */ + trait SigmaDsl extends Base { self: IRContext => trait BigInt extends Def[BigInt] { def add(that: Ref[BigInt]): Ref[BigInt]; def subtract(that: Ref[BigInt]): Ref[BigInt]; @@ -124,5 +126,4 @@ package sigma { trait ContextCompanion; trait SigmaContractCompanion; trait SigmaDslBuilderCompanion - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WRTypes.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WRTypes.scala new file mode 100644 index 0000000000..0bd2b47e5b --- /dev/null +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WRTypes.scala @@ -0,0 +1,13 @@ +package sigma.compiler.ir.wrappers.sigma + +import sigma.compiler.ir.{Base, IRContext} + + + /** IR representation of RType. */ + trait WRTypes extends Base { self: IRContext => + trait WRType[A] extends Def[WRType[A]] { + implicit def eA: Elem[A]; + def name: Ref[String] + }; + trait WRTypeCompanion + } \ No newline at end of file diff --git a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala similarity index 97% rename from sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala index 239bfff4e5..0a18ea586a 100644 --- a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala @@ -1,16 +1,21 @@ -package sigma +package sigma.compiler.ir.wrappers.sigma + +import scala.language.{existentials, implicitConversions} +import sigma.compiler.ir.IRContext +import sigma.compiler.ir.wrappers.sigma.impl.CollsDefs -import scala.language.{existentials,implicitConversions} -import scalan._ import scala.collection.compat.immutable.ArraySeq package impl { + import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} - // Abs ----------------------------------- -trait CollsDefs extends scalan.Scalan with Colls { - self: Library => +// Abs ----------------------------------- +/** Implementation part of IR represenation related to Coll type and methods. */ +trait CollsDefs extends Base with Colls { + self: IRContext => registerModule(CollsModule) @@ -634,9 +639,9 @@ object CollBuilder extends EntityObject("CollBuilder") { } -object CollsModule extends scalan.ModuleInfo("sigma", "Colls") { +object CollsModule extends ModuleInfo("sigma", "Colls") { val reflection = GraphIRReflection } } -trait CollsModule extends sigma.impl.CollsDefs {self: Library =>} +trait CollsModule extends CollsDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala similarity index 99% rename from sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 70fb35c329..c113cb7de3 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1,19 +1,23 @@ -package sigma +package sigma.compiler.ir.wrappers.sigma import scala.language.{existentials, implicitConversions} import scalan._ -import sigmastate.eval.SigmaLibrary +import sigma.compiler.ir.IRContext +import sigma.compiler.ir.wrappers.sigma.impl.SigmaDslDefs import scala.collection.compat.immutable.ArraySeq package impl { + import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.wrappers.sigma.SigmaDsl + import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} - import sigmastate.eval.SigmaLibrary +/** Implementation part of IR represenation related to Sigma types and methods. */ // Abs ----------------------------------- -trait SigmaDslDefs extends scalan.Scalan with SigmaDsl { - self: SigmaLibrary => +trait SigmaDslDefs extends Base with SigmaDsl { + self: IRContext => registerModule(SigmaDslModule) @@ -2321,9 +2325,9 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { registerEntityObject("SigmaDslBuilder", SigmaDslBuilder) } -object SigmaDslModule extends scalan.ModuleInfo("sigma", "SigmaDsl") { +object SigmaDslModule extends ModuleInfo("sigma", "SigmaDsl") { val reflection = GraphIRReflection } } -trait SigmaDslModule extends sigma.impl.SigmaDslDefs {self: SigmaLibrary =>} +trait SigmaDslModule extends SigmaDslDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WRTypesImpl.scala similarity index 84% rename from sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WRTypesImpl.scala index 9b2676f70d..beddba3085 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WRTypesImpl.scala @@ -1,18 +1,22 @@ -package wrappers.scalan +package sigma.compiler.ir.wrappers.sigma -import scala.language.{existentials,implicitConversions} +import sigma.compiler.ir.IRContext +import scala.language.{existentials, implicitConversions} import sigma.data.RType -import special.wrappers.WrappersModule -import special.wrappers.RTypeWrapSpec +import sigma.compiler.ir.wrappers.RTypeWrapSpec + import scala.collection.compat.immutable.ArraySeq package impl { - import scalan.GraphIRReflection + import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.wrappers.sigma.WRTypes + import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.reflection.{RClass, RMethod} +/** Implementation of IR nodes related to [[RType]]. */ // Abs ----------------------------------- -trait WRTypesDefs extends scalan.Scalan with WRTypes { - self: WrappersModule => +trait WRTypesDefs extends Base with WRTypes { + self: IRContext => registerModule(WRTypesModule) @@ -111,9 +115,9 @@ registerEntityObject("WRType", WRType) } -object WRTypesModule extends scalan.ModuleInfo("wrappers.scalan", "WRTypes") { +object WRTypesModule extends ModuleInfo("wrappers.scalan", "WRTypes") { val reflection = GraphIRReflection } } -trait WRTypesModule extends wrappers.scalan.impl.WRTypesDefs {self: WrappersModule =>} +trait WRTypesModule extends sigma.compiler.ir.wrappers.sigma.impl.WRTypesDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala similarity index 99% rename from sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala rename to sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala index 82aaea7e30..af5be938be 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala @@ -1,4 +1,4 @@ -package sigmastate.lang +package sigma.compiler.phases import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix import sigma.ast.NoType diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala similarity index 97% rename from sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala rename to sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 7fd6dadd45..679d98a18f 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -1,24 +1,26 @@ -package sigmastate.lang +package sigma.compiler.phases -import org.ergoplatform._ import sigma.ast.SCollection.{SBooleanArray, SByteArray} +import sigma.ast.SigmaPredef._ import sigma.ast._ -import sigma.ast.syntax.SValue +import sigma.ast.syntax.{SValue, _} import sigma.data.{Nullable, SigmaBoolean} -import sigma.util.Extensions.Ensuring -import sigmastate.exceptions._ -import SigmaPredef._ -import sigma.ast.syntax._ import sigma.exceptions.TyperException import sigma.serialization.OpCodes +import sigma.util.Extensions.Ensuring +import sigmastate.exceptions._ import scala.collection.mutable.ArrayBuffer -/** - * Type inference and analysis for Sigma expressions. +/** Type inference and analysis for Sigma expressions. + * @param builder SigmaBuilder instance to create new nodes + * @param predefFuncRegistry predefined functions registry used to resolve names + * @param typeEnv environment with types of variables/names + * @param lowerMethodCalls if true, then MethodCall nodes are lowered to the corresponding ErgoTree nodes */ class SigmaTyper(val builder: SigmaBuilder, predefFuncRegistry: PredefinedFuncRegistry, + typeEnv: Map[String, SType], lowerMethodCalls: Boolean) { import SigmaTyper._ import builder._ @@ -28,8 +30,10 @@ class SigmaTyper(val builder: SigmaBuilder, import SType.tT - private val predefinedEnv: Map[String, SType] = - predefFuncRegistry.funcs.map { case (k, f) => k -> f.declaration.tpe }.toMap + private val predefinedEnv: Map[String, SType] = { + val predefFuncs = predefFuncRegistry.funcs.map { case (k, f) => k -> f.declaration.tpe }.toMap + predefFuncs ++ typeEnv + } private def processGlobalMethod(srcCtx: Nullable[SourceContext], method: SMethod, diff --git a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala b/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala deleted file mode 100644 index 597711d458..0000000000 --- a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala +++ /dev/null @@ -1,25 +0,0 @@ -package sigmastate.eval - -import sigma.ast.TransformingSigmaBuilder - -/** Main interface of graph IR context which contain both GraphBuilding and TreeBuilding - * methods. - * It is not used in v5.0 interpreter and thus not part of consensus. - * - * Used in ErgoScript compiler only. - * - * @see CompiletimeIRContext - */ -trait IRContext extends TreeBuilding with GraphBuilding { - override val builder = TransformingSigmaBuilder - - /** Pass configuration which is used to turn-off constant propagation. - * USED IN TESTS ONLY. - * @see `beginPass(noCostPropagationPass)` */ - lazy val noConstPropagationPass = new DefaultPass( - "noCostPropagationPass", - Pass.defaultPassConfig.copy(constantPropagation = false)) -} - -/** IR context to be used by script development tools to compile ErgoScript into ErgoTree bytecode. */ -class CompiletimeIRContext extends IRContext diff --git a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala b/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala deleted file mode 100644 index 7745873620..0000000000 --- a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala +++ /dev/null @@ -1,17 +0,0 @@ -package sigmastate.eval - -import scalan.Library -import sigma.SigmaDslModule - -/** Main trait which represents sigma operations in graph IR cake. */ -trait SigmaLibrary extends Library - with sigma.wrappers.WrappersModule - with SigmaDslModule -{ - import WRType._ - - implicit lazy val wRTypeAnyElement: Elem[WRType[Any]] = wRTypeElement(AnyElement) - - /** During compilation represent a global value Global, see also SGlobal type. */ - def sigmaDslBuilder: Ref[SigmaDslBuilder] -} diff --git a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala deleted file mode 100644 index 6696788621..0000000000 --- a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala +++ /dev/null @@ -1,4 +0,0 @@ -package sigma.wrappers - -trait WrappersModule - extends special.wrappers.WrappersModule diff --git a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala deleted file mode 100644 index b74bec314e..0000000000 --- a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala +++ /dev/null @@ -1,10 +0,0 @@ -package special.wrappers - -import wrappers.scala.WOptionsModule -import wrappers.scalan.WRTypesModule -import wrappers.special.WSpecialPredefsModule - -trait WrappersModule - extends WSpecialPredefsModule - with WOptionsModule - with WRTypesModule \ No newline at end of file diff --git a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala b/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala deleted file mode 100644 index 8c6bc48f8e..0000000000 --- a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala +++ /dev/null @@ -1,13 +0,0 @@ -package wrappers.scalan { - import scalan._ - import special.wrappers.WrappersModule - - - trait WRTypes extends Base { self: WrappersModule => - trait WRType[A] extends Def[WRType[A]] { - implicit def eA: Elem[A]; - def name: Ref[String] - }; - trait WRTypeCompanion - } -} \ No newline at end of file diff --git a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala b/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala deleted file mode 100644 index 5abbab95e2..0000000000 --- a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala +++ /dev/null @@ -1,12 +0,0 @@ -package wrappers.special { - import scalan._ - - import special.wrappers.WrappersModule - - trait WSpecialPredefs extends Base { self: WrappersModule => - trait WSpecialPredef extends Def[WSpecialPredef]; - trait WSpecialPredefCompanion { - def some[A](x: Ref[A]): Ref[WOption[A]]; - } - } -} \ No newline at end of file diff --git a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala b/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala deleted file mode 100644 index 1f80e71676..0000000000 --- a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala +++ /dev/null @@ -1,69 +0,0 @@ -package wrappers.special - -import scala.language.{existentials,implicitConversions} -import scalan._ -import special.wrappers.WrappersModule - -package impl { - import sigma.data.Nullable - import sigma.reflection.RClass - - // Abs ----------------------------------- -trait WSpecialPredefsDefs extends scalan.Scalan with WSpecialPredefs { - self: WrappersModule => - - registerModule(WSpecialPredefsModule) - -import WOption._ -import WSpecialPredef._ - -object WSpecialPredef extends EntityObject("WSpecialPredef") { - - implicit case object WSpecialPredefCompanionElem extends CompanionElem[WSpecialPredefCompanionCtor] - - abstract class WSpecialPredefCompanionCtor extends CompanionDef[WSpecialPredefCompanionCtor] with WSpecialPredefCompanion { - def resultType = WSpecialPredefCompanionElem - override def toString = "WSpecialPredef" - } - implicit final def unrefWSpecialPredefCompanionCtor(p: Ref[WSpecialPredefCompanionCtor]): WSpecialPredefCompanionCtor = - p.node.asInstanceOf[WSpecialPredefCompanionCtor] - - lazy val RWSpecialPredef: MutableLazy[WSpecialPredefCompanionCtor] = MutableLazy(new WSpecialPredefCompanionCtor { - private val thisClass = RClass(classOf[WSpecialPredefCompanion]) - - def some[A](x: Ref[A]): Ref[WOption[A]] = { - implicit val eA = x.elem - asRep[WOption[A]](mkMethodCall(self, - thisClass.getMethod("some", classOf[Sym]), - Array[AnyRef](x), - true, false, element[WOption[A]])) - } - }) - - object WSpecialPredefCompanionMethods { - object some { - def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { - case MethodCall(receiver, method, args, _) if method.getName == "some" && receiver.elem == WSpecialPredefCompanionElem => - val res = args(0) - Nullable(res).asInstanceOf[Nullable[Ref[A] forSome {type A}]] - case _ => Nullable.None - } - def unapply(exp: Sym): Nullable[Ref[A] forSome {type A}] = unapply(exp.node) - } - } -} // of object WSpecialPredef - registerEntityObject("WSpecialPredef", WSpecialPredef) - - override def resetContext(): Unit = { - super.resetContext() - RWSpecialPredef.reset() - } - -} - -object WSpecialPredefsModule extends scalan.ModuleInfo("wrappers.special", "WSpecialPredefs") { - val reflection = GraphIRReflection -} -} - -trait WSpecialPredefsModule extends wrappers.special.impl.WSpecialPredefsDefs {self: WrappersModule =>} diff --git a/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala index 26e8b08b14..0216f71f21 100644 --- a/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala +++ b/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala @@ -4,6 +4,7 @@ import sigmastate.interpreter.Interpreter.ScriptNameProp import scala.collection.mutable import sigma.interpreter.{CostedProverResult, ProverResult} + import scala.collection.mutable.ArrayBuffer import org.ergoplatform.ErgoBox.{NonMandatoryRegisterId, TokenId} import sigma.data.{AvlTreeData, CAnyValue, CSigmaProp, Nullable} @@ -14,12 +15,12 @@ import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token} import sigma.ast.{ErgoTree, SType} import sigma.ast.EvaluatedValue import sigma.interpreter.ContextExtension -import sigmastate.eval.IRContext import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter} import sigmastate.helpers.TestingHelpers._ import sigma.ast.syntax.ValueOps import sigma.{AnyValue, Evaluation, SigmaProp} import ErgoTree.ZeroHeader +import sigma.compiler.ir.IRContext case class TestContractSpec(testSuite: CompilerTestingCommons)(implicit val IR: IRContext) extends ContractSpec { diff --git a/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala b/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala index 3d437a2f1d..a9da1792ec 100644 --- a/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala +++ b/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala @@ -1,8 +1,10 @@ package scalan +import sigma.compiler.ir.IRContext + trait BaseLiftableTests { self: BaseCtxTests => - trait LiftableTestKit { scalan: Scalan => + trait LiftableTestKit { scalan: IRContext => import Liftables._ /** Check the MethodCall reified in f can be mapped to unlifted method which can be invoked.*/ diff --git a/sc/shared/src/test/scala/scalan/LibraryTests.scala b/sc/shared/src/test/scala/scalan/LibraryTests.scala index d095a2f20a..b21bd2daf1 100644 --- a/sc/shared/src/test/scala/scalan/LibraryTests.scala +++ b/sc/shared/src/test/scala/scalan/LibraryTests.scala @@ -1,8 +1,9 @@ package scalan +import sigma.compiler.ir.IRContext import sigma.util.BenchmarkUtil.{measure, measureTime} -class Benchmark[T <: Scalan](createContext: => T) { +class Benchmark[T <: IRContext](createContext: => T) { val printDebugInfo: Boolean = false def run() = { diff --git a/sc/shared/src/test/scala/scalan/TestContexts.scala b/sc/shared/src/test/scala/scalan/TestContexts.scala index a86bf42276..82a6d6b21c 100644 --- a/sc/shared/src/test/scala/scalan/TestContexts.scala +++ b/sc/shared/src/test/scala/scalan/TestContexts.scala @@ -1,11 +1,12 @@ package scalan +import sigma.compiler.ir.{GraphIRReflection, IRContext} import sigma.reflection.RMethod import sigma.{BaseNestedTests, BaseShouldTests, BaseTests, TestUtils} trait TestContexts extends TestUtils { - trait TestContextApi { scalan: Scalan => + trait TestContextApi { ctx: IRContext => def invokeAll: Boolean def isInvokeEnabled(d: Def[_], m: RMethod): Boolean def shouldUnpack(e: Elem[_]): Boolean @@ -19,7 +20,7 @@ trait TestContexts extends TestUtils { emitF(testName, Seq(() => s1) ++ s2.map((s: Ref[_]) => () => s): _*) } } - abstract class TestContext(val testName: String) extends Scalan with TestContextApi { + abstract class TestContext(val testName: String) extends IRContext with TestContextApi { def this() = this(currentTestNameAsFileName) override val invokeAll = true diff --git a/sc/shared/src/test/scala/scalan/TestLibrary.scala b/sc/shared/src/test/scala/scalan/TestLibrary.scala index efbce25e68..cb3608d4c3 100644 --- a/sc/shared/src/test/scala/scalan/TestLibrary.scala +++ b/sc/shared/src/test/scala/scalan/TestLibrary.scala @@ -1,7 +1,9 @@ package scalan -trait TestLibrary extends Library { +import sigma.compiler.ir.{GraphIRReflection, IRContext} + +trait TestLibrary extends IRContext { import CollBuilder._ + import SigmaDslBuilder._ val reflection = (GraphIRReflection) - lazy val colBuilder: Ref[CollBuilder] = variable[CollBuilder] } diff --git a/sc/shared/src/test/scala/sigma/CollsStagingTests.scala b/sc/shared/src/test/scala/sigma/CollsStagingTests.scala index 3b56920c8d..b26c7d4119 100644 --- a/sc/shared/src/test/scala/sigma/CollsStagingTests.scala +++ b/sc/shared/src/test/scala/sigma/CollsStagingTests.scala @@ -3,6 +3,7 @@ package sigma import scala.language.reflectiveCalls import special.wrappers.WrappersTests import scalan._ +import sigma.compiler.ir.IRContext import sigma.data.CollOverArrayBuilder class CollsStagingTests extends WrappersTests { @@ -41,7 +42,7 @@ class CollsStagingTests extends WrappersTests { } test("invokeUnlifted for Col") { - val ctx = new WrappersCtx with Library + val ctx = new WrappersCtx with IRContext import ctx._ import Coll._ import CollBuilder._ @@ -59,7 +60,7 @@ class CollsStagingTests extends WrappersTests { } test("invokeUnlifted for method of Ctor") { - val ctx = new WrappersCtx with Library + val ctx = new WrappersCtx with IRContext import ctx._ import Coll._ import CollBuilder._ diff --git a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala index 91178b2b67..bcd4b21129 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala @@ -2,6 +2,7 @@ package sigma import org.scalatest.BeforeAndAfterAll import scalan.{BaseCtxTests, BaseLiftableTests} +import sigma.compiler.ir.IRContext import sigma.data.TrivialProp import sigma.eval.Extensions.toAnyValue import sigmastate.eval._ diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 46222d9fb1..31e873699b 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -25,12 +25,13 @@ import sigma.ast._ import sigma.eval.{CostDetails, EvalSettings, SigmaDsl} import sigmastate.crypto.DLogProtocol.DLogProverInput import sigmastate.crypto.SigmaProtocolPrivateInput -import sigmastate.eval.{CContext, CompiletimeIRContext, IRContext} +import sigmastate.eval.CContext import sigmastate.helpers.TestingHelpers._ import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, SigmaPPrint} import sigmastate.interpreter.Interpreter.{ScriptEnv, VerificationResult} import sigmastate.interpreter._ import sigma.ast.Apply +import sigma.compiler.ir.{CompiletimeIRContext, IRContext} import sigma.eval.Extensions.SigmaBooleanOps import sigma.interpreter.{ContextExtension, ProverResult} import sigma.serialization.ValueSerializer diff --git a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala index 28f907c199..f1d5c6aa89 100644 --- a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala +++ b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala @@ -1,16 +1,17 @@ package sigmastate import scala.util.DynamicVariable -import sigmastate.lang.{CompilerResult, CompilerSettings, SigmaCompiler} import sigmastate.interpreter.Interpreter.ScriptEnv import sigma.ast.{ErgoTree, SType, TransformingSigmaBuilder, Value} import org.ergoplatform.ErgoAddressEncoder.TestnetNetworkPrefix import sigma.ast.syntax.{SValue, SigmaPropValue} import sigma.serialization.ValueSerializer -import sigmastate.eval.IRContext +import sigma.compiler.ir.IRContext import sigma.ast.syntax.ValueOps +import sigma.compiler.{CompilerResult, CompilerSettings, SigmaCompiler} +import sigmastate.helpers.{NegativeTesting, SigmaPPrint} -trait CompilerTestsBase extends TestsBase { +trait CompilerTestsBase extends TestsBase with NegativeTesting { protected val _lowerMethodCalls = new DynamicVariable[Boolean](true) /** Returns true if MethodCall nodes should be lowered by TypeChecker to the @@ -63,4 +64,12 @@ trait CompilerTestsBase extends TestsBase { val tree = mkTestErgoTree(prop) (tree, prop) } + + /** Checks expectation pretty printing the actual value if there is a difference. */ + def checkEquals[T](actual: T, expected: T): Unit = { + if (expected != actual) { + SigmaPPrint.pprintln(actual, width = 100) + } + actual shouldBe expected + } } diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index b0b6273fad..7539bd5e48 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -17,9 +17,9 @@ import sigmastate.helpers.{ErgoLikeContextTesting, SigmaPPrint} import sigmastate.interpreter.Interpreter.ReductionResult import sigmastate.interpreter.CErgoTreeEvaluator import sigma.ast.syntax._ +import sigma.compiler.CompilerSettings import sigma.eval.EvalSettings import sigma.exceptions.{CostLimitException, InterpreterException} -import sigmastate.lang.CompilerSettings import sigma.serialization.ErgoTreeSerializer.DefaultSerializer import sigmastate.Plus import sigmastate.utils.Helpers.TryOps diff --git a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala index aedf35e914..4c0861c959 100644 --- a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala @@ -14,6 +14,7 @@ import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings import sigma.eval.EvalSettings.EvaluationMode import sigmastate.interpreter._ import sigma.ast.syntax.ValueOps +import sigma.compiler.ir.IRContext import sigma.data.CBox import sigma.eval.EvalSettings import sigma.exceptions.InterpreterException diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala index a10a717d2f..da9ed70efd 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala @@ -14,8 +14,10 @@ import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeConte import sigmastate.interpreter.Interpreter.ScriptEnv import sigmastate.interpreter.CErgoTreeEvaluator import sigma.ast.syntax.ValueOps +import sigma.compiler.{CompilerResult, CompilerSettings, SigmaCompiler} +import sigma.compiler.ir.IRContext import sigma.interpreter.ContextExtension -import sigmastate.lang.{CompilerResult, CompilerSettings, LangTests, SigmaCompiler} +import sigmastate.lang.LangTests import sigma.serialization.ErgoTreeSerializer.DefaultSerializer import sigmastate.CompilerTestsBase import sigma.{ContractsTestkit, Context => DContext} diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala index 526012f212..11ef6f4fac 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala @@ -8,6 +8,7 @@ import scalan.BaseCtxTests import sigma.ast.syntax.ValueOps import sigmastate.lang.LangTests import sigma.ast.Apply +import sigma.compiler.ir.IRContext class ErgoTreeBuildingTest extends BaseCtxTests with LangTests with ExampleContracts with ErgoScriptTestkit { diff --git a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala index 6c3708b782..3b1d6ba3dc 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala @@ -12,16 +12,17 @@ import sigma.data.{RType, SigmaBoolean} import sigma.validation.ValidationException import sigma.validation.ValidationRules.CheckSerializableTypeCode import sigma.ast.syntax.{SValue, SigmaPropValue} +import sigma.compiler.{CompilerSettings, SigmaCompiler} +import sigma.compiler.ir.IRContext import sigma.eval.{CostDetails, EvalSettings, Extensions, GivenCost, TracedCost} import sigmastate.helpers.TestingHelpers._ import sigma.interpreter.ContextExtension.VarBinding import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler import sigmastate.interpreter.Interpreter.ScriptEnv import sigmastate.interpreter._ -import sigmastate.lang.{CompilerSettings, SigmaCompiler} import sigma.serialization.SigmaSerializer import sigmastate.CompilerTestsBase -import sigmastate.eval.{CContext, IRContext} +import sigmastate.eval.CContext import scala.util.DynamicVariable diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index 1f758370a0..b4b4ad20cd 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -11,6 +11,7 @@ import sigmastate._ import sigmastate.interpreter.Interpreter.ScriptEnv import SigmaPredef.PredefinedFuncRegistry import sigma.ast.syntax._ +import sigma.compiler.phases.SigmaBinder import sigma.eval.SigmaDsl import sigma.exceptions.BinderException diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala index df8f644172..a03d160654 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala @@ -2,13 +2,19 @@ package sigmastate.lang import org.ergoplatform.ErgoAddressEncoder import org.ergoplatform.sdk.Parameter -import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import sigma.ast.{IntConstant, SInt, SLong, SString, StringConstant} -import sigmastate.eval.CompiletimeIRContext +import sigma.VersionContext +import sigma.ast.ErgoTree.HeaderType +import sigma.ast.{BinAnd, BoolToSigmaProp, ConstantPlaceholder, ErgoTree, FalseLeaf, GT, Height, IntConstant, LT, SBoolean, SInt, SLong, SString, TrueLeaf} +import sigma.compiler.SigmaTemplateCompiler +import sigma.exceptions.TyperException +import sigmastate.CompilerTestsBase +import sigmastate.interpreter.Interpreter.ScriptEnv + +class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyChecks with CompilerTestsBase { + val templateCompiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) -class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers { property("compiles full contract template") { val source = """/** This is my contracts description. @@ -24,8 +30,7 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck |@contract def contractName(p1: Int = 5, p2: String = "default string", param3: Long) = { | sigmaProp(true) |}""".stripMargin - val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - val template = compiler.compile(Map.empty, source) + val template = templateCompiler.compile(source) template.name shouldBe "contractName" template.description shouldBe "This is my contracts description. Here is another line describing what it does in more detail." @@ -36,16 +41,12 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck ) template.constTypes should contain theSameElementsInOrderAs Seq(SInt, SString, SLong) template.constValues.get should contain theSameElementsInOrderAs IndexedSeq( - Some(IntConstant(5).asWrappedType), - Some(StringConstant("default string").asWrappedType), + Some(5), + Some("default string"), None ) - val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - implicit val ir = new CompiletimeIRContext - val result = sigmaCompiler.compile(Map.empty, "{ sigmaProp(true) }") - - template.expressionTree shouldBe result.buildTree + checkEquals(template.expressionTree, BoolToSigmaProp(TrueLeaf)) } property("compiles contract template without braces") { @@ -62,8 +63,7 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck |*/ |@contract def contractName(p1: Int = 5, p2: String = "default string") = sigmaProp(true) |""".stripMargin - val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - val template = compiler.compile(Map.empty, source) + val template = templateCompiler.compile(source) template.name shouldBe "contractName" template.description shouldBe "This is my contracts description. Here is another line describing what it does in more detail." @@ -73,16 +73,137 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck ) template.constTypes should contain theSameElementsInOrderAs Seq(SInt, SString) template.constValues.get should contain theSameElementsInOrderAs IndexedSeq( - Some(IntConstant(5).asWrappedType), - Some(StringConstant("default string").asWrappedType) + Some(5), + Some("default string") + ) + + checkEquals(template.expressionTree, BoolToSigmaProp(TrueLeaf)) + } + + property("uses default value from parameter definition") { + val source = + """/**/ + |@contract def contractName(p: Boolean = true) = sigmaProp(p && HEIGHT > 1000) + |""".stripMargin + val template = templateCompiler.compile(source) + + template.parameters should contain theSameElementsInOrderAs IndexedSeq( + Parameter("p", "", 0) + ) + template.constTypes should contain theSameElementsInOrderAs Seq(SBoolean) + template.constValues.get should contain theSameElementsInOrderAs IndexedSeq( + Some(true) + ) + + val expectedExpr = BoolToSigmaProp(BinAnd(ConstantPlaceholder(0, SBoolean), GT(Height, IntConstant(1000)))) + checkEquals(template.expressionTree, expectedExpr) + + val expectedTree = new ErgoTree( + HeaderType @@ 26.toByte, // use ErgoTreeUtils to get explanation + Vector(TrueLeaf), + Right(BoolToSigmaProp(BinAnd(ConstantPlaceholder(0, SBoolean), GT(Height, IntConstant(1000)))))) + + expectedTree.version shouldBe VersionContext.JitActivationVersion + expectedTree.hasSize shouldBe true + expectedTree.isConstantSegregation shouldBe true + + // apply using default values declared in the parameters + checkEquals( + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map.empty + ), + expectedTree + ) + + // apply overriding the default values + checkEquals( + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map("p" -> FalseLeaf) + ), + expectedTree.copy(constants = Vector(FalseLeaf)) + ) + } + + property("uses given environment when provided (overriding default value)") { + val source = + """/**/ + |@contract def contractName(low: Int = 0, high: Int) = sigmaProp(low < HEIGHT && HEIGHT < high) + |""".stripMargin + val template = templateCompiler.compile(source) + + template.parameters should contain theSameElementsInOrderAs IndexedSeq( + Parameter("low", "", 0), + Parameter("high", "", 1) + ) + template.constTypes should contain theSameElementsInOrderAs Seq(SInt, SInt) + // check parsed default values + template.constValues.get should contain theSameElementsInOrderAs IndexedSeq( + Some(0), + None + ) + checkEquals( + template.expressionTree, + BoolToSigmaProp( + BinAnd( + LT(ConstantPlaceholder(0, SInt), Height), + LT(Height, ConstantPlaceholder(1, SInt)) + ) + ) ) - val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - implicit val ir = new CompiletimeIRContext - val result = sigmaCompiler.compile(Map.empty, "sigmaProp(true)") + // incomplete application (missing `high` parameter) + assertExceptionThrown( + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map.empty + ), + exceptionLike[IllegalArgumentException]( + "requirement failed: value for parameter `high` was not provided while it does not have a default value.") + ) + + val expectedTree = new ErgoTree( + HeaderType @@ 26.toByte, + Vector(IntConstant(0), IntConstant(100)), + Right( + BoolToSigmaProp( + BinAnd(LT(ConstantPlaceholder(0, SInt), Height), LT(Height, ConstantPlaceholder(1, SInt))) + ) + ) + ) + + // apply providing the parameter without default value + checkEquals( + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map("high" -> IntConstant(100)) + ), + expectedTree + ) - template.expressionTree shouldBe result.buildTree + // apply providing all parameters overriding the default values + checkEquals( + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map("low" -> IntConstant(10), "high" -> IntConstant(100)) + ), + expectedTree.copy(constants = Vector(IntConstant(10), IntConstant(100))) + ) } + + property("fails when the parameter is not provided") { + // NOTE: parameter `condition` is not provided */ + val source = + """/**/ + |@contract def contractName(low: Int = 0, high: Int) = sigmaProp(low < HEIGHT && HEIGHT < high) && condition + |""".stripMargin + assertExceptionThrown( + templateCompiler.compile(source), + exceptionLike[TyperException]("Cannot assign type for variable 'condition' because it is not found in env") + ) + } + } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index a474727943..6b93b098ea 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -19,6 +19,7 @@ import sigmastate.lang.parsers.ParserException import sigma.serialization.ErgoTreeSerializer import sigma.serialization.generators.ObjectGenerators import sigma.ast.Select +import sigma.compiler.phases.{SigmaBinder, SigmaTyper} import sigma.exceptions.TyperException class SigmaTyperTest extends AnyPropSpec @@ -34,7 +35,8 @@ class SigmaTyperTest extends AnyPropSpec val predefinedFuncRegistry = new PredefinedFuncRegistry(builder) val binder = new SigmaBinder(env, builder, TestnetNetworkPrefix, predefinedFuncRegistry) val bound = binder.bind(parsed) - val typer = new SigmaTyper(builder, predefinedFuncRegistry, lowerMethodCalls = true) + val typeEnv = env.collect { case (k, v: SType) => k -> v } + val typer = new SigmaTyper(builder, predefinedFuncRegistry, typeEnv, lowerMethodCalls = true) val typed = typer.typecheck(bound) assertSrcCtxForAllNodes(typed) if (expected != null) typed shouldBe expected @@ -51,7 +53,8 @@ class SigmaTyperTest extends AnyPropSpec val predefinedFuncRegistry = new PredefinedFuncRegistry(builder) val binder = new SigmaBinder(env, builder, TestnetNetworkPrefix, predefinedFuncRegistry) val bound = binder.bind(parsed) - val typer = new SigmaTyper(builder, predefinedFuncRegistry, lowerMethodCalls = true) + val typeEnv = env.collect { case (k, v: SType) => k -> v } + val typer = new SigmaTyper(builder, predefinedFuncRegistry, typeEnv, lowerMethodCalls = true) typer.typecheck(bound) }, { case te: TyperException => diff --git a/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala b/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala index e20d8a6d1e..f7129a7723 100644 --- a/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala @@ -10,9 +10,9 @@ import sigma.util.Extensions.SigmaPropOps import sigma.validation.ValidationException import ErgoTree.EmptyConstants import ErgoTree.HeaderType +import sigma.compiler.ir.IRContext import sigma.eval.Extensions.SigmaBooleanOps import sigmastate._ -import sigmastate.eval.IRContext import sigmastate.helpers.CompilerTestingCommons import sigma.serialization.ErgoTreeSerializer.DefaultSerializer diff --git a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala index 566bf5bd58..6b0c0080c9 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala @@ -9,7 +9,6 @@ import scorex.crypto.hash.{Blake2b256, Digest32} import sigma.ast.SCollection.SByteArray import sigma.ast._ import sigmastate._ -import sigmastate.eval.IRContext import sigmastate.eval._ import sigma.Extensions.ArrayOps import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter} @@ -19,6 +18,7 @@ import sigma.ast.syntax._ import sigma.Coll import sigma.ast.SAvlTree import sigma.ast.syntax.{GetVarByteArray, OptionValueOps} +import sigma.compiler.ir.IRContext import sigma.data.{AvlTreeData, AvlTreeFlags, CSigmaProp, TrivialProp} import sigma.eval.SigmaDsl import sigma.interpreter.ProverResult @@ -30,7 +30,7 @@ class AVLTreeScriptsSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { suite => import org.ergoplatform.dsl.AvlTreeHelpers._ lazy val spec = TestContractSpec(suite)(new TestingIRContext) - lazy val prover = spec.ProvingParty("Alice") + lazy val prover = spec.ProvingParty("Alice") private implicit lazy val IR: IRContext = spec.IR private val reg1 = ErgoBox.nonMandatoryRegisters(0) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala index e3d43ab868..77e78aa6bf 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala @@ -1,19 +1,19 @@ package sigmastate.utxo import sigmastate.CompilerCrossVersionProps -import sigmastate.eval.IRContext import sigma.Extensions.ArrayOps import sigma.Context import sigmastate.helpers.CompilerTestingCommons import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, TestContractSpec} import org.ergoplatform.ErgoBox import scorex.crypto.hash.Blake2b256 +import sigma.compiler.ir.IRContext import sigma.data.{CSigmaProp, TrivialProp} class UsingContextPropertiesSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { suite => lazy val spec = TestContractSpec(suite)(new TestingIRContext) - lazy val prover = spec.ProvingParty("Alice") + lazy val prover = spec.ProvingParty("Alice") private implicit lazy val IR: IRContext = spec.IR private val reg1 = ErgoBox.nonMandatoryRegisters(0) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala index 0dca8a4471..16b4e3e232 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala @@ -17,6 +17,7 @@ import scorex.util._ import sigma.Colls import sigma.data.{AvlTreeData, AvlTreeFlags} import ErgoTree.ZeroHeader +import sigma.compiler.ir.IRContext import sigma.eval.Extensions.SigmaBooleanOps import sigma.interpreter.ContextExtension import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv} diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala index c930135bc2..556c56bc03 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala @@ -22,6 +22,7 @@ import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingIn import sigmastate.interpreter.Interpreter.ScriptNameProp import sigmastate.interpreter.Interpreter import sigma.ast.syntax._ +import sigma.compiler.ir.IRContext import sigma.eval.SigmaDsl import sigma.serialization.ErgoTreeSerializer import sigma.serialization.ErgoTreeSerializer.DefaultSerializer diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala index ce4ed2114e..556fbf9c06 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala @@ -10,12 +10,12 @@ import sigma.data.{AvlTreeData, AvlTreeFlags, Digest32Coll, TrivialProp} import sigmastate.CompilerCrossVersionProps import sigma.ast.{AvlTreeConstant, ByteArrayConstant, LongConstant, SigmaPropConstant} import sigma.Extensions.ArrayOps -import sigmastate.eval.IRContext import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestProvingInterpreter} import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.Interpreter.ScriptNameProp import sigma.serialization.ErgoTreeSerializer import sigma.ast.syntax._ +import sigma.compiler.ir.IRContext import sigma.eval.SigmaDsl import scala.util.Random diff --git a/sc/shared/src/test/scala/special/wrappers/WOptionTests.scala b/sc/shared/src/test/scala/special/wrappers/WOptionTests.scala index 7e046739f0..e952ba7c00 100644 --- a/sc/shared/src/test/scala/special/wrappers/WOptionTests.scala +++ b/sc/shared/src/test/scala/special/wrappers/WOptionTests.scala @@ -1,7 +1,6 @@ package special.wrappers import scala.language.reflectiveCalls -import scalan.Library class WOptionTests extends WrappersTests { diff --git a/sc/shared/src/test/scala/special/wrappers/WSpecialPredefTests.scala b/sc/shared/src/test/scala/special/wrappers/WSpecialPredefTests.scala deleted file mode 100644 index e1097ebf6c..0000000000 --- a/sc/shared/src/test/scala/special/wrappers/WSpecialPredefTests.scala +++ /dev/null @@ -1,24 +0,0 @@ -package special.wrappers - - -import scala.language.reflectiveCalls -import sigma.data.RType - -class WSpecialPredefTests extends WrappersTests { - - lazy val ctx = new WrappersCtx - import ctx._ - import WSpecialPredef._ - - lazy val SPCM = WSpecialPredefCompanionMethods - - test("some") { - val x: Ref[Int] = 10 - val opt = RWSpecialPredef.some(x) - opt match { - case SPCM.some(_x) => _x shouldBe x - case _ => assert(false) - } - } - -} diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala index 5e491630bd..8da420bee6 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala @@ -153,7 +153,7 @@ case class ContractTemplate( .map(p => p.name) requiredParameterNames.foreach(name => require( paramValues.contains(name), - s"value for parameter $name was not provided while it does not have a default value.")) + s"value for parameter `$name` was not provided while it does not have a default value.")) val parameterizedConstantIndices = this.parameters.map(p => p.constantIndex).toSet val constIndexToParamIndex = this.parameters.zipWithIndex.map(pi => pi._1.constantIndex -> pi._2).toMap diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/ErgoTreeUtils.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/ErgoTreeUtils.scala new file mode 100644 index 0000000000..ffa6505377 --- /dev/null +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/ErgoTreeUtils.scala @@ -0,0 +1,26 @@ +package org.ergoplatform.sdk.utils + +import sigma.ast.ErgoTree +import sigma.ast.ErgoTree.HeaderType +import sigma.util.Extensions.BooleanOps + +/** SDK level utilities and helper methods to work with ErgoTrees. */ +object ErgoTreeUtils { + /** Prints description of the bits in the given ErgoTree header. */ + def explainTreeHeader(header: HeaderType): String = { + // convert byte to hex + val byteToHex = (b: Byte) => f"Ox${b & 0xff}%02x" + val hasSize = ErgoTree.hasSize(header) + s""" + |Header: ${byteToHex(header)} (${header.toString}) + |Bit 0: ${header.toByte & 0x01} \\ + |Bit 1: ${(header.toByte & 0x02) >> 1}\t-- ErgoTree version ${ErgoTree.getVersion(header)} + |Bit 2: ${(header.toByte & 0x04) >> 2} / + |Bit 3: ${hasSize.toByte} \t-- size of the whole tree is serialized after the header byte + |Bit 4: ${ErgoTree.isConstantSegregation(header).toByte} \t-- constant segregation is used for this ErgoTree + |Bit 5: ${header.toByte & 0x20} \t-- reserved (should be 0) + |Bit 6: ${header.toByte & 0x40} \t-- reserved (should be 0) + |Bit 7: ${header.toByte & 0x80} \t-- header contains more than 1 byte (default == 0) + |""".stripMargin + } +} diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala new file mode 100644 index 0000000000..8dd20ecf81 --- /dev/null +++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala @@ -0,0 +1,23 @@ +package org.ergoplatform.sdk.utils + +import org.scalatest.matchers.should.Matchers +import org.scalatest.propspec.AnyPropSpec +import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks +import sigma.ast.ErgoTree.HeaderType + +class ErgoTreeUtilsSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers { + property("explainTreeHeader") { + ErgoTreeUtils.explainTreeHeader(HeaderType @@ 26.toByte) shouldBe + """| + |Header: Ox1a (26) + |Bit 0: 0 \ + |Bit 1: 1 -- ErgoTree version 2 + |Bit 2: 0 / + |Bit 3: 1 -- size of the whole tree is serialized after the header byte + |Bit 4: 1 -- constant segregation is used for this ErgoTree + |Bit 5: 0 -- reserved (should be 0) + |Bit 6: 0 -- reserved (should be 0) + |Bit 7: 0 -- header contains more than 1 byte (default == 0) + |""".stripMargin + } +}