mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 14:40:17 +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:
|
||||
numOp = ?[]
|
||||
strArr = []
|
||||
strStream = *[]
|
||||
strEmptyStream: *string
|
||||
for i <- ?[]:
|
||||
strEmptyStream <<- "some"
|
||||
for i <- *[]:
|
||||
strEmptyStream <<- "some"
|
||||
for i <- []:
|
||||
strEmptyStream <<- "some"
|
||||
<- numOp, strArr, strStream, strEmptyStream, [], ?[], *[]
|
||||
service Peer("peer"):
|
||||
hodes: -> []string
|
||||
timeout: i32, string -> string
|
||||
|
||||
func test_timeout() -> string:
|
||||
on HOST_PEER_ID:
|
||||
nodes <- Peer.hodes()
|
||||
results: *string
|
||||
|
||||
for node <- nodes par:
|
||||
on node:
|
||||
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())
|
||||
_ <- AquaPathCompiler
|
||||
.compileFilesTo[IO](
|
||||
Path("./aqua-src/call_arrow.aqua"),
|
||||
Path("./aqua-src/hack.aqua"),
|
||||
List(Path("./aqua")),
|
||||
Option(Path("./target")),
|
||||
TypeScriptBackend,
|
||||
TransformConfig(wrapWithXor = true)
|
||||
TransformConfig(wrapWithXor = false)
|
||||
)
|
||||
.map {
|
||||
case Validated.Invalid(errs) =>
|
||||
|
@ -1,16 +1,14 @@
|
||||
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.arrow.FuncRaw
|
||||
import aqua.raw.ops.RawTag.Tree
|
||||
import aqua.raw.value.{CallArrowRaw, ValueRaw}
|
||||
import aqua.tree.{TreeNode, TreeNodeCompanion}
|
||||
import aqua.types.{ArrowType, ProductType}
|
||||
import cats.{Eval, Show}
|
||||
import cats.data.{Chain, NonEmptyList}
|
||||
import cats.free.Cofree
|
||||
|
||||
sealed trait RawTag extends TreeNode[RawTag] {
|
||||
|
||||
@ -46,6 +44,16 @@ sealed trait SeqGroupTag extends GroupTag
|
||||
|
||||
object SeqGroupTag extends SeqGroupTag {
|
||||
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
|
||||
|
@ -30,15 +30,19 @@ trait RawTagGivens {
|
||||
|
||||
given Semigroup[RawTag.Tree] with
|
||||
|
||||
override def combine(x: RawTag.Tree, y: RawTag.Tree): RawTag.Tree =
|
||||
(x.head, y.head) match {
|
||||
case (_, XorParTag(xor, par)) => combine(combine(x, xor), par)
|
||||
case (XorParTag(xor, par), _) => combine(combine(xor, par), y)
|
||||
case (SeqTag, SeqTag) => y.copy(tail = (x.tail, y.tail).mapN(_ ++ _))
|
||||
case (_, SeqTag) => y.copy(tail = y.tail.map(_.prepend(x)))
|
||||
case (SeqTag, _) => x.copy(tail = x.tail.map(_.append(y)))
|
||||
case _ => SeqTag.wrap(x, y)
|
||||
override def combine(x: RawTag.Tree, y: RawTag.Tree): RawTag.Tree = {
|
||||
// Remove right-asscoc protection of Seq with single child
|
||||
val flatX = SeqGroupTag.ungroupSingle(x)
|
||||
val flatY = SeqGroupTag.ungroupSingle(y)
|
||||
(flatX.head, flatY.head) match {
|
||||
case (_, XorParTag(xor, par)) => combine(combine(flatX, xor), par)
|
||||
case (XorParTag(xor, par), _) => combine(combine(xor, par), flatY)
|
||||
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
|
||||
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(_ ++ _)))
|
||||
case (XorTag, ParTag) => XorParTag(x, y).leaf
|
||||
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)) =>
|
||||
rightAssocCombine(rightAssocCombine(x, xor), par)
|
||||
case _ => x |+| y
|
||||
|
@ -18,7 +18,9 @@ case class ParExpr[F[_]](point: Token[F]) extends Expr[F](ParExpr, point) {
|
||||
}
|
||||
|
||||
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]] =
|
||||
`par`.lift.map(Token.lift[Span.S, Unit](_)).map(ParExpr(_))
|
||||
|
@ -2,9 +2,10 @@ package aqua.semantics
|
||||
|
||||
import aqua.parser.lexer.Token
|
||||
import aqua.semantics.rules.abilities.AbilitiesAlgebra
|
||||
import aqua.semantics.rules.names.NamesAlgebra
|
||||
import cats.Monad
|
||||
import cats.syntax.flatMap._
|
||||
import cats.syntax.functor._
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.functor.*
|
||||
|
||||
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
|
||||
)
|
||||
)
|
||||
|
||||
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] {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package aqua.semantics
|
||||
|
||||
import aqua.raw.ops.FuncOp
|
||||
import aqua.raw.ops.{FuncOp, SeqGroupTag}
|
||||
import aqua.raw.{Raw, RawContext, RawPart}
|
||||
import aqua.parser.lexer.Token
|
||||
import aqua.parser.{Ast, Expr}
|
||||
@ -42,7 +42,10 @@ object Semantics extends Logging {
|
||||
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
|
||||
.around(
|
||||
N.beginScope(expr.item) >> V.valueToRaw(expr.iterable).flatMap[Option[ValueRaw]] {
|
||||
V.valueToRaw(expr.iterable).flatMap[Option[ValueRaw]] {
|
||||
case Some(vm) =>
|
||||
vm.`type` match {
|
||||
case t: BoxType =>
|
||||
@ -71,7 +71,8 @@ class ForSem[S[_]](val expr: ForExpr[S]) extends AnyVal {
|
||||
case _ =>
|
||||
Raw.error("Wrong body of the For expression")
|
||||
}
|
||||
) <* N.endScope()
|
||||
)
|
||||
)
|
||||
.namesScope[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
|
||||
|
||||
val expected =
|
||||
ParTag.wrap(
|
||||
OnTag(
|
||||
LiteralRaw("\"other-peer\"", LiteralType.string),
|
||||
Chain.empty
|
||||
).wrap(
|
||||
SeqGroupTag.wrap(
|
||||
ParTag.wrap(
|
||||
OnTag(
|
||||
LiteralRaw("\"other-peer\"", LiteralType.string),
|
||||
Chain.empty
|
||||
).wrap(
|
||||
serviceCall
|
||||
),
|
||||
serviceCall
|
||||
),
|
||||
serviceCall
|
||||
)
|
||||
)
|
||||
|
||||
proc.equalsOrShowDiff(expected) should be(true)
|
||||
|
Loading…
Reference in New Issue
Block a user