Skip to content

Commit

Permalink
Implement inlining
Browse files Browse the repository at this point in the history
  • Loading branch information
InversionSpaces committed Jul 26, 2023
1 parent e199c56 commit 76fbb12
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import aqua.model.inline.Inline
import aqua.model.inline.RawValueInliner.{unfold, valueToModel}
import aqua.types.{ArrowType, ScalarType}
import aqua.raw.value.ApplyBoolOpRaw
import aqua.raw.value.ApplyBoolOpRaw.BoolOpRaw.*

import cats.data.Chain
import cats.syntax.traverse.*
Expand All @@ -17,14 +18,96 @@ import cats.syntax.functor.*
import cats.syntax.flatMap.*
import cats.syntax.apply.*
import cats.syntax.foldable.*
import cats.syntax.applicative.*

object ApplyBoolOpRawInliner extends RawInliner[ApplyBoolOpRaw] {

override def apply[S: Mangler: Exports: Arrows](
raw: ApplyBoolOpRaw,
propertiesAllowed: Boolean
): State[S, (ValueModel, Inline)] =
(unfold(raw.left), unfold(raw.right)).flatMapN { case ((lm, linline), (rm, rinline)) =>
???
): State[S, (ValueModel, Inline)] = for {
left <- unfold(raw.left)
(lmodel, linline) = left
right <- unfold(raw.right)
(rmodel, rinline) = right

result <- (lmodel, rmodel) match {
// Optimize in case of left value is known at compile time
case (LiteralModel.Bool(lvalue), _) =>
(raw.op match {
case And if !lvalue => (LiteralModel.bool(false), linline)
case Or if lvalue => (LiteralModel.bool(true), linline)
case _ => (rmodel, Inline(linline.predo ++ rinline.predo))
}).pure[State[S, *]]
// Optimize in case of right value is known at compile time and it has no computation
case (_, LiteralModel.Bool(rvalue)) if rinline.predo.isEmpty =>
(raw.op match {
case And if !rvalue => (LiteralModel.bool(false), linline)
case Or if rvalue => (LiteralModel.bool(true), linline)
case _ => (lmodel, linline)
}).pure[State[S, *]]
// Produce unoptimized inline
case _ => fullInline(lmodel, rmodel, linline, rinline, raw.op)
}
} yield result

private def fullInline[S: Mangler: Exports: Arrows](
lmodel: ValueModel,
rmodel: ValueModel,
linline: Inline,
rinline: Inline,
op: ApplyBoolOpRaw.BoolOpRaw
): State[S, (ValueModel, Inline)] = {
val (name, compareWith) = op match {
case And => ("and", true)
case Or => ("or", false)
}

/*
* (seq
* <left-inline>
* (xor
* (match <left-res> <compare-with>
* (seq
* <right-inline>
* (ap <right-res> <res-name>)
* )
* )
* (ap <left-res> <res-name>)
* )
* )
*
* TODO: Handle errors in <right-inline>
*/
val predo = (resName: String) =>
SeqModel.wrap(
linline.predo :+ XorModel.wrap(
MatchMismatchModel(
lmodel,
LiteralModel.bool(compareWith),
shouldMatch = true
).wrap(
SeqModel.wrap(
rinline.predo :+ FlattenModel(
rmodel,
resName
).leaf
)
),
FlattenModel(
lmodel,
resName
).leaf
)
)

Mangler[S]
.findAndForbidName(name)
.map(resName =>
(
VarModel(resName, ScalarType.bool),
Inline(Chain.one(predo(resName)))
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import cats.syntax.monoid.*
import cats.syntax.functor.*
import cats.syntax.flatMap.*
import cats.syntax.apply.*
import cats.syntax.foldable.*

object ApplyIntoCopyRawInliner extends Logging {

Expand Down Expand Up @@ -53,14 +54,14 @@ object ApplyIntoCopyRawInliner extends Logging {
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)(_ |+| _).desugar
valsInline = foldedFields.toList.foldMap { case (_, inline) => inline }.desugar
fields = foldedFields.map(_._1)
objCopy <- copyObj(value, fields, varModel)
} yield {
(
varModel,
Inline(
Chain.one(SeqModel.wrap((valsInline.predo :+ objCopy).toList: _*)),
Chain.one(SeqModel.wrap(valsInline.predo :+ objCopy)),
SeqMode
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging {
Chain(
SeqModel.wrap(
sd._2.toList ++
cd._2.toList :+ CallServiceModel(sd._1, value.name, cd._1).leaf: _*
cd._2.toList :+ CallServiceModel(sd._1, value.name, cd._1).leaf
)
)
)
Expand Down
15 changes: 15 additions & 0 deletions model/src/main/scala/aqua/model/ValueModel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ case class LiteralModel(value: String, `type`: Type) extends ValueModel {

object LiteralModel {

/**
* Used to match bool literals in pattern matching
*/
object Bool {

def unapply(lm: LiteralModel): Option[Boolean] =
lm match {
case LiteralModel("true", ScalarType.bool | LiteralType.bool) => true.some
case LiteralModel("false", ScalarType.bool | LiteralType.bool) => false.some
case _ => none
}
}

// AquaVM will return empty string for
// %last_error%.$.error_code if there is no %last_error%
val emptyErrorCode = quote("")
Expand All @@ -71,6 +84,8 @@ object LiteralModel {
def quote(str: String): LiteralModel = LiteralModel(s"\"$str\"", LiteralType.string)

def number(n: Int): LiteralModel = LiteralModel(n.toString, LiteralType.forInt(n))

def bool(b: Boolean): LiteralModel = LiteralModel(b.toString.toLowerCase, LiteralType.bool)
}

sealed trait PropertyModel {
Expand Down

0 comments on commit 76fbb12

Please sign in to comment.