mirror of
https://github.com/fluencelabs/aqua.git
synced 2025-03-15 11:40:50 +00:00
Topology refactoring (#100)
* Topology refactoring * TransformSpec fixed & improved * Fixes #98 * Better Par handling * Introduced Cursor class * Better exit process for par branch * Force move to target peer when exiting from a par branch
This commit is contained in:
parent
27f2912c5f
commit
1fc5557ba6
@ -13,6 +13,8 @@ service Test("test"):
|
||||
getUserList: -> []User
|
||||
doSomething: -> bool
|
||||
check: bool -> ()
|
||||
log: string -> ()
|
||||
getString: string -> string
|
||||
|
||||
func initAfterJoin(me: User) -> []User:
|
||||
allUsers <- Test.getUserList()
|
||||
@ -42,3 +44,18 @@ func checkStreams(ch: []string) -> []bool:
|
||||
stream <- Peer.is_connected(b)
|
||||
handleArr(stream)
|
||||
<- stream
|
||||
|
||||
func test(user: string, relay_id: string) -> string:
|
||||
on relay_id:
|
||||
Peer.is_connected("on relay_id")
|
||||
on user:
|
||||
Peer.is_connected("on user")
|
||||
par Peer.is_connected("par on init peer")
|
||||
<- ""
|
||||
|
||||
-- should fail, as using str2 in parallel
|
||||
func topologyTest(friend: string, friendRelay: string) -> string:
|
||||
on friend via friendRelay:
|
||||
str2 <- Test.getString("friends string via")
|
||||
par Test.log(str2)
|
||||
<- "finish"
|
@ -14,11 +14,14 @@ case class TypescriptFile(script: ScriptModel) {
|
||||
object TypescriptFile {
|
||||
|
||||
val Header: String =
|
||||
"""/**
|
||||
s"""/**
|
||||
| *
|
||||
| * This file is auto-generated. Do not edit manually: changes may be erased.
|
||||
| * Generated by Aqua compiler: https://github.com/fluencelabs/aqua/.
|
||||
| * If you find any bugs, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues
|
||||
| * Aqua version: ${Option(getClass.getPackage.getImplementationVersion)
|
||||
.filter(_.nonEmpty)
|
||||
.getOrElse("Unknown")}
|
||||
| *
|
||||
| */
|
||||
|import { FluenceClient, PeerIdB58 } from '@fluencelabs/fluence';
|
||||
|
16
build.sbt
16
build.sbt
@ -1,18 +1,18 @@
|
||||
val dottyVersion = "2.13.5"
|
||||
|
||||
//val dottyVersion = "3.0.0-RC3"
|
||||
|
||||
scalaVersion := dottyVersion
|
||||
|
||||
//val dottyVersion = "3.0.0-RC2"
|
||||
|
||||
val baseAquaVersion = settingKey[String]("base aqua version")
|
||||
|
||||
val catsV = "2.5.0"
|
||||
val catsV = "2.6.0"
|
||||
val catsParseV = "0.3.2"
|
||||
val monocleV = "3.0.0-M4"
|
||||
val scalaTestV = "3.2.7"
|
||||
val fs2V = "3.0.0"
|
||||
val catsEffectV = "3.0.2"
|
||||
val declineV = "2.0.0-RC1"
|
||||
val monocleV = "3.0.0-M5"
|
||||
val scalaTestV = "3.2.7" // TODO update version for scala 3-RC3
|
||||
val fs2V = "3.0.2"
|
||||
val catsEffectV = "3.1.0"
|
||||
val declineV = "2.0.0-RC1" // Scala3 issue: https://github.com/bkirwi/decline/issues/260
|
||||
|
||||
name := "aqua-hll"
|
||||
|
||||
|
@ -17,6 +17,7 @@ object Model {
|
||||
case (l: ScriptModel, r: ScriptModel) =>
|
||||
ScriptModel.SMMonoid.combine(l, r)
|
||||
|
||||
case (l: EmptyModel, r: EmptyModel) => EmptyModel(l.log + " |+| " + r.log)
|
||||
case (_: EmptyModel, r) => r
|
||||
case (l, _: EmptyModel) => l
|
||||
|
||||
@ -24,6 +25,7 @@ object Model {
|
||||
ScriptModel.toScriptPart(l).fold(r)(ScriptModel.SMMonoid.combine(_, r))
|
||||
case (l: ScriptModel, r) =>
|
||||
ScriptModel.toScriptPart(r).fold(l)(ScriptModel.SMMonoid.combine(l, _))
|
||||
|
||||
case (l, r) =>
|
||||
ScriptModel
|
||||
.toScriptPart(l)
|
||||
@ -31,8 +33,6 @@ object Model {
|
||||
ScriptModel.toScriptPart(r).fold(l)(rs => ScriptModel.SMMonoid.combine(ls, rs))
|
||||
)
|
||||
|
||||
case (l: EmptyModel, r: EmptyModel) => EmptyModel(l.log + " |+| " + r.log)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,20 @@
|
||||
package aqua.model
|
||||
|
||||
import aqua.types.Type
|
||||
import cats.Eq
|
||||
import cats.data.Chain
|
||||
|
||||
sealed trait ValueModel {
|
||||
def resolveWith(map: Map[String, ValueModel]): ValueModel = this
|
||||
}
|
||||
|
||||
object ValueModel {
|
||||
|
||||
implicit object ValueModelEq extends Eq[ValueModel] {
|
||||
override def eqv(x: ValueModel, y: ValueModel): Boolean = x == y
|
||||
}
|
||||
}
|
||||
|
||||
case class LiteralModel(value: String) extends ValueModel
|
||||
|
||||
object LiteralModel {
|
||||
|
@ -27,15 +27,19 @@ sealed trait OpTag {
|
||||
}
|
||||
|
||||
}
|
||||
sealed trait GroupTag extends OpTag
|
||||
sealed trait SeqGroupTag extends GroupTag
|
||||
|
||||
case object SeqTag extends OpTag
|
||||
case object ParTag extends OpTag
|
||||
case object XorTag extends OpTag
|
||||
case object SeqTag extends SeqGroupTag
|
||||
case object ParTag extends GroupTag
|
||||
case object XorTag extends GroupTag
|
||||
case class XorParTag(xor: FuncOp, par: FuncOp) extends OpTag
|
||||
case class OnTag(peerId: ValueModel, via: Chain[ValueModel]) extends OpTag
|
||||
case class OnTag(peerId: ValueModel, via: Chain[ValueModel]) extends SeqGroupTag
|
||||
case class NextTag(item: String) extends OpTag
|
||||
case class MatchMismatchTag(left: ValueModel, right: ValueModel, shouldMatch: Boolean) extends OpTag
|
||||
case class ForTag(item: String, iterable: ValueModel) extends OpTag
|
||||
|
||||
case class MatchMismatchTag(left: ValueModel, right: ValueModel, shouldMatch: Boolean)
|
||||
extends SeqGroupTag
|
||||
case class ForTag(item: String, iterable: ValueModel) extends SeqGroupTag
|
||||
|
||||
case class CallArrowTag(
|
||||
funcName: String,
|
||||
|
51
model/src/main/scala/aqua/model/topology/ChainZipper.scala
Normal file
51
model/src/main/scala/aqua/model/topology/ChainZipper.scala
Normal file
@ -0,0 +1,51 @@
|
||||
package aqua.model.topology
|
||||
|
||||
import cats.data.Chain
|
||||
import cats.free.Cofree
|
||||
|
||||
case class ChainZipper[T](prev: Chain[T], current: T, next: Chain[T]) {
|
||||
|
||||
def chain: Chain[T] = (prev :+ current) ++ next
|
||||
|
||||
def moveLeft: Option[ChainZipper[T]] =
|
||||
prev.initLast.map { case (init, last) =>
|
||||
ChainZipper(init, last, current +: next)
|
||||
}
|
||||
|
||||
def moveRight: Option[ChainZipper[T]] =
|
||||
next.uncons.map { case (head, tail) =>
|
||||
ChainZipper(prev :+ current, head, tail)
|
||||
}
|
||||
|
||||
def replaceInjecting(cz: ChainZipper[T]): ChainZipper[T] =
|
||||
copy(prev ++ cz.prev, cz.current, cz.next ++ next)
|
||||
}
|
||||
|
||||
object ChainZipper {
|
||||
def one[T](el: T): ChainZipper[T] = ChainZipper(Chain.empty, el, Chain.empty)
|
||||
|
||||
def fromChain[T](chain: Chain[T], prev: Chain[T] = Chain.empty): Chain[ChainZipper[T]] =
|
||||
chain.uncons.fold(Chain.empty[ChainZipper[T]]) { case (t, next) =>
|
||||
ChainZipper(prev, t, next) +: fromChain(next, prev :+ t)
|
||||
}
|
||||
|
||||
def fromChainMap[T](chain: Chain[T], prev: Chain[T] = Chain.empty)(
|
||||
f: ChainZipper[T] => Option[T]
|
||||
): Chain[T] =
|
||||
chain.uncons.fold(Chain.empty[T]) { case (t, next) =>
|
||||
f(ChainZipper(prev, t, next)).fold(fromChainMap(next, prev)(f))(r =>
|
||||
r +: fromChainMap(next, prev :+ r)(f)
|
||||
)
|
||||
}
|
||||
|
||||
object Matchers {
|
||||
|
||||
object `current` {
|
||||
def unapply[T](cz: ChainZipper[T]): Option[T] = Some(cz.current)
|
||||
}
|
||||
|
||||
object `head` {
|
||||
def unapply[F[_], T](cz: ChainZipper[Cofree[F, T]]): Option[T] = Some(cz.current.head)
|
||||
}
|
||||
}
|
||||
}
|
81
model/src/main/scala/aqua/model/topology/Cursor.scala
Normal file
81
model/src/main/scala/aqua/model/topology/Cursor.scala
Normal file
@ -0,0 +1,81 @@
|
||||
package aqua.model.topology
|
||||
|
||||
import Topology.Tree
|
||||
import aqua.model.func.body.{OnTag, OpTag, ParTag, SeqTag}
|
||||
import cats.Eval
|
||||
import cats.data.Chain
|
||||
import cats.free.Cofree
|
||||
|
||||
case class Cursor(point: ChainZipper[Tree], loc: Location) {
|
||||
|
||||
def downLoc(tree: Tree): Location =
|
||||
loc.down(point.copy(current = tree))
|
||||
|
||||
def prevOnTags: Chain[OnTag] =
|
||||
Chain
|
||||
.fromSeq(
|
||||
point.prev.lastOption
|
||||
.orElse(loc.lastLeftSeq.map(_._1.current))
|
||||
.toList
|
||||
.flatMap(Cursor.rightBoundary)
|
||||
.takeWhile {
|
||||
case ParTag => false
|
||||
case _ => true
|
||||
}
|
||||
)
|
||||
.collect { case o: OnTag =>
|
||||
o
|
||||
}
|
||||
|
||||
def nextOnTags: Chain[OnTag] =
|
||||
Chain
|
||||
.fromSeq(
|
||||
loc.lastRightSeq
|
||||
.map(_._1.current)
|
||||
.toList
|
||||
.flatMap(Cursor.leftBoundary)
|
||||
.takeWhile {
|
||||
case ParTag => false
|
||||
case _ => true
|
||||
}
|
||||
)
|
||||
.collect { case o: OnTag =>
|
||||
o
|
||||
}
|
||||
}
|
||||
|
||||
object Cursor {
|
||||
|
||||
def rightBoundary(root: Tree): LazyList[OpTag] =
|
||||
root.head #:: LazyList.unfold(root.tail)(_.value.lastOption.map(lo => lo.head -> lo.tail))
|
||||
|
||||
def leftBoundary(root: Tree): LazyList[OpTag] =
|
||||
root.head #:: LazyList.unfold(root.tail)(_.value.headOption.map(lo => lo.head -> lo.tail))
|
||||
|
||||
def transform(root: Tree)(f: Cursor => List[Tree]): Option[Tree] = {
|
||||
def step(cursor: Cursor): Option[Tree] =
|
||||
f(cursor) match {
|
||||
case Nil => None
|
||||
case h :: Nil =>
|
||||
val np = cursor.downLoc(h)
|
||||
Some(h.copy(tail = h.tail.map(ChainZipper.fromChainMap(_)(cz => step(Cursor(cz, np))))))
|
||||
case hs =>
|
||||
ChainZipper
|
||||
.fromChain(Chain.fromSeq(hs))
|
||||
.map(cursor.point.replaceInjecting)
|
||||
.map { cfh =>
|
||||
val np = cursor.loc.down(cfh)
|
||||
cfh.current.copy(tail =
|
||||
cfh.current.tail.map(ChainZipper.fromChainMap(_)(cz => step(Cursor(cz, np))))
|
||||
)
|
||||
}
|
||||
.uncons
|
||||
.map {
|
||||
case (h, t) if t.isEmpty => h
|
||||
case (h, t) => Cofree(SeqTag, Eval.later(h +: t))
|
||||
}
|
||||
}
|
||||
step(Cursor(ChainZipper.one(root), Location()))
|
||||
}
|
||||
|
||||
}
|
63
model/src/main/scala/aqua/model/topology/Location.scala
Normal file
63
model/src/main/scala/aqua/model/topology/Location.scala
Normal file
@ -0,0 +1,63 @@
|
||||
package aqua.model.topology
|
||||
|
||||
import aqua.model.ValueModel
|
||||
import aqua.model.func.body.{OnTag, SeqGroupTag}
|
||||
import cats.data.Chain
|
||||
import cats.free.Cofree
|
||||
|
||||
case class Location(path: List[ChainZipper[Topology.Tree]] = Nil) {
|
||||
def down(h: ChainZipper[Topology.Tree]): Location = copy(h :: path)
|
||||
|
||||
def lastOn: Option[OnTag] = path.map(_.current.head).collectFirst { case o: OnTag =>
|
||||
o
|
||||
}
|
||||
|
||||
def pathOn: List[OnTag] = path.map(_.current.head).collect { case o: OnTag =>
|
||||
o
|
||||
}
|
||||
|
||||
def pathViaChain: Chain[ValueModel] = Chain.fromSeq(
|
||||
path
|
||||
.map(_.current.head)
|
||||
.collectFirst { case t: OnTag =>
|
||||
t.via.toList
|
||||
}
|
||||
.toList
|
||||
.flatten
|
||||
)
|
||||
|
||||
def lastLeftSeq: Option[(ChainZipper[Topology.Tree], Location)] =
|
||||
path match {
|
||||
case (cz @ ChainZipper(prev, Cofree(_: SeqGroupTag, _), _)) :: tail if prev.nonEmpty =>
|
||||
cz.moveLeft.map(_ -> Location(tail))
|
||||
case _ :: tail => Location(tail).lastLeftSeq
|
||||
case Nil => None
|
||||
}
|
||||
|
||||
def lastRightSeq: Option[(ChainZipper[Topology.Tree], Location)] =
|
||||
path match {
|
||||
case (cz @ ChainZipper(_, Cofree(_: SeqGroupTag, _), next)) :: tail if next.nonEmpty =>
|
||||
cz.moveRight.map(_ -> Location(tail))
|
||||
case _ :: tail => Location(tail).lastRightSeq
|
||||
case Nil => None
|
||||
}
|
||||
|
||||
path.collectFirst {
|
||||
case ChainZipper(prev, Cofree(_: SeqGroupTag, _), _) if prev.nonEmpty => prev.lastOption
|
||||
}.flatten
|
||||
}
|
||||
|
||||
object Location {
|
||||
|
||||
object Matchers {
|
||||
|
||||
object /: {
|
||||
|
||||
def unapply(loc: Location): Option[(ChainZipper[Topology.Tree], Location)] =
|
||||
loc.path match {
|
||||
case h :: tail => Some(h -> Location(tail))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
96
model/src/main/scala/aqua/model/topology/Topology.scala
Normal file
96
model/src/main/scala/aqua/model/topology/Topology.scala
Normal file
@ -0,0 +1,96 @@
|
||||
package aqua.model.topology
|
||||
|
||||
import aqua.model.ValueModel
|
||||
import aqua.model.func.body._
|
||||
import cats.Eval
|
||||
import cats.data.Chain
|
||||
import cats.free.Cofree
|
||||
import ChainZipper.Matchers._
|
||||
import Location.Matchers._
|
||||
|
||||
object Topology {
|
||||
type Tree = Cofree[Chain, OpTag]
|
||||
|
||||
// Walks through peer IDs, doing a noop function on each
|
||||
// If same IDs are found in a row, does noop only once
|
||||
// if there's a chain like a -> b -> c -> ... -> b -> g, remove everything between b and b
|
||||
def through(peerIds: Chain[ValueModel]): Chain[Tree] =
|
||||
peerIds
|
||||
.foldLeft(Chain.empty[ValueModel]) {
|
||||
case (acc, p) if acc.lastOption.contains(p) => acc
|
||||
case (acc, p) if acc.contains(p) => acc.takeWhile(_ != p) :+ p
|
||||
case (acc, p) => acc :+ p
|
||||
}
|
||||
.map(FuncOps.noop)
|
||||
.map(_.tree)
|
||||
|
||||
def mapTag(tag: OpTag, loc: Location): OpTag = tag match {
|
||||
case c: CallServiceTag if c.peerId.isEmpty =>
|
||||
c.copy(peerId = loc.lastOn.map(_.peerId))
|
||||
case t => t
|
||||
}
|
||||
|
||||
def resolve(op: Tree): Tree =
|
||||
Cofree
|
||||
.cata[Chain, OpTag, Tree](resolveOnMoves(op)) {
|
||||
case (SeqTag | _: OnTag, children) =>
|
||||
Eval.later(
|
||||
Cofree(
|
||||
SeqTag,
|
||||
Eval.now(children.flatMap {
|
||||
case Cofree(SeqTag, ch) => ch.value
|
||||
case cf => Chain.one(cf)
|
||||
})
|
||||
)
|
||||
)
|
||||
case (head, children) => Eval.later(Cofree(head, Eval.now(children)))
|
||||
}
|
||||
.value
|
||||
|
||||
def resolveOnMoves(op: Tree): Tree =
|
||||
Cursor
|
||||
.transform(op) {
|
||||
case c @ Cursor(
|
||||
cz @ `current`(cf),
|
||||
loc @ `head`(parent: GroupTag) /: _
|
||||
) =>
|
||||
val cfu = cf.copy(mapTag(cf.head, loc))
|
||||
|
||||
val getThere = (cfu.head, loc.pathOn) match {
|
||||
case (OnTag(pid, _), h :: _) if h.peerId == pid => Chain.empty[ValueModel]
|
||||
case (OnTag(_, via), h :: _) =>
|
||||
h.via.reverse ++ via
|
||||
case (_, _) => Chain.empty[ValueModel]
|
||||
}
|
||||
|
||||
val prevOn = c.prevOnTags
|
||||
|
||||
val prevPath = prevOn.map { case OnTag(_, v) =>
|
||||
v.reverse
|
||||
}
|
||||
.flatMap(identity)
|
||||
|
||||
val nextOn = parent match {
|
||||
case ParTag | XorTag => c.nextOnTags
|
||||
case _ => Chain.empty[OnTag]
|
||||
}
|
||||
val nextPath = (if (nextOn.nonEmpty) getThere.reverse else Chain.empty) ++ nextOn.map {
|
||||
case OnTag(_, v) =>
|
||||
v.reverse
|
||||
}
|
||||
.flatMap(identity) ++ Chain.fromOption(
|
||||
// Dirty fix for join behaviour
|
||||
nextOn.lastOption.filter(_ => parent == ParTag).map(_.peerId)
|
||||
)
|
||||
|
||||
if (prevOn.isEmpty && getThere.isEmpty) cfu :: Nil
|
||||
else
|
||||
(through(prevPath ++ loc.pathViaChain ++ getThere)
|
||||
.append(cfu) ++ through(nextPath)).toList
|
||||
|
||||
case Cursor(ChainZipper(_, cf, _), loc) =>
|
||||
cf.copy(mapTag(cf.head, loc)) :: Nil
|
||||
}
|
||||
.getOrElse(op)
|
||||
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
package aqua.model.transform
|
||||
|
||||
import aqua.model.ValueModel
|
||||
import aqua.model.func.body.{CallServiceTag, FuncOps, OnTag, OpTag, ParTag, SeqTag}
|
||||
import cats.Eval
|
||||
import cats.data.Chain
|
||||
import cats.free.Cofree
|
||||
|
||||
object Topology {
|
||||
type Tree = Cofree[Chain, OpTag]
|
||||
|
||||
def rightBoundary(root: Tree): List[OpTag] =
|
||||
root.head :: root.tailForced.lastOption.fold(List.empty[OpTag])(rightBoundary)
|
||||
|
||||
// Walks through peer IDs, doing a noop function on each
|
||||
// If same IDs are found in a row, does noop only once
|
||||
// TODO: if there's a chain like a -> b -> c -> ... -> b -> g, remove everything between b and b
|
||||
def through(peerIds: Chain[ValueModel]): Chain[Tree] =
|
||||
peerIds
|
||||
.foldLeft(Chain.empty[ValueModel]) {
|
||||
case (acc, p) if acc.lastOption.contains(p) => acc
|
||||
case (acc, p) => acc :+ p
|
||||
}
|
||||
.map(FuncOps.noop)
|
||||
.map(_.tree)
|
||||
|
||||
// TODO: after topology is resolved, OnTag should be eliminated
|
||||
def resolve(op: Tree): Tree =
|
||||
transformWithPath(op) {
|
||||
case (path, c: CallServiceTag, children) if c.peerId.isEmpty =>
|
||||
Cofree[Chain, OpTag](
|
||||
c.copy(peerId = path.collectFirst { case OnTag(peerId, _) =>
|
||||
peerId
|
||||
}),
|
||||
children
|
||||
)
|
||||
case (path, tag @ OnTag(pid, via), children) =>
|
||||
// Drop seq/par/xor from path
|
||||
val pathOn = path.collect { case ot: OnTag =>
|
||||
ot
|
||||
}
|
||||
|
||||
pathOn match {
|
||||
// If we are on the right node, do nothing
|
||||
case Nil =>
|
||||
Cofree[Chain, OpTag](tag, children)
|
||||
case h :: _ if h.peerId == pid =>
|
||||
Cofree[Chain, OpTag](tag, children)
|
||||
case h :: _ =>
|
||||
Cofree[Chain, OpTag](
|
||||
tag,
|
||||
// TODO: merge children, if possible
|
||||
children.map(through(h.via.reverse ++ via) ++ _)
|
||||
)
|
||||
}
|
||||
|
||||
case (path, SeqTag, children) =>
|
||||
// TODO if we have OnTag, and then something else, need to get back
|
||||
// AND keep in mind that we will handle all the children with OnTag processor!
|
||||
|
||||
val pathViaChain = Chain.fromSeq(path.collectFirst { case t: OnTag =>
|
||||
t.via.toList
|
||||
}.toList.flatten)
|
||||
|
||||
def modifyChildrenList(list: List[Tree], prev: Option[Tree]): Chain[Tree] = list match {
|
||||
case Nil => Chain.empty
|
||||
case op :: tail =>
|
||||
// TODO further improve
|
||||
val prevPath = Chain
|
||||
.fromSeq(prev.toList.flatMap(rightBoundary).takeWhile {
|
||||
case ParTag => false
|
||||
case _ => true
|
||||
})
|
||||
.collect { case OnTag(_, v) =>
|
||||
v.reverse
|
||||
}
|
||||
|
||||
if (prevPath.isEmpty) op +: modifyChildrenList(tail, Some(op))
|
||||
else
|
||||
through(prevPath.flatMap(identity) ++ pathViaChain).append(op) ++ modifyChildrenList(
|
||||
tail,
|
||||
Some(op)
|
||||
)
|
||||
|
||||
case o :: ops => o +: modifyChildrenList(ops, Some(o))
|
||||
}
|
||||
|
||||
Cofree[Chain, OpTag](
|
||||
SeqTag,
|
||||
children.map(_.toList).map(modifyChildrenList(_, None))
|
||||
)
|
||||
|
||||
case (_, t, children) =>
|
||||
Cofree[Chain, OpTag](t, children)
|
||||
}
|
||||
|
||||
def transformWithPath(cf: Tree, path: List[OpTag] = Nil)(
|
||||
f: (List[OpTag], OpTag, Eval[Chain[Tree]]) => Tree
|
||||
): Tree = {
|
||||
val newCf = f(path, cf.head, cf.tail)
|
||||
Cofree[Chain, OpTag](
|
||||
newCf.head,
|
||||
newCf.tail.map(_.map(transformWithPath(_, newCf.head :: path)(f)))
|
||||
)
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package aqua.model.transform
|
||||
import aqua.model.func.body._
|
||||
import aqua.model.func.FuncCallable
|
||||
import aqua.model.VarModel
|
||||
import aqua.model.topology.Topology
|
||||
import aqua.types.ScalarType
|
||||
import cats.data.Chain
|
||||
import cats.free.Cofree
|
||||
|
23
model/src/test/scala/aqua/model/topology/LocationSpec.scala
Normal file
23
model/src/test/scala/aqua/model/topology/LocationSpec.scala
Normal file
@ -0,0 +1,23 @@
|
||||
package aqua.model.topology
|
||||
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import Location.Matchers._
|
||||
import ChainZipper.Matchers._
|
||||
import aqua.model.func.body.SeqTag
|
||||
import cats.Eval
|
||||
import cats.data.Chain
|
||||
import cats.free.Cofree
|
||||
|
||||
class LocationSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
"matchers" should "unapply correctly" in {
|
||||
val loc =
|
||||
Location(ChainZipper.one(Cofree(SeqTag, Eval.later(Chain.empty[Topology.Tree]))) :: Nil)
|
||||
|
||||
Option(loc).collect { case `head`(SeqTag) /: _ =>
|
||||
true
|
||||
} should be('defined)
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package aqua.model.transform
|
||||
package aqua.model.topology
|
||||
|
||||
import aqua.model.Node
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
@ -20,14 +20,11 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
val proc: Node = Topology.resolve(init)
|
||||
|
||||
val expected = on(
|
||||
initPeer,
|
||||
relay :: Nil,
|
||||
val expected =
|
||||
seq(
|
||||
call(1, initPeer),
|
||||
call(2, initPeer)
|
||||
)
|
||||
)
|
||||
|
||||
proc should be(expected)
|
||||
|
||||
@ -50,19 +47,8 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
val proc: Node = Topology.resolve(init)
|
||||
|
||||
val expected = on(
|
||||
initPeer,
|
||||
relay :: Nil,
|
||||
on(
|
||||
otherPeer,
|
||||
Nil,
|
||||
through(relay),
|
||||
seq(
|
||||
call(1, otherPeer),
|
||||
call(2, otherPeer)
|
||||
)
|
||||
)
|
||||
)
|
||||
val expected =
|
||||
seq(through(relay), call(1, otherPeer), call(2, otherPeer))
|
||||
|
||||
proc should be(expected)
|
||||
}
|
||||
@ -84,20 +70,13 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
val proc: Node = Topology.resolve(init)
|
||||
|
||||
val expected = on(
|
||||
initPeer,
|
||||
relay :: Nil,
|
||||
on(
|
||||
otherPeer,
|
||||
otherRelay :: Nil,
|
||||
val expected =
|
||||
seq(
|
||||
through(relay),
|
||||
through(otherRelay),
|
||||
seq(
|
||||
call(1, otherPeer),
|
||||
call(2, otherPeer)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
proc should be(expected)
|
||||
}
|
||||
@ -119,22 +98,15 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
val proc: Node = Topology.resolve(init)
|
||||
|
||||
val expected = on(
|
||||
initPeer,
|
||||
relay :: Nil,
|
||||
val expected =
|
||||
seq(
|
||||
on(
|
||||
otherPeer,
|
||||
otherRelay :: Nil,
|
||||
through(relay),
|
||||
through(otherRelay),
|
||||
call(1, otherPeer)
|
||||
),
|
||||
call(1, otherPeer),
|
||||
through(otherRelay),
|
||||
through(relay),
|
||||
call(2, initPeer)
|
||||
)
|
||||
)
|
||||
|
||||
// println(Console.BLUE + init)
|
||||
// println(Console.YELLOW + proc)
|
||||
@ -175,38 +147,25 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
val proc: Node = Topology.resolve(init)
|
||||
|
||||
val expected = on(
|
||||
initPeer,
|
||||
relay :: Nil,
|
||||
val expected =
|
||||
seq(
|
||||
on(
|
||||
otherPeer,
|
||||
otherRelay :: Nil,
|
||||
through(relay),
|
||||
through(otherRelay),
|
||||
call(0, otherPeer),
|
||||
on(
|
||||
otherPeer2,
|
||||
otherRelay :: Nil,
|
||||
through(otherRelay),
|
||||
call(1, otherPeer2),
|
||||
_match(
|
||||
otherPeer,
|
||||
otherRelay,
|
||||
on(
|
||||
otherPeer,
|
||||
otherRelay :: Nil,
|
||||
seq(
|
||||
through(otherRelay),
|
||||
call(2, otherPeer)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
through(otherRelay),
|
||||
through(relay),
|
||||
call(3, initPeer)
|
||||
)
|
||||
)
|
||||
|
||||
// println(Console.BLUE + init)
|
||||
// println(Console.YELLOW + proc)
|
@ -32,17 +32,17 @@ class TransformSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
val expectedFC =
|
||||
xor(
|
||||
on(
|
||||
initPeer,
|
||||
relayV :: Nil,
|
||||
seq(
|
||||
dataCall(bc, "relay", initPeer),
|
||||
on(otherPeer, Nil, through(relayV), call(1, otherPeer)),
|
||||
through(relayV),
|
||||
on(initPeer, relayV :: Nil, respCall(bc, ret, initPeer))
|
||||
)
|
||||
call(1, otherPeer),
|
||||
through(relayV),
|
||||
respCall(bc, ret, initPeer)
|
||||
),
|
||||
on(initPeer, relayV :: Nil, xorErrorCall(bc, initPeer))
|
||||
seq(
|
||||
through(relayV),
|
||||
xorErrorCall(bc, initPeer)
|
||||
)
|
||||
)
|
||||
|
||||
procFC.equalsOrPrintDiff(expectedFC) should be(true)
|
||||
@ -70,20 +70,18 @@ class TransformSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
val expectedFC =
|
||||
xor(
|
||||
on(
|
||||
initPeer,
|
||||
relayV :: Nil,
|
||||
seq(
|
||||
dataCall(bc, "relay", initPeer),
|
||||
seq(
|
||||
call(0, initPeer),
|
||||
on(otherPeer, Nil, through(relayV), call(1, otherPeer))
|
||||
),
|
||||
through(relayV),
|
||||
on(initPeer, relayV :: Nil, respCall(bc, ret, initPeer))
|
||||
)
|
||||
call(1, otherPeer),
|
||||
through(relayV),
|
||||
respCall(bc, ret, initPeer)
|
||||
),
|
||||
on(initPeer, relayV :: Nil, xorErrorCall(bc, initPeer))
|
||||
seq(
|
||||
through(relayV),
|
||||
xorErrorCall(bc, initPeer)
|
||||
)
|
||||
)
|
||||
|
||||
procFC.equalsOrPrintDiff(expectedFC) should be(true)
|
||||
@ -137,9 +135,6 @@ class TransformSpec extends AnyFlatSpec with Matchers {
|
||||
val res = Transform.forClient(f2, bc): Node
|
||||
|
||||
res.equalsOrPrintDiff(
|
||||
on(
|
||||
initPeer,
|
||||
relayV :: Nil,
|
||||
seq(
|
||||
dataCall(bc, "relay", initPeer),
|
||||
Node(
|
||||
@ -150,13 +145,8 @@ class TransformSpec extends AnyFlatSpec with Matchers {
|
||||
Some(initPeer)
|
||||
)
|
||||
),
|
||||
on(
|
||||
initPeer,
|
||||
relayV :: Nil,
|
||||
respCall(bc, VarModel("v", ScalarType.string), initPeer)
|
||||
)
|
||||
)
|
||||
)
|
||||
) should be(true)
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
sbt.version=1.5.0
|
||||
sbt.version=1.5.1
|
||||
|
Loading…
x
Reference in New Issue
Block a user