Skip to content

Commit

Permalink
Fixed if
Browse files Browse the repository at this point in the history
  • Loading branch information
InversionSpaces committed Jul 31, 2023
1 parent a407b55 commit c747816
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 69 deletions.
46 changes: 34 additions & 12 deletions model/inline/src/main/scala/aqua/model/inline/TagInliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import aqua.model.inline.state.{Arrows, Exports, Mangler}
import aqua.model.*
import aqua.model.inline.RawValueInliner.collectionToModel
import aqua.model.inline.raw.CallArrowRawInliner
import aqua.raw.value.ApplyBinaryOpRaw.Op as BinOp
import aqua.raw.ops.*
import aqua.raw.value.*
import aqua.types.{BoxType, CanonStreamType, StreamType}
import aqua.model.inline.Inline.parDesugarPrefixOpt

import cats.syntax.traverse.*
import cats.syntax.applicative.*
import cats.syntax.flatMap.*
Expand All @@ -18,7 +21,6 @@ import cats.data.{Chain, State, StateT}
import cats.syntax.show.*
import cats.syntax.bifunctor.*
import scribe.{log, Logging}
import aqua.model.inline.Inline.parDesugarPrefixOpt

/**
* [[TagInliner]] prepares a [[RawTag]] for futher processing by converting [[ValueRaw]]s into [[ValueModel]]s.
Expand Down Expand Up @@ -202,12 +204,36 @@ object TagInliner extends Logging {
prefix = parDesugarPrefix(viaF.prependedAll(pif))
)

case IfTag(leftRaw, rightRaw, shouldMatch) =>
(
valueToModel(leftRaw) >>= canonicalizeIfStream.tupled,
valueToModel(rightRaw) >>= canonicalizeIfStream.tupled
).mapN { case ((leftModel, leftPrefix), (rightModel, rightPrefix)) =>
val prefix = parDesugarPrefixOpt(leftPrefix, rightPrefix)
case IfTag(valueRaw) =>
(valueRaw match {
case ApplyBinaryOpRaw(op @ (BinOp.Eq | BinOp.Neq), left, right) =>
(
valueToModel(left),
valueToModel(right)
).mapN { case ((lmodel, lprefix), (rmodel, rprefix)) =>
val prefix = parDesugarPrefixOpt(lprefix, rprefix)
val matchModel = MatchMismatchModel(
left = lmodel,
right = rmodel,
shouldMatch = op match {
case BinOp.Eq => true
case BinOp.Neq => false
}
)

(prefix, matchModel)
}
case _ =>
valueToModel(valueRaw).map { case (valueModel, prefix) =>
val matchModel = MatchMismatchModel(
left = valueModel,
right = LiteralModel.bool(true),
shouldMatch = true
)

(prefix, matchModel)
}
}).map { case (prefix, matchModel) =>
val toModel = (children: Chain[OpModel.Tree]) =>
XorModel.wrap(
children.uncons.map { case (ifBody, elseBody) =>
Expand All @@ -227,11 +253,7 @@ object TagInliner extends Logging {
)
else elseBodyFiltered

MatchMismatchModel(
leftModel,
rightModel,
shouldMatch
).wrap(ifBody) +: elseBodyAugmented
matchModel.wrap(ifBody) +: elseBodyAugmented
}.getOrElse(children)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ object ApplyBinaryOpRawInliner extends RawInliner[ApplyBinaryOpRaw] {
val predo = (resName: String) =>
SeqModel.wrap(
linline.predo ++ rinline.predo :+ XorModel.wrap(
// TODO: Canonicalize values if they are streams
MatchMismatchModel(lmodel, rmodel, shouldMatch).wrap(
FlattenModel(
LiteralModel.bool(true),
Expand Down
2 changes: 1 addition & 1 deletion model/raw/src/main/scala/aqua/raw/ops/RawTag.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ case object ParTag extends ParGroupTag {
case object Par extends GroupTag
}

case class IfTag(left: ValueRaw, right: ValueRaw, equal: Boolean) extends GroupTag
case class IfTag(value: ValueRaw) extends GroupTag

object IfTag {

Expand Down
14 changes: 4 additions & 10 deletions parser/src/main/scala/aqua/parser/expr/func/IfExpr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@ package aqua.parser.expr.func
import aqua.parser.Expr
import aqua.parser.expr.func.{ForExpr, IfExpr}
import aqua.parser.lexer.Token.*
import aqua.parser.lexer.{EqOp, LiteralToken, ValueToken}
import aqua.parser.lexer.{LiteralToken, ValueToken}
import aqua.parser.lift.LiftParser
import aqua.types.LiteralType
import cats.parse.Parser as P
import cats.{~>, Comonad}
import aqua.parser.lift.Span
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}

case class IfExpr[F[_]](left: ValueToken[F], eqOp: EqOp[F], right: ValueToken[F])
extends Expr[F](IfExpr, eqOp) {
case class IfExpr[F[_]](value: ValueToken[F]) extends Expr[F](IfExpr, value) {

override def mapK[K[_]: Comonad](fk: F ~> K): IfExpr[K] =
copy(left.mapK(fk), eqOp.mapK(fk), right.mapK(fk))
copy(value.mapK(fk))
}

object IfExpr extends Expr.AndIndented {
Expand All @@ -24,10 +23,5 @@ object IfExpr extends Expr.AndIndented {
override def validChildren: List[Expr.Lexem] = ForExpr.validChildren

override val p: P[IfExpr[Span.S]] =
(`if` *> ` ` *> ValueToken.`value` ~ (` ` *> EqOp.p ~ (` ` *> ValueToken.`value`)).?).map {
case (left, Some((e, right))) =>
IfExpr(left, e, right)
case (left, None) =>
IfExpr(left, EqOp(left.as(true)), LiteralToken(left.as("true"), LiteralType.bool))
}
(`if` *> ` ` *> ValueToken.`value`).map(IfExpr(_))
}
27 changes: 0 additions & 27 deletions parser/src/main/scala/aqua/parser/lexer/EqOp.scala

This file was deleted.

36 changes: 17 additions & 19 deletions semantics/src/main/scala/aqua/semantics/expr/func/IfSem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import cats.syntax.applicative.*
import cats.syntax.flatMap.*
import cats.syntax.functor.*
import cats.syntax.apply.*
import cats.syntax.traverse.*
import aqua.types.ScalarType

class IfSem[S[_]](val expr: IfExpr[S]) extends AnyVal {

Expand All @@ -29,30 +31,26 @@ class IfSem[S[_]](val expr: IfExpr[S]) extends AnyVal {
): Prog[Alg, Raw] =
Prog
.around(
(V.valueToRaw(expr.left), V.valueToRaw(expr.right)).flatMapN {
case (Some(lt), Some(rt)) =>
T.ensureValuesComparable(
token = expr.token,
left = lt.`type`,
right = rt.`type`
).map(Option.when(_)(lt -> rt))
case _ => None.pure
},
(values: Option[(ValueRaw, ValueRaw)], ops: Raw) =>
values
V.valueToRaw(expr.value)
.flatMap(
_.flatTraverse(raw =>
T.ensureTypeMatches(
token = expr.value,
expected = ScalarType.bool,
givenType = raw.`type`
).map(Option.when(_)(raw))
)
),
(value: Option[ValueRaw], ops: Raw) =>
value
.fold(
Raw.error("`if` expression errored in matching types")
) { case (lt, rt) =>
)(raw =>
ops match {
case FuncOp(op) =>
IfTag(
left = lt,
right = rt,
equal = expr.eqOp.value
).wrap(op).toFuncOp
case FuncOp(op) => IfTag(raw).wrap(op).toFuncOp
case _ => Raw.error("Wrong body of the `if` expression")
}
}
)
.pure
)
.abilitiesScope[S](expr.token)
Expand Down

0 comments on commit c747816

Please sign in to comment.