mirror of
https://github.com/fluencelabs/aqua.git
synced 2025-03-15 11:40:50 +00:00
fix(compiler): Fix closure call compilation [fixes LNG-193] (#741)
This commit is contained in:
parent
8c2240d3b1
commit
c5534a964c
@ -222,9 +222,11 @@ object TagInliner extends Logging {
|
||||
case v =>
|
||||
valueToModel(v, false)
|
||||
}).flatMap { case (model, prefix) =>
|
||||
Exports[S]
|
||||
.resolved(assignTo, model)
|
||||
.as(None -> prefix)
|
||||
for {
|
||||
// NOTE: Name <assignTo> should not exist yet
|
||||
_ <- Mangler[S].forbidName(assignTo)
|
||||
_ <- Exports[S].resolved(assignTo, model)
|
||||
} yield None -> prefix
|
||||
}
|
||||
|
||||
case ClosureTag(arrow, detach) =>
|
||||
|
@ -75,38 +75,29 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging {
|
||||
private def resolveArrow[S: Mangler: Exports: Arrows](
|
||||
funcName: String,
|
||||
call: Call
|
||||
): State[S, (List[ValueModel], Inline)] =
|
||||
Arrows[S].arrows.flatMap(arrows =>
|
||||
arrows.get(funcName) match {
|
||||
case Some(fn) =>
|
||||
resolveFuncArrow(fn, call)
|
||||
case None =>
|
||||
Exports[S].exports.flatMap { exps =>
|
||||
): State[S, (List[ValueModel], Inline)] = for {
|
||||
arrows <- Arrows[S].arrows
|
||||
exports <- Exports[S].exports
|
||||
arrow = arrows
|
||||
.get(funcName)
|
||||
.orElse(
|
||||
// if there is no arrow, check if it is stored in Exports as variable and try to resolve it
|
||||
exps.get(funcName) match {
|
||||
case Some(VarModel(name, ArrowType(_, _), _)) =>
|
||||
Arrows[S].arrows.flatMap(arrows =>
|
||||
arrows.get(name) match {
|
||||
case Some(fn) =>
|
||||
resolveFuncArrow(fn, call)
|
||||
case _ =>
|
||||
exports
|
||||
.get(funcName)
|
||||
.collect { case VarModel(name, _: ArrowType, _) =>
|
||||
name
|
||||
}
|
||||
.flatMap(arrows.get)
|
||||
)
|
||||
result <- arrow.fold {
|
||||
logger.error(
|
||||
s"Inlining, cannot find arrow $funcName, available: ${arrows.keys
|
||||
.mkString(", ")}"
|
||||
)
|
||||
|
||||
State.pure(Nil -> Inline.empty)
|
||||
}
|
||||
)
|
||||
case _ =>
|
||||
logger.error(
|
||||
s"Inlining, cannot find arrow $funcName, available: ${arrows.keys
|
||||
.mkString(", ")}"
|
||||
)
|
||||
State.pure(Nil -> Inline.empty)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}(resolveFuncArrow(_, call))
|
||||
} yield result
|
||||
|
||||
override def apply[S: Mangler: Exports: Arrows](
|
||||
raw: CallArrowRaw,
|
||||
|
@ -19,6 +19,9 @@ trait Mangler[S] {
|
||||
|
||||
def forbid(names: Set[String]): State[S, Unit]
|
||||
|
||||
def forbidName(name: String): State[S, Unit] =
|
||||
forbid(Set(name))
|
||||
|
||||
def transformS[R](f: R => S, g: (R, S) => R): Mangler[R] =
|
||||
new Mangler[R] {
|
||||
|
||||
|
@ -581,21 +581,24 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
||||
}
|
||||
|
||||
/**
|
||||
* func inner(arg: u16) -> u16 -> u16:
|
||||
* closure = (x: u16) -> u16:
|
||||
* func innerName(arg: u16) -> u16 -> u16:
|
||||
* closureName = (x: u16) -> u16:
|
||||
* retval = x + arg
|
||||
* <- retval
|
||||
* <- closure
|
||||
* <- closureName
|
||||
*
|
||||
* func outer() -> u16:
|
||||
* c <- inner(42)
|
||||
* retval = 37 + c(1) + c(2)
|
||||
* <- retval
|
||||
* outterClosureName <- inner(42)
|
||||
* <body(outterClosureName.type)>
|
||||
* <- outterResultName
|
||||
*/
|
||||
"arrow inliner" should "leave meta after returned closure inlining" in {
|
||||
val innerName = "inner"
|
||||
val closureName = "closure"
|
||||
|
||||
def closureReturnModel(
|
||||
innerName: String,
|
||||
closureName: String,
|
||||
outterClosureName: String,
|
||||
outterResultName: String,
|
||||
body: (ArrowType) => List[RawTag.Tree]
|
||||
) = {
|
||||
val closureArg = VarRaw(
|
||||
"x",
|
||||
ScalarType.u16
|
||||
@ -689,33 +692,13 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
||||
)
|
||||
).leaf
|
||||
|
||||
val closureCall = (i: String) =>
|
||||
CallArrowRaw(
|
||||
ability = None,
|
||||
name = outterClosure.name,
|
||||
arguments = List(LiteralRaw(i, LiteralType.number)),
|
||||
baseType = closureType,
|
||||
serviceId = None
|
||||
)
|
||||
|
||||
val outerBody = SeqTag.wrap(
|
||||
innerCall,
|
||||
AssignmentTag(
|
||||
RawBuilder.add(
|
||||
RawBuilder.add(
|
||||
LiteralRaw("37", LiteralType.number),
|
||||
closureCall("1")
|
||||
),
|
||||
closureCall("2")
|
||||
),
|
||||
outterRes.name
|
||||
).leaf,
|
||||
ReturnTag(
|
||||
innerCall +: body(closureType) :+ ReturnTag(
|
||||
NonEmptyList
|
||||
.one(
|
||||
outterRes
|
||||
)
|
||||
).leaf
|
||||
).leaf: _*
|
||||
)
|
||||
|
||||
val outer = FuncArrow(
|
||||
@ -731,13 +714,63 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
||||
capturedTopology = None
|
||||
)
|
||||
|
||||
val model = ArrowInliner
|
||||
ArrowInliner
|
||||
.callArrow[InliningState](
|
||||
outer,
|
||||
CallModel(Nil, Nil)
|
||||
)
|
||||
.runA(InliningState())
|
||||
.value
|
||||
}
|
||||
|
||||
/**
|
||||
* func inner(arg: u16) -> u16 -> u16:
|
||||
* closure = (x: u16) -> u16:
|
||||
* retval = x + arg
|
||||
* <- retval
|
||||
* <- closure
|
||||
*
|
||||
* func outer() -> u16:
|
||||
* c <- inner(42)
|
||||
* retval = 37 + c(1) + c(2)
|
||||
* <- retval
|
||||
*/
|
||||
"arrow inliner" should "leave meta after returned closure inlining" in {
|
||||
val innerName = "inner"
|
||||
val closureName = "closure"
|
||||
val outterClosureName = "c"
|
||||
val outterResultName = "retval"
|
||||
|
||||
val closureCall = (closureType: ArrowType, i: String) =>
|
||||
CallArrowRaw(
|
||||
ability = None,
|
||||
name = outterClosureName,
|
||||
arguments = List(LiteralRaw(i, LiteralType.number)),
|
||||
baseType = closureType,
|
||||
serviceId = None
|
||||
)
|
||||
|
||||
val body = (closureType: ArrowType) =>
|
||||
List(
|
||||
AssignmentTag(
|
||||
RawBuilder.add(
|
||||
RawBuilder.add(
|
||||
LiteralRaw("37", LiteralType.number),
|
||||
closureCall(closureType, "1")
|
||||
),
|
||||
closureCall(closureType, "2")
|
||||
),
|
||||
outterResultName
|
||||
).leaf
|
||||
)
|
||||
|
||||
val model = closureReturnModel(
|
||||
innerName = innerName,
|
||||
closureName = closureName,
|
||||
outterClosureName = outterClosureName,
|
||||
outterResultName = outterResultName,
|
||||
body = body
|
||||
)
|
||||
|
||||
val closureCallModel = (x: String, o: VarModel) =>
|
||||
MetaModel
|
||||
@ -958,6 +991,136 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
||||
model.equalsOrShowDiff(expected) shouldEqual true
|
||||
}
|
||||
|
||||
/**
|
||||
* func inner(arg: u16) -> u16 -> u16:
|
||||
* closure = (x: u16) -> u16:
|
||||
* retval = x + arg
|
||||
* <- retval
|
||||
* <- closure
|
||||
*
|
||||
* func outer() -> u16:
|
||||
* c <- inner(42)
|
||||
* b = c
|
||||
* a = b
|
||||
* retval = 37 + a(1) + b(2) + c{3}
|
||||
* <- retval
|
||||
*/
|
||||
"arrow inliner" should "correctly inline renamed closure [bug LNG-193]" in {
|
||||
val innerName = "inner"
|
||||
val closureName = "closure"
|
||||
val outterClosureName = "c"
|
||||
val outterResultName = "retval"
|
||||
val firstRename = "b"
|
||||
val secondRename = "a"
|
||||
|
||||
val closureCall = (name: String, closureType: ArrowType, i: String) =>
|
||||
CallArrowRaw(
|
||||
ability = None,
|
||||
name = name,
|
||||
arguments = List(LiteralRaw(i, LiteralType.number)),
|
||||
baseType = closureType,
|
||||
serviceId = None
|
||||
)
|
||||
|
||||
val body = (closureType: ArrowType) =>
|
||||
List(
|
||||
AssignmentTag(
|
||||
VarRaw(outterClosureName, closureType),
|
||||
firstRename
|
||||
).leaf,
|
||||
AssignmentTag(
|
||||
VarRaw(firstRename, closureType),
|
||||
secondRename
|
||||
).leaf,
|
||||
AssignmentTag(
|
||||
RawBuilder
|
||||
.add(
|
||||
RawBuilder.add(
|
||||
RawBuilder.add(
|
||||
LiteralRaw("37", LiteralType.number),
|
||||
closureCall(secondRename, closureType, "1")
|
||||
),
|
||||
closureCall(firstRename, closureType, "2")
|
||||
),
|
||||
closureCall(outterClosureName, closureType, "3")
|
||||
),
|
||||
outterResultName
|
||||
).leaf
|
||||
)
|
||||
|
||||
val model = closureReturnModel(
|
||||
innerName = innerName,
|
||||
closureName = closureName,
|
||||
outterClosureName = outterClosureName,
|
||||
outterResultName = outterResultName,
|
||||
body = body
|
||||
)
|
||||
|
||||
val closureCallModel = (x: String, o: VarModel) =>
|
||||
MetaModel
|
||||
.CallArrowModel(closureName)
|
||||
.wrap(
|
||||
ApplyTopologyModel(closureName)
|
||||
.wrap(
|
||||
ModelBuilder
|
||||
.add(
|
||||
LiteralModel(x, LiteralType.number),
|
||||
LiteralModel("42", LiteralType.number)
|
||||
)(o)
|
||||
.leaf
|
||||
)
|
||||
)
|
||||
|
||||
/* WARNING: This naming is unstable */
|
||||
val tempAdd0 = VarModel("add-0", ScalarType.u16)
|
||||
val tempAdd1 = VarModel("add-1", ScalarType.u16)
|
||||
val tempAdd2 = VarModel("add-2", ScalarType.u16)
|
||||
val tempAdd3 = VarModel("add-3", ScalarType.u16)
|
||||
val tempAdd4 = VarModel("add-4", ScalarType.u16)
|
||||
val tempAdd = VarModel("add", ScalarType.u16)
|
||||
|
||||
val expected = SeqModel.wrap(
|
||||
MetaModel
|
||||
.CallArrowModel(innerName)
|
||||
.wrap(
|
||||
CaptureTopologyModel(closureName).leaf
|
||||
),
|
||||
SeqModel.wrap(
|
||||
ParModel.wrap(
|
||||
SeqModel.wrap(
|
||||
ParModel.wrap(
|
||||
SeqModel.wrap(
|
||||
closureCallModel("1", tempAdd2),
|
||||
ModelBuilder
|
||||
.add(
|
||||
LiteralModel("37", LiteralType.number),
|
||||
tempAdd2
|
||||
)(tempAdd1)
|
||||
.leaf
|
||||
),
|
||||
closureCallModel("2", tempAdd3)
|
||||
),
|
||||
ModelBuilder
|
||||
.add(
|
||||
tempAdd1,
|
||||
tempAdd3
|
||||
)(tempAdd0)
|
||||
.leaf
|
||||
),
|
||||
closureCallModel("3", tempAdd4)
|
||||
),
|
||||
ModelBuilder
|
||||
.add(
|
||||
tempAdd0,
|
||||
tempAdd4
|
||||
)(tempAdd)
|
||||
.leaf
|
||||
)
|
||||
)
|
||||
|
||||
model.equalsOrShowDiff(expected) shouldEqual true
|
||||
}
|
||||
|
||||
/*
|
||||
data Prod:
|
||||
value: string
|
||||
|
Loading…
x
Reference in New Issue
Block a user