mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-12 17:55:33 +00:00
Savepoint
This commit is contained in:
parent
9aec470d38
commit
a73996d8de
@ -3,7 +3,7 @@ package aqua.model.inline
|
|||||||
import aqua.model.*
|
import aqua.model.*
|
||||||
import aqua.model.inline.Inline.MergeMode.*
|
import aqua.model.inline.Inline.MergeMode.*
|
||||||
import aqua.model.inline.raw.*
|
import aqua.model.inline.raw.*
|
||||||
import aqua.model.inline.state.{Arrows, Counter, Exports, Mangler}
|
import aqua.model.inline.state.{Counter, Exports, Mangler}
|
||||||
import aqua.raw.ops.*
|
import aqua.raw.ops.*
|
||||||
import aqua.raw.value.*
|
import aqua.raw.value.*
|
||||||
import aqua.types.{ArrayType, LiteralType, OptionType, StreamType}
|
import aqua.types.{ArrayType, LiteralType, OptionType, StreamType}
|
||||||
@ -23,21 +23,26 @@ object RawValueInliner extends Logging {
|
|||||||
|
|
||||||
import aqua.model.inline.Inline.*
|
import aqua.model.inline.Inline.*
|
||||||
|
|
||||||
private[inline] def unfold[S: Mangler: Exports: Arrows](
|
private[inline] def unfold[S: Mangler: Exports](
|
||||||
raw: ValueRaw,
|
raw: ValueRaw,
|
||||||
propertiesAllowed: Boolean = true
|
propertiesAllowed: Boolean = true
|
||||||
): State[S, (ValueModel, Inline)] = for {
|
): State[S, (Exports.Export, Inline)] = for {
|
||||||
optimized <- StateT.liftF(Optimization.optimize(raw))
|
optimized <- StateT.liftF(Optimization.optimize(raw))
|
||||||
_ <- StateT.liftF(Eval.later(logger.trace("OPTIMIZIED " + optimized)))
|
_ <- StateT.liftF(Eval.later(logger.trace("OPTIMIZIED " + optimized)))
|
||||||
result <- optimized match {
|
result <- optimized match {
|
||||||
case VarRaw(name, t) =>
|
case VarRaw(name, t) =>
|
||||||
for {
|
for {
|
||||||
exports <- Exports[S].exports
|
maybeExport <- Exports[S].get(name)
|
||||||
model = VarModel(name, t, Chain.empty).resolveWith(exports)
|
model = VarModel(name, t)
|
||||||
} yield model -> Inline.empty
|
exp = maybeExport.getOrElse(
|
||||||
|
Exports.Export.Value(model)
|
||||||
|
)
|
||||||
|
} yield exp -> Inline.empty
|
||||||
|
|
||||||
case LiteralRaw(value, t) =>
|
case LiteralRaw(value, t) =>
|
||||||
State.pure(LiteralModel(value, t) -> Inline.empty)
|
val model = LiteralModel(value, t)
|
||||||
|
val exp = Exports.Export.Value(model)
|
||||||
|
State.pure(exp -> Inline.empty)
|
||||||
|
|
||||||
case alr: ApplyPropertyRaw =>
|
case alr: ApplyPropertyRaw =>
|
||||||
ApplyPropertiesRawInliner(alr, propertiesAllowed)
|
ApplyPropertiesRawInliner(alr, propertiesAllowed)
|
||||||
@ -115,7 +120,7 @@ object RawValueInliner extends Logging {
|
|||||||
): State[S, (CallModel, Option[OpModel.Tree])] = {
|
): State[S, (CallModel, Option[OpModel.Tree])] = {
|
||||||
valueListToModel(call.args).flatMap { args =>
|
valueListToModel(call.args).flatMap { args =>
|
||||||
if (flatStreamArguments)
|
if (flatStreamArguments)
|
||||||
args.map{ arg =>
|
args.map { arg =>
|
||||||
TagInliner.flat(arg._1, arg._2, true)
|
TagInliner.flat(arg._1, arg._2, true)
|
||||||
}.sequence
|
}.sequence
|
||||||
else
|
else
|
||||||
|
@ -6,7 +6,8 @@ import aqua.model.ValueModel.Ability
|
|||||||
import aqua.model.inline.Inline
|
import aqua.model.inline.Inline
|
||||||
import aqua.model.inline.Inline.MergeMode.*
|
import aqua.model.inline.Inline.MergeMode.*
|
||||||
import aqua.model.inline.RawValueInliner.unfold
|
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.raw.value.*
|
||||||
import aqua.types.*
|
import aqua.types.*
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ import scribe.Logging
|
|||||||
object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Logging {
|
object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Logging {
|
||||||
|
|
||||||
// in perspective literals can have properties and functors (like `nil` with length)
|
// 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,
|
literal: LiteralModel,
|
||||||
inl: Inline,
|
inl: Inline,
|
||||||
properties: Chain[PropertyModel]
|
properties: Chain[PropertyModel]
|
||||||
@ -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,
|
varModel: VarModel,
|
||||||
abilityType: NamedType,
|
abilityType: NamedType,
|
||||||
p: PropertyRaw
|
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,
|
varModel: VarModel,
|
||||||
p: PropertyRaw
|
p: PropertyRaw
|
||||||
): State[S, (VarModel, Inline)] =
|
): State[S, (VarModel, Inline)] =
|
||||||
@ -172,7 +173,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
private case class PropertyRawWithModel(raw: PropertyRaw, model: Option[PropertyModel])
|
private case class PropertyRawWithModel(raw: PropertyRaw, model: Option[PropertyModel])
|
||||||
|
|
||||||
// Unfold properties that we can process in parallel
|
// Unfold properties that we can process in parallel
|
||||||
private def optimizeProperties[S: Mangler: Exports: Arrows](
|
private def optimizeProperties[S: Mangler: Exports](
|
||||||
properties: Chain[PropertyRaw]
|
properties: Chain[PropertyRaw]
|
||||||
): State[S, (Chain[PropertyRawWithModel], Inline)] = {
|
): State[S, (Chain[PropertyRawWithModel], Inline)] = {
|
||||||
properties.map {
|
properties.map {
|
||||||
@ -211,7 +212,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
}.sequence.map(_.toList.unzip.bimap(Chain.fromSeq, _.combineAll))
|
}.sequence.map(_.toList.unzip.bimap(Chain.fromSeq, _.combineAll))
|
||||||
}
|
}
|
||||||
|
|
||||||
private def unfoldProperties[S: Mangler: Exports: Arrows](
|
private def unfoldProperties[S: Mangler: Exports](
|
||||||
prevInline: Inline,
|
prevInline: Inline,
|
||||||
vm: VarModel,
|
vm: VarModel,
|
||||||
properties: Chain[PropertyRaw],
|
properties: Chain[PropertyRaw],
|
||||||
@ -263,7 +264,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
/**
|
/**
|
||||||
* Unfold `stream[idx]`
|
* Unfold `stream[idx]`
|
||||||
*/
|
*/
|
||||||
private def unfoldStreamGate[S: Mangler: Exports: Arrows](
|
private def unfoldStreamGate[S: Mangler: Exports](
|
||||||
streamName: String,
|
streamName: String,
|
||||||
streamType: StreamType,
|
streamType: StreamType,
|
||||||
idx: ValueRaw
|
idx: ValueRaw
|
||||||
@ -325,21 +326,18 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
mergeMode = SeqMode
|
mergeMode = SeqMode
|
||||||
)
|
)
|
||||||
|
|
||||||
private def unfoldRawWithProperties[S: Mangler: Exports: Arrows](
|
private def unfoldRawWithProperties[S: Mangler: Exports](
|
||||||
raw: ValueRaw,
|
raw: ValueRaw,
|
||||||
properties: Chain[PropertyRaw],
|
properties: Chain[PropertyRaw],
|
||||||
propertiesAllowed: Boolean
|
propertiesAllowed: Boolean
|
||||||
): State[S, (ValueModel, Inline)] =
|
): State[S, (Export, Inline)] =
|
||||||
(raw, properties.uncons) match {
|
(raw, properties.uncons) match {
|
||||||
/**
|
|
||||||
* To inline
|
|
||||||
*/
|
|
||||||
case (
|
case (
|
||||||
vr @ VarRaw(_, st @ StreamType(_)),
|
vr @ VarRaw(_, st @ StreamType(_)),
|
||||||
Some(IntoIndexRaw(idx, _), otherProperties)
|
Some(IntoIndexRaw(idx, _), otherProperties)
|
||||||
) =>
|
) =>
|
||||||
unfold(vr).flatMap {
|
unfold(vr).flatMap {
|
||||||
case (VarModel(nameVM, _, _), inl) =>
|
case (Export.Value(VarModel(nameVM, _, _)), inl) =>
|
||||||
for {
|
for {
|
||||||
gateInlined <- unfoldStreamGate(nameVM, st, idx)
|
gateInlined <- unfoldStreamGate(nameVM, st, idx)
|
||||||
(gateVM, gateInline) = gateInlined
|
(gateVM, gateInline) = gateInlined
|
||||||
@ -362,12 +360,8 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
unfoldProperties(prevInline, vm, properties, propertiesAllowed)
|
unfoldProperties(prevInline, vm, properties, propertiesAllowed)
|
||||||
// To coerce types
|
// To coerce types
|
||||||
.map(identity)
|
.map(identity)
|
||||||
case (l: LiteralModel, inline) =>
|
case (l: LiteralModel, inl) =>
|
||||||
flatLiteralWithProperties(
|
flatLiteralWithProperties(l, inl, Chain.empty).flatMap { (varModel, prevInline) =>
|
||||||
l,
|
|
||||||
inline,
|
|
||||||
Chain.empty
|
|
||||||
).flatMap { (varModel, prevInline) =>
|
|
||||||
unfoldProperties(prevInline, varModel, properties, propertiesAllowed).map {
|
unfoldProperties(prevInline, varModel, properties, propertiesAllowed).map {
|
||||||
case (v, i) =>
|
case (v, i) =>
|
||||||
v -> i
|
v -> i
|
||||||
@ -389,10 +383,10 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
|
|||||||
flatten = VarModel(nn, varModel.`type`)
|
flatten = VarModel(nn, varModel.`type`)
|
||||||
} yield flatten -> Inline.tree(FlattenModel(varModel, flatten.name).leaf)
|
} yield flatten -> Inline.tree(FlattenModel(varModel, flatten.name).leaf)
|
||||||
|
|
||||||
override def apply[S: Mangler: Exports: Arrows](
|
override def apply[S: Mangler: Exports](
|
||||||
apr: ApplyPropertyRaw,
|
apr: ApplyPropertyRaw,
|
||||||
propertiesAllowed: Boolean
|
propertiesAllowed: Boolean
|
||||||
): State[S, (ValueModel, Inline)] = {
|
): State[S, (Export, Inline)] = {
|
||||||
val (raw, properties) = apr.unwind
|
val (raw, properties) = apr.unwind
|
||||||
unfoldRawWithProperties(raw, properties, propertiesAllowed)
|
unfoldRawWithProperties(raw, properties, propertiesAllowed)
|
||||||
}
|
}
|
||||||
|
@ -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.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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,260 +1,107 @@
|
|||||||
package aqua.model.inline.state
|
package aqua.model.inline.state
|
||||||
|
|
||||||
|
import aqua.model.FuncArrow
|
||||||
import aqua.model.ValueModel.Ability
|
import aqua.model.ValueModel.Ability
|
||||||
import aqua.model.{LiteralModel, ValueModel, VarModel}
|
import aqua.model.{LiteralModel, ValueModel, VarModel}
|
||||||
|
import aqua.types.ServiceType
|
||||||
import aqua.types.{AbilityType, GeneralAbilityType, NamedType}
|
import aqua.types.{AbilityType, GeneralAbilityType, NamedType}
|
||||||
|
|
||||||
import cats.data.{NonEmptyList, State}
|
import cats.data.{NonEmptyList, State}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exports – trace values available in the scope
|
* Exports – trace values available in the scope
|
||||||
* @tparam S
|
* @tparam S - State
|
||||||
* State
|
|
||||||
*/
|
*/
|
||||||
trait Exports[S] extends Scoped[S] {
|
trait Exports[S] extends Scoped[S] {
|
||||||
self =>
|
self =>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [[value]] is accessible as [[exportName]]
|
* [[exp]] is accessible as [[name]]
|
||||||
* @param exportName
|
* @param name - Name
|
||||||
* Name
|
* @param exp - Export
|
||||||
* @param value
|
|
||||||
* Value
|
|
||||||
*/
|
*/
|
||||||
def resolved(exportName: String, value: ValueModel): State[S, Unit]
|
def resolved(name: String, exp: Exports.Export): 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]
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the whole map of exports
|
* Resolve the whole map of exports
|
||||||
* @param exports
|
* @param exports - name -> export
|
||||||
* name -> value
|
|
||||||
*/
|
*/
|
||||||
def resolved(exports: Map[String, ValueModel]): State[S, Unit]
|
def resolved(exports: Map[String, Exports.Export]): State[S, Unit]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all export keys
|
* Rename names in variables
|
||||||
|
* @param renames - oldName -> newName
|
||||||
*/
|
*/
|
||||||
def getKeys: State[S, Set[String]]
|
def renameExports(renames: Map[String, String]): State[S, Unit]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get ability field from export
|
* Get export by name
|
||||||
* @param name variable ability name
|
* @param name - Name
|
||||||
* @param field ability field
|
|
||||||
*/
|
*/
|
||||||
def getAbilityField(name: String, field: String): State[S, Option[ValueModel]]
|
def get(name: String): State[S, Option[Exports.Export]]
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all the values available in the scope
|
|
||||||
*/
|
|
||||||
val exports: State[S, Map[String, ValueModel]]
|
|
||||||
|
|
||||||
final def gather(names: Seq[String]): State[S, Map[String, ValueModel]] =
|
|
||||||
exports.map(Exports.gatherFrom(names, _))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change [[S]] to [[R]]
|
* Change [[S]] to [[R]]
|
||||||
*/
|
*/
|
||||||
def transformS[R](f: R => S, g: (R, S) => R): Exports[R] = new Exports[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] =
|
override def resolved(name: String, exp: Exports.Export): State[R, Unit] =
|
||||||
self.resolved(exportName, value).transformS(f, g)
|
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)
|
self.resolved(exports).transformS(f, g)
|
||||||
|
|
||||||
override def resolveAbilityField(
|
override def renameExports(renames: Map[String, String]): State[R, Unit] =
|
||||||
abilityExportName: String,
|
self.renameExports(renames).transformS(f, g)
|
||||||
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] =
|
override def get(name: String): State[R, Option[Exports.Export]] =
|
||||||
self.copyWithAbilityPrefix(prefix, newPrefix).transformS(f, g)
|
self.get(name).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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Exports {
|
object Exports {
|
||||||
|
|
||||||
|
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])
|
||||||
|
}
|
||||||
|
|
||||||
|
object Export {
|
||||||
|
|
||||||
|
extension (c: Export.Context) {
|
||||||
|
|
||||||
|
def resolved(name: String, exp: Export): Export.Context =
|
||||||
|
c.copy(values = c.values + (name -> exp))
|
||||||
|
|
||||||
|
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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def apply[S](using exports: Exports[S]): Exports[S] = exports
|
def apply[S](using exports: Exports[S]): Exports[S] = exports
|
||||||
|
|
||||||
/**
|
object Simple extends Exports[Export.Context] {
|
||||||
* 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.filterKeys(names.toSet ++ related).toMap
|
type ST[A] = State[Export.Context, A]
|
||||||
}
|
|
||||||
|
|
||||||
// Get last linked VarModel
|
override def resolved(name: String, exp: Export): ST[Unit] =
|
||||||
def getLastValue(name: String, state: Map[String, ValueModel]): Option[ValueModel] = {
|
State.modify(_.resolved(name, exp))
|
||||||
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 Simple extends Exports[Map[String, ValueModel]] {
|
override def resolved(exports: Map[String, Export]): ST[Unit] =
|
||||||
|
State.modify(_.resolved(exports))
|
||||||
|
|
||||||
// Make links from one set of abilities to another (for ability assignment)
|
override def renameExports(renames: Map[String, String]): ST[Unit] =
|
||||||
private def getAbilityPairs(
|
State.modify(_.renameExports(renames))
|
||||||
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))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def resolved(
|
override def get(name: String): ST[Option[Export]] =
|
||||||
exportName: String,
|
State.inspect(_.values.get(name))
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def getLastVarName(name: String): State[Map[String, ValueModel], Option[String]] =
|
|
||||||
State.get.map(st => getLastValue(name, st).collect { case VarModel(name, _, _) => name })
|
|
||||||
|
|
||||||
override def resolved(exports: Map[String, ValueModel]): State[Map[String, ValueModel], Unit] =
|
|
||||||
State.modify(_ ++ exports)
|
|
||||||
|
|
||||||
override def resolveAbilityField(
|
|
||||||
abilityExportName: String,
|
|
||||||
fieldName: String,
|
|
||||||
value: ValueModel
|
|
||||||
): State[Map[String, ValueModel], Unit] =
|
|
||||||
State.modify(_ + (AbilityType.fullName(abilityExportName, fieldName) -> value))
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def getKeys: State[Map[String, ValueModel], Set[String]] = State.get.map(_.keySet)
|
|
||||||
|
|
||||||
override def getAbilityField(
|
|
||||||
name: String,
|
|
||||||
field: String
|
|
||||||
): State[Map[String, ValueModel], Option[ValueModel]] =
|
|
||||||
State.get.map(_.get(AbilityType.fullName(name, field)))
|
|
||||||
|
|
||||||
override val exports: State[Map[String, ValueModel], Map[String, ValueModel]] =
|
|
||||||
State.get
|
|
||||||
|
|
||||||
override val purge: State[Map[String, ValueModel], Map[String, ValueModel]] =
|
|
||||||
for {
|
|
||||||
s <- State.get
|
|
||||||
_ <- State.set(Map.empty)
|
|
||||||
} yield s
|
|
||||||
|
|
||||||
override protected def fill(s: Map[String, ValueModel]): State[Map[String, ValueModel], Unit] =
|
|
||||||
State.set(s)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user