From 5269fe92de8748655ca7cd5542b0e8d94e320acb Mon Sep 17 00:00:00 2001 From: DieMyst Date: Tue, 9 Jan 2024 15:35:54 +0700 Subject: [PATCH 01/13] String -> StringBuilder, debug stuff --- .../.jvm/src/main/scala/aqua/api/Test.scala | 35 ++++++- aqua-src/antithesis.aqua | 51 +++++++++- .../src/main/scala/aqua/backend/air/Air.scala | 93 +++++++++++++------ .../scala/aqua/compiler/AquaCompiler.scala | 17 +--- .../scala/aqua/compiler/CompilerAPI.scala | 31 +++---- io/src/test/scala/aqua/ImportsSpec.scala | 2 +- .../src/main/scala/aqua/linker/Linker.scala | 4 +- .../aqua/model/inline/ArrowInliner.scala | 2 + .../aqua/model/inline/RawValueInliner.scala | 12 +-- .../scala/aqua/model/inline/TagInliner.scala | 2 +- .../inline/raw/CallArrowRawInliner.scala | 7 +- .../inline/raw/CallServiceRawInliner.scala | 4 +- .../main/scala/aqua/model/AquaContext.scala | 22 ++--- .../aqua/model/transform/Transform.scala | 4 + .../model/transform/topology/PathFinder.scala | 24 ++--- .../model/transform/topology/Topology.scala | 16 ++-- .../scala/aqua/parser/lift/FileSpan.scala | 3 +- .../semantics/expr/func/CallArrowSem.scala | 8 +- .../rules/locations/LocationsState.scala | 5 +- .../scala/aqua/logging/LogFormatter.scala | 4 +- 20 files changed, 226 insertions(+), 120 deletions(-) diff --git a/api/api/.jvm/src/main/scala/aqua/api/Test.scala b/api/api/.jvm/src/main/scala/aqua/api/Test.scala index f587abaac..e554ccd82 100644 --- a/api/api/.jvm/src/main/scala/aqua/api/Test.scala +++ b/api/api/.jvm/src/main/scala/aqua/api/Test.scala @@ -14,18 +14,43 @@ import fs2.{Stream, text} object Test extends IOApp.Simple { override def run: IO[Unit] = { + APICompilation .compilePath( +// "/home/diemust/git/decider/src/aqua/decider/poll.aqua", +// "/home/diemust/git/ha/src/aqua/main.aqua", "./aqua-src/antithesis.aqua", - Imports.fromMap(Map("/" -> Map("" -> List("./aqua")))), - AquaAPIConfig(targetType = TypeScriptType), + Imports.fromMap( + Map( + "/" -> Map( +// "" -> List( +// "/home/diemust/git/decider/.fluence/aqua", +// "/home/diemust/.fluence/npm/@fluencelabs/aqua-lib/0.9.0/node_modules", +// "/home/diemust/.fluence/npm/@fluencelabs/spell/0.6.0/node_modules", +// "/home/diemust/.fluence/npm/@fluencelabs/registry/0.8.7/node_modules", +// "/home/diemust/.fluence/npm/@fluencelabs/aqua-ipfs/0.5.24/node_modules", +// "/home/diemust/.fluence/npm/@fluencelabs/installation-spell/0.6.0/node_modules" +// ) + "" -> List( + "/home/diemust/git/ha/.fluence/aqua", + "/home/diemust/.fluence/npm/@fluencelabs/aqua-lib/0.9.0/node_modules", + "/home/diemust/.fluence/npm/@fluencelabs/spell/0.6.0/node_modules", + "/home/diemust/.fluence/npm/@fluencelabs/registry/0.8.7/node_modules", + "/home/diemust/.fluence/npm/@fluencelabs/aqua-ipfs/0.5.24/node_modules", + "/home/diemust/.fluence/npm/@fluencelabs/installation-spell/0.6.0/node_modules" + ) + ) + ) + ), + AquaAPIConfig(logLevel = "info"), TypeScriptBackend(false, "IFluenceClient$$") - ) - .flatMap { res => + ).timed + .flatMap { case (duration, res) => + println("Compilation time: " + duration.toMillis) val (warnings, result) = res.value.run IO.delay { - warnings.toList.foreach(println) + // warnings.toList.foreach(println) } *> result.fold( errors => IO.delay { diff --git a/aqua-src/antithesis.aqua b/aqua-src/antithesis.aqua index 04fd94067..eb20c0818 100644 --- a/aqua-src/antithesis.aqua +++ b/aqua-src/antithesis.aqua @@ -1,3 +1,48 @@ -func arr() -> string: - n = "str" - <- n \ No newline at end of file +aqua M + +export haveFun + +data Worker: + host_id: string + worker_id: string + +ability Promise: + yield: -> () + -- Cannot make empty failed as (never) or smth like that without introducing a coordinator + --failed: -> () + +service Dummy("d"): + greeting(s: string) -> string + +ability Job: + run() + +ability WorkerJob: + runOnSingleWorker(worker: Worker) -> Job + +func done(): + a = "need some body!" + -- I'm done + +func done_promise() -> Promise: + <- Promise(yield = done) + +func disjoint_run{WorkerJob}() -> Job: + workers: *Worker + + run = func (): + job2 <- WorkerJob.runOnSingleWorker() + + <- Job(run = run) + +func haveFun(): + job2 = () -> Job: + run2 = (): + Dummy.greeting("hell!") + + <- Job(run = run2) + + worker_job = WorkerJob(runOnSingleWorker = job2) + subnet_job <- disjoint_run{worker_job}() + + subnet_job.run() \ No newline at end of file diff --git a/backend/air/src/main/scala/aqua/backend/air/Air.scala b/backend/air/src/main/scala/aqua/backend/air/Air.scala index 56a7bf226..b619b29a6 100644 --- a/backend/air/src/main/scala/aqua/backend/air/Air.scala +++ b/backend/air/src/main/scala/aqua/backend/air/Air.scala @@ -120,42 +120,77 @@ object Air { case class Comment(comment: String, air: Air) extends Air(Keyword.NA) - private def show(depth: Int, air: Air): String = { - def showNext(a: Air) = show(depth + 1, a) + private def showInternal(space: String, sb: StringBuilder, air: Air): Unit = { - val space = " " * depth + def showNext(a: Air): Unit = showInternal(space + " ", sb, a) air match { case Air.Comment(c, a) => - space + "; " + c.replace("\n", "\n" + space + "; ") + "\n" + - show(depth, a) + sb.append(space) + .append("; ") + .append(c.replace("\n", "\n" + space + "; ")) + .append("\n") + + showInternal(space, sb, a) + case _ => - s"$space(${air.keyword.value}" + - (air match { - case Air.Null ⇒ "" - case Air.Never ⇒ "" - case Air.Next(label) ⇒ s" $label" - case Air.New(item, inst) ⇒ s" ${item.show}\n${showNext(inst)}$space" - case Air.Fold(iter, label, inst, lastInst) ⇒ - val l = show(depth + 1, lastInst) - s" ${iter.show} $label\n${showNext(inst)}$l$space" - case Air.Match(left, right, inst) ⇒ - s" ${left.show} ${right.show}\n${showNext(inst)}$space" - case Air.Mismatch(left, right, inst) ⇒ - s" ${left.show} ${right.show}\n${showNext(inst)}$space" - case Air.Par(l, r) ⇒ s"\n${showNext(l)}${showNext(r)}$space" - case Air.Seq(l, r) ⇒ s"\n${showNext(l)}${showNext(r)}$space" - case Air.Xor(l, r) ⇒ s"\n${showNext(l)}${showNext(r)}$space" - case Air.Call(triplet, args, res) ⇒ - s" ${triplet.show} [${args.map(_.show).mkString(" ")}]${res.fold("")(" " + _)}" - case Air.Ap(operand, result) ⇒ s" ${operand.show} $result" - case Air.ApStreamMap(key, operand, result) ⇒ s" (${key.show} ${operand.show}) $result" - case Air.Fail(operand) => s" ${operand.show}" - case Air.Canon(operand, peerId, result) ⇒ s" ${peerId.show} ${operand.show} $result" - case Air.Comment(_, _) => ";; Should not be displayed" - }) + ")\n" + sb.append(s"$space(${air.keyword.value}") + (air match { + case Air.Null ⇒ + case Air.Never ⇒ + case Air.Next(label) ⇒ sb.append(s" $label") + case Air.New(item, inst) ⇒ + sb.append(s" ${item.show}\n") + showNext(inst) + sb.append(space) + case Air.Fold(iter, label, inst, lastInst) ⇒ + sb.append(" ").append(s" ${iter.show} $label\n") + showNext(inst) + showNext(lastInst) + sb.append(space) + case Air.Match(left, right, inst) ⇒ + sb.append(s" ${left.show} ${right.show}\n") + showNext(inst) + sb.append(space) + case Air.Mismatch(left, right, inst) ⇒ + sb.append(s" ${left.show} ${right.show}\n") + showNext(inst) + sb.append(space) + case Air.Par(l, r) ⇒ + sb.append("\n") + showNext(l) + showNext(r) + sb.append(space) + case Air.Seq(l, r) ⇒ + sb.append("\n") + showNext(l) + showNext(r) + sb.append(space) + case Air.Xor(l, r) ⇒ + sb.append("\n") + showNext(l) + showNext(r) + sb.append(space) + case Air.Call(triplet, args, res) ⇒ + sb.append(s" ${triplet.show} [${args.map(_.show).mkString(" ")}]${res.fold("")(" " + _)}") + case Air.Ap(operand, result) ⇒ + sb.append(s" ${operand.show} $result") + case Air.ApStreamMap(key, operand, result) ⇒ + sb.append(s" (${key.show} ${operand.show}) $result") + case Air.Fail(operand) => sb.append(s" ${operand.show}") + case Air.Canon(operand, peerId, result) ⇒ + sb.append(s" ${peerId.show} ${operand.show} $result") + case Air.Comment(_, _) => ";; Should not be displayed" + }) + sb.append(")\n") } + } + private def show(depth: Int, air: Air): String = { + val sb = StringBuilder() + val space = " " * depth + showInternal(space, sb, air) + sb.result() } implicit val s: Show[Air] = Show.show(show(0, _)) diff --git a/compiler/src/main/scala/aqua/compiler/AquaCompiler.scala b/compiler/src/main/scala/aqua/compiler/AquaCompiler.scala index 66b7c7446..94643ff83 100644 --- a/compiler/src/main/scala/aqua/compiler/AquaCompiler.scala +++ b/compiler/src/main/scala/aqua/compiler/AquaCompiler.scala @@ -1,30 +1,19 @@ package aqua.compiler -import aqua.backend.Backend import aqua.compiler.AquaError.{ParserError as AquaParserError, *} import aqua.linker.{AquaModule, Linker, Modules} -import aqua.model.AquaContext -import aqua.parser.lift.{LiftParser, Span} import aqua.parser.{Ast, ParserError} -import aqua.raw.RawPart.Parts -import aqua.raw.{RawContext, RawPart} -import aqua.res.AquaRes -import aqua.semantics.header.{HeaderHandler, HeaderSem, Picker} -import aqua.semantics.{CompilerState, Semantics} -import aqua.semantics.{SemanticError, SemanticWarning} +import aqua.semantics.header.{HeaderHandler, Picker} +import aqua.semantics.{SemanticError, Semantics} import cats.arrow.FunctionK import cats.data.* -import cats.data.Validated.{Invalid, Valid, validNec} -import cats.parse.Parser0 import cats.syntax.applicative.* import cats.syntax.either.* import cats.syntax.flatMap.* import cats.syntax.functor.* -import cats.syntax.monoid.* -import cats.syntax.semigroup.* import cats.syntax.traverse.* -import cats.{Comonad, Functor, Monad, Monoid, Order, ~>} +import cats.{Comonad, Monad, Monoid, Order, ~>} import scribe.Logging class AquaCompiler[F[_]: Monad, E, I: Order, S[_]: Comonad, C: Monoid: Picker]( diff --git a/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala b/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala index 722c59a23..b3cf3a759 100644 --- a/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala +++ b/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala @@ -1,33 +1,22 @@ package aqua.compiler +import aqua.backend.Backend import aqua.compiler.AquaError.* -import aqua.backend.{AirFunction, Backend} -import aqua.linker.{AquaModule, Linker, Modules} import aqua.model.AquaContext -import aqua.parser.lift.{LiftParser, Span} import aqua.parser.{Ast, ParserError} -import aqua.raw.RawPart.Parts -import aqua.raw.{RawContext, RawPart} -import aqua.res.AquaRes +import aqua.raw.RawContext +import aqua.semantics.RawSemantics import aqua.semantics.header.{HeaderHandler, HeaderSem} -import aqua.semantics.{CompilerState, RawSemantics, Semantics} import cats.data.* -import cats.data.Validated.{invalid, validNec, Invalid, Valid} -import cats.parse.Parser0 -import cats.syntax.applicative.* +import cats.syntax.either.* import cats.syntax.flatMap.* -import cats.syntax.foldable.* import cats.syntax.functor.* -import cats.syntax.monoid.* -import cats.syntax.semigroup.* +import cats.syntax.applicative.* import cats.syntax.traverse.* -import cats.syntax.either.* -import cats.{~>, Comonad, Monad, Monoid, Order} +import cats.{Comonad, Monad, Monoid, Order} import scribe.Logging -import scala.collection.MapView - object CompilerAPI extends Logging { private def toAquaProcessed[I: Order, E, S[_]: Comonad]( @@ -35,6 +24,8 @@ object CompilerAPI extends Logging { ): Chain[AquaProcessed[I]] = { logger.trace("linking finished") + println("files with context: " + filesWithContext.keys) + filesWithContext.toList // Process all contexts maintaining Cache .traverse { case (i, rawContext) => @@ -84,14 +75,19 @@ object CompilerAPI extends Logging { val compiler = getAquaCompiler[F, E, I, S](config) for { + _ <- logger.trace("Start compilation").pure[F] compiledRaw <- compiler.compileRaw(sources, parser) + _ <- logger.trace("Compile raw ended").pure[F] compiledV = compiledRaw.map(toAquaProcessed) + _ <- logger.trace("Aqua processed ended").pure[F] _ <- airValidator.init() result <- compiledV.flatTraverse { compiled => compiled.traverse { ap => logger.trace("generating output...") val res = backend.transform(ap.context) + logger.trace("end transforming...") val generated = backend.generate(res) + logger.trace("end generating...") val air = generated.toList.flatMap(_.air) val compiled = AquaCompiled( sourceId = ap.id, @@ -109,6 +105,7 @@ object CompilerAPI extends Logging { ) }.map(_.sequence.toEither.toEitherT) } + _ <- logger.trace("Writing result ended").pure[F] } yield result } diff --git a/io/src/test/scala/aqua/ImportsSpec.scala b/io/src/test/scala/aqua/ImportsSpec.scala index c463fd1b7..57d0c6d9b 100644 --- a/io/src/test/scala/aqua/ImportsSpec.scala +++ b/io/src/test/scala/aqua/ImportsSpec.scala @@ -11,7 +11,7 @@ class ImportsSpec extends AnyFlatSpec with ScalaCheckPropertyChecks with Matcher implicit override val generatorDrivenConfig = // Tests here are lightweight, so we can afford to run more of them - PropertyCheckConfiguration(minSuccessful = 500, sizeRange = 64) + PropertyCheckConfiguration(minSuccessful = 50, sizeRange = 32) val shortAlphaNumStr = for { length <- Gen.choose(1, 10) diff --git a/linker/src/main/scala/aqua/linker/Linker.scala b/linker/src/main/scala/aqua/linker/Linker.scala index 8669e201b..e7e2d91bf 100644 --- a/linker/src/main/scala/aqua/linker/Linker.scala +++ b/linker/src/main/scala/aqua/linker/Linker.scala @@ -106,9 +106,9 @@ object Linker extends Logging { logger.debug(s"${m.id} dependsOn $importKeys") val deps: T => T = importKeys.map(acc).foldLeft(identity[T]) { case (fAcc, f) => - logger.debug("COMBINING ONE TIME ") +// logger.debug("COMBINING ONE TIME ") t => { - logger.debug(s"call combine $t") +// logger.debug(s"call combine $t") fAcc(t) |+| f(t) } } 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 f69d2644b..a8bd31af3 100644 --- a/model/inline/src/main/scala/aqua/model/inline/ArrowInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/ArrowInliner.scala @@ -88,7 +88,9 @@ object ArrowInliner extends Logging { call: CallModel, outsideDeclaredStreams: Set[String] ): State[S, InlineResult] = for { + _ <- State.pure(logger.trace(s"before handle for ${fn.funcName}")) callableFuncBodyNoTopology <- TagInliner.handleTree(fn.body) + _ <- State.pure(logger.trace(s"TagInliner.handleTree finish for ${fn.funcName}")) callableFuncBody = fn.capturedTopology .fold(SeqModel)(ApplyTopologyModel.apply) 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 604733fd3..e04b97148 100644 --- a/model/inline/src/main/scala/aqua/model/inline/RawValueInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/RawValueInliner.scala @@ -28,7 +28,7 @@ object RawValueInliner extends Logging { propertiesAllowed: Boolean = true ): State[S, (ValueModel, Inline)] = for { 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 { case VarRaw(name, t) => for { @@ -83,20 +83,20 @@ object RawValueInliner extends Logging { for { vmp <- unfoldF (vm, map) = vmp - _ = logger.trace("MOD " + vm) +// _ = logger.trace("MOD " + vm) dc <- Exports[S].exports - _ = logger.trace("DEC " + dc) +// _ = logger.trace("DEC " + dc) ops <- inlineToTree(map) - _ = logger.trace("desugarized ops: " + ops) - _ = logger.trace("map was: " + map) +// _ = logger.trace("desugarized ops: " + ops) +// _ = logger.trace("map was: " + map) } yield vm -> parDesugarPrefix(ops.filterNot(_ == EmptyModel.leaf)) def valueToModel[S: Mangler: Exports: Arrows]( value: ValueRaw, propertiesAllowed: Boolean = true ): State[S, (ValueModel, Option[OpModel.Tree])] = for { - _ <- StateT.liftF(Eval.later(logger.trace("RAW " + value))) +// _ <- StateT.liftF(Eval.later(logger.trace("RAW " + value))) model <- toModel(unfold(value, propertiesAllowed)) } yield model 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 f161348ec..a871a8fa5 100644 --- a/model/inline/src/main/scala/aqua/model/inline/TagInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/TagInliner.scala @@ -319,7 +319,7 @@ object TagInliner extends Logging { operands .traverse(o => valueToModel(o)) .map(nel => { - logger.trace("join after " + nel.map(_._1)) +// logger.trace("join after " + nel.map(_._1)) // Empty because join behaviour will be processed in ApplyPropertiesRawInliner TagInlined.Empty(prefix = parDesugarPrefix(nel.toList.flatMap(_._2))) }) 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..8b5d153c8 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 @@ -18,7 +18,7 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { value: CallArrowRaw, exportTo: List[Call.Export] ): State[S, (List[ValueModel], Inline)] = { - logger.trace(s"${exportTo.mkString(" ")} $value") +// logger.trace(s"${exportTo.mkString(" ")} $value") val call = Call(value.arguments, exportTo) @@ -26,7 +26,7 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { * Here the back hop happens from [[TagInliner]] to [[ArrowInliner.callArrow]] */ val funcName = value.ability.fold(value.name)(_ + "." + value.name) - logger.trace(s" $funcName") +// logger.trace(s" $funcName") resolveArrow(funcName, call) } @@ -35,7 +35,7 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { fn: FuncArrow, call: Call ): State[S, (List[ValueModel], Inline)] = { - logger.trace(Console.YELLOW + s"Call arrow ${fn.funcName}" + Console.RESET) +// logger.trace(Console.YELLOW + s"Call arrow ${fn.funcName}" + Console.RESET) callToModel(call, false).flatMap { case (cm, p) => ArrowInliner .callArrowRet(fn, cm) @@ -59,6 +59,7 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { arrows <- Arrows[S].arrows exports <- Exports[S].exports lastArrow <- Exports[S].getLastVarName(funcName) + _ = println("lastArrow: " + lastArrow) arrow = arrows .get(funcName) .orElse( 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..0bdc27269 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 @@ -15,8 +15,8 @@ object CallServiceRawInliner extends RawInliner[CallServiceRaw] with Logging { 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) +// logger.trace(s"${exportTo.mkString(" ")} $value") +// logger.trace(Console.BLUE + s"call service id ${value.serviceId}" + Console.RESET) val call = Call(value.arguments, exportTo) diff --git a/model/src/main/scala/aqua/model/AquaContext.scala b/model/src/main/scala/aqua/model/AquaContext.scala index 9be943798..aad235bc9 100644 --- a/model/src/main/scala/aqua/model/AquaContext.scala +++ b/model/src/main/scala/aqua/model/AquaContext.scala @@ -156,10 +156,10 @@ object AquaContext extends Logging { // Convert RawContext into AquaContext, with exports handled def exportsFromRaw(rawContext: RawContext, cache: Cache): (AquaContext, Cache) = { - logger.trace(s"ExportsFromRaw ${rawContext.module}") +// logger.trace(s"ExportsFromRaw ${rawContext.module}") val (ctx, newCache) = fromRawContext(rawContext, cache) - logger.trace("raw: " + rawContext) - logger.trace("ctx: " + ctx) +// logger.trace("raw: " + rawContext) +// logger.trace("ctx: " + ctx) rawContext.exports .foldLeft( @@ -183,7 +183,7 @@ object AquaContext extends Logging { val (newCtx, newCache) = rawContext.parts .foldLeft[(AquaContext, Cache)] { // Laziness unefficiency happens here - logger.trace(s"raw: ${rawContext.module}") +// logger.trace(s"raw: ${rawContext.module}") val (i, c) = rawContext.init .map(fromRawContext(_, cache)) @@ -199,11 +199,11 @@ object AquaContext extends Logging { (i |+| blank.copy(abilities = abs)) -> absCache } { case ((ctx, ctxCache), (partContext, c: ConstantRaw)) => - logger.trace("Adding constant " + c.name) +// logger.trace("Adding constant " + c.name) // Just saving a constant // Actually this should have no effect, as constants are resolved by semantics val (pctx, pcache) = fromRawContext(partContext, ctxCache) - logger.trace("Got " + c.name + " from raw") +// logger.trace("Got " + c.name + " from raw") val add = blank .copy(values = @@ -215,12 +215,12 @@ object AquaContext extends Logging { case ((ctx, ctxCache), (partContext, func: FuncRaw)) => // To add a function, we have to know its scope - logger.trace("Adding func " + func.name) +// logger.trace("Adding func " + func.name) val (pctx, pcache) = fromRawContext(partContext, ctxCache) - logger.trace("Got " + func.name + " from raw") +// logger.trace("Got " + func.name + " from raw") val fr = FuncArrow.fromRaw(func, pctx.allFuncs, pctx.allValues, None) - logger.trace("Captured recursively for " + func.name) +// logger.trace("Captured recursively for " + func.name) val add = blank.copy(funcs = Map(func.name -> fr)) (ctx |+| add, pcache) @@ -232,9 +232,9 @@ object AquaContext extends Logging { case ((ctx, ctxCache), (partContext, m: ServiceRaw)) => // To add a service, we need to resolve its ID, if any - logger.trace("Adding service " + m.name) +// logger.trace("Adding service " + m.name) val (pctx, pcache) = fromRawContext(partContext, ctxCache) - logger.trace("Got " + m.name + " from raw") +// logger.trace("Got " + m.name + " from raw") val id = m.defaultId .map(ValueModel.fromRaw) .map(_.resolveWith(pctx.allValues)) diff --git a/model/transform/src/main/scala/aqua/model/transform/Transform.scala b/model/transform/src/main/scala/aqua/model/transform/Transform.scala index 760be8cc4..d06df33c6 100644 --- a/model/transform/src/main/scala/aqua/model/transform/Transform.scala +++ b/model/transform/src/main/scala/aqua/model/transform/Transform.scala @@ -117,6 +117,7 @@ object Transform extends Logging { ) for { + _ <- Eval.later { logger.trace("start transforming...")} // Pre transform and inline the function model <- funcToModelTree(func, preTransformer) // Post transform the function. @@ -125,9 +126,12 @@ object Transform extends Logging { // Topology module needs this `on` // as a starting point. initModel = initCallable.onInitPeer.wrap(model) + _ <- Eval.later { logger.trace("end funcToModel...")} tracingModel <- tracing(initModel) + _ <- Eval.later { logger.trace("end tracing...")} // Resolve topology resolved <- Topology.resolve(tracingModel) + _ <- Eval.later { logger.trace("end topology...")} // Clear the tree result = clear(resolved) } yield FuncRes( diff --git a/model/transform/src/main/scala/aqua/model/transform/topology/PathFinder.scala b/model/transform/src/main/scala/aqua/model/transform/topology/PathFinder.scala index 390a3a4ca..fca293173 100644 --- a/model/transform/src/main/scala/aqua/model/transform/topology/PathFinder.scala +++ b/model/transform/src/main/scala/aqua/model/transform/topology/PathFinder.scala @@ -56,8 +56,8 @@ object PathFinder extends Logging { fromPeer: Option[ValueModel], toPeer: Option[ValueModel] ): Chain[ValueModel] = { - logger.trace(s"FROM ON: $fromOn") - logger.trace(s"TO ON: $toOn") +// logger.trace(s"FROM ON: $fromOn") +// logger.trace(s"TO ON: $toOn") val (from, to) = skipCommonPrefix(fromOn, toOn) val fromFix = @@ -67,20 +67,20 @@ object PathFinder extends Logging { if (to.isEmpty && fromPeer != toPeer) Chain.fromOption(toOn.lastOption) else to - logger.trace("FIND PATH FROM | " + fromFix) - logger.trace(" TO | " + toFix) +// logger.trace("FIND PATH FROM | " + fromFix) +// logger.trace(" TO | " + toFix) val fromTo = fromFix.reverse.flatMap(_.via.reverse) ++ toFix.flatMap(_.via) - logger.trace(s"FROM TO: $fromTo") +// logger.trace(s"FROM TO: $fromTo") val toOptimize = Chain.fromOption(fromPeer) ++ fromTo ++ Chain.fromOption(toPeer) val optimized = optimizePath(toOptimize, fromPeer, toPeer) - logger.trace( - s"FROM PEER '${fromPeer.map(_.toString).getOrElse("None")}' TO PEER '${toPeer.map(_.toString).getOrElse("None")}'" - ) - logger.trace(" Optimized: " + optimized) +// logger.trace( +// s"FROM PEER '${fromPeer.map(_.toString).getOrElse("None")}' TO PEER '${toPeer.map(_.toString).getOrElse("None")}'" +// ) +// logger.trace(" Optimized: " + optimized) optimized } @@ -108,9 +108,9 @@ object PathFinder extends Logging { case (acc, p) => acc :+ p } - logger.trace(s"PEER IDS: $optimized") - logger.trace(s"FROM PEER: $fromPeer") - logger.trace(s"TO PEER: $toPeer") +// logger.trace(s"PEER IDS: $optimized") +// logger.trace(s"FROM PEER: $fromPeer") +// logger.trace(s"TO PEER: $toPeer") val skipFrom = optimized.uncons match { case Some((head, tail)) if fromPeer.contains(head) => tail diff --git a/model/transform/src/main/scala/aqua/model/transform/topology/Topology.scala b/model/transform/src/main/scala/aqua/model/transform/topology/Topology.scala index 7296872d7..773ccae41 100644 --- a/model/transform/src/main/scala/aqua/model/transform/topology/Topology.scala +++ b/model/transform/src/main/scala/aqua/model/transform/topology/Topology.scala @@ -61,10 +61,10 @@ case class Topology private ( .flatMap(tops => cursor.op match { case CaptureTopologyModel(name) => - logger.trace(s"Capturing topology `$name`") +// logger.trace(s"Capturing topology `$name`") Eval.now(tops + (name -> this)) case x => - logger.trace(s"Skip $x") +// logger.trace(s"Skip $x") cursor.toLastChild .traverse(_.topology.capturedTopologies) .map(_.getOrElse(Map.empty) ++ tops) @@ -327,16 +327,16 @@ object Topology extends Logging { } val resolvedCofree = cursor.traverse(wrap) { rc => - logger.debug(s"<:> $rc") +// logger.debug(s"<:> $rc") val currI = nextI val resolved = MakeRes .resolve(rc.topology.currentPeerId, currI) .lift .apply(rc.op) - logger.trace("Resolved: " + resolved) +// logger.trace("Resolved: " + resolved) - if (debug) printDebugInfo(rc, currI) +// if (debug) printDebugInfo(rc, currI) val chainZipperEv = resolved.traverse(tree => ( @@ -350,7 +350,7 @@ object Topology extends Logging { OptionT(chainZipperEv) } - logger.trace("Resolved Cofree: " + resolvedCofree.value.map(_.forceAll)) +// logger.trace("Resolved Cofree: " + resolvedCofree.value.map(_.forceAll)) resolvedCofree.map(NonEmptyChain.fromChain(_).map(_.uncons)).map { case None => @@ -416,12 +416,12 @@ object Topology extends Logging { tree: ResolvedOp.Tree ): Eval[Unit] = Eval.later { - if (cz.next.nonEmpty || cz.prev.nonEmpty) { + /*if (cz.next.nonEmpty || cz.prev.nonEmpty) { logger.debug(s"Resolved $rc -> $tree") if (cz.prev.nonEmpty) logger.trace("From prev: " + cz.prev.map(_.head).toList.mkString(" -> ")) if (cz.next.nonEmpty) logger.trace("To next: " + cz.next.map(_.head).toList.mkString(" -> ")) - } else logger.debug(s"EMPTY $rc -> $tree") + } else logger.debug(s"EMPTY $rc -> $tree")*/ } } diff --git a/parser/src/main/scala/aqua/parser/lift/FileSpan.scala b/parser/src/main/scala/aqua/parser/lift/FileSpan.scala index abd103244..0442aa765 100644 --- a/parser/src/main/scala/aqua/parser/lift/FileSpan.scala +++ b/parser/src/main/scala/aqua/parser/lift/FileSpan.scala @@ -16,7 +16,8 @@ case class FileSpan(name: String, locationMap: Eval[LocationMap], span: Span) { * @return FileSpan.Focus */ def focus(ctx: Int): Option[FileSpan.Focus] = - span.focus(locationMap.value, ctx).map(FileSpan.Focus(name, locationMap, ctx, _)) + span. + focus(locationMap.value, ctx).map(FileSpan.Focus(name, locationMap, ctx, _)) override def hashCode(): Int = (name, span).hashCode() diff --git a/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala b/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala index 6d291d130..016b09be4 100644 --- a/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala +++ b/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala @@ -27,8 +27,13 @@ class CallArrowSem[S[_]](val expr: CallArrowExpr[S]) extends AnyVal { private def getExports[Alg[_]: Monad](codomain: ProductType)(using N: NamesAlgebra[S, Alg], T: TypesAlgebra[S, Alg] - ): Alg[List[Call.Export]] = + ): Alg[List[Call.Export]] = { + println("call: " + expr.callArrow) + println("variables: " + variables) + println("codomain: " + codomain) (variables zip codomain.toList).traverse { case (v, t) => + println("v: " + v) + println("t: " + t) N.read(v, mustBeDefined = false).flatMap { case Some(stream @ StreamType(st)) => T.ensureTypeMatches(v, st, t).as(Call.Export(v.value, stream)) @@ -36,6 +41,7 @@ class CallArrowSem[S[_]](val expr: CallArrowExpr[S]) extends AnyVal { N.define(v, t).as(Call.Export(v.value, t)) } } + } private def toModel[Alg[_]: Monad](using N: NamesAlgebra[S, Alg], diff --git a/semantics/src/main/scala/aqua/semantics/rules/locations/LocationsState.scala b/semantics/src/main/scala/aqua/semantics/rules/locations/LocationsState.scala index dd11b98ed..d2178fe2a 100644 --- a/semantics/src/main/scala/aqua/semantics/rules/locations/LocationsState.scala +++ b/semantics/src/main/scala/aqua/semantics/rules/locations/LocationsState.scala @@ -21,8 +21,9 @@ case class LocationsState[S[_]]( name: String, token: Token[S] ): List[VariableInfo[S]] = { - if (!vars.exists(_.definition.name == name)) - logger.error(s"Unexpected. Cannot add occurrence for $name") + // TODO: this code lasts too long, but we can find errors in it. + // if (!vars.exists(_.definition.name == name)) + // logger.error(s"Unexpected. Cannot add occurrence for $name") vars.updateFirst(_.definition.name == name, v => v.copy(occurrences = token +: v.occurrences)) } diff --git a/utils/logging/src/main/scala/aqua/logging/LogFormatter.scala b/utils/logging/src/main/scala/aqua/logging/LogFormatter.scala index 36c29a623..62cacf1be 100644 --- a/utils/logging/src/main/scala/aqua/logging/LogFormatter.scala +++ b/utils/logging/src/main/scala/aqua/logging/LogFormatter.scala @@ -6,10 +6,10 @@ import scribe.{Level, Logger} object LogFormatter { val formatter: Formatter = - formatter"$date ${string("[")}$levelColored${string("]")} $messages$mdc" + formatter"$date $timeStamp ${string("[")}$levelColored${string("]")} $messages$mdc" val formatterWithFilename: Formatter = - formatter"$date $fileName ${string("[")}$levelColored${string("]")} $messages$mdc" + formatter"$date $timeStamp $fileName ${string("[")}$levelColored${string("]")} $messages$mdc" def initLogger(level: Option[Level]): Logger = { scribe.Logger.root From 711e58f20b1f99defac2e5dd6a7546667de37238 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Wed, 10 Jan 2024 16:27:06 +0700 Subject: [PATCH 02/13] bump --- .../.jvm/src/main/scala/aqua/api/Test.scala | 19 ++------ .../scala/aqua/compiler/CompilerAPI.scala | 47 +++++++++++++++++-- .../aqua/model/inline/ArrowInliner.scala | 5 +- .../inline/raw/CallArrowRawInliner.scala | 1 - .../main/scala/aqua/model/AquaContext.scala | 4 +- .../semantics/expr/func/CallArrowSem.scala | 5 -- 6 files changed, 53 insertions(+), 28 deletions(-) diff --git a/api/api/.jvm/src/main/scala/aqua/api/Test.scala b/api/api/.jvm/src/main/scala/aqua/api/Test.scala index e554ccd82..bf4011037 100644 --- a/api/api/.jvm/src/main/scala/aqua/api/Test.scala +++ b/api/api/.jvm/src/main/scala/aqua/api/Test.scala @@ -1,12 +1,10 @@ package aqua.api -import aqua.api.TargetType.TypeScriptType import aqua.backend.ts.TypeScriptBackend import aqua.compiler.AquaCompiled import aqua.files.FileModuleId import cats.data.Chain -import cats.data.Validated.{Invalid, Valid} import cats.effect.{IO, IOApp} import fs2.io.file.{Files, Path} import fs2.{Stream, text} @@ -17,22 +15,13 @@ object Test extends IOApp.Simple { APICompilation .compilePath( -// "/home/diemust/git/decider/src/aqua/decider/poll.aqua", -// "/home/diemust/git/ha/src/aqua/main.aqua", - "./aqua-src/antithesis.aqua", + "/home/diemust/git/decider/src/aqua/decider/poll.aqua", +// "./aqua-src/antithesis.aqua", Imports.fromMap( Map( "/" -> Map( -// "" -> List( -// "/home/diemust/git/decider/.fluence/aqua", -// "/home/diemust/.fluence/npm/@fluencelabs/aqua-lib/0.9.0/node_modules", -// "/home/diemust/.fluence/npm/@fluencelabs/spell/0.6.0/node_modules", -// "/home/diemust/.fluence/npm/@fluencelabs/registry/0.8.7/node_modules", -// "/home/diemust/.fluence/npm/@fluencelabs/aqua-ipfs/0.5.24/node_modules", -// "/home/diemust/.fluence/npm/@fluencelabs/installation-spell/0.6.0/node_modules" -// ) "" -> List( - "/home/diemust/git/ha/.fluence/aqua", + "/home/diemust/git/decider/.fluence/aqua", "/home/diemust/.fluence/npm/@fluencelabs/aqua-lib/0.9.0/node_modules", "/home/diemust/.fluence/npm/@fluencelabs/spell/0.6.0/node_modules", "/home/diemust/.fluence/npm/@fluencelabs/registry/0.8.7/node_modules", @@ -42,7 +31,7 @@ object Test extends IOApp.Simple { ) ) ), - AquaAPIConfig(logLevel = "info"), + AquaAPIConfig(logLevel = "trace"), TypeScriptBackend(false, "IFluenceClient$$") ).timed .flatMap { case (duration, res) => diff --git a/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala b/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala index b3cf3a759..55656f8f8 100644 --- a/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala +++ b/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala @@ -9,10 +9,10 @@ import aqua.semantics.RawSemantics import aqua.semantics.header.{HeaderHandler, HeaderSem} import cats.data.* +import cats.syntax.applicative.* import cats.syntax.either.* import cats.syntax.flatMap.* import cats.syntax.functor.* -import cats.syntax.applicative.* import cats.syntax.traverse.* import cats.{Comonad, Monad, Monoid, Order} import scribe.Logging @@ -37,9 +37,50 @@ object CompilerAPI extends Logging { _ <- State.set(expCache) } yield AquaProcessed(i, exp) } - .runA(AquaContext.Cache()) + .run(AquaContext.Cache()) + .map { case (cache, a) => + println( + cache.data.toList + .flatMap(_._2.funcs.keys) + .groupBy(identity) + .view + .values + .map(l => (l.headOption, l.size)) + .toList.sortBy(_._2).reverse + ) + println( + cache.data.toList + .flatMap(_._1.parts.map(_._2.name).toList) + .groupBy(identity) + .view + .values + .map(l => (l.headOption, l.size)) + .toList.sortBy(_._2).reverse + ) + println("modules rawcontext: ") + println( + cache.data.toList + .flatMap(_._1.module.toList) + .groupBy(identity) + .view + .values + .map(l => (l.headOption, l.size)) + .toList.sortBy(_._2).reverse + ) + println("modules aquacontext: ") + println( + cache.data.toList + .flatMap(_._2.module.toList) + .groupBy(identity) + .view + .values + .map(l => (l.headOption, l.size)) + .toList.sortBy(_._2).reverse + ) + a + } // Convert result List to Chain - .map(Chain.fromSeq) + .map(a => Chain.fromSeq(a)) .value } 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 418ebe3ac..7b72de19b 100644 --- a/model/inline/src/main/scala/aqua/model/inline/ArrowInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/ArrowInliner.scala @@ -88,9 +88,10 @@ object ArrowInliner extends Logging { call: CallModel, outsideDeclaredStreams: Set[String] ): State[S, InlineResult] = for { - _ <- State.pure(logger.trace(s"before handle for ${fn.funcName}")) + +// _ <- State.pure(logger.trace(s"before handle for ${fn.funcName}")) callableFuncBodyNoTopology <- TagInliner.handleTree(fn.body) - _ <- State.pure(logger.trace(s"TagInliner.handleTree finish for ${fn.funcName}")) +// _ <- State.pure(logger.trace(s"TagInliner.handleTree finish for ${fn.funcName}")) callableFuncBody = fn.capturedTopology .fold(SeqModel)(ApplyTopologyModel.apply) 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 8b5d153c8..c7a43b462 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 @@ -59,7 +59,6 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { arrows <- Arrows[S].arrows exports <- Exports[S].exports lastArrow <- Exports[S].getLastVarName(funcName) - _ = println("lastArrow: " + lastArrow) arrow = arrows .get(funcName) .orElse( diff --git a/model/src/main/scala/aqua/model/AquaContext.scala b/model/src/main/scala/aqua/model/AquaContext.scala index aad235bc9..ebb9995b8 100644 --- a/model/src/main/scala/aqua/model/AquaContext.scala +++ b/model/src/main/scala/aqua/model/AquaContext.scala @@ -113,7 +113,7 @@ case class AquaContext( object AquaContext extends Logging { - case class Cache(private val data: Chain[(RawContext, AquaContext)] = Chain.empty) { + case class Cache(data: Chain[(RawContext, AquaContext)] = Chain.empty) { lazy val size: Long = data.size def get(ctx: RawContext): Option[AquaContext] = @@ -255,7 +255,7 @@ object AquaContext extends Logging { (newCtx, newCache.updated(rawContext, newCtx)) } { ac => - logger.trace("Got from cache") +// logger.trace("Got from cache") ac -> cache } diff --git a/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala b/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala index 016b09be4..a99ca538b 100644 --- a/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala +++ b/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala @@ -28,12 +28,7 @@ class CallArrowSem[S[_]](val expr: CallArrowExpr[S]) extends AnyVal { N: NamesAlgebra[S, Alg], T: TypesAlgebra[S, Alg] ): Alg[List[Call.Export]] = { - println("call: " + expr.callArrow) - println("variables: " + variables) - println("codomain: " + codomain) (variables zip codomain.toList).traverse { case (v, t) => - println("v: " + v) - println("t: " + t) N.read(v, mustBeDefined = false).flatMap { case Some(stream @ StreamType(st)) => T.ensureTypeMatches(v, st, t).as(Call.Export(v.value, stream)) From f3137f4e4fbe431b057ac44355b806ea0c5301f0 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Wed, 17 Jan 2024 15:35:57 +0700 Subject: [PATCH 03/13] optimize Mangler --- .../scala/aqua/compiler/CompilerAPI.scala | 43 ------------- .../aqua/model/inline/ArrowInliner.scala | 3 - .../model/inline/state/InliningState.scala | 2 +- .../aqua/model/inline/state/Mangler.scala | 60 ++++++++----------- .../model/inline/RawValueInlinerSpec.scala | 38 ++++++------ .../src/main/scala/aqua/raw/RawContext.scala | 1 - .../main/scala/aqua/model/AquaContext.scala | 24 ++++---- .../aqua/model/transform/Transform.scala | 4 -- .../main/scala/aqua/semantics/Semantics.scala | 3 +- 9 files changed, 57 insertions(+), 121 deletions(-) diff --git a/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala b/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala index 55656f8f8..11b390dde 100644 --- a/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala +++ b/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala @@ -24,8 +24,6 @@ object CompilerAPI extends Logging { ): Chain[AquaProcessed[I]] = { logger.trace("linking finished") - println("files with context: " + filesWithContext.keys) - filesWithContext.toList // Process all contexts maintaining Cache .traverse { case (i, rawContext) => @@ -38,47 +36,6 @@ object CompilerAPI extends Logging { } yield AquaProcessed(i, exp) } .run(AquaContext.Cache()) - .map { case (cache, a) => - println( - cache.data.toList - .flatMap(_._2.funcs.keys) - .groupBy(identity) - .view - .values - .map(l => (l.headOption, l.size)) - .toList.sortBy(_._2).reverse - ) - println( - cache.data.toList - .flatMap(_._1.parts.map(_._2.name).toList) - .groupBy(identity) - .view - .values - .map(l => (l.headOption, l.size)) - .toList.sortBy(_._2).reverse - ) - println("modules rawcontext: ") - println( - cache.data.toList - .flatMap(_._1.module.toList) - .groupBy(identity) - .view - .values - .map(l => (l.headOption, l.size)) - .toList.sortBy(_._2).reverse - ) - println("modules aquacontext: ") - println( - cache.data.toList - .flatMap(_._2.module.toList) - .groupBy(identity) - .view - .values - .map(l => (l.headOption, l.size)) - .toList.sortBy(_._2).reverse - ) - a - } // Convert result List to Chain .map(a => Chain.fromSeq(a)) .value 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 7b72de19b..8288fae66 100644 --- a/model/inline/src/main/scala/aqua/model/inline/ArrowInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/ArrowInliner.scala @@ -88,10 +88,7 @@ object ArrowInliner extends Logging { call: CallModel, outsideDeclaredStreams: Set[String] ): State[S, InlineResult] = for { - -// _ <- State.pure(logger.trace(s"before handle for ${fn.funcName}")) callableFuncBodyNoTopology <- TagInliner.handleTree(fn.body) -// _ <- State.pure(logger.trace(s"TagInliner.handleTree finish for ${fn.funcName}")) callableFuncBody = fn.capturedTopology .fold(SeqModel)(ApplyTopologyModel.apply) 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 e7c452476..3219b9cdd 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 @@ -23,7 +23,7 @@ import scribe.Logging * for [[Counter]] */ case class InliningState( - noNames: Set[String] = Set.empty, + noNames: ManglerState = ManglerState(), resolvedExports: Map[String, ValueModel] = Map.empty, resolvedArrows: Map[String, FuncArrow] = Map.empty, instructionCounter: Int = 0 diff --git a/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala b/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala index 15a73edb2..2c94faede 100644 --- a/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala +++ b/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala @@ -4,62 +4,50 @@ import cats.data.State trait Mangler[S] { self => - def getForbiddenNames: State[S, Set[String]] - - def findNewNames(introduce: Set[String]): State[S, Map[String, String]] - - def findNewName(introduce: String): State[S, String] = - findNewNames(Set(introduce)).map(_.getOrElse(introduce, introduce)) + def getForbiddenNames: State[S, ManglerState] def findAndForbidName(introduce: String): State[S, String] = - for { - n <- findNewName(introduce) - _ <- forbid(Set(n)) - } yield n + findAndForbidNames(Set(introduce)).map(_.getOrElse(introduce, introduce)) - def findAndForbidNames(introduce: Set[String]): State[S, Map[String, String]] = - for { - n <- findNewNames(introduce) - _ <- forbid(introduce ++ n.values.toSet) - } yield n + def findAndForbidNames(introduce: Set[String]): State[S, Map[String, String]] def forbid(names: Set[String]): State[S, Unit] - def forbidName(name: String): State[S, Unit] = - forbid(Set(name)) - def transformS[R](f: R => S, g: (R, S) => R): Mangler[R] = new Mangler[R] { - val getForbiddenNames: State[R, Set[String]] = + val getForbiddenNames: State[R, ManglerState] = self.getForbiddenNames.transformS(f, g) - def findNewNames(introduce: Set[String]): State[R, Map[String, String]] = - self.findNewNames(introduce).transformS(f, g) - def forbid(names: Set[String]): State[R, Unit] = self.forbid(names).transformS(f, g) + + def findAndForbidNames(introduce: Set[String]): State[R, Map[String, String]] = + self.findAndForbidNames(introduce).transformS(f, g) } } +case class ManglerState(lastNumbers: Map[String, Int] = Map.empty) + object Mangler { def apply[S](implicit mangler: Mangler[S]): Mangler[S] = mangler - implicit object Simple extends Mangler[Set[String]] { - val getForbiddenNames: State[Set[String], Set[String]] = State.get - - def findNewNames(introduce: Set[String]): State[Set[String], Map[String, String]] = - getForbiddenNames.map(forbidden => - (forbidden intersect introduce).foldLeft(Map.empty[String, String]) { case (acc, name) => - acc + (name -> LazyList - .from(0) - .map(name + "-" + _) - .dropWhile(n => forbidden(n) || introduce(n) || acc.contains(n)) - .head) - } + implicit object Simple extends Mangler[ManglerState] { + val getForbiddenNames: State[ManglerState, ManglerState] = State.get + + def findAndForbidNames(introduce: Set[String]): State[ManglerState, Map[String, String]] = + getForbiddenNames.flatMap(forbidden => + val (newLastNumbers, newNames) = + introduce.foldLeft((forbidden.lastNumbers, Map.empty[String, String])) { + case ((lastNumbers, acc), name) => + val (newName, newNumber) = + lastNumbers.get(name).map(n => (s"$name-$n", n + 1)).getOrElse((name, 0)) + (lastNumbers + (name -> newNumber), acc + (name -> newName)) + } + State.modify[ManglerState](st => st.copy(lastNumbers = newLastNumbers)).map(_ => newNames) ) - def forbid(names: Set[String]): State[Set[String], Unit] = - State.modify(_ ++ names) + def forbid(names: Set[String]): State[ManglerState, Unit] = + State.modify(st => st.copy(lastNumbers = st.lastNumbers ++ names.map(_ -> 0))) } } diff --git a/model/inline/src/test/scala/aqua/model/inline/RawValueInlinerSpec.scala b/model/inline/src/test/scala/aqua/model/inline/RawValueInlinerSpec.scala index 8248986ea..d34081c6b 100644 --- a/model/inline/src/test/scala/aqua/model/inline/RawValueInlinerSpec.scala +++ b/model/inline/src/test/scala/aqua/model/inline/RawValueInlinerSpec.scala @@ -1,28 +1,27 @@ package aqua.model.inline -import aqua.model.inline.raw.{ApplyPropertiesRawInliner, StreamGateInliner} import aqua.model.* -import aqua.model.inline.state.InliningState -import aqua.raw.value.{ApplyPropertyRaw, FunctorRaw, IntoIndexRaw, LiteralRaw, VarRaw} -import aqua.types.* +import aqua.model.inline.raw.StreamGateInliner +import aqua.model.inline.state.{InliningState, ManglerState} import aqua.raw.value.* +import aqua.types.* import cats.Eval -import cats.data.NonEmptyMap -import cats.data.Chain -import cats.syntax.show.* -import cats.syntax.foldable.* +import cats.data.{Chain, NonEmptyMap} import cats.free.Cofree -import scala.collection.immutable.SortedMap -import scala.math +import cats.syntax.foldable.* +import org.scalatest.Inside import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers -import org.scalatest.Inside +import scala.collection.immutable.SortedMap +import scala.math class RawValueInlinerSpec extends AnyFlatSpec with Matchers with Inside { import RawValueInliner.valueToModel + def toMangler(noNames: Set[String]) = ManglerState(noNames.map(_ -> 0).toMap) + def join(stream: VarModel, size: ValueModel) = stream match { case VarModel( @@ -188,7 +187,7 @@ class RawValueInlinerSpec extends AnyFlatSpec with Matchers with Inside { "raw value inliner" should "desugarize a single non-recursive raw value" in { // x[y] valueToModel[InliningState](`raw x[y]`) - .runA(InliningState(noNames = Set("x", "y"))) + .runA(InliningState(noNames = toMangler(Set("x", "y")))) .value shouldBe ( VarModel( "x", @@ -200,7 +199,6 @@ class RawValueInlinerSpec extends AnyFlatSpec with Matchers with Inside { // TODO: unignore and fix after stream restrictions will be implemented ignore /*"raw value inliner"*/ should "unfold an IntoField PropertyModel" in { - import aqua.model.inline.state.Mangler.Simple // a.field1.field2 valueToModel[InliningState](`raw res.c`) .runA( @@ -222,7 +220,7 @@ class RawValueInlinerSpec extends AnyFlatSpec with Matchers with Inside { val (resVal, resTree) = valueToModel[InliningState]( `raw x[ys[0]]` ) - .runA(InliningState(noNames = Set("x", "ys"))) + .runA(InliningState(noNames = toMangler(Set("x", "ys")))) .value resVal should be( @@ -250,7 +248,9 @@ class RawValueInlinerSpec extends AnyFlatSpec with Matchers with Inside { it should "desugarize properties with functors x[ys[ys.length]][2] and make proper flattener tags" in { val (resVal, resTree) = valueToModel[InliningState]( `x[xs[ys.length]][xss[yss.length]]` - ).runA(InliningState(noNames = Set("x", "ys", "xs", "yss", "xss"))).value + ).runA( + InliningState(noNames = toMangler(Set("x", "ys", "xs", "yss", "xss"))) + ).value resVal should be( VarModel( @@ -325,7 +325,7 @@ class RawValueInlinerSpec extends AnyFlatSpec with Matchers with Inside { val (resVal, resTree) = valueToModel[InliningState]( `raw x[ys[0]][ys[1]]` ) - .runA(InliningState(noNames = Set("x", "ys"))) + .runA(InliningState(noNames = toMangler(Set("x", "ys")))) .value resVal should be( @@ -371,7 +371,7 @@ class RawValueInlinerSpec extends AnyFlatSpec with Matchers with Inside { IntoIndexRaw(idxRaw, ScalarType.string) ) - val initState = InliningState(noNames = Set("x", "ys")) + val initState = InliningState(noNames = toMangler(Set("x", "ys"))) // Here retrieve how size is inlined val (afterSizeState, (sizeModel, sizeTree)) = @@ -420,7 +420,7 @@ class RawValueInlinerSpec extends AnyFlatSpec with Matchers with Inside { ) val (resVal, resTree) = valueToModel[InliningState](streamWithProps) - .runA(InliningState(noNames = Set("x", "ys"))) + .runA(InliningState(noNames = toMangler(Set("x", "ys")))) .value } @@ -428,7 +428,7 @@ class RawValueInlinerSpec extends AnyFlatSpec with Matchers with Inside { val (resVal, resTree) = valueToModel[InliningState]( `raw x[zs[ys[0]]][ys[1]]` ) - .runA(InliningState(noNames = Set("x", "ys", "zs"))) + .runA(InliningState(noNames = toMangler(Set("x", "ys", "zs")))) .value // This is x[zs-0][ys-0] diff --git a/model/raw/src/main/scala/aqua/raw/RawContext.scala b/model/raw/src/main/scala/aqua/raw/RawContext.scala index 9f26d0286..6f4a5f2b0 100644 --- a/model/raw/src/main/scala/aqua/raw/RawContext.scala +++ b/model/raw/src/main/scala/aqua/raw/RawContext.scala @@ -10,7 +10,6 @@ import cats.data.Chain import cats.data.NonEmptyMap import cats.syntax.monoid.* import cats.syntax.option.* - import scala.collection.immutable.SortedMap /** diff --git a/model/src/main/scala/aqua/model/AquaContext.scala b/model/src/main/scala/aqua/model/AquaContext.scala index ebb9995b8..9225c9700 100644 --- a/model/src/main/scala/aqua/model/AquaContext.scala +++ b/model/src/main/scala/aqua/model/AquaContext.scala @@ -156,10 +156,10 @@ object AquaContext extends Logging { // Convert RawContext into AquaContext, with exports handled def exportsFromRaw(rawContext: RawContext, cache: Cache): (AquaContext, Cache) = { -// logger.trace(s"ExportsFromRaw ${rawContext.module}") + logger.trace(s"ExportsFromRaw ${rawContext.module}") val (ctx, newCache) = fromRawContext(rawContext, cache) -// logger.trace("raw: " + rawContext) -// logger.trace("ctx: " + ctx) + logger.trace("raw: " + rawContext) + logger.trace("ctx: " + ctx) rawContext.exports .foldLeft( @@ -183,7 +183,7 @@ object AquaContext extends Logging { val (newCtx, newCache) = rawContext.parts .foldLeft[(AquaContext, Cache)] { // Laziness unefficiency happens here -// logger.trace(s"raw: ${rawContext.module}") + logger.trace(s"raw: ${rawContext.module}") val (i, c) = rawContext.init .map(fromRawContext(_, cache)) @@ -199,11 +199,11 @@ object AquaContext extends Logging { (i |+| blank.copy(abilities = abs)) -> absCache } { case ((ctx, ctxCache), (partContext, c: ConstantRaw)) => -// logger.trace("Adding constant " + c.name) + logger.trace("Adding constant " + c.name) // Just saving a constant // Actually this should have no effect, as constants are resolved by semantics val (pctx, pcache) = fromRawContext(partContext, ctxCache) -// logger.trace("Got " + c.name + " from raw") + logger.trace("Got " + c.name + " from raw") val add = blank .copy(values = @@ -215,12 +215,12 @@ object AquaContext extends Logging { case ((ctx, ctxCache), (partContext, func: FuncRaw)) => // To add a function, we have to know its scope -// logger.trace("Adding func " + func.name) + logger.trace("Adding func " + func.name) val (pctx, pcache) = fromRawContext(partContext, ctxCache) -// logger.trace("Got " + func.name + " from raw") + logger.trace("Got " + func.name + " from raw") val fr = FuncArrow.fromRaw(func, pctx.allFuncs, pctx.allValues, None) -// logger.trace("Captured recursively for " + func.name) + logger.trace("Captured recursively for " + func.name) val add = blank.copy(funcs = Map(func.name -> fr)) (ctx |+| add, pcache) @@ -232,9 +232,9 @@ object AquaContext extends Logging { case ((ctx, ctxCache), (partContext, m: ServiceRaw)) => // To add a service, we need to resolve its ID, if any -// logger.trace("Adding service " + m.name) + logger.trace("Adding service " + m.name) val (pctx, pcache) = fromRawContext(partContext, ctxCache) -// logger.trace("Got " + m.name + " from raw") + logger.trace("Got " + m.name + " from raw") val id = m.defaultId .map(ValueModel.fromRaw) .map(_.resolveWith(pctx.allValues)) @@ -255,7 +255,7 @@ object AquaContext extends Logging { (newCtx, newCache.updated(rawContext, newCtx)) } { ac => -// logger.trace("Got from cache") + logger.trace("Got from cache") ac -> cache } diff --git a/model/transform/src/main/scala/aqua/model/transform/Transform.scala b/model/transform/src/main/scala/aqua/model/transform/Transform.scala index d06df33c6..760be8cc4 100644 --- a/model/transform/src/main/scala/aqua/model/transform/Transform.scala +++ b/model/transform/src/main/scala/aqua/model/transform/Transform.scala @@ -117,7 +117,6 @@ object Transform extends Logging { ) for { - _ <- Eval.later { logger.trace("start transforming...")} // Pre transform and inline the function model <- funcToModelTree(func, preTransformer) // Post transform the function. @@ -126,12 +125,9 @@ object Transform extends Logging { // Topology module needs this `on` // as a starting point. initModel = initCallable.onInitPeer.wrap(model) - _ <- Eval.later { logger.trace("end funcToModel...")} tracingModel <- tracing(initModel) - _ <- Eval.later { logger.trace("end tracing...")} // Resolve topology resolved <- Topology.resolve(tracingModel) - _ <- Eval.later { logger.trace("end topology...")} // Clear the tree result = clear(resolved) } yield FuncRes( diff --git a/semantics/src/main/scala/aqua/semantics/Semantics.scala b/semantics/src/main/scala/aqua/semantics/Semantics.scala index bf76ea63f..9eebb9aa9 100644 --- a/semantics/src/main/scala/aqua/semantics/Semantics.scala +++ b/semantics/src/main/scala/aqua/semantics/Semantics.scala @@ -1,9 +1,8 @@ package aqua.semantics import aqua.parser.Ast -import aqua.semantics.SemanticError -import cats.data.{Chain, EitherNec, EitherT, NonEmptyChain, ValidatedNec, Writer} +import cats.data.{Chain, EitherT, NonEmptyChain, Writer} trait Semantics[S[_], C] { From e34c155ef504f1709831809dbbbff23e069a6b10 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Wed, 17 Jan 2024 15:46:44 +0700 Subject: [PATCH 04/13] fix compilation --- compiler/src/main/scala/aqua/compiler/CompilerAPI.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala b/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala index 11b390dde..19b378249 100644 --- a/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala +++ b/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala @@ -35,9 +35,9 @@ object CompilerAPI extends Logging { _ <- State.set(expCache) } yield AquaProcessed(i, exp) } - .run(AquaContext.Cache()) + .runA(AquaContext.Cache()) // Convert result List to Chain - .map(a => Chain.fromSeq(a)) + .map(Chain.fromSeq) .value } From e925d3dd1df60985d6fcc67e4bef97f6f5b2004b Mon Sep 17 00:00:00 2001 From: DieMyst Date: Wed, 17 Jan 2024 17:20:33 +0700 Subject: [PATCH 05/13] fix tests --- .../scala/aqua/model/inline/state/Mangler.scala | 9 +++++++-- .../rules/mangler/ManglerInterpreter.scala | 14 +++++++------- .../semantics/rules/mangler/ManglerState.scala | 11 ++--------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala b/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala index 2c94faede..ed1d5699c 100644 --- a/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala +++ b/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala @@ -32,6 +32,9 @@ case class ManglerState(lastNumbers: Map[String, Int] = Map.empty) object Mangler { def apply[S](implicit mangler: Mangler[S]): Mangler[S] = mangler + private def genName(name: String, n: Int) = + s"$name-$n" + implicit object Simple extends Mangler[ManglerState] { val getForbiddenNames: State[ManglerState, ManglerState] = State.get @@ -41,13 +44,15 @@ object Mangler { introduce.foldLeft((forbidden.lastNumbers, Map.empty[String, String])) { case ((lastNumbers, acc), name) => val (newName, newNumber) = - lastNumbers.get(name).map(n => (s"$name-$n", n + 1)).getOrElse((name, 0)) + lastNumbers.get(name).map(n => (genName(name, n), n + 1)).getOrElse((name, 0)) (lastNumbers + (name -> newNumber), acc + (name -> newName)) } State.modify[ManglerState](st => st.copy(lastNumbers = newLastNumbers)).map(_ => newNames) ) def forbid(names: Set[String]): State[ManglerState, Unit] = - State.modify(st => st.copy(lastNumbers = st.lastNumbers ++ names.map(_ -> 0))) + State.modify(st => + st.copy(lastNumbers = st.lastNumbers ++ names.map(n => n -> st.lastNumbers.getOrElse(n, 0))) + ) } } diff --git a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala b/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala index 0eff5d809..3fd47c130 100644 --- a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala +++ b/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala @@ -2,21 +2,21 @@ package aqua.semantics.rules.mangler import cats.data.State import monocle.Lens -import monocle.macros.GenLens class ManglerInterpreter[X](using lens: Lens[X, ManglerState] ) extends ManglerAlgebra[State[X, *]] { + def genName(name: String, n: Int) = s"$name-$n" + override def rename(name: String): State[X, String] = for { s <- get - newName = LazyList - .from(0) - .map(i => s"$name-$i") - .dropWhile(s.isForbidden) - .head - _ <- modify(_.forbid(newName)) + newNameAndNum = s.forbidden.get(name).map(n => genName(name, n + 1) -> (n + 1)).getOrElse(genName(name, 0) -> 0) + (newName, newNum) = newNameAndNum + _ = println("newName = " + newName) + _ = println("newNum = " + newNum) + _ <- modify(st => st.copy(forbidden = st.forbidden + (name -> newNum))) } yield newName private lazy val get: State[X, ManglerState] = diff --git a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerState.scala b/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerState.scala index 7d7f5dca8..a618a1931 100644 --- a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerState.scala +++ b/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerState.scala @@ -3,15 +3,8 @@ package aqua.semantics.rules.mangler import cats.kernel.Monoid final case class ManglerState( - forbidden: Set[String] = Set.empty -) { - - def isForbidden(name: String): Boolean = - forbidden.contains(name) - - def forbid(name: String): ManglerState = - copy(forbidden = forbidden + name) -} + forbidden: Map[String, Int] = Map.empty +) object ManglerState { From a64ad709690a47b71d448792626bf115793521a6 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Wed, 17 Jan 2024 17:35:27 +0700 Subject: [PATCH 06/13] fix tests --- .../inline/src/main/scala/aqua/model/inline/state/Mangler.scala | 2 +- .../scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala b/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala index ed1d5699c..c20f1df18 100644 --- a/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala +++ b/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala @@ -52,7 +52,7 @@ object Mangler { def forbid(names: Set[String]): State[ManglerState, Unit] = State.modify(st => - st.copy(lastNumbers = st.lastNumbers ++ names.map(n => n -> st.lastNumbers.getOrElse(n, 0))) + st.copy(lastNumbers = st.lastNumbers ++ names.map(n => n -> st.lastNumbers.getOrElse(n, -1))) ) } } diff --git a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala b/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala index 3fd47c130..b63d20dc9 100644 --- a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala +++ b/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala @@ -14,8 +14,6 @@ class ManglerInterpreter[X](using s <- get newNameAndNum = s.forbidden.get(name).map(n => genName(name, n + 1) -> (n + 1)).getOrElse(genName(name, 0) -> 0) (newName, newNum) = newNameAndNum - _ = println("newName = " + newName) - _ = println("newNum = " + newNum) _ <- modify(st => st.copy(forbidden = st.forbidden + (name -> newNum))) } yield newName From a9024467d0f88c3a99e485121e002974f26320df Mon Sep 17 00:00:00 2001 From: DieMyst Date: Wed, 17 Jan 2024 17:44:26 +0700 Subject: [PATCH 07/13] revert --- .../scala/aqua/compiler/CompilerAPI.scala | 6 ----- .../src/main/scala/aqua/linker/Linker.scala | 4 ++-- .../aqua/model/inline/RawValueInliner.scala | 12 +++++----- .../model/transform/topology/PathFinder.scala | 24 +++++++++---------- .../model/transform/topology/Topology.scala | 16 ++++++------- 5 files changed, 28 insertions(+), 34 deletions(-) diff --git a/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala b/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala index 19b378249..c665aafb5 100644 --- a/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala +++ b/compiler/src/main/scala/aqua/compiler/CompilerAPI.scala @@ -73,19 +73,14 @@ object CompilerAPI extends Logging { val compiler = getAquaCompiler[F, E, I, S](config) for { - _ <- logger.trace("Start compilation").pure[F] compiledRaw <- compiler.compileRaw(sources, parser) - _ <- logger.trace("Compile raw ended").pure[F] compiledV = compiledRaw.map(toAquaProcessed) - _ <- logger.trace("Aqua processed ended").pure[F] _ <- airValidator.init() result <- compiledV.flatTraverse { compiled => compiled.traverse { ap => logger.trace("generating output...") val res = backend.transform(ap.context) - logger.trace("end transforming...") val generated = backend.generate(res) - logger.trace("end generating...") val air = generated.toList.flatMap(_.air) val compiled = AquaCompiled( sourceId = ap.id, @@ -103,7 +98,6 @@ object CompilerAPI extends Logging { ) }.map(_.sequence.toEither.toEitherT) } - _ <- logger.trace("Writing result ended").pure[F] } yield result } diff --git a/linker/src/main/scala/aqua/linker/Linker.scala b/linker/src/main/scala/aqua/linker/Linker.scala index e7e2d91bf..8669e201b 100644 --- a/linker/src/main/scala/aqua/linker/Linker.scala +++ b/linker/src/main/scala/aqua/linker/Linker.scala @@ -106,9 +106,9 @@ object Linker extends Logging { logger.debug(s"${m.id} dependsOn $importKeys") val deps: T => T = importKeys.map(acc).foldLeft(identity[T]) { case (fAcc, f) => -// logger.debug("COMBINING ONE TIME ") + logger.debug("COMBINING ONE TIME ") t => { -// logger.debug(s"call combine $t") + logger.debug(s"call combine $t") fAcc(t) |+| f(t) } } 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 a673e9237..365c5bfa0 100644 --- a/model/inline/src/main/scala/aqua/model/inline/RawValueInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/RawValueInliner.scala @@ -28,7 +28,7 @@ object RawValueInliner extends Logging { propertiesAllowed: Boolean = true ): State[S, (ValueModel, Inline)] = for { 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 { case VarRaw(name, t) => for { @@ -83,20 +83,20 @@ object RawValueInliner extends Logging { for { vmp <- unfoldF (vm, map) = vmp -// _ = logger.trace("MOD " + vm) + _ = logger.trace("MOD " + vm) dc <- Exports[S].exports -// _ = logger.trace("DEC " + dc) + _ = logger.trace("DEC " + dc) ops <- inlineToTree(map) -// _ = logger.trace("desugarized ops: " + ops) -// _ = logger.trace("map was: " + map) + _ = logger.trace("desugarized ops: " + ops) + _ = logger.trace("map was: " + map) } yield vm -> parDesugarPrefix(ops.filterNot(_ == EmptyModel.leaf)) def valueToModel[S: Mangler: Exports: Arrows]( value: ValueRaw, propertiesAllowed: Boolean = true ): State[S, (ValueModel, Option[OpModel.Tree])] = for { -// _ <- StateT.liftF(Eval.later(logger.trace("RAW " + value))) + _ <- StateT.liftF(Eval.later(logger.trace("RAW " + value))) model <- toModel(unfold(value, propertiesAllowed)) } yield model diff --git a/model/transform/src/main/scala/aqua/model/transform/topology/PathFinder.scala b/model/transform/src/main/scala/aqua/model/transform/topology/PathFinder.scala index fca293173..390a3a4ca 100644 --- a/model/transform/src/main/scala/aqua/model/transform/topology/PathFinder.scala +++ b/model/transform/src/main/scala/aqua/model/transform/topology/PathFinder.scala @@ -56,8 +56,8 @@ object PathFinder extends Logging { fromPeer: Option[ValueModel], toPeer: Option[ValueModel] ): Chain[ValueModel] = { -// logger.trace(s"FROM ON: $fromOn") -// logger.trace(s"TO ON: $toOn") + logger.trace(s"FROM ON: $fromOn") + logger.trace(s"TO ON: $toOn") val (from, to) = skipCommonPrefix(fromOn, toOn) val fromFix = @@ -67,20 +67,20 @@ object PathFinder extends Logging { if (to.isEmpty && fromPeer != toPeer) Chain.fromOption(toOn.lastOption) else to -// logger.trace("FIND PATH FROM | " + fromFix) -// logger.trace(" TO | " + toFix) + logger.trace("FIND PATH FROM | " + fromFix) + logger.trace(" TO | " + toFix) val fromTo = fromFix.reverse.flatMap(_.via.reverse) ++ toFix.flatMap(_.via) -// logger.trace(s"FROM TO: $fromTo") + logger.trace(s"FROM TO: $fromTo") val toOptimize = Chain.fromOption(fromPeer) ++ fromTo ++ Chain.fromOption(toPeer) val optimized = optimizePath(toOptimize, fromPeer, toPeer) -// logger.trace( -// s"FROM PEER '${fromPeer.map(_.toString).getOrElse("None")}' TO PEER '${toPeer.map(_.toString).getOrElse("None")}'" -// ) -// logger.trace(" Optimized: " + optimized) + logger.trace( + s"FROM PEER '${fromPeer.map(_.toString).getOrElse("None")}' TO PEER '${toPeer.map(_.toString).getOrElse("None")}'" + ) + logger.trace(" Optimized: " + optimized) optimized } @@ -108,9 +108,9 @@ object PathFinder extends Logging { case (acc, p) => acc :+ p } -// logger.trace(s"PEER IDS: $optimized") -// logger.trace(s"FROM PEER: $fromPeer") -// logger.trace(s"TO PEER: $toPeer") + logger.trace(s"PEER IDS: $optimized") + logger.trace(s"FROM PEER: $fromPeer") + logger.trace(s"TO PEER: $toPeer") val skipFrom = optimized.uncons match { case Some((head, tail)) if fromPeer.contains(head) => tail diff --git a/model/transform/src/main/scala/aqua/model/transform/topology/Topology.scala b/model/transform/src/main/scala/aqua/model/transform/topology/Topology.scala index 773ccae41..7296872d7 100644 --- a/model/transform/src/main/scala/aqua/model/transform/topology/Topology.scala +++ b/model/transform/src/main/scala/aqua/model/transform/topology/Topology.scala @@ -61,10 +61,10 @@ case class Topology private ( .flatMap(tops => cursor.op match { case CaptureTopologyModel(name) => -// logger.trace(s"Capturing topology `$name`") + logger.trace(s"Capturing topology `$name`") Eval.now(tops + (name -> this)) case x => -// logger.trace(s"Skip $x") + logger.trace(s"Skip $x") cursor.toLastChild .traverse(_.topology.capturedTopologies) .map(_.getOrElse(Map.empty) ++ tops) @@ -327,16 +327,16 @@ object Topology extends Logging { } val resolvedCofree = cursor.traverse(wrap) { rc => -// logger.debug(s"<:> $rc") + logger.debug(s"<:> $rc") val currI = nextI val resolved = MakeRes .resolve(rc.topology.currentPeerId, currI) .lift .apply(rc.op) -// logger.trace("Resolved: " + resolved) + logger.trace("Resolved: " + resolved) -// if (debug) printDebugInfo(rc, currI) + if (debug) printDebugInfo(rc, currI) val chainZipperEv = resolved.traverse(tree => ( @@ -350,7 +350,7 @@ object Topology extends Logging { OptionT(chainZipperEv) } -// logger.trace("Resolved Cofree: " + resolvedCofree.value.map(_.forceAll)) + logger.trace("Resolved Cofree: " + resolvedCofree.value.map(_.forceAll)) resolvedCofree.map(NonEmptyChain.fromChain(_).map(_.uncons)).map { case None => @@ -416,12 +416,12 @@ object Topology extends Logging { tree: ResolvedOp.Tree ): Eval[Unit] = Eval.later { - /*if (cz.next.nonEmpty || cz.prev.nonEmpty) { + if (cz.next.nonEmpty || cz.prev.nonEmpty) { logger.debug(s"Resolved $rc -> $tree") if (cz.prev.nonEmpty) logger.trace("From prev: " + cz.prev.map(_.head).toList.mkString(" -> ")) if (cz.next.nonEmpty) logger.trace("To next: " + cz.next.map(_.head).toList.mkString(" -> ")) - } else logger.debug(s"EMPTY $rc -> $tree")*/ + } else logger.debug(s"EMPTY $rc -> $tree") } } From 8a5b9afc2eb170fb59d0220d40ee709d2e443bc6 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Fri, 19 Jan 2024 13:56:35 +0700 Subject: [PATCH 08/13] refactoring algorithm, tests --- .../.jvm/src/main/scala/aqua/api/Test.scala | 6 +- aqua-src/antithesis.aqua | 63 ++++------ build.sbt | 15 ++- .../scala/aqua/model/inline/TagInliner.scala | 2 +- .../model/inline/state/InliningState.scala | 1 + .../aqua/model/inline/state/Mangler.scala | 20 +--- .../scala/aqua/model/inline/ManglerSpec.scala | 109 ++++++++++++++++++ .../scala/aqua/semantics/CompilerState.scala | 2 +- .../semantics/expr/func/ServiceIdSem.scala | 4 +- .../rules/mangler/ManglerInterpreter.scala | 12 +- .../rules/mangler/ManglerState.scala | 17 --- .../scala/aqua/mangler/ManglerState.scala | 66 +++++++++++ 12 files changed, 230 insertions(+), 87 deletions(-) create mode 100644 model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala delete mode 100644 semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerState.scala create mode 100644 utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala diff --git a/api/api/.jvm/src/main/scala/aqua/api/Test.scala b/api/api/.jvm/src/main/scala/aqua/api/Test.scala index bf4011037..edc6fcc75 100644 --- a/api/api/.jvm/src/main/scala/aqua/api/Test.scala +++ b/api/api/.jvm/src/main/scala/aqua/api/Test.scala @@ -15,8 +15,8 @@ object Test extends IOApp.Simple { APICompilation .compilePath( - "/home/diemust/git/decider/src/aqua/decider/poll.aqua", -// "./aqua-src/antithesis.aqua", +// "/home/diemust/git/decider/src/aqua/decider/poll.aqua", + "./aqua-src/antithesis.aqua", Imports.fromMap( Map( "/" -> Map( @@ -31,7 +31,7 @@ object Test extends IOApp.Simple { ) ) ), - AquaAPIConfig(logLevel = "trace"), + AquaAPIConfig(logLevel = "info"), TypeScriptBackend(false, "IFluenceClient$$") ).timed .flatMap { case (duration, res) => diff --git a/aqua-src/antithesis.aqua b/aqua-src/antithesis.aqua index eb20c0818..446f57b99 100644 --- a/aqua-src/antithesis.aqua +++ b/aqua-src/antithesis.aqua @@ -1,48 +1,33 @@ aqua M -export haveFun +export returnSrvAsAbility -data Worker: - host_id: string - worker_id: string +ability MyAb: + call() -> string -ability Promise: - yield: -> () - -- Cannot make empty failed as (never) or smth like that without introducing a coordinator - --failed: -> () +service MySrv("default-id"): + call() -> string -service Dummy("d"): - greeting(s: string) -> string +func mySrvDefault() -> MyAb: + <- MySrv -ability Job: - run() +func mySrvResolved() -> MyAb: + MySrv "resolved-id" + <- MySrv -ability WorkerJob: - runOnSingleWorker(worker: Worker) -> Job +func mySrvThird() -> MyAb: + MySrv "third-id" + <- MySrv -func done(): - a = "need some body!" - -- I'm done +func useMyAb{MyAb}() -> string: + <- MyAb.call() -func done_promise() -> Promise: - <- Promise(yield = done) - -func disjoint_run{WorkerJob}() -> Job: - workers: *Worker - - run = func (): - job2 <- WorkerJob.runOnSingleWorker() - - <- Job(run = run) - -func haveFun(): - job2 = () -> Job: - run2 = (): - Dummy.greeting("hell!") - - <- Job(run = run2) - - worker_job = WorkerJob(runOnSingleWorker = job2) - subnet_job <- disjoint_run{worker_job}() - - subnet_job.run() \ No newline at end of file +func returnSrvAsAbility() -> []string: + result: *string + MySrvDefault <- mySrvDefault() + MySrvResolved <- mySrvResolved() + MySrvThird <- mySrvThird() + result <- useMyAb{MySrvDefault}() + result <- useMyAb{MySrvResolved}() + result <- useMyAb{MySrvThird}() + <- result \ No newline at end of file diff --git a/build.sbt b/build.sbt index fc653bfb0..6ddd5c147 100644 --- a/build.sbt +++ b/build.sbt @@ -188,7 +188,7 @@ lazy val inline = crossProject(JVMPlatform, JSPlatform) .crossType(CrossType.Pure) .in(file("model/inline")) .settings(commons) - .dependsOn(raw, model) + .dependsOn(raw, model, mangler) lazy val transform = crossProject(JVMPlatform, JSPlatform) .withoutSuffixFor(JVMPlatform) @@ -207,7 +207,7 @@ lazy val semantics = crossProject(JVMPlatform, JSPlatform) "dev.optics" %%% "monocle-macro" % monocleV ) ) - .dependsOn(raw, parser, errors) + .dependsOn(raw, parser, errors, mangler) lazy val compiler = crossProject(JVMPlatform, JSPlatform) .withoutSuffixFor(JVMPlatform) @@ -253,6 +253,17 @@ lazy val logging = crossProject(JVMPlatform, JSPlatform) ) ) +lazy val mangler = crossProject(JVMPlatform, JSPlatform) + .withoutSuffixFor(JVMPlatform) + .crossType(CrossType.Pure) + .in(file("utils/mangler")) + .settings(commons) + .settings( + libraryDependencies ++= Seq( + "org.typelevel" %%% "cats-core" % catsV + ) + ) + lazy val constants = crossProject(JVMPlatform, JSPlatform) .withoutSuffixFor(JVMPlatform) .crossType(CrossType.Pure) 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 b2df353f2..e3146b172 100644 --- a/model/inline/src/main/scala/aqua/model/inline/TagInliner.scala +++ b/model/inline/src/main/scala/aqua/model/inline/TagInliner.scala @@ -321,7 +321,7 @@ object TagInliner extends Logging { operands .traverse(o => valueToModel(o)) .map(nel => { -// logger.trace("join after " + nel.map(_._1)) + logger.trace("join after " + nel.map(_._1)) // Empty because join behaviour will be processed in ApplyPropertiesRawInliner TagInlined.Empty(prefix = parDesugarPrefix(nel.toList.flatMap(_._2))) }) 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 3219b9cdd..0c25a2b29 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,5 +1,6 @@ package aqua.model.inline.state +import aqua.mangler.ManglerState import aqua.model.{FuncArrow, ValueModel} import aqua.model.inline.state.{Arrows, Counter, Exports, Mangler} import aqua.raw.arrow.FuncRaw diff --git a/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala b/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala index c20f1df18..e2289debe 100644 --- a/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala +++ b/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala @@ -1,6 +1,7 @@ package aqua.model.inline.state import cats.data.State +import aqua.mangler.ManglerState trait Mangler[S] { self => @@ -27,32 +28,19 @@ trait Mangler[S] { } } -case class ManglerState(lastNumbers: Map[String, Int] = Map.empty) - object Mangler { def apply[S](implicit mangler: Mangler[S]): Mangler[S] = mangler - private def genName(name: String, n: Int) = - s"$name-$n" - implicit object Simple extends Mangler[ManglerState] { val getForbiddenNames: State[ManglerState, ManglerState] = State.get def findAndForbidNames(introduce: Set[String]): State[ManglerState, Map[String, String]] = getForbiddenNames.flatMap(forbidden => - val (newLastNumbers, newNames) = - introduce.foldLeft((forbidden.lastNumbers, Map.empty[String, String])) { - case ((lastNumbers, acc), name) => - val (newName, newNumber) = - lastNumbers.get(name).map(n => (genName(name, n), n + 1)).getOrElse((name, 0)) - (lastNumbers + (name -> newNumber), acc + (name -> newName)) - } - State.modify[ManglerState](st => st.copy(lastNumbers = newLastNumbers)).map(_ => newNames) + val (newState, newNames) = forbidden.findNewNames(introduce) + State.modify[ManglerState](_ => newState).map(_ => newNames) ) def forbid(names: Set[String]): State[ManglerState, Unit] = - State.modify(st => - st.copy(lastNumbers = st.lastNumbers ++ names.map(n => n -> st.lastNumbers.getOrElse(n, -1))) - ) + State.modify(st => st.forbid(names)) } } diff --git a/model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala b/model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala new file mode 100644 index 000000000..dd3536fb6 --- /dev/null +++ b/model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala @@ -0,0 +1,109 @@ +package aqua.model.inline + +import aqua.mangler.ManglerState +import aqua.model.inline.state.Mangler +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + +class ManglerSpec extends AnyFlatSpec with Matchers { + + "mangler" should "forbid right" in { + val mangler = Mangler.Simple + + val a = for { + _ <- mangler.forbid(Set("first", "second")) + fn <- mangler.getForbiddenNames + } yield fn + + println(a.runA(ManglerState()).value) + } + + "mangler" should "rename right" in { + val mangler = Mangler.Simple + + val results = for { + res <- mangler.findAndForbidNames(Set("first", "second")) + fn <- mangler.getForbiddenNames + } yield (res, fn) + + val (res, _) = results.runA(ManglerState()).value + res shouldBe Map() + } + + "mangler" should "rename same words right" in { + val mangler = Mangler.Simple + + val results = for { + res1 <- mangler.findAndForbidNames(Set("first", "first")) + res2 <- mangler.findAndForbidNames(Set("first", "first")) + fn <- mangler.getForbiddenNames + } yield (res1, res2, fn) + + val (r1, r2, _) = results.runA(ManglerState()).value + r1 shouldBe Map() + r2 shouldBe Map("first" -> "first-0") + } + + "mangler" should "rename right if already have renamed" in { + val mangler = Mangler.Simple + + val results = for { + res1 <- mangler.findAndForbidNames(Set("first", "first-0", "first-1")) + res2 <- mangler.findAndForbidNames(Set("first")) + res3 <- mangler.findAndForbidNames(Set("first-0")) + res4 <- mangler.findAndForbidNames(Set("first-1")) + res5 <- mangler.findAndForbidNames(Set("first-2")) + fn <- mangler.getForbiddenNames + } yield (res1, res2, res3, res4, res5, fn) + + val (r1, r2, r3, r4, r5, _) = results.runA(ManglerState()).value + r1 shouldBe Map() + r2 shouldBe Map("first" -> "first-2") + r3 shouldBe Map("first" -> "first-0-0") + r4 shouldBe Map("first" -> "first-1-0") + r5 shouldBe Map("first" -> "first-2-0") + } + + "mangler" should "rename multiple times right" in { + val mangler = Mangler.Simple + + val results = for { + res <- mangler.findAndForbidNames(Set("first", "second")) + res2 <- mangler.findAndForbidNames(Set("first", "second")) + res3 <- mangler.findAndForbidNames(Set("first")) + res4 <- mangler.findAndForbidNames(Set("first", "second")) + res5 <- mangler.findAndForbidNames(Set("second")) + fn <- mangler.getForbiddenNames + } yield (res, res2, res3, res4, res5, fn) + + val (r1, r2, r3, r4, r5, _) = results.runA(ManglerState()).value + r1 shouldBe Map() + r2 shouldBe Map("first" -> "first-0", "second" -> "second-0") + r3 shouldBe Map("first" -> "first-1") + r4 shouldBe Map("first" -> "first-2", "second" -> "second-1") + r5 shouldBe Map("second" -> "second-2") + } + + "mangler" should "forbid and rename right" in { + val mangler = Mangler.Simple + + val results = for { + _ <- mangler.forbid(Set("first", "second")) + res1 <- mangler.findAndForbidNames(Set("first", "second")) + res2 <- mangler.findAndForbidNames(Set("first")) + _ <- mangler.forbid(Set("first")) + _ <- mangler.forbid(Set("first", "second")) + _ <- mangler.forbid(Set("second")) + res3 <- mangler.findAndForbidNames(Set("second")) + res4 <- mangler.findAndForbidNames(Set("second", "first")) + fn <- mangler.getForbiddenNames + } yield (res1, res2, res3, res4, fn) + + val (r1, r2, r3, r4, _) = results.runA(ManglerState()).value + r1 shouldBe Map("first" -> "first-0", "second" -> "second-0") + r2 shouldBe Map("first" -> "first-1") + r3 shouldBe Map("second" -> "second-1") + r4 shouldBe Map("first" -> "first-2", "second" -> "second-2") + } + +} diff --git a/semantics/src/main/scala/aqua/semantics/CompilerState.scala b/semantics/src/main/scala/aqua/semantics/CompilerState.scala index 1ea492121..ef7783d57 100644 --- a/semantics/src/main/scala/aqua/semantics/CompilerState.scala +++ b/semantics/src/main/scala/aqua/semantics/CompilerState.scala @@ -1,12 +1,12 @@ package aqua.semantics +import aqua.mangler.ManglerState import aqua.parser.lexer.Token import aqua.raw.Raw import aqua.raw.RawContext import aqua.semantics.rules.abilities.AbilitiesState import aqua.semantics.rules.definitions.DefinitionsState import aqua.semantics.rules.locations.LocationsState -import aqua.semantics.rules.mangler.ManglerState import aqua.semantics.rules.names.NamesState import aqua.semantics.rules.report.ReportState import aqua.semantics.rules.types.TypesState diff --git a/semantics/src/main/scala/aqua/semantics/expr/func/ServiceIdSem.scala b/semantics/src/main/scala/aqua/semantics/expr/func/ServiceIdSem.scala index 7274c8446..32dfc65a4 100644 --- a/semantics/src/main/scala/aqua/semantics/expr/func/ServiceIdSem.scala +++ b/semantics/src/main/scala/aqua/semantics/expr/func/ServiceIdSem.scala @@ -31,11 +31,11 @@ class ServiceIdSem[S[_]](val expr: ServiceIdExpr[S]) extends AnyVal { ) serviceType <- EitherT.fromOptionF( T.resolveServiceType(expr.service), - Raw.error("Can not resolve service type") + Raw.error("Cannot resolve service type") ) name <- EitherT.fromOptionF( A.renameService(expr.service), - Raw.error("Can not set service ID") + Raw.error("Cannot set service ID") ) _ <- EitherT.liftF( N.derive( diff --git a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala b/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala index b63d20dc9..bc50d5f0a 100644 --- a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala +++ b/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala @@ -1,5 +1,7 @@ package aqua.semantics.rules.mangler +import aqua.mangler.ManglerState + import cats.data.State import monocle.Lens @@ -7,14 +9,12 @@ class ManglerInterpreter[X](using lens: Lens[X, ManglerState] ) extends ManglerAlgebra[State[X, *]] { - def genName(name: String, n: Int) = s"$name-$n" - override def rename(name: String): State[X, String] = for { - s <- get - newNameAndNum = s.forbidden.get(name).map(n => genName(name, n + 1) -> (n + 1)).getOrElse(genName(name, 0) -> 0) - (newName, newNum) = newNameAndNum - _ <- modify(st => st.copy(forbidden = st.forbidden + (name -> newNum))) + state <- get + result = state.forbidAndRename(name) + (newState, newName) = result + _ <- modify(_ => newState) } yield newName private lazy val get: State[X, ManglerState] = diff --git a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerState.scala b/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerState.scala deleted file mode 100644 index a618a1931..000000000 --- a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerState.scala +++ /dev/null @@ -1,17 +0,0 @@ -package aqua.semantics.rules.mangler - -import cats.kernel.Monoid - -final case class ManglerState( - forbidden: Map[String, Int] = Map.empty -) - -object ManglerState { - - given Monoid[ManglerState] with { - override val empty: ManglerState = ManglerState() - - override def combine(x: ManglerState, y: ManglerState): ManglerState = - ManglerState(forbidden = x.forbidden ++ y.forbidden) - } -} diff --git a/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala b/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala new file mode 100644 index 000000000..a37709151 --- /dev/null +++ b/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala @@ -0,0 +1,66 @@ +package aqua.mangler + +import cats.Monoid + +import scala.annotation.tailrec + +case class ManglerState(lastNumbers: Map[String, Int] = Map.empty) { + + private def genName(name: String, n: Int) = + s"$name-$n" + + /** + * Find new unique name, that was never used. + * + * @param name base name + * @param number possible suffix for the name + * @param lastNumbers names with last used numbers + * @return + */ + @tailrec + private def findName(name: String, number: Int, lastNumbers: Map[String, Int]): (String, Int) = { + val newName = genName(name, number) + lastNumbers.get(newName) match { + case Some(n) => + val newNumber = n + 1 + findName(name, newNumber, lastNumbers) + case None => (newName, number) + } + } + + def findNewNames(introduce: Set[String]): (ManglerState, Map[String, String]) = { + val (newLastNumbers, newNames) = introduce.foldLeft((lastNumbers, Map.empty[String, String])) { + case ((accLastNumbers, acc), name) => + val (newName, newNumber) = accLastNumbers.get(name) match { + case Some(n) => findName(name, n + 1, accLastNumbers) + case None => (name, -1) + } + val newAcc = if (newNumber == -1) acc else acc + (name -> newName) + (accLastNumbers + (name -> newNumber) + (newName -> -1), newAcc) + } + + (copy(lastNumbers = newLastNumbers), newNames) + } + + + def forbid(names: Set[String]): ManglerState = { + val newLastNumbers = names.map(n => n -> lastNumbers.getOrElse(n, -1)).toMap + copy(lastNumbers = newLastNumbers ++ lastNumbers) + } + + def forbidAndRename(name: String): (ManglerState, String) = { + val set = Set(name) + val (newState, newNames) = forbid(set).findNewNames(set) + (newState, newNames(name)) + } +} + +object ManglerState { + + given Monoid[ManglerState] with { + override val empty: ManglerState = ManglerState() + + override def combine(x: ManglerState, y: ManglerState): ManglerState = + ManglerState(lastNumbers = x.lastNumbers ++ y.lastNumbers) + } +} From c960320038c28611607c9e2a26f9ed6ec4a839f9 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Fri, 19 Jan 2024 15:32:13 +0700 Subject: [PATCH 09/13] fix algorithm --- .../src/test/scala/aqua/model/inline/ManglerSpec.scala | 8 +++----- .../scala/aqua/model/inline/RawValueInlinerSpec.scala | 5 +++-- .../src/main/scala/aqua/mangler/ManglerState.scala | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala b/model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala index dd3536fb6..6fec133a4 100644 --- a/model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala +++ b/model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala @@ -14,8 +14,6 @@ class ManglerSpec extends AnyFlatSpec with Matchers { _ <- mangler.forbid(Set("first", "second")) fn <- mangler.getForbiddenNames } yield fn - - println(a.runA(ManglerState()).value) } "mangler" should "rename right" in { @@ -59,9 +57,9 @@ class ManglerSpec extends AnyFlatSpec with Matchers { val (r1, r2, r3, r4, r5, _) = results.runA(ManglerState()).value r1 shouldBe Map() r2 shouldBe Map("first" -> "first-2") - r3 shouldBe Map("first" -> "first-0-0") - r4 shouldBe Map("first" -> "first-1-0") - r5 shouldBe Map("first" -> "first-2-0") + r3 shouldBe Map("first-0" -> "first-0-0") + r4 shouldBe Map("first-1" -> "first-1-0") + r5 shouldBe Map("first-2" -> "first-2-0") } "mangler" should "rename multiple times right" in { diff --git a/model/inline/src/test/scala/aqua/model/inline/RawValueInlinerSpec.scala b/model/inline/src/test/scala/aqua/model/inline/RawValueInlinerSpec.scala index d34081c6b..e7a25680d 100644 --- a/model/inline/src/test/scala/aqua/model/inline/RawValueInlinerSpec.scala +++ b/model/inline/src/test/scala/aqua/model/inline/RawValueInlinerSpec.scala @@ -1,11 +1,11 @@ package aqua.model.inline +import aqua.mangler.ManglerState import aqua.model.* import aqua.model.inline.raw.StreamGateInliner -import aqua.model.inline.state.{InliningState, ManglerState} +import aqua.model.inline.state.InliningState import aqua.raw.value.* import aqua.types.* - import cats.Eval import cats.data.{Chain, NonEmptyMap} import cats.free.Cofree @@ -13,6 +13,7 @@ import cats.syntax.foldable.* import org.scalatest.Inside import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers + import scala.collection.immutable.SortedMap import scala.math diff --git a/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala b/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala index a37709151..95c76dbfe 100644 --- a/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala +++ b/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala @@ -22,7 +22,7 @@ case class ManglerState(lastNumbers: Map[String, Int] = Map.empty) { val newName = genName(name, number) lastNumbers.get(newName) match { case Some(n) => - val newNumber = n + 1 + val newNumber = number + 1 findName(name, newNumber, lastNumbers) case None => (newName, number) } From d6986a1ea191ff0388705d6f3c397b5c3d93627e Mon Sep 17 00:00:00 2001 From: DieMyst Date: Fri, 19 Jan 2024 15:39:29 +0700 Subject: [PATCH 10/13] clear PR --- .../scala/aqua/model/inline/raw/CallArrowRawInliner.scala | 6 +++--- .../scala/aqua/model/inline/raw/CallServiceRawInliner.scala | 4 ++-- model/src/main/scala/aqua/model/AquaContext.scala | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) 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 c7a43b462..3aa8227e8 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 @@ -18,7 +18,7 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { value: CallArrowRaw, exportTo: List[Call.Export] ): State[S, (List[ValueModel], Inline)] = { -// logger.trace(s"${exportTo.mkString(" ")} $value") + logger.trace(s"${exportTo.mkString(" ")} $value") val call = Call(value.arguments, exportTo) @@ -26,7 +26,7 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { * Here the back hop happens from [[TagInliner]] to [[ArrowInliner.callArrow]] */ val funcName = value.ability.fold(value.name)(_ + "." + value.name) -// logger.trace(s" $funcName") + logger.trace(s" $funcName") resolveArrow(funcName, call) } @@ -35,7 +35,7 @@ object CallArrowRawInliner extends RawInliner[CallArrowRaw] with Logging { fn: FuncArrow, call: Call ): State[S, (List[ValueModel], Inline)] = { -// logger.trace(Console.YELLOW + s"Call arrow ${fn.funcName}" + Console.RESET) + logger.trace(Console.YELLOW + s"Call arrow ${fn.funcName}" + Console.RESET) callToModel(call, false).flatMap { case (cm, p) => ArrowInliner .callArrowRet(fn, cm) 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 0bdc27269..9c8e000cd 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 @@ -15,8 +15,8 @@ object CallServiceRawInliner extends RawInliner[CallServiceRaw] with Logging { 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) + logger.trace(s"${exportTo.mkString(" ")} $value") + logger.trace(Console.BLUE + s"call service id ${value.serviceId}" + Console.RESET) val call = Call(value.arguments, exportTo) diff --git a/model/src/main/scala/aqua/model/AquaContext.scala b/model/src/main/scala/aqua/model/AquaContext.scala index 9225c9700..9be943798 100644 --- a/model/src/main/scala/aqua/model/AquaContext.scala +++ b/model/src/main/scala/aqua/model/AquaContext.scala @@ -113,7 +113,7 @@ case class AquaContext( object AquaContext extends Logging { - case class Cache(data: Chain[(RawContext, AquaContext)] = Chain.empty) { + case class Cache(private val data: Chain[(RawContext, AquaContext)] = Chain.empty) { lazy val size: Long = data.size def get(ctx: RawContext): Option[AquaContext] = From 40c4efc1a030a88b5480b22f2a3079ffe3bd5e7a Mon Sep 17 00:00:00 2001 From: DieMyst Date: Fri, 19 Jan 2024 17:38:32 +0700 Subject: [PATCH 11/13] add comments --- api/api/.jvm/src/main/scala/aqua/api/Test.scala | 6 +----- .../src/main/scala/aqua/mangler/ManglerState.scala | 10 ++++++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/api/api/.jvm/src/main/scala/aqua/api/Test.scala b/api/api/.jvm/src/main/scala/aqua/api/Test.scala index edc6fcc75..3e60c207e 100644 --- a/api/api/.jvm/src/main/scala/aqua/api/Test.scala +++ b/api/api/.jvm/src/main/scala/aqua/api/Test.scala @@ -22,11 +22,7 @@ object Test extends IOApp.Simple { "/" -> Map( "" -> List( "/home/diemust/git/decider/.fluence/aqua", - "/home/diemust/.fluence/npm/@fluencelabs/aqua-lib/0.9.0/node_modules", - "/home/diemust/.fluence/npm/@fluencelabs/spell/0.6.0/node_modules", - "/home/diemust/.fluence/npm/@fluencelabs/registry/0.8.7/node_modules", - "/home/diemust/.fluence/npm/@fluencelabs/aqua-ipfs/0.5.24/node_modules", - "/home/diemust/.fluence/npm/@fluencelabs/installation-spell/0.6.0/node_modules" + "/home/diemust/git/decider/.fluence/aqua-dependencies/node_modules", ) ) ) diff --git a/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala b/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala index 95c76dbfe..84973539b 100644 --- a/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala +++ b/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala @@ -21,13 +21,16 @@ case class ManglerState(lastNumbers: Map[String, Int] = Map.empty) { private def findName(name: String, number: Int, lastNumbers: Map[String, Int]): (String, Int) = { val newName = genName(name, number) lastNumbers.get(newName) match { - case Some(n) => + // if there is such name already - increment number + case Some(_) => val newNumber = number + 1 + // repeat until find unique name findName(name, newNumber, lastNumbers) case None => (newName, number) } } + // find unique names that have not yet been used def findNewNames(introduce: Set[String]): (ManglerState, Map[String, String]) = { val (newLastNumbers, newNames) = introduce.foldLeft((lastNumbers, Map.empty[String, String])) { case ((accLastNumbers, acc), name) => @@ -35,19 +38,22 @@ case class ManglerState(lastNumbers: Map[String, Int] = Map.empty) { case Some(n) => findName(name, n + 1, accLastNumbers) case None => (name, -1) } + // if number is '-1', then it was not yet in the list, so there is no need to rename it val newAcc = if (newNumber == -1) acc else acc + (name -> newName) + // update last number for introduced name and add new name to a list (accLastNumbers + (name -> newNumber) + (newName -> -1), newAcc) } (copy(lastNumbers = newLastNumbers), newNames) } - + // add names to used list def forbid(names: Set[String]): ManglerState = { val newLastNumbers = names.map(n => n -> lastNumbers.getOrElse(n, -1)).toMap copy(lastNumbers = newLastNumbers ++ lastNumbers) } + // forbid name and return unique def forbidAndRename(name: String): (ManglerState, String) = { val set = Set(name) val (newState, newNames) = forbid(set).findNewNames(set) From c92755bc48b10f9796bee2d2b906250a0f357b84 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Fri, 19 Jan 2024 17:43:34 +0700 Subject: [PATCH 12/13] refactor --- .../src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala b/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala index a99ca538b..6d291d130 100644 --- a/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala +++ b/semantics/src/main/scala/aqua/semantics/expr/func/CallArrowSem.scala @@ -27,7 +27,7 @@ class CallArrowSem[S[_]](val expr: CallArrowExpr[S]) extends AnyVal { private def getExports[Alg[_]: Monad](codomain: ProductType)(using N: NamesAlgebra[S, Alg], T: TypesAlgebra[S, Alg] - ): Alg[List[Call.Export]] = { + ): Alg[List[Call.Export]] = (variables zip codomain.toList).traverse { case (v, t) => N.read(v, mustBeDefined = false).flatMap { case Some(stream @ StreamType(st)) => @@ -36,7 +36,6 @@ class CallArrowSem[S[_]](val expr: CallArrowExpr[S]) extends AnyVal { N.define(v, t).as(Call.Export(v.value, t)) } } - } private def toModel[Alg[_]: Monad](using N: NamesAlgebra[S, Alg], From b5c66d0f7ae520278e3109149456665d7cf5a716 Mon Sep 17 00:00:00 2001 From: DieMyst Date: Mon, 22 Jan 2024 15:18:46 +0700 Subject: [PATCH 13/13] PR fixes --- .../.jvm/src/main/scala/aqua/api/Test.scala | 17 ++--- io/src/test/scala/aqua/ImportsSpec.scala | 2 +- .../model/inline/state/InliningState.scala | 2 +- .../aqua/model/inline/state/Mangler.scala | 16 +---- .../scala/aqua/model/inline/ManglerSpec.scala | 51 ++++----------- .../rules/mangler/ManglerInterpreter.scala | 14 +--- .../scala/aqua/mangler/ManglerState.scala | 65 +++++++++---------- 7 files changed, 53 insertions(+), 114 deletions(-) diff --git a/api/api/.jvm/src/main/scala/aqua/api/Test.scala b/api/api/.jvm/src/main/scala/aqua/api/Test.scala index 3e60c207e..d81c00412 100644 --- a/api/api/.jvm/src/main/scala/aqua/api/Test.scala +++ b/api/api/.jvm/src/main/scala/aqua/api/Test.scala @@ -1,5 +1,6 @@ package aqua.api +import aqua.api.TargetType.TypeScriptType import aqua.backend.ts.TypeScriptBackend import aqua.compiler.AquaCompiled import aqua.files.FileModuleId @@ -15,19 +16,9 @@ object Test extends IOApp.Simple { APICompilation .compilePath( -// "/home/diemust/git/decider/src/aqua/decider/poll.aqua", "./aqua-src/antithesis.aqua", - Imports.fromMap( - Map( - "/" -> Map( - "" -> List( - "/home/diemust/git/decider/.fluence/aqua", - "/home/diemust/git/decider/.fluence/aqua-dependencies/node_modules", - ) - ) - ) - ), - AquaAPIConfig(logLevel = "info"), + Imports.fromMap(Map("/" -> Map("" -> List("./aqua")))), + AquaAPIConfig(targetType = TypeScriptType), TypeScriptBackend(false, "IFluenceClient$$") ).timed .flatMap { case (duration, res) => @@ -35,7 +26,7 @@ object Test extends IOApp.Simple { val (warnings, result) = res.value.run IO.delay { - // warnings.toList.foreach(println) + warnings.toList.foreach(println) } *> result.fold( errors => IO.delay { diff --git a/io/src/test/scala/aqua/ImportsSpec.scala b/io/src/test/scala/aqua/ImportsSpec.scala index 57d0c6d9b..c463fd1b7 100644 --- a/io/src/test/scala/aqua/ImportsSpec.scala +++ b/io/src/test/scala/aqua/ImportsSpec.scala @@ -11,7 +11,7 @@ class ImportsSpec extends AnyFlatSpec with ScalaCheckPropertyChecks with Matcher implicit override val generatorDrivenConfig = // Tests here are lightweight, so we can afford to run more of them - PropertyCheckConfiguration(minSuccessful = 50, sizeRange = 32) + PropertyCheckConfiguration(minSuccessful = 500, sizeRange = 64) val shortAlphaNumStr = for { length <- Gen.choose(1, 10) 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 0c25a2b29..e931cd0aa 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 @@ -36,7 +36,7 @@ object InliningState { Counter.Simple.transformS(_.instructionCounter, (acc, i) => acc.copy(instructionCounter = i)) given Mangler[InliningState] = - Mangler.Simple.transformS(_.noNames, (acc, nn) => acc.copy(noNames = nn)) + Mangler[ManglerState].transformS(_.noNames, (acc, nn) => acc.copy(noNames = nn)) given Arrows[InliningState] = Arrows.Simple.transformS(_.resolvedArrows, (acc, aa) => acc.copy(resolvedArrows = aa)) diff --git a/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala b/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala index e2289debe..3e3b4c86c 100644 --- a/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala +++ b/model/inline/src/main/scala/aqua/model/inline/state/Mangler.scala @@ -5,8 +5,6 @@ import aqua.mangler.ManglerState trait Mangler[S] { self => - def getForbiddenNames: State[S, ManglerState] - def findAndForbidName(introduce: String): State[S, String] = findAndForbidNames(Set(introduce)).map(_.getOrElse(introduce, introduce)) @@ -17,9 +15,6 @@ trait Mangler[S] { def transformS[R](f: R => S, g: (R, S) => R): Mangler[R] = new Mangler[R] { - val getForbiddenNames: State[R, ManglerState] = - self.getForbiddenNames.transformS(f, g) - def forbid(names: Set[String]): State[R, Unit] = self.forbid(names).transformS(f, g) @@ -29,16 +24,11 @@ trait Mangler[S] { } object Mangler { - def apply[S](implicit mangler: Mangler[S]): Mangler[S] = mangler - - implicit object Simple extends Mangler[ManglerState] { - val getForbiddenNames: State[ManglerState, ManglerState] = State.get + def apply[S](using mangler: Mangler[S]): Mangler[S] = mangler + given Mangler[ManglerState] with { def findAndForbidNames(introduce: Set[String]): State[ManglerState, Map[String, String]] = - getForbiddenNames.flatMap(forbidden => - val (newState, newNames) = forbidden.findNewNames(introduce) - State.modify[ManglerState](_ => newState).map(_ => newNames) - ) + State.apply(_.findNewNames(introduce)) def forbid(names: Set[String]): State[ManglerState, Unit] = State.modify(st => st.forbid(names)) diff --git a/model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala b/model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala index 6fec133a4..df17745f7 100644 --- a/model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala +++ b/model/inline/src/test/scala/aqua/model/inline/ManglerSpec.scala @@ -7,43 +7,19 @@ import org.scalatest.matchers.should.Matchers class ManglerSpec extends AnyFlatSpec with Matchers { - "mangler" should "forbid right" in { - val mangler = Mangler.Simple - - val a = for { - _ <- mangler.forbid(Set("first", "second")) - fn <- mangler.getForbiddenNames - } yield fn - } - "mangler" should "rename right" in { - val mangler = Mangler.Simple + val mangler = Mangler[ManglerState] val results = for { res <- mangler.findAndForbidNames(Set("first", "second")) - fn <- mangler.getForbiddenNames - } yield (res, fn) + } yield res - val (res, _) = results.runA(ManglerState()).value + val res = results.runA(ManglerState()).value res shouldBe Map() } - "mangler" should "rename same words right" in { - val mangler = Mangler.Simple - - val results = for { - res1 <- mangler.findAndForbidNames(Set("first", "first")) - res2 <- mangler.findAndForbidNames(Set("first", "first")) - fn <- mangler.getForbiddenNames - } yield (res1, res2, fn) - - val (r1, r2, _) = results.runA(ManglerState()).value - r1 shouldBe Map() - r2 shouldBe Map("first" -> "first-0") - } - "mangler" should "rename right if already have renamed" in { - val mangler = Mangler.Simple + val mangler = Mangler[ManglerState] val results = for { res1 <- mangler.findAndForbidNames(Set("first", "first-0", "first-1")) @@ -51,10 +27,9 @@ class ManglerSpec extends AnyFlatSpec with Matchers { res3 <- mangler.findAndForbidNames(Set("first-0")) res4 <- mangler.findAndForbidNames(Set("first-1")) res5 <- mangler.findAndForbidNames(Set("first-2")) - fn <- mangler.getForbiddenNames - } yield (res1, res2, res3, res4, res5, fn) + } yield (res1, res2, res3, res4, res5) - val (r1, r2, r3, r4, r5, _) = results.runA(ManglerState()).value + val (r1, r2, r3, r4, r5) = results.runA(ManglerState()).value r1 shouldBe Map() r2 shouldBe Map("first" -> "first-2") r3 shouldBe Map("first-0" -> "first-0-0") @@ -63,7 +38,7 @@ class ManglerSpec extends AnyFlatSpec with Matchers { } "mangler" should "rename multiple times right" in { - val mangler = Mangler.Simple + val mangler = Mangler[ManglerState] val results = for { res <- mangler.findAndForbidNames(Set("first", "second")) @@ -71,10 +46,9 @@ class ManglerSpec extends AnyFlatSpec with Matchers { res3 <- mangler.findAndForbidNames(Set("first")) res4 <- mangler.findAndForbidNames(Set("first", "second")) res5 <- mangler.findAndForbidNames(Set("second")) - fn <- mangler.getForbiddenNames - } yield (res, res2, res3, res4, res5, fn) + } yield (res, res2, res3, res4, res5) - val (r1, r2, r3, r4, r5, _) = results.runA(ManglerState()).value + val (r1, r2, r3, r4, r5) = results.runA(ManglerState()).value r1 shouldBe Map() r2 shouldBe Map("first" -> "first-0", "second" -> "second-0") r3 shouldBe Map("first" -> "first-1") @@ -83,7 +57,7 @@ class ManglerSpec extends AnyFlatSpec with Matchers { } "mangler" should "forbid and rename right" in { - val mangler = Mangler.Simple + val mangler = Mangler[ManglerState] val results = for { _ <- mangler.forbid(Set("first", "second")) @@ -94,10 +68,9 @@ class ManglerSpec extends AnyFlatSpec with Matchers { _ <- mangler.forbid(Set("second")) res3 <- mangler.findAndForbidNames(Set("second")) res4 <- mangler.findAndForbidNames(Set("second", "first")) - fn <- mangler.getForbiddenNames - } yield (res1, res2, res3, res4, fn) + } yield (res1, res2, res3, res4) - val (r1, r2, r3, r4, _) = results.runA(ManglerState()).value + val (r1, r2, r3, r4) = results.runA(ManglerState()).value r1 shouldBe Map("first" -> "first-0", "second" -> "second-0") r2 shouldBe Map("first" -> "first-1") r3 shouldBe Map("second" -> "second-1") diff --git a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala b/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala index bc50d5f0a..ef97b0a6c 100644 --- a/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala +++ b/semantics/src/main/scala/aqua/semantics/rules/mangler/ManglerInterpreter.scala @@ -10,16 +10,8 @@ class ManglerInterpreter[X](using ) extends ManglerAlgebra[State[X, *]] { override def rename(name: String): State[X, String] = - for { - state <- get - result = state.forbidAndRename(name) - (newState, newName) = result - _ <- modify(_ => newState) - } yield newName + apply(_.forbidAndRename(name)) - private lazy val get: State[X, ManglerState] = - State.get[X].map(lens.get) - - private def modify(f: ManglerState => ManglerState): State[X, Unit] = - State.modify[X](lens.modify(f)) + private def apply[A](f: ManglerState => (ManglerState, A)): State[X, A] = + State.apply(lens.modifyF(f andThen (_.swap)) andThen (_.swap)) } diff --git a/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala b/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala index 84973539b..2cad60869 100644 --- a/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala +++ b/utils/mangler/src/main/scala/aqua/mangler/ManglerState.scala @@ -4,53 +4,46 @@ import cats.Monoid import scala.annotation.tailrec -case class ManglerState(lastNumbers: Map[String, Int] = Map.empty) { +case class ManglerState(namesNumbers: Map[String, Int] = Map.empty) { private def genName(name: String, n: Int) = s"$name-$n" - /** - * Find new unique name, that was never used. - * - * @param name base name - * @param number possible suffix for the name - * @param lastNumbers names with last used numbers - * @return - */ - @tailrec - private def findName(name: String, number: Int, lastNumbers: Map[String, Int]): (String, Int) = { - val newName = genName(name, number) - lastNumbers.get(newName) match { - // if there is such name already - increment number - case Some(_) => - val newNumber = number + 1 - // repeat until find unique name - findName(name, newNumber, lastNumbers) - case None => (newName, number) - } - } - // find unique names that have not yet been used def findNewNames(introduce: Set[String]): (ManglerState, Map[String, String]) = { - val (newLastNumbers, newNames) = introduce.foldLeft((lastNumbers, Map.empty[String, String])) { - case ((accLastNumbers, acc), name) => - val (newName, newNumber) = accLastNumbers.get(name) match { - case Some(n) => findName(name, n + 1, accLastNumbers) - case None => (name, -1) + introduce.foldLeft(this, Map.empty[String, String]) { + case ((state, newNames), name) => + val namesNumbers = state.namesNumbers + if (!namesNumbers.contains(name)) { + val newState = state.copy( + namesNumbers = namesNumbers + .updated(name, 0) + ) + + (newState, newNames) + } else { + val (newNumber, newName) = LazyList + .from(namesNumbers.getOrElse(name, 0)) + .map(n => n -> genName(name, n)) + .dropWhile { case (_, newName) => + namesNumbers.contains(newName) + } + .head + val newState = copy( + namesNumbers = namesNumbers + .updated(name, newNumber + 1) + .updated(newName, 0) + ) + + (newState, newNames + (name -> newName)) } - // if number is '-1', then it was not yet in the list, so there is no need to rename it - val newAcc = if (newNumber == -1) acc else acc + (name -> newName) - // update last number for introduced name and add new name to a list - (accLastNumbers + (name -> newNumber) + (newName -> -1), newAcc) } - - (copy(lastNumbers = newLastNumbers), newNames) } // add names to used list def forbid(names: Set[String]): ManglerState = { - val newLastNumbers = names.map(n => n -> lastNumbers.getOrElse(n, -1)).toMap - copy(lastNumbers = newLastNumbers ++ lastNumbers) + val newLastNumbers = names.map(n => n -> namesNumbers.getOrElse(n, 0)).toMap + copy(namesNumbers = newLastNumbers ++ namesNumbers) } // forbid name and return unique @@ -67,6 +60,6 @@ object ManglerState { override val empty: ManglerState = ManglerState() override def combine(x: ManglerState, y: ManglerState): ManglerState = - ManglerState(lastNumbers = x.lastNumbers ++ y.lastNumbers) + ManglerState(namesNumbers = x.namesNumbers ++ y.namesNumbers) } }