mirror of
https://github.com/fluencelabs/aqua.git
synced 2025-04-24 22:42:13 +00:00
AssignmentExpression (#155)
* AssignmentExpression * Increment minor version due to syntax enhancement * Don't generate (null) for assignment tags * AbilityIdTag * Added defaultId to ServiceModel * fix compilation Co-authored-by: DieMyst <dmitry.shakhtarin@fluence.ai>
This commit is contained in:
parent
15f582eaf9
commit
d300a7dea3
@ -3,8 +3,18 @@ service OpH("op"):
|
||||
|
||||
func a(b: string) -> string:
|
||||
c <- OpH.puk(b)
|
||||
e = "hello"
|
||||
OpH.puk(e)
|
||||
|
||||
f = "world"
|
||||
OpH "planet"
|
||||
OpH.puk(f)
|
||||
|
||||
x = "!!!"
|
||||
OpH.puk(x)
|
||||
<- c
|
||||
|
||||
func d(e: string) -> string:
|
||||
f <- a(e)
|
||||
OpH.puk("in func d(e) now")
|
||||
<- f
|
||||
|
@ -3,12 +3,11 @@ package aqua.backend.air
|
||||
import aqua.model._
|
||||
import aqua.model.func.Call
|
||||
import aqua.model.func.body._
|
||||
import aqua.types.{OptionType, StreamType}
|
||||
import aqua.types.StreamType
|
||||
import cats.Eval
|
||||
import cats.data.Chain
|
||||
import cats.free.Cofree
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import wvlet.log.Logger
|
||||
|
||||
sealed trait AirGen {
|
||||
def generate: Air
|
||||
@ -17,6 +16,9 @@ sealed trait AirGen {
|
||||
|
||||
object AirGen {
|
||||
|
||||
private val logger = Logger.of[AirGen.type]
|
||||
import logger._
|
||||
|
||||
def lambdaToString(ls: List[LambdaModel]): String = ls match {
|
||||
case Nil => ""
|
||||
case IntoArrayModel(_) :: tail =>
|
||||
@ -85,8 +87,8 @@ object AirGen {
|
||||
|
||||
case CallArrowTag(funcName, _) =>
|
||||
// TODO: should be already resolved & removed from tree
|
||||
println(
|
||||
Console.RED + s"Unresolved arrow in AirGen: $funcName" + Console.RESET
|
||||
error(
|
||||
s"Unresolved arrow in AirGen: $funcName"
|
||||
)
|
||||
Eval later NullGen
|
||||
|
||||
@ -95,10 +97,13 @@ object AirGen {
|
||||
Eval later opsToSingle(
|
||||
ops
|
||||
)
|
||||
case _: NoAirTag =>
|
||||
// TODO: should be already resolved & removed from tree
|
||||
Eval later NullGen
|
||||
case XorParTag(opsx, opsy) =>
|
||||
// TODO should be resolved
|
||||
println(
|
||||
Console.RED + "XorParTag reached AirGen, most likely it's an error" + Console.RESET
|
||||
error(
|
||||
"XorParTag reached AirGen, most likely it's an error"
|
||||
)
|
||||
Eval later opsToSingle(
|
||||
Chain(apply(opsx.tree), apply(opsy.tree))
|
||||
|
25
build.sbt
25
build.sbt
@ -24,12 +24,13 @@ val airframeLog = "org.wvlet.airframe" %% "airframe-log" % airframeLogV
|
||||
name := "aqua-hll"
|
||||
|
||||
val commons = Seq(
|
||||
baseAquaVersion := "0.1.4",
|
||||
baseAquaVersion := "0.1.5",
|
||||
version := baseAquaVersion.value + "-" + sys.env.getOrElse("BUILD_NUMBER", "SNAPSHOT"),
|
||||
scalaVersion := dottyVersion,
|
||||
libraryDependencies ++= Seq(
|
||||
"org.typelevel" %% "log4cats-core" % log4catsV,
|
||||
"org.scalatest" %% "scalatest" % scalaTestV % Test
|
||||
airframeLog,
|
||||
"org.scalatest" %% "scalatest" % scalaTestV % Test
|
||||
),
|
||||
addCompilerPlugin("org.typelevel" %% "kind-projector" % "0.11.3" cross CrossVersion.full)
|
||||
)
|
||||
@ -43,16 +44,15 @@ lazy val cli = project
|
||||
assembly / mainClass := Some("aqua.AquaCli"),
|
||||
assembly / assemblyJarName := "aqua-cli-" + version.value + ".jar",
|
||||
libraryDependencies ++= Seq(
|
||||
"com.monovore" %% "decline" % declineV,
|
||||
"com.monovore" %% "decline-effect" % declineV,
|
||||
"org.typelevel" %% "cats-effect" % catsEffectV,
|
||||
"co.fs2" %% "fs2-core" % fs2V,
|
||||
"co.fs2" %% "fs2-io" % fs2V,
|
||||
"org.typelevel" %% "log4cats-slf4j" % log4catsV,
|
||||
airframeLog,
|
||||
"com.beachape" %% "enumeratum" % enumeratumV,
|
||||
"org.slf4j" % "slf4j-jdk14" % slf4jV,
|
||||
"com.monovore" %% "decline-enumeratum" % declineEnumV
|
||||
"com.monovore" %% "decline" % declineV,
|
||||
"com.monovore" %% "decline-effect" % declineV,
|
||||
"org.typelevel" %% "cats-effect" % catsEffectV,
|
||||
"co.fs2" %% "fs2-core" % fs2V,
|
||||
"co.fs2" %% "fs2-io" % fs2V,
|
||||
"org.typelevel" %% "log4cats-slf4j" % log4catsV,
|
||||
"com.beachape" %% "enumeratum" % enumeratumV,
|
||||
"org.slf4j" % "slf4j-jdk14" % slf4jV,
|
||||
"com.monovore" %% "decline-enumeratum" % declineEnumV
|
||||
)
|
||||
)
|
||||
.dependsOn(semantics, `backend-air`, `backend-ts`, linker)
|
||||
@ -88,7 +88,6 @@ lazy val model = project
|
||||
.settings(commons: _*)
|
||||
.settings(
|
||||
libraryDependencies ++= Seq(
|
||||
airframeLog,
|
||||
"org.typelevel" %% "cats-free" % catsV
|
||||
)
|
||||
)
|
||||
|
@ -3,4 +3,8 @@ package aqua.model
|
||||
import aqua.types.ArrowType
|
||||
import cats.data.NonEmptyMap
|
||||
|
||||
case class ServiceModel(name: String, arrows: NonEmptyMap[String, ArrowType]) extends Model
|
||||
case class ServiceModel(
|
||||
name: String,
|
||||
arrows: NonEmptyMap[String, ArrowType],
|
||||
defaultId: Option[ValueModel]
|
||||
) extends Model
|
||||
|
@ -1,6 +1,6 @@
|
||||
package aqua.model.func
|
||||
|
||||
import aqua.model.func.body.{CallArrowTag, FuncOp, OpTag}
|
||||
import aqua.model.func.body.{AssignmentTag, CallArrowTag, FuncOp, OpTag}
|
||||
import aqua.model.{ValueModel, VarModel}
|
||||
import aqua.types.{ArrowType, Type}
|
||||
import cats.Eval
|
||||
@ -82,6 +82,15 @@ case class FuncCallable(
|
||||
// Functions may export variables, so collect them
|
||||
capturedValues
|
||||
) {
|
||||
case ((noNames, resolvedExports), tag @ AssignmentTag(value, assignTo)) =>
|
||||
(noNames, resolvedExports + (assignTo -> value.resolveWith(resolvedExports))) -> Cofree[
|
||||
Chain,
|
||||
OpTag
|
||||
](
|
||||
tag.mapValues(_.resolveWith(resolvedExports)),
|
||||
Eval.now(Chain.empty)
|
||||
)
|
||||
|
||||
case ((noNames, resolvedExports), CallArrowTag(fn, c)) if allArrows.contains(fn) =>
|
||||
// Apply arguments to a function – recursion
|
||||
val callResolved = c.mapValues(_.resolveWith(resolvedExports))
|
||||
|
@ -42,6 +42,7 @@ case class FuncOp(tree: Cofree[Chain, OpTag]) extends Model {
|
||||
} match {
|
||||
case c: CallArrowTag => c.copy(call = c.call.mapExport(n => vals.getOrElse(n, n)))
|
||||
case c: CallServiceTag => c.copy(call = c.call.mapExport(n => vals.getOrElse(n, n)))
|
||||
case a: AssignmentTag => a.copy(assignTo = vals.getOrElse(a.assignTo, a.assignTo))
|
||||
case t: ForTag if vals.contains(t.item) => t.copy(item = vals(t.item))
|
||||
case t: NextTag if vals.contains(t.item) => t.copy(item = vals(t.item))
|
||||
case t => t
|
||||
|
@ -23,10 +23,17 @@ sealed trait OpTag {
|
||||
call.mapValues(f),
|
||||
pid.map(f)
|
||||
)
|
||||
case AssignmentTag(value, assignTo) =>
|
||||
AssignmentTag(f(value), assignTo)
|
||||
case AbilityIdTag(value, ability) =>
|
||||
AssignmentTag(f(value), ability)
|
||||
case _ => this
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sealed trait NoAirTag extends OpTag
|
||||
|
||||
sealed trait GroupTag extends OpTag
|
||||
sealed trait SeqGroupTag extends GroupTag
|
||||
|
||||
@ -55,6 +62,16 @@ case class CallArrowTag(
|
||||
call: Call
|
||||
) extends OpTag
|
||||
|
||||
case class AssignmentTag(
|
||||
value: ValueModel,
|
||||
assignTo: String
|
||||
) extends NoAirTag
|
||||
|
||||
case class AbilityIdTag(
|
||||
value: ValueModel,
|
||||
service: String
|
||||
) extends NoAirTag
|
||||
|
||||
case class CallServiceTag(
|
||||
serviceId: ValueModel,
|
||||
funcName: String,
|
||||
|
@ -10,6 +10,17 @@ import cats.free.Cofree
|
||||
|
||||
object Transform {
|
||||
|
||||
def defaultFilter(t: OpTag): Boolean = t match {
|
||||
case _: NoAirTag => false
|
||||
case _ => true
|
||||
}
|
||||
|
||||
def clear(
|
||||
tree: Cofree[Chain, OpTag],
|
||||
filter: OpTag => Boolean = defaultFilter
|
||||
): Cofree[Chain, OpTag] =
|
||||
tree.copy(tail = tree.tail.map(_.filter(t => filter(t.head)).map(clear(_, filter))))
|
||||
|
||||
def forClient(func: FuncCallable, conf: BodyConfig): Cofree[Chain, OpTag] = {
|
||||
val initCallable: InitPeerCallable = InitViaRelayCallable(
|
||||
Chain.fromOption(conf.relayVarName).map(VarModel(_, ScalarType.string))
|
||||
@ -38,13 +49,14 @@ object Transform {
|
||||
callback,
|
||||
conf.respFuncName
|
||||
)
|
||||
|
||||
Topology.resolve(
|
||||
errorsCatcher
|
||||
.transform(
|
||||
wrapFunc.resolve(func).value
|
||||
)
|
||||
.tree
|
||||
clear(
|
||||
Topology.resolve(
|
||||
errorsCatcher
|
||||
.transform(
|
||||
wrapFunc.resolve(func).value
|
||||
)
|
||||
.tree
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ object ForExpr extends Expr.AndIndented {
|
||||
Expr.defer(ForExpr) ::
|
||||
CallArrowExpr ::
|
||||
AbilityIdExpr ::
|
||||
AssignmentExpr ::
|
||||
Expr.defer(TryExpr) ::
|
||||
Expr.defer(IfExpr) ::
|
||||
Expr.defer(ElseOtherwiseExpr) ::
|
||||
|
@ -20,6 +20,7 @@ object FuncExpr extends Expr.AndIndented {
|
||||
|
||||
override def validChildren: List[Expr.Lexem] =
|
||||
AbilityIdExpr ::
|
||||
AssignmentExpr ::
|
||||
ReturnExpr ::
|
||||
ForExpr ::
|
||||
Expr.defer(OnExpr) ::
|
||||
|
@ -16,6 +16,7 @@ object IfExpr extends Expr.AndIndented {
|
||||
Expr.defer(OnExpr) ::
|
||||
CallArrowExpr ::
|
||||
AbilityIdExpr ::
|
||||
AssignmentExpr ::
|
||||
Expr.defer(TryExpr) ::
|
||||
Expr.defer(ForExpr) ::
|
||||
Expr.defer(IfExpr) ::
|
||||
|
@ -15,6 +15,7 @@ object OnExpr extends Expr.AndIndented {
|
||||
Expr.defer(OnExpr) ::
|
||||
CallArrowExpr ::
|
||||
AbilityIdExpr ::
|
||||
AssignmentExpr ::
|
||||
ParExpr ::
|
||||
Expr.defer(TryExpr) ::
|
||||
Expr.defer(ForExpr) ::
|
||||
|
@ -19,6 +19,7 @@ object ExprSem {
|
||||
): Prog[G, Model] =
|
||||
expr match {
|
||||
case expr: AbilityIdExpr[F] => new AbilityIdSem(expr).program[G]
|
||||
case expr: AssignmentExpr[F] => new AssignmentSem(expr).program[G]
|
||||
case expr: AliasExpr[F] => new AliasSem(expr).program[G]
|
||||
case expr: ConstantExpr[F] => new ConstantSem(expr).program[G]
|
||||
case expr: DeclareStreamExpr[F] => new DeclareStreamSem(expr).program[G]
|
||||
|
@ -1,15 +1,23 @@
|
||||
package aqua.semantics.expr
|
||||
|
||||
import aqua.model.Model
|
||||
import aqua.model.func.body.{AbilityIdTag, FuncOp}
|
||||
import aqua.parser.expr.AbilityIdExpr
|
||||
import aqua.semantics.Prog
|
||||
import aqua.semantics.rules.ValuesAlgebra
|
||||
import aqua.semantics.rules.abilities.AbilitiesAlgebra
|
||||
import cats.syntax.flatMap._
|
||||
import cats.syntax.functor._
|
||||
|
||||
class AbilityIdSem[F[_]](val expr: AbilityIdExpr[F]) extends AnyVal {
|
||||
|
||||
def program[Alg[_]](implicit A: AbilitiesAlgebra[F, Alg], V: ValuesAlgebra[F, Alg]): Prog[Alg, Model] =
|
||||
V.ensureIsString(expr.id) >> A.setServiceId(expr.ability, expr.id) as Model.empty("Ability ID generates no model")
|
||||
def program[Alg[_]](implicit
|
||||
A: AbilitiesAlgebra[F, Alg],
|
||||
V: ValuesAlgebra[F, Alg]
|
||||
): Prog[Alg, Model] =
|
||||
V.ensureIsString(expr.id) >> A.setServiceId(expr.ability, expr.id) >> V.valueToModel(
|
||||
expr.id
|
||||
) map {
|
||||
case Some(id) => FuncOp.leaf(AbilityIdTag(id, expr.ability.value)): Model
|
||||
case _ => Model.error("Cannot resolve ability ID")
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
package aqua.semantics.expr
|
||||
|
||||
import aqua.model.Model
|
||||
import aqua.model.func.body.{AssignmentTag, FuncOp, FuncOps}
|
||||
import aqua.parser.expr.{AbilityIdExpr, AssignmentExpr}
|
||||
import aqua.semantics.Prog
|
||||
import aqua.semantics.rules.ValuesAlgebra
|
||||
import aqua.semantics.rules.abilities.AbilitiesAlgebra
|
||||
import aqua.semantics.rules.names.NamesAlgebra
|
||||
import cats.free.Free
|
||||
import cats.syntax.flatMap._
|
||||
import cats.syntax.functor._
|
||||
|
||||
class AssignmentSem[F[_]](val expr: AssignmentExpr[F]) extends AnyVal {
|
||||
|
||||
def program[Alg[_]](implicit
|
||||
N: NamesAlgebra[F, Alg],
|
||||
V: ValuesAlgebra[F, Alg]
|
||||
): Prog[Alg, Model] =
|
||||
V.valueToModel(expr.value).flatMap {
|
||||
case Some(vm) =>
|
||||
N.define(expr.variable, vm.lastType) as (FuncOp
|
||||
.leaf(AssignmentTag(vm, expr.variable.value)): Model)
|
||||
case _ => Free.pure[Alg, Model](Model.error("Cannot resolve assignment type"))
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package aqua.semantics.expr
|
||||
|
||||
import aqua.model.{Model, ServiceModel}
|
||||
import aqua.model.{Model, ServiceModel, ValueModel}
|
||||
import aqua.parser.expr.ServiceExpr
|
||||
import aqua.semantics.Prog
|
||||
import aqua.semantics.rules.ValuesAlgebra
|
||||
@ -10,7 +10,6 @@ import aqua.semantics.rules.types.TypesAlgebra
|
||||
import cats.free.Free
|
||||
import cats.syntax.apply._
|
||||
import cats.syntax.flatMap._
|
||||
import cats.syntax.functor._
|
||||
|
||||
class ServiceSem[F[_]](val expr: ServiceExpr[F]) extends AnyVal {
|
||||
|
||||
@ -26,18 +25,23 @@ class ServiceSem[F[_]](val expr: ServiceExpr[F]) extends AnyVal {
|
||||
(A.purgeArrows(expr.name) <* A.endScope()).flatMap {
|
||||
case Some(nel) =>
|
||||
val arrows = nel.map(kv => kv._1.value -> kv._2).toNem
|
||||
A.defineService(
|
||||
expr.name,
|
||||
arrows
|
||||
).flatMap {
|
||||
case true =>
|
||||
val srv = ServiceModel(expr.name.value, arrows)
|
||||
expr.id.fold(Free.pure[Alg, Model](srv))(idV =>
|
||||
V.ensureIsString(idV) >> A.setServiceId(expr.name, idV) as (srv: Model)
|
||||
for {
|
||||
defaultId <- expr.id
|
||||
.map(v => V.valueToModel(v))
|
||||
.getOrElse(Free.pure[Alg, Option[ValueModel]](None))
|
||||
defineResult <- A.defineService(
|
||||
expr.name,
|
||||
arrows,
|
||||
defaultId
|
||||
)
|
||||
_ <- expr.id
|
||||
.fold(Free.pure[Alg, Unit](()))(idV =>
|
||||
(V.ensureIsString(idV) >> A.setServiceId(expr.name, idV)).map(_ => ())
|
||||
)
|
||||
case false =>
|
||||
Free.pure(Model.empty("Service not created due to validation errors"))
|
||||
}
|
||||
} yield
|
||||
if (defineResult) {
|
||||
ServiceModel(expr.name.value, arrows, defaultId)
|
||||
} else Model.empty("Service not created due to validation errors")
|
||||
|
||||
case None =>
|
||||
Free.pure(Model.error("Service has no arrows, fails"))
|
||||
|
@ -1,5 +1,6 @@
|
||||
package aqua.semantics.rules.abilities
|
||||
|
||||
import aqua.model.ValueModel
|
||||
import aqua.parser.lexer.{Ability, Name, Token, Value}
|
||||
import aqua.types.ArrowType
|
||||
import cats.InjectK
|
||||
@ -14,8 +15,12 @@ class AbilitiesAlgebra[F[_], Alg[_]](implicit A: InjectK[AbilityOp[F, *], Alg])
|
||||
def purgeArrows(token: Token[F]): Free[Alg, Option[NonEmptyList[(Name[F], ArrowType)]]] =
|
||||
Free.liftInject[Alg](PurgeArrows[F](token))
|
||||
|
||||
def defineService(name: Ability[F], arrows: NonEmptyMap[String, ArrowType]): Free[Alg, Boolean] =
|
||||
Free.liftInject[Alg](DefineService[F](name, arrows))
|
||||
def defineService(
|
||||
name: Ability[F],
|
||||
arrows: NonEmptyMap[String, ArrowType],
|
||||
defaultId: Option[ValueModel]
|
||||
): Free[Alg, Boolean] =
|
||||
Free.liftInject[Alg](DefineService[F](name, arrows, defaultId))
|
||||
|
||||
def getArrow(name: Ability[F], arrow: Name[F]): Free[Alg, Option[ArrowType]] =
|
||||
Free.liftInject[Alg](GetArrow[F](name, arrow))
|
||||
|
@ -1,12 +1,12 @@
|
||||
package aqua.semantics.rules.abilities
|
||||
|
||||
import aqua.model.ServiceModel
|
||||
import aqua.semantics.rules.{ReportError, StackInterpreter}
|
||||
import aqua.parser.lexer.{Name, Value}
|
||||
import aqua.semantics.rules.{ReportError, StackInterpreter}
|
||||
import aqua.types.ArrowType
|
||||
import cats.data.{NonEmptyList, State}
|
||||
import cats.~>
|
||||
import cats.syntax.functor._
|
||||
import cats.~>
|
||||
import monocle.Lens
|
||||
import monocle.macros.GenLens
|
||||
|
||||
@ -105,8 +105,8 @@ class AbilitiesInterpreter[F[_], X](implicit
|
||||
case None =>
|
||||
modify(s =>
|
||||
s.copy(
|
||||
services =
|
||||
s.services.updated(ds.name.value, ServiceModel(ds.name.value, ds.arrows)),
|
||||
services = s.services
|
||||
.updated(ds.name.value, ServiceModel(ds.name.value, ds.arrows, ds.defaultId)),
|
||||
definitions = s.definitions.updated(ds.name.value, ds.name)
|
||||
)
|
||||
).as(true)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package aqua.semantics.rules.abilities
|
||||
|
||||
import aqua.model.ValueModel
|
||||
import aqua.parser.lexer.{Ability, Name, Token, Value}
|
||||
import aqua.types.ArrowType
|
||||
import cats.data.{NonEmptyList, NonEmptyMap}
|
||||
@ -11,8 +12,11 @@ case class DefineArrow[F[_]](arrow: Name[F], `type`: ArrowType) extends AbilityO
|
||||
case class PurgeArrows[F[_]](token: Token[F])
|
||||
extends AbilityOp[F, Option[NonEmptyList[(Name[F], ArrowType)]]]
|
||||
|
||||
case class DefineService[F[_]](name: Ability[F], arrows: NonEmptyMap[String, ArrowType])
|
||||
extends AbilityOp[F, Boolean]
|
||||
case class DefineService[F[_]](
|
||||
name: Ability[F],
|
||||
arrows: NonEmptyMap[String, ArrowType],
|
||||
defaultId: Option[ValueModel]
|
||||
) extends AbilityOp[F, Boolean]
|
||||
|
||||
case class GetArrow[F[_]](name: Ability[F], arrow: Name[F]) extends AbilityOp[F, Option[ArrowType]]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user