mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 22:50:18 +00:00
Js build (#247)
This commit is contained in:
parent
f59a93ac27
commit
296c64836d
@ -56,6 +56,7 @@ lazy val cli = crossProject(JSPlatform, JVMPlatform)
|
||||
|
||||
lazy val cliJS = cli.js
|
||||
.settings(
|
||||
scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule)),
|
||||
scalaJSUseMainModuleInitializer := true
|
||||
)
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
package aqua
|
||||
|
||||
import aqua.backend.Backend
|
||||
import aqua.backend.ts.TypeScriptBackend
|
||||
import aqua.compiler.{AquaCompiler, AquaError, AquaSources}
|
||||
import aqua.model.transform.TransformConfig
|
||||
import cats.effect.IO
|
||||
import cats.effect.unsafe.implicits.global
|
||||
import cats.data.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.applicative.*
|
||||
import cats.{Applicative, Monad, Show}
|
||||
import aqua.parser.lift.FileSpan
|
||||
|
||||
object JsApp {
|
||||
|
||||
trait AquaJsError {}
|
||||
|
||||
case class FileId(name: String)
|
||||
|
||||
class Sources[F[_]: Applicative] extends AquaSources[F, AquaJsError, FileId] {
|
||||
|
||||
def sources: F[ValidatedNec[AquaJsError, Chain[(FileId, String)]]] =
|
||||
Validated.Valid(Chain.empty).pure[F]
|
||||
|
||||
// Resolve id of the imported imp string from I file
|
||||
def resolveImport(from: FileId, imp: String): F[ValidatedNec[AquaJsError, FileId]] =
|
||||
Validated.Valid(FileId("")).pure[F]
|
||||
|
||||
// Load file by its resolved I
|
||||
def load(file: FileId): F[ValidatedNec[AquaJsError, String]] = Validated.Valid("").pure[F]
|
||||
}
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
// test code
|
||||
// val sources = new Sources[IO]()
|
||||
// val bodyConfig = GenerationConfig()
|
||||
// val b = AquaCompiler
|
||||
// .compileTo[IO, AquaJsError, FileId, FileSpan.F, String](
|
||||
// sources,
|
||||
// (fmid, src) => FileSpan.fileSpanLiftParser(fmid.name, src),
|
||||
// TypeScriptBackend,
|
||||
// bodyConfig,
|
||||
// (a) => ???
|
||||
// )
|
||||
println("Hello world!")
|
||||
}
|
||||
}
|
@ -6,11 +6,11 @@ import cats.data.Chain
|
||||
import cats.effect.IO
|
||||
import cats.effect.unsafe.implicits.global
|
||||
import fs2.text
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import fs2.io.file.{Files, Path}
|
||||
import org.scalatest.flatspec.AsyncFlatSpec
|
||||
|
||||
class SourcesSpec extends AnyFlatSpec with Matchers {
|
||||
class SourcesSpec extends AsyncFlatSpec with Matchers {
|
||||
implicit val aquaIO: AquaIO[IO] = AquaFilesIO.summon[IO]
|
||||
|
||||
"AquaFileSources" should "generate correct fileId with imports" in {
|
||||
@ -18,8 +18,7 @@ class SourcesSpec extends AnyFlatSpec with Matchers {
|
||||
val importPath = path.resolve("imports")
|
||||
|
||||
val sourceGen = new AquaFileSources[IO](path, importPath :: Nil)
|
||||
|
||||
val result = sourceGen.sources.unsafeRunSync()
|
||||
sourceGen.sources.map { result =>
|
||||
result.isValid shouldBe true
|
||||
|
||||
val listResult = result
|
||||
@ -37,6 +36,7 @@ class SourcesSpec extends AnyFlatSpec with Matchers {
|
||||
val (importNearId, importFileNear) = listResult.head
|
||||
importNearId shouldBe "importNear.aqua"
|
||||
importFileNear.nonEmpty shouldBe true
|
||||
}.unsafeToFuture()
|
||||
}
|
||||
|
||||
"AquaFileSources" should "throw an error if a source file doesn't exist" in {
|
||||
@ -44,8 +44,7 @@ class SourcesSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
val sourceGen = new AquaFileSources[IO](path, Nil)
|
||||
|
||||
val result = sourceGen.sources.unsafeRunSync()
|
||||
result.isInvalid shouldBe true
|
||||
sourceGen.sources.map(result => result.isInvalid shouldBe true).unsafeToFuture()
|
||||
}
|
||||
|
||||
"AquaFileSources" should "throw an error if there is no import that is indicated in a source" in {
|
||||
@ -53,9 +52,10 @@ class SourcesSpec extends AnyFlatSpec with Matchers {
|
||||
val importPath = path.resolve("random/import/path")
|
||||
|
||||
val sourceGen = new AquaFileSources[IO](path, importPath :: Nil)
|
||||
val result =
|
||||
sourceGen.resolveImport(FileModuleId(path.resolve("no-file.aqua")), "no/file").unsafeRunSync()
|
||||
result.isInvalid shouldBe true
|
||||
sourceGen
|
||||
.resolveImport(FileModuleId(path.resolve("no-file.aqua")), "no/file")
|
||||
.map(result => result.isInvalid shouldBe true)
|
||||
.unsafeToFuture()
|
||||
}
|
||||
|
||||
"AquaFileSources" should "find correct imports" in {
|
||||
@ -64,36 +64,33 @@ class SourcesSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
val sourceGen = new AquaFileSources[IO](srcPath, importPath :: Nil)
|
||||
|
||||
(for {
|
||||
// should be found in importPath
|
||||
val result =
|
||||
sourceGen
|
||||
.resolveImport(FileModuleId(srcPath), "imports/import.aqua")
|
||||
.unsafeRunSync()
|
||||
|
||||
result <- sourceGen.resolveImport(FileModuleId(srcPath), "imports/import.aqua")
|
||||
exists <- {
|
||||
result.isValid shouldBe true
|
||||
val file = result.getOrElse(FileModuleId(Path("/some/random"))).file
|
||||
Files[IO].exists(file).unsafeRunSync() shouldBe true
|
||||
Files[IO].exists(file)
|
||||
}
|
||||
_ = exists shouldBe true
|
||||
|
||||
// should be found near src file
|
||||
val result2 =
|
||||
sourceGen
|
||||
.resolveImport(FileModuleId(srcPath), "importNear.aqua")
|
||||
.unsafeRunSync()
|
||||
|
||||
result2 <- sourceGen.resolveImport(FileModuleId(srcPath), "importNear.aqua")
|
||||
exists2 <- {
|
||||
result2.isValid shouldBe true
|
||||
val file2 = result2.getOrElse(FileModuleId(Path("/some/random"))).file
|
||||
Files[IO].exists(file2).unsafeRunSync() shouldBe true
|
||||
|
||||
Files[IO].exists(file2)
|
||||
}
|
||||
_ = exists2 shouldBe true
|
||||
// near src file but in another directory
|
||||
val sourceGen2 = new AquaFileSources[IO](srcPath, Nil)
|
||||
val result3 =
|
||||
sourceGen2
|
||||
.resolveImport(FileModuleId(srcPath), "imports/import.aqua")
|
||||
.unsafeRunSync()
|
||||
|
||||
sourceGen2 = new AquaFileSources[IO](srcPath, Nil)
|
||||
result3 <- sourceGen2.resolveImport(FileModuleId(srcPath), "imports/import.aqua")
|
||||
exists3 <- {
|
||||
result3.isValid shouldBe true
|
||||
val file3 = result3.getOrElse(FileModuleId(Path("/some/random"))).file
|
||||
Files[IO].exists(file3).unsafeRunSync() shouldBe true
|
||||
Files[IO].exists(file3)
|
||||
}
|
||||
} yield { exists3 shouldBe true }).unsafeToFuture()
|
||||
}
|
||||
|
||||
"AquaFileSources" should "resolve correct path for target" in {
|
||||
@ -106,12 +103,16 @@ class SourcesSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
val suffix = "_custom.super"
|
||||
|
||||
val resolved = sourceGen.resolveTargetPath(filePath, targetPath, suffix).unsafeRunSync()
|
||||
sourceGen
|
||||
.resolveTargetPath(filePath, targetPath, suffix)
|
||||
.map { resolved =>
|
||||
resolved.isValid shouldBe true
|
||||
|
||||
val targetFilePath = resolved.toOption.get
|
||||
targetFilePath.toString shouldBe "/target/dir/some-dir/file_custom.super"
|
||||
}
|
||||
.unsafeToFuture()
|
||||
}
|
||||
|
||||
"AquaFileSources" should "write correct file with correct path" in {
|
||||
val path = Path("cli/.jvm/src/test/test-dir")
|
||||
@ -121,22 +122,22 @@ class SourcesSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
// clean up
|
||||
val resultPath = Path("cli/.jvm/src/test/test-dir/target/imports/import_hey.custom")
|
||||
Files[IO].deleteIfExists(resultPath).unsafeRunSync()
|
||||
|
||||
val sourceGen = new AquaFileSources[IO](path, Nil)
|
||||
val content = "some random content"
|
||||
val compiled = AquaCompiled[FileModuleId](
|
||||
(for {
|
||||
_ <- Files[IO].deleteIfExists(resultPath)
|
||||
sourceGen = new AquaFileSources[IO](path, Nil)
|
||||
content = "some random content"
|
||||
compiled = AquaCompiled[FileModuleId](
|
||||
FileModuleId(filePath),
|
||||
Seq(Generated("_hey.custom", content))
|
||||
)
|
||||
|
||||
val resolved = sourceGen.write(targetPath)(compiled).unsafeRunSync()
|
||||
resolved <- sourceGen.write(targetPath)(compiled)
|
||||
_ = {
|
||||
resolved.size shouldBe 1
|
||||
resolved.head.isValid shouldBe true
|
||||
|
||||
Files[IO].exists(resultPath).unsafeRunSync() shouldBe true
|
||||
|
||||
val resultText = Files[IO]
|
||||
}
|
||||
exists <- Files[IO].exists(resultPath)
|
||||
_ = exists shouldBe true
|
||||
result <- Files[IO]
|
||||
.readAll(resultPath)
|
||||
.fold(
|
||||
Vector
|
||||
@ -147,12 +148,10 @@ class SourcesSpec extends AnyFlatSpec with Matchers {
|
||||
.attempt
|
||||
.compile
|
||||
.last
|
||||
.unsafeRunSync()
|
||||
.get
|
||||
.right
|
||||
.get
|
||||
resultText = result.get.right.get
|
||||
_ <- Files[IO].deleteIfExists(resultPath)
|
||||
} yield {
|
||||
resultText shouldBe content
|
||||
|
||||
Files[IO].deleteIfExists(resultPath).unsafeRunSync()
|
||||
}).unsafeToFuture()
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,19 @@
|
||||
package aqua
|
||||
|
||||
import aqua.backend.Version
|
||||
import aqua.model.LiteralModel
|
||||
import aqua.model.transform.TransformConfig
|
||||
import aqua.parser.expr.ConstantExpr
|
||||
import aqua.parser.lift.LiftParser
|
||||
import cats.data.Validated.{Invalid, Valid}
|
||||
import cats.data.{NonEmptyList, Validated, ValidatedNel}
|
||||
import cats.effect.{ExitCode, IO, unsafe}
|
||||
import cats.data.{NonEmptyList, Validated, ValidatedNec, ValidatedNel}
|
||||
import cats.effect.{ExitCode, IO}
|
||||
import cats.effect.std.Console
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.traverse.*
|
||||
import cats.{Comonad, Functor}
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.{Comonad, Functor, Monad}
|
||||
import com.monovore.decline.Opts.help
|
||||
import com.monovore.decline.{Opts, Visibility}
|
||||
import scribe.Level
|
||||
@ -41,84 +44,56 @@ object AppOps {
|
||||
)
|
||||
}
|
||||
|
||||
def checkPath(implicit runtime: unsafe.IORuntime): String => ValidatedNel[String, Path] = {
|
||||
pathStr =>
|
||||
Validated
|
||||
.fromEither(Validated.catchNonFatal {
|
||||
def checkPath[F[_]: Monad: Files](pathStr: String): F[ValidatedNec[String, Path]] = {
|
||||
val p = Path(pathStr)
|
||||
Files[IO]
|
||||
Files[F]
|
||||
.exists(p)
|
||||
.flatMap { exists =>
|
||||
if (exists)
|
||||
Files[IO].isRegularFile(p).map { isFile =>
|
||||
Files[F].isRegularFile(p).map { isFile =>
|
||||
if (isFile) {
|
||||
val filename = p.fileName.toString
|
||||
val ext = Option(filename)
|
||||
.filter(_.contains("."))
|
||||
.map(f => f.substring(f.lastIndexOf(".") + 1))
|
||||
.getOrElse("")
|
||||
if (ext != "aqua") Left("File must be with 'aqua' extension")
|
||||
else Right(p)
|
||||
if (p.extName != ".aqua") Validated.invalidNec("File must be with 'aqua' extension")
|
||||
else Validated.validNec(p)
|
||||
} else
|
||||
Right(p)
|
||||
Validated.validNec(p)
|
||||
}
|
||||
else
|
||||
IO(Left(s"There is no path '${p.toString}'"))
|
||||
Validated.invalidNec(s"There is no path '${p.toString}'").pure[F]
|
||||
}
|
||||
// TODO: make it with correct effects
|
||||
.unsafeRunSync()
|
||||
}.toEither.left.map(t => s"An error occurred on imports reading: ${t.getMessage}").flatten)
|
||||
.toValidatedNel
|
||||
}
|
||||
|
||||
def inputOpts(implicit runtime: unsafe.IORuntime): Opts[Path] =
|
||||
def inputOpts[F[_]: Monad: Files]: Opts[F[ValidatedNec[String, Path]]] =
|
||||
Opts
|
||||
.option[String](
|
||||
"input",
|
||||
"Path to an aqua file or an input directory that contains your .aqua files",
|
||||
"i"
|
||||
)
|
||||
.mapValidated(checkPath)
|
||||
.map(s => checkPath[F](s))
|
||||
|
||||
def outputOpts(implicit runtime: unsafe.IORuntime): Opts[Path] =
|
||||
Opts.option[String]("output", "Path to the output directory", "o").mapValidated(checkPath)
|
||||
def outputOpts[F[_]: Monad: Files]: Opts[F[ValidatedNec[String, Path]]] =
|
||||
Opts.option[String]("output", "Path to the output directory", "o").map(s => checkPath[F](s))
|
||||
|
||||
def importOpts(implicit runtime: unsafe.IORuntime): Opts[List[Path]] =
|
||||
def importOpts[F[_]: Monad: Files]: Opts[F[ValidatedNec[String, List[Path]]]] =
|
||||
Opts
|
||||
.options[String]("import", "Path to the directory to import from", "m")
|
||||
.mapValidated { ps =>
|
||||
val checked = ps
|
||||
.map(pStr => {
|
||||
Validated.catchNonFatal {
|
||||
.map { ps =>
|
||||
val checked: List[F[ValidatedNec[String, Path]]] = ps.toList.map { pStr =>
|
||||
val p = Path(pStr)
|
||||
(for {
|
||||
exists <- Files[IO].exists(p)
|
||||
isDir <- Files[IO].isDirectory(p)
|
||||
exists <- Files[F].exists(p)
|
||||
isDir <- Files[F].isDirectory(p)
|
||||
} yield {
|
||||
if (exists && isDir) Right(p)
|
||||
else Left(s"There is no path ${p.toString} or it is not a directory")
|
||||
if (exists && isDir) Validated.validNec[String, Path](p)
|
||||
else
|
||||
Validated.invalidNec[String, Path](
|
||||
s"There is no path ${p.toString} or it is not a directory"
|
||||
)
|
||||
})
|
||||
// TODO: make it with correct effects
|
||||
.unsafeRunSync()
|
||||
}
|
||||
})
|
||||
.toList
|
||||
checked.map {
|
||||
case Validated.Valid(pE) =>
|
||||
pE match {
|
||||
case Right(p) =>
|
||||
Validated.Valid(p)
|
||||
case Left(e) =>
|
||||
Validated.Invalid(e)
|
||||
|
||||
checked.sequence.map(_.sequence)
|
||||
}
|
||||
case Validated.Invalid(e) =>
|
||||
Validated.Invalid(s"Error occurred on imports reading: ${e.getMessage}")
|
||||
}.traverse {
|
||||
case Valid(a) => Validated.validNel(a)
|
||||
case Invalid(e) => Validated.invalidNel(e)
|
||||
}
|
||||
}
|
||||
.withDefault(List.empty)
|
||||
|
||||
def constantOpts[F[_]: LiftParser: Comonad]: Opts[List[TransformConfig.Const]] =
|
||||
Opts
|
||||
@ -168,7 +143,7 @@ object AppOps {
|
||||
.withDefault(false)
|
||||
|
||||
lazy val versionStr: String =
|
||||
Option(getClass.getPackage.getImplementationVersion).filter(_.nonEmpty).getOrElse("no version")
|
||||
Version.version
|
||||
|
||||
def versionAndExit[F[_]: Console: Functor]: F[ExitCode] = Console[F]
|
||||
.println(versionStr)
|
@ -7,19 +7,21 @@ import aqua.backend.ts.TypeScriptBackend
|
||||
import aqua.files.AquaFilesIO
|
||||
import aqua.model.transform.TransformConfig
|
||||
import aqua.parser.lift.LiftParser.Implicits.idLiftParser
|
||||
import cats.Id
|
||||
import cats.data.Validated
|
||||
import cats.{Functor, Id, Monad}
|
||||
import cats.data.{Chain, NonEmptyList, Validated, ValidatedNec, ValidatedNel}
|
||||
import cats.effect.*
|
||||
import cats.effect.std.Console as ConsoleEff
|
||||
import cats.syntax.apply.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.flatMap.*
|
||||
import com.monovore.decline.Opts
|
||||
import com.monovore.decline.effect.CommandIOApp
|
||||
import fs2.io.file.Files
|
||||
import scribe.Logging
|
||||
|
||||
object AquaCli extends IOApp with Logging {
|
||||
import AppOps._
|
||||
import AppOps.*
|
||||
|
||||
sealed trait CompileTarget
|
||||
case object TypescriptTarget extends CompileTarget
|
||||
@ -45,9 +47,9 @@ object AquaCli extends IOApp with Logging {
|
||||
) orElse helpOpt.as(
|
||||
helpAndExit
|
||||
) orElse (
|
||||
inputOpts,
|
||||
importOpts,
|
||||
outputOpts,
|
||||
inputOpts[F],
|
||||
importOpts[F],
|
||||
outputOpts[F],
|
||||
compileToAir,
|
||||
compileToJs,
|
||||
noRelay,
|
||||
@ -57,7 +59,7 @@ object AquaCli extends IOApp with Logging {
|
||||
logLevelOpt,
|
||||
constantOpts[Id]
|
||||
).mapN {
|
||||
case (input, imports, output, toAir, toJs, noRelay, noXor, h, v, logLevel, constants) =>
|
||||
case (inputF, importsF, outputF, toAir, toJs, noRelay, noXor, h, v, logLevel, constants) =>
|
||||
scribe.Logger.root
|
||||
.clearHandlers()
|
||||
.clearModifiers()
|
||||
@ -78,6 +80,11 @@ object AquaCli extends IOApp with Logging {
|
||||
bc.copy(relayVarName = bc.relayVarName.filterNot(_ => noRelay))
|
||||
}
|
||||
logger.info(s"Aqua Compiler ${versionStr}")
|
||||
|
||||
(inputF, outputF, importsF).mapN {(i, o, imp) =>
|
||||
i.andThen { input =>
|
||||
o.andThen { output =>
|
||||
imp.map { imports =>
|
||||
AquaPathCompiler
|
||||
.compileFilesTo[F](
|
||||
input,
|
||||
@ -86,9 +93,17 @@ object AquaCli extends IOApp with Logging {
|
||||
targetToBackend(target),
|
||||
bc
|
||||
)
|
||||
.map {
|
||||
}
|
||||
}
|
||||
}
|
||||
}.flatMap {
|
||||
case Validated.Invalid(errs) =>
|
||||
errs.map(System.out.println)
|
||||
errs.map(logger.error(_))
|
||||
ExitCode.Error.pure[F]
|
||||
case Validated.Valid(result) =>
|
||||
result.map {
|
||||
case Validated.Invalid(errs) =>
|
||||
errs.map(logger.error(_))
|
||||
ExitCode.Error
|
||||
case Validated.Valid(results) =>
|
||||
results.map(logger.info(_))
|
||||
@ -97,6 +112,7 @@ object AquaCli extends IOApp with Logging {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def run(args: List[String]): IO[ExitCode] = {
|
||||
CommandIOApp.run[IO](
|
@ -1,6 +1,6 @@
|
||||
package aqua
|
||||
|
||||
import aqua.compiler._
|
||||
import aqua.compiler.*
|
||||
import aqua.files.FileModuleId
|
||||
import aqua.io.AquaFileError
|
||||
import aqua.parser.lift.FileSpan
|
@ -12,13 +12,14 @@ import cats.syntax.functor.*
|
||||
import cats.syntax.monad.*
|
||||
import cats.syntax.traverse.*
|
||||
import fs2.io.file.{Files, Path}
|
||||
import scribe.Logging
|
||||
|
||||
import scala.util.Try
|
||||
|
||||
class AquaFileSources[F[_]: AquaIO: Monad: Files: Functor](
|
||||
sourcesPath: Path,
|
||||
importFrom: List[Path]
|
||||
) extends AquaSources[F, AquaFileError, FileModuleId] {
|
||||
) extends AquaSources[F, AquaFileError, FileModuleId] with Logging {
|
||||
private val filesIO = implicitly[AquaIO[F]]
|
||||
|
||||
override def sources: F[ValidatedNec[AquaFileError, Chain[(FileModuleId, String)]]] =
|
@ -7,15 +7,16 @@ import aqua.model.transform.TransformConfig
|
||||
import aqua.model.transform.res.AquaRes
|
||||
import aqua.parser.lift.LiftParser
|
||||
import aqua.semantics.Semantics
|
||||
import cats.data.Validated.{Invalid, Valid, validNec}
|
||||
import cats.data.Validated.{validNec, Invalid, Valid}
|
||||
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.traverse.*
|
||||
import cats.{Comonad, Monad}
|
||||
import scribe.Logging
|
||||
|
||||
object AquaCompiler {
|
||||
object AquaCompiler extends Logging {
|
||||
|
||||
def compile[F[_]: Monad, E, I, S[_]: Comonad](
|
||||
sources: AquaSources[F, E, I],
|
||||
@ -26,10 +27,13 @@ object AquaCompiler {
|
||||
import config.aquaContextMonoid
|
||||
type Err = AquaError[I, E, S]
|
||||
new AquaParser[F, E, I, S](sources, liftI)
|
||||
.resolve[ValidatedNec[Err, AquaContext]](ast =>
|
||||
context =>
|
||||
context.andThen(ctx => Semantics.process(ast, ctx).leftMap(_.map[Err](CompileError(_))))
|
||||
)
|
||||
.resolve[ValidatedNec[Err, AquaContext]] { ast => context =>
|
||||
context.andThen { ctx =>
|
||||
Semantics
|
||||
.process(ast, ctx)
|
||||
.leftMap(_.map[Err](CompileError(_)))
|
||||
}
|
||||
}
|
||||
.map {
|
||||
case Valid(modules) =>
|
||||
Linker.link[I, AquaError[I, E, S], ValidatedNec[Err, AquaContext]](
|
||||
|
@ -5,17 +5,18 @@ import aqua.parser.Ast
|
||||
import aqua.parser.head.ImportExpr
|
||||
import aqua.parser.lift.LiftParser
|
||||
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}
|
||||
import cats.syntax.applicative._
|
||||
import cats.syntax.flatMap._
|
||||
import cats.syntax.functor._
|
||||
import cats.syntax.traverse._
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.traverse.*
|
||||
import cats.{Comonad, Monad}
|
||||
import scribe.Logging
|
||||
|
||||
// TODO: add tests
|
||||
class AquaParser[F[_]: Monad, E, I, S[_]: Comonad](
|
||||
sources: AquaSources[F, E, I],
|
||||
liftI: (I, String) => LiftParser[S]
|
||||
) {
|
||||
) extends Logging {
|
||||
|
||||
type Body = Ast[S]
|
||||
type Err = AquaError[I, E, S]
|
||||
|
Loading…
Reference in New Issue
Block a user