mirror of
https://github.com/fluencelabs/aqua.git
synced 2025-03-15 11:40:50 +00:00
Fix for greedy par (#487)
This commit is contained in:
parent
e9a686aac6
commit
abd101c4f9
@ -1,12 +1,18 @@
|
|||||||
func emptySugar() -> []u32, []string, []string, *string, ?u32, []u32, ?string:
|
service Peer("peer"):
|
||||||
numOp = ?[]
|
hodes: -> []string
|
||||||
strArr = []
|
timeout: i32, string -> string
|
||||||
strStream = *[]
|
|
||||||
strEmptyStream: *string
|
func test_timeout() -> string:
|
||||||
for i <- ?[]:
|
on HOST_PEER_ID:
|
||||||
strEmptyStream <<- "some"
|
nodes <- Peer.hodes()
|
||||||
for i <- *[]:
|
results: *string
|
||||||
strEmptyStream <<- "some"
|
|
||||||
for i <- []:
|
for node <- nodes par:
|
||||||
strEmptyStream <<- "some"
|
on node:
|
||||||
<- numOp, strArr, strStream, strEmptyStream, [], ?[], *[]
|
results <<- node
|
||||||
|
|
||||||
|
timeout: *string
|
||||||
|
join results[999]
|
||||||
|
par join results[123]
|
||||||
|
|
||||||
|
<- timeout!
|
@ -22,11 +22,11 @@ object Test extends IOApp.Simple {
|
|||||||
start <- IO(System.currentTimeMillis())
|
start <- IO(System.currentTimeMillis())
|
||||||
_ <- AquaPathCompiler
|
_ <- AquaPathCompiler
|
||||||
.compileFilesTo[IO](
|
.compileFilesTo[IO](
|
||||||
Path("./aqua-src/call_arrow.aqua"),
|
Path("./aqua-src/hack.aqua"),
|
||||||
List(Path("./aqua")),
|
List(Path("./aqua")),
|
||||||
Option(Path("./target")),
|
Option(Path("./target")),
|
||||||
TypeScriptBackend,
|
TypeScriptBackend,
|
||||||
TransformConfig(wrapWithXor = true)
|
TransformConfig(wrapWithXor = false)
|
||||||
)
|
)
|
||||||
.map {
|
.map {
|
||||||
case Validated.Invalid(errs) =>
|
case Validated.Invalid(errs) =>
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
package aqua.raw.ops
|
package aqua.raw.ops
|
||||||
|
|
||||||
import aqua.raw.arrow.FuncRaw
|
|
||||||
import aqua.raw.value.ValueRaw
|
|
||||||
import aqua.raw.value.CallArrowRaw
|
|
||||||
import cats.data.{Chain, NonEmptyList}
|
|
||||||
import cats.free.Cofree
|
|
||||||
import cats.Show
|
|
||||||
import cats.Eval
|
|
||||||
import aqua.raw.Raw
|
import aqua.raw.Raw
|
||||||
|
import aqua.raw.arrow.FuncRaw
|
||||||
import aqua.raw.ops.RawTag.Tree
|
import aqua.raw.ops.RawTag.Tree
|
||||||
|
import aqua.raw.value.{CallArrowRaw, ValueRaw}
|
||||||
import aqua.tree.{TreeNode, TreeNodeCompanion}
|
import aqua.tree.{TreeNode, TreeNodeCompanion}
|
||||||
import aqua.types.{ArrowType, ProductType}
|
import aqua.types.{ArrowType, ProductType}
|
||||||
|
import cats.{Eval, Show}
|
||||||
|
import cats.data.{Chain, NonEmptyList}
|
||||||
|
import cats.free.Cofree
|
||||||
|
|
||||||
sealed trait RawTag extends TreeNode[RawTag] {
|
sealed trait RawTag extends TreeNode[RawTag] {
|
||||||
|
|
||||||
@ -46,6 +44,16 @@ sealed trait SeqGroupTag extends GroupTag
|
|||||||
|
|
||||||
object SeqGroupTag extends SeqGroupTag {
|
object SeqGroupTag extends SeqGroupTag {
|
||||||
override def toString: String = "SeqGroup"
|
override def toString: String = "SeqGroup"
|
||||||
|
|
||||||
|
def ungroupSingle(tree: Tree): Tree = tree.head match {
|
||||||
|
case SeqGroupTag =>
|
||||||
|
val children = tree.tail.value
|
||||||
|
children.headOption.fold(tree) {
|
||||||
|
case h if children.length == 1 => h
|
||||||
|
case _ => tree
|
||||||
|
}
|
||||||
|
case _ => tree
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed trait ParGroupTag extends GroupTag
|
sealed trait ParGroupTag extends GroupTag
|
||||||
|
@ -30,15 +30,19 @@ trait RawTagGivens {
|
|||||||
|
|
||||||
given Semigroup[RawTag.Tree] with
|
given Semigroup[RawTag.Tree] with
|
||||||
|
|
||||||
override def combine(x: RawTag.Tree, y: RawTag.Tree): RawTag.Tree =
|
override def combine(x: RawTag.Tree, y: RawTag.Tree): RawTag.Tree = {
|
||||||
(x.head, y.head) match {
|
// Remove right-asscoc protection of Seq with single child
|
||||||
case (_, XorParTag(xor, par)) => combine(combine(x, xor), par)
|
val flatX = SeqGroupTag.ungroupSingle(x)
|
||||||
case (XorParTag(xor, par), _) => combine(combine(xor, par), y)
|
val flatY = SeqGroupTag.ungroupSingle(y)
|
||||||
case (SeqTag, SeqTag) => y.copy(tail = (x.tail, y.tail).mapN(_ ++ _))
|
(flatX.head, flatY.head) match {
|
||||||
case (_, SeqTag) => y.copy(tail = y.tail.map(_.prepend(x)))
|
case (_, XorParTag(xor, par)) => combine(combine(flatX, xor), par)
|
||||||
case (SeqTag, _) => x.copy(tail = x.tail.map(_.append(y)))
|
case (XorParTag(xor, par), _) => combine(combine(xor, par), flatY)
|
||||||
case _ => SeqTag.wrap(x, y)
|
case (SeqTag, SeqTag) => flatY.copy(tail = (flatX.tail, flatY.tail).mapN(_ ++ _))
|
||||||
|
case (_, SeqTag) => flatY.copy(tail = flatY.tail.map(_.prepend(flatX)))
|
||||||
|
case (SeqTag, _) => flatX.copy(tail = flatX.tail.map(_.append(flatY)))
|
||||||
|
case _ => SeqTag.wrap(flatX, flatY)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Semigroup for foldRight processing
|
// Semigroup for foldRight processing
|
||||||
def rightAssocCombine(x: RawTag.Tree, y: RawTag.Tree): RawTag.Tree =
|
def rightAssocCombine(x: RawTag.Tree, y: RawTag.Tree): RawTag.Tree =
|
||||||
@ -51,7 +55,10 @@ trait RawTagGivens {
|
|||||||
SeqGroupTag.wrap(y.copy(tail = (x.tail, y.tail).mapN(_ ++ _)))
|
SeqGroupTag.wrap(y.copy(tail = (x.tail, y.tail).mapN(_ ++ _)))
|
||||||
case (XorTag, ParTag) => XorParTag(x, y).leaf
|
case (XorTag, ParTag) => XorParTag(x, y).leaf
|
||||||
case (_, ParTag | XorTag) =>
|
case (_, ParTag | XorTag) =>
|
||||||
SeqTag.wrap(y.copy(tail = y.tail.map(_.prepend(x))))
|
// When right-associative tag is combined with left-associative,
|
||||||
|
// we need result to be left-associative to prevent greedy behavior.
|
||||||
|
// SeqGroupTag does just this.
|
||||||
|
SeqGroupTag.wrap(y.copy(tail = y.tail.map(_.prepend(x))))
|
||||||
case (_, XorParTag(xor, par)) =>
|
case (_, XorParTag(xor, par)) =>
|
||||||
rightAssocCombine(rightAssocCombine(x, xor), par)
|
rightAssocCombine(rightAssocCombine(x, xor), par)
|
||||||
case _ => x |+| y
|
case _ => x |+| y
|
||||||
|
@ -18,7 +18,9 @@ case class ParExpr[F[_]](point: Token[F]) extends Expr[F](ParExpr, point) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object ParExpr extends Expr.Prefix() {
|
object ParExpr extends Expr.Prefix() {
|
||||||
override def continueWith: List[Expr.Lexem] = CallArrowExpr :: OnExpr :: ForExpr :: Nil
|
|
||||||
|
override def continueWith: List[Expr.Lexem] =
|
||||||
|
CallArrowExpr :: OnExpr :: ForExpr :: JoinExpr :: Nil
|
||||||
|
|
||||||
override val p: Parser[Expr[Span.S]] =
|
override val p: Parser[Expr[Span.S]] =
|
||||||
`par`.lift.map(Token.lift[Span.S, Unit](_)).map(ParExpr(_))
|
`par`.lift.map(Token.lift[Span.S, Unit](_)).map(ParExpr(_))
|
||||||
|
@ -2,9 +2,10 @@ package aqua.semantics
|
|||||||
|
|
||||||
import aqua.parser.lexer.Token
|
import aqua.parser.lexer.Token
|
||||||
import aqua.semantics.rules.abilities.AbilitiesAlgebra
|
import aqua.semantics.rules.abilities.AbilitiesAlgebra
|
||||||
|
import aqua.semantics.rules.names.NamesAlgebra
|
||||||
import cats.Monad
|
import cats.Monad
|
||||||
import cats.syntax.flatMap._
|
import cats.syntax.flatMap.*
|
||||||
import cats.syntax.functor._
|
import cats.syntax.functor.*
|
||||||
|
|
||||||
import scala.language.implicitConversions
|
import scala.language.implicitConversions
|
||||||
|
|
||||||
@ -28,6 +29,14 @@ sealed abstract class Prog[Alg[_]: Monad, A] extends (Alg[A] => Alg[A]) {
|
|||||||
(_: Unit, m: A) => Ab.endScope() as m
|
(_: Unit, m: A) => Ab.endScope() as m
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def namesScope[S[_]](token: Token[S])(implicit N: NamesAlgebra[S, Alg]): Prog[Alg, A] =
|
||||||
|
wrap(
|
||||||
|
RunAround(
|
||||||
|
N.beginScope(token),
|
||||||
|
(_: Unit, m: A) => N.endScope() as m
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class RunAfter[Alg[_]: Monad, A](prog: Alg[A]) extends Prog[Alg, A] {
|
case class RunAfter[Alg[_]: Monad, A](prog: Alg[A]) extends Prog[Alg, A] {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package aqua.semantics
|
package aqua.semantics
|
||||||
|
|
||||||
import aqua.raw.ops.FuncOp
|
import aqua.raw.ops.{FuncOp, SeqGroupTag}
|
||||||
import aqua.raw.{Raw, RawContext, RawPart}
|
import aqua.raw.{Raw, RawContext, RawPart}
|
||||||
import aqua.parser.lexer.Token
|
import aqua.parser.lexer.Token
|
||||||
import aqua.parser.{Ast, Expr}
|
import aqua.parser.{Ast, Expr}
|
||||||
@ -42,7 +42,10 @@ object Semantics extends Logging {
|
|||||||
case (prev, acc) => prev :: acc
|
case (prev, acc) => prev :: acc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map(_.reduceLeftOption(_ |+| _).getOrElse(Raw.empty("AST is empty")))
|
.map(
|
||||||
|
_.reduceLeftOption(_ |+| _)
|
||||||
|
.getOrElse(Raw.empty("AST is empty"))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ class ForSem[S[_]](val expr: ForExpr[S]) extends AnyVal {
|
|||||||
): Prog[F, Raw] =
|
): Prog[F, Raw] =
|
||||||
Prog
|
Prog
|
||||||
.around(
|
.around(
|
||||||
N.beginScope(expr.item) >> V.valueToRaw(expr.iterable).flatMap[Option[ValueRaw]] {
|
V.valueToRaw(expr.iterable).flatMap[Option[ValueRaw]] {
|
||||||
case Some(vm) =>
|
case Some(vm) =>
|
||||||
vm.`type` match {
|
vm.`type` match {
|
||||||
case t: BoxType =>
|
case t: BoxType =>
|
||||||
@ -71,7 +71,8 @@ class ForSem[S[_]](val expr: ForExpr[S]) extends AnyVal {
|
|||||||
case _ =>
|
case _ =>
|
||||||
Raw.error("Wrong body of the For expression")
|
Raw.error("Wrong body of the For expression")
|
||||||
}
|
}
|
||||||
) <* N.endScope()
|
)
|
||||||
)
|
)
|
||||||
|
.namesScope[S](expr.token)
|
||||||
.abilitiesScope[S](expr.token)
|
.abilitiesScope[S](expr.token)
|
||||||
}
|
}
|
||||||
|
@ -46,14 +46,16 @@ class SemanticsSpec extends AnyFlatSpec with Matchers {
|
|||||||
CallArrowRawTag.service(LiteralRaw.quote("srv1"), "fn1", emptyCall, "A", arrowType).leaf
|
CallArrowRawTag.service(LiteralRaw.quote("srv1"), "fn1", emptyCall, "A", arrowType).leaf
|
||||||
|
|
||||||
val expected =
|
val expected =
|
||||||
ParTag.wrap(
|
SeqGroupTag.wrap(
|
||||||
OnTag(
|
ParTag.wrap(
|
||||||
LiteralRaw("\"other-peer\"", LiteralType.string),
|
OnTag(
|
||||||
Chain.empty
|
LiteralRaw("\"other-peer\"", LiteralType.string),
|
||||||
).wrap(
|
Chain.empty
|
||||||
|
).wrap(
|
||||||
|
serviceCall
|
||||||
|
),
|
||||||
serviceCall
|
serviceCall
|
||||||
),
|
)
|
||||||
serviceCall
|
|
||||||
)
|
)
|
||||||
|
|
||||||
proc.equalsOrShowDiff(expected) should be(true)
|
proc.equalsOrShowDiff(expected) should be(true)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user