diff --git a/model/inline/src/main/scala/aqua/model/inline/ArrowInliner.scala b/model/inline/src/main/scala/aqua/model/inline/ArrowInliner.scala index f5fd6327b..2b4664511 100644 --- a/model/inline/src/main/scala/aqua/model/inline/ArrowInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/ArrowInliner.scala @@ -3,7 +3,7 @@ package aqua.model.inline import aqua.errors.Errors.internalError import aqua.model import aqua.model.* -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.inline.state.{Exports, Mangler} import aqua.raw.ops.RawTag import aqua.raw.value.{ValueRaw, VarRaw} import aqua.types.* @@ -26,7 +26,7 @@ import scribe.Logging */ object ArrowInliner extends Logging { - def callArrow[S: Exports: Arrows: Mangler]( + def callArrow[S: Exports: Mangler]( arrow: FuncArrow, call: CallModel ): State[S, OpModel.Tree] = @@ -42,7 +42,7 @@ object ArrowInliner extends Logging { ) // push results to streams if they are exported to streams - private def pushStreamResults[S: Mangler: Exports: Arrows]( + private def pushStreamResults[S: Mangler: Exports]( outsideStreamNames: Set[String], exportTo: List[CallModel.Export], results: List[ValueRaw] @@ -83,7 +83,7 @@ object ArrowInliner extends Logging { ) // Apply a callable function, get its fully resolved body & optional value, if any - private def inline[S: Mangler: Arrows: Exports]( + private def inline[S: Mangler: Exports]( fn: FuncArrow, call: CallModel, outsideDeclaredStreams: Set[String] @@ -116,7 +116,8 @@ object ArrowInliner extends Logging { // find and get resolved arrows if we return them from the function returnedArrows = rets.collect { case VarModel(name, _: ArrowType, _) => name }.toSet - arrowsToSave <- Arrows[S].pickArrows(returnedArrows) + // TODO: rewrite + // arrowsToSave <- Arrows[S].pickArrows(returnedArrows) body = SeqModel.wrap(callableFuncBody :: ops) } yield InlineResult( @@ -213,13 +214,14 @@ object ArrowInliner extends Logging { } } - private def getAbilityArrows[S: Arrows: Exports]( + private def getAbilityArrows[S: Exports]( name: String, `type`: GeneralAbilityType ): State[S, Map[String, FuncArrow]] = for { exports <- Exports[S].exports - arrows <- Arrows[S].arrows - } yield getAbilityArrows(name, None, `type`, exports, arrows) + // TODO: Rewrite + // arrows <- Arrows[S].arrows + } yield getAbilityArrows(name, None, `type`, exports, ???) final case class Renamed[T]( renames: Map[String, String], @@ -298,9 +300,10 @@ object ArrowInliner extends Logging { } // Gather abilities related arrows - val abilitiesArrows = abilitiesValues.toList.foldMap { case (_, (_, values)) => - Arrows.arrowsByValues(fn.capturedArrows, values).toList - }.toMap + val abilitiesArrows = ??? + // abilitiesValues.toList.foldMap { case (_, (_, values)) => + // Arrows.arrowsByValues(fn.capturedArrows, values).toList + // }.toMap // Gather all other values and arrows that are not related to abilities val otherValues = fn.capturedValues -- abilitiesValuesKeys @@ -354,10 +357,11 @@ object ArrowInliner extends Logging { // Rename values and arrows unrelated to abilities otherValuesRenamed <- findNewNames(otherValues) - otherArrowsValues = Arrows.arrowsByValues( - otherArrows, - otherValues - ) + otherArrowsValues = ??? + // Arrows.arrowsByValues( + // otherArrows, + // otherValues + // ) otherArrowsValuesRenamed = Renamed( otherValuesRenamed.renames.filterKeys(otherArrowsValues.keySet).toMap, otherArrowsValues.renamed(otherValuesRenamed.renames) @@ -414,7 +418,7 @@ object ArrowInliner extends Logging { * @param arrows Arrows that are available for callee * @return Prepared function */ - private def prelude[S: Mangler: Arrows: Exports]( + private def prelude[S: Mangler: Exports]( fn: FuncArrow, call: CallModel, exports: Map[String, ValueModel], @@ -481,35 +485,37 @@ object ArrowInliner extends Logging { ret = fn.ret.map(_.renameVars(renaming)) - _ <- Arrows[S].resolved(arrowsResolved) + // TODO: Rewrite + // _ <- Arrows[S].resolved(arrowsResolved) _ <- Exports[S].resolved(exportsResolved) } yield (fn.copy(body = treeWithCanons, ret = ret), SeqModel.wrap(canons)) - private[inline] def callArrowRet[S: Exports: Arrows: Mangler]( + private[inline] def callArrowRet[S: Exports: Mangler]( arrow: FuncArrow, call: CallModel ): State[S, (OpModel.Tree, List[ValueModel])] = for { - passArrows <- Arrows[S].pickArrows(call.arrowArgNames) + // TODO: Rewrite + // passArrows <- Arrows[S].pickArrows(call.arrowArgNames) arrowsFromAbilities <- call.abilityArgs .traverse(getAbilityArrows.tupled) .map(_.flatMap(_.toList).toMap) + passArrows = ??? exports <- Exports[S].exports streams <- getOutsideStreamNames arrows = passArrows ++ arrowsFromAbilities - + inlineResult <- Exports[S].scope( - Arrows[S].scope( - for { - // Process renamings, prepare environment - fnCanon <- ArrowInliner.prelude(arrow, call, exports, arrows) - inlineResult <- ArrowInliner.inline(fnCanon._1, call, streams) - } yield inlineResult.copy(tree = SeqModel.wrap(fnCanon._2, inlineResult.tree)) - ) + for { + // Process renamings, prepare environment + fnCanon <- ArrowInliner.prelude(arrow, call, exports, arrows) + inlineResult <- ArrowInliner.inline(fnCanon._1, call, streams) + } yield inlineResult.copy(tree = SeqModel.wrap(fnCanon._2, inlineResult.tree)) ) exportTo = call.exportTo.map(_.name) - _ <- Arrows[S].resolved(inlineResult.arrowsToSave) + // TODO: Rewrite + // _ <- Arrows[S].resolved(inlineResult.arrowsToSave) _ <- Exports[S].resolved( exportTo .zip(inlineResult.returnedValues) diff --git a/model/inline/src/main/scala/aqua/model/inline/MakeStructRawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/MakeStructRawInliner.scala index d8fdc1333..b9b30aa9f 100644 --- a/model/inline/src/main/scala/aqua/model/inline/MakeStructRawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/MakeStructRawInliner.scala @@ -1,15 +1,15 @@ package aqua.model.inline +import aqua.model.* import aqua.model.inline.RawValueInliner.unfold import aqua.model.inline.raw.RawInliner -import aqua.model.inline.state.{Arrows, Exports, Mangler} -import aqua.model.* +import aqua.model.inline.state.{Exports, Mangler} import aqua.raw.value.MakeStructRaw import aqua.types.{StreamMapType, StructType} import cats.data.{Chain, NonEmptyMap, State} -import cats.syntax.foldable.* import cats.syntax.bifunctor.* +import cats.syntax.foldable.* import cats.syntax.functor.* object MakeStructRawInliner extends RawInliner[MakeStructRaw] { @@ -58,7 +58,7 @@ object MakeStructRawInliner extends RawInliner[MakeStructRaw] { constructThroughMap(mapName, mapType, CallModel.Export(resultName, resultType), fields) } - override def apply[S: Mangler: Exports: Arrows]( + override def apply[S: Mangler: Exports]( raw: MakeStructRaw, propertiesAllowed: Boolean ): State[S, (ValueModel, Inline)] = { diff --git a/model/inline/src/main/scala/aqua/model/inline/RawValueInliner.scala b/model/inline/src/main/scala/aqua/model/inline/RawValueInliner.scala index 365c5bfa0..325832010 100644 --- a/model/inline/src/main/scala/aqua/model/inline/RawValueInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/RawValueInliner.scala @@ -3,7 +3,8 @@ package aqua.model.inline import aqua.model.* import aqua.model.inline.Inline.MergeMode.* import aqua.model.inline.raw.* -import aqua.model.inline.state.{Arrows, Counter, Exports, Mangler} +import aqua.model.inline.state.Exports.Export +import aqua.model.inline.state.{Counter, Exports, Mangler} import aqua.raw.ops.* import aqua.raw.value.* import aqua.types.{ArrayType, LiteralType, OptionType, StreamType} @@ -23,21 +24,26 @@ object RawValueInliner extends Logging { import aqua.model.inline.Inline.* - private[inline] def unfold[S: Mangler: Exports: Arrows]( + private[inline] def unfold[S: Mangler: Exports]( raw: ValueRaw, propertiesAllowed: Boolean = true - ): State[S, (ValueModel, Inline)] = for { + ): State[S, (Export, Inline)] = for { optimized <- StateT.liftF(Optimization.optimize(raw)) _ <- StateT.liftF(Eval.later(logger.trace("OPTIMIZIED " + optimized))) result <- optimized match { + case LiteralRaw(value, t) => + val model = LiteralModel(value, t) + val exp = Export.Value(model) + State.pure(exp -> Inline.empty) + case VarRaw(name, t) => for { - exports <- Exports[S].exports - model = VarModel(name, t, Chain.empty).resolveWith(exports) - } yield model -> Inline.empty - - case LiteralRaw(value, t) => - State.pure(LiteralModel(value, t) -> Inline.empty) + maybeExport <- Exports[S].get(name) + model = VarModel(name, t) + exp = maybeExport.getOrElse( + Export.Value(model) + ) + } yield exp -> Inline.empty case alr: ApplyPropertyRaw => ApplyPropertiesRawInliner(alr, propertiesAllowed) @@ -69,7 +75,7 @@ object RawValueInliner extends Logging { } } yield result - private[inline] def inlineToTree[S: Mangler: Exports: Arrows]( + private[inline] def inlineToTree[S: Mangler: Exports]( inline: Inline ): State[S, List[OpModel.Tree]] = (inline.mergeMode match { @@ -77,7 +83,7 @@ object RawValueInliner extends Logging { case ParMode => inline.predo.toList }).pure - private[inline] def toModel[S: Mangler: Exports: Arrows]( + private[inline] def toModel[S: Mangler: Exports]( unfoldF: State[S, (ValueModel, Inline)] ): State[S, (ValueModel, Option[OpModel.Tree])] = for { @@ -92,7 +98,7 @@ object RawValueInliner extends Logging { _ = logger.trace("map was: " + map) } yield vm -> parDesugarPrefix(ops.filterNot(_ == EmptyModel.leaf)) - def valueToModel[S: Mangler: Exports: Arrows]( + def valueToModel[S: Mangler: Exports]( value: ValueRaw, propertiesAllowed: Boolean = true ): State[S, (ValueModel, Option[OpModel.Tree])] = for { @@ -100,7 +106,7 @@ object RawValueInliner extends Logging { model <- toModel(unfold(value, propertiesAllowed)) } yield model - def valueListToModel[S: Mangler: Exports: Arrows]( + def valueListToModel[S: Mangler: Exports]( values: List[ValueRaw] ): State[S, List[(ValueModel, Option[OpModel.Tree])]] = values.traverse(valueToModel(_)) @@ -109,14 +115,14 @@ object RawValueInliner extends Logging { * Unfold all arguments and make CallModel * @param flatStreamArguments canonicalize and flatten all stream arguments if true */ - def callToModel[S: Mangler: Exports: Arrows]( + def callToModel[S: Mangler: Exports]( call: Call, flatStreamArguments: Boolean ): State[S, (CallModel, Option[OpModel.Tree])] = { valueListToModel(call.args).flatMap { args => if (flatStreamArguments) args.map { arg => - TagInliner.flat(arg._1, arg._2) + TagInliner.flat(arg._1, arg._2, true) }.sequence else State.pure(args) diff --git a/model/inline/src/main/scala/aqua/model/inline/TagInliner.scala b/model/inline/src/main/scala/aqua/model/inline/TagInliner.scala index e3146b172..1b8f756e3 100644 --- a/model/inline/src/main/scala/aqua/model/inline/TagInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/TagInliner.scala @@ -3,7 +3,7 @@ package aqua.model.inline import aqua.errors.Errors.internalError import aqua.model.* import aqua.model.inline.raw.{CallArrowRawInliner, CallServiceRawInliner} -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.inline.state.{Exports, Mangler} import aqua.model.inline.tag.IfTagInliner import aqua.raw.ops.* import aqua.raw.value.* @@ -193,7 +193,7 @@ object TagInliner extends Logging { * @tparam S Current state * @return Model (if any), and prefix (if any) */ - def tagToModel[S: Mangler: Arrows: Exports]( + def tagToModel[S: Mangler: Exports]( tag: RawTag ): State[S, TagInlined[S]] = tag match { @@ -374,11 +374,13 @@ object TagInliner extends Logging { } yield TagInlined.Empty(prefix = prefix) case ClosureTag(arrow, detach) => - if (detach) Arrows[S].resolved(arrow, None).as(TagInlined.Empty()) - else - Arrows[S] - .resolved(arrow, arrow.name.some) - .as(TagInlined.Single(model = CaptureTopologyModel(arrow.name))) + ??? + // TODO: Rewrite + // if (detach) Arrows[S].resolved(arrow, None).as(TagInlined.Empty()) + // else + // Arrows[S] + // .resolved(arrow, arrow.name.some) + // .as(TagInlined.Single(model = CaptureTopologyModel(arrow.name))) case NextTag(item) => for { @@ -431,12 +433,13 @@ object TagInliner extends Logging { } yield methodName -> fn } + // TODO: Rewrite // Resolve wrappers in arrows - _ <- Arrows[S].resolved( - methods.map { case (_, fn) => - fn.funcName -> fn - }.toMap - ) + // _ <- Arrows[S].resolved( + // methods.map { case (_, fn) => + // fn.funcName -> fn + // }.toMap + // ) // Resolve wrappers in exports _ <- methods.traverse { case (methodName, fn) => @@ -475,7 +478,7 @@ object TagInliner extends Logging { inlined <- headInlined.build(children) } yield inlined - def handleTree[S: Exports: Mangler: Arrows]( + def handleTree[S: Exports: Mangler]( tree: RawTag.Tree ): State[S, OpModel.Tree] = traverseS(tree, tagToModel(_)) diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/ApplyBinaryOpRawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/ApplyBinaryOpRawInliner.scala index 48c06cadf..6b213effe 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/ApplyBinaryOpRawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/ApplyBinaryOpRawInliner.scala @@ -2,32 +2,32 @@ package aqua.model.inline.raw import aqua.errors.Errors.internalError import aqua.model.* -import aqua.model.inline.raw.RawInliner -import aqua.model.inline.TagInliner -import aqua.model.inline.state.{Arrows, Exports, Mangler} -import aqua.raw.value.{AbilityRaw, LiteralRaw, MakeStructRaw} -import cats.data.{NonEmptyList, NonEmptyMap, State} import aqua.model.inline.Inline +import aqua.model.inline.Inline.MergeMode import aqua.model.inline.RawValueInliner.{unfold, valueToModel} -import aqua.types.{ArrowType, ScalarType, Type} +import aqua.model.inline.TagInliner +import aqua.model.inline.raw.RawInliner +import aqua.model.inline.state.{Exports, Mangler} import aqua.raw.value.ApplyBinaryOpRaw import aqua.raw.value.ApplyBinaryOpRaw.Op import aqua.raw.value.ApplyBinaryOpRaw.Op.* -import aqua.model.inline.Inline.MergeMode +import aqua.raw.value.{AbilityRaw, LiteralRaw, MakeStructRaw} +import aqua.types.LiteralType +import aqua.types.{ArrowType, ScalarType, Type} import cats.data.Chain -import cats.syntax.traverse.* -import cats.syntax.monoid.* -import cats.syntax.functor.* -import cats.syntax.flatMap.* +import cats.data.{NonEmptyList, NonEmptyMap, State} +import cats.syntax.applicative.* import cats.syntax.apply.* +import cats.syntax.flatMap.* import cats.syntax.foldable.* -import cats.syntax.applicative.* -import aqua.types.LiteralType +import cats.syntax.functor.* +import cats.syntax.monoid.* +import cats.syntax.traverse.* object ApplyBinaryOpRawInliner extends RawInliner[ApplyBinaryOpRaw] { - override def apply[S: Mangler: Exports: Arrows]( + override def apply[S: Mangler: Exports]( raw: ApplyBinaryOpRaw, propertiesAllowed: Boolean ): State[S, (ValueModel, Inline)] = for { @@ -83,7 +83,7 @@ object ApplyBinaryOpRawInliner extends RawInliner[ApplyBinaryOpRaw] { } } yield result - private def inlineEqOp[S: Mangler: Exports: Arrows]( + private def inlineEqOp[S: Mangler: Exports]( lmodel: ValueModel, rmodel: ValueModel, linline: Inline, @@ -106,7 +106,7 @@ object ApplyBinaryOpRawInliner extends RawInliner[ApplyBinaryOpRaw] { case _ => fullInlineEqOp(lmodel, rmodel, linline, rinline, op, resType) } - private def fullInlineEqOp[S: Mangler: Exports: Arrows]( + private def fullInlineEqOp[S: Mangler: Exports]( lmodel: ValueModel, rmodel: ValueModel, linline: Inline, @@ -152,7 +152,7 @@ object ApplyBinaryOpRawInliner extends RawInliner[ApplyBinaryOpRaw] { result(name, resType, predo) } - private def inlineBoolOp[S: Mangler: Exports: Arrows]( + private def inlineBoolOp[S: Mangler: Exports]( lmodel: ValueModel, rmodel: ValueModel, linline: Inline, @@ -178,7 +178,7 @@ object ApplyBinaryOpRawInliner extends RawInliner[ApplyBinaryOpRaw] { case _ => fullInlineBoolOp(lmodel, rmodel, linline, rinline, op, resType) } - private def fullInlineBoolOp[S: Mangler: Exports: Arrows]( + private def fullInlineBoolOp[S: Mangler: Exports]( lmodel: ValueModel, rmodel: ValueModel, linline: Inline, @@ -230,7 +230,7 @@ object ApplyBinaryOpRawInliner extends RawInliner[ApplyBinaryOpRaw] { result(name, resType, predo) } - private def inlineCmpOp[S: Mangler: Exports: Arrows]( + private def inlineCmpOp[S: Mangler: Exports]( lmodel: ValueModel, rmodel: ValueModel, linline: Inline, @@ -276,7 +276,7 @@ object ApplyBinaryOpRawInliner extends RawInliner[ApplyBinaryOpRaw] { result(fn, resType, predo) } - private def inlineMathOp[S: Mangler: Exports: Arrows]( + private def inlineMathOp[S: Mangler: Exports]( lmodel: ValueModel, rmodel: ValueModel, linline: Inline, diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/ApplyFunctorRawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/ApplyFunctorRawInliner.scala index eb297e175..2e2dd6aee 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/ApplyFunctorRawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/ApplyFunctorRawInliner.scala @@ -3,7 +3,7 @@ package aqua.model.inline.raw import aqua.model.inline.Inline import aqua.model.inline.Inline.MergeMode.* import aqua.model.inline.RawValueInliner.unfold -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.inline.state.{Exports, Mangler} import aqua.model.{ CallModel, CanonicalizeModel, @@ -24,7 +24,7 @@ import scribe.Logging object ApplyFunctorRawInliner extends Logging { - def apply[S: Mangler: Exports: Arrows]( + def apply[S: Mangler: Exports]( value: ValueModel, functor: FunctorRaw ): State[S, (VarModel, Inline)] = { diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/ApplyIntoCopyRawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/ApplyIntoCopyRawInliner.scala index a4dabc1d8..f2dc67657 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/ApplyIntoCopyRawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/ApplyIntoCopyRawInliner.scala @@ -4,10 +4,11 @@ import aqua.errors.Errors.internalError import aqua.model.* import aqua.model.inline.Inline.MergeMode.* import aqua.model.inline.RawValueInliner.unfold -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.inline.state.{Exports, Mangler} import aqua.model.inline.{Inline, MakeStructRawInliner} import aqua.raw.value.IntoCopyRaw import aqua.types.{StreamMapType, StructType} + import cats.data.{Chain, NonEmptyMap, State} import cats.syntax.foldable.* import cats.syntax.functor.* @@ -40,10 +41,16 @@ object ApplyIntoCopyRawInliner extends Logging { } MakeStructRawInliner - .constructThroughMap(mapName, mapType, CallModel.Export(resultName, resultType), fields, nonCopiedValues) + .constructThroughMap( + mapName, + mapType, + CallModel.Export(resultName, resultType), + fields, + nonCopiedValues + ) } - def apply[S: Mangler: Exports: Arrows]( + def apply[S: Mangler: Exports]( value: VarModel, intoCopy: IntoCopyRaw ): State[S, (VarModel, Inline)] = { diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/ApplyPropertiesRawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/ApplyPropertiesRawInliner.scala index 7327efc82..b76f0bed7 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/ApplyPropertiesRawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/ApplyPropertiesRawInliner.scala @@ -6,7 +6,8 @@ import aqua.model.ValueModel.Ability import aqua.model.inline.Inline import aqua.model.inline.Inline.MergeMode.* import aqua.model.inline.RawValueInliner.unfold -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.inline.state.Exports.Export +import aqua.model.inline.state.{Exports, Mangler} import aqua.raw.value.* import aqua.types.* @@ -24,10 +25,10 @@ import scribe.Logging object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Logging { // in perspective literals can have properties and functors (like `nil` with length) - def flatLiteralWithProperties[S: Mangler: Exports: Arrows]( + def flatLiteralWithProperties[S: Mangler: Exports]( literal: LiteralModel, inl: Inline, - properties: Chain[PropertyModel] + properties: Chain[PropertyModel] = Chain.empty ): State[S, (VarModel, Inline)] = { for { apName <- Mangler[S].findAndForbidName("literal_ap") @@ -45,7 +46,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi } } - private def unfoldAbilityProperty[S: Mangler: Exports: Arrows]( + private def unfoldAbilityProperty[S: Mangler: Exports]( varModel: VarModel, abilityType: NamedType, p: PropertyRaw @@ -112,7 +113,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi ) } - private[inline] def unfoldProperty[S: Mangler: Exports: Arrows]( + private[inline] def unfoldProperty[S: Mangler: Exports]( varModel: VarModel, p: PropertyRaw ): State[S, (VarModel, Inline)] = @@ -172,7 +173,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi private case class PropertyRawWithModel(raw: PropertyRaw, model: Option[PropertyModel]) // Unfold properties that we can process in parallel - private def optimizeProperties[S: Mangler: Exports: Arrows]( + private def optimizeProperties[S: Mangler: Exports]( properties: Chain[PropertyRaw] ): State[S, (Chain[PropertyRawWithModel], Inline)] = { properties.map { @@ -211,16 +212,14 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi }.sequence.map(_.toList.unzip.bimap(Chain.fromSeq, _.combineAll)) } - private def unfoldProperties[S: Mangler: Exports: Arrows]( - prevInline: Inline, - vm: VarModel, - properties: Chain[PropertyRaw], - propertiesAllowed: Boolean - ): State[S, (VarModel, Inline)] = { + private def unfoldProperties[S: Mangler: Exports]( + exp: Export, + properties: Chain[PropertyRaw] + ): State[S, (Export, Inline)] = { optimizeProperties(properties).flatMap { case (optimizedProps, optimizationInline) => optimizedProps .foldLeft[State[S, (VarModel, Inline)]]( - State.pure((vm, prevInline.mergeWith(optimizationInline, SeqMode))) + State.pure((vm, Inline.empty)) ) { case (state, property) => state.flatMap { case (vm @ Ability(_, at), leftInline) => @@ -263,7 +262,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi /** * Unfold `stream[idx]` */ - private def unfoldStreamGate[S: Mangler: Exports: Arrows]( + private def unfoldStreamGate[S: Mangler: Exports]( streamName: String, streamType: StreamType, idx: ValueRaw @@ -274,19 +273,27 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi * apply possible optimizations */ sizeInlined <- unfold(idx.increment) - (sizeVM, sizeInline) = sizeInlined + (sizeExp, sizeInline) = sizeInlined + sizeVM <- sizeExp match { + case Export.Value(vm) => + State.pure(vm) + case _ => + internalError(s"Unexpected: size ($sizeExp) is not a value") + } /** * Inline idx which is `size - 1` * TODO: Do not generate it if * it is not needed, e.g. in `join` */ - idxInlined <- sizeVM match { + idxInlined <- vm match { /** * Micro optimization: if idx is a literal * do not generate inline. */ case LiteralModel.Integer(i, t) => - (LiteralModel((i - 1).toString, t), Inline.empty).pure[State[S, *]] + State.pure( + (LiteralModel((i - 1).toString, t), Inline.empty) + ) case _ => Mangler[S].findAndForbidName(s"${streamName}_idx").map { idxName => val idxVar = VarModel(idxName, sizeVM.`type`) @@ -325,54 +332,40 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi mergeMode = SeqMode ) - private def unfoldRawWithProperties[S: Mangler: Exports: Arrows]( + private def unfoldRawWithProperties[S: Mangler: Exports]( raw: ValueRaw, - properties: Chain[PropertyRaw], - propertiesAllowed: Boolean - ): State[S, (ValueModel, Inline)] = + properties: Chain[PropertyRaw] + ): State[S, (Export, Inline)] = (raw, properties.uncons) match { - /** - * To inline - */ case ( vr @ VarRaw(_, st @ StreamType(_)), Some(IntoIndexRaw(idx, _), otherProperties) ) => unfold(vr).flatMap { - case (VarModel(nameVM, _, _), inl) => + case (Export.Value(VarModel(nameVM, _, _)), inl) => for { gateInlined <- unfoldStreamGate(nameVM, st, idx) (gateVM, gateInline) = gateInlined propsInlined <- unfoldProperties( gateInline, - gateVM, - otherProperties, - propertiesAllowed + Export.Value(gateVM), + otherProperties ) } yield propsInlined case _ => internalError( - s"Unfolded stream ($vr) cannot be a literal" + s"Unexpected: stream ($vr) is not a variable" ) } case (_, _) => unfold(raw).flatMap { - case (vm: VarModel, prevInline) => - unfoldProperties(prevInline, vm, properties, propertiesAllowed) - // To coerce types - .map(identity) - case (l: LiteralModel, inline) => - flatLiteralWithProperties( - l, - inline, - Chain.empty - ).flatMap { (varModel, prevInline) => - unfoldProperties(prevInline, varModel, properties, propertiesAllowed).map { - case (v, i) => - v -> i - } + case (Export.Value(l: LiteralModel), inl) => + flatLiteralWithProperties(l, inl).flatMap { (vm, prevInline) => + unfoldProperties(prevInline, Export.Value(vm), properties) } + case (exp, prevInline) => + unfoldProperties(prevInline, exp, properties) } } @@ -389,11 +382,10 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi flatten = VarModel(nn, varModel.`type`) } yield flatten -> Inline.tree(FlattenModel(varModel, flatten.name).leaf) - override def apply[S: Mangler: Exports: Arrows]( - apr: ApplyPropertyRaw, - propertiesAllowed: Boolean - ): State[S, (ValueModel, Inline)] = { + override def apply[S: Mangler: Exports]( + apr: ApplyPropertyRaw + ): State[S, (Export, Inline)] = { val (raw, properties) = apr.unwind - unfoldRawWithProperties(raw, properties, propertiesAllowed) + unfoldRawWithProperties(raw, properties) } } diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/ApplyUnaryOpRawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/ApplyUnaryOpRawInliner.scala index 8d77845b6..22f97f488 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/ApplyUnaryOpRawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/ApplyUnaryOpRawInliner.scala @@ -1,28 +1,28 @@ package aqua.model.inline.raw import aqua.model.* -import aqua.model.inline.raw.RawInliner -import aqua.model.inline.state.{Arrows, Exports, Mangler} -import aqua.raw.value.{AbilityRaw, LiteralRaw, MakeStructRaw} -import cats.data.{NonEmptyList, NonEmptyMap, State} import aqua.model.inline.Inline import aqua.model.inline.RawValueInliner.{unfold, valueToModel} -import aqua.types.{ArrowType, ScalarType} +import aqua.model.inline.raw.RawInliner +import aqua.model.inline.state.{Exports, Mangler} import aqua.raw.value.ApplyUnaryOpRaw import aqua.raw.value.ApplyUnaryOpRaw.Op.* +import aqua.raw.value.{AbilityRaw, LiteralRaw, MakeStructRaw} +import aqua.types.{ArrowType, ScalarType} import cats.data.Chain -import cats.syntax.traverse.* -import cats.syntax.monoid.* -import cats.syntax.functor.* -import cats.syntax.flatMap.* +import cats.data.{NonEmptyList, NonEmptyMap, State} +import cats.syntax.applicative.* import cats.syntax.apply.* +import cats.syntax.flatMap.* import cats.syntax.foldable.* -import cats.syntax.applicative.* +import cats.syntax.functor.* +import cats.syntax.monoid.* +import cats.syntax.traverse.* object ApplyUnaryOpRawInliner extends RawInliner[ApplyUnaryOpRaw] { - override def apply[S: Mangler: Exports: Arrows]( + override def apply[S: Mangler: Exports]( raw: ApplyUnaryOpRaw, propertiesAllowed: Boolean ): State[S, (ValueModel, Inline)] = for { @@ -40,7 +40,7 @@ object ApplyUnaryOpRawInliner extends RawInliner[ApplyUnaryOpRaw] { } } yield result - private def fullInline[S: Mangler: Exports: Arrows]( + private def fullInline[S: Mangler: Exports]( vm: ValueModel, vinline: Inline, op: ApplyUnaryOpRaw.Op diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/CallArrowRawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/CallArrowRawInliner.scala index 3aa8227e8..4813175c3 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/CallArrowRawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/CallArrowRawInliner.scala @@ -3,7 +3,7 @@ package aqua.model.inline.raw import aqua.errors.Errors.internalError import aqua.model.* import aqua.model.inline.RawValueInliner.callToModel -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.inline.state.{Exports, Mangler} import aqua.model.inline.{ArrowInliner, Inline, RawValueInliner} import aqua.raw.ops.Call import aqua.raw.value.CallArrowRaw @@ -14,7 +14,7 @@ import scribe.Logging object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { - private[inline] def unfold[S: Mangler: Exports: Arrows]( + private[inline] def unfold[S: Mangler: Exports]( value: CallArrowRaw, exportTo: List[Call.Export] ): State[S, (List[ValueModel], Inline)] = { @@ -31,7 +31,7 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { resolveArrow(funcName, call) } - private def resolveFuncArrow[S: Mangler: Exports: Arrows]( + private def resolveFuncArrow[S: Mangler: Exports]( fn: FuncArrow, call: Call ): State[S, (List[ValueModel], Inline)] = { @@ -52,13 +52,15 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { } } - private def resolveArrow[S: Mangler: Exports: Arrows]( + private def resolveArrow[S: Mangler: Exports]( funcName: String, call: Call ): State[S, (List[ValueModel], Inline)] = for { - arrows <- Arrows[S].arrows + // TODO: Rewrite + // arrows <- Arrows[S].arrows exports <- Exports[S].exports lastArrow <- Exports[S].getLastVarName(funcName) + arrows: Map[String, FuncArrow] = ??? arrow = arrows .get(funcName) .orElse( @@ -76,7 +78,7 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { }) } yield result - override def apply[S: Mangler: Exports: Arrows]( + override def apply[S: Mangler: Exports]( raw: CallArrowRaw, propertiesAllowed: Boolean ): State[S, (ValueModel, Inline)] = diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/CallServiceRawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/CallServiceRawInliner.scala index 9c8e000cd..45d32c8ec 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/CallServiceRawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/CallServiceRawInliner.scala @@ -3,22 +3,22 @@ package aqua.model.inline.raw import aqua.model.* import aqua.model.inline.Inline import aqua.model.inline.RawValueInliner.{callToModel, valueToModel} -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.inline.state.{Exports, Mangler} import aqua.raw.ops.Call import aqua.raw.value.CallServiceRaw + import cats.data.{Chain, State} import scribe.Logging object CallServiceRawInliner extends RawInliner[CallServiceRaw] with Logging { - private[inline] def unfold[S: Mangler: Exports: Arrows]( + private[inline] def unfold[S: Mangler: Exports]( value: CallServiceRaw, exportTo: List[Call.Export] ): State[S, (List[ValueModel], Inline)] = Exports[S].exports.flatMap { exports => logger.trace(s"${exportTo.mkString(" ")} $value") logger.trace(Console.BLUE + s"call service id ${value.serviceId}" + Console.RESET) - val call = Call(value.arguments, exportTo) for { @@ -40,7 +40,7 @@ object CallServiceRawInliner extends RawInliner[CallServiceRaw] with Logging { } yield values.values.toList -> inline } - override def apply[S: Mangler: Exports: Arrows]( + override def apply[S: Mangler: Exports]( raw: CallServiceRaw, propertiesAllowed: Boolean ): State[S, (ValueModel, Inline)] = diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/CollectionRawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/CollectionRawInliner.scala index 3344b380d..a9a79049c 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/CollectionRawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/CollectionRawInliner.scala @@ -3,7 +3,7 @@ package aqua.model.inline.raw import aqua.model.* import aqua.model.inline.Inline import aqua.model.inline.RawValueInliner.valueToModel -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.inline.state.{Exports, Mangler} import aqua.raw.value.CollectionRaw import aqua.types.StreamMapType import aqua.types.{ArrayType, CanonStreamType, OptionType, StreamType} @@ -12,7 +12,7 @@ import cats.data.{Chain, State} object CollectionRawInliner extends RawInliner[CollectionRaw] { - override def apply[S: Mangler: Exports: Arrows]( + override def apply[S: Mangler: Exports]( raw: CollectionRaw, propertiesAllowed: Boolean ): State[S, (ValueModel, Inline)] = diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/MakeAbilityRawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/MakeAbilityRawInliner.scala index 6f9deab02..5a9fb192b 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/MakeAbilityRawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/MakeAbilityRawInliner.scala @@ -3,7 +3,7 @@ package aqua.model.inline.raw import aqua.model.ValueModel.Ability import aqua.model.inline.Inline import aqua.model.inline.RawValueInliner.unfold -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.inline.state.{Exports, Mangler} import aqua.model.{SeqModel, ValueModel, VarModel} import aqua.raw.value.AbilityRaw import aqua.types.AbilityType @@ -15,7 +15,7 @@ import cats.syntax.functor.* object MakeAbilityRawInliner extends RawInliner[AbilityRaw] { - private def updateFields[S: Mangler: Exports: Arrows]( + private def updateFields[S: Mangler: Exports]( name: String, fields: NonEmptyMap[String, (ValueModel, Inline)] ): State[S, Unit] = @@ -27,7 +27,7 @@ object MakeAbilityRawInliner extends RawInliner[AbilityRaw] { Exports[S].resolveAbilityField(name, n, vm) }.as(()) - override def apply[S: Mangler: Exports: Arrows]( + override def apply[S: Mangler: Exports]( raw: AbilityRaw, propertiesAllowed: Boolean ): State[S, (ValueModel, Inline)] = { diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/RawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/RawInliner.scala index aee39da2b..7d1b20b59 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/RawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/RawInliner.scala @@ -2,15 +2,16 @@ package aqua.model.inline.raw import aqua.model.ValueModel import aqua.model.inline.Inline -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.inline.state.Exports.Export +import aqua.model.inline.state.{Exports, Mangler} import aqua.raw.value.ValueRaw + import cats.data.State trait RawInliner[T <: ValueRaw] { - def apply[S: Mangler: Exports: Arrows]( - raw: T, - propertiesAllowed: Boolean = true - ): State[S, (ValueModel, Inline)] + def apply[S: Mangler: Exports]( + raw: T + ): State[S, (Export, Inline)] } diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/StreamGateInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/StreamGateInliner.scala index fac02fd00..1ddebdd75 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/StreamGateInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/StreamGateInliner.scala @@ -3,17 +3,17 @@ package aqua.model.inline.raw import aqua.errors.Errors.internalError import aqua.model.* import aqua.model.inline.Inline -import aqua.model.inline.state.{Arrows, Exports, Mangler} import aqua.model.inline.RawValueInliner.unfold +import aqua.model.inline.state.{Exports, Mangler} import aqua.types.{ArrayType, CanonStreamType, ScalarType, StreamType} -import cats.data.State import cats.data.Chain +import cats.data.State +import cats.instances.stream +import cats.syntax.applicative.* import cats.syntax.monoid.* import cats.syntax.option.* -import cats.syntax.applicative.* import scribe.Logging -import cats.instances.stream object StreamGateInliner extends Logging { @@ -88,7 +88,7 @@ object StreamGateInliner extends Logging { ) } - def apply[S: Mangler: Exports: Arrows]( + def apply[S: Mangler: Exports]( streamName: String, streamType: StreamType, sizeModel: ValueModel diff --git a/model/inline/src/main/scala/aqua/model/inline/raw/StreamRawInliner.scala b/model/inline/src/main/scala/aqua/model/inline/raw/StreamRawInliner.scala index adc7e1be8..05653b6db 100644 --- a/model/inline/src/main/scala/aqua/model/inline/raw/StreamRawInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/raw/StreamRawInliner.scala @@ -3,7 +3,7 @@ package aqua.model.inline.raw import aqua.model.* import aqua.model.inline.Inline import aqua.model.inline.RawValueInliner.valueToModel -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.inline.state.{Exports, Mangler} import aqua.raw.value.StreamRaw import cats.data.{Chain, State} @@ -11,7 +11,7 @@ import cats.syntax.traverse.* object StreamRawInliner extends RawInliner[StreamRaw] { - override def apply[S: Mangler: Exports: Arrows]( + override def apply[S: Mangler: Exports]( raw: StreamRaw, propertiesAllowed: Boolean ): State[S, (ValueModel, Inline)] = { diff --git a/model/inline/src/main/scala/aqua/model/inline/state/Arrows.scala b/model/inline/src/main/scala/aqua/model/inline/state/Arrows.scala deleted file mode 100644 index 34759319b..000000000 --- a/model/inline/src/main/scala/aqua/model/inline/state/Arrows.scala +++ /dev/null @@ -1,142 +0,0 @@ -package aqua.model.inline.state - -import aqua.model.ValueModel -import aqua.model.{ArgsCall, FuncArrow} -import aqua.raw.arrow.FuncRaw -import aqua.types.* - -import cats.data.State -import cats.instances.list.* -import cats.syntax.functor.* -import cats.syntax.option.* -import cats.syntax.show.* -import cats.syntax.traverse.* - -/** - * State algebra for resolved arrows - * - * @tparam S - * State - */ -trait Arrows[S] extends Scoped[S] { - self => - def save(name: String, arrow: FuncArrow): State[S, Unit] - - /** - * Arrow is resolved – save it to the state [[S]] - * - * @param arrow resolved arrow - * @param topology captured topology - */ - final def resolved( - arrow: FuncRaw, - topology: Option[String] - )(using Exports[S]): State[S, Unit] = - for { - arrs <- arrows - capturedVars <- Exports[S].gather(arrow.capturedVars.toSeq) - capturedArrows = arrs.view.filterKeys(arrow.capturedVars).toMap ++ - Arrows.arrowsByValues(arrs, capturedVars) - funcArrow = FuncArrow.fromRaw(arrow, capturedArrows, capturedVars, topology) - _ <- save(arrow.name, funcArrow) - } yield () - - /** - * Save arrows to the state [[S]] - * - * @param arrows - * Resolved arrows, accessible by key name which could differ from arrow's name - */ - final def resolved(arrows: Map[String, FuncArrow]): State[S, Unit] = - arrows.toList.traverse(save).void - - /** - * All arrows available for use in scope - */ - val arrows: State[S, Map[String, FuncArrow]] - - /** - * Pick a subset of arrows by names - * - * @param names - * What arrows should be taken - */ - def pickArrows(names: Set[String]): State[S, Map[String, FuncArrow]] = - arrows.map(_.view.filterKeys(names).toMap) - - /** - * Take arrows selected by the function call arguments - * - * @param args - * @return - */ - def argsArrows(args: ArgsCall): State[S, Map[String, FuncArrow]] = - arrows.map(args.arrowArgsMap) - - /** - * Changes the [[S]] type to [[R]] - * - * @param f - * Lens getter - * @param g - * Lens setter - * @tparam R - * New state type - */ - def transformS[R](f: R => S, g: (R, S) => R): Arrows[R] = new Arrows[R] { - - override def save(name: String, arrow: FuncArrow): State[R, Unit] = - self.save(name, arrow).transformS(f, g) - - override val arrows: State[R, Map[String, FuncArrow]] = self.arrows.transformS(f, g) - - override val purge: State[R, R] = - self.purgeR(f, g) - - override protected def fill(s: R): State[R, Unit] = - self.fillR(s, f, g) - - } -} - -object Arrows { - - /** - * Retrieve all arrows that correspond to values - */ - def arrowsByValues( - arrows: Map[String, FuncArrow], - values: Map[String, ValueModel] - ): Map[String, FuncArrow] = { - val arrowKeys = arrows.keySet ++ arrows.values.map(_.funcName) - val varsKeys = values.keySet ++ values.values.collect { case ValueModel.Arrow(vm, _) => - vm.name - } - val keys = arrowKeys.intersect(varsKeys) - - arrows.filter { case (arrowName, arrow) => - keys.contains(arrowName) || keys.contains(arrow.funcName) - } - } - - def apply[S](implicit arrows: Arrows[S]): Arrows[S] = arrows - - // Default implementation with the most straightforward state – just a Map - object Simple extends Arrows[Map[String, FuncArrow]] { - - override def save(name: String, arrow: FuncArrow): State[Map[String, FuncArrow], Unit] = - State.modify(_ + (name -> arrow)) - - override val arrows: State[Map[String, FuncArrow], Map[String, FuncArrow]] = - State.get - - override val purge: State[Map[String, FuncArrow], Map[String, FuncArrow]] = - for { - s <- State.get - _ <- State.set(Map.empty) - } yield s - - override protected def fill(s: Map[String, FuncArrow]): State[Map[String, FuncArrow], Unit] = - State.set(s) - } -} diff --git a/model/inline/src/main/scala/aqua/model/inline/state/Exports.scala b/model/inline/src/main/scala/aqua/model/inline/state/Exports.scala index a97ffaa95..e5af8d818 100644 --- a/model/inline/src/main/scala/aqua/model/inline/state/Exports.scala +++ b/model/inline/src/main/scala/aqua/model/inline/state/Exports.scala @@ -1,260 +1,125 @@ package aqua.model.inline.state +import aqua.model.FuncArrow import aqua.model.ValueModel.Ability import aqua.model.{LiteralModel, ValueModel, VarModel} +import aqua.types.ServiceType import aqua.types.{AbilityType, GeneralAbilityType, NamedType} import cats.data.{NonEmptyList, State} +import cats.syntax.functor.* /** * Exports – trace values available in the scope - * @tparam S - * State + * @tparam S - State */ trait Exports[S] extends Scoped[S] { self => /** - * [[value]] is accessible as [[exportName]] - * @param exportName - * Name - * @param value - * Value + * [[exp]] is accessible as [[name]] + * @param name - Name + * @param exp - Export */ - def resolved(exportName: String, value: ValueModel): State[S, Unit] - - /** - * [[value]] is accessible as [[abilityExportName]].[[fieldName]] - * - * @param abilityExportName - * Ability Name - * @param fieldName - * Field Name - * @param value - * Value - */ - def resolveAbilityField( - abilityExportName: String, - fieldName: String, - value: ValueModel - ): State[S, Unit] - - /** - * Rename ability prefix to new one - */ - def copyWithAbilityPrefix(prefix: String, newPrefix: String): State[S, Unit] - - /** - * Get name of last linked VarModel. If the last element is not VarModel, return None - */ - def getLastVarName(name: String): State[S, Option[String]] - - /** - * Rename names in variables - */ - def renameVariables(renames: Map[String, String]): State[S, Unit] + def resolved(name: String, exp: Exports.Export): State[S, Unit] /** * Resolve the whole map of exports - * @param exports - * name -> value + * @param exports - name -> export */ - def resolved(exports: Map[String, ValueModel]): State[S, Unit] + def resolved(exports: Map[String, Exports.Export]): State[S, Unit] /** - * Get all export keys - */ - def getKeys: State[S, Set[String]] - - /** - * Get ability field from export - * @param name variable ability name - * @param field ability field + * Rename names in variables + * @param renames - oldName -> newName */ - def getAbilityField(name: String, field: String): State[S, Option[ValueModel]] + def renameExports(renames: Map[String, String]): State[S, Unit] /** - * Get all the values available in the scope + * Get export by name + * @param name - Name */ - val exports: State[S, Map[String, ValueModel]] - - final def gather(names: Seq[String]): State[S, Map[String, ValueModel]] = - exports.map(Exports.gatherFrom(names, _)) + def get(name: String): State[S, Option[Exports.Export]] /** * Change [[S]] to [[R]] */ def transformS[R](f: R => S, g: (R, S) => R): Exports[R] = new Exports[R] { - override def resolved(exportName: String, value: ValueModel): State[R, Unit] = - self.resolved(exportName, value).transformS(f, g) + override def resolved(name: String, exp: Exports.Export): State[R, Unit] = + self.resolved(name, exp).transformS(f, g) - override def resolved(exports: Map[String, ValueModel]): State[R, Unit] = + override def resolved(exports: Map[String, Exports.Export]): State[R, Unit] = self.resolved(exports).transformS(f, g) - override def resolveAbilityField( - abilityExportName: String, - fieldName: String, - value: ValueModel - ): State[R, Unit] = - self.resolveAbilityField(abilityExportName, fieldName, value).transformS(f, g) - - override def copyWithAbilityPrefix(prefix: String, newPrefix: String): State[R, Unit] = - self.copyWithAbilityPrefix(prefix, newPrefix).transformS(f, g) + override def renameExports(renames: Map[String, String]): State[R, Unit] = + self.renameExports(renames).transformS(f, g) - override def getLastVarName(name: String): State[R, Option[String]] = - self.getLastVarName(name).transformS(f, g) - - override def renameVariables(renames: Map[String, String]): State[R, Unit] = - self.renameVariables(renames).transformS(f, g) - - override def getKeys: State[R, Set[String]] = - self.getKeys.transformS(f, g) - - override def getAbilityField(name: String, field: String): State[R, Option[ValueModel]] = - self.getAbilityField(name, field).transformS(f, g) - - override val exports: State[R, Map[String, ValueModel]] = - self.exports.transformS(f, g) - - override val purge: State[R, R] = - self.purgeR(f, g) - - override protected def fill(s: R): State[R, Unit] = - self.fillR(s, f, g) + override def get(name: String): State[R, Option[Exports.Export]] = + self.get(name).transformS(f, g) } } object Exports { - def apply[S](using exports: Exports[S]): Exports[S] = exports - - /** - * Gather all the values that are related to the given names - * (ability fields) - * - * @param names names of variables - * @param state exports state - */ - def gatherFrom( - names: Seq[String], - state: Map[String, ValueModel] - ): Map[String, ValueModel] = { - val related = for { - variable <- names - exp <- state.get(variable).toList - at <- exp.`type` match { - case at: GeneralAbilityType => at :: Nil - case _ => Nil - } - field <- at.allFields.toNel.toList - (fieldName, _) = field - } yield AbilityType.fullName(variable, fieldName) - state.view.filterKeys(names.toSet ++ related).toMap + enum Export { + case Value(value: ValueModel) + case Arrow(arrow: FuncArrow) + case Ability(abilityType: AbilityType, values: Map[String, Export]) + case Service(serviceType: ServiceType, arrows: Map[String, Arrow]) + case Context(values: Map[String, Export]) } - // Get last linked VarModel - def getLastValue(name: String, state: Map[String, ValueModel]): Option[ValueModel] = { - state.get(name) match { - case Some(vm @ VarModel(n, _, _)) => - if (name == n) Option(vm) - else getLastValue(n, state).orElse(Option(vm)) - case lm @ Some(LiteralModel(_, _)) => - lm - case _ => - None - } - } + object Export { - object Simple extends Exports[Map[String, ValueModel]] { + extension (c: Export.Context) { - // Make links from one set of abilities to another (for ability assignment) - private def getAbilityPairs( - oldName: String, - newName: String, - at: NamedType, - state: Map[String, ValueModel] - ): NonEmptyList[(String, ValueModel)] = { - at.fields.toNel.flatMap { - case (n, at @ AbilityType(_, _)) => - val newFullName = AbilityType.fullName(newName, n) - val oldFullName = AbilityType.fullName(oldName, n) - getAbilityPairs(oldFullName, newFullName, at, state) - case (n, t) => - val newFullName = AbilityType.fullName(newName, n) - val oldFullName = AbilityType.fullName(oldName, n) - // put link on last variable in chain - val lastVar = Exports.getLastValue(oldFullName, state) - NonEmptyList.of((newFullName, lastVar.getOrElse(VarModel(oldFullName, t)))) - } - } + def resolved(name: String, exp: Export): Export.Context = + c.copy(values = c.values + (name -> exp)) - override def resolved( - exportName: String, - value: ValueModel - ): State[Map[String, ValueModel], Unit] = State.modify { state => - value match { - case Ability(vm, at) if vm.properties.isEmpty => - val pairs = getAbilityPairs(vm.name, exportName, at, state) - state ++ pairs.toList.toMap + (exportName -> value) - case _ => state + (exportName -> value) - } + def resolved(exports: Map[String, Export]): Export.Context = + c.copy(values = c.values ++ exports) + + def renameExports(renames: Map[String, String]): Export.Context = + c.copy(values = c.values.map { case (name, exp) => + renames.getOrElse(name, name) -> exp + }) } + } - override def getLastVarName(name: String): State[Map[String, ValueModel], Option[String]] = - State.get.map(st => getLastValue(name, st).collect { case VarModel(name, _, _) => name }) + final case class ExportsState( + global: Export.Context = Export.Context(Map.empty) + ) { - override def resolved(exports: Map[String, ValueModel]): State[Map[String, ValueModel], Unit] = - State.modify(_ ++ exports) + def resolved(name: String, exp: Export): ExportsState = + copy(global = global.resolved(name, exp)) - override def resolveAbilityField( - abilityExportName: String, - fieldName: String, - value: ValueModel - ): State[Map[String, ValueModel], Unit] = - State.modify(_ + (AbilityType.fullName(abilityExportName, fieldName) -> value)) + def resolved(exports: Map[String, Export]): ExportsState = + copy(global = global.resolved(exports)) - override def copyWithAbilityPrefix( - prefix: String, - newPrefix: String - ): State[Map[String, ValueModel], Unit] = - State.modify { state => - state.flatMap { - case (k, v) if k.startsWith(prefix) => - List(k.replaceFirst(prefix, newPrefix) -> v, k -> v) - case (k, v) => List(k -> v) - } - } + def renameExports(renames: Map[String, String]): ExportsState = + copy(global = global.renameExports(renames)) + + def values: Map[String, Export] = + global.values + } + + def apply[S](using exports: Exports[S]): Exports[S] = exports - override def renameVariables( - renames: Map[String, String] - ): State[Map[String, ValueModel], Unit] = - State.modify { - _.map { - case (k, vm @ VarModel(name, _, _)) if renames.contains(name) => - k -> vm.copy(name = renames.getOrElse(name, name)) - case (k, v) => k -> v - } - } + given Exports[ExportsState] with { - override def getKeys: State[Map[String, ValueModel], Set[String]] = State.get.map(_.keySet) + type ST[A] = State[ExportsState, A] - override def getAbilityField( - name: String, - field: String - ): State[Map[String, ValueModel], Option[ValueModel]] = - State.get.map(_.get(AbilityType.fullName(name, field))) + override def resolved(name: String, exp: Export): ST[Unit] = + State.modify(_.resolved(name, exp)) - override val exports: State[Map[String, ValueModel], Map[String, ValueModel]] = - State.get + override def resolved(exports: Map[String, Export]): ST[Unit] = + State.modify(_.resolved(exports)) - override val purge: State[Map[String, ValueModel], Map[String, ValueModel]] = - for { - s <- State.get - _ <- State.set(Map.empty) - } yield s + override def renameExports(renames: Map[String, String]): ST[Unit] = + State.modify[ExportsState](_.renameExports(renames)).void - override protected def fill(s: Map[String, ValueModel]): State[Map[String, ValueModel], Unit] = - State.set(s) + override def get(name: String): ST[Option[Export]] = + State.inspect(_.values.get(name)) } } diff --git a/model/inline/src/main/scala/aqua/model/inline/state/InliningState.scala b/model/inline/src/main/scala/aqua/model/inline/state/InliningState.scala index e931cd0aa..45bcb23b7 100644 --- a/model/inline/src/main/scala/aqua/model/inline/state/InliningState.scala +++ b/model/inline/src/main/scala/aqua/model/inline/state/InliningState.scala @@ -1,11 +1,13 @@ package aqua.model.inline.state import aqua.mangler.ManglerState +import aqua.model.inline.state.Exports.ExportsState +import aqua.model.inline.state.{Counter, Exports, Mangler} import aqua.model.{FuncArrow, ValueModel} -import aqua.model.inline.state.{Arrows, Counter, Exports, Mangler} import aqua.raw.arrow.FuncRaw import aqua.raw.value.{ValueRaw, VarRaw} import aqua.types.ArrowType + import cats.data.{Chain, State} import cats.instances.list.* import cats.syntax.traverse.* @@ -25,8 +27,7 @@ import scribe.Logging */ case class InliningState( noNames: ManglerState = ManglerState(), - resolvedExports: Map[String, ValueModel] = Map.empty, - resolvedArrows: Map[String, FuncArrow] = Map.empty, + resolvedExports: ExportsState = ExportsState(), instructionCounter: Int = 0 ) @@ -38,10 +39,7 @@ object InliningState { given Mangler[InliningState] = Mangler[ManglerState].transformS(_.noNames, (acc, nn) => acc.copy(noNames = nn)) - given Arrows[InliningState] = - Arrows.Simple.transformS(_.resolvedArrows, (acc, aa) => acc.copy(resolvedArrows = aa)) - given Exports[InliningState] = - Exports.Simple.transformS(_.resolvedExports, (acc, ex) => acc.copy(resolvedExports = ex)) + Exports[ExportsState].transformS(_.resolvedExports, (acc, ex) => acc.copy(resolvedExports = ex)) } diff --git a/model/inline/src/main/scala/aqua/model/inline/tag/IfTagInliner.scala b/model/inline/src/main/scala/aqua/model/inline/tag/IfTagInliner.scala index e563c6095..610c1fff4 100644 --- a/model/inline/src/main/scala/aqua/model/inline/tag/IfTagInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/tag/IfTagInliner.scala @@ -1,17 +1,17 @@ package aqua.model.inline.tag -import aqua.raw.value.{ApplyBinaryOpRaw, ValueRaw} -import aqua.raw.value.ApplyBinaryOpRaw.Op as BinOp -import aqua.model.ValueModel import aqua.model.* -import aqua.model.inline.state.{Arrows, Exports, Mangler} +import aqua.model.ValueModel +import aqua.model.inline.Inline.parDesugarPrefixOpt import aqua.model.inline.RawValueInliner.valueToModel import aqua.model.inline.TagInliner.canonicalizeIfStream -import aqua.model.inline.Inline.parDesugarPrefixOpt +import aqua.model.inline.state.{Exports, Mangler} +import aqua.raw.value.ApplyBinaryOpRaw.Op as BinOp +import aqua.raw.value.{ApplyBinaryOpRaw, ValueRaw} import cats.data.Chain -import cats.syntax.flatMap.* import cats.syntax.apply.* +import cats.syntax.flatMap.* final case class IfTagInliner( valueRaw: ValueRaw