mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-01 05:10:18 +00:00
Upper cased constants (#260)
This commit is contained in:
parent
621e06dd9c
commit
d881f5bdbe
31
.github/workflows/test_branch.yml
vendored
31
.github/workflows/test_branch.yml
vendored
@ -47,18 +47,19 @@ jobs:
|
||||
sbt test
|
||||
|
||||
### Update & build
|
||||
# - name: Integration test
|
||||
# run: |
|
||||
# git clone https://github.com/fluencelabs/aqua-playground.git
|
||||
# cd aqua-playground
|
||||
# npm i
|
||||
# cd ..
|
||||
# sbt "cli/run -i aqua-playground/aqua/examples -o aqua-playground/src/compiled/examples -m aqua-playground/node_modules -c \"uniqueConst = 1\" -c \"anotherConst = \\\"ab\\\"\""
|
||||
# cd aqua-playground
|
||||
# npm run examples
|
||||
# cd ..
|
||||
# sbt "cliJS/fastOptJS"
|
||||
# rm -rf aqua-playground/src/compiled/examples/*
|
||||
# node cli/.js/target/scala-3.0.1/cli-fastopt.js -i aqua-playground/aqua/examples -o aqua-playground/src/compiled/examples -m aqua-playground/node_modules -c "uniqueConst = 1" -c "anotherConst = \"ab\""
|
||||
# cd aqua-playground
|
||||
# npm run examples
|
||||
- name: Integration test
|
||||
run: |
|
||||
git clone https://github.com/fluencelabs/aqua-playground.git
|
||||
cd aqua-playground
|
||||
rm -rf src/compiled/examples/*
|
||||
npm i
|
||||
cd ..
|
||||
sbt "cli/run -i aqua-playground/aqua/examples -o aqua-playground/src/compiled/examples -m aqua-playground/node_modules -c \"UNIQUE_CONST = 1\" -c \"ANOTHER_CONST = \\\"ab\\\"\""
|
||||
cd aqua-playground
|
||||
npm run examples
|
||||
cd ..
|
||||
sbt "cliJS/fastOptJS"
|
||||
rm -rf aqua-playground/src/compiled/examples/*
|
||||
node cli/.js/target/scala-3.0.1/cli-fastopt.js -i aqua-playground/aqua/examples -o aqua-playground/src/compiled/examples -m aqua-playground/node_modules -c "UNIQUE_CONST = 1" -c "ANOTHER_CONST = \"ab\""
|
||||
cd aqua-playground
|
||||
npm run examples
|
||||
|
2
.jvmopts
2
.jvmopts
@ -1,6 +1,6 @@
|
||||
-Dfile.encoding=UTF8
|
||||
-Xms1G
|
||||
-Xmx5G
|
||||
-Xmx6G
|
||||
-XX:ReservedCodeCacheSize=500M
|
||||
-XX:+TieredCompilation
|
||||
-XX:+UseParallelGC
|
@ -1,4 +1,6 @@
|
||||
module Export.Test declares foobar, foo, bar
|
||||
module Export.Test declares foobar, foo, bar, ExpSrv, FA
|
||||
|
||||
const FA = "constant"
|
||||
|
||||
func bar() -> string:
|
||||
<- " I am MyFooBar bar"
|
||||
@ -12,5 +14,6 @@ func foobar() -> []string:
|
||||
res <- bar()
|
||||
<- res
|
||||
|
||||
service ExpSrv:
|
||||
baz()
|
||||
service ExpSrv("exp-srv"):
|
||||
baz()
|
||||
log: string -> ()
|
@ -1,8 +1,9 @@
|
||||
-- import.aqua
|
||||
module Import.Test
|
||||
import foobar from "export.aqua"
|
||||
import foobar, FA as C, ExpSrv from "export.aqua"
|
||||
|
||||
use foo as f from "export.aqua" as Exp
|
||||
use foo as f, FA as U from "export.aqua" as Exp
|
||||
use foo as f, FA from "export.aqua" as Exp1
|
||||
|
||||
use "export.aqua"
|
||||
|
||||
@ -10,7 +11,13 @@ import "gen/OneMore.aqua"
|
||||
|
||||
import OneMore as OM from "gen/OneMore.aqua"
|
||||
|
||||
export foo_wrapper as wrap, foobar as barfoo
|
||||
export consts as main--, foobar as barfoo
|
||||
|
||||
func consts():
|
||||
ExpSrv.log(C)
|
||||
ExpSrv.log(Exp.U)
|
||||
ExpSrv.log(Exp1.FA)
|
||||
ExpSrv.log(Export.Test.FA)
|
||||
|
||||
func foo_wrapper() -> string:
|
||||
z <- Exp.f()
|
||||
@ -20,4 +27,6 @@ func foo_wrapper() -> string:
|
||||
OM "ohmygod"
|
||||
OM.more_call()
|
||||
OM.consume(q)
|
||||
ExpSrv.log(C)
|
||||
ExpSrv.log(Exp.U)
|
||||
<- z
|
@ -3,7 +3,7 @@ module Ret
|
||||
import Service from "service.aqua"
|
||||
|
||||
use "error.aqua"
|
||||
export GetStr, tupleFunc, Service as S
|
||||
export GetStr, multiReturnFunc, Service as S
|
||||
|
||||
service GetStr("multiret-test"):
|
||||
retStr: string -> string
|
||||
@ -11,18 +11,21 @@ service GetStr("multiret-test"):
|
||||
service GetNum("multiret-num"):
|
||||
retNum: -> u8
|
||||
|
||||
const someNum = 5
|
||||
const someStr = "some-str"
|
||||
const SOME_NUM = 5
|
||||
const SOME_STR = "some-str"
|
||||
|
||||
func tupleFunc() -> string, u8:
|
||||
str <- GetStr.retStr(someStr)
|
||||
str <- GetStr.retStr(SOME_STR)
|
||||
n <- GetNum.retNum()
|
||||
Err.Peer.is_connected("Connected?")
|
||||
<- str, n
|
||||
|
||||
func multiReturnFunc(somethingToReturn: []u8, smthOption: ?string) -> []string, u8, string, []u8, ?string, u8:
|
||||
res: *string
|
||||
res <- GetStr.retStr(someStr)
|
||||
res <- GetStr.retStr("random-str")
|
||||
res <- GetStr.retStr(SOME_STR)
|
||||
try:
|
||||
res <- GetStr.retStr("random-str")
|
||||
catch e:
|
||||
GetStr.retStr(e.msg)
|
||||
res, tNum <- tupleFunc()
|
||||
<- res, 5, someStr, somethingToReturn, smthOption, tNum
|
||||
<- res, 5, SOME_STR, somethingToReturn, smthOption, tNum
|
||||
|
@ -29,10 +29,10 @@ object AirGen extends Logging {
|
||||
def valueToData(vm: ValueModel): DataView = vm match {
|
||||
case LiteralModel(value, _) => DataView.StringScalar(value)
|
||||
case VarModel(name, t, lambda) =>
|
||||
val n = t match {
|
||||
val n = (t match {
|
||||
case _: StreamType => "$" + name
|
||||
case _ => name
|
||||
}
|
||||
}).replace('.', '_')
|
||||
if (lambda.isEmpty) DataView.Variable(n)
|
||||
else DataView.VarLens(n, lambdaToString(lambda.toList))
|
||||
}
|
||||
@ -43,10 +43,10 @@ object AirGen extends Logging {
|
||||
case list => list.reduceLeft(SeqGen(_, _))
|
||||
}
|
||||
|
||||
def exportToString(exportTo: Call.Export): String = exportTo match {
|
||||
def exportToString(exportTo: Call.Export): String = (exportTo match {
|
||||
case Call.Export(name, _: StreamType) => "$" + name
|
||||
case Call.Export(name, _) => name
|
||||
}
|
||||
}).replace('.', '_')
|
||||
|
||||
private def folder(op: ResolvedOp, ops: Chain[AirGen]): Eval[AirGen] =
|
||||
op match {
|
||||
|
@ -17,7 +17,7 @@ val declineV = "2.1.0"
|
||||
name := "aqua-hll"
|
||||
|
||||
val commons = Seq(
|
||||
baseAquaVersion := "0.2.2",
|
||||
baseAquaVersion := "0.3.0",
|
||||
version := baseAquaVersion.value + "-" + sys.env.getOrElse("BUILD_NUMBER", "SNAPSHOT"),
|
||||
scalaVersion := dottyVersion,
|
||||
libraryDependencies ++= Seq(
|
||||
|
@ -16,7 +16,7 @@ object Test extends IOApp.Simple {
|
||||
start <- IO(System.currentTimeMillis())
|
||||
_ <- AquaPathCompiler
|
||||
.compileFilesTo[IO](
|
||||
Path("./aqua-src"),
|
||||
Path("./aqua-src/import.aqua"),
|
||||
List(Path("./aqua")),
|
||||
Path("./target"),
|
||||
TypeScriptBackend,
|
||||
|
@ -97,12 +97,12 @@ object AppOps {
|
||||
|
||||
def constantOpts[F[_]: LiftParser: Comonad]: Opts[List[TransformConfig.Const]] =
|
||||
Opts
|
||||
.options[String]("const", "Constant that will be used in an aqua code", "c")
|
||||
.options[String]("const", "Constant that will be used in an aqua code. Constant name must be upper cased.", "c")
|
||||
.mapValidated { strs =>
|
||||
val parsed = strs.map(s => ConstantExpr.onlyLiteral.parseAll(s))
|
||||
|
||||
val errors = parsed.collect { case Left(er) =>
|
||||
er
|
||||
val errors = parsed.zip(strs).collect { case (Left(er), str) =>
|
||||
str
|
||||
}
|
||||
|
||||
NonEmptyList
|
||||
@ -113,7 +113,8 @@ object AppOps {
|
||||
TransformConfig.Const(v._1.value, LiteralModel(v._2.value, v._2.ts))
|
||||
})
|
||||
) { errors =>
|
||||
Validated.invalid(errors.map(_.toString))
|
||||
val errorMsgs = errors.map (str => s"Invalid constant definition '$str'.")
|
||||
Validated.invalid(errorMsgs)
|
||||
}
|
||||
}
|
||||
.withDefault(List.empty)
|
||||
|
@ -27,6 +27,9 @@ case class AquaContext(
|
||||
private def prefixFirst[T](prefix: String, pair: (String, T)): (String, T) =
|
||||
(prefix + pair._1, pair._2)
|
||||
|
||||
def isEmpty: Boolean = this == AquaContext.blank
|
||||
def nonEmpty: Boolean = !isEmpty
|
||||
|
||||
def pick(
|
||||
name: String,
|
||||
rename: Option[String],
|
||||
@ -45,7 +48,19 @@ case class AquaContext(
|
||||
services = getter(_.services)
|
||||
)
|
||||
}
|
||||
.filter(_.`type`(name).nonEmpty)
|
||||
.filter(_.nonEmpty)
|
||||
|
||||
def pickHeader: AquaContext =
|
||||
AquaContext.blank.copy(module = module, declares = declares, exports = exports)
|
||||
|
||||
def pickDeclared(implicit semi: Semigroup[AquaContext]): AquaContext =
|
||||
if (module.isEmpty) this
|
||||
else
|
||||
declares
|
||||
.flatMap(pick(_, None))
|
||||
.foldLeft(pickHeader)(
|
||||
_ |+| _
|
||||
)
|
||||
|
||||
def allTypes(prefix: String = ""): Map[String, Type] =
|
||||
abilities
|
||||
@ -83,6 +98,7 @@ case class AquaContext(
|
||||
types ++
|
||||
values.view.mapValues(_.lastType) ++
|
||||
services.view.mapValues(_.`type`) ++
|
||||
// TODO do we need to pass abilities as type?
|
||||
abilities.flatMap { case (n, c) =>
|
||||
c.`type`(n).map(n -> _)
|
||||
}
|
||||
|
@ -100,6 +100,8 @@ case class VarModel(name: String, `type`: Type, lambda: Chain[LambdaModel] = Cha
|
||||
case Some(vv) => vv // TODO check that lambda is empty, otherwise error
|
||||
case None => this // Should not happen
|
||||
}
|
||||
|
||||
override def toString(): String = s"var{$name: " + `type` + s"}.${lambda.toList.mkString(".")}"
|
||||
}
|
||||
|
||||
object VarModel {
|
||||
|
@ -24,21 +24,39 @@ case class TransformConfig(
|
||||
// or relay's variable otherwise
|
||||
val hostPeerId: TransformConfig.Const =
|
||||
TransformConfig.Const(
|
||||
"host_peer_id",
|
||||
"HOST_PEER_ID",
|
||||
relayVarName.fold[ValueModel](LiteralModel.initPeerId)(r => VarModel(r, ScalarType.string))
|
||||
)
|
||||
|
||||
val initPeerId: TransformConfig.Const =
|
||||
TransformConfig.Const(
|
||||
"INIT_PEER_ID",
|
||||
LiteralModel.initPeerId
|
||||
)
|
||||
|
||||
val nil: TransformConfig.Const =
|
||||
TransformConfig.Const(
|
||||
"nil", // TODO: shouldn't it be NIL?
|
||||
LiteralModel.nil
|
||||
)
|
||||
|
||||
val lastError: TransformConfig.Const =
|
||||
TransformConfig.Const(
|
||||
"LAST_ERROR",
|
||||
VarModel.lastError
|
||||
)
|
||||
|
||||
val constantsMap =
|
||||
(hostPeerId :: initPeerId :: nil :: lastError :: constants)
|
||||
.map(c => c.name -> c.value)
|
||||
.toMap
|
||||
|
||||
implicit val aquaContextMonoid: Monoid[AquaContext] = {
|
||||
val constantsMap = (hostPeerId :: constants).map(c => c.name -> c.value).toMap
|
||||
|
||||
AquaContext
|
||||
.implicits(
|
||||
AquaContext.blank
|
||||
.copy(values =
|
||||
Map(
|
||||
VarModel.lastError.name -> VarModel.lastError,
|
||||
"nil" -> LiteralModel.nil
|
||||
) ++ constantsMap
|
||||
)
|
||||
.copy(values = constantsMap)
|
||||
)
|
||||
.aquaContextMonoid
|
||||
}
|
||||
|
@ -22,14 +22,14 @@ object ConstantExpr extends Expr.Leaf {
|
||||
|
||||
override def p[F[_]: LiftParser: Comonad]: P[ConstantExpr[F]] =
|
||||
((((`const` *> ` ` *> Name
|
||||
.p[F] <* ` `) ~ `?`.?).with1 <* `=` <* ` `) ~ Value.`value`).map {
|
||||
.upper[F] <* ` `) ~ `?`.?).with1 <* `=` <* ` `) ~ Value.`value`).map {
|
||||
case ((name, mark), value) =>
|
||||
ConstantExpr(name, value, mark.nonEmpty)
|
||||
}
|
||||
|
||||
def onlyLiteral[F[_]: LiftParser: Comonad]: P[(Name[F], Literal[F])] =
|
||||
((((Name
|
||||
.p[F] <* ` `) ~ `?`.?).with1 <* `=` <* ` `) ~ Value.literal).map { case ((name, _), value) =>
|
||||
.upper[F] <* ` `) ~ `?`.?).with1 <* `=` <* ` `) ~ Value.literal).map { case ((name, _), value) =>
|
||||
(name, value)
|
||||
}
|
||||
}
|
||||
|
@ -27,4 +27,10 @@ object FromExpr {
|
||||
|
||||
def importFrom[F[_]: LiftParser: Comonad]: P[NonEmptyList[NameOrAbAs[F]]] =
|
||||
comma[NameOrAbAs[F]](nameOrAbAs[F]) <* ` ` <* `from`
|
||||
|
||||
def show[F[_]](ne: NonEmptyList[NameOrAbAs[F]]): String =
|
||||
ne.toList.map(_.fold(
|
||||
non => non._1.value + non._2.map(_.value).fold("")(" as "+_),
|
||||
non => non._1.value + non._2.map(_.value).fold("")(" as "+_)
|
||||
)).mkString(", ")
|
||||
}
|
@ -8,8 +8,11 @@ import cats.parse.Parser
|
||||
import cats.~>
|
||||
|
||||
case class ImportExpr[F[_]](filename: Literal[F]) extends FilenameExpr[F] {
|
||||
|
||||
override def mapK[K[_]: Comonad](fk: F ~> K): ImportExpr[K] =
|
||||
copy(filename.mapK(fk))
|
||||
|
||||
override def toString: String = s"import ${filename.value}"
|
||||
}
|
||||
|
||||
object ImportExpr extends HeaderExpr.Leaf {
|
||||
|
@ -12,8 +12,11 @@ case class ImportFromExpr[F[_]](
|
||||
imports: NonEmptyList[FromExpr.NameOrAbAs[F]],
|
||||
filename: Literal[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))
|
||||
|
||||
override def toString: String = s"import ${FromExpr.show(imports)} from ${filename.value}"
|
||||
}
|
||||
|
||||
object ImportFromExpr extends HeaderExpr.Leaf {
|
||||
|
@ -11,8 +11,12 @@ case class UseExpr[F[_]](
|
||||
filename: Literal[F],
|
||||
asModule: Option[Ability[F]]
|
||||
) extends FilenameExpr[F] {
|
||||
|
||||
override def mapK[K[_]: Comonad](fk: F ~> K): UseExpr[K] =
|
||||
copy(filename.mapK(fk), asModule.map(_.mapK(fk)))
|
||||
|
||||
override def toString(): String =
|
||||
s"use ${filename.value}${asModule.map(_.value).fold("")(" as " + _)}"
|
||||
}
|
||||
|
||||
object UseExpr extends HeaderExpr.Leaf {
|
||||
|
@ -16,6 +16,9 @@ case class UseFromExpr[F[_]](
|
||||
|
||||
override def mapK[K[_]: Comonad](fk: F ~> K): UseFromExpr[K] =
|
||||
copy(FromExpr.mapK(imports)(fk), filename.mapK(fk), asModule.mapK(fk))
|
||||
|
||||
override def toString(): String =
|
||||
s"use ${FromExpr.show(imports)} from ${filename.value} as ${asModule.value}"
|
||||
}
|
||||
|
||||
object UseFromExpr extends HeaderExpr.Leaf {
|
||||
|
@ -24,8 +24,11 @@ object Name {
|
||||
def p[F[_]: LiftParser: Comonad]: P[Name[F]] =
|
||||
`name`.lift.map(Name(_))
|
||||
|
||||
def upper[F[_]: LiftParser: Comonad]: P[Name[F]] =
|
||||
NAME.lift.map(Name(_))
|
||||
|
||||
def dotted[F[_]: LiftParser: Comonad]: P[Name[F]] =
|
||||
((`Class`.repSep(`.`).map(_.toList.mkString(".")) ~ `.`).?.with1 ~ `name`).string.lift
|
||||
((`Class` ~ `.`).backtrack.rep0.?.with1 ~ P.oneOf(`name` :: NAME :: Nil)).string.lift
|
||||
.map(Name(_))
|
||||
|
||||
def nameAs[F[_]: LiftParser: Comonad]: P[As[F]] =
|
||||
|
@ -19,8 +19,10 @@ object Token {
|
||||
private val AZ = ('A' to 'Z').toSet
|
||||
private val f09 = ('0' to '9').toSet
|
||||
private val anum = az ++ AZ ++ f09
|
||||
private val upperAnum = AZ ++ f09
|
||||
private val f_ = Set('_')
|
||||
private val anum_ = anum ++ f_
|
||||
private val upperAnum_ = upperAnum ++ f_
|
||||
private val nl = Set('\n', '\r')
|
||||
|
||||
val ` *` : P0[String] = P.charsWhile0(fSpaces)
|
||||
@ -59,9 +61,10 @@ object Token {
|
||||
val ` : ` : P[Unit] = P.char(':').surroundedBy(` `.?)
|
||||
val `anum_*` : P[Unit] = P.charsWhile(anum_).void
|
||||
|
||||
val NAME: P[String] = P.charsWhile(upperAnum_).string
|
||||
val `name`: P[String] = (P.charIn(az) ~ P.charsWhile(anum_).?).string
|
||||
|
||||
val `Class`: P[String] = (P.charIn(AZ) ~ P.charsWhile(anum_).?).map { case (c, s) ⇒
|
||||
val `Class`: P[String] = (P.charIn(AZ) ~ P.charsWhile(anum_).backtrack.?).map { case (c, s) ⇒
|
||||
c.toString ++ s.getOrElse("")
|
||||
}
|
||||
val `\n` : P[Unit] = P.string("\n\r") | P.char('\n') | P.string("\r\n")
|
||||
|
@ -18,16 +18,16 @@ class AssignmentExprSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
||||
AssignmentExpr[Id]("a", toVar("b"))
|
||||
)
|
||||
|
||||
parseConstant("const a = b") should be(
|
||||
ConstantExpr[Id]("a", toVar("b"), skipIfAlreadyDefined = false)
|
||||
parseConstant("const A = B") should be(
|
||||
ConstantExpr[Id]("A", toVar("B"), skipIfAlreadyDefined = false)
|
||||
)
|
||||
|
||||
parseConstant("const a = 1") should be(
|
||||
ConstantExpr[Id]("a", toNumber(1), skipIfAlreadyDefined = false)
|
||||
parseConstant("const A = 1") should be(
|
||||
ConstantExpr[Id]("A", toNumber(1), skipIfAlreadyDefined = false)
|
||||
)
|
||||
|
||||
parseConstant("const a ?= 1") should be(
|
||||
ConstantExpr[Id]("a", toNumber(1), skipIfAlreadyDefined = true)
|
||||
parseConstant("const A ?= 1") should be(
|
||||
ConstantExpr[Id]("A", toNumber(1), skipIfAlreadyDefined = true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,12 @@ class FromSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
||||
|
||||
import AquaSpec.*
|
||||
|
||||
"from constants" should "be parsed" in {
|
||||
FromExpr.nameOrAbAs[Id].parseAll("SOME_CONSTANT").value shouldBe Right((toAb("SOME_CONSTANT"), None))
|
||||
|
||||
FromExpr.nameOrAbAs[Id].parseAll("SOME_CONSTANT as SC").value shouldBe Right((toAb("SOME_CONSTANT"), Some(toAb("SC"))))
|
||||
}
|
||||
|
||||
"from expression" should "be parsed" in {
|
||||
FromExpr.nameOrAbAs[Id].parseAll("Ability").value should be(Right(toAb("Ability") -> None))
|
||||
FromExpr.nameOrAbAs[Id].parseAll("Ability as Ab").value should be(
|
||||
|
30
parser/src/test/scala/aqua/parser/head/UseSpec.scala
Normal file
30
parser/src/test/scala/aqua/parser/head/UseSpec.scala
Normal file
@ -0,0 +1,30 @@
|
||||
package aqua.parser.head
|
||||
|
||||
import aqua.AquaSpec
|
||||
import aqua.parser.expr.AbilityIdExpr
|
||||
import aqua.parser.lexer.{Literal, Token}
|
||||
import aqua.parser.lift.LiftParser.Implicits.*
|
||||
import aqua.types.LiteralType
|
||||
import cats.Id
|
||||
import cats.data.NonEmptyList
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class UseSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
||||
|
||||
import AquaSpec.*
|
||||
|
||||
"use" should "be parsed" in {
|
||||
UseFromExpr.p[Id].parseAll("use DECLARE_CONST2 as DC2 from \"declare.aqua\" as Declare").value shouldBe
|
||||
UseFromExpr(
|
||||
NonEmptyList.one(Right((toAb("DECLARE_CONST2"), Some(toAb("DC2"))))),
|
||||
toStr("declare.aqua"),
|
||||
toAb("Declare"))
|
||||
|
||||
UseFromExpr.p[Id].parseAll("use DECLARE_CONST from \"declare.aqua\" as Declare").value shouldBe
|
||||
UseFromExpr(
|
||||
NonEmptyList.one(Right((toAb("DECLARE_CONST"), None))),
|
||||
toStr("declare.aqua"),
|
||||
toAb("Declare"))
|
||||
}
|
||||
}
|
@ -44,4 +44,12 @@ class TokenSpec extends AnyFlatSpec with Matchers with EitherValues {
|
||||
|""".stripMargin).value should be(())
|
||||
}
|
||||
|
||||
"name token" should "parse" in {
|
||||
`name`.parseAll("some_name").value should be("some_name")
|
||||
}
|
||||
|
||||
"NAME token" should "parse" in {
|
||||
NAME.parseAll("SOME_NAME").value should be("SOME_NAME")
|
||||
}
|
||||
|
||||
}
|
||||
|
26
parser/src/test/scala/aqua/parser/lexer/VarLambdaSpec.scala
Normal file
26
parser/src/test/scala/aqua/parser/lexer/VarLambdaSpec.scala
Normal file
@ -0,0 +1,26 @@
|
||||
package aqua.parser.lexer
|
||||
|
||||
import aqua.parser.lift.LiftParser.Implicits.idLiftParser
|
||||
import cats.Id
|
||||
import cats.data.NonEmptyList
|
||||
import org.scalatest.EitherValues
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class VarLambdaSpec extends AnyFlatSpec with Matchers with EitherValues {
|
||||
|
||||
"var lambda" should "parse" in {
|
||||
val opsP = (s: String) => Name.dotted[Id].parseAll(s).value
|
||||
|
||||
opsP("SomeClass.some_val") should be(Name[Id]("SomeClass.some_val"))
|
||||
|
||||
opsP("some_val") should be(Name[Id]("some_val"))
|
||||
|
||||
opsP("SOME_CONST") should be(Name[Id]("SOME_CONST"))
|
||||
|
||||
opsP("SomeClass.SOME_CONST") should be(Name[Id]("SomeClass.SOME_CONST"))
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -18,15 +18,12 @@ case class CompilerState[F[_]](
|
||||
object CompilerState {
|
||||
type S[F[_]] = State[CompilerState[F], Model]
|
||||
|
||||
def init[F[_]](ctx: AquaContext): CompilerState[F] = {
|
||||
// TODO: should go to Monoid[AquaContext].empty, along with overriden constants
|
||||
val withLE = ctx.copy(values = ctx.values + ("%last_error%" -> VarModel.lastError))
|
||||
def init[F[_]](ctx: AquaContext): CompilerState[F] =
|
||||
CompilerState(
|
||||
names = NamesState.init[F](withLE),
|
||||
abilities = AbilitiesState.init[F](withLE),
|
||||
types = TypesState.init[F](withLE)
|
||||
names = NamesState.init[F](ctx),
|
||||
abilities = AbilitiesState.init[F](ctx),
|
||||
types = TypesState.init[F](ctx)
|
||||
)
|
||||
}
|
||||
|
||||
implicit def compilerStateMonoid[F[_]]: Monoid[S[F]] = new Monoid[S[F]] {
|
||||
override def empty: S[F] = State.pure(EmptyModel("compiler state monoid empty"))
|
||||
|
@ -58,6 +58,7 @@ object HeaderSem {
|
||||
def resolve(f: FilenameExpr[S]): ResAC[S] =
|
||||
imports
|
||||
.get(f.fileValue)
|
||||
.map(_.pickDeclared)
|
||||
.fold[ResAC[S]](
|
||||
error(f.token, "Cannot resolve the import")
|
||||
)(validNec)
|
||||
@ -91,7 +92,7 @@ object HeaderSem {
|
||||
}
|
||||
)
|
||||
)
|
||||
.reduce
|
||||
.foldLeft[ResAC[S]](validNec(ctx.pickHeader))(_ |+| _)
|
||||
|
||||
// Convert an imported context into a module (ability)
|
||||
def toModule(ctx: AquaContext, tkn: Token[S], rename: Option[Ability[S]]): ResAC[S] =
|
||||
@ -103,7 +104,7 @@ object HeaderSem {
|
||||
tkn,
|
||||
s"Used module has no `module` header. Please add `module` header or use ... as ModuleName, or switch to import"
|
||||
)
|
||||
)(modName => validNec(acm.empty.copy(abilities = Map(modName -> ctx))))
|
||||
)(modName => validNec(AquaContext.blank.copy(abilities = Map(modName -> ctx))))
|
||||
|
||||
// Handler for every header expression, will be combined later
|
||||
val onExpr: PartialFunction[HeaderExpr[S], Res[S]] = {
|
||||
@ -154,27 +155,33 @@ object HeaderSem {
|
||||
// Import, map declarations
|
||||
resolve(f)
|
||||
.andThen(getFrom(f, _))
|
||||
.map(ctx => HeaderSem[S](ctx, (c, _) => validNec(c)))
|
||||
.map { ctx =>
|
||||
HeaderSem[S](ctx, (c, _) => validNec(c))
|
||||
}
|
||||
|
||||
case f @ UseExpr(_, asModule) =>
|
||||
// Import, move into a module scope
|
||||
resolve(f)
|
||||
.andThen(toModule(_, f.token, asModule))
|
||||
.map(fc => HeaderSem[S](fc, (c, _) => validNec(c)))
|
||||
.map { fc =>
|
||||
HeaderSem[S](fc, (c, _) => validNec(c))
|
||||
}
|
||||
|
||||
case f @ UseFromExpr(_, _, asModule) =>
|
||||
// Import, cherry-pick declarations, move to a module scope
|
||||
resolve(f)
|
||||
.andThen(getFrom(f, _))
|
||||
.andThen(toModule(_, f.token, Some(asModule)))
|
||||
.map(fc => HeaderSem[S](fc, (c, _) => validNec(c)))
|
||||
.map { fc =>
|
||||
HeaderSem[S](fc, (c, _) => validNec(c))
|
||||
}
|
||||
|
||||
case ExportExpr(pubs) =>
|
||||
// Save exports, finally handle them
|
||||
validNec(
|
||||
HeaderSem[S](
|
||||
// Nothing there
|
||||
acm.empty,
|
||||
AquaContext.blank,
|
||||
(ctx, initCtx) =>
|
||||
pubs
|
||||
.map(
|
||||
@ -197,7 +204,7 @@ object HeaderSem {
|
||||
}
|
||||
)
|
||||
)
|
||||
.foldLeft[ResAC[S]](validNec(ctx.exports.getOrElse(acm.empty)))(_ |+| _)
|
||||
.foldLeft[ResAC[S]](validNec(ctx.exports.getOrElse(AquaContext.blank)))(_ |+| _)
|
||||
.map(expCtx => ctx.copy(exports = Some(expCtx)))
|
||||
)
|
||||
)
|
||||
|
@ -39,7 +39,7 @@ class ValuesAlgebra[F[_], Alg[_]](implicit N: NamesAlgebra[F, Alg], T: TypesAlge
|
||||
case Some(t) =>
|
||||
T.resolveLambda(t, ops)
|
||||
.map(Chain.fromSeq)
|
||||
.map(VarModel(name.value.replace('.', '_'), t, _))
|
||||
.map(VarModel(name.value, t, _))
|
||||
.map(Some(_))
|
||||
case None =>
|
||||
Free.pure(None)
|
||||
|
Loading…
Reference in New Issue
Block a user