From 2619abca9a08110e8bd290dd0d0db84a129d7319 Mon Sep 17 00:00:00 2001 From: Ivan Mashonskii Date: Fri, 24 Mar 2023 17:20:43 +0300 Subject: [PATCH] NODE-2569 Fix compaction for scripts with global variables and functions (#3826) --- .../v1/compiler/ContractScriptCompactor.scala | 73 +- .../lang/v1/compiler/Decompiler.scala | 259 ++--- .../lang/v1/compiler/ExpressionCompiler.scala | 293 +++--- .../lang/v1/compiler/TypeCast.scala | 3 +- .../v1/evaluator/ctx/impl/CryptoContext.scala | 14 +- .../evaluator/ctx/impl/GlobalValNames.scala | 17 + .../v1/evaluator/ctx/impl/PureContext.scala | 19 +- .../evaluator/ctx/impl/waves/Functions.scala | 14 +- .../v1/evaluator/ctx/impl/waves/Vals.scala | 15 +- .../wavesplatform/lang/v1/parser/Parser.scala | 3 +- .../wavesplatform/lang/IntegrationTest.scala | 2 +- .../ContractCompilerCompactorTest.scala | 951 ++++++++++-------- .../lang/compiler/ContractCompilerTest.scala | 8 +- .../lang/compiler/DecompilerTest.scala | 6 +- .../lang/compiler/ErrorTest.scala | 21 +- .../compiler/ExpressionCompilerV1Test.scala | 13 +- .../ExpressionCompilerWithParserV2Test.scala | 2 +- .../estimator/ScriptEstimatorV3Test.scala | 39 +- .../lang/evaluator/EvaluatorV1V2Test.scala | 4 +- .../evaluator/string/MakeStringTest.scala | 4 +- .../lang/parser/UnderscoreTest.scala | 4 +- .../state/diffs/ci/BigIntInvokeTest.scala | 41 +- .../state/diffs/ci/CallableV4DiffTest.scala | 3 +- .../diffs/ci/DAppDataEntryTypeTest.scala | 7 +- .../state/diffs/ci/DAppListArgTypesTest.scala | 3 +- .../ci/InvokeScriptTransactionDiffTest.scala | 23 +- .../state/diffs/ci/ListParamInvokeTest.scala | 10 +- .../state/diffs/ci/ScriptTransferTest.scala | 5 +- .../ci/sync/SyncDAppListArgTypesTest.scala | 7 +- .../diffs/ci/sync/SyncDAppPaymentTest.scala | 3 +- .../diffs/ci/sync/SyncDAppTransferTest.scala | 9 +- .../diffs/smart/eth/EthereumInvokeTest.scala | 6 +- .../smart/eth/EthereumTransferSmartTest.scala | 3 +- .../predef/TransactionBindingsTest.scala | 8 +- .../UserFunctionComplexityTest.scala | 10 +- .../com/wavesplatform/lang/v1/ReplTest.scala | 3 +- 36 files changed, 1053 insertions(+), 852 deletions(-) create mode 100644 lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/GlobalValNames.scala diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractScriptCompactor.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractScriptCompactor.scala index 9443dc9d1e0..2c53d731024 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractScriptCompactor.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractScriptCompactor.scala @@ -3,6 +3,7 @@ package com.wavesplatform.lang.v1.compiler import com.wavesplatform.lang.contract.DApp import com.wavesplatform.lang.v1.FunctionHeader.{Native, User} import com.wavesplatform.lang.v1.compiler.Terms.{BLOCK, DECLARATION, EXPR, FUNC, FUNCTION_CALL, GETTER, IF, LET, LET_BLOCK, REF} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import scala.annotation.tailrec @@ -13,7 +14,7 @@ object ContractScriptCompactor { type ReplaceNameF = (String, State) => CompactionResult[String] def compact(dApp: DApp): DApp = - compact(dApp, State(0, Map.empty)) + compact(dApp, State(0, Map.empty, Set.empty)) def decompact(dApp: DApp): DApp = if (dApp.meta.originalNames.nonEmpty) { @@ -69,10 +70,10 @@ object ContractScriptCompactor { case None => val compactName = idxToName(state.counter) if (hasConflict(compactName, dApp)) { - createCompName(oldName, State(state.counter + 1, state.originalNames), dApp) + createCompName(oldName, State(state.counter + 1, state.originalNames, state.knownDecs), dApp) } else { assert(!hasConflict(compactName, dApp)) - CompactionResult(compactName, State(state.counter + 1, state.originalNames.updated(oldName, compactName))) + CompactionResult(compactName, State(state.counter + 1, state.originalNames.updated(oldName, compactName), state.knownDecs)) } } @@ -83,21 +84,20 @@ object ContractScriptCompactor { state.originalNames.getOrElse(oldName, oldName) private def decompact(dApp: DApp, originalNames: Vector[String]): DApp = { - val compNameToOriginalName = originalNames.zipWithIndex.map { - case (originalName, idx) => - val compName = idxToName(idx) - val resultOriginalName = if (originalName.isEmpty) compName else originalName - compName -> resultOriginalName + val compNameToOriginalName = originalNames.zipWithIndex.map { case (originalName, idx) => + val compName = idxToName(idx) + val resultOriginalName = if (originalName.isEmpty) compName else originalName + compName -> resultOriginalName }.toMap - val compDAppRes = processDappWithoutMeta(dApp, State(0, compNameToOriginalName), restoreOriginalName) + val compDAppRes = processDappWithoutMeta(dApp, State(0, compNameToOriginalName, Set.empty), restoreOriginalName) compDAppRes.value.copy( meta = dApp.meta.withOriginalNames(Vector.empty) ) } private def decompactOld(dApp: DApp, originalNames: Map[String, String]): DApp = { - val compDAppRes = processDappWithoutMeta(dApp, State(0, originalNames), restoreOriginalName) + val compDAppRes = processDappWithoutMeta(dApp, State(0, originalNames, Set.empty), restoreOriginalName) compDAppRes.value.copy( meta = dApp.meta.withCompactNameAndOriginalNamePairList(Seq.empty) ) @@ -105,9 +105,8 @@ object ContractScriptCompactor { private def compact(dApp: DApp, state: State): DApp = { val compDAppRes = processDappWithoutMeta(dApp, state, createCompName(_, _, dApp)) - val oldNameToIdx = compDAppRes.state.originalNames.map { - case (oldName, compName) => - oldName -> nameToIdx(compName) + val oldNameToIdx = compDAppRes.state.originalNames.map { case (oldName, compName) => + oldName -> nameToIdx(compName) } val emptyElemsWithIdx = oldNameToIdx.values.maxOption .map { maxIdx => @@ -123,28 +122,34 @@ object ContractScriptCompactor { } private def hasConflict(compactName: String, dApp: DApp): Boolean = - dApp.callableFuncs.exists(_.u.name == compactName) + dApp.callableFuncs.exists(_.u.name == compactName) || GlobalValNames.All.contains(compactName) private def processLet(let: LET, state: State, replaceNameF: ReplaceNameF): CompactionResult[LET] = { val compNameRes = replaceNameF(let.name, state) val compValueRes = processExpr(let.value, compNameRes.state, replaceNameF) - CompactionResult(let.copy(name = compNameRes.value, value = compValueRes.value), compValueRes.state) + CompactionResult( + let.copy(name = compNameRes.value, value = compValueRes.value), + compValueRes.state.copy(knownDecs = compNameRes.state.knownDecs + let.name) + ) } private def processFunc(func: FUNC, state: State, replaceNameF: ReplaceNameF): CompactionResult[FUNC] = { val compNameRes = replaceNameF(func.name, state) val compArgsRes = processList(func.args, compNameRes.state, replaceNameF) - val compBodyRes = processExpr(func.body, compArgsRes.state, replaceNameF) + val compBodyRes = processExpr(func.body, compArgsRes.state.addKnownDecs(func.args), replaceNameF) - CompactionResult(func.copy(name = compNameRes.value, args = compArgsRes.value, body = compBodyRes.value), compBodyRes.state) + CompactionResult( + func.copy(name = compNameRes.value, args = compArgsRes.value, body = compBodyRes.value), + compBodyRes.state.copy(knownDecs = state.knownDecs + func.name) + ) } private def processDec(dec: DECLARATION, state: State, replaceNameF: ReplaceNameF): CompactionResult[DECLARATION] = { dec match { - case l: LET => processLet(l, state, replaceNameF) + case l: LET => processLet(l, state, replaceNameF) case f: FUNC => processFunc(f, state, replaceNameF) - case other => CompactionResult(other, state) + case other => CompactionResult(other, state) } } @@ -154,22 +159,30 @@ object ContractScriptCompactor { val compDecRes = processDec(b.dec, state, replaceNameF) val compBodyRes = processExpr(b.body, compDecRes.state, replaceNameF) - CompactionResult(b.copy(dec = compDecRes.value, body = compBodyRes.value), compBodyRes.state) + CompactionResult(b.copy(dec = compDecRes.value, body = compBodyRes.value), compBodyRes.state.copy(knownDecs = state.knownDecs)) case lb: LET_BLOCK => val compLetRes = processLet(lb.let, state, replaceNameF) val compBodyRes = processExpr(lb.body, compLetRes.state, replaceNameF) - CompactionResult(lb.copy(let = compLetRes.value, body = compBodyRes.value), compBodyRes.state) + CompactionResult(lb.copy(let = compLetRes.value, body = compBodyRes.value), compBodyRes.state.copy(knownDecs = state.knownDecs)) case fc: FUNCTION_CALL => val newFunction = fc.function match { - case User(internalName, _) => User(getReplacedName(internalName, state)) - case nF: Native => nF + case User(internalName, _) if state.knownDecs.contains(internalName) => + User(getReplacedName(internalName, state)) + case uF: User => uF + case nF: Native => nF } val compArgsRes = processList[EXPR](fc.args, state, processExpr(_, _, replaceNameF)) CompactionResult(fc.copy(function = newFunction, args = compArgsRes.value), compArgsRes.state) case r: REF => - CompactionResult(r.copy(key = getReplacedName(r.key, state)), state) + val newKey = if (state.knownDecs.contains(r.key)) { + getReplacedName(r.key, state) + } else { + r.key + } + + CompactionResult(r.copy(key = newKey), state) case g: GETTER => val compExprRes = processExpr(g.expr, state, replaceNameF) @@ -191,24 +204,24 @@ object ContractScriptCompactor { case (CompactionResult(compFuncs, state), func) => val compInvArgNameRes = replaceNameF(func.annotation.invocationArgName, state) val compArgsRes = processList(func.u.args, compInvArgNameRes.state, replaceNameF) - val compBodyRes = processExpr(func.u.body, compArgsRes.state, replaceNameF) + val compBodyRes = processExpr(func.u.body, compArgsRes.state.addKnownDecs(func.annotation.invocationArgName +: func.u.args), replaceNameF) val compFunc = func.copy( annotation = func.annotation.copy(invocationArgName = compInvArgNameRes.value), u = func.u.copy(args = compArgsRes.value, body = compBodyRes.value) ) - CompactionResult(compFuncs :+ compFunc, compBodyRes.state) + CompactionResult(compFuncs :+ compFunc, compBodyRes.state.copy(knownDecs = state.knownDecs)) } val compVerifierFuncOptRes = dApp.verifierFuncOpt .fold[CompactionResult[Option[DApp.VerifierFunction]]](CompactionResult(None, compCallableFuncsRes.state)) { vFunc => val compInvArgNameRes = replaceNameF(vFunc.annotation.invocationArgName, compCallableFuncsRes.state) - val compFuncRes = processFunc(vFunc.u, compInvArgNameRes.state, replaceNameF) + val compFuncRes = processFunc(vFunc.u, compInvArgNameRes.state.addKnownDecs(Seq(vFunc.annotation.invocationArgName)), replaceNameF) val newVFunc = vFunc.copy( annotation = vFunc.annotation.copy(invocationArgName = compInvArgNameRes.value), u = compFuncRes.value ) - CompactionResult(Some(newVFunc), compFuncRes.state) + CompactionResult(Some(newVFunc), compFuncRes.state.copy(knownDecs = compInvArgNameRes.state.knownDecs)) } CompactionResult( @@ -249,6 +262,8 @@ object ContractScriptCompactor { loop(list, compF, CompactionResult(Vector.empty[A], state)) } - case class State(counter: Int, originalNames: Map[String, String]) + case class State(counter: Int, originalNames: Map[String, String], knownDecs: Set[String]) { + def addKnownDecs(dec: Seq[String]): State = copy(knownDecs = knownDecs ++ dec) + } case class CompactionResult[+A](value: A, state: State) } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala index d5a6466d88c..c6c12a6fc8b 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala @@ -9,6 +9,7 @@ import com.wavesplatform.lang.v1.FunctionHeader import com.wavesplatform.lang.v1.FunctionHeader.{Native, User} import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.evaluator.FunctionIds +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.{ExtractedFuncPostfix, ExtractedFuncPrefix} import monix.eval.Coeval @@ -36,10 +37,10 @@ object Decompiler { private def decl(e: Coeval[DECLARATION], ctx: DecompilerContext): Coeval[String] = e flatMap { case Terms.FUNC(name, args, body) => - expr(pure(body), ctx, BracesWhenNeccessary, DontIndentFirstLine).map( - fb => - out("func " + name + " (" + args.mkString(",") + ") = ", ctx.ident) + - out(fb + NEWLINE, ctx.ident)) + expr(pure(body), ctx, BracesWhenNeccessary, DontIndentFirstLine).map(fb => + out("func " + name + " (" + args.mkString(",") + ") = ", ctx.ident) + + out(fb + NEWLINE, ctx.ident) + ) case Terms.LET(name, value) => expr(pure(value), ctx, BracesWhenNeccessary, DontIndentFirstLine).map(e => out("let " + name + " = " + e, ctx.ident)) case _: FAILED_DEC => Coeval.now("FAILED_DEC") @@ -58,42 +59,44 @@ object Decompiler { def unapply(e: EXPR): Option[(String, EXPR, EXPR)] = { e match { case LET_BLOCK(LET(name, v), body) => Some((name, v, body)) - case BLOCK(LET(name, v), body) => Some((name, v, body)) - case _ => None + case BLOCK(LET(name, v), body) => Some((name, v, body)) + case _ => None } } } private def caseExpr(Name: String, e: EXPR, ctx: DecompilerContext): Coeval[(String, Option[EXPR])] = { e match { - case IF( - tc, - ANY_LET(name, REF(Name), cExpr), - tailExpr) => extrTypes(Name, tc) flatMap { - case None => expr(pure(e), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => - ("case _ => " ++ NEWLINE ++ e, None) + case IF(tc, ANY_LET(name, REF(Name), cExpr), tailExpr) => + extrTypes(Name, tc) flatMap { + case None => + expr(pure(e), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => + ("case _ => " ++ NEWLINE ++ e, None) + } + case Some(tl) => + expr(pure(cExpr), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => + ("case " ++ name ++ ": " ++ tl.mkString("|") ++ " => " ++ NEWLINE ++ e, Some(tailExpr)) + } } - case Some(tl) => expr(pure(cExpr), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => - ("case " ++ name ++ ": " ++ tl.mkString("|") ++ " => " ++ NEWLINE ++ e, Some(tailExpr)) + case IF(tc, cExpr, tailExpr) => + extrTypes(Name, tc) flatMap { + case None => + expr(pure(e), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => + ("case _ => " ++ NEWLINE ++ e, None) + } + case Some(tl) => + expr(pure(cExpr), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => + ("case _: " ++ tl.mkString("|") ++ " => " ++ NEWLINE ++ e, Some(tailExpr)) + } } - } - case IF( - tc, - cExpr, - tailExpr) => extrTypes(Name, tc) flatMap { - case None => expr(pure(e), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => - ("case _ => " ++ NEWLINE ++ e, None) + case ANY_LET(name, REF(Name), e) => + expr(pure(e), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => + ("case " ++ name ++ " => " ++ NEWLINE ++ e, None) } - case Some(tl) => expr(pure(cExpr), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => - ("case _: " ++ tl.mkString("|") ++ " => " ++ NEWLINE ++ e, Some(tailExpr)) + case _ => + expr(pure(e), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => + ("case _ => " ++ NEWLINE ++ e, None) } - } - case ANY_LET(name, REF(Name), e) => expr(pure(e), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => - ("case " ++ name ++ " => " ++ NEWLINE ++ e, None) - } - case _ => expr(pure(e), ctx.incrementIdent(), NoBraces, IdentFirstLine) map { e => - ("case _ => " ++ NEWLINE ++ e, None) - } } } @@ -113,107 +116,115 @@ object Decompiler { private[lang] def expr(e: Coeval[EXPR], ctx: DecompilerContext, braces: BlockBraces, firstLinePolicy: FirstLinePolicy): Coeval[String] = { def checkBrackets(expr: EXPR) = expr match { // no need while all binaty ops is bracked. // case Terms.FUNCTION_CALL(FunctionHeader.Native(id), _) if ctx.binaryOps.contains(id) /* || ctx.unaryOps.contains(id) */ => ("(", ")") - case Terms.IF(_, _, _) => ("(", ")") + case Terms.IF(_, _, _) => ("(", ")") case Terms.LET_BLOCK(_, _) => ("(", ")") - case Terms.BLOCK(_, _) => ("(", ")") - case _ => ("", "") + case Terms.BLOCK(_, _) => ("(", ")") + case _ => ("", "") } - def argsStr(args: List[EXPR]) = args.map(argStr).toVector.sequence + def argsStr(args: List[EXPR]) = args.map(argStr).toVector.sequence def listStr(elems: List[EXPR]) = argsStr(elems).map(_.mkString("[", ", ", "]")) - def argStr(elem: EXPR) = expr(pure(elem), ctx, BracesWhenNeccessary, DontIndentFirstLine) + def argStr(elem: EXPR) = expr(pure(elem), ctx, BracesWhenNeccessary, DontIndentFirstLine) val i = if (firstLinePolicy == DontIndentFirstLine) 0 else ctx.ident - e.flatMap(v => (v: @unchecked) match { - case Terms.BLOCK(Terms.LET(MatchRef(name), e), body) => matchBlock(name, pure(body), ctx.incrementIdent()) flatMap { b => - expr(pure(e), ctx.incrementIdent(), NoBraces, DontIndentFirstLine) map { ex => - out("match " ++ ex ++ " {" ++ NEWLINE, ctx.ident) ++ - out( b, 0) ++ - out("}", ctx.ident) - } - } - case Terms.BLOCK(declPar, body) => - val braceThis = braces match { - case NoBraces => false - case BracesWhenNeccessary => true - } - val modifiedCtx = if (braceThis) ctx.incrementIdent() else ctx - for { - d <- decl(pure(declPar), modifiedCtx) - b <- expr(pure(body), modifiedCtx, NoBraces, IdentFirstLine) - } yield { - if (braceThis) - out("{" + NEWLINE, ident = 0) + + e.flatMap(v => + (v: @unchecked) match { + case Terms.BLOCK(Terms.LET(MatchRef(name), e), body) => + matchBlock(name, pure(body), ctx.incrementIdent()) flatMap { b => + expr(pure(e), ctx.incrementIdent(), NoBraces, DontIndentFirstLine) map { ex => + out("match " ++ ex ++ " {" ++ NEWLINE, ctx.ident) ++ + out(b, 0) ++ + out("}", ctx.ident) + } + } + case Terms.BLOCK(declPar, body) => + val braceThis = braces match { + case NoBraces => false + case BracesWhenNeccessary => true + } + val modifiedCtx = if (braceThis) ctx.incrementIdent() else ctx + for { + d <- decl(pure(declPar), modifiedCtx) + b <- expr(pure(body), modifiedCtx, NoBraces, IdentFirstLine) + } yield { + if (braceThis) + out("{" + NEWLINE, ident = 0) + + out(d + NEWLINE, 0) + + out(b + NEWLINE, 0) + + out("}", ctx.ident + 1) + else out(d + NEWLINE, 0) + - out(b + NEWLINE, 0) + - out("}", ctx.ident + 1) - else - out(d + NEWLINE, 0) + - out(b, 0) - } - case Terms.LET_BLOCK(let, exprPar) => expr(pure(Terms.BLOCK(let, exprPar)), ctx, braces, firstLinePolicy) - case Terms.TRUE => pureOut("true", i) - case Terms.FALSE => pureOut("false", i) - case Terms.CONST_BOOLEAN(b) => pureOut(b.toString.toLowerCase(), i) - case Terms.CONST_LONG(t) => pureOut(t.toLong.toString, i) - case Terms.CONST_STRING(s) => pureOut("\"" ++ s ++ "\"", i) - case Terms.CONST_BYTESTR(bs) => pureOut(if(bs.size <= 128) { "base58'" ++ bs.toString ++ "'" } else { "base64'" ++ bs.base64Raw ++ "'" }, i) - case Terms.REF(ref) => pureOut(ref, i) - case Terms.GETTER(getExpr, fld) => - val (bs, be) = checkBrackets(getExpr) - expr(pure(getExpr), ctx, NoBraces, firstLinePolicy).map(a => s"$bs$a$be.$fld") - case Terms.IF(cond, it, iff) => - for { - c <- expr(pure(cond), ctx, BracesWhenNeccessary, DontIndentFirstLine) - it <- expr(pure(it), ctx.incrementIdent(), BracesWhenNeccessary, DontIndentFirstLine) - iff <- expr(pure(iff), ctx.incrementIdent(), BracesWhenNeccessary, DontIndentFirstLine) - } yield - out("if (" + c + ")" + NEWLINE, i) + + out(b, 0) + } + case Terms.LET_BLOCK(let, exprPar) => expr(pure(Terms.BLOCK(let, exprPar)), ctx, braces, firstLinePolicy) + case Terms.TRUE => pureOut("true", i) + case Terms.FALSE => pureOut("false", i) + case Terms.CONST_BOOLEAN(b) => pureOut(b.toString.toLowerCase(), i) + case Terms.CONST_LONG(t) => pureOut(t.toLong.toString, i) + case Terms.CONST_STRING(s) => pureOut("\"" ++ s ++ "\"", i) + case Terms.CONST_BYTESTR(bs) => + pureOut( + if (bs.size <= 128) { "base58'" ++ bs.toString ++ "'" } + else { "base64'" ++ bs.base64Raw ++ "'" }, + i + ) + case Terms.REF(ref) => pureOut(ref, i) + case Terms.GETTER(getExpr, fld) => + val (bs, be) = checkBrackets(getExpr) + expr(pure(getExpr), ctx, NoBraces, firstLinePolicy).map(a => s"$bs$a$be.$fld") + case Terms.IF(cond, it, iff) => + for { + c <- expr(pure(cond), ctx, BracesWhenNeccessary, DontIndentFirstLine) + it <- expr(pure(it), ctx.incrementIdent(), BracesWhenNeccessary, DontIndentFirstLine) + iff <- expr(pure(iff), ctx.incrementIdent(), BracesWhenNeccessary, DontIndentFirstLine) + } yield out("if (" + c + ")" + NEWLINE, i) + out("then " + it + NEWLINE, ctx.ident + 1) + out("else " + iff, ctx.ident + 1) - case FUNCTION_CALL(`cons`, args) => - collectListArgs(args) match { - case (elems, None) => listStr(elems) - case (List(elem), Some(listVar)) => argStr(elem).map(v => s"$v :: $listVar") - case (elems, Some(listVar)) => listStr(elems).map(v => s"$v :: $listVar") - } - case FUNCTION_CALL(`listElem`, List(list, index)) => - val (bs,be) = checkBrackets(list) - for (l <- argStr(list); i <- argStr(index)) yield s"$bs$l$be[$i]" - case Terms.FUNCTION_CALL(func, args) => - val argsCoeval = argsStr(args) - func match { - case FunctionHeader.Native(id) if ctx.binaryOps.contains(id) && args.size == 2 => - val (bs0, be0) = args(0) match { - case Terms.IF(_,_,_) => ("(", ")") - case _ => ("", "") - } - val (bs1, be1) = args(1) match { - case Terms.IF(_,_,_) => ("(", ")") - case _ => ("", "") - } - - argsCoeval.map(as => out(s"(${bs0}${as(0)}${be0} ${ctx.binaryOps(id)} ${bs1}${as(1)}${be1})", i)) - - case FunctionHeader.User(internalName, _) if internalName == "!=" => - argsCoeval.map(as => out(s"(${as(0)} != ${as(1)})", i)) - - case header => - val name = extractFunctionName(ctx, header) - argsCoeval.map(as => out(s"$name(${as.mkString(", ")})", i)) - } - case a: Terms.ARR => pureOut(a.toString, i) - case obj: Terms.CaseObj => pureOut(obj.toString, i) - }) + case FUNCTION_CALL(`cons`, args) => + collectListArgs(args) match { + case (elems, None) => listStr(elems) + case (List(elem), Some(listVar)) => argStr(elem).map(v => s"$v :: $listVar") + case (elems, Some(listVar)) => listStr(elems).map(v => s"$v :: $listVar") + } + case FUNCTION_CALL(`listElem`, List(list, index)) => + val (bs, be) = checkBrackets(list) + for (l <- argStr(list); i <- argStr(index)) yield s"$bs$l$be[$i]" + case Terms.FUNCTION_CALL(func, args) => + val argsCoeval = argsStr(args) + func match { + case FunctionHeader.Native(id) if ctx.binaryOps.contains(id) && args.size == 2 => + val (bs0, be0) = args(0) match { + case Terms.IF(_, _, _) => ("(", ")") + case _ => ("", "") + } + val (bs1, be1) = args(1) match { + case Terms.IF(_, _, _) => ("(", ")") + case _ => ("", "") + } + + argsCoeval.map(as => out(s"(${bs0}${as(0)}${be0} ${ctx.binaryOps(id)} ${bs1}${as(1)}${be1})", i)) + + case FunctionHeader.User(internalName, _) if internalName == "!=" => + argsCoeval.map(as => out(s"(${as(0)} != ${as(1)})", i)) + + case header => + val name = extractFunctionName(ctx, header) + argsCoeval.map(as => out(s"$name(${as.mkString(", ")})", i)) + } + case a: Terms.ARR => pureOut(a.toString, i) + case obj: Terms.CaseObj => pureOut(obj.toString, i) + } + ) } private val extractedFuncR = s"$ExtractedFuncPrefix(\\w+)\\((.+)\\)".r private def extractFunctionName(ctx: DecompilerContext, header: FunctionHeader) = header match { - case inner@User(_, name) => - extractedFuncR.findFirstMatchIn(name) + case inner @ User(_, name) => + extractedFuncR + .findFirstMatchIn(name) .flatMap(m => (m.group(1), m.group(2)) match { case ("User", name) => Some(User(name)) @@ -225,7 +236,7 @@ object Decompiler { .getOrElse(getFunctionName(ctx, inner)) case h => getFunctionName(ctx, h) - } + } private def getFunctionName(ctx: DecompilerContext, header: FunctionHeader) = header match { @@ -233,14 +244,14 @@ object Decompiler { case User(_, name) => name } - private val nil = REF("nil") - private val cons = Native(FunctionIds.CREATE_LIST) + private val nil = REF(GlobalValNames.Nil) + private val cons = Native(FunctionIds.CREATE_LIST) private val listElem = Native(FunctionIds.GET_LIST) private def collectListArgs(args: List[EXPR]): (List[EXPR], Option[String]) = { def flattenRec(args: List[EXPR]): List[EXPR] = args match { case a :: FUNCTION_CALL(`cons`, nextArgs) :: Nil => a :: flattenRec(nextArgs) - case l => l + case l => l } flattenRec(args) match { case a :+ `nil` => (a, None) @@ -259,14 +270,12 @@ object Decompiler { val decls: Seq[Coeval[String]] = decs.map(expr => decl(pure(expr), ctx)) val callables: Seq[Coeval[String]] = callableFuncs - .map { - case CallableFunction(annotation, u) => - Decompiler.decl(pure(u), ctx).map(out(NEWLINE + "@Callable(" + annotation.invocationArgName + ")" + NEWLINE, 0) + _) + .map { case CallableFunction(annotation, u) => + Decompiler.decl(pure(u), ctx).map(out(NEWLINE + "@Callable(" + annotation.invocationArgName + ")" + NEWLINE, 0) + _) } - val verifier: Seq[Coeval[String]] = verifierFuncOpt.map { - case VerifierFunction(annotation, u) => - Decompiler.decl(pure(u), ctx).map(out(NEWLINE + "@Verifier(" + annotation.invocationArgName + ")" + NEWLINE, 0) + _) + val verifier: Seq[Coeval[String]] = verifierFuncOpt.map { case VerifierFunction(annotation, u) => + Decompiler.decl(pure(u), ctx).map(out(NEWLINE + "@Verifier(" + annotation.invocationArgName + ")" + NEWLINE, 0) + _) }.toSeq val result = for { diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala index 65c302eb885..68dd02a7074 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala @@ -10,9 +10,21 @@ import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.Types.* import com.wavesplatform.lang.v1.evaluator.EvaluatorV1.* import com.wavesplatform.lang.v1.evaluator.ctx.* -import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.lang.v1.parser.BinaryOperation.* -import com.wavesplatform.lang.v1.parser.Expressions.{BINARY_OP, CompositePattern, ConstsPat, MATCH_CASE, ObjPat, PART, Pos, Single, TuplePat, Type, TypedVar} +import com.wavesplatform.lang.v1.parser.Expressions.{ + BINARY_OP, + CompositePattern, + ConstsPat, + MATCH_CASE, + ObjPat, + PART, + Pos, + Single, + TuplePat, + Type, + TypedVar +} import com.wavesplatform.lang.v1.parser.{BinaryOperation, Expressions, Parser} import com.wavesplatform.lang.v1.task.imports.* import com.wavesplatform.lang.v1.{BaseGlobal, ContractLimits, FunctionHeader} @@ -91,7 +103,7 @@ object ExpressionCompiler { } def compileDecls(input: String, ctx: CompilerContext): Either[String, EXPR] = { - val adjustedDecls = s"$input\n${PureContext.unitVarName}" + val adjustedDecls = s"$input\n${GlobalValNames.Unit}" compileUntyped(adjustedDecls, ctx) } @@ -133,20 +145,20 @@ object ExpressionCompiler { List(Generic(x.position.start, x.position.end, x.message)) ).pure[CompileM] - case Expressions.GETTER(p, ref, field, _, _, c) => compileGetter(p, field, ref, saveExprContext, allowIllFormedStrings, c) - case Expressions.BLOCK(p, dec, body, _, _) => compileBlock(p, dec, body, saveExprContext, allowIllFormedStrings) - case Expressions.IF(p, cond, ifTrue, ifFalse, _, _) => compileIf(p, cond, ifTrue, ifFalse, saveExprContext, allowIllFormedStrings) - case Expressions.REF(p, key, _, _) => compileRef(p, key, saveExprContext) - case Expressions.FUNCTION_CALL(p, name, args, _, _) => compileFunctionCall(p, name, args, saveExprContext, allowIllFormedStrings) - case Expressions.MATCH(p, ex, cases, _, _) => compileMatch(p, ex, cases.toList, saveExprContext, allowIllFormedStrings) - case f: Expressions.FOLD => compileFold(f) + case Expressions.GETTER(p, ref, field, _, _, c) => compileGetter(p, field, ref, saveExprContext, allowIllFormedStrings, c) + case Expressions.BLOCK(p, dec, body, _, _) => compileBlock(p, dec, body, saveExprContext, allowIllFormedStrings) + case Expressions.IF(p, cond, ifTrue, ifFalse, _, _) => compileIf(p, cond, ifTrue, ifFalse, saveExprContext, allowIllFormedStrings) + case Expressions.REF(p, key, _, _) => compileRef(p, key, saveExprContext) + case Expressions.FUNCTION_CALL(p, name, args, _, _) => compileFunctionCall(p, name, args, saveExprContext, allowIllFormedStrings) + case Expressions.MATCH(p, ex, cases, _, _) => compileMatch(p, ex, cases.toList, saveExprContext, allowIllFormedStrings) + case f: Expressions.FOLD => compileFold(f) case Expressions.GENERIC_FUNCTION_CALL(p, e, name, t, _, _) => compileGenericFunctionCall(p, e, name, t, saveExprContext, allowIllFormedStrings) case Expressions.BINARY_OP(p, a, op, b, _, _) => op match { case AND_OP => compileIf(p, a, b, Expressions.FALSE(p), saveExprContext, allowIllFormedStrings) case OR_OP => compileIf(p, a, Expressions.TRUE(p), b, saveExprContext, allowIllFormedStrings) - case _ => compileFunctionCall(p, PART.VALID(p, BinaryOperation.opsToFunctions(op)), List(a, b), saveExprContext, allowIllFormedStrings) + case _ => compileFunctionCall(p, PART.VALID(p, BinaryOperation.opsToFunctions(op)), List(a, b), saveExprContext, allowIllFormedStrings) } } } @@ -182,17 +194,18 @@ object ExpressionCompiler { ) errorList = condWithErr._1.errors ++ ifTrue.errors ++ ifFalse.errors - result = if (condWithErr._2.isEmpty) { - CompilationStepResultExpr( - ctx, - IF(condWithErr._1.expr, ifTrue.expr, ifFalse.expr), - t, - parseNodeExpr, - errorList - ) - } else { - CompilationStepResultExpr(ctx, FAILED_EXPR(), NOTHING, parseNodeExpr, errorList ++ condWithErr._2.map(List(_)).get) - } + result = + if (condWithErr._2.isEmpty) { + CompilationStepResultExpr( + ctx, + IF(condWithErr._1.expr, ifTrue.expr, ifFalse.expr), + t, + parseNodeExpr, + errorList + ) + } else { + CompilationStepResultExpr(ctx, FAILED_EXPR(), NOTHING, parseNodeExpr, errorList ++ condWithErr._2.map(List(_)).get) + } } yield result private def flatSingle( @@ -214,7 +227,7 @@ object ExpressionCompiler { private def findGenericType(p: Pos, t: String): Either[CompilationError, FINAL => FINAL] = t match { case Type.ListTypeName => Right(LIST) - case _ => Left(GenericTypeNotFound(p.start, p.end, t)) + case _ => Left(GenericTypeNotFound(p.start, p.end, t)) } private def compileMatch( @@ -273,12 +286,10 @@ object ExpressionCompiler { case UNION(tl, _) => UNION(tl.filter(t => !matchTypes.contains(t)), None) case _ => NOTHING } - ifCasesWithErr <- inspectFlat[Id, CompilerContext, CompilationError, Expressions.EXPR]( - updatedCtx => { - val ref = Expressions.REF(p, PART.VALID(p, refTmpKey), ctxOpt = saveExprContext.toOption(updatedCtx)) - mkIfCases(cases, matchTypes, ref, defaultType, allowShadowVarName, updatedCtx).toCompileM - } - ).handleError() + ifCasesWithErr <- inspectFlat[Id, CompilerContext, CompilationError, Expressions.EXPR](updatedCtx => { + val ref = Expressions.REF(p, PART.VALID(p, refTmpKey), ctxOpt = saveExprContext.toOption(updatedCtx)) + mkIfCases(cases, matchTypes, ref, defaultType, allowShadowVarName, updatedCtx).toCompileM + }).handleError() compiledMatch <- compileLetBlock( p, Expressions.LET(p, PART.VALID(p, refTmpKey), expr), @@ -292,17 +303,21 @@ object ExpressionCompiler { saveExprContext, allowIllFormedStrings ) - checktypes = if (matchTypes.contains(LIST(ANY))) { - (matchTypes.filter(_ != LIST(ANY)), UNION.create((exprTypes match { - case ANY => List(ANY) - case t => t.typeList - }).filter { - case LIST(_) => false - case _ => true - })) - } else { - (matchTypes, exprTypes) - } + checktypes = + if (matchTypes.contains(LIST(ANY))) { + ( + matchTypes.filter(_ != LIST(ANY)), + UNION.create((exprTypes match { + case ANY => List(ANY) + case t => t.typeList + }).filter { + case LIST(_) => false + case _ => true + }) + ) + } else { + (matchTypes, exprTypes) + } matchedTypesUnion = UNION.create(checktypes._1) checkWithErr <- Either .cond( @@ -316,17 +331,18 @@ object ExpressionCompiler { errorList = ifCasesWithErr._2 ++ compiledMatch.errors ++ checkWithErr._2 - result = if (errorList.isEmpty) { - compiledMatch.copy(errors = compiledMatch.errors ++ typedExpr.errors) - } else { - CompilationStepResultExpr( - ctx, - FAILED_EXPR(), - NOTHING, - Expressions.MATCH(p, typedExpr.parseNodeExpr, cases, ctxOpt = saveExprContext.toOption(ctx)), - errorList ++ typedExpr.errors - ) - } + result = + if (errorList.isEmpty) { + compiledMatch.copy(errors = compiledMatch.errors ++ typedExpr.errors) + } else { + CompilationStepResultExpr( + ctx, + FAILED_EXPR(), + NOTHING, + Expressions.MATCH(p, typedExpr.parseNodeExpr, cases, ctxOpt = saveExprContext.toOption(ctx)), + errorList ++ typedExpr.errors + ) + } } yield result private def exprContainsRef(expr: Expressions.EXPR, ref: String): Boolean = @@ -401,8 +417,8 @@ object ExpressionCompiler { for { ctx <- get[Id, CompilerContext, CompilationError] letName <- handlePart(dec.name) - .ensureOr(n => AlreadyDefined(p.start, p.end, n, isFunction = false))( - n => !ctx.varDefs.contains(n) || dec.allowShadowing || allowedExceptions.contains(n) + .ensureOr(n => AlreadyDefined(p.start, p.end, n, isFunction = false))(n => + !ctx.varDefs.contains(n) || dec.allowShadowing || allowedExceptions.contains(n) ) .ensureOr(n => AlreadyDefined(p.start, p.end, n, isFunction = true))(n => !ctx.functionDefs.contains(n)) } yield letName @@ -426,11 +442,12 @@ object ExpressionCompiler { errorList = letNameWithErr._2 parseNodeDecl = let.copy(value = compiledLet.parseNodeExpr) - result = if (errorList.isEmpty) { - CompilationStepResultDec(ctx, LET(letNameWithErr._1.get, compiledLet.expr), letType, parseNodeDecl, compiledLet.errors) - } else { - CompilationStepResultDec(ctx, FAILED_DEC(), letType, parseNodeDecl, errorList ++ compiledLet.errors) - } + result = + if (errorList.isEmpty) { + CompilationStepResultDec(ctx, LET(letNameWithErr._1.get, compiledLet.expr), letType, parseNodeDecl, compiledLet.errors) + } else { + CompilationStepResultDec(ctx, FAILED_DEC(), letType, parseNodeDecl, errorList ++ compiledLet.errors) + } } yield result def compileFunc( @@ -452,12 +469,11 @@ object ExpressionCompiler { .handleError() ctx <- get[Id, CompilerContext, CompilationError] argTypesWithErr <- func.args.toList - .traverse { - case (argName, argType) => - for { - name <- handlePart(argName) - handledType <- handleCompositeType(p, argType, None, Some(name)) - } yield (name, VariableInfo(argName.position, handledType)) + .traverse { case (argName, argType) => + for { + name <- handlePart(argName) + handledType <- handleCompositeType(p, argType, None, Some(name)) + } yield (name, VariableInfo(argName.position, handledType)) } .handleError() compiledFuncBody <- local { @@ -469,17 +485,18 @@ object ExpressionCompiler { errorList = funcNameWithErr._2 ++ argsWithErr._2 ++ argTypesWithErr._2 parseNodeDecl = func.copy(expr = compiledFuncBody.parseNodeExpr) - result = if (errorList.isEmpty) { - CompilationStepResultDec( - ctx, - FUNC(funcNameWithErr._1.get, argTypesWithErr._1.get.map(_._1), compiledFuncBody.expr), - compiledFuncBody.t, - parseNodeDecl, - compiledFuncBody.errors - ) - } else { - CompilationStepResultDec(ctx, FAILED_DEC(), compiledFuncBody.t, parseNodeDecl, errorList ++ compiledFuncBody.errors) - } + result = + if (errorList.isEmpty) { + CompilationStepResultDec( + ctx, + FUNC(funcNameWithErr._1.get, argTypesWithErr._1.get.map(_._1), compiledFuncBody.expr), + compiledFuncBody.t, + parseNodeDecl, + compiledFuncBody.errors + ) + } else { + CompilationStepResultDec(ctx, FAILED_DEC(), compiledFuncBody.t, parseNodeDecl, errorList ++ compiledFuncBody.errors) + } } yield (result, argTypesWithErr._1.map(_.map(nameAnfInfo => (nameAnfInfo._1, nameAnfInfo._2.vType))).getOrElse(List.empty)) } @@ -511,11 +528,12 @@ object ExpressionCompiler { compiledBody.parseNodeExpr.resultType, saveExprContext.toOption(compiledBody.ctx) ) - result = if (!compLetResult.dec.isItFailed) { - LET_BLOCK(compLetResult.dec.asInstanceOf[LET], compiledBody.expr) - } else { - FAILED_EXPR() - } + result = + if (!compLetResult.dec.isItFailed) { + LET_BLOCK(compLetResult.dec.asInstanceOf[LET], compiledBody.expr) + } else { + FAILED_EXPR() + } } yield CompilationStepResultExpr(compiledBody.ctx, result, compiledBody.t, parseNodeExpr, compLetResult.errors ++ compiledBody.errors) private def compileFuncBlock( @@ -564,12 +582,13 @@ object ExpressionCompiler { errorList = fieldWithErr._2 ++ getterWithErr._2 parseNodeExpr = Expressions.GETTER(p, compiledRef.parseNodeExpr, fieldPart, ctxOpt = saveExprContext.toOption(ctx)) - result = if (errorList.isEmpty) { - val (ctx, expr, t) = getterWithErr._1.get - CompilationStepResultExpr(ctx, expr, t, parseNodeExpr.copy(resultType = Some(t)), compiledRef.errors) - } else { - CompilationStepResultExpr(ctx, FAILED_EXPR(), NOTHING, parseNodeExpr, errorList ++ compiledRef.errors) - } + result = + if (errorList.isEmpty) { + val (ctx, expr, t) = getterWithErr._1.get + CompilationStepResultExpr(ctx, expr, t, parseNodeExpr.copy(resultType = Some(t)), compiledRef.errors) + } else { + CompilationStepResultExpr(ctx, FAILED_EXPR(), NOTHING, parseNodeExpr, errorList ++ compiledRef.errors) + } } yield result private def compileFunctionCall( @@ -610,12 +629,13 @@ object ExpressionCompiler { saveExprContext.toOption(ctx) ) - result = if (errorList.isEmpty) { - val (expr, t) = funcCallWithErr._1.get - CompilationStepResultExpr(ctx, expr, t, parseNodeExpr, argErrorList) - } else { - CompilationStepResultExpr(ctx, FAILED_EXPR(), NOTHING, parseNodeExpr, errorList ++ argErrorList) - } + result = + if (errorList.isEmpty) { + val (expr, t) = funcCallWithErr._1.get + CompilationStepResultExpr(ctx, expr, t, parseNodeExpr, argErrorList) + } else { + CompilationStepResultExpr(ctx, FAILED_EXPR(), NOTHING, parseNodeExpr, errorList ++ argErrorList) + } } yield result private def compileGenericFunctionCall( @@ -639,28 +659,29 @@ object ExpressionCompiler { ctx <- get[Id, CompilerContext, CompilationError] typeWithErr = ctx .resolveVar(keyWithErr._1.getOrElse("")) - .fold[(Option[FINAL], Iterable[CompilationError])]((None, List(DefNotFound(p.start, p.end, keyWithErr._1.getOrElse("")))))( - info => (Some(info.vType), List.empty) + .fold[(Option[FINAL], Iterable[CompilationError])]((None, List(DefNotFound(p.start, p.end, keyWithErr._1.getOrElse("")))))(info => + (Some(info.vType), List.empty) ) errorList = keyWithErr._2 ++ typeWithErr._2 - result = if (errorList.isEmpty) { - CompilationStepResultExpr( - ctx, - REF(keyWithErr._1.get), - typeWithErr._1.get, - Expressions.REF(p, keyPart, typeWithErr._1, saveExprContext.toOption(ctx)) - ) - } else { - CompilationStepResultExpr( - ctx, - FAILED_EXPR(), - NOTHING, - Expressions.REF(p, keyPart, ctxOpt = saveExprContext.toOption(ctx)), - errorList - ) - } + result = + if (errorList.isEmpty) { + CompilationStepResultExpr( + ctx, + REF(keyWithErr._1.get), + typeWithErr._1.get, + Expressions.REF(p, keyPart, typeWithErr._1, saveExprContext.toOption(ctx)) + ) + } else { + CompilationStepResultExpr( + ctx, + FAILED_EXPR(), + NOTHING, + Expressions.REF(p, keyPart, ctxOpt = saveExprContext.toOption(ctx)), + errorList + ) + } } yield result private def compileFold(fold: Expressions.FOLD): CompileM[CompilationStepResultExpr] = @@ -683,7 +704,9 @@ object ExpressionCompiler { .getOrElse { val accTypeStr = if (accType == NOTHING) ANY else accType val listInnerTypeStr = if (listInnerType == NOTHING) ANY else listInnerType - Left(Generic(fold.position.start, fold.position.end, s"Can't find suitable function $funcName(a: $accTypeStr, b: $listInnerTypeStr) for $name")) + Left( + Generic(fold.position.start, fold.position.end, s"Can't find suitable function $funcName(a: $accTypeStr, b: $listInnerTypeStr) for $name") + ) } .toCompileM _ <- set[Id, CompilerContext, CompilationError](ctx.copy(foldIdx = ctx.foldIdx + 1)) @@ -782,11 +805,10 @@ object ExpressionCompiler { case _ => nextExprE } } - exprE.map( - expr => - p.caseType.fold(expr) { _ => - val let = Expressions.LET(p.position, newRef.key, newRef, Some(caseType), allowShadowing = true) - Expressions.BLOCK(p.position, let, expr) + exprE.map(expr => + p.caseType.fold(expr) { _ => + val let = Expressions.LET(p.position, newRef.key, newRef, Some(caseType), allowShadowing = true) + Expressions.BLOCK(p.position, let, expr) } ) } @@ -852,14 +874,13 @@ object ExpressionCompiler { cond Right( makeIfCase( - p.caseType.fold(checkingCond)( - t => - BINARY_OP( - pos, - Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(refTmp, Expressions.CONST_STRING(pos, t.name))), - BinaryOperation.AND_OP, - Expressions.BLOCK(pos, Expressions.LET(pos, newRef.key, newRef, Some(caseType), true), checkingCond) - ) + p.caseType.fold(checkingCond)(t => + BINARY_OP( + pos, + Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(refTmp, Expressions.CONST_STRING(pos, t.name))), + BinaryOperation.AND_OP, + Expressions.BLOCK(pos, Expressions.LET(pos, newRef.key, newRef, Some(caseType), true), checkingCond) + ) ), blockWithNewVar, further @@ -878,12 +899,11 @@ object ExpressionCompiler { ) } - (cases zip caseTypes).foldRight(default) { - case ((mc, caseType), furtherEi) => - furtherEi match { - case Right(further) => f(mc, caseType, further) - case Left(e) => Left(e) - } + (cases zip caseTypes).foldRight(default) { case ((mc, caseType), furtherEi) => + furtherEi match { + case Right(further) => f(mc, caseType, further) + case Left(e) => Left(e) + } } } @@ -1067,12 +1087,11 @@ object ExpressionCompiler { .value ._2 .leftMap(e => s"Compilation failed: ${Show[CompilationError].show(e)}") - .flatMap( - res => - Either.cond( - res.errors.isEmpty, - (res.ctx, res.expr, res.t), - s"Compilation failed: [${res.errors.map(e => Show[CompilationError].show(e)).mkString("; ")}]" - ) + .flatMap(res => + Either.cond( + res.errors.isEmpty, + (res.ctx, res.expr, res.t), + s"Compilation failed: [${res.errors.map(e => Show[CompilationError].show(e)).mkString("; ")}]" + ) ) } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeCast.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeCast.scala index 22722a4715e..38b6207c034 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeCast.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeCast.scala @@ -4,6 +4,7 @@ import com.wavesplatform.lang.v1.compiler.CompilationError.{GenericFunctionNotFo import com.wavesplatform.lang.v1.compiler.ExpressionCompiler.CompilationStepResultExpr import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.Types.* +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext.* import com.wavesplatform.lang.v1.parser.Expressions.Pos import com.wavesplatform.lang.v1.parser.Parser.GenericMethod.{As, ExactAs} @@ -41,7 +42,7 @@ object TypeCast { CONST_STRING(s"Couldn't cast ${expr.t} to $targetType").explicitGet() private def as(p: Pos, targetType: FINAL, expr: CompilationStepResultExpr): CompilationStepResultExpr = - cast(p, targetType, UNION(targetType, UNIT), expr, REF(unitVarName)) + cast(p, targetType, UNION(targetType, UNIT), expr, REF(GlobalValNames.Unit)) private def cast(p: Pos, targetType: FINAL, resultExprType: FINAL, expr: CompilationStepResultExpr, onError: EXPR): CompilationStepResultExpr = { targetType match { diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/CryptoContext.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/CryptoContext.scala index 9e500865016..4c5968fca64 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/CryptoContext.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/CryptoContext.scala @@ -1,17 +1,17 @@ package com.wavesplatform.lang.v1.evaluator.ctx.impl -import cats.implicits._ +import cats.implicits.* import cats.{Id, Monad} import com.wavesplatform.common.merkle.Merkle.createRoot import com.wavesplatform.common.state.ByteStr import com.wavesplatform.lang.{ExecutionError, CommonError} -import com.wavesplatform.lang.directives.values.{StdLibVersion, V3, _} -import com.wavesplatform.lang.v1.compiler.Terms._ -import com.wavesplatform.lang.v1.compiler.Types._ +import com.wavesplatform.lang.directives.values.{StdLibVersion, V3, *} +import com.wavesplatform.lang.v1.compiler.Terms.* +import com.wavesplatform.lang.v1.compiler.Types.* import com.wavesplatform.lang.v1.compiler.{CompilerContext, Terms} import com.wavesplatform.lang.v1.evaluator.Contextful.NoContext import com.wavesplatform.lang.v1.evaluator.ContextfulVal -import com.wavesplatform.lang.v1.evaluator.FunctionIds._ +import com.wavesplatform.lang.v1.evaluator.FunctionIds.* import com.wavesplatform.lang.v1.evaluator.ctx.impl.crypto.RSA.DigestAlgorithm import com.wavesplatform.lang.v1.evaluator.ctx.{BaseFunction, EvaluationContext, NativeFunction} import com.wavesplatform.lang.v1.{BaseGlobal, CTX} @@ -20,7 +20,7 @@ import scala.collection.mutable object CryptoContext { - private val rsaTypeNames = List("NoAlg", "Md5", "Sha1", "Sha224", "Sha256", "Sha384", "Sha512", "Sha3224", "Sha3256", "Sha3384", "Sha3512") + val rsaTypeNames = List("NoAlg", "Md5", "Sha1", "Sha224", "Sha256", "Sha384", "Sha512", "Sha3224", "Sha3256", "Sha3384", "Sha3512") private def rsaHashAlgs(v: StdLibVersion) = { rsaTypeNames.map(CASETYPEREF(_, List.empty, v > V3)) @@ -371,7 +371,7 @@ object CryptoContext { ) { case xs @ ARR(proof) :: CONST_BYTESTR(value) :: CONST_LONG(index) :: Nil => val filteredProofs = proof.collect { - case bs@CONST_BYTESTR(v) if v.size == 32 => bs + case bs @ CONST_BYTESTR(v) if v.size == 32 => bs } if (value.size == 32 && proof.length <= 16 && filteredProofs.size == proof.size) { diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/GlobalValNames.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/GlobalValNames.scala new file mode 100644 index 00000000000..9f607d5e4bf --- /dev/null +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/GlobalValNames.scala @@ -0,0 +1,17 @@ +package com.wavesplatform.lang.v1.evaluator.ctx.impl + +object GlobalValNames { + val Sell: String = "Sell" + val Buy: String = "Buy" + val Height: String = "height" + val LastBlock: String = "lastBlock" + val Tx: String = "tx" + val This: String = "this" + val Nil: String = "nil" + val Unit: String = "unit" + + val All: Set[String] = + Set(Buy, Sell, Height, LastBlock, Nil, This, Tx, Unit) ++ + Rounding.fromV5.map(_.definition._1) ++ + CryptoContext.rsaTypeNames.map(_.toUpperCase) +} diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala index 9514757792b..bb040b08b0e 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala @@ -253,7 +253,7 @@ object PureContext { ("@a", PARAMETERIZEDUNION(List(TYPEPARAM('T'), UNIT))) ) { IF( - FUNCTION_CALL(eq, List(REF("@a"), REF("unit"))), + FUNCTION_CALL(eq, List(REF("@a"), REF(GlobalValNames.Unit))), FUNCTION_CALL(throwWithMessage, List(CONST_STRING("extract() called on unit value").explicitGet())), REF("@a") ) @@ -293,7 +293,7 @@ object PureContext { case _ => base } IF( - FUNCTION_CALL(PureContext.eq, List(REF("@a"), REF("unit"))), + FUNCTION_CALL(PureContext.eq, List(REF("@a"), REF(GlobalValNames.Unit))), FUNCTION_CALL(throwWithMessage, List(CONST_STRING(errorMessage).explicitGet())), REF("@a") ) @@ -310,7 +310,7 @@ object PureContext { ("@alternative", TYPEPARAM('T')) ) { IF( - FUNCTION_CALL(eq, List(REF("@value"), REF("unit"))), + FUNCTION_CALL(eq, List(REF("@value"), REF(GlobalValNames.Unit))), REF("@alternative"), REF("@value") ) @@ -325,7 +325,7 @@ object PureContext { ("@msg", STRING) ) { IF( - FUNCTION_CALL(eq, List(REF("@a"), REF("unit"))), + FUNCTION_CALL(eq, List(REF("@a"), REF(GlobalValNames.Unit))), FUNCTION_CALL(throwWithMessage, List(REF("@msg"))), REF("@a") ) @@ -338,7 +338,7 @@ object PureContext { BOOLEAN, ("@a", PARAMETERIZEDUNION(List(TYPEPARAM('T'), UNIT))) ) { - FUNCTION_CALL(ne, List(REF("@a"), REF("unit"))) + FUNCTION_CALL(ne, List(REF("@a"), REF(GlobalValNames.Unit))) } def fraction(fixLimitCheck: Boolean): BaseFunction[NoContext] = @@ -1731,14 +1731,15 @@ object PureContext { } } - val unitVarName = "unit" - private val nil: (String, (LIST, ContextfulVal[NoContext])) = - ("nil", (LIST(NOTHING), ContextfulVal.pure[NoContext](ARR(IndexedSeq.empty[EVALUATED], EMPTYARR_WEIGHT, limited = false).explicitGet()))) + ( + GlobalValNames.Nil, + (LIST(NOTHING), ContextfulVal.pure[NoContext](ARR(IndexedSeq.empty[EVALUATED], EMPTYARR_WEIGHT, limited = false).explicitGet())) + ) private val commonVars: Map[String, (FINAL, ContextfulVal[NoContext])] = Map( - (unitVarName, (UNIT, ContextfulVal.pure(unit))) + (GlobalValNames.Unit, (UNIT, ContextfulVal.pure(unit))) ) private val v1V2Vars: Map[String, (FINAL, ContextfulVal[NoContext])] = commonVars ++ Rounding.all.map(_.definition) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala index f1da83d1394..fe40b3f515d 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala @@ -14,7 +14,7 @@ import com.wavesplatform.lang.v1.evaluator.FunctionIds.* import com.wavesplatform.lang.v1.evaluator.ctx.impl.converters.* import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.Bindings.{scriptTransfer as _, *} import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.Types.* -import com.wavesplatform.lang.v1.evaluator.ctx.impl.{EnvironmentFunctions, PureContext, notImplemented, unit} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.{EnvironmentFunctions, GlobalValNames, PureContext, notImplemented, unit} import com.wavesplatform.lang.v1.evaluator.ctx.{BaseFunction, NativeFunction, UserFunction} import com.wavesplatform.lang.v1.evaluator.{ContextfulNativeFunction, ContextfulUserFunction, FunctionIds, Log} import com.wavesplatform.lang.v1.traits.domain.{Issue, Lease, Recipient} @@ -156,7 +156,7 @@ object Functions { List(REF("@val"), CONST_STRING(dataType.innerType.name).explicitGet()) ), REF("@val"), - REF("unit") + REF(GlobalValNames.Unit) ) ) } @@ -334,13 +334,13 @@ object Functions { IF( verifyAddressChecksumExpr(REF("@afs_addrBytes"), version), FUNCTION_CALL(FunctionHeader.User("Address"), List(REF("@afs_addrBytes"))), - REF("unit") + REF(GlobalValNames.Unit) ), - REF("unit") + REF(GlobalValNames.Unit) ), - REF("unit") + REF(GlobalValNames.Unit) ), - REF("unit") + REF(GlobalValNames.Unit) ) ) } @@ -523,7 +523,7 @@ object Functions { val wavesBalanceF: BaseFunction[Environment] = UserFunction("wavesBalance", 109, LONG, ("@addressOrAlias", addressOrAliasType)) { - FUNCTION_CALL(assetBalanceF.header, List(REF("@addressOrAlias"), REF("unit"))) + FUNCTION_CALL(assetBalanceF.header, List(REF("@addressOrAlias"), REF(GlobalValNames.Unit))) } val txHeightByIdF: BaseFunction[Environment] = diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Vals.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Vals.scala index 4672b393244..567d0843c21 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Vals.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Vals.scala @@ -8,6 +8,7 @@ import com.wavesplatform.lang.directives.values.StdLibVersion import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.Types.* import com.wavesplatform.lang.v1.evaluator.ContextfulVal +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames.* import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.Bindings.{buildAssetInfo, ordType, orderObject, transactionObject} import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.Types.* import com.wavesplatform.lang.v1.traits.Environment @@ -21,7 +22,7 @@ object Vals { proofsEnabled: Boolean, fixBigScriptField: Boolean ): (String, (UNION, ContextfulVal[Environment])) = - ("tx", (scriptInputType(isTokenContext, version, proofsEnabled), inputEntityVal(version, proofsEnabled, fixBigScriptField))) + (Tx, (scriptInputType(isTokenContext, version, proofsEnabled), inputEntityVal(version, proofsEnabled, fixBigScriptField))) private def scriptInputType(isTokenContext: Boolean, version: StdLibVersion, proofsEnabled: Boolean) = if (isTokenContext) @@ -106,18 +107,18 @@ object Vals { } } - def lastBlock(version: StdLibVersion) = ("lastBlock", (blockInfo(version), lastBlockVal(version))) + def lastBlock(version: StdLibVersion) = (LastBlock, (blockInfo(version), lastBlockVal(version))) val sellOrdTypeVal: ContextfulVal[Environment] = ContextfulVal.fromEval(Eval.now(Right(ordType(OrdType.Sell)))) val buyOrdTypeVal: ContextfulVal[Environment] = ContextfulVal.fromEval(Eval.now(Right(ordType(OrdType.Buy)))) - val sell = ("Sell", (ordTypeType, sellOrdTypeVal)) - val buy = ("Buy", (ordTypeType, buyOrdTypeVal)) + val sell = (Sell, (ordTypeType, sellOrdTypeVal)) + val buy = (Buy, (ordTypeType, buyOrdTypeVal)) - val height: (String, (LONG.type, ContextfulVal[Environment])) = ("height", (LONG, heightVal)) + val height: (String, (LONG.type, ContextfulVal[Environment])) = (Height, (LONG, heightVal)) - val accountThis: (String, (CASETYPEREF, ContextfulVal[Environment])) = ("this", (addressType, accountThisVal)) + val accountThis: (String, (CASETYPEREF, ContextfulVal[Environment])) = (This, (addressType, accountThisVal)) def assetThis(version: StdLibVersion): (String, (CASETYPEREF, ContextfulVal[Environment])) = - ("this", (assetType(version), assetThisVal(version))) + (This, (assetType(version), assetThisVal(version))) } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala index 3d3faa15dc7..290fcaaf97e 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala @@ -5,6 +5,7 @@ import cats.instances.list.* import cats.syntax.either.* import cats.syntax.traverse.* import com.wavesplatform.common.state.ByteStr +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext.MaxListLengthV4 import com.wavesplatform.lang.v1.parser.BinaryOperation.* import com.wavesplatform.lang.v1.parser.Expressions.* @@ -583,7 +584,7 @@ class Parser(implicit offset: Int) { } def parseReplExpr(str: String): Parsed[EXPR] = { - def unit[A: P] = Pass(REF(AnyPos, VALID(AnyPos, "unit"))) + def unit[A: P] = Pass(REF(AnyPos, VALID(AnyPos, GlobalValNames.Unit))) def replAtom[A: P] = baseAtom(block(Some(unit))(_)) def replExpr[A: P] = binaryOp(baseAtom(replAtom(_))(_), opsByPriority) parse(str, replExpr(_), verboseFailures = true) diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/IntegrationTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/IntegrationTest.scala index ad27d7772da..16252b56dec 100755 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/IntegrationTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/IntegrationTest.scala @@ -1603,7 +1603,7 @@ class IntegrationTest extends PropSpec with Inside { ("true", "Boolean"), ("123", "Int"), ("base58'aaaa'", "ByteVector"), - ("unit", "Unit") + (GlobalValNames.Unit, "Unit") ) #::: getElement /* Example for size = 2 diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerCompactorTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerCompactorTest.scala index 6755afdb0b6..02d294b4951 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerCompactorTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerCompactorTest.scala @@ -8,10 +8,16 @@ import com.wavesplatform.lang.directives.{Directive, DirectiveParser, DirectiveS import com.wavesplatform.lang.directives.values.{DApp as DAppType, *} import com.wavesplatform.lang.script.{Script, ScriptPreprocessor} import com.wavesplatform.lang.script.ContractScript.ContractScriptImpl +import com.wavesplatform.lang.v1.FunctionHeader.User +import com.wavesplatform.lang.v1.compiler.Terms.{CONST_LONG, CaseObj} +import com.wavesplatform.lang.v1.compiler.Types.{ANY, BIGINT, BOOLEAN, LIST, LONG, PARAMETERIZED, PARAMETERIZEDLIST, STRING, UNION} import com.wavesplatform.lang.v1.compiler.{ContractScriptCompactor, TestCompiler} +import com.wavesplatform.lang.v1.evaluator.Contextful.NoContext +import com.wavesplatform.lang.v1.evaluator.ContextfulVal +import com.wavesplatform.lang.v1.evaluator.ctx.impl.Rounding.Down import com.wavesplatform.lang.v1.{CTX, compiler} -import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext -import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.WavesContext +import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, GlobalValNames, PureContext} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.{Types, WavesContext} import com.wavesplatform.lang.v1.parser.{Expressions, Parser} import com.wavesplatform.lang.v1.traits.Environment import com.wavesplatform.protobuf.dapp.DAppMeta @@ -25,6 +31,18 @@ class ContractCompilerCompactorTest extends PropSpec { Script.decompile(ContractScriptImpl(stdLibVersion, dApp.copy(meta = DAppMeta())))._1 } + private def fullCtxForV(version: StdLibVersion): CTX[Environment] = { + val transactionType = Types.buildTransferTransactionType(true) + val tx = CaseObj(transactionType, Map("amount" -> CONST_LONG(100000000L))) + ctxForV(version) |+| + CryptoContext.build(Global, version).withEnvironment[Environment] |+| + CTX[NoContext]( + Seq(transactionType), + Map(("tx", (transactionType, ContextfulVal.pure[NoContext](tx)))), + Array.empty + ).withEnvironment[Environment] + } + private def ctxForV(version: StdLibVersion): CTX[Environment] = PureContext.build(version, useNewPowPrecision = true).withEnvironment[Environment] |+| WavesContext.build(Global, DirectiveSet(version, Account, DAppType).explicitGet(), fixBigScriptField = true) @@ -55,7 +73,10 @@ class ContractCompilerCompactorTest extends PropSpec { } def checkForV(version: StdLibVersion): Assertion = { - val result = compiler.ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true).explicitGet().compactedSource(version) + val result = compiler + .ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true) + .explicitGet() + .compactedSource(version) result shouldBe s"""{-# STDLIB_VERSION ${version.id} #-} |{-# SCRIPT_TYPE ACCOUNT #-} |{-# CONTENT_TYPE DAPP #-} @@ -122,30 +143,33 @@ class ContractCompilerCompactorTest extends PropSpec { def exprForV(version: StdLibVersion): Expressions.DAPP = { val script = s""" - | {-# STDLIB_VERSION ${version.id} #-} - | {-# CONTENT_TYPE DAPP #-} - | - | func barFunc() = { - | let fooVar = 40 - | fooVar - | } - | - | func bazFunc() = { - | let fooVar = 2 - | fooVar - | } - | - | @Verifier(tx) - | func verify() = { - | barFunc() + bazFunc() == 42 - | } - | + | {-# STDLIB_VERSION ${version.id} #-} + | {-# CONTENT_TYPE DAPP #-} + | + | func barFunc() = { + | let fooVar = 40 + | fooVar + | } + | + | func bazFunc() = { + | let fooVar = 2 + | fooVar + | } + | + | @Verifier(tx) + | func verify() = { + | barFunc() + bazFunc() == 42 + | } + | """.stripMargin Parser.parseContract(script).get.value } def checkForV(version: StdLibVersion): Assertion = { - val result = compiler.ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true).explicitGet().compactedSource(version) + val result = compiler + .ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true) + .explicitGet() + .compactedSource(version) result shouldBe s"""{-# STDLIB_VERSION ${version.id} #-} |{-# SCRIPT_TYPE ACCOUNT #-} |{-# CONTENT_TYPE DAPP #-} @@ -175,23 +199,26 @@ class ContractCompilerCompactorTest extends PropSpec { def exprForV(version: StdLibVersion): Expressions.DAPP = { val script = s""" - | {-# STDLIB_VERSION ${version.id} #-} - | {-# CONTENT_TYPE DAPP #-} - | - | let fooVar = "some value" - | - | @Verifier(tx) - | func verify() = { - | let a = "some value" - | fooVar == a - | } - | + | {-# STDLIB_VERSION ${version.id} #-} + | {-# CONTENT_TYPE DAPP #-} + | + | let fooVar = "some value" + | + | @Verifier(tx) + | func verify() = { + | let a = "some value" + | fooVar == a + | } + | """.stripMargin Parser.parseContract(script).get.value } def checkForV(version: StdLibVersion): Assertion = { - val result = compiler.ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true).explicitGet().compactedSource(version) + val result = compiler + .ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true) + .explicitGet() + .compactedSource(version) result shouldBe s"""{-# STDLIB_VERSION ${version.id} #-} |{-# SCRIPT_TYPE ACCOUNT #-} |{-# CONTENT_TYPE DAPP #-} @@ -214,22 +241,22 @@ class ContractCompilerCompactorTest extends PropSpec { def exprForV(version: StdLibVersion): Expressions.DAPP = { val script = s""" - | {-# STDLIB_VERSION ${version.id} #-} - | {-# CONTENT_TYPE DAPP #-} - | - | let fooVar = 42 - | - | func barFunc(barFuncArg1: Int) = 100500 + barFuncArg1 - | - | @Callable(invocation) - | func bazCallableFunc(bazCallableFuncArg1: Int, bazCallableFuncArg2: String) = { - | let result = barFunc(fooVar) + bazCallableFuncArg1 - | [ - | IntegerEntry("integerEntryKey", result), - | StringEntry("stringEntryKey", bazCallableFuncArg2) - | ] - | } - | + | {-# STDLIB_VERSION ${version.id} #-} + | {-# CONTENT_TYPE DAPP #-} + | + | let fooVar = 42 + | + | func barFunc(barFuncArg1: Int) = 100500 + barFuncArg1 + | + | @Callable(invocation) + | func bazCallableFunc(bazCallableFuncArg1: Int, bazCallableFuncArg2: String) = { + | let result = barFunc(fooVar) + bazCallableFuncArg1 + | [ + | IntegerEntry("integerEntryKey", result), + | StringEntry("stringEntryKey", bazCallableFuncArg2) + | ] + | } + | """.stripMargin Parser.parseContract(script).get.value } @@ -238,7 +265,7 @@ class ContractCompilerCompactorTest extends PropSpec { val compilationCompactedResult = compiler.ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true) val decompactedResult = ContractScriptCompactor.decompact(compilationCompactedResult.explicitGet()) - //noinspection RedundantDefaultArgument + // noinspection RedundantDefaultArgument val compilationResult = compiler.ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = false) decompactedResult shouldBe compilationResult.explicitGet() @@ -305,7 +332,7 @@ class ContractCompilerCompactorTest extends PropSpec { "g" -> "result" ).map(p => CompactNameAndOriginalNamePair(p._1, p._2)) - val compilationNotCompactedResult = compiler.ContractCompiler(ctxForV(V5).compilerContext, expr, V5).explicitGet() + val compilationNotCompactedResult = compiler.ContractCompiler(ctxForV(V5).compilerContext, expr, V5).explicitGet() val compilationCompactedResultNoMeta = compiler.ContractCompiler(ctxForV(V5).compilerContext, compactedExpr, V5).explicitGet() val oldCompactedResult = compilationCompactedResultNoMeta.copy( meta = compilationCompactedResultNoMeta.meta @@ -321,34 +348,37 @@ class ContractCompilerCompactorTest extends PropSpec { def exprForV(version: StdLibVersion): Expressions.DAPP = { val script = s""" - |{-# STDLIB_VERSION ${version.id} #-} - |{-# CONTENT_TYPE DAPP #-} - | - |let varX = 111 - |let varY = 222 - |let varZ = 333 - | - |func func3() = varZ * 444 - |func func2() = 100500 - varY - |func func1() = func2() + 42 - | - |@Callable(i) - |func call() = { - | let tmp1 = func1() + varX - | [IntegerEntry("somekey", tmp1)] - |} - | - |@Verifier(tx) - |func verify() = { - | func2() != varX - |} - | + |{-# STDLIB_VERSION ${version.id} #-} + |{-# CONTENT_TYPE DAPP #-} + | + |let varX = 111 + |let varY = 222 + |let varZ = 333 + | + |func func3() = varZ * 444 + |func func2() = 100500 - varY + |func func1() = func2() + 42 + | + |@Callable(i) + |func call() = { + | let tmp1 = func1() + varX + | [IntegerEntry("somekey", tmp1)] + |} + | + |@Verifier(tx) + |func verify() = { + | func2() != varX + |} + | """.stripMargin Parser.parseContract(script).get.value } def checkForV(version: StdLibVersion): Assertion = { - val result = compiler.ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true, removeUnusedCode = true).explicitGet().compactedSource(version) + val result = compiler + .ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true, removeUnusedCode = true) + .explicitGet() + .compactedSource(version) result shouldBe s"""{-# STDLIB_VERSION ${version.id} #-} |{-# SCRIPT_TYPE ACCOUNT #-} |{-# CONTENT_TYPE DAPP #-} @@ -397,18 +427,18 @@ class ContractCompilerCompactorTest extends PropSpec { def scriptForV(version: StdLibVersion): String = s""" - | {-# STDLIB_VERSION ${version.id} #-} - | {-# CONTENT_TYPE DAPP #-} - | {-# IMPORT lib1,lib2 #-} - | - | @Verifier(tx) - | func verify() = { - | foo() + bar() == 42 - | } + | {-# STDLIB_VERSION ${version.id} #-} + | {-# CONTENT_TYPE DAPP #-} + | {-# IMPORT lib1,lib2 #-} + | + | @Verifier(tx) + | func verify() = { + | foo() + bar() == 42 + | } """.stripMargin def checkForV(version: StdLibVersion): Assertion = { - //noinspection RedundantDefaultArgument + // noinspection RedundantDefaultArgument val compilationResult = for { directives <- DirectiveParser(scriptForV(version)) ds <- Directive.extractDirectives(directives) @@ -418,18 +448,18 @@ class ContractCompilerCompactorTest extends PropSpec { } yield r.compactedSource(version) compilationResult.explicitGet() shouldBe s"""{-# STDLIB_VERSION ${version.id} #-} - |{-# SCRIPT_TYPE ACCOUNT #-} - |{-# CONTENT_TYPE DAPP #-} - |func bar () = 2 - | - | - |func foo () = 40 - | - | - | - |@Verifier(tx) - |func verify () = ((foo() + bar()) == 42) - |""".stripMargin + |{-# SCRIPT_TYPE ACCOUNT #-} + |{-# CONTENT_TYPE DAPP #-} + |func bar () = 2 + | + | + |func foo () = 40 + | + | + | + |@Verifier(tx) + |func verify () = ((foo() + bar()) == 42) + |""".stripMargin } checkForV(V5) @@ -440,22 +470,25 @@ class ContractCompilerCompactorTest extends PropSpec { def exprForV(version: StdLibVersion): Expressions.DAPP = { val script = s"""{-# STDLIB_VERSION ${version.id} #-} - |{-# CONTENT_TYPE DAPP #-} - | - |func a() = true - |func b() = a() - |func bb() = b() - | - |@Callable(i) - |func c() = { - | strict r = bb() - | [] - |}""".stripMargin + |{-# CONTENT_TYPE DAPP #-} + | + |func a() = true + |func b() = a() + |func bb() = b() + | + |@Callable(i) + |func c() = { + | strict r = bb() + | [] + |}""".stripMargin Parser.parseContract(script).get.value } def checkForV(version: StdLibVersion): Assertion = { - val result = compiler.ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true).explicitGet().compactedSource(version) + val result = compiler + .ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true) + .explicitGet() + .compactedSource(version) result shouldBe s"""{-# STDLIB_VERSION ${version.id} #-} |{-# SCRIPT_TYPE ACCOUNT #-} |{-# CONTENT_TYPE DAPP #-} @@ -487,318 +520,321 @@ class ContractCompilerCompactorTest extends PropSpec { def exprForV(version: StdLibVersion): Expressions.DAPP = { val script = s"""{-# STDLIB_VERSION ${version.id} #-} - |{-# CONTENT_TYPE DAPP #-} - | - |${(1 to 100).map("func a" + _ + " () = true").mkString("\n")}""".stripMargin + |{-# CONTENT_TYPE DAPP #-} + | + |${(1 to 100).map("func a" + _ + " () = true").mkString("\n")}""".stripMargin Parser.parseContract(script).get.value } def checkForV(version: StdLibVersion): Assertion = { - val result = compiler.ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true).explicitGet().compactedSource(version) + val result = compiler + .ContractCompiler(ctxForV(version).compilerContext, exprForV(version), version, needCompaction = true) + .explicitGet() + .compactedSource(version) result shouldBe s"""{-# STDLIB_VERSION ${version.id} #-} - |{-# SCRIPT_TYPE ACCOUNT #-} - |{-# CONTENT_TYPE DAPP #-} - |func a () = true - | - | - |func b () = true - | - | - |func c () = true - | - | - |func d () = true - | - | - |func e () = true - | - | - |func f () = true - | - | - |func g () = true - | - | - |func h () = true - | - | - |func i () = true - | - | - |func j () = true - | - | - |func k () = true - | - | - |func l () = true - | - | - |func m () = true - | - | - |func n () = true - | - | - |func o () = true - | - | - |func p () = true - | - | - |func q () = true - | - | - |func r () = true - | - | - |func s () = true - | - | - |func t () = true - | - | - |func u () = true - | - | - |func v () = true - | - | - |func w () = true - | - | - |func x () = true - | - | - |func y () = true - | - | - |func z () = true - | - | - |func A () = true - | - | - |func B () = true - | - | - |func C () = true - | - | - |func D () = true - | - | - |func E () = true - | - | - |func F () = true - | - | - |func G () = true - | - | - |func H () = true - | - | - |func I () = true - | - | - |func J () = true - | - | - |func K () = true - | - | - |func L () = true - | - | - |func M () = true - | - | - |func N () = true - | - | - |func O () = true - | - | - |func P () = true - | - | - |func Q () = true - | - | - |func R () = true - | - | - |func S () = true - | - | - |func T () = true - | - | - |func U () = true - | - | - |func V () = true - | - | - |func W () = true - | - | - |func X () = true - | - | - |func Y () = true - | - | - |func Z () = true - | - | - |func aa () = true - | - | - |func ab () = true - | - | - |func ac () = true - | - | - |func ad () = true - | - | - |func ae () = true - | - | - |func af () = true - | - | - |func ag () = true - | - | - |func ah () = true - | - | - |func ai () = true - | - | - |func aj () = true - | - | - |func ak () = true - | - | - |func al () = true - | - | - |func am () = true - | - | - |func an () = true - | - | - |func ao () = true - | - | - |func ap () = true - | - | - |func aq () = true - | - | - |func ar () = true - | - | - |func as () = true - | - | - |func at () = true - | - | - |func au () = true - | - | - |func av () = true - | - | - |func aw () = true - | - | - |func ax () = true - | - | - |func ay () = true - | - | - |func az () = true - | - | - |func aA () = true - | - | - |func aB () = true - | - | - |func aC () = true - | - | - |func aD () = true - | - | - |func aE () = true - | - | - |func aF () = true - | - | - |func aG () = true - | - | - |func aH () = true - | - | - |func aI () = true - | - | - |func aJ () = true - | - | - |func aK () = true - | - | - |func aL () = true - | - | - |func aM () = true - | - | - |func aN () = true - | - | - |func aO () = true - | - | - |func aP () = true - | - | - |func aQ () = true - | - | - |func aR () = true - | - | - |func aS () = true - | - | - |func aT () = true - | - | - |func aU () = true - | - | - |func aV () = true - | - | - |""".stripMargin + |{-# SCRIPT_TYPE ACCOUNT #-} + |{-# CONTENT_TYPE DAPP #-} + |func a () = true + | + | + |func b () = true + | + | + |func c () = true + | + | + |func d () = true + | + | + |func e () = true + | + | + |func f () = true + | + | + |func g () = true + | + | + |func h () = true + | + | + |func i () = true + | + | + |func j () = true + | + | + |func k () = true + | + | + |func l () = true + | + | + |func m () = true + | + | + |func n () = true + | + | + |func o () = true + | + | + |func p () = true + | + | + |func q () = true + | + | + |func r () = true + | + | + |func s () = true + | + | + |func t () = true + | + | + |func u () = true + | + | + |func v () = true + | + | + |func w () = true + | + | + |func x () = true + | + | + |func y () = true + | + | + |func z () = true + | + | + |func A () = true + | + | + |func B () = true + | + | + |func C () = true + | + | + |func D () = true + | + | + |func E () = true + | + | + |func F () = true + | + | + |func G () = true + | + | + |func H () = true + | + | + |func I () = true + | + | + |func J () = true + | + | + |func K () = true + | + | + |func L () = true + | + | + |func M () = true + | + | + |func N () = true + | + | + |func O () = true + | + | + |func P () = true + | + | + |func Q () = true + | + | + |func R () = true + | + | + |func S () = true + | + | + |func T () = true + | + | + |func U () = true + | + | + |func V () = true + | + | + |func W () = true + | + | + |func X () = true + | + | + |func Y () = true + | + | + |func Z () = true + | + | + |func aa () = true + | + | + |func ab () = true + | + | + |func ac () = true + | + | + |func ad () = true + | + | + |func ae () = true + | + | + |func af () = true + | + | + |func ag () = true + | + | + |func ah () = true + | + | + |func ai () = true + | + | + |func aj () = true + | + | + |func ak () = true + | + | + |func al () = true + | + | + |func am () = true + | + | + |func an () = true + | + | + |func ao () = true + | + | + |func ap () = true + | + | + |func aq () = true + | + | + |func ar () = true + | + | + |func as () = true + | + | + |func at () = true + | + | + |func au () = true + | + | + |func av () = true + | + | + |func aw () = true + | + | + |func ax () = true + | + | + |func ay () = true + | + | + |func az () = true + | + | + |func aA () = true + | + | + |func aB () = true + | + | + |func aC () = true + | + | + |func aD () = true + | + | + |func aE () = true + | + | + |func aF () = true + | + | + |func aG () = true + | + | + |func aH () = true + | + | + |func aI () = true + | + | + |func aJ () = true + | + | + |func aK () = true + | + | + |func aL () = true + | + | + |func aM () = true + | + | + |func aN () = true + | + | + |func aO () = true + | + | + |func aP () = true + | + | + |func aQ () = true + | + | + |func aR () = true + | + | + |func aS () = true + | + | + |func aT () = true + | + | + |func aU () = true + | + | + |func aV () = true + | + | + |""".stripMargin } checkForV(V5) @@ -820,4 +856,89 @@ class ContractCompilerCompactorTest extends PropSpec { ) compiled.explicitGet().decs.map(_.name) shouldBe List("user") } + + property("compaction should work correctly with global variables") { + def script(varName: String): String = + s""" + |{-# STDLIB_VERSION 6 #-} + |{-# CONTENT_TYPE DAPP #-} + |{-# SCRIPT_TYPE ACCOUNT #-} + | + |func f($varName: Any) = $varName + | + |@Callable(i) + |func e() = { + | ( [], f($varName) ) + |} + """.stripMargin + + GlobalValNames.All.foreach { globalName => + val expr = Parser.parseContract(script(globalName)).get.value + val dApp = compiler.ContractCompiler(fullCtxForV(V6).compilerContext, expr, V6, needCompaction = true).explicitGet() + dApp.compactedSource(V6) shouldBe + s"""{-# STDLIB_VERSION 6 #-} + |{-# SCRIPT_TYPE ACCOUNT #-} + |{-# CONTENT_TYPE DAPP #-} + |func a (b) = b + | + | + |@Callable(c) + |func e () = $$Tuple2(nil, a($globalName)) + | + |""".stripMargin + + ContractScriptCompactor.decompact(dApp) shouldBe compiler.ContractCompiler(fullCtxForV(V6).compilerContext, expr, V6).explicitGet() + } + } + + property("compaction should work correctly with global user functions") { + val globalUserFunctions = + fullCtxForV(V6).functions + .filter(f => f.header.isInstanceOf[User] && f.name.head.isLetter) + .map { func => + func.name -> func.signature.args.map { case (_, tp) => + tp match { + case PARAMETERIZEDLIST(_) | LIST(_) => "nil" + case ANY | BIGINT | LONG | _: PARAMETERIZED => "1" + case STRING => "\"1\"" + case BOOLEAN => "true" + case UNION(types, _) if types.contains(Down.`type`) => "DOWN" + case UNION(types, _) if types.contains(Types.aliasType) => "Alias(\"123\")" + case _ => ??? + } + } + } + + def script(funcName: String, funcArgs: Seq[String]): String = + s""" + |{-# STDLIB_VERSION 6 #-} + |{-# CONTENT_TYPE DAPP #-} + |{-# SCRIPT_TYPE ACCOUNT #-} + | + |func f($funcName: Any) = $funcName + | + |@Callable(i) + |func e() = { + | ( [], $funcName(${funcArgs.mkString(",")}) ) + |} + """.stripMargin + + globalUserFunctions.foreach { case (funcName, args) => + val expr = Parser.parseContract(script(funcName, args)).get.value + val dApp = compiler.ContractCompiler(fullCtxForV(V6).compilerContext, expr, V6, needCompaction = true).explicitGet() + dApp.compactedSource(V6) shouldBe + s"""{-# STDLIB_VERSION 6 #-} + |{-# SCRIPT_TYPE ACCOUNT #-} + |{-# CONTENT_TYPE DAPP #-} + |func a (b) = b + | + | + |@Callable(c) + |func e () = $$Tuple2(nil, $funcName(${args.mkString(", ")})) + | + |""".stripMargin + + ContractScriptCompactor.decompact(dApp) shouldBe compiler.ContractCompiler(fullCtxForV(V6).compilerContext, expr, V6).explicitGet() + } + } } diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerTest.scala index 9df488184bc..600f3229e63 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerTest.scala @@ -16,7 +16,7 @@ import com.wavesplatform.lang.v1.compiler.{CompilerContext, ScriptResultSource, import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 import com.wavesplatform.lang.v1.evaluator.FunctionIds import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.{FieldNames, Types, WavesContext} -import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, PureContext} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, GlobalValNames, PureContext} import com.wavesplatform.lang.v1.parser.Parser import com.wavesplatform.lang.v1.traits.Environment import com.wavesplatform.lang.v1.{ContractLimits, compiler} @@ -108,7 +108,7 @@ class ContractCompilerTest extends PropSpec { FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("a").explicitGet(), REF("a"))), FUNCTION_CALL( Native(1100), - List(FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("sender").explicitGet(), REF("sender0"))), REF("nil")) + List(FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("sender").explicitGet(), REF("sender0"))), REF(GlobalValNames.Nil)) ) ) ) @@ -133,7 +133,7 @@ class ContractCompilerTest extends PropSpec { FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("a").explicitGet(), CONST_STRING("b").explicitGet())), FUNCTION_CALL( Native(1100), - List(FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("sender").explicitGet(), REF("sender0"))), REF("nil")) + List(FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("sender").explicitGet(), REF("sender0"))), REF(GlobalValNames.Nil)) ) ) ) @@ -204,7 +204,7 @@ class ContractCompilerTest extends PropSpec { FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("a").explicitGet(), CONST_STRING("b").explicitGet())), FUNCTION_CALL( Native(1100), - List(FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("sender").explicitGet(), REF("sender0"))), REF("nil")) + List(FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("sender").explicitGet(), REF("sender0"))), REF(GlobalValNames.Nil)) ) ) ) diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/DecompilerTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/DecompilerTest.scala index b7e7aafa5dc..c9d0de0923e 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/DecompilerTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/DecompilerTest.scala @@ -252,7 +252,7 @@ class DecompilerTest extends PropSpec { FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("b").explicitGet(), CONST_LONG(1))), FUNCTION_CALL( Native(1100), - List(FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("sender").explicitGet(), REF("x"))), REF("nil")) + List(FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("sender").explicitGet(), REF("x"))), REF(GlobalValNames.Nil)) ) ) ) @@ -267,7 +267,7 @@ class DecompilerTest extends PropSpec { FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("a").explicitGet(), REF("a"))), FUNCTION_CALL( Native(1100), - List(FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("sender").explicitGet(), REF("x"))), REF("nil")) + List(FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("sender").explicitGet(), REF("x"))), REF(GlobalValNames.Nil)) ) ) ) @@ -415,7 +415,7 @@ class DecompilerTest extends PropSpec { | then 1 | else 2 | ).foo""".stripMargin - val expr4 = FUNCTION_CALL(Native(401), List(IF(TRUE, REF("nil"), REF("nil")), CONST_LONG(0))) + val expr4 = FUNCTION_CALL(Native(401), List(IF(TRUE, REF(GlobalValNames.Nil), REF(GlobalValNames.Nil)), CONST_LONG(0))) Decompiler(expr4, decompilerContextV3) shouldEq """(if (true) | then nil diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ErrorTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ErrorTest.scala index a944ec1a9a6..34180e1189f 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ErrorTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ErrorTest.scala @@ -5,10 +5,11 @@ import com.wavesplatform.lang.Common.multiplierFunction import com.wavesplatform.lang.contract.DApp import com.wavesplatform.lang.directives.values.V5 import com.wavesplatform.lang.v1.compiler.{ExpressionCompiler, TestCompiler} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.lang.v1.parser.BinaryOperation.SUM_OP import com.wavesplatform.lang.v1.parser.Expressions import com.wavesplatform.lang.v1.parser.Expressions.Pos.AnyPos -import com.wavesplatform.test._ +import com.wavesplatform.test.* class ErrorTest extends PropSpec { @@ -17,7 +18,7 @@ class ErrorTest extends PropSpec { errorTests( "can't define LET with the same name as predefined constant" -> "already defined in the scope" -> BLOCK( AnyPos, - LET(AnyPos, PART.VALID(AnyPos, "unit"), CONST_LONG(AnyPos, 2)), + LET(AnyPos, PART.VALID(AnyPos, GlobalValNames.Unit), CONST_LONG(AnyPos, 2)), TRUE(AnyPos) ), "can't define LET with the same name as predefined function" -> "function with this name is already defined" -> BLOCK( @@ -31,7 +32,7 @@ class ErrorTest extends PropSpec { SUM_OP, CONST_LONG(AnyPos, 1) ), - "IF clause must be boolean" -> "Unexpected type, required: Boolean" -> IF(AnyPos, CONST_LONG(AnyPos, 0), TRUE(AnyPos), FALSE(AnyPos)), + "IF clause must be boolean" -> "Unexpected type, required: Boolean" -> IF(AnyPos, CONST_LONG(AnyPos, 0), TRUE(AnyPos), FALSE(AnyPos)), "FUNCTION_CALL with wrong amount of arguments" -> "requires 2 arguments" -> FUNCTION_CALL( AnyPos, PART.VALID(AnyPos, multiplierFunction.name), @@ -129,9 +130,8 @@ class ErrorTest extends PropSpec { "List[Any] | List[Any]" ) - invalidPatternsWithError.foreach { - case (pattern, expectedError) => - createPatternMatchScript(pattern) shouldBe Left(expectedError) + invalidPatternsWithError.foreach { case (pattern, expectedError) => + createPatternMatchScript(pattern) shouldBe Left(expectedError) } validPatterns.foreach { pattern => @@ -156,11 +156,10 @@ class ErrorTest extends PropSpec { |""".stripMargin ) - private def errorTests(exprs: ((String, String), Expressions.EXPR)*): Unit = exprs.foreach { - case ((label, error), input) => - property(s"Error: $label") { - ExpressionCompiler(compilerContext, input) should produce(error) - } + private def errorTests(exprs: ((String, String), Expressions.EXPR)*): Unit = exprs.foreach { case ((label, error), input) => + property(s"Error: $label") { + ExpressionCompiler(compilerContext, input) should produce(error) + } } } diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerV1Test.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerV1Test.scala index 68758b9699e..d2660022d26 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerV1Test.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerV1Test.scala @@ -16,7 +16,7 @@ import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 import com.wavesplatform.lang.v1.evaluator.FunctionIds import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext.* import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.WavesContext -import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, PureContext} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, GlobalValNames, PureContext} import com.wavesplatform.lang.v1.parser.BinaryOperation.SUM_OP import com.wavesplatform.lang.v1.parser.Expressions.Pos import com.wavesplatform.lang.v1.parser.Expressions.Pos.AnyPos @@ -594,7 +594,10 @@ class ExpressionCompilerV1Test extends PropSpec { CONST_LONG(1), FUNCTION_CALL( Native(1100), - List(CONST_LONG(2), FUNCTION_CALL(Native(1100), List(CONST_LONG(3), FUNCTION_CALL(Native(1100), List(CONST_LONG(4), REF("nil")))))) + List( + CONST_LONG(2), + FUNCTION_CALL(Native(1100), List(CONST_LONG(3), FUNCTION_CALL(Native(1100), List(CONST_LONG(4), REF(GlobalValNames.Nil))))) + ) ), CONST_LONG(5) ) @@ -777,10 +780,10 @@ class ExpressionCompilerV1Test extends PropSpec { expr = Expressions.FUNCTION_CALL( AnyPos, Expressions.PART.VALID(AnyPos, idOptionLong.name), - List(Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, "unit"))) + List(Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, GlobalValNames.Unit))) ), expectedResult = { res: Either[String, (EXPR, TYPE)] => - res shouldBe Right((FUNCTION_CALL(idOptionLong.header, List(REF("unit"))), UNIT)) + res shouldBe Right((FUNCTION_CALL(idOptionLong.header, List(REF(GlobalValNames.Unit))), UNIT)) } ) @@ -1129,7 +1132,7 @@ class ExpressionCompilerV1Test extends PropSpec { FunctionHeader.Native(1100), List( CONST_STRING("").explicitGet(), - REF("nil") + REF(GlobalValNames.Nil) ) ) ) diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerWithParserV2Test.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerWithParserV2Test.scala index d285de2a361..224fd0c8ab4 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerWithParserV2Test.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerWithParserV2Test.scala @@ -169,7 +169,7 @@ class ExpressionCompilerWithParserV2Test extends PropSpec { PART.VALID(AnyPos, "cons"), List( CONST_BYTESTR(AnyPos, PART.VALID(AnyPos, ByteStr(Array())), Some(BYTESTR), None), - REF(AnyPos, PART.VALID(AnyPos, "nil"), Some(LIST(NOTHING)), None) + REF(AnyPos, PART.VALID(AnyPos, GlobalValNames.Nil), Some(LIST(NOTHING)), None) ), Some(LIST(BYTESTR)), None diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorV3Test.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorV3Test.scala index d21993a9519..55878dbcf7d 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorV3Test.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorV3Test.scala @@ -8,6 +8,7 @@ import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.Types.CASETYPEREF import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 import com.wavesplatform.lang.v1.evaluator.FunctionIds +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.test.* import scala.collection.immutable.ArraySeq @@ -62,11 +63,11 @@ class ScriptEstimatorV3Test cost(cond) = cost(h) + cost(f) + cost(g) + 2 = 15 cost(then) = cost(h) + cost(f) + cost(g) + 2 = 15 cost(else) = cost(h) + cost(f) + cost(g) + 3 = 16 - */ + */ estimateNoOverhead(script) shouldBe Right( - 15 /* cond */ + - 16 /* else */ + - 1 /* b */ + 15 /* cond */ + + 16 /* else */ + + 1 /* b */ ) } @@ -104,13 +105,13 @@ class ScriptEstimatorV3Test estimateNoOverhead(script) shouldBe Right( 1 /* a == b condition */ + - 2 /* d + y + 1 expr inside else block */ + - 0 /* let y decl inside else block */ + - 1 /* let a decl used in condition */ + - 0 /* let b decl used in condition */ + - 3 /* let c decl used in then */ + - 0 /* let d decl used in else */ + - 0 /* let e unused decl */ + 2 /* d + y + 1 expr inside else block */ + + 0 /* let y decl inside else block */ + + 1 /* let a decl used in condition */ + + 0 /* let b decl used in condition */ + + 3 /* let c decl used in then */ + + 0 /* let d decl used in else */ + + 0 /* let e unused decl */ ) } @@ -118,9 +119,9 @@ class ScriptEstimatorV3Test val n = 750 val script = s""" - | func f0() = 0 - | ${(0 until n).map(i => s"func f${i + 1}() = if (true) then f$i() else f$i()").mkString("\n")} - | f$n() + | func f0() = 0 + | ${(0 until n).map(i => s"func f${i + 1}() = if (true) then f$i() else f$i()").mkString("\n")} + | f$n() """.stripMargin /* @@ -128,13 +129,13 @@ class ScriptEstimatorV3Test cost(f1) = cost(cond) + cost(true) + cost(f0) = 1 + 1 + 1 = 1 * 2 + 1 cost(f2) = cost(cond) + cost(true) + cost(f1) = 1 + 1 + 3 = 2 * 2 + 1 cost(fn) = n * 2 + 1 - */ + */ estimate(script) shouldBe Right(n * 2 + 1) /* cost(f0) = 1 cost(fn) = 1 - */ + */ estimateNoOverhead(script) shouldBe Right(1) } @@ -185,7 +186,7 @@ class ScriptEstimatorV3Test ) estimateNoOverhead(script) shouldBe Right( - 0 /* let a */ + + 0 /* let a */ + 0 /* let b */ + 1 /* a == 1 condition */ + 1 /* a > 1 condition */ + @@ -238,8 +239,8 @@ class ScriptEstimatorV3Test List( CaseObj(CASETYPEREF("Address", Nil), Map()), CONST_STRING("default").explicitGet(), - REF("nil"), - REF("nil") + REF(GlobalValNames.Nil), + REF(GlobalValNames.Nil) ) ) estimate(functionCosts(V5), expr(FunctionIds.CALLDAPP)) should produce("not found") diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala index b6c5e88dbcf..61bfbed6f7c 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala @@ -976,7 +976,7 @@ class EvaluatorV1V2Test extends PropSpec with EitherValues { eval[CONST_BOOLEAN]( defaultFullContext.evaluationContext(environment), - FUNCTION_CALL(FunctionHeader.Native(EQ), List(term, REF("unit"))) + FUNCTION_CALL(FunctionHeader.Native(EQ), List(term, REF(GlobalValNames.Unit))) ) shouldBe evaluated(false) } @@ -1112,7 +1112,7 @@ class EvaluatorV1V2Test extends PropSpec with EitherValues { evalToBytes(toBytesBoolean, TRUE) shouldBe evaluated(ByteStr.fromBytes(1)) evalToBytes(toBytesBoolean, FALSE) shouldBe evaluated(ByteStr.fromBytes(0)) - evalToBytes(toStringBoolean, REF("unit")) should produce("Can't apply (CaseObj) to 'toString(b: Boolean)'") + evalToBytes(toStringBoolean, REF(GlobalValNames.Unit)) should produce("Can't apply (CaseObj) to 'toString(b: Boolean)'") forAll(Gen.choose(Long.MinValue, Long.MaxValue), Gen.alphaNumStr) { (n, s) => evalToBytes(toBytesLong, CONST_LONG(n)) shouldBe evaluated(ByteStr(ByteBuffer.allocate(8).putLong(n).array)) diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/string/MakeStringTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/string/MakeStringTest.scala index 4bd0daee6e8..b2b2c9f9ec2 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/string/MakeStringTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/string/MakeStringTest.scala @@ -7,7 +7,7 @@ import com.wavesplatform.lang.evaluator.EvaluatorSpec import com.wavesplatform.lang.v1.FunctionHeader.Native import com.wavesplatform.lang.v1.compiler.Terms.{CONST_BOOLEAN, CONST_BYTESTR, CONST_LONG, CONST_STRING, EXPR, FUNCTION_CALL, REF} import com.wavesplatform.lang.v1.evaluator.FunctionIds -import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext +import com.wavesplatform.lang.v1.evaluator.ctx.impl.{GlobalValNames, PureContext} import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext.MaxListLengthV4 import com.wavesplatform.test.produce @@ -25,7 +25,7 @@ class MakeStringTest extends EvaluatorSpec { property("makeString rejects non-string types in V6") { def mkConsList(values: List[EXPR]): EXPR = values match { case Nil => - REF("nil") + REF(GlobalValNames.Nil) case value :: rest => FUNCTION_CALL( diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/parser/UnderscoreTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/parser/UnderscoreTest.scala index 7f1d9cd68ee..1e0f1f281c0 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/parser/UnderscoreTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/parser/UnderscoreTest.scala @@ -6,7 +6,7 @@ import com.wavesplatform.lang.utils.* import com.wavesplatform.lang.v1.FunctionHeader.{Native, User} import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.{Decompiler, ExpressionCompiler} -import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext +import com.wavesplatform.lang.v1.evaluator.ctx.impl.{GlobalValNames, PureContext} import com.wavesplatform.test.{PropSpec, *} class UnderscoreTest extends PropSpec { @@ -103,7 +103,7 @@ class UnderscoreTest extends PropSpec { Native(1100), List( CONST_LONG(3), - FUNCTION_CALL(Native(1100), List(CONST_LONG(4), FUNCTION_CALL(Native(1100), List(CONST_LONG(5), REF("nil"))))) + FUNCTION_CALL(Native(1100), List(CONST_LONG(4), FUNCTION_CALL(Native(1100), List(CONST_LONG(5), REF(GlobalValNames.Nil))))) ) ) ) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/BigIntInvokeTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/BigIntInvokeTest.scala index 5649802e226..10c58af5b34 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/BigIntInvokeTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/BigIntInvokeTest.scala @@ -16,6 +16,7 @@ import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.lang.v1.evaluator.FunctionIds import com.wavesplatform.lang.v1.evaluator.FunctionIds.TO_BIGINT +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.protobuf.dapp.DAppMeta import com.wavesplatform.test.* import com.wavesplatform.transaction.TxHelpers @@ -40,7 +41,7 @@ class BigIntInvokeTest extends PropSpec with Inside with WithState with DBCacheS Nil, FUNCTION_CALL( FunctionHeader.Native(FunctionIds.CREATE_LIST), - List(action(FUNCTION_CALL(Native(TO_BIGINT), List(CONST_LONG(bigIntValue)))), REF("nil")) + List(action(FUNCTION_CALL(Native(TO_BIGINT), List(CONST_LONG(bigIntValue)))), REF(GlobalValNames.Nil)) ) ) ) @@ -54,13 +55,12 @@ class BigIntInvokeTest extends PropSpec with Inside with WithState with DBCacheS val dAppAcc = TxHelpers.signer(0) val invoker = TxHelpers.signer(1) - testDomain(AddrWithBalance.enoughBalances(dAppAcc, invoker), from = V5) { - case (version, d) => - val setScript = TxHelpers.setScript(dAppAcc, dApp(action, version)) - val invoke = TxHelpers.invoke(dAppAcc.toAddress, func = None, invoker = invoker) + testDomain(AddrWithBalance.enoughBalances(dAppAcc, invoker), from = V5) { case (version, d) => + val setScript = TxHelpers.setScript(dAppAcc, dApp(action, version)) + val invoke = TxHelpers.invoke(dAppAcc.toAddress, func = None, invoker = invoker) - d.appendBlock(setScript) - d.appendBlockE(invoke) should produce(message) + d.appendBlock(setScript) + d.appendBlockE(invoke) should produce(message) } } @@ -81,7 +81,7 @@ class BigIntInvokeTest extends PropSpec with Inside with WithState with DBCacheS val transfer: EXPR => FUNCTION_CALL = { expr => FUNCTION_CALL( FunctionHeader.User("ScriptTransfer"), - List(FUNCTION_CALL(FunctionHeader.User("Address"), List(CONST_BYTESTR(ByteStr.empty).explicitGet())), expr, REF("unit")) + List(FUNCTION_CALL(FunctionHeader.User("Address"), List(CONST_BYTESTR(ByteStr.empty).explicitGet())), expr, REF(GlobalValNames.Unit)) ) } @@ -136,21 +136,20 @@ class BigIntInvokeTest extends PropSpec with Inside with WithState with DBCacheS val invoke = TxHelpers.invoke(dAppAcc1.toAddress, func = Some("default"), invoker = dAppAcc1) - testDomain(from = V5) { - case (version, d) => - val preparingTxs = Seq( - TxHelpers.genesis(dAppAcc1.toAddress), - TxHelpers.genesis(dAppAcc2.toAddress), - TxHelpers.setScript(dAppAcc1, dApp1(dAppAcc2.toAddress, version)), - TxHelpers.setScript(dAppAcc2, dApp2(version)) - ) + testDomain(from = V5) { case (version, d) => + val preparingTxs = Seq( + TxHelpers.genesis(dAppAcc1.toAddress), + TxHelpers.genesis(dAppAcc2.toAddress), + TxHelpers.setScript(dAppAcc1, dApp1(dAppAcc2.toAddress, version)), + TxHelpers.setScript(dAppAcc2, dApp2(version)) + ) - d.appendBlock(preparingTxs*) - d.appendBlock(invoke) + d.appendBlock(preparingTxs*) + d.appendBlock(invoke) - d.liquidDiff.errorMessage(invoke.id()) shouldBe None - d.liquidDiff.scriptsRun shouldBe 2 - d.liquidDiff.accountData.head._2.data("key").value shouldBe 1 + d.liquidDiff.errorMessage(invoke.id()) shouldBe None + d.liquidDiff.scriptsRun shouldBe 2 + d.liquidDiff.accountData.head._2.data("key").value shouldBe 1 } } } diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV4DiffTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV4DiffTest.scala index 825e2b8f15f..1b8f289e0c7 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV4DiffTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV4DiffTest.scala @@ -9,6 +9,7 @@ import com.wavesplatform.lagonaki.mocks.TestBlock import com.wavesplatform.lang.directives.values.V4 import com.wavesplatform.lang.script.Script import com.wavesplatform.lang.v1.compiler.TestCompiler +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.state.diffs.* import com.wavesplatform.state.diffs.FeeValidation.FeeConstants import com.wavesplatform.state.diffs.TransactionDiffer.TransactionValidationError @@ -314,7 +315,7 @@ class CallableV4DiffTest extends PropSpec with WithDomain with EitherValues { | let i0 = Issue("SponsoredAsset0", "SponsoredAsset description", 1000000000000000, 2, true, unit, 0) | [ | i0, - | SponsorFee(calculateAssetId(i0), ${minSponsoredAssetFee.getOrElse("unit")}) + | SponsorFee(calculateAssetId(i0), ${minSponsoredAssetFee.getOrElse(GlobalValNames.Unit)}) | ] """.stripMargin ) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppDataEntryTypeTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppDataEntryTypeTest.scala index c281bc7145a..65da578b517 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppDataEntryTypeTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppDataEntryTypeTest.scala @@ -12,6 +12,7 @@ import com.wavesplatform.lang.script.Script import com.wavesplatform.lang.v1.FunctionHeader import com.wavesplatform.lang.v1.compiler.Terms.{CONST_BOOLEAN, CONST_LONG, CONST_STRING, FUNC, FUNCTION_CALL, REF} import com.wavesplatform.lang.v1.evaluator.FunctionIds +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.protobuf.dapp.DAppMeta import com.wavesplatform.settings.TestFunctionalitySettings import com.wavesplatform.test.* @@ -37,7 +38,9 @@ class DAppDataEntryTypeTest BlockchainFeatures.DataTransaction.id -> 0, BlockchainFeatures.BlockReward.id -> 0, BlockchainFeatures.BlockV5.id -> 0 - ), estimatorPreCheckHeight = Int.MaxValue) + ), + estimatorPreCheckHeight = Int.MaxValue + ) private def dApp(constructor: String): Script = { val value = if (constructor == "BooleanEntry") CONST_LONG(1) else CONST_BOOLEAN(true) @@ -59,7 +62,7 @@ class DAppDataEntryTypeTest FunctionHeader.User(constructor), List(CONST_STRING("key").explicitGet(), value) ), - REF("nil") + REF(GlobalValNames.Nil) ) ) ) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppListArgTypesTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppListArgTypesTest.scala index ee086aec369..075a8d3ddfe 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppListArgTypesTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppListArgTypesTest.scala @@ -11,6 +11,7 @@ import com.wavesplatform.lang.script.{ContractScript, Script} import com.wavesplatform.lang.v1.FunctionHeader.User import com.wavesplatform.lang.v1.compiler.Terms.{CONST_STRING, *} import com.wavesplatform.lang.v1.compiler.{TestCompiler, Types} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.protobuf.dapp.DAppMeta import com.wavesplatform.settings.TestFunctionalitySettings import com.wavesplatform.state.diffs.ENOUGH_AMT @@ -43,7 +44,7 @@ class DAppListArgTypesTest extends PropSpec with WithDomain with Inside { property("can't pass list as callable argument before V4 activation") { // precompiled to avoid compilation error - val callable = CallableFunction(CallableAnnotation("i"), FUNC("f", List("args"), REF("nil"))) + val callable = CallableFunction(CallableAnnotation("i"), FUNC("f", List("args"), REF(GlobalValNames.Nil))) val v3DApp = DApp(DAppMeta(), Nil, List(callable), None) val (preparingTxs, invoke, _) = preconditions(ContractScript(V3, v3DApp).explicitGet(), rideList()) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala index 1b9df6da3a5..dcf2d756a75 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala @@ -26,6 +26,7 @@ import com.wavesplatform.lang.v1.compiler.{Terms, TestCompiler} import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 import com.wavesplatform.lang.v1.evaluator.FunctionIds.CREATE_LIST import com.wavesplatform.lang.v1.evaluator.ScriptResultV3 +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.FieldNames import com.wavesplatform.protobuf.dapp.DAppMeta import com.wavesplatform.settings.TestSettings @@ -100,7 +101,7 @@ class InvokeScriptTransactionDiffTest extends PropSpec with WithDomain with DBCa User("DataEntry"), List(CONST_STRING("argument").explicitGet(), CONST_STRING("abcde" * 1024).explicitGet()) ), - REF("nil") + REF(GlobalValNames.Nil) ) else if (emptyData) List( @@ -108,7 +109,7 @@ class InvokeScriptTransactionDiffTest extends PropSpec with WithDomain with DBCa User("DataEntry"), List(CONST_STRING("").explicitGet(), CONST_STRING("abcde").explicitGet()) ), - REF("nil") + REF(GlobalValNames.Nil) ) else List( @@ -117,7 +118,7 @@ class InvokeScriptTransactionDiffTest extends PropSpec with WithDomain with DBCa Native(1100), List( FUNCTION_CALL(User("DataEntry"), List(CONST_STRING("sender").explicitGet(), GETTER(GETTER(REF("i"), "caller"), "bytes"))), - REF("nil") + REF(GlobalValNames.Nil) ) ) ) @@ -164,12 +165,12 @@ class InvokeScriptTransactionDiffTest extends PropSpec with WithDomain with DBCa List( FUNCTION_CALL(User("Address"), List(CONST_BYTESTR(ByteStr(recipientAddress.bytes)).explicitGet())), CONST_LONG(recipientAmount), - a.fold(REF("unit"): EXPR)(asset => CONST_BYTESTR(asset.id).explicitGet()) + a.fold(REF(GlobalValNames.Unit): EXPR)(asset => CONST_BYTESTR(asset.id).explicitGet()) ) ) ) - val payments: EXPR = transfers.foldRight(REF("nil"): EXPR) { case (elem, tail) => + val payments: EXPR = transfers.foldRight(REF(GlobalValNames.Nil): EXPR) { case (elem, tail) => FUNCTION_CALL(Native(CREATE_LIST), List(elem, tail)) } @@ -204,12 +205,12 @@ class InvokeScriptTransactionDiffTest extends PropSpec with WithDomain with DBCa case recipientAddress: Alias => FUNCTION_CALL(User("Alias"), List(CONST_STRING(recipientAddress.name).explicitGet())) }, CONST_LONG(amount), - a.fold(REF("unit"): EXPR)(asset => CONST_BYTESTR(asset.id).explicitGet()) + a.fold(REF(GlobalValNames.Unit): EXPR)(asset => CONST_BYTESTR(asset.id).explicitGet()) ) ) ) - val payments: EXPR = transfers.foldRight(REF("nil"): EXPR) { case (elem, tail) => + val payments: EXPR = transfers.foldRight(REF(GlobalValNames.Nil): EXPR) { case (elem, tail) => FUNCTION_CALL(Native(CREATE_LIST), List(elem, tail)) } @@ -1555,12 +1556,12 @@ class InvokeScriptTransactionDiffTest extends PropSpec with WithDomain with DBCa List( FUNCTION_CALL(User("Address"), List(CONST_BYTESTR(ByteStr(recipientAddress.bytes)).explicitGet())), CONST_LONG(recipientAmount), - a.fold(REF("unit"): EXPR)(asset => CONST_BYTESTR(asset.id).explicitGet()) + a.fold(REF(GlobalValNames.Unit): EXPR)(asset => CONST_BYTESTR(asset.id).explicitGet()) ) ) ) - val payments: EXPR = transfers.foldRight(REF("nil"): EXPR) { case (elem, tail) => + val payments: EXPR = transfers.foldRight(REF(GlobalValNames.Nil): EXPR) { case (elem, tail) => FUNCTION_CALL(Native(CREATE_LIST), List(elem, tail)) } @@ -1599,12 +1600,12 @@ class InvokeScriptTransactionDiffTest extends PropSpec with WithDomain with DBCa case recipientAddress: Alias => FUNCTION_CALL(User("Alias"), List(CONST_STRING(recipientAddress.name).explicitGet())) }, CONST_LONG(recipientAmount), - a.fold(REF("unit"): EXPR)(asset => CONST_BYTESTR(asset.id).explicitGet()) + a.fold(REF(GlobalValNames.Unit): EXPR)(asset => CONST_BYTESTR(asset.id).explicitGet()) ) ) ) - val payments: EXPR = transfers.foldRight(REF("nil"): EXPR) { case (elem, tail) => + val payments: EXPR = transfers.foldRight(REF(GlobalValNames.Nil): EXPR) { case (elem, tail) => FUNCTION_CALL(Native(CREATE_LIST), List(elem, tail)) } diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/ListParamInvokeTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/ListParamInvokeTest.scala index a377e03027f..32924cd74d5 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/ListParamInvokeTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/ListParamInvokeTest.scala @@ -13,6 +13,7 @@ import com.wavesplatform.lang.v1.FunctionHeader.{Native, User} import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.lang.v1.evaluator.FunctionIds +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.protobuf.dapp.DAppMeta import com.wavesplatform.settings.TestFunctionalitySettings import com.wavesplatform.test.{PropSpec, produce} @@ -47,7 +48,7 @@ class ListParamInvokeTest extends PropSpec with WithState with Inside { User("DataEntry"), List(CONST_STRING("entry2").explicitGet(), FUNCTION_CALL(Native(FunctionIds.GET_LIST), List(REF("args"), CONST_LONG(1)))) ), - REF("nil") + REF(GlobalValNames.Nil) ) ) ) @@ -66,10 +67,9 @@ class ListParamInvokeTest extends PropSpec with WithState with Inside { property("pass list args") { val (genesis, setScript, invoke, dAppAddress) = paymentPreconditions(dApp(V4)) - assertDiffAndState(Seq(TestBlock.create(genesis :+ setScript)), TestBlock.create(Seq(invoke)), features(withV4 = true)) { - case (_, blockchain) => - blockchain.accountData(dAppAddress, "entry1").get.value shouldBe "value1" - blockchain.accountData(dAppAddress, "entry2").get.value shouldBe "value2" + assertDiffAndState(Seq(TestBlock.create(genesis :+ setScript)), TestBlock.create(Seq(invoke)), features(withV4 = true)) { case (_, blockchain) => + blockchain.accountData(dAppAddress, "entry1").get.value shouldBe "value1" + blockchain.accountData(dAppAddress, "entry2").get.value shouldBe "value2" } } diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferTest.scala index 2acf87b548f..cb2e3920165 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferTest.scala @@ -10,6 +10,7 @@ import com.wavesplatform.lang.v1.FunctionHeader.{Native, User} import com.wavesplatform.lang.v1.compiler.Terms.{CONST_STRING, FUNC, FUNCTION_CALL, REF} import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.lang.v1.evaluator.FunctionIds.CREATE_LIST +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.protobuf.dapp.DAppMeta import com.wavesplatform.state.diffs.FeeValidation.{FeeConstants, FeeUnit} import com.wavesplatform.test.* @@ -79,9 +80,9 @@ class ScriptTransferTest extends PropSpec with WithDomain { List( FUNCTION_CALL( User("ScriptTransfer"), - List(FUNCTION_CALL(User("Alias"), List(CONST_STRING("alias").explicitGet())), REF("unit")) + List(FUNCTION_CALL(User("Alias"), List(CONST_STRING("alias").explicitGet())), REF(GlobalValNames.Unit)) ), - REF("nil") + REF(GlobalValNames.Nil) ) ) val dApp = diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppListArgTypesTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppListArgTypesTest.scala index 72ff47e4712..07c0e700d69 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppListArgTypesTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppListArgTypesTest.scala @@ -4,14 +4,15 @@ import com.wavesplatform.TransactionGenBase import com.wavesplatform.account.Address import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.db.WithDomain -import com.wavesplatform.features.BlockchainFeatures._ +import com.wavesplatform.features.BlockchainFeatures.* import com.wavesplatform.lang.directives.values.V5 import com.wavesplatform.lang.script.Script import com.wavesplatform.lang.v1.compiler.TestCompiler +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.settings.TestFunctionalitySettings import com.wavesplatform.state.diffs.ENOUGH_AMT import com.wavesplatform.state.diffs.ci.ciFee -import com.wavesplatform.test._ +import com.wavesplatform.test.* import com.wavesplatform.transaction.Asset.Waves import com.wavesplatform.transaction.smart.{InvokeScriptTransaction, SetScriptTransaction} import com.wavesplatform.transaction.utils.Signed @@ -85,7 +86,7 @@ class SyncDAppListArgTypesTest extends PropSpec with WithDomain with Transaction assert(forbidAfterActivation = false, """ [1, "s", true, base58''] """) assert(forbidAfterActivation = false, """ [] """) - assert(forbidAfterActivation = true, "unit") + assert(forbidAfterActivation = true, GlobalValNames.Unit) assert(forbidAfterActivation = true, "toBigInt(1)") assert(forbidAfterActivation = true, "[toBigInt(1)]") assert(forbidAfterActivation = true, "[unit]") diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppPaymentTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppPaymentTest.scala index 73bf28feed9..6ab2f2afed4 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppPaymentTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppPaymentTest.scala @@ -9,6 +9,7 @@ import com.wavesplatform.features.BlockchainFeatures import com.wavesplatform.lang.directives.values.V5 import com.wavesplatform.lang.script.Script import com.wavesplatform.lang.v1.compiler.TestCompiler +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.state.Portfolio import com.wavesplatform.state.diffs.{ENOUGH_AMT, produceRejectOrFailedDiff} import com.wavesplatform.test.* @@ -331,7 +332,7 @@ class SyncDAppPaymentTest extends PropSpec with WithDomain { | @Callable(i) | func default() = { | ${sigVerify(bigComplexity)} - | let asset = ${asset.fold("unit")(a => s"base58'$a'")} + | let asset = ${asset.fold(GlobalValNames.Unit)(a => s"base58'$a'")} | strict r = Address(base58'$dApp').invoke("default", [], [AttachedPayment(asset, $amount)]) | [] | } diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTransferTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTransferTest.scala index 08808fc2856..3b74850d7b7 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTransferTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTransferTest.scala @@ -16,6 +16,7 @@ import com.wavesplatform.lang.v1.FunctionHeader.{Native, User} import com.wavesplatform.lang.v1.compiler.Terms.{CONST_STRING, FUNC, FUNCTION_CALL, REF} import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.lang.v1.evaluator.FunctionIds.CREATE_LIST +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.protobuf.dapp.DAppMeta import com.wavesplatform.state.diffs.produceRejectOrFailedDiff import com.wavesplatform.test.* @@ -262,7 +263,7 @@ class SyncDAppTransferTest extends PropSpec with WithDomain { | @Callable(i) | func bar() = { | ${sigVerify(bigComplexity)} - | let asset = ${asset.fold("unit")(a => s"base58'$a'")} + | let asset = ${asset.fold(GlobalValNames.Unit)(a => s"base58'$a'")} | [ | ScriptTransfer(${recipient.map(addr => s"Address(base58'$addr')").getOrElse("i.caller")}, $amount, asset) | ] @@ -271,7 +272,7 @@ class SyncDAppTransferTest extends PropSpec with WithDomain { | @Callable(i) | func default() = { | ${sigVerify(bigComplexity)} - | let asset = ${asset.fold("unit")(a => s"base58'$a'")} + | let asset = ${asset.fold(GlobalValNames.Unit)(a => s"base58'$a'")} | [ | ScriptTransfer(${recipient.map(addr => s"Address(base58'$addr')").getOrElse("i.caller")}, $amount, asset) | ] @@ -285,9 +286,9 @@ class SyncDAppTransferTest extends PropSpec with WithDomain { List( FUNCTION_CALL( User("ScriptTransfer"), - List(FUNCTION_CALL(User("Alias"), List(CONST_STRING("alias").explicitGet())), REF("unit")) + List(FUNCTION_CALL(User("Alias"), List(CONST_STRING("alias").explicitGet())), REF(GlobalValNames.Unit)) ), - REF("nil") + REF(GlobalValNames.Nil) ) ) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokeTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokeTest.scala index ad3a2cbb6ab..661255b9ef8 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokeTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokeTest.scala @@ -11,6 +11,7 @@ import com.wavesplatform.lang.directives.values.{StdLibVersion, V3, V5} import com.wavesplatform.lang.script.Script import com.wavesplatform.lang.script.v1.ExprScript import com.wavesplatform.lang.v1.compiler.{Terms, TestCompiler} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.lang.v1.traits.domain.AttachedPayments.* import com.wavesplatform.state.Portfolio import com.wavesplatform.state.diffs.ENOUGH_AMT @@ -55,7 +56,8 @@ class EthereumInvokeTest extends PropSpec with WithDomain with EthHelpers { | let feeAssetId = t.feeAssetId == unit | let checkFunc = t.function == "default" | let checkArgs = t.args == [$passingArg] - | let payments = ${if (version > V3) s"t.payments == [$payments]" else s"t.payment == ${if (payments.nonEmpty) payments else "unit"}"} + | let payments = ${if (version > V3) s"t.payments == [$payments]" + else s"t.payment == ${if (payments.nonEmpty) payments else GlobalValNames.Unit}"} | ${assertProvenPart("t", proofs = false)} && dAppAddress && feeAssetId && checkFunc && checkArgs && payments && checkId """.stripMargin } @@ -69,7 +71,7 @@ class EthereumInvokeTest extends PropSpec with WithDomain with EthHelpers { | ${if (syncCall) s""" strict r = invoke(Address(base58'$dAppAddress'), "default", [], []) """ else ""} | let check = | value == $passingArg && - | ${if (version > V3) s"i.payments == [$payments]" else s"i.payment == ${if (payments.nonEmpty) payments else "unit"}"} + | ${if (version > V3) s"i.payments == [$payments]" else s"i.payment == ${if (payments.nonEmpty) payments else GlobalValNames.Unit}"} | | ${if (version > V3) """[ BooleanEntry("check", check) ]""" else """ WriteSet([DataEntry("check", check)]) """} | } diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferSmartTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferSmartTest.scala index 6cd77a858f6..5168ef5a634 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferSmartTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferSmartTest.scala @@ -7,6 +7,7 @@ import com.wavesplatform.db.WithDomain import com.wavesplatform.lang.directives.DirectiveDictionary import com.wavesplatform.lang.directives.values.{StdLibVersion, V3, V6} import com.wavesplatform.lang.v1.compiler.TestCompiler +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.state.Portfolio import com.wavesplatform.state.diffs.ENOUGH_AMT import com.wavesplatform.state.diffs.smart.predef.{assertProvenPart, provenPart} @@ -32,7 +33,7 @@ class EthereumTransferSmartTest extends PropSpec with WithDomain with EthHelpers TestCompiler(version).compileExpression( s""" | let t = $getTx(base58'${tx.id()}').${if (version >= V3) "value" else "extract"}() - | ${if (version >= V3) checkEthTransfer(tx, Some(asset.fold("unit")(id => s"base58'$id'")), recipient) else "t == t"} + | ${if (version >= V3) checkEthTransfer(tx, Some(asset.fold(GlobalValNames.Unit)(id => s"base58'$id'")), recipient) else "t == t"} """.stripMargin ) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/TransactionBindingsTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/TransactionBindingsTest.scala index a6b53155448..926036e5b8d 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/TransactionBindingsTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/TransactionBindingsTest.scala @@ -17,7 +17,7 @@ import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.lang.v1.evaluator.EvaluatorV1 import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.{FieldNames, WavesContext} -import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, PureContext} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, GlobalValNames, PureContext} import com.wavesplatform.lang.v1.parser.Parser import com.wavesplatform.lang.v1.traits.Environment import com.wavesplatform.lang.v1.compiler @@ -344,7 +344,7 @@ class TransactionBindingsTest extends PropSpec with PathMockFactory with EitherV | match tx { | case t : InvokeScriptTransaction => | let paymentAmount = ${Common.fold(size, "t.payments", "0", "assetsAmountSum")()} == ${tx.payments.map(_.amount).sum} - | let paymentAssets = ${Common.fold(size, "t.payments", "nil", "extractAssets")()} == $paymentsStr + | let paymentAssets = ${Common.fold(size, "t.payments", GlobalValNames.Nil, "extractAssets")()} == $paymentsStr | | paymentAmount && paymentAssets | @@ -442,7 +442,7 @@ class TransactionBindingsTest extends PropSpec with PathMockFactory with EitherV | match tx { | case t: InvokeExpressionTransaction => | ${provenPart(tx)} - | let checkFeeAssetId = t.feeAssetId == ${tx.feeAssetId.fold("unit")(a => s"base58'${a.id.toString}'")} + | let checkFeeAssetId = t.feeAssetId == ${tx.feeAssetId.fold(GlobalValNames.Unit)(a => s"base58'${a.id.toString}'")} | let checkExpression = t.expression == base58'${expression.bytes()}' | ${assertProvenPart("t")} && checkFeeAssetId && checkExpression | case _ => throw() @@ -729,7 +729,7 @@ class TransactionBindingsTest extends PropSpec with PathMockFactory with EitherV |match tx { | case o: Order => | let orderType = o.orderType - | orderType == ${if (ord.orderType == OrderType.BUY) "Buy" else "Sell"} + | orderType == ${if (ord.orderType == OrderType.BUY) GlobalValNames.Buy else GlobalValNames.Sell} | case _ => throw() |} """.stripMargin diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityTest.scala b/node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityTest.scala index 8de709864a8..6e5d2cc7ca4 100644 --- a/node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityTest.scala +++ b/node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityTest.scala @@ -4,12 +4,12 @@ import cats.kernel.Monoid import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.lang.directives.DirectiveSet -import com.wavesplatform.lang.directives.values._ +import com.wavesplatform.lang.directives.values.* import com.wavesplatform.lang.v1.FunctionHeader.User -import com.wavesplatform.lang.v1.compiler.Terms._ +import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.estimator.ScriptEstimator -import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves._ -import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, PureContext} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.* +import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, GlobalValNames, PureContext} import com.wavesplatform.lang.v1.traits.Environment import com.wavesplatform.lang.v1.{CTX, FunctionHeader} import com.wavesplatform.lang.{Global, utils} @@ -218,7 +218,7 @@ class UserFunctionComplexityTest(estimator: ScriptEstimator) extends PropSpec { est(exprUNot).explicitGet() shouldBe 2 val exprDataByIndex = LET_BLOCK( - LET("arr", FUNCTION_CALL(PureContext.listConstructor(checkSize = false), List(CONST_STRING("str_1").explicitGet(), REF("nil")))), + LET("arr", FUNCTION_CALL(PureContext.listConstructor(checkSize = false), List(CONST_STRING("str_1").explicitGet(), REF(GlobalValNames.Nil)))), FUNCTION_CALL(User("getString"), List(REF("arr"), CONST_LONG(0))) ) est(exprDataByIndex).explicitGet() shouldBe 43 diff --git a/repl/jvm/src/test/scala/com/wavesplatform/lang/v1/ReplTest.scala b/repl/jvm/src/test/scala/com/wavesplatform/lang/v1/ReplTest.scala index 60e4925a951..15c231615f0 100644 --- a/repl/jvm/src/test/scala/com/wavesplatform/lang/v1/ReplTest.scala +++ b/repl/jvm/src/test/scala/com/wavesplatform/lang/v1/ReplTest.scala @@ -1,6 +1,7 @@ package com.wavesplatform.lang.v1 import cats.Functor +import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.lang.v1.repl.Repl import com.wavesplatform.lang.v1.repl.node.BlockchainUnavailableException import com.wavesplatform.lang.v1.repl.node.http.NodeClient.ResponseWrapper @@ -153,7 +154,7 @@ class ReplTest extends AnyPropSpec with Matchers { val repl = Repl() await(repl.execute("let a = 5")) repl.info("a") shouldBe "let a: Int" - repl.info("unit") shouldBe "let unit: Unit" + repl.info(GlobalValNames.Unit) shouldBe "let unit: Unit" } property("state reassign") {