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 =>
|
case v =>
|
||||||
valueToModel(v, false)
|
valueToModel(v, false)
|
||||||
}).flatMap { case (model, prefix) =>
|
}).flatMap { case (model, prefix) =>
|
||||||
Exports[S]
|
for {
|
||||||
.resolved(assignTo, model)
|
// NOTE: Name <assignTo> should not exist yet
|
||||||
.as(None -> prefix)
|
_ <- Mangler[S].forbidName(assignTo)
|
||||||
|
_ <- Exports[S].resolved(assignTo, model)
|
||||||
|
} yield None -> prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
case ClosureTag(arrow, detach) =>
|
case ClosureTag(arrow, detach) =>
|
||||||
|
@ -75,38 +75,29 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging {
|
|||||||
private def resolveArrow[S: Mangler: Exports: Arrows](
|
private def resolveArrow[S: Mangler: Exports: Arrows](
|
||||||
funcName: String,
|
funcName: String,
|
||||||
call: Call
|
call: Call
|
||||||
): State[S, (List[ValueModel], Inline)] =
|
): State[S, (List[ValueModel], Inline)] = for {
|
||||||
Arrows[S].arrows.flatMap(arrows =>
|
arrows <- Arrows[S].arrows
|
||||||
arrows.get(funcName) match {
|
exports <- Exports[S].exports
|
||||||
case Some(fn) =>
|
arrow = arrows
|
||||||
resolveFuncArrow(fn, call)
|
.get(funcName)
|
||||||
case None =>
|
.orElse(
|
||||||
Exports[S].exports.flatMap { exps =>
|
// if there is no arrow, check if it is stored in Exports as variable and try to resolve it
|
||||||
// if there is no arrow, check if it is stored in Exports as variable and try to resolve it
|
exports
|
||||||
exps.get(funcName) match {
|
.get(funcName)
|
||||||
case Some(VarModel(name, ArrowType(_, _), _)) =>
|
.collect { case VarModel(name, _: ArrowType, _) =>
|
||||||
Arrows[S].arrows.flatMap(arrows =>
|
name
|
||||||
arrows.get(name) match {
|
|
||||||
case Some(fn) =>
|
|
||||||
resolveFuncArrow(fn, call)
|
|
||||||
case _ =>
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
.flatMap(arrows.get)
|
||||||
)
|
)
|
||||||
|
result <- arrow.fold {
|
||||||
|
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](
|
override def apply[S: Mangler: Exports: Arrows](
|
||||||
raw: CallArrowRaw,
|
raw: CallArrowRaw,
|
||||||
|
@ -19,6 +19,9 @@ trait Mangler[S] {
|
|||||||
|
|
||||||
def forbid(names: Set[String]): State[S, Unit]
|
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] =
|
def transformS[R](f: R => S, g: (R, S) => R): Mangler[R] =
|
||||||
new Mangler[R] {
|
new Mangler[R] {
|
||||||
|
|
||||||
|
@ -581,21 +581,24 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* func inner(arg: u16) -> u16 -> u16:
|
* func innerName(arg: u16) -> u16 -> u16:
|
||||||
* closure = (x: u16) -> u16:
|
* closureName = (x: u16) -> u16:
|
||||||
* retval = x + arg
|
* retval = x + arg
|
||||||
* <- retval
|
* <- retval
|
||||||
* <- closure
|
* <- closureName
|
||||||
*
|
*
|
||||||
* func outer() -> u16:
|
* func outer() -> u16:
|
||||||
* c <- inner(42)
|
* outterClosureName <- inner(42)
|
||||||
* retval = 37 + c(1) + c(2)
|
* <body(outterClosureName.type)>
|
||||||
* <- retval
|
* <- outterResultName
|
||||||
*/
|
*/
|
||||||
"arrow inliner" should "leave meta after returned closure inlining" in {
|
def closureReturnModel(
|
||||||
val innerName = "inner"
|
innerName: String,
|
||||||
val closureName = "closure"
|
closureName: String,
|
||||||
|
outterClosureName: String,
|
||||||
|
outterResultName: String,
|
||||||
|
body: (ArrowType) => List[RawTag.Tree]
|
||||||
|
) = {
|
||||||
val closureArg = VarRaw(
|
val closureArg = VarRaw(
|
||||||
"x",
|
"x",
|
||||||
ScalarType.u16
|
ScalarType.u16
|
||||||
@ -689,33 +692,13 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
)
|
)
|
||||||
).leaf
|
).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(
|
val outerBody = SeqTag.wrap(
|
||||||
innerCall,
|
innerCall +: body(closureType) :+ ReturnTag(
|
||||||
AssignmentTag(
|
|
||||||
RawBuilder.add(
|
|
||||||
RawBuilder.add(
|
|
||||||
LiteralRaw("37", LiteralType.number),
|
|
||||||
closureCall("1")
|
|
||||||
),
|
|
||||||
closureCall("2")
|
|
||||||
),
|
|
||||||
outterRes.name
|
|
||||||
).leaf,
|
|
||||||
ReturnTag(
|
|
||||||
NonEmptyList
|
NonEmptyList
|
||||||
.one(
|
.one(
|
||||||
outterRes
|
outterRes
|
||||||
)
|
)
|
||||||
).leaf
|
).leaf: _*
|
||||||
)
|
)
|
||||||
|
|
||||||
val outer = FuncArrow(
|
val outer = FuncArrow(
|
||||||
@ -731,13 +714,63 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
capturedTopology = None
|
capturedTopology = None
|
||||||
)
|
)
|
||||||
|
|
||||||
val model = ArrowInliner
|
ArrowInliner
|
||||||
.callArrow[InliningState](
|
.callArrow[InliningState](
|
||||||
outer,
|
outer,
|
||||||
CallModel(Nil, Nil)
|
CallModel(Nil, Nil)
|
||||||
)
|
)
|
||||||
.runA(InliningState())
|
.runA(InliningState())
|
||||||
.value
|
.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) =>
|
val closureCallModel = (x: String, o: VarModel) =>
|
||||||
MetaModel
|
MetaModel
|
||||||
@ -958,6 +991,136 @@ class ArrowInlinerSpec extends AnyFlatSpec with Matchers {
|
|||||||
model.equalsOrShowDiff(expected) shouldEqual true
|
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:
|
data Prod:
|
||||||
value: string
|
value: string
|
||||||
|
Loading…
x
Reference in New Issue
Block a user