mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 22:50:18 +00:00
fix(compiler): Fix gate inlining [LNG-253] (#924)
* Fix gate inlining * Remake stream gate inlining, fix unit tests * Fix: add flat inline * Refactor, add comments
This commit is contained in:
parent
feb7a167a2
commit
b298eebf5e
@ -1,14 +1,6 @@
|
|||||||
package aqua.compiler
|
package aqua.compiler
|
||||||
|
|
||||||
import aqua.model.{
|
import aqua.model.{CallModel, ForModel, FunctorModel, LiteralModel, ValueModel, VarModel}
|
||||||
CallModel,
|
|
||||||
ForModel,
|
|
||||||
FunctorModel,
|
|
||||||
IntoIndexModel,
|
|
||||||
LiteralModel,
|
|
||||||
ValueModel,
|
|
||||||
VarModel
|
|
||||||
}
|
|
||||||
import aqua.model.transform.ModelBuilder
|
import aqua.model.transform.ModelBuilder
|
||||||
import aqua.model.transform.TransformConfig
|
import aqua.model.transform.TransformConfig
|
||||||
import aqua.model.transform.Transform
|
import aqua.model.transform.Transform
|
||||||
@ -115,8 +107,8 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers {
|
|||||||
|
|
||||||
private val init = LiteralModel.fromRaw(ValueRaw.InitPeerId)
|
private val init = LiteralModel.fromRaw(ValueRaw.InitPeerId)
|
||||||
|
|
||||||
private def join(vm: VarModel, idx: ValueModel) =
|
private def join(vm: VarModel, size: ValueModel) =
|
||||||
ResBuilder.join(vm, idx, init)
|
ResBuilder.join(vm, size, init)
|
||||||
|
|
||||||
"aqua compiler" should "create right topology" in {
|
"aqua compiler" should "create right topology" in {
|
||||||
|
|
||||||
@ -156,6 +148,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers {
|
|||||||
val canonResult = VarModel("-" + results.name + "-fix-0", CanonStreamType(resultsType.element))
|
val canonResult = VarModel("-" + results.name + "-fix-0", CanonStreamType(resultsType.element))
|
||||||
val flatResult = VarModel("-results-flat-0", ArrayType(ScalarType.string))
|
val flatResult = VarModel("-results-flat-0", ArrayType(ScalarType.string))
|
||||||
val initPeer = LiteralModel.fromRaw(ValueRaw.InitPeerId)
|
val initPeer = LiteralModel.fromRaw(ValueRaw.InitPeerId)
|
||||||
|
val sizeVar = VarModel("results_size", LiteralType.unsigned)
|
||||||
val retVar = VarModel("ret", ScalarType.string)
|
val retVar = VarModel("ret", ScalarType.string)
|
||||||
|
|
||||||
val expected =
|
val expected =
|
||||||
@ -195,7 +188,13 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
join(results, LiteralModel.fromRaw(LiteralRaw.number(2))),
|
ResBuilder.add(
|
||||||
|
LiteralModel.number(2),
|
||||||
|
LiteralModel.number(1),
|
||||||
|
sizeVar,
|
||||||
|
initPeer
|
||||||
|
),
|
||||||
|
join(results, sizeVar),
|
||||||
CanonRes(results, init, CallModel.Export(canonResult.name, canonResult.`type`)).leaf,
|
CanonRes(results, init, CallModel.Export(canonResult.name, canonResult.`type`)).leaf,
|
||||||
ApRes(
|
ApRes(
|
||||||
canonResult,
|
canonResult,
|
||||||
|
@ -6,12 +6,12 @@ import aqua.model.*
|
|||||||
import aqua.model.inline.raw.{
|
import aqua.model.inline.raw.{
|
||||||
ApplyBinaryOpRawInliner,
|
ApplyBinaryOpRawInliner,
|
||||||
ApplyFunctorRawInliner,
|
ApplyFunctorRawInliner,
|
||||||
ApplyGateRawInliner,
|
|
||||||
ApplyPropertiesRawInliner,
|
ApplyPropertiesRawInliner,
|
||||||
ApplyUnaryOpRawInliner,
|
ApplyUnaryOpRawInliner,
|
||||||
CallArrowRawInliner,
|
CallArrowRawInliner,
|
||||||
CollectionRawInliner,
|
CollectionRawInliner,
|
||||||
MakeAbilityRawInliner
|
MakeAbilityRawInliner,
|
||||||
|
StreamGateInliner
|
||||||
}
|
}
|
||||||
import aqua.raw.ops.*
|
import aqua.raw.ops.*
|
||||||
import aqua.raw.value.*
|
import aqua.raw.value.*
|
||||||
@ -48,9 +48,6 @@ object RawValueInliner extends Logging {
|
|||||||
case alr: ApplyPropertyRaw =>
|
case alr: ApplyPropertyRaw =>
|
||||||
ApplyPropertiesRawInliner(alr, propertiesAllowed)
|
ApplyPropertiesRawInliner(alr, propertiesAllowed)
|
||||||
|
|
||||||
case agr: ApplyGateRaw =>
|
|
||||||
ApplyGateRawInliner(agr, propertiesAllowed)
|
|
||||||
|
|
||||||
case cr: CollectionRaw =>
|
case cr: CollectionRaw =>
|
||||||
CollectionRawInliner(cr, propertiesAllowed)
|
CollectionRawInliner(cr, propertiesAllowed)
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import cats.syntax.bifunctor.*
|
|||||||
import cats.syntax.foldable.*
|
import cats.syntax.foldable.*
|
||||||
import cats.syntax.monoid.*
|
import cats.syntax.monoid.*
|
||||||
import cats.syntax.traverse.*
|
import cats.syntax.traverse.*
|
||||||
|
import cats.syntax.option.*
|
||||||
import scribe.Logging
|
import scribe.Logging
|
||||||
|
|
||||||
object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Logging {
|
object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Logging {
|
||||||
@ -48,17 +49,6 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def removeProperties[S: Mangler](
|
|
||||||
varModel: VarModel
|
|
||||||
): State[S, (VarModel, Inline)] = {
|
|
||||||
for {
|
|
||||||
nn <- Mangler[S].findAndForbidName(varModel.name + "_flat")
|
|
||||||
} yield {
|
|
||||||
val flatten = VarModel(nn, varModel.`type`)
|
|
||||||
flatten -> Inline.tree(FlattenModel(varModel, flatten.name).leaf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def unfoldAbilityProperty[S: Mangler: Exports: Arrows](
|
private def unfoldAbilityProperty[S: Mangler: Exports: Arrows](
|
||||||
varModel: VarModel,
|
varModel: VarModel,
|
||||||
abilityType: NamedType,
|
abilityType: NamedType,
|
||||||
@ -143,9 +133,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
|
|
||||||
case f @ FunctorRaw(_, _) =>
|
case f @ FunctorRaw(_, _) =>
|
||||||
for {
|
for {
|
||||||
flattenVI <-
|
flattenVI <- removeProperties(varModel)
|
||||||
if (varModel.properties.nonEmpty) removeProperties(varModel)
|
|
||||||
else State.pure(varModel, Inline.empty)
|
|
||||||
(flatten, inline) = flattenVI
|
(flatten, inline) = flattenVI
|
||||||
newVI <- ApplyFunctorRawInliner(flatten, f)
|
newVI <- ApplyFunctorRawInliner(flatten, f)
|
||||||
} yield {
|
} yield {
|
||||||
@ -157,9 +145,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
|
|
||||||
case ic @ IntoCopyRaw(_, _) =>
|
case ic @ IntoCopyRaw(_, _) =>
|
||||||
for {
|
for {
|
||||||
flattenVI <-
|
flattenVI <- removeProperties(varModel)
|
||||||
if (varModel.properties.nonEmpty) removeProperties(varModel)
|
|
||||||
else State.pure(varModel, Inline.empty)
|
|
||||||
(flatten, inline) = flattenVI
|
(flatten, inline) = flattenVI
|
||||||
newVI <- ApplyIntoCopyRawInliner(flatten, ic)
|
newVI <- ApplyIntoCopyRawInliner(flatten, ic)
|
||||||
} yield {
|
} yield {
|
||||||
@ -182,15 +168,31 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
unfold(vr, propertiesAllowed = false).flatMap {
|
unfold(vr, propertiesAllowed = false).flatMap {
|
||||||
case (vm @ VarModel(_, _, _), inline) if vm.properties.nonEmpty =>
|
case (vm @ VarModel(_, _, _), inline) if vm.properties.nonEmpty =>
|
||||||
removeProperties(vm).map { case (vf, inlf) =>
|
removeProperties(vm).map { case (vf, inlf) =>
|
||||||
PropertyRawWithModel(iir, Option(IntoIndexModel(vf.name, t))) -> Inline(
|
PropertyRawWithModel(
|
||||||
|
iir,
|
||||||
|
IntoIndexModel
|
||||||
|
.fromValueModel(vf, t)
|
||||||
|
.getOrElse(
|
||||||
|
internalError(s"Unexpected: could not convert ($vf) to IntoIndexModel")
|
||||||
|
)
|
||||||
|
.some
|
||||||
|
) -> Inline(
|
||||||
inline.predo ++ inlf.predo,
|
inline.predo ++ inlf.predo,
|
||||||
mergeMode = SeqMode
|
mergeMode = SeqMode
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
case (VarModel(name, _, _), inline) =>
|
case (vm, inline) =>
|
||||||
State.pure(PropertyRawWithModel(iir, Option(IntoIndexModel(name, t))) -> inline)
|
(
|
||||||
case (LiteralModel(literal, _), inline) =>
|
PropertyRawWithModel(
|
||||||
State.pure(PropertyRawWithModel(iir, Option(IntoIndexModel(literal, t))) -> inline)
|
iir,
|
||||||
|
IntoIndexModel
|
||||||
|
.fromValueModel(vm, t)
|
||||||
|
.getOrElse(
|
||||||
|
internalError(s"Unexpected: could not convert ($vm) to IntoIndexModel")
|
||||||
|
)
|
||||||
|
.some
|
||||||
|
) -> inline
|
||||||
|
).pure
|
||||||
}
|
}
|
||||||
|
|
||||||
case p => State.pure(PropertyRawWithModel(p, None) -> Inline.empty)
|
case p => State.pure(PropertyRawWithModel(p, None) -> Inline.empty)
|
||||||
@ -246,31 +248,88 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unfold `stream[idx]`
|
||||||
|
*/
|
||||||
|
private def unfoldStreamGate[S: Mangler: Exports: Arrows](
|
||||||
|
streamName: String,
|
||||||
|
streamType: StreamType,
|
||||||
|
idx: ValueRaw
|
||||||
|
): State[S, (VarModel, Inline)] = for {
|
||||||
|
/**
|
||||||
|
* Inline idx
|
||||||
|
*/
|
||||||
|
idxInlined <- unfold(idx)
|
||||||
|
(idxVM, idxInline) = idxInlined
|
||||||
|
/**
|
||||||
|
* Inline size which is `idx + 1`
|
||||||
|
* TODO: Refactor to apply optimizations
|
||||||
|
*/
|
||||||
|
sizeName <- Mangler[S].findAndForbidName(s"${streamName}_size")
|
||||||
|
sizeVar = VarModel(sizeName, idxVM.`type`)
|
||||||
|
sizeInline = CallServiceModel(
|
||||||
|
"math",
|
||||||
|
funcName = "add",
|
||||||
|
args = List(idxVM, LiteralModel.number(1)),
|
||||||
|
result = sizeVar
|
||||||
|
).leaf
|
||||||
|
gateInlined <- StreamGateInliner(streamName, streamType, sizeVar)
|
||||||
|
(gateVM, gateInline) = gateInlined
|
||||||
|
/**
|
||||||
|
* Remove properties from idx
|
||||||
|
* as we need to use it in index
|
||||||
|
* TODO: Do not generate it
|
||||||
|
* if it is not needed,
|
||||||
|
* e.g. in `join`
|
||||||
|
*/
|
||||||
|
idxFlattened <- idxVM match {
|
||||||
|
case vr: VarModel => removeProperties(vr)
|
||||||
|
case _ => (idxVM, Inline.empty).pure[State[S, *]]
|
||||||
|
}
|
||||||
|
(idxFlat, idxFlatInline) = idxFlattened
|
||||||
|
/**
|
||||||
|
* Construct stream[idx]
|
||||||
|
*/
|
||||||
|
gate = gateVM.withProperty(
|
||||||
|
IntoIndexModel
|
||||||
|
.fromValueModel(idxFlat, streamType.element)
|
||||||
|
.getOrElse(
|
||||||
|
internalError(s"Unexpected: could not convert ($idxFlat) to IntoIndexModel")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} yield gate -> Inline(
|
||||||
|
idxInline.predo
|
||||||
|
.append(sizeInline) ++
|
||||||
|
gateInline.predo ++
|
||||||
|
idxFlatInline.predo,
|
||||||
|
mergeMode = SeqMode
|
||||||
|
)
|
||||||
|
|
||||||
private def unfoldRawWithProperties[S: Mangler: Exports: Arrows](
|
private def unfoldRawWithProperties[S: Mangler: Exports: Arrows](
|
||||||
raw: ValueRaw,
|
raw: ValueRaw,
|
||||||
properties: Chain[PropertyRaw],
|
properties: Chain[PropertyRaw],
|
||||||
propertiesAllowed: Boolean
|
propertiesAllowed: Boolean
|
||||||
): State[S, (ValueModel, Inline)] = {
|
): State[S, (ValueModel, Inline)] = {
|
||||||
((raw, properties.headOption) match {
|
((raw, properties.uncons) match {
|
||||||
case (vr @ VarRaw(_, st @ StreamType(_)), Some(IntoIndexRaw(idx, _))) =>
|
/**
|
||||||
|
* To inline
|
||||||
|
*/
|
||||||
|
case (
|
||||||
|
vr @ VarRaw(_, st @ StreamType(_)),
|
||||||
|
Some(IntoIndexRaw(idx, _), otherProperties)
|
||||||
|
) =>
|
||||||
unfold(vr).flatMap {
|
unfold(vr).flatMap {
|
||||||
case (VarModel(nameVM, _, _), inl) =>
|
case (VarModel(nameVM, _, _), inl) =>
|
||||||
val gateRaw = ApplyGateRaw(nameVM, st, idx)
|
for {
|
||||||
unfold(gateRaw).flatMap {
|
gateInlined <- unfoldStreamGate(nameVM, st, idx)
|
||||||
case (gateResVal: VarModel, gateResInline) =>
|
(gateVM, gateInline) = gateInlined
|
||||||
unfoldProperties(gateResInline, gateResVal, properties, propertiesAllowed).map {
|
propsInlined <- unfoldProperties(
|
||||||
case (v, i) =>
|
gateInline,
|
||||||
v -> Inline(
|
gateVM,
|
||||||
inl.predo ++ i.predo,
|
otherProperties,
|
||||||
mergeMode = SeqMode
|
propertiesAllowed
|
||||||
)
|
)
|
||||||
}
|
} yield propsInlined
|
||||||
case (v, i) =>
|
|
||||||
// what if pass nil as stream argument?
|
|
||||||
internalError(
|
|
||||||
s"Unfolded stream ($gateRaw) cannot be a literal"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
case l =>
|
case l =>
|
||||||
internalError(
|
internalError(
|
||||||
s"Unfolded stream ($vr) cannot be a literal"
|
s"Unfolded stream ($vr) cannot be a literal"
|
||||||
@ -299,6 +358,19 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove properties from the var and return a new var without them
|
||||||
|
*/
|
||||||
|
private def removeProperties[S: Mangler](
|
||||||
|
varModel: VarModel
|
||||||
|
): State[S, (VarModel, Inline)] =
|
||||||
|
if (varModel.properties.isEmpty) (varModel, Inline.empty).pure
|
||||||
|
else
|
||||||
|
for {
|
||||||
|
nn <- Mangler[S].findAndForbidName(varModel.name + "_flat")
|
||||||
|
flatten = VarModel(nn, varModel.`type`)
|
||||||
|
} yield flatten -> Inline.tree(FlattenModel(varModel, flatten.name).leaf)
|
||||||
|
|
||||||
override def apply[S: Mangler: Exports: Arrows](
|
override def apply[S: Mangler: Exports: Arrows](
|
||||||
apr: ApplyPropertyRaw,
|
apr: ApplyPropertyRaw,
|
||||||
propertiesAllowed: Boolean
|
propertiesAllowed: Boolean
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package aqua.model.inline.raw
|
package aqua.model.inline.raw
|
||||||
|
|
||||||
|
import aqua.errors.Errors.internalError
|
||||||
import aqua.model.*
|
import aqua.model.*
|
||||||
import aqua.model.inline.Inline
|
import aqua.model.inline.Inline
|
||||||
import aqua.model.inline.state.{Arrows, Exports, Mangler}
|
import aqua.model.inline.state.{Arrows, Exports, Mangler}
|
||||||
import aqua.raw.value.{ApplyGateRaw, LiteralRaw, VarRaw}
|
import aqua.raw.value.{LiteralRaw, VarRaw}
|
||||||
import aqua.model.inline.RawValueInliner.unfold
|
import aqua.model.inline.RawValueInliner.unfold
|
||||||
import aqua.types.{ArrayType, CanonStreamType, ScalarType, StreamType}
|
import aqua.types.{ArrayType, CanonStreamType, ScalarType, StreamType}
|
||||||
|
|
||||||
@ -11,16 +12,17 @@ import cats.data.State
|
|||||||
import cats.data.Chain
|
import cats.data.Chain
|
||||||
import cats.syntax.monoid.*
|
import cats.syntax.monoid.*
|
||||||
import cats.syntax.option.*
|
import cats.syntax.option.*
|
||||||
|
import cats.syntax.applicative.*
|
||||||
import scribe.Logging
|
import scribe.Logging
|
||||||
|
import cats.instances.stream
|
||||||
|
|
||||||
object ApplyGateRawInliner extends RawInliner[ApplyGateRaw] with Logging {
|
object StreamGateInliner extends Logging {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To wait for the element of a stream by the given index, the following model is generated:
|
* To wait for size elements of a stream,
|
||||||
|
* the following model is generated:
|
||||||
* (seq
|
* (seq
|
||||||
* (seq
|
* (seq
|
||||||
* (seq
|
|
||||||
* (call <peer> ("math" "add") [0 1] stream_incr)
|
|
||||||
* (fold $stream s
|
* (fold $stream s
|
||||||
* (seq
|
* (seq
|
||||||
* (seq
|
* (seq
|
||||||
@ -28,7 +30,7 @@ object ApplyGateRawInliner extends RawInliner[ApplyGateRaw] with Logging {
|
|||||||
* (canon <peer> $stream_test #stream_iter_canon)
|
* (canon <peer> $stream_test #stream_iter_canon)
|
||||||
* )
|
* )
|
||||||
* (xor
|
* (xor
|
||||||
* (match #stream_iter_canon.length stream_incr
|
* (match #stream_iter_canon.length size
|
||||||
* (null)
|
* (null)
|
||||||
* )
|
* )
|
||||||
* (next s)
|
* (next s)
|
||||||
@ -36,7 +38,6 @@ object ApplyGateRawInliner extends RawInliner[ApplyGateRaw] with Logging {
|
|||||||
* )
|
* )
|
||||||
* (never)
|
* (never)
|
||||||
* )
|
* )
|
||||||
* )
|
|
||||||
* (canon <peer> $stream_test #stream_result_canon)
|
* (canon <peer> $stream_test #stream_result_canon)
|
||||||
* )
|
* )
|
||||||
* (ap #stream_result_canon stream_gate)
|
* (ap #stream_result_canon stream_gate)
|
||||||
@ -45,8 +46,7 @@ object ApplyGateRawInliner extends RawInliner[ApplyGateRaw] with Logging {
|
|||||||
def joinStreamOnIndexModel(
|
def joinStreamOnIndexModel(
|
||||||
streamName: String,
|
streamName: String,
|
||||||
streamType: StreamType,
|
streamType: StreamType,
|
||||||
idxModel: ValueModel,
|
sizeModel: ValueModel,
|
||||||
idxIncrName: String,
|
|
||||||
testName: String,
|
testName: String,
|
||||||
iterName: String,
|
iterName: String,
|
||||||
canonName: String,
|
canonName: String,
|
||||||
@ -55,16 +55,10 @@ object ApplyGateRawInliner extends RawInliner[ApplyGateRaw] with Logging {
|
|||||||
): OpModel.Tree = {
|
): OpModel.Tree = {
|
||||||
val varSTest = VarModel(testName, streamType)
|
val varSTest = VarModel(testName, streamType)
|
||||||
val iter = VarModel(iterName, streamType.element)
|
val iter = VarModel(iterName, streamType.element)
|
||||||
|
|
||||||
val iterCanon = VarModel(iterCanonName, CanonStreamType(streamType.element))
|
val iterCanon = VarModel(iterCanonName, CanonStreamType(streamType.element))
|
||||||
|
val resultCanon = VarModel(canonName, CanonStreamType(streamType.element))
|
||||||
val resultCanon =
|
|
||||||
VarModel(canonName, CanonStreamType(streamType.element))
|
|
||||||
|
|
||||||
val incrVar = VarModel(idxIncrName, ScalarType.u32)
|
|
||||||
|
|
||||||
RestrictionModel(varSTest.name, streamType).wrap(
|
RestrictionModel(varSTest.name, streamType).wrap(
|
||||||
increment(idxModel, incrVar),
|
|
||||||
ForModel(iter.name, VarModel(streamName, streamType), ForModel.Mode.Never.some).wrap(
|
ForModel(iter.name, VarModel(streamName, streamType), ForModel.Mode.Never.some).wrap(
|
||||||
PushToStreamModel(
|
PushToStreamModel(
|
||||||
iter,
|
iter,
|
||||||
@ -77,8 +71,10 @@ object ApplyGateRawInliner extends RawInliner[ApplyGateRaw] with Logging {
|
|||||||
XorModel.wrap(
|
XorModel.wrap(
|
||||||
MatchMismatchModel(
|
MatchMismatchModel(
|
||||||
iterCanon
|
iterCanon
|
||||||
.copy(properties = Chain.one(FunctorModel("length", ScalarType.`u32`))),
|
.withProperty(
|
||||||
incrVar,
|
FunctorModel("length", ScalarType.`u32`)
|
||||||
|
),
|
||||||
|
sizeModel,
|
||||||
true
|
true
|
||||||
).leaf,
|
).leaf,
|
||||||
NextModel(iter.name).leaf
|
NextModel(iter.name).leaf
|
||||||
@ -95,25 +91,23 @@ object ApplyGateRawInliner extends RawInliner[ApplyGateRaw] with Logging {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def apply[S: Mangler: Exports: Arrows](
|
def apply[S: Mangler: Exports: Arrows](
|
||||||
afr: ApplyGateRaw,
|
streamName: String,
|
||||||
propertyAllowed: Boolean
|
streamType: StreamType,
|
||||||
): State[S, (ValueModel, Inline)] =
|
sizeModel: ValueModel
|
||||||
|
): State[S, (VarModel, Inline)] =
|
||||||
for {
|
for {
|
||||||
uniqueCanonName <- Mangler[S].findAndForbidName(afr.name + "_result_canon")
|
uniqueCanonName <- Mangler[S].findAndForbidName(streamName + "_result_canon")
|
||||||
uniqueResultName <- Mangler[S].findAndForbidName(afr.name + "_gate")
|
uniqueResultName <- Mangler[S].findAndForbidName(streamName + "_gate")
|
||||||
uniqueTestName <- Mangler[S].findAndForbidName(afr.name + "_test")
|
uniqueTestName <- Mangler[S].findAndForbidName(streamName + "_test")
|
||||||
uniqueIdxIncr <- Mangler[S].findAndForbidName(afr.name + "_incr")
|
uniqueIdxIncr <- Mangler[S].findAndForbidName(streamName + "_incr")
|
||||||
uniqueIterCanon <- Mangler[S].findAndForbidName(afr.name + "_iter_canon")
|
uniqueIterCanon <- Mangler[S].findAndForbidName(streamName + "_iter_canon")
|
||||||
uniqueIter <- Mangler[S].findAndForbidName(afr.name + "_fold_var")
|
uniqueIter <- Mangler[S].findAndForbidName(streamName + "_fold_var")
|
||||||
idxFolded <- unfold(afr.idx)
|
|
||||||
(idxModel, idxInline) = idxFolded
|
|
||||||
} yield {
|
} yield {
|
||||||
val gate = joinStreamOnIndexModel(
|
val gate = joinStreamOnIndexModel(
|
||||||
streamName = afr.name,
|
streamName = streamName,
|
||||||
streamType = afr.streamType,
|
streamType = streamType,
|
||||||
idxModel = idxModel,
|
sizeModel = sizeModel,
|
||||||
idxIncrName = uniqueIdxIncr,
|
|
||||||
testName = uniqueTestName,
|
testName = uniqueTestName,
|
||||||
iterName = uniqueIter,
|
iterName = uniqueIter,
|
||||||
canonName = uniqueCanonName,
|
canonName = uniqueCanonName,
|
||||||
@ -121,24 +115,12 @@ object ApplyGateRawInliner extends RawInliner[ApplyGateRaw] with Logging {
|
|||||||
resultName = uniqueResultName
|
resultName = uniqueResultName
|
||||||
)
|
)
|
||||||
|
|
||||||
val tree = SeqModel.wrap(idxInline.predo.toList :+ gate)
|
val inline = Inline(predo = Chain.one(gate))
|
||||||
|
val value = VarModel(
|
||||||
val treeInline = Inline(predo = Chain.one(tree))
|
uniqueResultName,
|
||||||
|
ArrayType(streamType.element)
|
||||||
(
|
|
||||||
VarModel(uniqueResultName, ArrayType(afr.streamType.element)),
|
|
||||||
treeInline
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(value, inline)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def increment(v: ValueModel, result: VarModel) =
|
|
||||||
CallServiceModel(
|
|
||||||
LiteralModel("\"math\"", ScalarType.string),
|
|
||||||
"add",
|
|
||||||
CallModel(
|
|
||||||
v :: LiteralModel.fromRaw(LiteralRaw.number(1)) :: Nil,
|
|
||||||
CallModel.Export(result.name, result.`type`) :: Nil
|
|
||||||
)
|
|
||||||
).leaf
|
|
||||||
}
|
}
|
@ -58,8 +58,8 @@ object ValueRaw {
|
|||||||
errorType
|
errorType
|
||||||
)
|
)
|
||||||
|
|
||||||
type ApplyRaw = ApplyGateRaw | ApplyPropertyRaw | CallArrowRaw | CollectionRaw |
|
type ApplyRaw = ApplyPropertyRaw | CallArrowRaw | CollectionRaw | ApplyBinaryOpRaw |
|
||||||
ApplyBinaryOpRaw | ApplyUnaryOpRaw
|
ApplyUnaryOpRaw
|
||||||
}
|
}
|
||||||
|
|
||||||
case class ApplyPropertyRaw(value: ValueRaw, property: PropertyRaw) extends ValueRaw {
|
case class ApplyPropertyRaw(value: ValueRaw, property: PropertyRaw) extends ValueRaw {
|
||||||
@ -94,22 +94,6 @@ object ApplyPropertyRaw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case class ApplyGateRaw(name: String, streamType: StreamType, idx: ValueRaw) extends ValueRaw {
|
|
||||||
override def baseType: Type = streamType
|
|
||||||
|
|
||||||
override def `type`: Type = idx.`type`
|
|
||||||
|
|
||||||
override def renameVars(map: Map[String, String]): ValueRaw =
|
|
||||||
copy(name = map.getOrElse(name, name), idx = idx.renameVars(map))
|
|
||||||
|
|
||||||
override def map(f: ValueRaw => ValueRaw): ValueRaw =
|
|
||||||
f(copy(idx = f(idx)))
|
|
||||||
|
|
||||||
override def toString: String = s"gate $name.$idx"
|
|
||||||
|
|
||||||
override def varNames: Set[String] = Set(name) ++ idx.varNames
|
|
||||||
}
|
|
||||||
|
|
||||||
case class VarRaw(name: String, baseType: Type) extends ValueRaw {
|
case class VarRaw(name: String, baseType: Type) extends ValueRaw {
|
||||||
|
|
||||||
override def map(f: ValueRaw => ValueRaw): ValueRaw = f(this)
|
override def map(f: ValueRaw => ValueRaw): ValueRaw = f(this)
|
||||||
|
@ -9,32 +9,22 @@ import cats.syntax.option.*
|
|||||||
|
|
||||||
object ResBuilder {
|
object ResBuilder {
|
||||||
|
|
||||||
def join(stream: VarModel, onIdx: ValueModel, peer: ValueModel) = {
|
def join(stream: VarModel, sizeModel: ValueModel, peer: ValueModel) = {
|
||||||
val testVM = VarModel(stream.name + "_test", stream.`type`)
|
val testVM = VarModel(stream.name + "_test", stream.`type`)
|
||||||
val testStreamType = stream.`type`.asInstanceOf[StreamType] // Unsafe
|
val testStreamType = stream.`type`.asInstanceOf[StreamType] // Unsafe
|
||||||
val iter = VarModel(stream.name + "_fold_var", ScalarType.string)
|
val iter = VarModel(stream.name + "_fold_var", ScalarType.string)
|
||||||
val canon = VarModel(stream.name + "_iter_canon", CanonStreamType(ScalarType.string))
|
val canon = VarModel(stream.name + "_iter_canon", CanonStreamType(ScalarType.string))
|
||||||
val canonRes = VarModel(stream.name + "_result_canon", CanonStreamType(ScalarType.string))
|
val canonRes = VarModel(stream.name + "_result_canon", CanonStreamType(ScalarType.string))
|
||||||
val arrayRes = VarModel(stream.name + "_gate", ArrayType(ScalarType.string))
|
val arrayRes = VarModel(stream.name + "_gate", ArrayType(ScalarType.string))
|
||||||
val idx = VarModel(stream.name + "_incr", ScalarType.u32)
|
|
||||||
|
|
||||||
RestrictionRes(testVM.name, testStreamType).wrap(
|
RestrictionRes(testVM.name, testStreamType).wrap(
|
||||||
CallServiceRes(
|
|
||||||
LiteralModel("\"math\"", ScalarType.string),
|
|
||||||
"add",
|
|
||||||
CallRes(
|
|
||||||
onIdx :: LiteralModel.fromRaw(LiteralRaw.number(1)) :: Nil,
|
|
||||||
Some(CallModel.Export(idx.name, idx.`type`))
|
|
||||||
),
|
|
||||||
peer
|
|
||||||
).leaf,
|
|
||||||
FoldRes(iter.name, stream, ForModel.Mode.Never.some).wrap(
|
FoldRes(iter.name, stream, ForModel.Mode.Never.some).wrap(
|
||||||
ApRes(iter, CallModel.Export(testVM.name, testVM.`type`)).leaf,
|
ApRes(iter, CallModel.Export(testVM.name, testVM.`type`)).leaf,
|
||||||
CanonRes(testVM, peer, CallModel.Export(canon.name, canon.`type`)).leaf,
|
CanonRes(testVM, peer, CallModel.Export(canon.name, canon.`type`)).leaf,
|
||||||
XorRes.wrap(
|
XorRes.wrap(
|
||||||
MatchMismatchRes(
|
MatchMismatchRes(
|
||||||
canon.copy(properties = Chain.one(FunctorModel("length", ScalarType.u32))),
|
canon.copy(properties = Chain.one(FunctorModel("length", ScalarType.u32))),
|
||||||
idx,
|
sizeModel,
|
||||||
true
|
true
|
||||||
).leaf,
|
).leaf,
|
||||||
NextRes(iter.name).leaf
|
NextRes(iter.name).leaf
|
||||||
@ -45,4 +35,20 @@ object ResBuilder {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def add(
|
||||||
|
a: ValueModel,
|
||||||
|
b: ValueModel,
|
||||||
|
res: VarModel,
|
||||||
|
peer: ValueModel
|
||||||
|
): ResolvedOp.Tree =
|
||||||
|
CallServiceRes(
|
||||||
|
LiteralModel.quote("math"),
|
||||||
|
"add",
|
||||||
|
CallRes(
|
||||||
|
a :: b :: Nil,
|
||||||
|
Some(CallModel.Export(res.name, res.`type`))
|
||||||
|
),
|
||||||
|
peer
|
||||||
|
).leaf
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -157,6 +157,15 @@ case class IntoIndexModel(idx: String, `type`: Type) extends PropertyModel {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object IntoIndexModel {
|
||||||
|
|
||||||
|
def fromValueModel(vm: ValueModel, `type`: Type): Option[IntoIndexModel] = vm match {
|
||||||
|
case VarModel(name, _, Chain.nil) => IntoIndexModel(name, `type`).some
|
||||||
|
case LiteralModel(value, _) => IntoIndexModel(value, `type`).some
|
||||||
|
case _ => none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case class VarModel(name: String, baseType: Type, properties: Chain[PropertyModel] = Chain.empty)
|
case class VarModel(name: String, baseType: Type, properties: Chain[PropertyModel] = Chain.empty)
|
||||||
extends ValueModel with Logging {
|
extends ValueModel with Logging {
|
||||||
|
|
||||||
@ -173,14 +182,13 @@ case class VarModel(name: String, baseType: Type, properties: Chain[PropertyMode
|
|||||||
private def deriveFrom(vm: VarModel): VarModel =
|
private def deriveFrom(vm: VarModel): VarModel =
|
||||||
vm.copy(properties = vm.properties ++ properties)
|
vm.copy(properties = vm.properties ++ properties)
|
||||||
|
|
||||||
|
def withProperty(p: PropertyModel): VarModel =
|
||||||
|
copy(properties = properties :+ p)
|
||||||
|
|
||||||
def intoField(field: String): Option[VarModel] = `type` match {
|
def intoField(field: String): Option[VarModel] = `type` match {
|
||||||
case StructType(_, fields) =>
|
case StructType(_, fields) =>
|
||||||
fields(field)
|
fields(field)
|
||||||
.map(fieldType =>
|
.map(fieldType => withProperty(IntoFieldModel(field, fieldType)))
|
||||||
copy(
|
|
||||||
properties = properties :+ IntoFieldModel(field, fieldType)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
case _ => none
|
case _ => none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import aqua.res.{CallRes, CallServiceRes, MakeRes}
|
|||||||
import aqua.types.{ArrayType, LiteralType, ScalarType}
|
import aqua.types.{ArrayType, LiteralType, ScalarType}
|
||||||
import aqua.types.StreamType
|
import aqua.types.StreamType
|
||||||
import aqua.model.IntoIndexModel
|
import aqua.model.IntoIndexModel
|
||||||
import aqua.model.inline.raw.ApplyGateRawInliner
|
import aqua.model.inline.raw.StreamGateInliner
|
||||||
import aqua.model.OnModel
|
import aqua.model.OnModel
|
||||||
import aqua.model.FailModel
|
import aqua.model.FailModel
|
||||||
import aqua.res.ResolvedOp
|
import aqua.res.ResolvedOp
|
||||||
@ -142,21 +142,20 @@ object ModelBuilder {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param stream stream [[VarModel]]
|
* @param stream stream [[VarModel]]
|
||||||
* @param idx id [[ValueModel]]
|
* @param size size [[ValueModel]]
|
||||||
* @return [[OpModel.Tree]] of join of `stream[idx]`
|
* @return [[OpModel.Tree]] of join of size elements of stream
|
||||||
*/
|
*/
|
||||||
def join(stream: VarModel, idx: ValueModel): OpModel.Tree =
|
def join(stream: VarModel, size: ValueModel): OpModel.Tree =
|
||||||
stream match {
|
stream match {
|
||||||
case VarModel(
|
case VarModel(
|
||||||
streamName,
|
streamName,
|
||||||
streamType: StreamType,
|
streamType: StreamType,
|
||||||
Chain.`nil`
|
Chain.`nil`
|
||||||
) =>
|
) =>
|
||||||
ApplyGateRawInliner.joinStreamOnIndexModel(
|
StreamGateInliner.joinStreamOnIndexModel(
|
||||||
streamName = streamName,
|
streamName = streamName,
|
||||||
streamType = streamType,
|
streamType = streamType,
|
||||||
idxModel = idx,
|
sizeModel = size,
|
||||||
idxIncrName = streamName + "_incr",
|
|
||||||
testName = streamName + "_test",
|
testName = streamName + "_test",
|
||||||
iterName = streamName + "_fold_var",
|
iterName = streamName + "_fold_var",
|
||||||
canonName = streamName + "_result_canon",
|
canonName = streamName + "_result_canon",
|
||||||
@ -165,4 +164,12 @@ object ModelBuilder {
|
|||||||
)
|
)
|
||||||
case _ => ???
|
case _ => ???
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def add(a: ValueModel, b: ValueModel, res: VarModel): OpModel.Tree =
|
||||||
|
CallServiceModel(
|
||||||
|
"math",
|
||||||
|
"add",
|
||||||
|
args = List(a, b),
|
||||||
|
result = res
|
||||||
|
).leaf
|
||||||
}
|
}
|
||||||
|
@ -25,22 +25,45 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
|||||||
import ModelBuilder.{join as joinModel, *}
|
import ModelBuilder.{join as joinModel, *}
|
||||||
import ResBuilder.join as joinRes
|
import ResBuilder.join as joinRes
|
||||||
|
|
||||||
def joinModelRes(streamEl: ValueRaw | ValueModel): (OpModel.Tree, ResolvedOp.Tree) =
|
def joinModelRes(
|
||||||
|
streamEl: ValueRaw | ValueModel
|
||||||
|
): (Chain[OpModel.Tree], Chain[ResolvedOp.Tree]) =
|
||||||
streamEl match {
|
streamEl match {
|
||||||
case vm: ValueModel => vm
|
case vm: ValueModel => vm
|
||||||
case vr: ValueRaw => ValueModel.fromRaw(vr)
|
case vr: ValueRaw => ValueModel.fromRaw(vr)
|
||||||
} match {
|
} match {
|
||||||
case stream @ VarModel(name, baseType, IntoIndexModel(idx, idxType) ==: Chain.`nil`) =>
|
case stream @ VarModel(name, baseType, IntoIndexModel(idx, idxType) ==: Chain.`nil`) =>
|
||||||
val idxModel =
|
val idxModel =
|
||||||
if (idx.forall(Character.isDigit)) LiteralModel(idx, idxType)
|
if (idx.forall(Character.isDigit)) LiteralModel(idx, ScalarType.u32)
|
||||||
else VarModel(idx, idxType)
|
else VarModel(idx, ScalarType.u32)
|
||||||
|
|
||||||
val streamWithoutIdx = stream.copy(properties = Chain.`nil`)
|
val streamWithoutIdx = stream.copy(properties = Chain.`nil`)
|
||||||
|
|
||||||
(
|
val sizeModel = VarModel(s"${name}_size", ScalarType.u32)
|
||||||
joinModel(streamWithoutIdx, idxModel),
|
val sizeTree = ModelBuilder.add(
|
||||||
joinRes(streamWithoutIdx, idxModel, ValueModel.fromRaw(initPeer))
|
idxModel,
|
||||||
|
LiteralModel.number(1),
|
||||||
|
sizeModel
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val model = Chain(
|
||||||
|
sizeTree,
|
||||||
|
joinModel(streamWithoutIdx, sizeModel)
|
||||||
|
)
|
||||||
|
|
||||||
|
val sizeTreeResolved = ResBuilder.add(
|
||||||
|
idxModel,
|
||||||
|
LiteralModel.number(1),
|
||||||
|
sizeModel,
|
||||||
|
ValueModel.fromRaw(initPeer)
|
||||||
|
)
|
||||||
|
|
||||||
|
val resolved = Chain(
|
||||||
|
sizeTreeResolved,
|
||||||
|
joinRes(streamWithoutIdx, sizeModel, ValueModel.fromRaw(initPeer))
|
||||||
|
)
|
||||||
|
|
||||||
|
(model, resolved)
|
||||||
case _ => ???
|
case _ => ???
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,10 +485,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
|||||||
|
|
||||||
val (joinModel, joinRes) = joinModelRes(streamEl)
|
val (joinModel, joinRes) = joinModelRes(streamEl)
|
||||||
|
|
||||||
val init = SeqModel.wrap(
|
val foldModel = foldPar(
|
||||||
DeclareStreamModel(stream).leaf,
|
|
||||||
OnModel(initPeer, Chain.one(relay)).wrap(
|
|
||||||
foldPar(
|
|
||||||
"i",
|
"i",
|
||||||
valueArray,
|
valueArray,
|
||||||
OnModel(iRelay, Chain.empty).wrap(
|
OnModel(iRelay, Chain.empty).wrap(
|
||||||
@ -476,17 +496,19 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
joinModel,
|
val init = SeqModel.wrap(
|
||||||
|
DeclareStreamModel(stream).leaf,
|
||||||
|
OnModel(initPeer, Chain.one(relay)).wrap(
|
||||||
|
foldModel +:
|
||||||
|
joinModel :+
|
||||||
callModel(3, Nil, streamRaw :: Nil)
|
callModel(3, Nil, streamRaw :: Nil)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val proc = Topology.resolve(init).value
|
val proc = Topology.resolve(init).value
|
||||||
|
|
||||||
val expected = SeqRes.wrap(
|
val foldRes = ParRes.wrap(
|
||||||
through(relay),
|
|
||||||
ParRes.wrap(
|
|
||||||
FoldRes("i", valueArray, ForModel.Mode.Never.some).wrap(
|
FoldRes("i", valueArray, ForModel.Mode.Never.some).wrap(
|
||||||
ParRes.wrap(
|
ParRes.wrap(
|
||||||
// better if first relay will be outside `for`
|
// better if first relay will be outside `for`
|
||||||
@ -507,8 +529,13 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
|||||||
NextRes("i").leaf
|
NextRes("i").leaf
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
joinRes,
|
val expected = SeqRes.wrap(
|
||||||
|
Chain(
|
||||||
|
through(relay),
|
||||||
|
foldRes
|
||||||
|
) ++
|
||||||
|
joinRes :+
|
||||||
callRes(3, initPeer, None, stream :: Nil)
|
callRes(3, initPeer, None, stream :: Nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -543,17 +570,15 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
) +:
|
||||||
joinModel,
|
joinModel :+
|
||||||
callModel(3, Nil, streamRaw :: Nil)
|
callModel(3, Nil, streamRaw :: Nil)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val proc = Topology.resolve(init).value
|
val proc = Topology.resolve(init).value
|
||||||
|
|
||||||
val expected = SeqRes.wrap(
|
val fold = ParRes.wrap(
|
||||||
through(relay),
|
|
||||||
ParRes.wrap(
|
|
||||||
FoldRes("i", valueArray, ForModel.Mode.Never.some).wrap(
|
FoldRes("i", valueArray, ForModel.Mode.Never.some).wrap(
|
||||||
ParRes.wrap(
|
ParRes.wrap(
|
||||||
// better if first relay will be outside `for`
|
// better if first relay will be outside `for`
|
||||||
@ -576,8 +601,13 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
|||||||
NextRes("i").leaf
|
NextRes("i").leaf
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
joinRes,
|
val expected = SeqRes.wrap(
|
||||||
|
Chain(
|
||||||
|
through(relay),
|
||||||
|
fold
|
||||||
|
) ++
|
||||||
|
joinRes :+
|
||||||
callRes(3, initPeer, None, stream :: Nil)
|
callRes(3, initPeer, None, stream :: Nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -804,8 +834,8 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
|||||||
OnModel(i, Chain.empty).wrap(
|
OnModel(i, Chain.empty).wrap(
|
||||||
callModel(1, CallModel.Export(used.name, used.`type`) :: Nil)
|
callModel(1, CallModel.Export(used.name, used.`type`) :: Nil)
|
||||||
)
|
)
|
||||||
),
|
) +:
|
||||||
joinModel,
|
joinModel :+
|
||||||
callModel(3, Nil, used :: Nil)
|
callModel(3, Nil, used :: Nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -828,8 +858,8 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
|||||||
NextRes("i").leaf
|
NextRes("i").leaf
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
) +:
|
||||||
joinRes,
|
joinRes :+
|
||||||
callRes(3, initPeer, None, ValueModel.fromRaw(used) :: Nil)
|
callRes(3, initPeer, None, ValueModel.fromRaw(used) :: Nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -844,8 +874,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
|||||||
|
|
||||||
val (joinModel, joinRes) = joinModelRes(usedWithIdx)
|
val (joinModel, joinRes) = joinModelRes(usedWithIdx)
|
||||||
|
|
||||||
val init = OnModel(initPeer, Chain.one(relay)).wrap(
|
val foldModel = foldPar(
|
||||||
foldPar(
|
|
||||||
"i",
|
"i",
|
||||||
valueArray,
|
valueArray,
|
||||||
OnModel(i, Chain.empty).wrap(
|
OnModel(i, Chain.empty).wrap(
|
||||||
@ -853,15 +882,16 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
|||||||
callModel(1, CallModel.Export(used.name, used.`type`) :: Nil)
|
callModel(1, CallModel.Export(used.name, used.`type`) :: Nil)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
joinModel,
|
val init = OnModel(initPeer, Chain.one(relay)).wrap(
|
||||||
|
foldModel +:
|
||||||
|
joinModel :+
|
||||||
callModel(3, Nil, used :: Nil)
|
callModel(3, Nil, used :: Nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
val proc = Topology.resolve(init).value
|
val proc = Topology.resolve(init).value
|
||||||
|
|
||||||
val expected = SeqRes.wrap(
|
val foldRes = ParRes.wrap(
|
||||||
ParRes.wrap(
|
|
||||||
FoldRes("i", ValueModel.fromRaw(valueArray), ForModel.Mode.Never.some).wrap(
|
FoldRes("i", ValueModel.fromRaw(valueArray), ForModel.Mode.Never.some).wrap(
|
||||||
ParRes.wrap(
|
ParRes.wrap(
|
||||||
SeqRes.wrap(
|
SeqRes.wrap(
|
||||||
@ -881,8 +911,10 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
|||||||
NextRes("i").leaf
|
NextRes("i").leaf
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
joinRes,
|
val expected = SeqRes.wrap(
|
||||||
|
foldRes +:
|
||||||
|
joinRes :+
|
||||||
callRes(3, initPeer, None, ValueModel.fromRaw(used) :: Nil)
|
callRes(3, initPeer, None, ValueModel.fromRaw(used) :: Nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user