Fix for passing a stream argument with lambda to a function waiting for a scalar (#420)

This commit is contained in:
Dmitry Kurinskiy 2022-02-06 00:26:07 +03:00 committed by GitHub
parent f311afd760
commit 6d03a0d95b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 109 additions and 3 deletions

9
aqua-src/hack.aqua Normal file
View File

@ -0,0 +1,9 @@
data RelayerSig:
address: string
func send_vote(log: string -> ()):
maybeAck: *RelayerSig
log(maybeAck[0].address)

View File

@ -22,7 +22,7 @@ object Test extends IOApp.Simple {
start <- IO(System.currentTimeMillis())
_ <- AquaPathCompiler
.compileFilesTo[IO](
Path("./aqua-src/"),
Path("./aqua-src/hack.aqua"),
List(Path("./aqua")),
Option(Path("./target")),
TypeScriptBackend,

View File

@ -129,9 +129,11 @@ object ArrowInliner extends Logging {
// @see ArrowInlinerSpec `pass stream to callback properly` test
case v @ VarRaw(name, baseType: BoxType, _) if streamToRename.contains(name) =>
v.copy(baseType = StreamType(baseType.element))
case v: VarRaw if streamToRename.contains(v.name) =>
v.copy(baseType = StreamType(v.baseType))
case v => v
}))
.rename(streamToRename)
.renameExports(streamToRename)
// Function body on its own defines some values; collect their names
// except stream arguments. They should be already renamed

View File

@ -5,6 +5,7 @@ import aqua.model.inline.state.InliningState
import aqua.raw.ops.*
import aqua.raw.value.{IntoFieldRaw, IntoIndexRaw, LiteralRaw, VarRaw}
import aqua.types.*
import cats.syntax.show.*
import cats.data.{Chain, NonEmptyList, NonEmptyMap}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
@ -117,6 +118,95 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
)
) should be(true)
} /*
func stream-callback(cb: string -> ()):
records: *string
cb(records!)
*/
"arrow inliner" should "pass stream to callback properly, holding lambda" in {
val streamType = StreamType(ScalarType.string)
val streamVar = VarRaw("records", streamType)
val streamVarLambda =
VarRaw("records", streamType, Chain(IntoIndexRaw(LiteralRaw.number(0), ScalarType.string)))
val streamModel = VarModel(
"records",
StreamType(ScalarType.string),
Chain.one(IntoIndexModel("0", ScalarType.string))
)
val cbType = ArrowType(ProductType(ScalarType.string :: Nil), ProductType(Nil))
val cbVal = VarModel("cb-pass", cbType)
val cbArg =
VarRaw(
"cbVar",
ScalarType.string
)
val cbArrow = FuncArrow(
"cb",
CallServiceTag(
LiteralRaw.quote("test-service"),
"some-call",
Call(cbArg :: Nil, Nil)
).leaf,
ArrowType(
ProductType.labelled(
(
cbArg.name,
cbArg.`type`
) :: Nil
),
ProductType(Nil)
),
Nil,
Map.empty,
Map.empty
)
val model: OpModel.Tree = ArrowInliner
.callArrow[InliningState](
FuncArrow(
"stream-callback",
RestrictionTag(streamVar.name, true).wrap(
SeqTag.wrap(
DeclareStreamTag(streamVar).leaf,
CallArrowTag("cb", Call(streamVarLambda :: Nil, Nil)).leaf
)
),
ArrowType(
ProductType.labelled(
(
"cb",
cbType
) :: Nil
),
ProductType(Nil)
),
Nil,
Map("cb" -> cbArrow),
Map.empty
),
CallModel(cbVal :: Nil, Nil)
)
.run(InliningState())
.value
._2
model.equalsOrShowDiff(
RestrictionModel(streamVar.name, true).wrap(
SeqModel.wrapWithEmpty(
EmptyModel.leaf,
CallServiceModel(
LiteralModel("\"test-service\"", LiteralType.string),
"some-call",
CallModel(streamModel :: Nil, Nil)
).leaf
)
)
) should be(true)
}
/*

View File

@ -66,6 +66,11 @@ trait RawTagGivens {
else
tree.map[RawTag](_.mapValues(_.renameVars(vals)).renameExports(vals))
def renameExports(vals: Map[String, String]): RawTag.Tree =
if (vals.isEmpty) tree
else
tree.map[RawTag](_.renameExports(vals))
def definesVarNames: Eval[Set[String]] =
Cofree.cata[Chain, RawTag, Set[String]](tree) { case (tag, acc) =>
Eval.later(acc.foldLeft(tag.definesVarNames)(_ ++ _))

View File

@ -5,6 +5,7 @@ import aqua.model.ArgsCall
import aqua.raw.ops.{Call, CallArrowTag, FuncOp, RawTag, SeqTag}
import aqua.raw.value.{ValueRaw, VarRaw}
import aqua.types.*
import cats.syntax.show.*
// TODO: doc
case class FuncPreTransformer(
@ -76,7 +77,6 @@ case class FuncPreTransformer(
FuncArrow(
wrapCallableName,
transform(
// TODO wrapNonEmpty?
SeqTag.wrap(
CallArrowTag(func.funcName, funcCall).leaf ::
returnType.headOption