From dae234dc5a3f3ed30d6ad17d8ef1c367179ba33c Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 27 Aug 2021 15:57:44 +0300 Subject: [PATCH] Performance improvement: single parser instance (#254) --- build.sbt | 4 +- .../main/scala/aqua/AquaPathCompiler.scala | 24 +++++++++- .../scala/aqua/compiler/AquaCompiler.scala | 14 +++--- .../main/scala/aqua/compiler/AquaParser.scala | 15 ++++--- parser/src/main/scala/aqua/parser/Ast.scala | 21 ++------- parser/src/main/scala/aqua/parser/Expr.scala | 3 ++ .../src/main/scala/aqua/parser/Parser.scala | 44 +++++++++++++++++++ .../main/scala/aqua/parser/ParserError.scala | 19 ++++++-- .../aqua/parser/expr/AbilityIdExpr.scala | 8 +++- .../scala/aqua/parser/expr/AliasExpr.scala | 5 ++- .../aqua/parser/expr/ArrowTypeExpr.scala | 5 ++- .../aqua/parser/expr/AssignmentExpr.scala | 5 ++- .../aqua/parser/expr/CallArrowExpr.scala | 12 ++++- .../scala/aqua/parser/expr/CatchExpr.scala | 5 ++- .../main/scala/aqua/parser/expr/CoExpr.scala | 5 ++- .../scala/aqua/parser/expr/ConstantExpr.scala | 7 ++- .../aqua/parser/expr/DataStructExpr.scala | 7 ++- .../aqua/parser/expr/DeclareStreamExpr.scala | 7 ++- .../aqua/parser/expr/ElseOtherwiseExpr.scala | 5 ++- .../aqua/parser/expr/FieldTypeExpr.scala | 7 ++- .../main/scala/aqua/parser/expr/ForExpr.scala | 7 ++- .../scala/aqua/parser/expr/FuncExpr.scala | 4 ++ .../main/scala/aqua/parser/expr/IfExpr.scala | 6 ++- .../main/scala/aqua/parser/expr/OnExpr.scala | 7 ++- .../main/scala/aqua/parser/expr/ParExpr.scala | 7 ++- .../aqua/parser/expr/PushToStreamExpr.scala | 7 ++- .../scala/aqua/parser/expr/ReturnExpr.scala | 8 +++- .../scala/aqua/parser/expr/RootExpr.scala | 7 ++- .../scala/aqua/parser/expr/ServiceExpr.scala | 7 ++- .../main/scala/aqua/parser/expr/TryExpr.scala | 7 ++- .../scala/aqua/parser/head/ExportExpr.scala | 4 ++ .../scala/aqua/parser/head/FilenameExpr.scala | 5 +++ .../scala/aqua/parser/head/FromExpr.scala | 8 ++++ .../scala/aqua/parser/head/HeadExpr.scala | 7 ++- .../scala/aqua/parser/head/HeaderExpr.scala | 3 ++ .../scala/aqua/parser/head/ImportExpr.scala | 6 ++- .../aqua/parser/head/ImportFromExpr.scala | 6 ++- .../scala/aqua/parser/head/ModuleExpr.scala | 9 ++++ .../main/scala/aqua/parser/head/UseExpr.scala | 6 ++- .../scala/aqua/parser/head/UseFromExpr.scala | 7 ++- .../scala/aqua/parser/lexer/Ability.scala | 3 ++ .../main/scala/aqua/parser/lexer/EqOp.scala | 4 ++ .../scala/aqua/parser/lexer/LambdaOp.scala | 11 ++++- .../main/scala/aqua/parser/lexer/Name.scala | 3 ++ .../main/scala/aqua/parser/lexer/Token.scala | 9 +++- .../scala/aqua/parser/lexer/TypeToken.scala | 26 ++++++++++- .../main/scala/aqua/parser/lexer/Value.scala | 20 ++++++--- .../test/scala/aqua/parser/FuncExprSpec.scala | 12 ++--- .../scala/aqua/semantics/SemanticsSpec.scala | 7 ++- 49 files changed, 362 insertions(+), 83 deletions(-) create mode 100644 parser/src/main/scala/aqua/parser/Parser.scala diff --git a/build.sbt b/build.sbt index 5ee132e4..b6e25513 100644 --- a/build.sbt +++ b/build.sbt @@ -85,8 +85,8 @@ lazy val parser = crossProject(JVMPlatform, JSPlatform) .settings(commons: _*) .settings( libraryDependencies ++= Seq( - "org.typelevel" %%% "cats-parse" % catsParseV, - "org.typelevel" %%% "cats-free" % catsV + "org.typelevel" %%% "cats-parse" % catsParseV, + "org.typelevel" %%% "cats-free" % catsV ) ) .dependsOn(types) diff --git a/cli/src/main/scala/aqua/AquaPathCompiler.scala b/cli/src/main/scala/aqua/AquaPathCompiler.scala index 7b0490d2..1ed34dee 100644 --- a/cli/src/main/scala/aqua/AquaPathCompiler.scala +++ b/cli/src/main/scala/aqua/AquaPathCompiler.scala @@ -5,13 +5,20 @@ import aqua.compiler.{AquaCompiler, AquaError} import aqua.files.{AquaFileSources, FileModuleId} import aqua.io.* import aqua.model.transform.TransformConfig +import aqua.parser.{Ast, LexerError} import aqua.parser.lift.FileSpan import cats.data.* import cats.syntax.functor.* import cats.syntax.show.* -import cats.{Monad, Show} +import cats.{~>, Eval, Monad, Show} import scribe.Logging import fs2.io.file.{Files, Path} +import aqua.parser.lift.{LiftParser, Span} +import cats.parse.LocationMap +import cats.~> +import aqua.parser.lift.LiftParser.LiftErrorOps +import Span.spanLiftParser +import aqua.parser.Parser object AquaPathCompiler extends Logging { @@ -27,7 +34,20 @@ object AquaPathCompiler extends Logging { AquaCompiler .compileTo[F, AquaFileError, FileModuleId, FileSpan.F, String]( sources, - (fmid, src) => FileSpan.fileSpanLiftParser(fmid.file.toString, src), + id => { + source => { + val nat = new (Span.F ~> FileSpan.F) { + override def apply[A](span: Span.F[A]): FileSpan.F[A] = { + ( + FileSpan(id.file.fileName.toString, Eval.later(LocationMap(source)), span._1), + span._2 + ) + } + } + import Span.spanLiftParser + Parser.natParser(Parser.spanParser, nat)(source) + } + }, backend, bodyConfig, sources.write(targetPath) diff --git a/compiler/src/main/scala/aqua/compiler/AquaCompiler.scala b/compiler/src/main/scala/aqua/compiler/AquaCompiler.scala index 034f733d..b2404b9a 100644 --- a/compiler/src/main/scala/aqua/compiler/AquaCompiler.scala +++ b/compiler/src/main/scala/aqua/compiler/AquaCompiler.scala @@ -5,12 +5,13 @@ import aqua.linker.Linker import aqua.model.AquaContext import aqua.model.transform.TransformConfig import aqua.model.transform.res.AquaRes -import aqua.parser.lift.LiftParser -import aqua.parser.Ast +import aqua.parser.lift.{LiftParser, Span} +import aqua.parser.{Ast, ParserError} import aqua.semantics.Semantics import aqua.semantics.header.HeaderSem import cats.data.Validated.{validNec, Invalid, Valid} import cats.data.{Chain, NonEmptyChain, NonEmptyMap, Validated, ValidatedNec} +import cats.parse.Parser0 import cats.syntax.applicative.* import cats.syntax.flatMap.* import cats.syntax.functor.* @@ -18,12 +19,13 @@ import cats.syntax.traverse.* import cats.syntax.monoid.* import cats.{Comonad, Monad, Monoid, Order} import scribe.Logging +import cats.~> object AquaCompiler extends Logging { def compile[F[_]: Monad, E, I: Order, S[_]: Comonad]( sources: AquaSources[F, E, I], - liftI: (I, String) => LiftParser[S], + parser: I => String => ValidatedNec[ParserError[S], Ast[S]], backend: Backend, config: TransformConfig ): F[ValidatedNec[AquaError[I, E, S], Chain[AquaCompiled[I]]]] = { @@ -32,7 +34,7 @@ object AquaCompiler extends Logging { type Ctx = NonEmptyMap[I, AquaContext] type ValidatedCtx = ValidatedNec[Err, Ctx] - new AquaParser[F, E, I, S](sources, liftI) + new AquaParser[F, E, I, S](sources, parser) .resolve[ValidatedCtx](mod => context => // Context with prepared imports @@ -95,12 +97,12 @@ object AquaCompiler extends Logging { def compileTo[F[_]: Monad, E, I: Order, S[_]: Comonad, T]( sources: AquaSources[F, E, I], - liftI: (I, String) => LiftParser[S], + parser: I => String => ValidatedNec[ParserError[S], Ast[S]], backend: Backend, config: TransformConfig, write: AquaCompiled[I] => F[Seq[Validated[E, T]]] ): F[ValidatedNec[AquaError[I, E, S], Chain[T]]] = - compile[F, E, I, S](sources, liftI, backend, config).flatMap { + compile[F, E, I, S](sources, parser, backend, config).flatMap { case Valid(compiled) => compiled.map { ac => write(ac).map( diff --git a/compiler/src/main/scala/aqua/compiler/AquaParser.scala b/compiler/src/main/scala/aqua/compiler/AquaParser.scala index b9a11db5..e5d6bc19 100644 --- a/compiler/src/main/scala/aqua/compiler/AquaParser.scala +++ b/compiler/src/main/scala/aqua/compiler/AquaParser.scala @@ -1,21 +1,23 @@ package aqua.compiler import aqua.linker.{AquaModule, Modules} -import aqua.parser.Ast +import aqua.parser.{Ast, ParserError} import aqua.parser.head.{FilenameExpr, ImportExpr} -import aqua.parser.lift.LiftParser +import aqua.parser.lift.{LiftParser, Span} import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec} +import cats.parse.Parser0 import cats.syntax.applicative.* import cats.syntax.flatMap.* import cats.syntax.functor.* import cats.syntax.traverse.* import cats.{Comonad, Monad} import scribe.Logging +import cats.~> // TODO: add tests class AquaParser[F[_]: Monad, E, I, S[_]: Comonad]( sources: AquaSources[F, E, I], - liftI: (I, String) => LiftParser[S] + parser: I => String => ValidatedNec[ParserError[S], Ast[S]] ) extends Logging { type Body = Ast[S] @@ -26,8 +28,8 @@ class AquaParser[F[_]: Monad, E, I, S[_]: Comonad]( sources.sources .map( _.leftMap(_.map[Err](SourcesErr(_))).andThen(_.map { case (i, s) => - implicit val lift: LiftParser[S] = liftI(i, s) - Ast.fromString[S](s).bimap(_.map[Err](ParserErr(_)), ast => Chain.one(i -> ast)) + parser(i)(s) + .bimap(_.map[Err](ParserErr(_)), ast => Chain.one(i -> ast)) }.foldLeft(Validated.validNec[Err, Chain[(I, Body)]](Chain.nil))(_ combine _)) ) @@ -84,8 +86,7 @@ class AquaParser[F[_]: Monad, E, I, S[_]: Comonad]( sources .load(imp) .map(_.leftMap(_.map[Err](SourcesErr(_))).andThen { src => - implicit val lift: LiftParser[S] = liftI(imp, src) - Ast.fromString[S](src).leftMap(_.map[Err](ParserErr(_))) + parser(imp)(src).leftMap(_.map[Err](ParserErr(_))) }) .flatMap { case Validated.Valid(ast) => diff --git a/parser/src/main/scala/aqua/parser/Ast.scala b/parser/src/main/scala/aqua/parser/Ast.scala index 39a39def..a0022a79 100644 --- a/parser/src/main/scala/aqua/parser/Ast.scala +++ b/parser/src/main/scala/aqua/parser/Ast.scala @@ -1,13 +1,13 @@ package aqua.parser -import aqua.parser.expr._ +import aqua.parser.expr.* import aqua.parser.head.{HeadExpr, HeaderExpr} -import aqua.parser.lift.LiftParser -import aqua.parser.lift.LiftParser._ +import aqua.parser.lift.{LiftParser, Span} +import aqua.parser.lift.LiftParser.* import cats.data.{Chain, Validated, ValidatedNec} import cats.free.Cofree -import cats.parse.Parser0 as P0 import cats.{Comonad, Eval} +import cats.~> case class Ast[S[_]](head: Ast.Head[S], tree: Ast.Tree[S]) { @@ -21,17 +21,4 @@ case class Ast[S[_]](head: Ast.Head[S], tree: Ast.Tree[S]) { object Ast { type Tree[S[_]] = Cofree[Chain, Expr[S]] type Head[S[_]] = Cofree[Chain, HeaderExpr[S]] - - def parser[S[_]: LiftParser: Comonad](): P0[ValidatedNec[ParserError[S], Ast[S]]] = - (HeadExpr.ast[S].with1 ~ RootExpr.ast[S]()).map { case (head, bodyMaybe) => - bodyMaybe.map(Ast(head, _)) - } - - def fromString[S[_]: LiftParser: Comonad](script: String): ValidatedNec[ParserError[S], Ast[S]] = - parser[S]() - .parseAll(script) match { - case Right(value) => value - case Left(e) => Validated.invalidNec(LexerError[S](e.wrapErr)) - } - } diff --git a/parser/src/main/scala/aqua/parser/Expr.scala b/parser/src/main/scala/aqua/parser/Expr.scala index 148f444f..40d08e85 100644 --- a/parser/src/main/scala/aqua/parser/Expr.scala +++ b/parser/src/main/scala/aqua/parser/Expr.scala @@ -11,6 +11,7 @@ import cats.free.Cofree import cats.parse.Parser as P import cats.syntax.comonad.* import cats.{Comonad, Eval} +import cats.~> abstract class Expr[F[_]](val companion: Expr.Companion, val token: Token[F]) { @@ -18,6 +19,8 @@ abstract class Expr[F[_]](val companion: Expr.Companion, val token: Token[F]) { case _: Expr.Block => true case _ => false } + + def mapK[K[_]: Comonad](fk: F ~> K): Expr[K] } object Expr { diff --git a/parser/src/main/scala/aqua/parser/Parser.scala b/parser/src/main/scala/aqua/parser/Parser.scala new file mode 100644 index 00000000..a6f4580f --- /dev/null +++ b/parser/src/main/scala/aqua/parser/Parser.scala @@ -0,0 +1,44 @@ +package aqua.parser + +import cats.data.{Validated, ValidatedNec} +import aqua.parser.Ast +import aqua.parser.ParserError +import aqua.parser.LexerError +import aqua.parser.expr.RootExpr +import aqua.parser.head.HeadExpr +import aqua.parser.lift.{FileSpan, LiftParser, Span} +import cats.{Comonad, Eval, ~>} +import cats.parse.LocationMap +import cats.parse.Parser0 as P0 +import cats.Id +import aqua.parser.lift.LiftParser.LiftErrorOps + + +object Parser { + + import Span.spanLiftParser + lazy val spanParser = parserSchema[Span.F]() + import LiftParser.Implicits.idLiftParser + lazy val idParser = parserSchema[Id]() + + def parserSchema[S[_] : LiftParser : Comonad](): P0[ValidatedNec[ParserError[S], Ast[S]]] = + (HeadExpr.ast[S].with1 ~ RootExpr.ast[S]()).map { case (head, bodyMaybe) => + bodyMaybe.map(Ast(head, _)) + } + + def parser[S[_] : LiftParser : Comonad](p: P0[ValidatedNec[ParserError[S], Ast[S]]])(source: String): ValidatedNec[ParserError[S], Ast[S]] = { + p.parseAll(source) match { + case Right(value) => value + case Left(e) => Validated.invalidNec(LexerError(e.wrapErr)) + } + } + + def natParser[S[_] : LiftParser : Comonad, K[_] : Comonad]( + p: P0[ValidatedNec[ParserError[S], Ast[S]]], + nat: S ~> K + )(source: String): ValidatedNec[ParserError[K], Ast[K]] = + parser[S](p)(source).bimap( + e => e.map(_.mapK(nat)), + ast => Ast[K](ast.head.map(_.mapK(nat)), ast.tree.map(_.mapK(nat))) + ) +} diff --git a/parser/src/main/scala/aqua/parser/ParserError.scala b/parser/src/main/scala/aqua/parser/ParserError.scala index 675395d6..056138a4 100644 --- a/parser/src/main/scala/aqua/parser/ParserError.scala +++ b/parser/src/main/scala/aqua/parser/ParserError.scala @@ -1,9 +1,20 @@ package aqua.parser import cats.parse.Parser +import cats.~> -trait ParserError[F[_]] +trait ParserError[F[_]] { + def mapK[K[_]](fk: F ~> K): ParserError[K] +} -case class LexerError[F[_]](err: F[Parser.Error]) extends ParserError[F] -case class BlockIndentError[F[_]](indent: F[String], message: String) extends ParserError[F] -case class FuncReturnError[F[_]](point: F[Unit], message: String) extends ParserError[F] +case class LexerError[F[_]](err: F[Parser.Error]) extends ParserError[F] { + def mapK[K[_]](fk: F ~> K): LexerError[K] = copy(fk(err)) +} +case class BlockIndentError[F[_]](indent: F[String], message: String) extends ParserError[F] { + def mapK[K[_]](fk: F ~> K): BlockIndentError[K] = + copy(fk(indent)) +} +case class FuncReturnError[F[_]](point: F[Unit], message: String) extends ParserError[F] { + def mapK[K[_]](fk: F ~> K): FuncReturnError[K] = + copy(fk(point)) +} diff --git a/parser/src/main/scala/aqua/parser/expr/AbilityIdExpr.scala b/parser/src/main/scala/aqua/parser/expr/AbilityIdExpr.scala index 4e30b743..52b7f9da 100644 --- a/parser/src/main/scala/aqua/parser/expr/AbilityIdExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/AbilityIdExpr.scala @@ -6,9 +6,15 @@ import aqua.parser.lexer.{Ability, Value} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.{Parser => P} +import cats.~> case class AbilityIdExpr[F[_]](ability: Ability[F], id: Value[F]) - extends Expr[F](AbilityIdExpr, ability) + extends Expr[F](AbilityIdExpr, ability) { + + def mapK[K[_]: Comonad](fk: F ~> K): AbilityIdExpr[K] = + copy(ability.copy(fk(ability.name)), id.mapK(fk)) + +} object AbilityIdExpr extends Expr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/expr/AliasExpr.scala b/parser/src/main/scala/aqua/parser/expr/AliasExpr.scala index 856ce3e3..51f8924a 100644 --- a/parser/src/main/scala/aqua/parser/expr/AliasExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/AliasExpr.scala @@ -6,9 +6,12 @@ import aqua.parser.lexer.{CustomTypeToken, TypeToken} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.Parser +import cats.~> case class AliasExpr[F[_]](name: CustomTypeToken[F], target: TypeToken[F]) - extends Expr[F](AliasExpr, name) + extends Expr[F](AliasExpr, name) { + def mapK[K[_]: Comonad](fk: F ~> K): AliasExpr[K] = copy(name.mapK(fk), target.mapK(fk)) +} object AliasExpr extends Expr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/expr/ArrowTypeExpr.scala b/parser/src/main/scala/aqua/parser/expr/ArrowTypeExpr.scala index 43de300a..3c315132 100644 --- a/parser/src/main/scala/aqua/parser/expr/ArrowTypeExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/ArrowTypeExpr.scala @@ -6,9 +6,12 @@ import aqua.parser.lexer.{ArrowTypeToken, DataTypeToken, Name} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.Parser +import cats.~> case class ArrowTypeExpr[F[_]](name: Name[F], `type`: ArrowTypeToken[F]) - extends Expr[F](ArrowTypeExpr, name) + extends Expr[F](ArrowTypeExpr, name) { + def mapK[K[_]: Comonad](fk: F ~> K): ArrowTypeExpr[K] = copy(name.mapK(fk), `type`.mapK(fk)) +} object ArrowTypeExpr extends Expr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/expr/AssignmentExpr.scala b/parser/src/main/scala/aqua/parser/expr/AssignmentExpr.scala index 8e799d94..d05422d7 100644 --- a/parser/src/main/scala/aqua/parser/expr/AssignmentExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/AssignmentExpr.scala @@ -6,11 +6,14 @@ import aqua.parser.lexer.{Name, Value} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.{Parser => P} +import cats.~> case class AssignmentExpr[F[_]]( variable: Name[F], value: Value[F] -) extends Expr[F](AssignmentExpr, variable) +) extends Expr[F](AssignmentExpr, variable) { + def mapK[K[_]: Comonad](fk: F ~> K): AssignmentExpr[K] = copy(variable.mapK(fk), value.mapK(fk)) +} object AssignmentExpr extends Expr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/expr/CallArrowExpr.scala b/parser/src/main/scala/aqua/parser/expr/CallArrowExpr.scala index 28e88485..cc2faa6c 100644 --- a/parser/src/main/scala/aqua/parser/expr/CallArrowExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/CallArrowExpr.scala @@ -6,13 +6,23 @@ import aqua.parser.lexer.{Ability, Name, Value} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.{Parser => P} +import cats.~> case class CallArrowExpr[F[_]]( variables: List[Name[F]], ability: Option[Ability[F]], funcName: Name[F], args: List[Value[F]] -) extends Expr[F](CallArrowExpr, funcName) +) extends Expr[F](CallArrowExpr, funcName) { + + def mapK[K[_]: Comonad](fk: F ~> K): CallArrowExpr[K] = + copy( + variables.map(_.mapK(fk)), + ability.map(_.mapK(fk)), + funcName.mapK(fk), + args.map(_.mapK(fk)) + ) +} object CallArrowExpr extends Expr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/expr/CatchExpr.scala b/parser/src/main/scala/aqua/parser/expr/CatchExpr.scala index 7441b73e..34816866 100644 --- a/parser/src/main/scala/aqua/parser/expr/CatchExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/CatchExpr.scala @@ -6,8 +6,11 @@ import aqua.parser.lexer.Token._ import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.Parser +import cats.~> -case class CatchExpr[F[_]](name: Name[F]) extends Expr[F](CatchExpr, name) +case class CatchExpr[F[_]](name: Name[F]) extends Expr[F](CatchExpr, name) { + def mapK[K[_]: Comonad](fk: F ~> K): CatchExpr[K] = copy(name.mapK(fk)) +} object CatchExpr extends Expr.AndIndented { diff --git a/parser/src/main/scala/aqua/parser/expr/CoExpr.scala b/parser/src/main/scala/aqua/parser/expr/CoExpr.scala index 6b79e292..2014c366 100644 --- a/parser/src/main/scala/aqua/parser/expr/CoExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/CoExpr.scala @@ -7,8 +7,11 @@ import aqua.parser.lift.LiftParser._ import cats.Comonad import cats.parse.Parser import Token.`co` +import cats.~> -case class CoExpr[F[_]](point: Token[F]) extends Expr[F](CoExpr, point) +case class CoExpr[F[_]](point: Token[F]) extends Expr[F](CoExpr, point) { + def mapK[K[_]: Comonad](fk: F ~> K): CoExpr[K] = copy(point.mapK(fk)) +} object CoExpr extends Expr.Prefix { override def continueWith: List[Expr.Lexem] = ParExpr.continueWith diff --git a/parser/src/main/scala/aqua/parser/expr/ConstantExpr.scala b/parser/src/main/scala/aqua/parser/expr/ConstantExpr.scala index c1bb7f78..dc1ed97b 100644 --- a/parser/src/main/scala/aqua/parser/expr/ConstantExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/ConstantExpr.scala @@ -6,12 +6,17 @@ import aqua.parser.lexer.{Literal, Name, Value} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.{Parser => P} +import cats.~> case class ConstantExpr[F[_]]( name: Name[F], value: Value[F], skipIfAlreadyDefined: Boolean -) extends Expr[F](ConstantExpr, name) +) extends Expr[F](ConstantExpr, name) { + + def mapK[K[_]: Comonad](fk: F ~> K): ConstantExpr[K] = + copy(name.mapK(fk), value.mapK(fk), skipIfAlreadyDefined) +} object ConstantExpr extends Expr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/expr/DataStructExpr.scala b/parser/src/main/scala/aqua/parser/expr/DataStructExpr.scala index 63143fad..50531056 100644 --- a/parser/src/main/scala/aqua/parser/expr/DataStructExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/DataStructExpr.scala @@ -2,12 +2,15 @@ package aqua.parser.expr import aqua.parser.Expr import aqua.parser.lexer.CustomTypeToken -import aqua.parser.lexer.Token._ +import aqua.parser.lexer.Token.* import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.Parser +import cats.~> -case class DataStructExpr[F[_]](name: CustomTypeToken[F]) extends Expr[F](DataStructExpr, name) +case class DataStructExpr[F[_]](name: CustomTypeToken[F]) extends Expr[F](DataStructExpr, name) { + override def mapK[K[_]: Comonad](fk: F ~> K): DataStructExpr[K] = copy(name.mapK(fk)) +} object DataStructExpr extends Expr.AndIndented { diff --git a/parser/src/main/scala/aqua/parser/expr/DeclareStreamExpr.scala b/parser/src/main/scala/aqua/parser/expr/DeclareStreamExpr.scala index 32205be6..bec23d4b 100644 --- a/parser/src/main/scala/aqua/parser/expr/DeclareStreamExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/DeclareStreamExpr.scala @@ -6,9 +6,14 @@ import aqua.parser.lexer.{Name, Token, TypeToken} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.Parser +import cats.~> case class DeclareStreamExpr[F[_]](name: Name[F], `type`: TypeToken[F]) - extends Expr[F](DeclareStreamExpr, name) + extends Expr[F](DeclareStreamExpr, name) { + + override def mapK[K[_]: Comonad](fk: F ~> K): DeclareStreamExpr[K] = + copy(name.mapK(fk), `type`.mapK(fk)) +} object DeclareStreamExpr extends Expr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/expr/ElseOtherwiseExpr.scala b/parser/src/main/scala/aqua/parser/expr/ElseOtherwiseExpr.scala index 3c4afeb5..b0cdb598 100644 --- a/parser/src/main/scala/aqua/parser/expr/ElseOtherwiseExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/ElseOtherwiseExpr.scala @@ -7,8 +7,11 @@ import aqua.parser.lift.LiftParser import aqua.parser.lift.LiftParser._ import cats.Comonad import cats.parse.Parser +import cats.~> -case class ElseOtherwiseExpr[F[_]](point: Token[F]) extends Expr[F](ElseOtherwiseExpr, point) +case class ElseOtherwiseExpr[F[_]](point: Token[F]) extends Expr[F](ElseOtherwiseExpr, point) { + override def mapK[K[_]: Comonad](fk: F ~> K): ElseOtherwiseExpr[K] = copy(point.mapK(fk)) +} object ElseOtherwiseExpr extends Expr.AndIndented { diff --git a/parser/src/main/scala/aqua/parser/expr/FieldTypeExpr.scala b/parser/src/main/scala/aqua/parser/expr/FieldTypeExpr.scala index e9886112..c4b355fe 100644 --- a/parser/src/main/scala/aqua/parser/expr/FieldTypeExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/FieldTypeExpr.scala @@ -6,9 +6,14 @@ import aqua.parser.lexer.{DataTypeToken, Name} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.Parser +import cats.~> case class FieldTypeExpr[F[_]](name: Name[F], `type`: DataTypeToken[F]) - extends Expr[F](FieldTypeExpr, name) + extends Expr[F](FieldTypeExpr, name) { + + override def mapK[K[_]: Comonad](fk: F ~> K): FieldTypeExpr[K] = + copy(name.mapK(fk), `type`.mapK(fk)) +} object FieldTypeExpr extends Expr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/expr/ForExpr.scala b/parser/src/main/scala/aqua/parser/expr/ForExpr.scala index 01424967..7d11de2d 100644 --- a/parser/src/main/scala/aqua/parser/expr/ForExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/ForExpr.scala @@ -8,12 +8,17 @@ import aqua.parser.lift.LiftParser._ import cats.Comonad import cats.parse.{Parser => P} import cats.syntax.comonad._ +import cats.~> case class ForExpr[F[_]]( item: Name[F], iterable: Value[F], mode: Option[(F[ForExpr.Mode], ForExpr.Mode)] -) extends Expr[F](ForExpr, item) +) extends Expr[F](ForExpr, item) { + + override def mapK[K[_]: Comonad](fk: F ~> K): ForExpr[K] = + copy(item.mapK(fk), iterable.mapK(fk), mode.map { case (mF, m) => (fk(mF), m) }) +} object ForExpr extends Expr.AndIndented { sealed trait Mode diff --git a/parser/src/main/scala/aqua/parser/expr/FuncExpr.scala b/parser/src/main/scala/aqua/parser/expr/FuncExpr.scala index d8f1abf9..e30722c9 100644 --- a/parser/src/main/scala/aqua/parser/expr/FuncExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/FuncExpr.scala @@ -8,6 +8,7 @@ import cats.Comonad import cats.data.{Validated, ValidatedNec} import cats.free.Cofree import cats.parse.Parser +import cats.~> case class FuncExpr[F[_]]( name: Name[F], @@ -15,6 +16,9 @@ case class FuncExpr[F[_]]( retValue: List[Value[F]] ) extends Expr[F](FuncExpr, name) { def ret = arrowTypeExpr.res + + override def mapK[K[_]: Comonad](fk: F ~> K): FuncExpr[K] = + copy(name.mapK(fk), arrowTypeExpr.mapK(fk), retValue.map(_.mapK(fk))) } object FuncExpr extends Expr.AndIndented { diff --git a/parser/src/main/scala/aqua/parser/expr/IfExpr.scala b/parser/src/main/scala/aqua/parser/expr/IfExpr.scala index d7b669f0..ec66ae15 100644 --- a/parser/src/main/scala/aqua/parser/expr/IfExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/IfExpr.scala @@ -7,9 +7,13 @@ import aqua.parser.lift.LiftParser import aqua.types.LiteralType import cats.Comonad import cats.parse.{Parser => P} +import cats.~> case class IfExpr[F[_]](left: Value[F], eqOp: EqOp[F], right: Value[F]) - extends Expr[F](IfExpr, eqOp) + extends Expr[F](IfExpr, eqOp) { + override def mapK[K[_]: Comonad](fk: F ~> K): IfExpr[K] = + copy(left.mapK(fk), eqOp.mapK(fk), right.mapK(fk)) +} object IfExpr extends Expr.AndIndented { diff --git a/parser/src/main/scala/aqua/parser/expr/OnExpr.scala b/parser/src/main/scala/aqua/parser/expr/OnExpr.scala index a4038469..6113c0fe 100644 --- a/parser/src/main/scala/aqua/parser/expr/OnExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/OnExpr.scala @@ -6,8 +6,13 @@ import aqua.parser.lexer.Value import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.{Parser => P} +import cats.~> -case class OnExpr[F[_]](peerId: Value[F], via: List[Value[F]]) extends Expr[F](OnExpr, peerId) +case class OnExpr[F[_]](peerId: Value[F], via: List[Value[F]]) extends Expr[F](OnExpr, peerId) { + + override def mapK[K[_]: Comonad](fk: F ~> K): OnExpr[K] = + copy(peerId.mapK(fk), via.map(_.mapK(fk))) +} object OnExpr extends Expr.AndIndented { diff --git a/parser/src/main/scala/aqua/parser/expr/ParExpr.scala b/parser/src/main/scala/aqua/parser/expr/ParExpr.scala index ddc12d2e..fe9d0436 100644 --- a/parser/src/main/scala/aqua/parser/expr/ParExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/ParExpr.scala @@ -7,8 +7,13 @@ import cats.parse.Parser import aqua.parser.lexer.Token._ import aqua.parser.lift.LiftParser import aqua.parser.lift.LiftParser._ +import cats.~> -case class ParExpr[F[_]](point: Token[F]) extends Expr[F](ParExpr, point) +case class ParExpr[F[_]](point: Token[F]) extends Expr[F](ParExpr, point) { + + override def mapK[K[_]: Comonad](fk: F ~> K): ParExpr[K] = + copy(point.mapK(fk)) +} object ParExpr extends Expr.Prefix { override def continueWith: List[Expr.Lexem] = CallArrowExpr :: OnExpr :: ForExpr :: Nil diff --git a/parser/src/main/scala/aqua/parser/expr/PushToStreamExpr.scala b/parser/src/main/scala/aqua/parser/expr/PushToStreamExpr.scala index f27e6677..97c98fbb 100644 --- a/parser/src/main/scala/aqua/parser/expr/PushToStreamExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/PushToStreamExpr.scala @@ -6,11 +6,16 @@ import aqua.parser.lexer.{Name, Value} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.{Parser => P} +import cats.~> case class PushToStreamExpr[F[_]]( stream: Name[F], value: Value[F] -) extends Expr[F](PushToStreamExpr, stream) +) extends Expr[F](PushToStreamExpr, stream) { + + override def mapK[K[_]: Comonad](fk: F ~> K): PushToStreamExpr[K] = + copy(stream.mapK(fk), value.mapK(fk)) +} object PushToStreamExpr extends Expr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/expr/ReturnExpr.scala b/parser/src/main/scala/aqua/parser/expr/ReturnExpr.scala index 06256a8f..ae190829 100644 --- a/parser/src/main/scala/aqua/parser/expr/ReturnExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/ReturnExpr.scala @@ -7,8 +7,14 @@ import aqua.parser.lift.LiftParser import cats.Comonad import cats.data.NonEmptyList import cats.parse.Parser +import cats.~> -case class ReturnExpr[F[_]](values: NonEmptyList[Value[F]]) extends Expr[F](ReturnExpr, values.head) +case class ReturnExpr[F[_]](values: NonEmptyList[Value[F]]) + extends Expr[F](ReturnExpr, values.head) { + + override def mapK[K[_]: Comonad](fk: F ~> K): ReturnExpr[K] = + copy(values.map(_.mapK(fk))) +} object ReturnExpr extends Expr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/expr/RootExpr.scala b/parser/src/main/scala/aqua/parser/expr/RootExpr.scala index 2d4f4d3c..d1c0d664 100644 --- a/parser/src/main/scala/aqua/parser/expr/RootExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/RootExpr.scala @@ -10,8 +10,13 @@ import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec} import cats.free.Cofree import cats.parse.{Parser => P} import cats.{Comonad, Eval} +import cats.~> -case class RootExpr[F[_]](point: Token[F]) extends Expr[F](RootExpr, point) +case class RootExpr[F[_]](point: Token[F]) extends Expr[F](RootExpr, point) { + + override def mapK[K[_]: Comonad](fk: F ~> K): RootExpr[K] = + copy(point.mapK(fk)) +} object RootExpr extends Expr.Companion { diff --git a/parser/src/main/scala/aqua/parser/expr/ServiceExpr.scala b/parser/src/main/scala/aqua/parser/expr/ServiceExpr.scala index e467f705..1fb41be4 100644 --- a/parser/src/main/scala/aqua/parser/expr/ServiceExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/ServiceExpr.scala @@ -6,9 +6,14 @@ import aqua.parser.lexer.{Ability, Value} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.Parser +import cats.~> case class ServiceExpr[F[_]](name: Ability[F], id: Option[Value[F]]) - extends Expr[F](ServiceExpr, name) + extends Expr[F](ServiceExpr, name) { + + override def mapK[K[_]: Comonad](fk: F ~> K): ServiceExpr[K] = + copy(name.mapK(fk), id.map(_.mapK(fk))) +} object ServiceExpr extends Expr.AndIndented { diff --git a/parser/src/main/scala/aqua/parser/expr/TryExpr.scala b/parser/src/main/scala/aqua/parser/expr/TryExpr.scala index afdf8d4d..4d3dc158 100644 --- a/parser/src/main/scala/aqua/parser/expr/TryExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/TryExpr.scala @@ -7,8 +7,13 @@ import aqua.parser.lift.LiftParser import aqua.parser.lift.LiftParser._ import cats.Comonad import cats.parse.{Parser => P} +import cats.~> -case class TryExpr[F[_]](point: Token[F]) extends Expr[F](TryExpr, point) +case class TryExpr[F[_]](point: Token[F]) extends Expr[F](TryExpr, point) { + + override def mapK[K[_]: Comonad](fk: F ~> K): TryExpr[K] = + copy(point.mapK(fk)) +} object TryExpr extends Expr.AndIndented { diff --git a/parser/src/main/scala/aqua/parser/head/ExportExpr.scala b/parser/src/main/scala/aqua/parser/head/ExportExpr.scala index 637d15b3..f653a71d 100644 --- a/parser/src/main/scala/aqua/parser/head/ExportExpr.scala +++ b/parser/src/main/scala/aqua/parser/head/ExportExpr.scala @@ -7,10 +7,14 @@ import cats.Comonad import cats.data.NonEmptyList import cats.parse.Parser import cats.syntax.either.* +import cats.~> case class ExportExpr[F[_]](pubs: NonEmptyList[FromExpr.NameOrAbAs[F]]) extends HeaderExpr[F] { override def token: Token[F] = pubs.head.bimap(_._1, _._1).fold(identity, identity) + + override def mapK[K[_]: Comonad](fk: F ~> K): ExportExpr[K] = + copy(FromExpr.mapK(pubs)(fk)) } object ExportExpr extends HeaderExpr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/head/FilenameExpr.scala b/parser/src/main/scala/aqua/parser/head/FilenameExpr.scala index 370268c7..a9b750db 100644 --- a/parser/src/main/scala/aqua/parser/head/FilenameExpr.scala +++ b/parser/src/main/scala/aqua/parser/head/FilenameExpr.scala @@ -1,6 +1,8 @@ package aqua.parser.head import aqua.parser.lexer.{Literal, Token} +import cats.Comonad +import cats.~> trait FilenameExpr[F[_]] extends HeaderExpr[F] { def filename: Literal[F] @@ -8,4 +10,7 @@ trait FilenameExpr[F[_]] extends HeaderExpr[F] { override def token: Token[F] = filename def fileValue: String = filename.value.drop(1).dropRight(1) + + override def mapK[K[_]: Comonad](fk: F ~> K): FilenameExpr[K] + } diff --git a/parser/src/main/scala/aqua/parser/head/FromExpr.scala b/parser/src/main/scala/aqua/parser/head/FromExpr.scala index 5feea1f4..a1ec63b2 100644 --- a/parser/src/main/scala/aqua/parser/head/FromExpr.scala +++ b/parser/src/main/scala/aqua/parser/head/FromExpr.scala @@ -6,12 +6,20 @@ import aqua.parser.lift.LiftParser import cats.Comonad import cats.data.NonEmptyList import cats.parse.Parser as P +import cats.~> trait FromExpr[F[_]] { def imports: NonEmptyList[FromExpr.NameOrAbAs[F]] } object FromExpr { + + def mapK[F[_], K[_]: Comonad](imports: NonEmptyList[FromExpr.NameOrAbAs[F]])(fk: F ~> K): NonEmptyList[FromExpr.NameOrAbAs[K]] = + imports.map { + case Left((n, nOp)) => Left((n.mapK(fk), nOp.map(_.mapK(fk)))) + case Right(a, aOp) => Right((a.mapK(fk), aOp.map(_.mapK(fk)))) + } + type NameOrAbAs[F[_]] = Either[Name.As[F], Ability.As[F]] def nameOrAbAs[F[_]: LiftParser: Comonad]: P[NameOrAbAs[F]] = diff --git a/parser/src/main/scala/aqua/parser/head/HeadExpr.scala b/parser/src/main/scala/aqua/parser/head/HeadExpr.scala index 6794e3dc..6077b8e8 100644 --- a/parser/src/main/scala/aqua/parser/head/HeadExpr.scala +++ b/parser/src/main/scala/aqua/parser/head/HeadExpr.scala @@ -9,8 +9,13 @@ import cats.data.Chain import cats.free.Cofree import cats.parse.{Parser => P, Parser0 => P0} import aqua.parser.lexer.Token +import cats.~> -case class HeadExpr[S[_]](token: Token[S]) extends HeaderExpr[S] +case class HeadExpr[S[_]](token: Token[S]) extends HeaderExpr[S] { + + def mapK[K[_]: Comonad](fk: S ~> K): HeadExpr[K] = + copy(token.mapK(fk)) +} object HeadExpr { diff --git a/parser/src/main/scala/aqua/parser/head/HeaderExpr.scala b/parser/src/main/scala/aqua/parser/head/HeaderExpr.scala index cf00bba4..86b5eeae 100644 --- a/parser/src/main/scala/aqua/parser/head/HeaderExpr.scala +++ b/parser/src/main/scala/aqua/parser/head/HeaderExpr.scala @@ -7,9 +7,12 @@ import cats.{Comonad, Eval} import cats.data.Chain import cats.free.Cofree import cats.parse.Parser as P +import cats.~> trait HeaderExpr[S[_]] { def token: Token[S] + + def mapK[K[_]: Comonad](fk: S ~> K): HeaderExpr[K] } object HeaderExpr { diff --git a/parser/src/main/scala/aqua/parser/head/ImportExpr.scala b/parser/src/main/scala/aqua/parser/head/ImportExpr.scala index e6896957..1c00aa47 100644 --- a/parser/src/main/scala/aqua/parser/head/ImportExpr.scala +++ b/parser/src/main/scala/aqua/parser/head/ImportExpr.scala @@ -5,8 +5,12 @@ import aqua.parser.lexer.{Literal, Value} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.Parser +import cats.~> -case class ImportExpr[F[_]](filename: Literal[F]) extends FilenameExpr[F] +case class ImportExpr[F[_]](filename: Literal[F]) extends FilenameExpr[F] { + override def mapK[K[_]: Comonad](fk: F ~> K): ImportExpr[K] = + copy(filename.mapK(fk)) +} object ImportExpr extends HeaderExpr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/head/ImportFromExpr.scala b/parser/src/main/scala/aqua/parser/head/ImportFromExpr.scala index 677fdb8c..a0e84987 100644 --- a/parser/src/main/scala/aqua/parser/head/ImportFromExpr.scala +++ b/parser/src/main/scala/aqua/parser/head/ImportFromExpr.scala @@ -6,11 +6,15 @@ import aqua.parser.lift.LiftParser import cats.Comonad import cats.data.NonEmptyList import cats.parse.Parser +import cats.~> case class ImportFromExpr[F[_]]( imports: NonEmptyList[FromExpr.NameOrAbAs[F]], filename: Literal[F] -) extends FilenameExpr[F] with FromExpr[F] +) extends FilenameExpr[F] with FromExpr[F] { + override def mapK[K[_]: Comonad](fk: F ~> K): ImportFromExpr[K] = + copy(FromExpr.mapK(imports)(fk), filename.mapK(fk)) +} object ImportFromExpr extends HeaderExpr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/head/ModuleExpr.scala b/parser/src/main/scala/aqua/parser/head/ModuleExpr.scala index 2d6734d2..554644a8 100644 --- a/parser/src/main/scala/aqua/parser/head/ModuleExpr.scala +++ b/parser/src/main/scala/aqua/parser/head/ModuleExpr.scala @@ -7,6 +7,7 @@ import aqua.parser.lift.LiftParser import aqua.parser.lift.LiftParser.* import cats.Comonad import cats.parse.Parser +import cats.~> case class ModuleExpr[F[_]]( name: Ability[F], @@ -15,6 +16,14 @@ case class ModuleExpr[F[_]]( declareCustom: List[Ability[F]] ) extends HeaderExpr[F] { override def token: Token[F] = name + + override def mapK[K[_]: Comonad](fk: F ~> K): ModuleExpr[K] = + copy( + name.mapK(fk), + declareAll.map(_.mapK(fk)), + declareNames.map(_.mapK(fk)), + declareCustom.map(_.mapK(fk)) + ) } object ModuleExpr extends HeaderExpr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/head/UseExpr.scala b/parser/src/main/scala/aqua/parser/head/UseExpr.scala index 33b58c39..a7f44aaf 100644 --- a/parser/src/main/scala/aqua/parser/head/UseExpr.scala +++ b/parser/src/main/scala/aqua/parser/head/UseExpr.scala @@ -5,11 +5,15 @@ import aqua.parser.lexer.{Ability, Literal, Value} import aqua.parser.lift.LiftParser import cats.Comonad import cats.parse.Parser +import cats.~> case class UseExpr[F[_]]( filename: Literal[F], asModule: Option[Ability[F]] -) extends FilenameExpr[F] +) extends FilenameExpr[F] { + override def mapK[K[_]: Comonad](fk: F ~> K): UseExpr[K] = + copy(filename.mapK(fk), asModule.map(_.mapK(fk))) +} object UseExpr extends HeaderExpr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/head/UseFromExpr.scala b/parser/src/main/scala/aqua/parser/head/UseFromExpr.scala index 816676dd..fa8a1db0 100644 --- a/parser/src/main/scala/aqua/parser/head/UseFromExpr.scala +++ b/parser/src/main/scala/aqua/parser/head/UseFromExpr.scala @@ -6,12 +6,17 @@ import aqua.parser.lift.LiftParser import cats.Comonad import cats.data.NonEmptyList import cats.parse.Parser +import cats.~> case class UseFromExpr[F[_]]( imports: NonEmptyList[FromExpr.NameOrAbAs[F]], filename: Literal[F], asModule: Ability[F] -) extends FilenameExpr[F] with FromExpr[F] +) extends FilenameExpr[F] with FromExpr[F] { + + override def mapK[K[_]: Comonad](fk: F ~> K): UseFromExpr[K] = + copy(FromExpr.mapK(imports)(fk), filename.mapK(fk), asModule.mapK(fk)) +} object UseFromExpr extends HeaderExpr.Leaf { diff --git a/parser/src/main/scala/aqua/parser/lexer/Ability.scala b/parser/src/main/scala/aqua/parser/lexer/Ability.scala index faf5cbaa..445bfdf7 100644 --- a/parser/src/main/scala/aqua/parser/lexer/Ability.scala +++ b/parser/src/main/scala/aqua/parser/lexer/Ability.scala @@ -7,10 +7,13 @@ import cats.Comonad import cats.parse.{Parser => P} import cats.syntax.functor._ import cats.syntax.comonad._ +import cats.~> case class Ability[F[_]: Comonad](name: F[String]) extends Token[F] { override def as[T](v: T): F[T] = name.as(v) + def mapK[K[_]: Comonad](fk: F ~> K): Ability[K] = copy(fk(name)) + def value: String = name.extract } diff --git a/parser/src/main/scala/aqua/parser/lexer/EqOp.scala b/parser/src/main/scala/aqua/parser/lexer/EqOp.scala index b7f56823..52847341 100644 --- a/parser/src/main/scala/aqua/parser/lexer/EqOp.scala +++ b/parser/src/main/scala/aqua/parser/lexer/EqOp.scala @@ -7,10 +7,14 @@ import Token._ import cats.parse.{Parser => P} import LiftParser._ import cats.syntax.comonad._ +import cats.~> case class EqOp[F[_]: Comonad](eq: F[Boolean]) extends Token[F] { override def as[T](v: T): F[T] = eq.as(v) + override def mapK[K[_]: Comonad](fk: F ~> K): EqOp[K] = + copy(fk(eq)) + def value: Boolean = eq.extract } diff --git a/parser/src/main/scala/aqua/parser/lexer/LambdaOp.scala b/parser/src/main/scala/aqua/parser/lexer/LambdaOp.scala index 3090128a..afb70709 100644 --- a/parser/src/main/scala/aqua/parser/lexer/LambdaOp.scala +++ b/parser/src/main/scala/aqua/parser/lexer/LambdaOp.scala @@ -9,23 +9,32 @@ import cats.syntax.comonad.* import cats.syntax.functor.* import cats.{Comonad, Functor} import scala.language.postfixOps +import cats.~> -sealed trait LambdaOp[F[_]] extends Token[F] +sealed trait LambdaOp[F[_]] extends Token[F] { + def mapK[K[_]: Comonad](fk: F ~> K): LambdaOp[K] +} case class IntoField[F[_]: Comonad](name: F[String]) extends LambdaOp[F] { override def as[T](v: T): F[T] = name.as(v) + override def mapK[K[_]: Comonad](fk: F ~> K): LambdaOp[K] = copy(fk(name)) + def value: String = name.extract } case class IntoIndex[F[_]: Comonad](idx: F[Int]) extends LambdaOp[F] { override def as[T](v: T): F[T] = idx.as(v) + override def mapK[K[_]: Comonad](fk: F ~> K): IntoIndex[K] = copy(fk(idx)) + def value: Int = idx.extract } case class IntoArray[F[_]: Functor](override val unit: F[Unit]) extends LambdaOp[F] { override def as[T](v: T): F[T] = unit.as(v) + + override def mapK[K[_]: Comonad](fk: F ~> K): IntoArray[K] = copy(fk(unit)) } object LambdaOp { diff --git a/parser/src/main/scala/aqua/parser/lexer/Name.scala b/parser/src/main/scala/aqua/parser/lexer/Name.scala index 87843cd6..b12bd851 100644 --- a/parser/src/main/scala/aqua/parser/lexer/Name.scala +++ b/parser/src/main/scala/aqua/parser/lexer/Name.scala @@ -7,10 +7,13 @@ import cats.Comonad import cats.parse.{Parser => P} import cats.syntax.functor._ import cats.syntax.comonad._ +import cats.~> case class Name[F[_]: Comonad](name: F[String]) extends Token[F] { override def as[T](v: T): F[T] = name.as(v) + override def mapK[K[_]: Comonad](fk: F ~> K): Name[K] = copy(fk(name)) + def value: String = name.extract } diff --git a/parser/src/main/scala/aqua/parser/lexer/Token.scala b/parser/src/main/scala/aqua/parser/lexer/Token.scala index da94f69d..82964ea2 100644 --- a/parser/src/main/scala/aqua/parser/lexer/Token.scala +++ b/parser/src/main/scala/aqua/parser/lexer/Token.scala @@ -1,12 +1,15 @@ package aqua.parser.lexer -import cats.Functor +import cats.{Comonad, Functor} import cats.data.NonEmptyList -import cats.parse.{Accumulator0, Parser => P, Parser0 => P0} +import cats.parse.{Accumulator0, Parser as P, Parser0 as P0} +import cats.~> trait Token[F[_]] { def as[T](v: T): F[T] + def mapK[K[_]: Comonad](fk: F ~> K): Token[K] + def unit: F[Unit] = as(()) } @@ -92,6 +95,8 @@ object Token { case class LiftToken[F[_]: Functor, A](point: F[A]) extends Token[F] { override def as[T](v: T): F[T] = Functor[F].as(point, v) + override def mapK[K[_]: Comonad](fk: F ~> K): LiftToken[K, A] = + copy(fk(point)) } def lift[F[_]: Functor, A](point: F[A]): Token[F] = LiftToken(point) diff --git a/parser/src/main/scala/aqua/parser/lexer/TypeToken.scala b/parser/src/main/scala/aqua/parser/lexer/TypeToken.scala index b83a557b..562ad35c 100644 --- a/parser/src/main/scala/aqua/parser/lexer/TypeToken.scala +++ b/parser/src/main/scala/aqua/parser/lexer/TypeToken.scala @@ -8,24 +8,33 @@ import cats.Comonad import cats.parse.{Parser => P} import cats.syntax.comonad._ import cats.syntax.functor._ +import cats.~> -sealed trait TypeToken[F[_]] extends Token[F] -sealed trait DataTypeToken[F[_]] extends TypeToken[F] +sealed trait TypeToken[F[_]] extends Token[F] { + def mapK[K[_]: Comonad](fk: F ~> K): TypeToken[K] +} + +sealed trait DataTypeToken[F[_]] extends TypeToken[F] { + override def mapK[K[_]: Comonad](fk: F ~> K): DataTypeToken[K] +} case class TopBottomToken[F[_]: Comonad](override val unit: F[Unit], isTop: Boolean) extends DataTypeToken[F] { override def as[T](v: T): F[T] = unit.as(v) def isBottom: Boolean = !isTop + override def mapK[K[_]: Comonad](fk: F ~> K): TopBottomToken[K] = copy(fk(unit), isTop) } case class ArrayTypeToken[F[_]: Comonad](override val unit: F[Unit], data: DataTypeToken[F]) extends DataTypeToken[F] { override def as[T](v: T): F[T] = unit.as(v) + override def mapK[K[_]: Comonad](fk: F ~> K): ArrayTypeToken[K] = copy(fk(unit), data.mapK(fk)) } case class StreamTypeToken[F[_]: Comonad](override val unit: F[Unit], data: DataTypeToken[F]) extends DataTypeToken[F] { override def as[T](v: T): F[T] = unit.as(v) + override def mapK[K[_]: Comonad](fk: F ~> K): StreamTypeToken[K] = copy(fk(unit), data.mapK(fk)) } object StreamTypeToken { @@ -38,6 +47,9 @@ object StreamTypeToken { case class OptionTypeToken[F[_]: Comonad](override val unit: F[Unit], data: DataTypeToken[F]) extends DataTypeToken[F] { override def as[T](v: T): F[T] = unit.as(v) + + override def mapK[K[_]: Comonad](fk: F ~> K): OptionTypeToken[K] = + copy(fk(unit), data.mapK(fk)) } object OptionTypeToken { @@ -50,6 +62,8 @@ object OptionTypeToken { case class CustomTypeToken[F[_]: Comonad](name: F[String]) extends DataTypeToken[F] { override def as[T](v: T): F[T] = name.as(v) + override def mapK[K[_]: Comonad](fk: F ~> K): CustomTypeToken[K] = copy(fk(name)) + def value: String = name.extract } @@ -65,6 +79,8 @@ object CustomTypeToken { case class BasicTypeToken[F[_]: Comonad](scalarType: F[ScalarType]) extends DataTypeToken[F] { override def as[T](v: T): F[T] = scalarType.as(v) + override def mapK[K[_]: Comonad](fk: F ~> K): BasicTypeToken[K] = + copy(fk(scalarType)) def value: ScalarType = scalarType.extract } @@ -84,6 +100,12 @@ case class ArrowTypeToken[F[_]: Comonad]( ) extends TypeToken[F] { override def as[T](v: T): F[T] = unit.as(v) + override def mapK[K[_]: Comonad](fk: F ~> K): ArrowTypeToken[K] = + copy( + fk(unit), + args.map { case (n, t) => (n.map(_.mapK(fk)), t.mapK(fk)) }, + res.map(_.mapK(fk)) + ) def argTypes: List[TypeToken[F]] = args.map(_._2) } diff --git a/parser/src/main/scala/aqua/parser/lexer/Value.scala b/parser/src/main/scala/aqua/parser/lexer/Value.scala index 5d0b14e5..a60e02dc 100644 --- a/parser/src/main/scala/aqua/parser/lexer/Value.scala +++ b/parser/src/main/scala/aqua/parser/lexer/Value.scala @@ -1,23 +1,31 @@ package aqua.parser.lexer -import aqua.parser.lexer.Token._ +import aqua.parser.Expr +import aqua.parser.lexer.Token.* import aqua.parser.lift.LiftParser -import aqua.parser.lift.LiftParser._ +import aqua.parser.lift.LiftParser.* import aqua.types.LiteralType -import cats.parse.{Numbers, Parser => P} -import cats.syntax.comonad._ -import cats.syntax.functor._ +import cats.parse.{Numbers, Parser as P} +import cats.syntax.comonad.* +import cats.syntax.functor.* import cats.{Comonad, Functor} +import cats.~> -sealed trait Value[F[_]] extends Token[F] +sealed trait Value[F[_]] extends Token[F] { + def mapK[K[_]: Comonad](fk: F ~> K): Value[K] +} case class VarLambda[F[_]](name: Name[F], lambda: List[LambdaOp[F]] = Nil) extends Value[F] { override def as[T](v: T): F[T] = name.as(v) + + def mapK[K[_]: Comonad](fk: F ~> K): VarLambda[K] = copy(name.mapK(fk), lambda.map(_.mapK(fk))) } case class Literal[F[_]: Comonad](valueToken: F[String], ts: LiteralType) extends Value[F] { override def as[T](v: T): F[T] = valueToken.as(v) + def mapK[K[_]: Comonad](fk: F ~> K): Literal[K] = copy(fk(valueToken), ts) + def value: String = valueToken.extract } diff --git a/parser/src/test/scala/aqua/parser/FuncExprSpec.scala b/parser/src/test/scala/aqua/parser/FuncExprSpec.scala index f95adf69..f1b75656 100644 --- a/parser/src/test/scala/aqua/parser/FuncExprSpec.scala +++ b/parser/src/test/scala/aqua/parser/FuncExprSpec.scala @@ -1,7 +1,7 @@ package aqua.parser import aqua.AquaSpec -import aqua.parser.Ast.parser + import aqua.parser.expr.* import aqua.parser.lexer.{ArrowTypeToken, BasicTypeToken, EqOp, Literal, Token, VarLambda} import aqua.parser.lift.LiftParser.Implicits.idLiftParser @@ -19,6 +19,8 @@ import scala.language.implicitConversions class FuncExprSpec extends AnyFlatSpec with Matchers with AquaSpec { import AquaSpec._ + val parser = Parser.idParser + "func header" should "parse" in { funcExpr("func some() -> bool") should be( FuncExpr("some", toNamedArrow(Nil, List(bool: BasicTypeToken[Id])), Nil) @@ -113,7 +115,7 @@ class FuncExprSpec extends AnyFlatSpec with Matchers with AquaSpec { | <- v |""".stripMargin - parser[Id]().parseAll(script).value.toEither.isLeft shouldBe true + parser.parseAll(script).value.toEither.isLeft shouldBe true } "function with multiline definitions" should "parse without error" in { @@ -131,7 +133,7 @@ class FuncExprSpec extends AnyFlatSpec with Matchers with AquaSpec { | <- v |""".stripMargin - parser[Id]().parseAll(script).value.toEither.isLeft shouldBe true + parser.parseAll(script).value.toEither.isLeft shouldBe true } "multi function expression" should "parse" in { @@ -151,7 +153,7 @@ class FuncExprSpec extends AnyFlatSpec with Matchers with AquaSpec { | three <- Local.gt() | <- two""".stripMargin - val tree = parser[Id]().parseAll(script).value.toEither.value + val tree = parser.parseAll(script).value.toEither.value val qTree = tree.tree.foldLeft(mutable.Queue.empty[Expr[Id]]) { case (acc, tag) => acc.enqueue(tag) @@ -283,6 +285,6 @@ class FuncExprSpec extends AnyFlatSpec with Matchers with AquaSpec { | str2 <- LocalPrint.print("in on") | par LocalPrint.print("in par")""".stripMargin - val tree = parser[Id]().parseAll(script).value.toEither.value + val tree = parser.parseAll(script).value.toEither.value } } diff --git a/semantics/src/test/scala/aqua/semantics/SemanticsSpec.scala b/semantics/src/test/scala/aqua/semantics/SemanticsSpec.scala index b62d0bdf..917d9906 100644 --- a/semantics/src/test/scala/aqua/semantics/SemanticsSpec.scala +++ b/semantics/src/test/scala/aqua/semantics/SemanticsSpec.scala @@ -2,21 +2,24 @@ package aqua.semantics import aqua.Node import aqua.Node.* +import aqua.parser.Ast import aqua.model.func.raw.{FuncOp, FuncOps, SeqTag} import aqua.model.transform.TransformConfig import aqua.model.transform.funcop.* import aqua.model.{AquaContext, LiteralModel} -import aqua.parser.Ast +import aqua.parser.Parser import aqua.parser.lift.{LiftParser, Span} import aqua.types.LiteralType import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers +import cats.~> class SemanticsSpec extends AnyFlatSpec with Matchers { // use it to fix https://github.com/fluencelabs/aqua/issues/90 "sem" should "create right model" in { implicit val fileLift: LiftParser[Span.F] = Span.spanLiftParser + val parser = Parser.parser(Parser.spanParser) val script = """service A("srv1"): @@ -27,7 +30,7 @@ class SemanticsSpec extends AnyFlatSpec with Matchers { | A.fn1() | par A.fn1()""".stripMargin - val ast = Ast.fromString(script).toList.head + val ast = parser(script).toList.head val ctx = AquaContext.blank val bc = TransformConfig()