mirror of
https://github.com/fluencelabs/aqua.git
synced 2025-03-15 11:40:50 +00:00
Capture and apply topology (#451)
This commit is contained in:
parent
fe3015a2cd
commit
ab0990dd72
@ -1,21 +1,68 @@
|
|||||||
module Closure declares *
|
module Closure declares *
|
||||||
|
|
||||||
export smth
|
import "builtin.aqua"
|
||||||
|
|
||||||
service Srv("srv"):
|
export closureOut2, closureIn, closureOut, closureBig, closureOut3
|
||||||
noop: string -> ()
|
|
||||||
|
service MyOp("op"):
|
||||||
|
identity(s: string) -> string
|
||||||
|
|
||||||
|
service LocalSrv("local_srv"):
|
||||||
inside: -> ()
|
inside: -> ()
|
||||||
trial: -> ()
|
|
||||||
|
|
||||||
func smth() -> bool, string:
|
func closureOut2():
|
||||||
|
on HOST_PEER_ID:
|
||||||
|
closure = () -> Info:
|
||||||
|
p2Id <- Peer.identify()
|
||||||
|
<- p2Id
|
||||||
|
closure()
|
||||||
|
|
||||||
|
func closureIn(peer1: string) -> string:
|
||||||
variable = "const"
|
variable = "const"
|
||||||
co on "x":
|
co on peer1:
|
||||||
Srv.trial()
|
p1Id <- MyOp.identity("co on")
|
||||||
closure = () -> string:
|
closure = (s: string) -> string:
|
||||||
Srv.inside()
|
if s == "in":
|
||||||
<- variable
|
LocalSrv.inside()
|
||||||
|
p2Id <- MyOp.identity(s)
|
||||||
|
<- p2Id
|
||||||
|
p <- closure("in")
|
||||||
|
<- p
|
||||||
|
|
||||||
on "other":
|
func closureOut3(peer2: string) -> Info:
|
||||||
c <- closure()
|
on peer2:
|
||||||
Srv.noop(c)
|
closure = (s: string) -> Info:
|
||||||
<- true, ""
|
if s == "in":
|
||||||
|
LocalSrv.inside()
|
||||||
|
p2Id <- Peer.identify()
|
||||||
|
<- p2Id
|
||||||
|
p2Id <- closure("on")
|
||||||
|
<- p2Id
|
||||||
|
|
||||||
|
func closureOut(peer2: string) -> Info:
|
||||||
|
closure = func (s: string) -> Info:
|
||||||
|
if s == "in":
|
||||||
|
LocalSrv.inside()
|
||||||
|
p2Id <- Peer.identify()
|
||||||
|
<- p2Id
|
||||||
|
on peer2:
|
||||||
|
p2Id <- closure("on")
|
||||||
|
<- p2Id
|
||||||
|
|
||||||
|
func closureBig(peer1: string, peer2: string) -> string, string:
|
||||||
|
variable = "const"
|
||||||
|
co on peer1:
|
||||||
|
p1Id <- MyOp.identity("co on")
|
||||||
|
closure = func (s: string) -> string:
|
||||||
|
p2Id: *string
|
||||||
|
if s == "in":
|
||||||
|
p2 <- MyOp.identity(s)
|
||||||
|
p2Id <<- p2
|
||||||
|
else:
|
||||||
|
p2Info <- Peer.identify()
|
||||||
|
p2Id <<- p2Info.external_addresses!0
|
||||||
|
<- p2Id!
|
||||||
|
p <- closure("in")
|
||||||
|
on peer2:
|
||||||
|
p2Id <- closure("on")
|
||||||
|
<- p, p2Id
|
@ -1,4 +1,12 @@
|
|||||||
func optionSugar(numSome: ?u32, numNone: ?u32) -> []u32:
|
func emptySugar() -> []u32, []string, []string, *string, ?u32, []u32, ?string:
|
||||||
arr = ?[numNone!, numSome!, "123"]
|
numOp = ?[]
|
||||||
<- arr
|
strArr = []
|
||||||
|
strStream = *[]
|
||||||
|
strEmptyStream: *string
|
||||||
|
for i <- ?[]:
|
||||||
|
strEmptyStream <<- "some"
|
||||||
|
for i <- *[]:
|
||||||
|
strEmptyStream <<- "some"
|
||||||
|
for i <- []:
|
||||||
|
strEmptyStream <<- "some"
|
||||||
|
<- numOp, strArr, strStream, strEmptyStream, [], ?[], *[]
|
||||||
|
@ -17,7 +17,7 @@ val scribeV = "3.6.6"
|
|||||||
name := "aqua-hll"
|
name := "aqua-hll"
|
||||||
|
|
||||||
val commons = Seq(
|
val commons = Seq(
|
||||||
baseAquaVersion := "0.6.3",
|
baseAquaVersion := "0.6.4",
|
||||||
version := baseAquaVersion.value + "-" + sys.env.getOrElse("BUILD_NUMBER", "SNAPSHOT"),
|
version := baseAquaVersion.value + "-" + sys.env.getOrElse("BUILD_NUMBER", "SNAPSHOT"),
|
||||||
scalaVersion := dottyVersion,
|
scalaVersion := dottyVersion,
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
|
@ -160,7 +160,8 @@ class Runner(
|
|||||||
ArrowType(NilType, returnCodomain),
|
ArrowType(NilType, returnCodomain),
|
||||||
ret,
|
ret,
|
||||||
Map(func.name -> funcCallable),
|
Map(func.name -> funcCallable),
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,8 @@ object ScriptOpts extends Logging {
|
|||||||
ArrowType(NilType, NilType),
|
ArrowType(NilType, NilType),
|
||||||
Nil,
|
Nil,
|
||||||
Map(funcName -> callable),
|
Map(funcName -> callable),
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
),
|
),
|
||||||
tConfig
|
tConfig
|
||||||
)
|
)
|
||||||
|
@ -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/hack.aqua"),
|
Path("./aqua-src/closure.aqua"),
|
||||||
List(Path("./aqua")),
|
List(Path("./aqua")),
|
||||||
Option(Path("./target")),
|
Option(Path("./target")),
|
||||||
TypeScriptBackend,
|
TypeScriptBackend,
|
||||||
TransformConfig(wrapWithXor = false)
|
TransformConfig(wrapWithXor = true)
|
||||||
)
|
)
|
||||||
.map {
|
.map {
|
||||||
case Validated.Invalid(errs) =>
|
case Validated.Invalid(errs) =>
|
||||||
|
@ -41,7 +41,11 @@ object ArrowInliner extends Logging {
|
|||||||
|
|
||||||
// Now, substitute the arrows that were received as function arguments
|
// Now, substitute the arrows that were received as function arguments
|
||||||
// Use the new op tree (args are replaced with values, names are unique & safe)
|
// Use the new op tree (args are replaced with values, names are unique & safe)
|
||||||
callableFuncBody <- TagInliner.handleTree(tree, fn.funcName)
|
callableFuncBodyNoTopology <- TagInliner.handleTree(tree, fn.funcName)
|
||||||
|
callableFuncBody =
|
||||||
|
fn.capturedTopology
|
||||||
|
.fold[OpModel](SeqModel)(ApplyTopologyModel.apply)
|
||||||
|
.wrap(callableFuncBodyNoTopology)
|
||||||
|
|
||||||
// Fix return values with exports collected in the body
|
// Fix return values with exports collected in the body
|
||||||
resolvedResult <- RawValueInliner.valueListToModel(result)
|
resolvedResult <- RawValueInliner.valueListToModel(result)
|
||||||
|
@ -120,8 +120,13 @@ object TagInliner extends Logging {
|
|||||||
_ <- Exports[S].resolved(assignTo, cd._1)
|
_ <- Exports[S].resolved(assignTo, cd._1)
|
||||||
} yield Some(SeqModel) -> cd._2
|
} yield Some(SeqModel) -> cd._2
|
||||||
|
|
||||||
case ClosureTag(arrow) =>
|
case ClosureTag(arrow, detach) =>
|
||||||
Arrows[S].resolved(arrow).map(_ => None -> None)
|
if (detach) Arrows[S].resolved(arrow, None).map(_ => None -> None)
|
||||||
|
else
|
||||||
|
for {
|
||||||
|
t <- Mangler[S].findAndForbidName(arrow.name)
|
||||||
|
_ <- Arrows[S].resolved(arrow, Some(t))
|
||||||
|
} yield Some(CaptureTopologyModel(t)) -> None
|
||||||
|
|
||||||
case NextTag(item) =>
|
case NextTag(item) =>
|
||||||
pure(NextModel(item))
|
pure(NextModel(item))
|
||||||
|
@ -25,11 +25,11 @@ trait Arrows[S] extends Scoped[S] {
|
|||||||
* @param e
|
* @param e
|
||||||
* contextual Exports that an arrow captures
|
* contextual Exports that an arrow captures
|
||||||
*/
|
*/
|
||||||
final def resolved(arrow: FuncRaw)(implicit e: Exports[S]): State[S, Unit] =
|
final def resolved(arrow: FuncRaw, topology: Option[String])(implicit e: Exports[S]): State[S, Unit] =
|
||||||
for {
|
for {
|
||||||
exps <- e.exports
|
exps <- e.exports
|
||||||
arrs <- arrows
|
arrs <- arrows
|
||||||
funcArrow = FuncArrow.fromRaw(arrow, arrs, exps)
|
funcArrow = FuncArrow.fromRaw(arrow, arrs, exps, topology)
|
||||||
_ <- save(arrow.name, funcArrow)
|
_ <- save(arrow.name, funcArrow)
|
||||||
} yield ()
|
} yield ()
|
||||||
|
|
||||||
|
@ -22,7 +22,8 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
ArrowType(ProductType(Nil), ProductType(Nil)),
|
ArrowType(ProductType(Nil), ProductType(Nil)),
|
||||||
Nil,
|
Nil,
|
||||||
Map.empty,
|
Map.empty,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
),
|
),
|
||||||
CallModel(Nil, Nil)
|
CallModel(Nil, Nil)
|
||||||
)
|
)
|
||||||
@ -73,7 +74,8 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
),
|
),
|
||||||
Nil,
|
Nil,
|
||||||
Map.empty,
|
Map.empty,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
val model: OpModel.Tree = ArrowInliner
|
val model: OpModel.Tree = ArrowInliner
|
||||||
@ -97,7 +99,8 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
),
|
),
|
||||||
Nil,
|
Nil,
|
||||||
Map("cb" -> cbArrow),
|
Map("cb" -> cbArrow),
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
),
|
),
|
||||||
CallModel(cbVal :: Nil, Nil)
|
CallModel(cbVal :: Nil, Nil)
|
||||||
)
|
)
|
||||||
@ -162,7 +165,8 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
),
|
),
|
||||||
Nil,
|
Nil,
|
||||||
Map.empty,
|
Map.empty,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
val model: OpModel.Tree = ArrowInliner
|
val model: OpModel.Tree = ArrowInliner
|
||||||
@ -186,7 +190,8 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
),
|
),
|
||||||
Nil,
|
Nil,
|
||||||
Map("cb" -> cbArrow),
|
Map("cb" -> cbArrow),
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
),
|
),
|
||||||
CallModel(cbVal :: Nil, Nil)
|
CallModel(cbVal :: Nil, Nil)
|
||||||
)
|
)
|
||||||
@ -241,7 +246,8 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
),
|
),
|
||||||
Nil,
|
Nil,
|
||||||
Map.empty,
|
Map.empty,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
val model: OpModel.Tree = ArrowInliner
|
val model: OpModel.Tree = ArrowInliner
|
||||||
@ -260,7 +266,8 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
ArrowType(ProductType(Nil), ProductType(returnType :: Nil)),
|
ArrowType(ProductType(Nil), ProductType(returnType :: Nil)),
|
||||||
Nil,
|
Nil,
|
||||||
Map(innerName -> inner),
|
Map(innerName -> inner),
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
),
|
),
|
||||||
CallModel(Nil, Nil)
|
CallModel(Nil, Nil)
|
||||||
)
|
)
|
||||||
@ -340,7 +347,8 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
),
|
),
|
||||||
Nil,
|
Nil,
|
||||||
Map.empty,
|
Map.empty,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
// wrapper that export object and call inner function
|
// wrapper that export object and call inner function
|
||||||
@ -358,7 +366,8 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
),
|
),
|
||||||
Nil,
|
Nil,
|
||||||
Map(inner.funcName -> inner),
|
Map(inner.funcName -> inner),
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
),
|
),
|
||||||
CallModel(Nil, Nil)
|
CallModel(Nil, Nil)
|
||||||
)
|
)
|
||||||
@ -426,7 +435,8 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
),
|
),
|
||||||
Nil,
|
Nil,
|
||||||
Map.empty,
|
Map.empty,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
// wrapper that export object and call inner function
|
// wrapper that export object and call inner function
|
||||||
@ -445,7 +455,8 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
),
|
),
|
||||||
Nil,
|
Nil,
|
||||||
Map(inner.funcName -> inner),
|
Map(inner.funcName -> inner),
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
),
|
),
|
||||||
CallModel(Nil, Nil)
|
CallModel(Nil, Nil)
|
||||||
)
|
)
|
||||||
|
@ -140,11 +140,12 @@ case class AssignmentTag(
|
|||||||
}
|
}
|
||||||
|
|
||||||
case class ClosureTag(
|
case class ClosureTag(
|
||||||
func: FuncRaw
|
func: FuncRaw,
|
||||||
|
detach: Boolean
|
||||||
) extends NoExecTag {
|
) extends NoExecTag {
|
||||||
|
|
||||||
override def mapValues(f: ValueRaw => ValueRaw): RawTag =
|
override def mapValues(f: ValueRaw => ValueRaw): RawTag =
|
||||||
ClosureTag(
|
copy(
|
||||||
func.copy(arrow =
|
func.copy(arrow =
|
||||||
func.arrow.copy(
|
func.arrow.copy(
|
||||||
ret = func.arrow.ret.map(_.map(f)),
|
ret = func.arrow.ret.map(_.map(f)),
|
||||||
|
@ -52,8 +52,7 @@ object MakeRes {
|
|||||||
currentPeerId: Option[ValueModel],
|
currentPeerId: Option[ValueModel],
|
||||||
i: Int
|
i: Int
|
||||||
): PartialFunction[OpModel, ResolvedOp.Tree] = {
|
): PartialFunction[OpModel, ResolvedOp.Tree] = {
|
||||||
case SeqModel => SeqRes.leaf
|
case SeqModel | _: OnModel | _: ApplyTopologyModel => SeqRes.leaf
|
||||||
case _: OnModel => SeqRes.leaf
|
|
||||||
case MatchMismatchModel(a, b, s) =>
|
case MatchMismatchModel(a, b, s) =>
|
||||||
MatchMismatchRes(a, b, s).leaf
|
MatchMismatchRes(a, b, s).leaf
|
||||||
case ForModel(item, iter) if !isNillLiteral(iter) => FoldRes(item, iter).leaf
|
case ForModel(item, iter) if !isNillLiteral(iter) => FoldRes(item, iter).leaf
|
||||||
|
@ -114,7 +114,8 @@ object AquaContext extends Logging {
|
|||||||
arrowType,
|
arrowType,
|
||||||
ret.map(_.toRaw),
|
ret.map(_.toRaw),
|
||||||
Map.empty,
|
Map.empty,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -188,7 +189,7 @@ object AquaContext extends Logging {
|
|||||||
|
|
||||||
val (pctx, pcache) = fromRawContext(partContext, ctxCache)
|
val (pctx, pcache) = fromRawContext(partContext, ctxCache)
|
||||||
logger.trace("Got " + func.name + " from raw")
|
logger.trace("Got " + func.name + " from raw")
|
||||||
val fr = FuncArrow.fromRaw(func, pctx.allFuncs, pctx.allValues)
|
val fr = FuncArrow.fromRaw(func, pctx.allFuncs, pctx.allValues, None)
|
||||||
logger.trace("Captured recursively for " + func.name)
|
logger.trace("Captured recursively for " + func.name)
|
||||||
val add = blank.copy(funcs = Map(func.name -> fr))
|
val add = blank.copy(funcs = Map(func.name -> fr))
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@ case class FuncArrow(
|
|||||||
arrowType: ArrowType,
|
arrowType: ArrowType,
|
||||||
ret: List[ValueRaw],
|
ret: List[ValueRaw],
|
||||||
capturedArrows: Map[String, FuncArrow],
|
capturedArrows: Map[String, FuncArrow],
|
||||||
capturedValues: Map[String, ValueModel]
|
capturedValues: Map[String, ValueModel],
|
||||||
|
capturedTopology: Option[String]
|
||||||
) {
|
) {
|
||||||
|
|
||||||
lazy val args: List[(String, Type)] = arrowType.domain.toLabelledList()
|
lazy val args: List[(String, Type)] = arrowType.domain.toLabelledList()
|
||||||
@ -25,7 +26,8 @@ object FuncArrow {
|
|||||||
def fromRaw(
|
def fromRaw(
|
||||||
raw: FuncRaw,
|
raw: FuncRaw,
|
||||||
arrows: Map[String, FuncArrow],
|
arrows: Map[String, FuncArrow],
|
||||||
constants: Map[String, ValueModel]
|
constants: Map[String, ValueModel],
|
||||||
|
topology: Option[String] = None
|
||||||
): FuncArrow =
|
): FuncArrow =
|
||||||
FuncArrow(
|
FuncArrow(
|
||||||
raw.name,
|
raw.name,
|
||||||
@ -33,6 +35,7 @@ object FuncArrow {
|
|||||||
raw.arrow.`type`,
|
raw.arrow.`type`,
|
||||||
raw.arrow.ret,
|
raw.arrow.ret,
|
||||||
arrows,
|
arrows,
|
||||||
constants
|
constants,
|
||||||
|
topology
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -150,5 +150,8 @@ case class JoinModel(operands: NonEmptyList[ValueModel]) extends ForceExecModel
|
|||||||
operands.toList.flatMap(_.usesVarNames).toSet
|
operands.toList.flatMap(_.usesVarNames).toSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case class CaptureTopologyModel(name: String) extends NoExecModel
|
||||||
|
case class ApplyTopologyModel(name: String) extends SeqGroupModel
|
||||||
|
|
||||||
case object EmptyModel extends NoExecModel
|
case object EmptyModel extends NoExecModel
|
||||||
case object NullModel extends NoExecModel
|
case object NullModel extends NoExecModel
|
||||||
|
@ -4,8 +4,10 @@ import aqua.model.transform.pre.InitPeerCallable
|
|||||||
import aqua.model.{
|
import aqua.model.{
|
||||||
CallModel,
|
CallModel,
|
||||||
CallServiceModel,
|
CallServiceModel,
|
||||||
|
ForceExecModel,
|
||||||
LiteralModel,
|
LiteralModel,
|
||||||
MatchMismatchModel,
|
MatchMismatchModel,
|
||||||
|
NoExecModel,
|
||||||
OnModel,
|
OnModel,
|
||||||
OpModel,
|
OpModel,
|
||||||
SeqModel,
|
SeqModel,
|
||||||
@ -26,12 +28,21 @@ case class ErrorsCatcher(
|
|||||||
callable: InitPeerCallable
|
callable: InitPeerCallable
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
private def hasExec(children: Chain[OpModel.Tree]): Boolean =
|
||||||
|
children.exists {
|
||||||
|
case Cofree(head: ForceExecModel, _) =>
|
||||||
|
true
|
||||||
|
case Cofree(_, tail) =>
|
||||||
|
hasExec(tail.value)
|
||||||
|
}
|
||||||
|
|
||||||
def transform(op: OpModel.Tree): OpModel.Tree =
|
def transform(op: OpModel.Tree): OpModel.Tree =
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
var i = 0
|
var i = 0
|
||||||
Cofree
|
Cofree
|
||||||
.cata[Chain, OpModel, OpModel.Tree](op) {
|
.cata[Chain, OpModel, OpModel.Tree](op) {
|
||||||
case (ot @ (OnModel(_, _) | MatchMismatchModel(_, _, _)), children) =>
|
case (ot @ (OnModel(_, _) | MatchMismatchModel(_, _, _)), children)
|
||||||
|
if hasExec(children) =>
|
||||||
i = i + 1
|
i = i + 1
|
||||||
Eval now ot.wrap(
|
Eval now ot.wrap(
|
||||||
XorModel.wrap(
|
XorModel.wrap(
|
||||||
|
@ -48,7 +48,8 @@ case class FuncPreTransformer(
|
|||||||
arrowType,
|
arrowType,
|
||||||
ret.map(_.toRaw),
|
ret.map(_.toRaw),
|
||||||
Map.empty,
|
Map.empty,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +93,8 @@ case class FuncPreTransformer(
|
|||||||
argName -> arrowToCallback(argName, arrowType)
|
argName -> arrowToCallback(argName, arrowType)
|
||||||
}
|
}
|
||||||
.toMap,
|
.toMap,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,11 @@ case class OpModelTreeCursor(
|
|||||||
lazy val children: LazyList[OpModelTreeCursor] =
|
lazy val children: LazyList[OpModelTreeCursor] =
|
||||||
LazyList.unfold(toFirstChild)(_.map(c => c -> c.toNextSibling))
|
LazyList.unfold(toFirstChild)(_.map(c => c -> c.toNextSibling))
|
||||||
|
|
||||||
|
lazy val subtree: LazyList[OpModelTreeCursor] =
|
||||||
|
children.flatMap(c => c #:: c.subtree).prepended(this)
|
||||||
|
|
||||||
def findInside(f: OpModelTreeCursor => Boolean): LazyList[OpModelTreeCursor] =
|
def findInside(f: OpModelTreeCursor => Boolean): LazyList[OpModelTreeCursor] =
|
||||||
children.flatMap(_.findInside(f)).prependedAll(Option.when(f(this))(this))
|
subtree.filter(f)
|
||||||
|
|
||||||
lazy val topology: Topology = Topology.make(this)
|
lazy val topology: Topology = Topology.make(this)
|
||||||
|
|
||||||
|
@ -34,13 +34,51 @@ case class Topology private (
|
|||||||
begins: Topology.Begins,
|
begins: Topology.Begins,
|
||||||
ends: Topology.Ends,
|
ends: Topology.Ends,
|
||||||
after: Topology.After
|
after: Topology.After
|
||||||
) {
|
) extends Logging {
|
||||||
|
|
||||||
val pathOn: Eval[List[OnModel]] = Eval
|
val parent: Option[Topology] = cursor.moveUp.map(_.topology)
|
||||||
.later(cursor.tagsPath.collect { case o: OnModel =>
|
|
||||||
o
|
val parents: LazyList[Topology] =
|
||||||
})
|
LazyList.unfold(parent)(p => p.map(pp => pp -> pp.parent))
|
||||||
.memoize
|
|
||||||
|
// Map of all previously-seen Captured Topologies -- see CaptureTopologyModel, ApplyTopologyModel
|
||||||
|
val capturedTopologies: Eval[Map[String, Topology]] =
|
||||||
|
cursor.moveLeft
|
||||||
|
.fold(Eval.now(Map.empty[String, Topology]))(_.topology.capturedTopologies)
|
||||||
|
.flatMap(tops =>
|
||||||
|
cursor.current.head match {
|
||||||
|
case CaptureTopologyModel(name) =>
|
||||||
|
logger.trace(s"Capturing topology `$name`")
|
||||||
|
Eval.now(tops + (name -> this))
|
||||||
|
case x =>
|
||||||
|
logger.trace(s"Skip $x")
|
||||||
|
cursor.toLastChild
|
||||||
|
.map(_.topology.capturedTopologies.map(_ ++ tops))
|
||||||
|
.getOrElse(Eval.now(tops))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.memoize
|
||||||
|
|
||||||
|
// Current topology location – stack of OnModel's collected from parents branch
|
||||||
|
// ApplyTopologyModel shifts topology to pathOn where this topology was Captured
|
||||||
|
val pathOn: Eval[List[OnModel]] =
|
||||||
|
Eval
|
||||||
|
.later(cursor.current.head match {
|
||||||
|
case o: OnModel =>
|
||||||
|
parent.fold[Eval[List[OnModel]]](Eval.now(o :: Nil))(_.pathOn.map(o :: _))
|
||||||
|
case ApplyTopologyModel(name) =>
|
||||||
|
capturedTopologies.flatMap(
|
||||||
|
_.get(name).fold(
|
||||||
|
Eval.later {
|
||||||
|
logger.error(s"Captured topology `$name` not found")
|
||||||
|
List.empty[OnModel]
|
||||||
|
}
|
||||||
|
)(_.pathOn)
|
||||||
|
)
|
||||||
|
case _ => parent.fold[Eval[List[OnModel]]](Eval.now(Nil))(_.pathOn)
|
||||||
|
})
|
||||||
|
.flatMap(identity)
|
||||||
|
.memoize
|
||||||
|
|
||||||
lazy val firstExecutesOn: Eval[Option[List[OnModel]]] =
|
lazy val firstExecutesOn: Eval[Option[List[OnModel]]] =
|
||||||
(cursor.op match {
|
(cursor.op match {
|
||||||
@ -100,11 +138,6 @@ case class Topology private (
|
|||||||
def findInside(f: Topology => Boolean): LazyList[Topology] =
|
def findInside(f: Topology => Boolean): LazyList[Topology] =
|
||||||
children.flatMap(_.findInside(f)).prependedAll(Option.when(f(this))(this))
|
children.flatMap(_.findInside(f)).prependedAll(Option.when(f(this))(this))
|
||||||
|
|
||||||
val parent: Option[Topology] = cursor.moveUp.map(_.topology)
|
|
||||||
|
|
||||||
val parents: LazyList[Topology] =
|
|
||||||
LazyList.unfold(parent)(p => p.map(pp => pp -> pp.parent))
|
|
||||||
|
|
||||||
lazy val forModel: Option[ForModel] = Option(cursor.op).collect { case ft: ForModel =>
|
lazy val forModel: Option[ForModel] = Option(cursor.op).collect { case ft: ForModel =>
|
||||||
ft
|
ft
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,8 @@ class TransformSpec extends AnyFlatSpec with Matchers {
|
|||||||
stringArrow,
|
stringArrow,
|
||||||
ret :: Nil,
|
ret :: Nil,
|
||||||
Map.empty,
|
Map.empty,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
val bc = TransformConfig()
|
val bc = TransformConfig()
|
||||||
@ -85,7 +86,8 @@ class TransformSpec extends AnyFlatSpec with Matchers {
|
|||||||
stringArrow,
|
stringArrow,
|
||||||
ret :: Nil,
|
ret :: Nil,
|
||||||
Map.empty,
|
Map.empty,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
val bc = TransformConfig(wrapWithXor = false)
|
val bc = TransformConfig(wrapWithXor = false)
|
||||||
@ -130,7 +132,8 @@ class TransformSpec extends AnyFlatSpec with Matchers {
|
|||||||
stringArrow,
|
stringArrow,
|
||||||
VarRaw("v", ScalarType.string) :: Nil,
|
VarRaw("v", ScalarType.string) :: Nil,
|
||||||
Map.empty,
|
Map.empty,
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
val f2: FuncArrow =
|
val f2: FuncArrow =
|
||||||
@ -140,7 +143,8 @@ class TransformSpec extends AnyFlatSpec with Matchers {
|
|||||||
stringArrow,
|
stringArrow,
|
||||||
VarRaw("v", ScalarType.string) :: Nil,
|
VarRaw("v", ScalarType.string) :: Nil,
|
||||||
Map("callable" -> f1),
|
Map("callable" -> f1),
|
||||||
Map.empty
|
Map.empty,
|
||||||
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
val bc = TransformConfig(wrapWithXor = false)
|
val bc = TransformConfig(wrapWithXor = false)
|
||||||
|
@ -13,17 +13,18 @@ import aqua.parser.lift.Span
|
|||||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||||
|
|
||||||
case class ClosureExpr[F[_]](
|
case class ClosureExpr[F[_]](
|
||||||
name: Name[F]
|
name: Name[F],
|
||||||
|
detach: Option[F[Unit]]
|
||||||
) extends Expr[F](ClosureExpr, name) {
|
) extends Expr[F](ClosureExpr, name) {
|
||||||
|
|
||||||
override def mapK[K[_]: Comonad](fk: F ~> K): ClosureExpr[K] =
|
override def mapK[K[_]: Comonad](fk: F ~> K): ClosureExpr[K] =
|
||||||
copy(name.mapK(fk))
|
copy(name.mapK(fk), detach.map(fk.apply))
|
||||||
}
|
}
|
||||||
|
|
||||||
object ClosureExpr extends Expr.Prefix() {
|
object ClosureExpr extends Expr.Prefix() {
|
||||||
override def continueWith: List[Expr.Lexem] = Expr.defer(ArrowExpr) :: Nil
|
override def continueWith: List[Expr.Lexem] = Expr.defer(ArrowExpr) :: Nil
|
||||||
|
|
||||||
override val p: Parser[ClosureExpr[Span.S]] =
|
override val p: Parser[ClosureExpr[Span.S]] =
|
||||||
(Name.p <* ` ` <* `=`).map(ClosureExpr(_))
|
((Name.p <* ` ` <* `=`) ~ (` ` *> `func`.lift).backtrack.?).map(ClosureExpr(_, _))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,18 +14,24 @@ import cats.data.NonEmptyList
|
|||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
|
||||||
class ClosureExprSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
class ClosureExprSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
||||||
|
|
||||||
import AquaSpec._
|
import AquaSpec._
|
||||||
|
|
||||||
val parser = Parser.spanParser
|
val parser = Parser.spanParser
|
||||||
|
|
||||||
"closure header" should "parse" in {
|
"closure header" should "parse" in {
|
||||||
closureExpr("someName =") should be(
|
closureExpr("someName =") should be(
|
||||||
ClosureExpr[Id](toName("someName"))
|
ClosureExpr[Id](toName("someName"), None)
|
||||||
|
)
|
||||||
|
|
||||||
|
closureExpr("someName = func") should be(
|
||||||
|
ClosureExpr[Id](toName("someName"), Some(()))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
"closure" should "parse" in {
|
"closure" should "parse" in {
|
||||||
val script = """func f() -> string:
|
val script =
|
||||||
|
"""func f() -> string:
|
||||||
| closure = (s: string) -> string:
|
| closure = (s: string) -> string:
|
||||||
| LocalSrv.inside()
|
| LocalSrv.inside()
|
||||||
| p2Id <- Peer.identify()
|
| p2Id <- Peer.identify()
|
||||||
@ -43,12 +49,22 @@ class ClosureExprSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
|||||||
qTree.d() shouldBe RootExpr(Token.lift[Id, Unit](()))
|
qTree.d() shouldBe RootExpr(Token.lift[Id, Unit](()))
|
||||||
qTree.d() shouldBe FuncExpr("f")
|
qTree.d() shouldBe FuncExpr("f")
|
||||||
qTree.d() shouldBe ArrowExpr(toArrowType(Nil, Some(scToBt(string))))
|
qTree.d() shouldBe ArrowExpr(toArrowType(Nil, Some(scToBt(string))))
|
||||||
qTree.d() shouldBe ClosureExpr("closure")
|
qTree.d() shouldBe ClosureExpr("closure", None)
|
||||||
qTree.d() shouldBe ArrowExpr(toNamedArrow(("s", scToBt(string)) :: Nil, scToBt(string) :: Nil))
|
qTree.d() shouldBe ArrowExpr(toNamedArrow(("s", scToBt(string)) :: Nil, scToBt(string) :: Nil))
|
||||||
qTree.d() shouldBe CallArrowExpr(Nil, Some(Ability[Id]("LocalSrv")), toName("inside"), Nil)
|
qTree.d() shouldBe CallArrowExpr(Nil, Some(Ability[Id]("LocalSrv")), toName("inside"), Nil)
|
||||||
qTree.d() shouldBe CallArrowExpr(toName("p2Id") :: Nil, Some(Ability[Id]("Peer")), toName("identify"), Nil)
|
qTree.d() shouldBe CallArrowExpr(
|
||||||
|
toName("p2Id") :: Nil,
|
||||||
|
Some(Ability[Id]("Peer")),
|
||||||
|
toName("identify"),
|
||||||
|
Nil
|
||||||
|
)
|
||||||
qTree.d() shouldBe ReturnExpr(NonEmptyList(VarToken[Id](toName("p2Id")), Nil))
|
qTree.d() shouldBe ReturnExpr(NonEmptyList(VarToken[Id](toName("p2Id")), Nil))
|
||||||
qTree.d() shouldBe CallArrowExpr(toName("v") :: Nil, None, toName("closure"), toStr("input") :: Nil)
|
qTree.d() shouldBe CallArrowExpr(
|
||||||
|
toName("v") :: Nil,
|
||||||
|
None,
|
||||||
|
toName("closure"),
|
||||||
|
toStr("input") :: Nil
|
||||||
|
)
|
||||||
qTree.d() shouldBe ReturnExpr(NonEmptyList(VarToken[Id](toName("v")), Nil))
|
qTree.d() shouldBe ReturnExpr(NonEmptyList(VarToken[Id](toName("v")), Nil))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,12 @@ class ClosureSem[S[_]](val expr: ClosureExpr[S]) extends AnyVal {
|
|||||||
): Prog[Alg, Raw] =
|
): Prog[Alg, Raw] =
|
||||||
Prog.after {
|
Prog.after {
|
||||||
case arrow: ArrowRaw =>
|
case arrow: ArrowRaw =>
|
||||||
|
// TODO: if detached, clear all locally-defined abilities
|
||||||
N.defineArrow(
|
N.defineArrow(
|
||||||
expr.name,
|
expr.name,
|
||||||
arrow.`type`,
|
arrow.`type`,
|
||||||
isRoot = false
|
isRoot = false
|
||||||
) as ClosureTag(FuncRaw(expr.name.value, arrow)).funcOpLeaf
|
) as ClosureTag(FuncRaw(expr.name.value, arrow), expr.detach.isDefined).funcOpLeaf
|
||||||
|
|
||||||
case m =>
|
case m =>
|
||||||
Raw.error("Closure must continue with an arrow definition").pure[Alg]
|
Raw.error("Closure must continue with an arrow definition").pure[Alg]
|
||||||
|
@ -34,7 +34,7 @@ class ClosureSemSpec extends AnyFlatSpec with Matchers {
|
|||||||
|
|
||||||
val program: Prog[State[CompilerState[cats.Id], *], Raw] = {
|
val program: Prog[State[CompilerState[cats.Id], *], Raw] = {
|
||||||
import CompilerState.*
|
import CompilerState.*
|
||||||
val expr = ClosureExpr(Name[Id]("closure"))
|
val expr = ClosureExpr(Name[Id]("closure"), None)
|
||||||
val sem = new ClosureSem[Id](expr)
|
val sem = new ClosureSem[Id](expr)
|
||||||
|
|
||||||
sem.program[State[CompilerState[Id], *]]
|
sem.program[State[CompilerState[Id], *]]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user