Fixes version display and empty module compilation (fixes #264 #265) (#274)

This commit is contained in:
Dima 2021-09-07 11:02:36 +03:00 committed by GitHub
parent 835a7f7672
commit 621e06dd9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 73 additions and 35 deletions

View File

@ -0,0 +1,9 @@
-- import.aqua
module Import.Test
import foobar from "export.aqua"
use foo as f from "export.aqua" as Exp
use "export.aqua"
export foobar as barfoo

View File

@ -1,7 +1,5 @@
package aqua.backend
object Version {
// TODO: get version for JS compiler
lazy val version = "Unknown (JS)"
lazy val version = BuildInfo.version
}

View File

@ -2,7 +2,5 @@ package aqua.backend
object Version {
lazy val version = Option(getClass.getPackage.getImplementationVersion)
.filter(_.nonEmpty)
.getOrElse("Unknown")
lazy val version = BuildInfo.version
}

View File

@ -146,6 +146,11 @@ lazy val backend = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Pure)
.in(file("backend"))
.settings(commons: _*)
.enablePlugins(BuildInfoPlugin)
.settings(
buildInfoKeys := Seq[BuildInfoKey](version),
buildInfoPackage := "aqua.backend"
)
.dependsOn(transform)
lazy val `backend-air` = crossProject(JVMPlatform, JSPlatform)

View File

@ -12,8 +12,9 @@ object Test extends IOApp.Simple {
implicit val aio: AquaIO[IO] = new AquaFilesIO[IO]
override def run: IO[Unit] =
IO.println("Start ms: " + System.currentTimeMillis()) *>
AquaPathCompiler
for {
start <- IO(System.currentTimeMillis())
_ <- AquaPathCompiler
.compileFilesTo[IO](
Path("./aqua-src"),
List(Path("./aqua")),
@ -26,6 +27,8 @@ object Test extends IOApp.Simple {
errs.map(System.err.println): Unit
case Validated.Valid(res) =>
res.map(println): Unit
} <* IO.println("End ms : " + System.currentTimeMillis())
}
_ <- IO.println("Compilation ends in : " + (System.currentTimeMillis() - start) + " ms")
} yield ()
}

View File

@ -2,14 +2,16 @@ package aqua.parser
import cats.data.{Validated, ValidatedNec}
import aqua.parser.Ast
import aqua.parser.Ast.Tree
import aqua.parser.ParserError
import aqua.parser.LexerError
import aqua.parser.expr.RootExpr
import aqua.parser.head.HeadExpr
import aqua.parser.lexer.Token
import aqua.parser.lift.{FileSpan, LiftParser, Span}
import cats.{Comonad, Eval, ~>}
import cats.parse.LocationMap
import cats.parse.Parser0 as P0
import cats.parse.{Parser as P, Parser0 as P0}
import cats.Id
import aqua.parser.lift.LiftParser.LiftErrorOps
@ -22,7 +24,7 @@ object Parser {
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) =>
(HeadExpr.ast[S] ~ RootExpr.ast0[S]()).map { case (head, bodyMaybe) =>
bodyMaybe.map(Ast(head, _))
}

View File

@ -2,13 +2,13 @@ package aqua.parser.expr
import aqua.parser.Ast.Tree
import aqua.parser.lexer.Token
import aqua.parser.lexer.Token._
import aqua.parser.lexer.Token.*
import aqua.parser.lift.LiftParser
import aqua.parser.lift.LiftParser._
import aqua.parser.lift.LiftParser.*
import aqua.parser.{Expr, ParserError}
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}
import cats.data.{Chain, NonEmptyChain, NonEmptyList, Validated, ValidatedNec}
import cats.free.Cofree
import cats.parse.{Parser => P}
import cats.parse.{Parser0 as P0, Parser as P}
import cats.{Comonad, Eval}
import cats.~>
@ -23,16 +23,38 @@ object RootExpr extends Expr.Companion {
def validChildren: List[Expr.Lexem] =
ServiceExpr :: AliasExpr :: DataStructExpr :: ConstantExpr :: FuncExpr :: Nil
override def ast[F[_]: LiftParser: Comonad](): P[ValidatedNec[ParserError[F], Tree[F]]] =
(P.unit.lift0.map(Token.lift[F, Unit](_)).with1 ~
private def gatherResults[F[_]: LiftParser: Comonad](results: NonEmptyList[ValidatedNec[ParserError[F], Tree[F]]]): (Chain[ParserError[F]], Chain[Tree[F]]) = {
results.foldLeft[(Chain[ParserError[F]], Chain[Tree[F]])](Chain.empty -> Chain.empty) {
case ((errs, trees), Validated.Valid(tree)) => (errs, trees :+ tree)
case ((errs, trees), Validated.Invalid(err)) => (errs ++ err.toChain, trees)
}
}
private def linesParser[F[_]: LiftParser: Comonad](): P[NonEmptyList[ValidatedNec[ParserError[F], Tree[F]]]] =
P.repSep(
P.oneOf(RootExpr.validChildren.map(_.ast[F]())),
` \n+`
).surroundedBy(` \n+`.?)
.map(_.foldLeft[(Chain[ParserError[F]], Chain[Tree[F]])](Chain.empty -> Chain.empty) {
case ((errs, trees), Validated.Valid(tree)) => (errs, trees :+ tree)
case ((errs, trees), Validated.Invalid(err)) => (errs ++ err.toChain, trees)
})).map { case (point, (errs, trees)) =>
private def rootToken[F[_]: LiftParser: Comonad]: P0[Token[F]] =
P.unit.lift0.map(Token.lift[F, Unit](_))
private def parserSchema[F[_]: LiftParser: Comonad](): P[(Token[F], (Chain[ParserError[F]], Chain[Tree[F]]))] =
rootToken.with1 ~
linesParser().map(l => gatherResults(l))
def empty[F[_] : LiftParser : Comonad](): P0[ValidatedNec[ParserError[F], Tree[F]]] =
(rootToken <* (Token.` \n*` *> Token.` `.? *> P.end))
.map(point => Validated.validNec(Cofree(RootExpr[F](point), Eval.now(Chain.empty))))
// Could handle empty body
def ast0[F[_]: LiftParser: Comonad](): P0[ValidatedNec[ParserError[F], Tree[F]]] =
// `empty` is first to handle errors from `ast` at a first place
empty().backtrack | ast()
override def ast[F[_]: LiftParser: Comonad](): P[ValidatedNec[ParserError[F], Tree[F]]] =
parserSchema()
.map { case (point, (errs, trees)) =>
NonEmptyChain
.fromChain(errs)
.fold[ValidatedNec[ParserError[F], Tree[F]]](

View File

@ -71,6 +71,7 @@ object Token {
(` `.?.void *> (`--` *> P.charsWhile0(_ != '\n')).?.void).with1 *> `\n`
val ` \n+` : P[Unit] = P.repAs[Unit, Unit](` \n`.backtrack, 1)(Accumulator0.unitAccumulator0)
val ` \n*` : P0[Unit] = P.repAs0[Unit, Unit](` \n`.backtrack)(Accumulator0.unitAccumulator0)
val ` : \n+` : P[Unit] = ` `.?.with1 *> `:` *> ` \n+`
val `,` : P[Unit] = P.char(',') <* ` `.?
val `.` : P[Unit] = P.char('.')

View File

@ -1,3 +1,4 @@
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.0")
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.1.0")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0")

View File

@ -1,26 +1,21 @@
package aqua.semantics
import aqua.model.func.raw.FuncOp
import aqua.model.{AquaContext, Model, ScriptModel}
import aqua.model.{AquaContext, EmptyModel, Model, ScriptModel}
import aqua.parser.lexer.Token
import aqua.parser.{Ast, Expr}
import aqua.semantics.rules.ReportError
import aqua.semantics.rules.abilities.{
AbilitiesAlgebra,
AbilitiesInterpreter,
AbilitiesState,
AbilityOp
}
import aqua.semantics.rules.abilities.{AbilitiesAlgebra, AbilitiesInterpreter, AbilitiesState, AbilityOp}
import aqua.semantics.rules.names.{NameOp, NamesAlgebra, NamesInterpreter, NamesState}
import aqua.semantics.rules.types.{TypeOp, TypesAlgebra, TypesInterpreter, TypesState}
import cats.Eval
import cats.arrow.FunctionK
import cats.data.Validated.{Invalid, Valid}
import cats.data._
import cats.data.*
import cats.free.Free
import cats.kernel.Monoid
import cats.syntax.apply._
import cats.syntax.semigroup._
import cats.syntax.apply.*
import cats.syntax.semigroup.*
import monocle.Lens
import monocle.macros.GenLens
import scribe.Logging
@ -96,7 +91,11 @@ object Semantics extends Logging {
NonEmptyChain
.fromChain(state.errors)
.fold[ValidatedNec[SemanticError[S], AquaContext]](Valid(ctx))(Invalid(_))
case (state, _) =>
case (state, _: EmptyModel) =>
NonEmptyChain
.fromChain(state.errors)
.fold[ValidatedNec[SemanticError[S], AquaContext]](Valid(init))(Invalid(_))
case (state, m) =>
NonEmptyChain
.fromChain(state.errors)
.map(Invalid(_))