Skip to content

Commit

Permalink
fix: Canonicalize variable in object creation or copy if variable is …
Browse files Browse the repository at this point in the history
…a stream (#649)
  • Loading branch information
DieMyst authored Jan 27, 2023
1 parent 1bd0d79 commit fedd743
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import aqua.model.{
import aqua.model.inline.raw.RawInliner
import cats.data.Chain
import aqua.model.inline.state.{Arrows, Exports, Mangler}
import aqua.raw.value.{MakeStructRaw, LiteralRaw}
import aqua.raw.value.{LiteralRaw, MakeStructRaw}
import cats.data.{NonEmptyMap, State}
import aqua.model.inline.Inline
import aqua.model.inline.RawValueInliner.{unfold, valueToModel}
Expand All @@ -25,18 +25,24 @@ import cats.syntax.apply.*

object MakeStructRawInliner extends RawInliner[MakeStructRaw] {

private def createObj(fields: NonEmptyMap[String, ValueModel], result: VarModel): OpModel.Tree = {
val args = fields.toSortedMap.toList.flatMap { case (name, value) =>
private def createObj[S: Mangler](
fields: NonEmptyMap[String, ValueModel],
result: VarModel
): State[S, OpModel.Tree] = {
fields.toSortedMap.toList.flatMap { case (name, value) =>
LiteralModel.fromRaw(LiteralRaw.quote(name)) :: value :: Nil
}.map(TagInliner.canonicalizeIfStream(_, None)).sequence.map { argsWithOps =>
val (args, ops) = argsWithOps.unzip
val createOp =
CallServiceModel(
"json",
"obj",
args,
result
).leaf
SeqModel.wrap((ops.flatten :+ createOp): _*)

}
CallServiceModel(
LiteralModel("\"json\"", ScalarType.string),
"obj",
CallModel(
args,
CallModel.Export(result.name, result.`type`) :: Nil
)
).leaf
}

override def apply[S: Mangler: Exports: Arrows](
Expand All @@ -46,11 +52,11 @@ object MakeStructRawInliner extends RawInliner[MakeStructRaw] {
for {
name <- Mangler[S].findAndForbidName(raw.structType.name + "_obj")
foldedFields <- raw.fields.nonEmptyTraverse(unfold(_))
varModel = VarModel(name, raw.baseType)
valsInline = foldedFields.toSortedMap.values.map(_._2).fold(Inline.empty)(_ |+| _)
fields = foldedFields.map(_._1)
objCreation <- createObj(fields, varModel)
} yield {
val varModel = VarModel(name, raw.baseType)
val valsInline = foldedFields.toSortedMap.values.map(_._2).fold(Inline.empty)(_ |+| _)
val fields = foldedFields.map(_._1)
val objCreation = createObj(fields, varModel)
(
varModel,
Inline(
Expand Down
12 changes: 6 additions & 6 deletions model/inline/src/main/scala/aqua/model/inline/TagInliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ object TagInliner extends Logging {
private def none[S]: State[S, (Option[OpModel], Option[OpModel.Tree])] =
State.pure(None -> None)

private def fixModel[S: Mangler: Arrows: Exports](
def canonicalizeIfStream[S: Mangler](
vm: ValueModel,
ops: Option[OpModel.Tree]
): State[S, (ValueModel, Option[OpModel.Tree])] = {
Expand Down Expand Up @@ -125,13 +125,13 @@ object TagInliner extends Logging {
for {
ld <- valueToModel(left)
rd <- valueToModel(right)
ldfixed <- fixModel(ld._1, ld._2)
rdfixed <- fixModel(rd._1, rd._2)
ldCanon <- canonicalizeIfStream(ld._1, ld._2)
rdCanon <- canonicalizeIfStream(rd._1, rd._2)
} yield Some(
MatchMismatchModel(ldfixed._1, rdfixed._1, shouldMatch)
MatchMismatchModel(ldCanon._1, rdCanon._1, shouldMatch)
) -> parDesugarPrefixOpt(
ldfixed._2,
rdfixed._2
ldCanon._2,
rdCanon._2
)

case ForTag(item, iterable, mode) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import aqua.model.{
ValueModel,
VarModel
}
import aqua.model.inline.{Inline, SeqMode}
import aqua.model.inline.{Inline, SeqMode, TagInliner}
import aqua.model.inline.MakeStructRawInliner.createObj
import aqua.model.inline.RawValueInliner.unfold
import aqua.model.inline.state.{Arrows, Exports, Mangler}
Expand All @@ -25,22 +25,24 @@ import cats.syntax.apply.*

object ApplyIntoCopyRawInliner extends Logging {

private def copyObj(
private def copyObj[S: Mangler](
value: VarModel,
fields: NonEmptyMap[String, ValueModel],
result: VarModel
): OpModel.Tree = {
val args = fields.toSortedMap.toList.flatMap { case (name, value) =>
): State[S, OpModel.Tree] = {
fields.toSortedMap.toList.flatMap { case (name, value) =>
LiteralModel.fromRaw(LiteralRaw.quote(name)) :: value :: Nil
}
CallServiceModel(
LiteralModel("\"json\"", ScalarType.string),
"puts",
CallModel(
}.map(TagInliner.canonicalizeIfStream(_, None)).sequence.map { argsWithOps =>
val (args, ops) = argsWithOps.unzip
val copyOp = CallServiceModel(
"json",
"puts",
value +: args,
CallModel.Export(result.name, result.`type`) :: Nil
)
).leaf
result
).leaf
SeqModel.wrap((ops.flatten :+ copyOp): _*)
}

}

def apply[S: Mangler: Exports: Arrows](
Expand All @@ -50,16 +52,16 @@ object ApplyIntoCopyRawInliner extends Logging {
for {
name <- Mangler[S].findAndForbidName(value.name + "_obj_copy")
foldedFields <- intoCopy.fields.nonEmptyTraverse(unfold(_))
varModel = VarModel(name, value.baseType)
valsInline = foldedFields.toSortedMap.values.map(_._2).fold(Inline.empty)(_ |+| _)
fields = foldedFields.map(_._1)
objCopy <- copyObj(value, fields, varModel)
} yield {
val varModel = VarModel(name, value.baseType)
val valsInline = foldedFields.toSortedMap.values.map(_._2).fold(Inline.empty)(_ |+| _)
val fields = foldedFields.map(_._1)
val objCreation = copyObj(value, fields, varModel)
(
varModel,
Inline(
valsInline.flattenValues,
Chain.one(SeqModel.wrap((valsInline.predo :+ objCreation).toList: _*)),
Chain.one(SeqModel.wrap((valsInline.predo :+ objCopy).toList: _*)),
SeqMode
)
)
Expand Down
13 changes: 13 additions & 0 deletions model/src/main/scala/aqua/model/OpModel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import cats.Show
import cats.Eval
import cats.data.NonEmptyList
import aqua.tree.{TreeNode, TreeNodeCompanion}
import aqua.types.ScalarType

import scala.annotation.tailrec

Expand Down Expand Up @@ -140,6 +141,18 @@ case class CallServiceModel(serviceId: ValueModel, funcName: String, call: CallM
override def exportsVarNames: Set[String] = call.exportTo.map(_.name).toSet
}

object CallServiceModel {
def apply(serviceId: String, funcName: String, args: List[ValueModel], result: VarModel): CallServiceModel =
CallServiceModel(
LiteralModel(s"\"$serviceId\"", ScalarType.string),
funcName,
CallModel(
args,
CallModel.Export(result.name, result.`type`) :: Nil
)
)
}

case class CanonicalizeModel(operand: ValueModel, exportTo: CallModel.Export)
extends ForceExecModel {

Expand Down

0 comments on commit fedd743

Please sign in to comment.