mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 06:30:17 +00:00
Imports/exports fixes (#258)
* Fix for export in headerless file * Ability arrow resolution bugfix * Trying to reproduce a bug * Allow dots in module declaration
This commit is contained in:
parent
bc461457da
commit
3e7b11db10
16
aqua-src/export.aqua
Normal file
16
aqua-src/export.aqua
Normal file
@ -0,0 +1,16 @@
|
||||
module Export.Test declares foobar, foo, bar
|
||||
|
||||
func bar() -> string:
|
||||
<- " I am MyFooBar bar"
|
||||
|
||||
func foo() -> string:
|
||||
<- "I am MyFooBar foo"
|
||||
|
||||
func foobar() -> []string:
|
||||
res: *string
|
||||
res <- foo()
|
||||
res <- bar()
|
||||
<- res
|
||||
|
||||
service ExpSrv:
|
||||
baz()
|
3
aqua-src/gen/OneMore.aqua
Normal file
3
aqua-src/gen/OneMore.aqua
Normal file
@ -0,0 +1,3 @@
|
||||
service OneMore:
|
||||
more_call()
|
||||
consume(s: string)
|
23
aqua-src/import.aqua
Normal file
23
aqua-src/import.aqua
Normal file
@ -0,0 +1,23 @@
|
||||
-- import.aqua
|
||||
module Import.Test
|
||||
import foobar from "export.aqua"
|
||||
|
||||
use foo as f from "export.aqua" as Exp
|
||||
|
||||
use "export.aqua"
|
||||
|
||||
import "gen/OneMore.aqua"
|
||||
|
||||
import OneMore as OM from "gen/OneMore.aqua"
|
||||
|
||||
export foo_wrapper as wrap, foobar as barfoo
|
||||
|
||||
func foo_wrapper() -> string:
|
||||
z <- Exp.f()
|
||||
q <- Export.Test.bar()
|
||||
OneMore "hello"
|
||||
OneMore.more_call()
|
||||
OM "ohmygod"
|
||||
OM.more_call()
|
||||
OM.consume(q)
|
||||
<- z
|
@ -17,7 +17,7 @@ val declineV = "2.1.0"
|
||||
name := "aqua-hll"
|
||||
|
||||
val commons = Seq(
|
||||
baseAquaVersion := "0.2.0",
|
||||
baseAquaVersion := "0.2.1",
|
||||
version := baseAquaVersion.value + "-" + sys.env.getOrElse("BUILD_NUMBER", "SNAPSHOT"),
|
||||
scalaVersion := dottyVersion,
|
||||
libraryDependencies ++= Seq(
|
||||
@ -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)
|
||||
|
@ -5,6 +5,7 @@ import aqua.model.func.{ArgsCall, FuncCallable, FuncModel}
|
||||
import aqua.types.{StructType, Type}
|
||||
import cats.Monoid
|
||||
import cats.data.NonEmptyMap
|
||||
import cats.kernel.Semigroup
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.monoid.*
|
||||
import scribe.Logging
|
||||
@ -150,37 +151,34 @@ object AquaContext extends Logging {
|
||||
)
|
||||
|
||||
def fromScriptModel(sm: ScriptModel, init: AquaContext)(implicit
|
||||
aqum: Monoid[AquaContext]
|
||||
aqum: Semigroup[AquaContext]
|
||||
): AquaContext =
|
||||
sm.models
|
||||
.foldLeft((init, Monoid.empty[AquaContext])) {
|
||||
.foldLeft((init, blank)) {
|
||||
case ((ctx, exportContext), c: ConstantModel) =>
|
||||
val add =
|
||||
Monoid
|
||||
.empty[AquaContext]
|
||||
blank
|
||||
.copy(values =
|
||||
if (c.allowOverrides && ctx.values.contains(c.name)) ctx.values
|
||||
else ctx.values.updated(c.name, c.value.resolveWith(ctx.values))
|
||||
if (c.allowOverrides && ctx.values.contains(c.name)) Map.empty
|
||||
else Map(c.name -> c.value.resolveWith(ctx.values))
|
||||
)
|
||||
(ctx |+| add, exportContext |+| add)
|
||||
case ((ctx, exportContext), func: FuncModel) =>
|
||||
val fr = func.capture(ctx.allFuncs(), ctx.allValues())
|
||||
val add =
|
||||
Monoid.empty[AquaContext].copy(funcs = ctx.funcs.updated(func.name, fr))
|
||||
blank.copy(funcs = Map(func.name -> fr))
|
||||
(ctx |+| add, exportContext |+| add)
|
||||
case ((ctx, exportContext), t: TypeModel) =>
|
||||
val add =
|
||||
Monoid.empty[AquaContext].copy(types = ctx.types.updated(t.name, t.`type`))
|
||||
blank.copy(types = Map(t.name -> t.`type`))
|
||||
(ctx |+| add, exportContext |+| add)
|
||||
case ((ctx, exportContext), m: ServiceModel) =>
|
||||
val add =
|
||||
Monoid
|
||||
.empty[AquaContext]
|
||||
blank
|
||||
.copy(
|
||||
abilities = m.defaultId.fold(ctx.abilities)(id =>
|
||||
ctx.abilities.updated(m.name, fromServiceModel(m, id))
|
||||
),
|
||||
services = ctx.services.updated(m.name, m)
|
||||
abilities =
|
||||
m.defaultId.fold(Map.empty)(id => Map(m.name -> fromServiceModel(m, id))),
|
||||
services = Map(m.name -> m)
|
||||
)
|
||||
(ctx |+| add, exportContext |+| add)
|
||||
case (ce, _) => ce
|
||||
|
@ -40,7 +40,7 @@ object ModuleExpr extends HeaderExpr.Leaf {
|
||||
nameOrAbList[F].map(Left(_)) | `star`.lift.map(Token.lift(_)).map(Right(_))
|
||||
|
||||
override def p[F[_]: LiftParser: Comonad]: Parser[ModuleExpr[F]] =
|
||||
(`module` *> ` ` *> Ability.ab[F] ~
|
||||
(`module` *> ` ` *> Ability.dotted[F] ~
|
||||
(` declares ` *> nameOrAbListOrAll[F]).?).map {
|
||||
case (name, None) =>
|
||||
ModuleExpr(name, None, Nil, Nil)
|
||||
|
@ -13,11 +13,16 @@ import cats.syntax.semigroup.*
|
||||
import cats.instances.list.*
|
||||
import cats.instances.option.*
|
||||
import cats.free.Cofree
|
||||
import cats.kernel.Semigroup
|
||||
|
||||
case class HeaderSem[S[_]](
|
||||
initCtx: AquaContext,
|
||||
finCtx: AquaContext => ValidatedNec[SemanticError[S], AquaContext]
|
||||
)
|
||||
finInitCtx: (AquaContext, AquaContext) => ValidatedNec[SemanticError[S], AquaContext]
|
||||
) {
|
||||
|
||||
def finCtx: AquaContext => ValidatedNec[SemanticError[S], AquaContext] =
|
||||
finInitCtx(_, initCtx)
|
||||
}
|
||||
|
||||
object HeaderSem {
|
||||
type Res[S[_]] = ValidatedNec[SemanticError[S], HeaderSem[S]]
|
||||
@ -27,12 +32,12 @@ object HeaderSem {
|
||||
acm: Monoid[AquaContext]
|
||||
): Monoid[HeaderSem[S]] =
|
||||
new Monoid[HeaderSem[S]] {
|
||||
override def empty: HeaderSem[S] = HeaderSem(acm.empty, validNec(_))
|
||||
override def empty: HeaderSem[S] = HeaderSem(acm.empty, (c, _) => validNec(c))
|
||||
|
||||
override def combine(a: HeaderSem[S], b: HeaderSem[S]): HeaderSem[S] =
|
||||
HeaderSem(
|
||||
a.initCtx |+| b.initCtx,
|
||||
a.finCtx.andThen(_.andThen(b.finCtx))
|
||||
(c, i) => a.finInitCtx(c, i).andThen(b.finInitCtx(_, i))
|
||||
)
|
||||
}
|
||||
|
||||
@ -69,7 +74,7 @@ object HeaderSem {
|
||||
.getOrElse(
|
||||
error(
|
||||
n,
|
||||
s"Imported file declares [${ctx.declares.mkString(", ")}], no ${n.value} declared. Try adding `declares *` to that file."
|
||||
s"Imported file `declares ${ctx.declares.mkString(", ")}`, no ${n.value} declared. Try adding `declares ${n.value}` to that file."
|
||||
)
|
||||
)
|
||||
},
|
||||
@ -80,7 +85,7 @@ object HeaderSem {
|
||||
.getOrElse(
|
||||
error(
|
||||
n,
|
||||
s"Imported file declares [${ctx.declares.mkString(", ")}], no ${n.value} declared. Try adding `declares *` to that file."
|
||||
s"Imported file `declares ${ctx.declares.mkString(", ")}`, no ${n.value} declared. Try adding `declares ${n.value}` to that file."
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -112,7 +117,7 @@ object HeaderSem {
|
||||
module = Some(name.value),
|
||||
declares = shouldDeclare
|
||||
),
|
||||
ctx =>
|
||||
(ctx, _) =>
|
||||
// When file is handled, check that all the declarations exists
|
||||
if (declareAll.nonEmpty)
|
||||
validNec(
|
||||
@ -144,25 +149,25 @@ object HeaderSem {
|
||||
|
||||
case f @ ImportExpr(_) =>
|
||||
// Import everything from a file
|
||||
resolve(f).map(fc => HeaderSem[S](fc, validNec(_)))
|
||||
resolve(f).map(fc => HeaderSem[S](fc, (c, _) => validNec(c)))
|
||||
case f @ ImportFromExpr(_, _) =>
|
||||
// Import, map declarations
|
||||
resolve(f)
|
||||
.andThen(getFrom(f, _))
|
||||
.map(ctx => HeaderSem[S](ctx, validNec(_)))
|
||||
.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, validNec(_)))
|
||||
.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, validNec(_)))
|
||||
.map(fc => HeaderSem[S](fc, (c, _) => validNec(c)))
|
||||
|
||||
case ExportExpr(pubs) =>
|
||||
// Save exports, finally handle them
|
||||
@ -170,12 +175,12 @@ object HeaderSem {
|
||||
HeaderSem[S](
|
||||
// Nothing there
|
||||
acm.empty,
|
||||
ctx =>
|
||||
(ctx, initCtx) =>
|
||||
pubs
|
||||
.map(
|
||||
_.fold(
|
||||
{ case (n, rn) =>
|
||||
ctx
|
||||
(initCtx |+| ctx)
|
||||
.pick(n.value, rn.map(_.value), declared = false)
|
||||
.map(validNec)
|
||||
.getOrElse(
|
||||
@ -183,7 +188,7 @@ object HeaderSem {
|
||||
)
|
||||
},
|
||||
{ case (n, rn) =>
|
||||
ctx
|
||||
(initCtx |+| ctx)
|
||||
.pick(n.value, rn.map(_.value), declared = false)
|
||||
.map(validNec)
|
||||
.getOrElse(
|
||||
@ -198,11 +203,11 @@ object HeaderSem {
|
||||
)
|
||||
|
||||
case HeadExpr(token) =>
|
||||
// Old file exports everything
|
||||
validNec(HeaderSem[S](acm.empty, ctx => validNec(ctx.copy(exports = Some(ctx)))))
|
||||
// Old file exports everything that it declares
|
||||
validNec(HeaderSem[S](acm.empty, (ctx, _) => validNec(ctx.copy(exports = Some(ctx)))))
|
||||
|
||||
case f: FilenameExpr[S] =>
|
||||
resolve(f).map(fc => HeaderSem[S](fc, validNec(_)))
|
||||
resolve(f).map(fc => HeaderSem[S](fc, (c, _) => validNec(c)))
|
||||
}
|
||||
|
||||
Cofree
|
||||
|
@ -62,7 +62,7 @@ class AbilitiesInterpreter[F[_], X](implicit
|
||||
s"Ability is found, but arrow is undefined, available: ${abCtx.funcs.keys.toList
|
||||
.mkString(", ")}"
|
||||
).as(Option.empty[ArrowType])
|
||||
)(a => State.pure(Some(a)))
|
||||
)(fn => State.pure(Some(fn.arrowType)))
|
||||
case None =>
|
||||
report(ga.name, "Ability with this name is undefined").as(Option.empty[ArrowType])
|
||||
}
|
||||
|
@ -199,7 +199,9 @@ case class ArrowType(domain: ProductType, codomain: ProductType) extends Type {
|
||||
s"$domain -> $codomain"
|
||||
}
|
||||
|
||||
case class StreamType(element: Type) extends BoxType
|
||||
case class StreamType(element: Type) extends BoxType {
|
||||
override def toString: String = s"*$element"
|
||||
}
|
||||
|
||||
object Type {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user