bump changes

This commit is contained in:
DieMyst 2023-09-05 11:37:06 +02:00
parent df2e794a99
commit deb56c3021
25 changed files with 317 additions and 119 deletions

View File

@ -2,11 +2,23 @@ service Console("run-console"):
print(s: string) print(s: string)
func main(): func main():
ss: *string -- NewConsole = Console.??id??("new id")
dd: *string -- NewConsole.print("")
peerId = "peerId"
relay = "relay" Console "new id"
parsec s <- ss on peerId via relay: NewAb = Ab(print = Console.print)
Console.print(s)
for d <- dd par:
Console.print(d) Console.print("sfre")
for i <- incr:
Console "inside for id"
Console.print("sfre")
Console "new id"
Console.print("sfre")
Console "inside for id"
-- Console -> ConsoleNew
Console.print("sfre")

View File

@ -18,7 +18,7 @@ object MakeAbilityRawInliner extends RawInliner[AbilityRaw] {
fields: NonEmptyMap[String, (ValueModel, Inline)] fields: NonEmptyMap[String, (ValueModel, Inline)]
): State[S, Unit] = { ): State[S, Unit] = {
for { for {
res <- fields.toNel.traverse { _ <- fields.toNel.traverse {
case (n, (Ability(abilityName, _, _), _)) => case (n, (Ability(abilityName, _, _), _)) =>
val leftName = AbilityType.fullName(name, n) val leftName = AbilityType.fullName(name, n)
Exports[S].copyWithAbilityPrefix(abilityName, leftName) Exports[S].copyWithAbilityPrefix(abilityName, leftName)

View File

@ -10,3 +10,8 @@ case class ArrowRaw(
ret: List[ValueRaw], ret: List[ValueRaw],
body: RawTag.Tree body: RawTag.Tree
) extends Raw ) extends Raw
// func -internal-():
// AssignemntTag(res1, CallArrowRaw("serviceId"))
// res1 <- CallArrowRaw("serviceId")
// <- res1

View File

@ -1,6 +1,5 @@
package aqua.raw.arrow package aqua.raw.arrow
import aqua.raw.value.ValueRaw
import aqua.raw.RawPart import aqua.raw.RawPart
import aqua.types.Type import aqua.types.Type

View File

@ -277,15 +277,6 @@ object EmptyTag extends NoExecTag {
override def mapValues(f: ValueRaw => ValueRaw): RawTag = this override def mapValues(f: ValueRaw => ValueRaw): RawTag = this
} }
case class AbilityIdTag(
value: ValueRaw,
service: String
) extends NoExecTag {
override def mapValues(f: ValueRaw => ValueRaw): RawTag =
AbilityIdTag(value.map(f), service)
}
case class PushToStreamTag(operand: ValueRaw, exportTo: Call.Export) extends RawTag { case class PushToStreamTag(operand: ValueRaw, exportTo: Call.Export) extends RawTag {
override def exportsVarNames: Set[String] = Set(exportTo.name) override def exportsVarNames: Set[String] = Set(exportTo.name)

View File

@ -95,6 +95,17 @@ case class ApplyGateRaw(name: String, streamType: StreamType, idx: ValueRaw) ext
override def varNames: Set[String] = Set(name) ++ idx.varNames override def varNames: Set[String] = Set(name) ++ idx.varNames
} }
case class ServiceFuncRaw(name: String, baseType: ArrowType) extends ValueRaw {
override def map(f: ValueRaw => ValueRaw): ValueRaw = f(this)
override def renameVars(map: Map[String, String]): ValueRaw =
copy(map.getOrElse(name, name))
override def toString: String = s"var{$name: " + baseType + s"}"
override def varNames: Set[String] = Set(name)
}
case class VarRaw(name: String, baseType: Type) extends ValueRaw { case class VarRaw(name: String, baseType: Type) extends ValueRaw {
override def map(f: ValueRaw => ValueRaw): ValueRaw = f(this) override def map(f: ValueRaw => ValueRaw): ValueRaw = f(this)
@ -164,8 +175,10 @@ case class MakeStructRaw(fields: NonEmptyMap[String, ValueRaw], structType: Stru
copy(fields = fields.map(_.renameVars(map))) copy(fields = fields.map(_.renameVars(map)))
} }
case class AbilityRaw(fieldsAndArrows: NonEmptyMap[String, ValueRaw], abilityType: AbilityType) case class AbilityRaw(
extends ValueRaw { fieldsAndArrows: NonEmptyMap[String, ValueRaw],
abilityType: AbilityType
) extends ValueRaw {
override def baseType: Type = abilityType override def baseType: Type = abilityType
@ -234,6 +247,27 @@ object ApplyUnaryOpRaw {
} }
} }
case class ServiceCallDefinitionRaw(
name: String,
baseType: ArrowType,
serviceId: ValueRaw
) extends ValueRaw {
override def `type`: Type = baseType.codomain.uncons.map(_._1).getOrElse(baseType)
override def map(f: ValueRaw => ValueRaw): ValueRaw =
this
override def varNames: Set[String] = Set.empty
override def renameVars(map: Map[String, String]): ValueRaw =
copy(
serviceId = serviceId.renameVars(map)
)
override def toString: String =
s"(service calldef ($serviceId $name) $baseType)"
}
case class CallArrowRaw( case class CallArrowRaw(
// TODO: ability should hold a type, not name // TODO: ability should hold a type, not name
ability: Option[String], ability: Option[String],

View File

@ -2,10 +2,9 @@ package aqua.model
import aqua.raw.arrow.FuncRaw import aqua.raw.arrow.FuncRaw
import aqua.raw.ops.CallArrowRawTag import aqua.raw.ops.CallArrowRawTag
import aqua.raw.value.ValueRaw import aqua.raw.value.{AbilityRaw, CallArrowRaw, LiteralRaw, ValueRaw, VarRaw}
import aqua.raw.value.CallArrowRaw
import aqua.raw.{ConstantRaw, RawContext, RawPart, ServiceRaw, TypeRaw} import aqua.raw.{ConstantRaw, RawContext, RawPart, ServiceRaw, TypeRaw}
import aqua.types.{StructType, Type} import aqua.types.{AbilityType, StructType, Type}
import cats.Monoid import cats.Monoid
import cats.data.NonEmptyMap import cats.data.NonEmptyMap
import cats.data.Chain import cats.data.Chain
@ -140,7 +139,7 @@ object AquaContext extends Logging {
.get(rawContext) .get(rawContext)
.fold { .fold {
logger.trace(s"Compiling ${rawContext.module}, cache has ${cache.size} entries") logger.trace(s"Compiling ${rawContext.module}, cache has ${cache.size} entries")
println("raw parts: " + rawContext.parts)
val (newCtx, newCache) = rawContext.parts val (newCtx, newCache) = rawContext.parts
.foldLeft[(AquaContext, Cache)] { .foldLeft[(AquaContext, Cache)] {
// Laziness unefficiency happens here // Laziness unefficiency happens here
@ -165,11 +164,23 @@ object AquaContext extends Logging {
// Actually this should have no effect, as constants are resolved by semantics // Actually this should have no effect, as constants are resolved by semantics
val (pctx, pcache) = fromRawContext(partContext, ctxCache) val (pctx, pcache) = fromRawContext(partContext, ctxCache)
logger.trace("Got " + c.name + " from raw") logger.trace("Got " + c.name + " from raw")
val values = c.value match {
// it could be only for services with default service ids
// case AbilityRaw(fieldsAndArrows, abilityType, Some(LiteralRaw(v, _))) =>
// fieldsAndArrows.flatMap {
// case VarRaw(n, t) =>
// Some(CallArrowRaw(None, AbilityType.fullName(abilityType.name, n), ))
// case _ => None
// }
case _ =>
if (c.allowOverrides && pctx.values.contains(c.name)) Map.empty
else Map(c.name -> ValueModel.fromRaw(c.value).resolveWith(pctx.allValues))
}
val add = val add =
blank blank
.copy(values = .copy(values =
if (c.allowOverrides && pctx.values.contains(c.name)) Map.empty values
else Map(c.name -> ValueModel.fromRaw(c.value).resolveWith(pctx.allValues))
) )
(ctx |+| add, pcache) (ctx |+| add, pcache)

View File

@ -48,7 +48,9 @@ object ValueModel {
VarModel(name, t) VarModel(name, t)
case LiteralRaw(value, t) => case LiteralRaw(value, t) =>
LiteralModel(value, t) LiteralModel(value, t)
case _ => ??? case p =>
println("catch: " + p)
???
} }
object Ability { object Ability {

View File

@ -20,7 +20,7 @@ case class ArrowExpr[F[_]](arrowTypeExpr: ArrowTypeToken[F])
object ArrowExpr extends Expr.AndIndented { object ArrowExpr extends Expr.AndIndented {
val funcChildren: List[Expr.Lexem] = val funcChildren: List[Expr.Lexem] =
AbilityIdExpr :: ServiceIdExpr ::
PushToStreamExpr :: PushToStreamExpr ::
ForExpr :: ForExpr ::
Expr.defer(OnExpr) :: Expr.defer(OnExpr) ::

View File

@ -1,7 +1,7 @@
package aqua.parser.expr.func package aqua.parser.expr.func
import aqua.parser.Expr import aqua.parser.Expr
import aqua.parser.expr.func.AbilityIdExpr import aqua.parser.expr.func.ServiceIdExpr
import aqua.parser.lexer.Token.* import aqua.parser.lexer.Token.*
import aqua.parser.lexer.{Ability, NamedTypeToken, ValueToken} import aqua.parser.lexer.{Ability, NamedTypeToken, ValueToken}
import aqua.parser.lift.LiftParser import aqua.parser.lift.LiftParser
@ -10,19 +10,19 @@ import cats.{Comonad, ~>}
import aqua.parser.lift.Span import aqua.parser.lift.Span
import aqua.parser.lift.Span.{P0ToSpan, PToSpan} import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
case class AbilityIdExpr[F[_]](ability: NamedTypeToken[F], id: ValueToken[F]) case class ServiceIdExpr[F[_]](ability: NamedTypeToken[F], id: ValueToken[F])
extends Expr[F](AbilityIdExpr, ability) { extends Expr[F](ServiceIdExpr, ability) {
def mapK[K[_]: Comonad](fk: F ~> K): AbilityIdExpr[K] = def mapK[K[_]: Comonad](fk: F ~> K): ServiceIdExpr[K] =
copy(ability.copy(fk(ability.name)), id.mapK(fk)) copy(ability.copy(fk(ability.name)), id.mapK(fk))
} }
object AbilityIdExpr extends Expr.Leaf { object ServiceIdExpr extends Expr.Leaf {
override val p: P[AbilityIdExpr[Span.S]] = override val p: P[ServiceIdExpr[Span.S]] =
((NamedTypeToken.dotted <* ` `) ~ ValueToken.`value`).map { case (ability, id) => ((NamedTypeToken.dotted <* ` `) ~ ValueToken.`value`).map { case (ability, id) =>
AbilityIdExpr(ability, id) ServiceIdExpr(ability, id)
} }
} }

View File

@ -118,8 +118,8 @@ trait AquaSpec extends EitherValues {
def parseUse(str: String): UseFromExpr[Id] = def parseUse(str: String): UseFromExpr[Id] =
UseFromExpr.p.parseAll(str).value.mapK(spanToId) UseFromExpr.p.parseAll(str).value.mapK(spanToId)
def parseAbId(str: String): AbilityIdExpr[Id] = def parseAbId(str: String): ServiceIdExpr[Id] =
AbilityIdExpr.p.parseAll(str).value.mapK(spanToId) ServiceIdExpr.p.parseAll(str).value.mapK(spanToId)
def parseOn(str: String): OnExpr[Id] = def parseOn(str: String): OnExpr[Id] =
OnExpr.p.parseAll(str).value.mapK(spanToId) OnExpr.p.parseAll(str).value.mapK(spanToId)

View File

@ -2,7 +2,7 @@ package aqua.parser
import aqua.AquaSpec import aqua.AquaSpec
import aqua.parser.expr.* import aqua.parser.expr.*
import aqua.parser.expr.func.{AbilityIdExpr, ArrowExpr, CallArrowExpr, IfExpr, OnExpr, ReturnExpr} import aqua.parser.expr.func.{ServiceIdExpr, ArrowExpr, CallArrowExpr, IfExpr, OnExpr, ReturnExpr}
import aqua.parser.lexer.{ import aqua.parser.lexer.{
ArrowTypeToken, ArrowTypeToken,
BasicTypeToken, BasicTypeToken,
@ -123,7 +123,7 @@ class FuncExprSpec extends AnyFlatSpec with Matchers with Inside with Inspectors
) )
) )
) )
ifBody(1).head.mapK(spanToId) should be(AbilityIdExpr(toNamedType("Peer"), toStr("some id"))) ifBody(1).head.mapK(spanToId) should be(ServiceIdExpr(toNamedType("Peer"), toStr("some id")))
ifBody(2).head.mapK(spanToId) should be( ifBody(2).head.mapK(spanToId) should be(
CallArrowExpr(Nil, CallArrowToken("call", List(toBool(true)))) CallArrowExpr(Nil, CallArrowToken("call", List(toBool(true))))
) )

View File

@ -1,31 +1,31 @@
package aqua.parser package aqua.parser
import aqua.AquaSpec import aqua.AquaSpec
import aqua.parser.expr.func.AbilityIdExpr import aqua.parser.expr.func.ServiceIdExpr
import aqua.parser.lexer.LiteralToken import aqua.parser.lexer.LiteralToken
import aqua.types.LiteralType import aqua.types.LiteralType
import cats.Id import cats.Id
import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers import org.scalatest.matchers.should.Matchers
class AbilityIdExprSpec extends AnyFlatSpec with Matchers with AquaSpec { class ServiceIdExprSpec extends AnyFlatSpec with Matchers with AquaSpec {
import AquaSpec._ import AquaSpec._
"abilities" should "be parsed" in { "abilities" should "be parsed" in {
parseAbId("Ab a") should be( parseAbId("Ab a") should be(
AbilityIdExpr[Id](toNamedType("Ab"), toVar("a")) ServiceIdExpr[Id](toNamedType("Ab"), toVar("a"))
) )
parseAbId("Ab \"a\"") should be( parseAbId("Ab \"a\"") should be(
AbilityIdExpr[Id](toNamedType("Ab"), LiteralToken[Id]("\"a\"", LiteralType.string)) ServiceIdExpr[Id](toNamedType("Ab"), LiteralToken[Id]("\"a\"", LiteralType.string))
) )
parseAbId("Ab 1") should be( parseAbId("Ab 1") should be(
AbilityIdExpr[Id](toNamedType("Ab"), toNumber(1)) ServiceIdExpr[Id](toNamedType("Ab"), toNumber(1))
) )
parseAbId("Ab a.id") should be( parseAbId("Ab a.id") should be(
AbilityIdExpr[Id](toNamedType("Ab"), toVarLambda("a", List("id"))) ServiceIdExpr[Id](toNamedType("Ab"), toVarLambda("a", List("id")))
) )
} }

View File

@ -1,7 +1,7 @@
package aqua.parser.head package aqua.parser.head
import aqua.AquaSpec import aqua.AquaSpec
import aqua.parser.expr.func.AbilityIdExpr import aqua.parser.expr.func.ServiceIdExpr
import aqua.parser.lexer.{LiteralToken, Token} import aqua.parser.lexer.{LiteralToken, Token}
import aqua.parser.lift.LiftParser.Implicits.* import aqua.parser.lift.LiftParser.Implicits.*
import aqua.types.LiteralType import aqua.types.LiteralType

View File

@ -1,7 +1,7 @@
package aqua.parser.head package aqua.parser.head
import aqua.AquaSpec import aqua.AquaSpec
import aqua.parser.expr.func.AbilityIdExpr import aqua.parser.expr.func.ServiceIdExpr
import aqua.parser.lexer.{LiteralToken, Token} import aqua.parser.lexer.{LiteralToken, Token}
import aqua.parser.lift.LiftParser.Implicits.* import aqua.parser.lift.LiftParser.Implicits.*
import aqua.types.LiteralType import aqua.types.LiteralType

View File

@ -1,7 +1,7 @@
package aqua.parser.head package aqua.parser.head
import aqua.AquaSpec import aqua.AquaSpec
import aqua.parser.expr.func.AbilityIdExpr import aqua.parser.expr.func.ServiceIdExpr
import aqua.parser.lexer.{LiteralToken, Token} import aqua.parser.lexer.{LiteralToken, Token}
import aqua.types.LiteralType import aqua.types.LiteralType
import cats.Id import cats.Id

View File

@ -1,7 +1,7 @@
package aqua.parser.head package aqua.parser.head
import aqua.AquaSpec import aqua.AquaSpec
import aqua.parser.expr.func.AbilityIdExpr import aqua.parser.expr.func.ServiceIdExpr
import aqua.parser.lexer.{LiteralToken, Token} import aqua.parser.lexer.{LiteralToken, Token}
import aqua.parser.lift.LiftParser.Implicits.* import aqua.parser.lift.LiftParser.Implicits.*
import aqua.types.LiteralType import aqua.types.LiteralType

View File

@ -27,7 +27,7 @@ object ExprSem {
L: LocationsAlgebra[S, G] L: LocationsAlgebra[S, G]
): Prog[G, Raw] = ): Prog[G, Raw] =
expr match { expr match {
case expr: AbilityIdExpr[S] => new AbilityIdSem(expr).program[G] case expr: ServiceIdExpr[S] => new ServiceIdSem(expr).program[G]
case expr: AssignmentExpr[S] => new AssignmentSem(expr).program[G] case expr: AssignmentExpr[S] => new AssignmentSem(expr).program[G]
case expr: PushToStreamExpr[S] => new PushToStreamSem(expr).program[G] case expr: PushToStreamExpr[S] => new PushToStreamSem(expr).program[G]
case expr: AliasExpr[S] => new AliasSem(expr).program[G] case expr: AliasExpr[S] => new AliasSem(expr).program[G]

View File

@ -1,21 +1,119 @@
package aqua.semantics.expr package aqua.semantics.expr
import aqua.parser.expr.ServiceExpr import aqua.parser.expr.ServiceExpr
import aqua.raw.{Raw, ServiceRaw} import aqua.raw.arrow.{ArrowRaw, FuncRaw}
import aqua.raw.ops.CallArrowRawTag
import aqua.raw.value.{AbilityRaw, CallArrowRaw, ValueRaw, VarRaw}
import aqua.raw.{ConstantRaw, Raw, RawPart, ServiceRaw, TypeRaw}
import aqua.semantics.Prog import aqua.semantics.Prog
import aqua.semantics.rules.ValuesAlgebra import aqua.semantics.rules.ValuesAlgebra
import aqua.semantics.rules.abilities.AbilitiesAlgebra import aqua.semantics.rules.abilities.AbilitiesAlgebra
import aqua.semantics.rules.definitions.DefinitionsAlgebra import aqua.semantics.rules.definitions.DefinitionsAlgebra
import aqua.semantics.rules.names.NamesAlgebra import aqua.semantics.rules.names.NamesAlgebra
import aqua.semantics.rules.types.TypesAlgebra import aqua.semantics.rules.types.TypesAlgebra
import aqua.types.{AbilityType, ArrowType}
import cats.syntax.apply.* import cats.syntax.apply.*
import cats.syntax.flatMap.* import cats.syntax.flatMap.*
import cats.syntax.functor.* import cats.syntax.functor.*
import cats.syntax.applicative.* import cats.syntax.applicative.*
import cats.syntax.traverse.*
import cats.Monad import cats.Monad
import cats.data.Chain
class ServiceSem[S[_]](val expr: ServiceExpr[S]) extends AnyVal { class ServiceSem[S[_]](val expr: ServiceExpr[S]) extends AnyVal {
def createAbilityValue[Alg[_]: Monad](id: ValueRaw, abilityType: AbilityType)(implicit
A: AbilitiesAlgebra[S, Alg],
N: NamesAlgebra[S, Alg],
T: TypesAlgebra[S, Alg],
V: ValuesAlgebra[S, Alg],
D: DefinitionsAlgebra[S, Alg]
) = {}
// service AbServType("defaultId"):
// ...
// AbServType(func1 = ...'defaultId', func2 = ...'defaultId')
// AbServType.func1()
// VarRaw(Serv.-default-id-, "defaultId")
// Serv "new id"
// VarRaw(Serv.-default-id-, "new id")
/*
ability Ab:
fff: string -> string
eee: string -> string
service Serv:
fff: string -> string
service Eserv:
eee: string -> string
func nested{Ab}:
...
someNewFunc{AbVal}():
Serv "freferf"
AbVal.fff()
AbVal.eee()
func main():
Serv "aaa"
Serv.fff()
Eserv "bbb"
Serv "zzz"
Serv.fff()
nested{Serv}()
AbVal = Ab(fff = Serv.fff, Eserv.eee)
someNewFunc{AbVal}()
*/
// ...
/*
func main():
AbServType "some id"
AbServType(func1 = ...'some id', func2 = ...'some id')
CallServiceModel('some id')
AbServType "some id2"
AbServType(func1 = ...'some id2', func2 = ...'some id2')
VarRaw(name, arrowType) -> Arrows FuncRaw(name, arrowType)
FuncRaw(name, arrowType, body = ServiceCall)
*/
private def toFuncRaw(name: String, abilityName: String, serviceId: ValueRaw, t: ArrowType): FuncRaw = {
val args = t.domain.toLabelledList().map(st => VarRaw(st._1, st._2))
val rett = t.codomain.toList.headOption
val ret = rett.map(t => VarRaw("ret", t))
val raw = CallArrowRaw(None, name, args, t, Some(serviceId))
val body = ret match {
case Some(vr) =>
val callExpr = aqua.raw.ops.Call.Export(vr.name, vr.baseType)
CallArrowRawTag(callExpr :: Nil, raw)
case None =>
CallArrowRawTag(Nil, raw)
}
val arrow = ArrowRaw(t, ret.toList, body.leaf)
val fullName = AbilityType.fullName(abilityName, name)
FuncRaw(fullName, arrow)
}
def program[Alg[_]: Monad](implicit def program[Alg[_]: Monad](implicit
A: AbilitiesAlgebra[S, Alg], A: AbilitiesAlgebra[S, Alg],
N: NamesAlgebra[S, Alg], N: NamesAlgebra[S, Alg],
@ -23,34 +121,34 @@ class ServiceSem[S[_]](val expr: ServiceExpr[S]) extends AnyVal {
V: ValuesAlgebra[S, Alg], V: ValuesAlgebra[S, Alg],
D: DefinitionsAlgebra[S, Alg] D: DefinitionsAlgebra[S, Alg]
): Prog[Alg, Raw] = ): Prog[Alg, Raw] =
Prog.after( Prog.after(_ =>
_ => D.purgeArrows(expr.name).flatMap {
D.purgeArrows(expr.name).flatMap { case Some(nel) =>
case Some(nel) => val arrows = nel.map(kv => kv._1.value -> kv._2).toNem
val arrows = nel.map(kv => kv._1.value -> (kv._1, kv._2)).toNem val abType = AbilityType(expr.name.value, arrows)
for { for {
defaultId <- expr.id _ <- T.defineNamedType(expr.name, abType)
.map(v => V.valueToRaw(v)) defaultId <- expr.id
.getOrElse(None.pure[Alg]) .map(v => V.valueToRaw(v))
defineResult <- A.defineService( .getOrElse(None.pure[Alg])
expr.name, _ <- expr.id.traverse(id => V.ensureIsString(id))
arrows,
defaultId
)
_ <- (expr.id zip defaultId)
.fold(().pure[Alg])(idV =>
(V.ensureIsString(idV._1) >> A.setServiceId(expr.name, idV._1, idV._2)).map(_ =>
()
)
)
} yield
if (defineResult) {
ServiceRaw(expr.name.value, arrows.map(_._2), defaultId)
} else Raw.empty("Service not created due to validation errors")
case None => serviceArrows = defaultId match {
Raw.error("Service has no arrows, fails").pure[Alg] case Some(did) =>
val funcs = arrows.mapBoth {
case (funcName, t) => funcName -> toFuncRaw(funcName, expr.name.value, did, t)
}
funcs.toNel.toList.map(_._2)
case None => Nil
}
} yield {
println("serviceArrows: " + serviceArrows)
val tr = TypeRaw(expr.name.value, abType)
RawPart.Parts(Chain.fromSeq(serviceArrows) :+ tr)
}
case None =>
Raw.error("Service has no arrows, fails").pure[Alg]
} }
) )
} }

View File

@ -1,8 +1,8 @@
package aqua.semantics.expr.func package aqua.semantics.expr.func
import aqua.parser.expr.func.ServiceIdExpr
import aqua.raw.Raw import aqua.raw.Raw
import aqua.raw.ops.AbilityIdTag import aqua.raw.ops.EmptyTag
import aqua.parser.expr.func.AbilityIdExpr
import aqua.semantics.Prog import aqua.semantics.Prog
import aqua.semantics.rules.ValuesAlgebra import aqua.semantics.rules.ValuesAlgebra
import aqua.semantics.rules.abilities.AbilitiesAlgebra import aqua.semantics.rules.abilities.AbilitiesAlgebra
@ -11,7 +11,7 @@ import cats.syntax.applicative.*
import cats.syntax.flatMap.* import cats.syntax.flatMap.*
import cats.syntax.functor.* import cats.syntax.functor.*
class AbilityIdSem[S[_]](val expr: AbilityIdExpr[S]) extends AnyVal { class ServiceIdSem[S[_]](val expr: ServiceIdExpr[S]) extends AnyVal {
def program[Alg[_]: Monad](implicit def program[Alg[_]: Monad](implicit
A: AbilitiesAlgebra[S, Alg], A: AbilitiesAlgebra[S, Alg],
@ -21,10 +21,7 @@ class AbilityIdSem[S[_]](val expr: AbilityIdExpr[S]) extends AnyVal {
expr.id expr.id
) >>= { ) >>= {
case Some(id) => case Some(id) =>
A.setServiceId(expr.ability, expr.id, id) as (AbilityIdTag( A.setServiceId(expr.ability, expr.id, id) as (EmptyTag.funcOpLeaf: Raw)
id,
expr.ability.value
).funcOpLeaf: Raw)
case _ => Raw.error("Cannot resolve ability ID").pure[Alg] case _ => Raw.error("Cannot resolve ability ID").pure[Alg]
} }
} }

View File

@ -4,11 +4,13 @@ import aqua.parser.lexer.*
import aqua.parser.lexer.InfixToken.{BoolOp, CmpOp, EqOp, MathOp, Op as InfOp} import aqua.parser.lexer.InfixToken.{BoolOp, CmpOp, EqOp, MathOp, Op as InfOp}
import aqua.parser.lexer.PrefixToken.Op as PrefOp import aqua.parser.lexer.PrefixToken.Op as PrefOp
import aqua.raw.value.* import aqua.raw.value.*
import aqua.raw.ServiceRaw
import aqua.raw.arrow.{ArrowRaw, FuncRaw}
import aqua.raw.ops.{AssignmentTag, CallArrowRawTag}
import aqua.semantics.rules.abilities.AbilitiesAlgebra import aqua.semantics.rules.abilities.AbilitiesAlgebra
import aqua.semantics.rules.names.NamesAlgebra import aqua.semantics.rules.names.NamesAlgebra
import aqua.semantics.rules.types.TypesAlgebra import aqua.semantics.rules.types.TypesAlgebra
import aqua.types.* import aqua.types.*
import cats.Monad import cats.Monad
import cats.data.Chain import cats.data.Chain
import cats.syntax.applicative.* import cats.syntax.applicative.*
@ -48,6 +50,8 @@ class ValuesAlgebra[S[_], Alg[_]: Monad](implicit
def resolveType(v: ValueToken[S]): Alg[Option[Type]] = def resolveType(v: ValueToken[S]): Alg[Option[Type]] =
valueToRaw(v).map(_.map(_.`type`)) valueToRaw(v).map(_.map(_.`type`))
//
private def resolveSingleProperty(rootType: Type, op: PropertyOp[S]): Alg[Option[PropertyRaw]] = private def resolveSingleProperty(rootType: Type, op: PropertyOp[S]): Alg[Option[PropertyRaw]] =
op match { op match {
case op: IntoField[S] => case op: IntoField[S] =>
@ -81,11 +85,23 @@ class ValuesAlgebra[S[_], Alg[_]: Monad](implicit
LiteralRaw(l.value, t).some.pure[Alg] LiteralRaw(l.value, t).some.pure[Alg]
case VarToken(name) => case VarToken(name) =>
N.read(name).flatMap { N.read(name, false).flatMap {
case Some(t) => case Some(t) =>
VarRaw(name.value, t).some.pure[Alg] VarRaw(name.value, t).some.pure[Alg]
case None => case None =>
None.pure[Alg] A.getServiceByName(name).flatMap {
case Some(ServiceRaw(sName, arrows, Some(did))) =>
val t = AbilityType(sName, arrows)
N.define(name, t).map(_ => VarRaw(name.value, t).some)
case _ =>
// to report an error
N.read(name).flatMap {
case Some(t) => VarRaw(name.value, t).some.pure[Alg]
case None => None.pure[Alg]
}
}
} }
case prop @ PropertyToken(value, properties) => case prop @ PropertyToken(value, properties) =>
@ -121,10 +137,10 @@ class ValuesAlgebra[S[_], Alg[_]: Monad](implicit
StructType(typeName.value, rf.map(_.`type`)), StructType(typeName.value, rf.map(_.`type`)),
Some(MakeStructRaw(rf, struct)) Some(MakeStructRaw(rf, struct))
) )
case scope @ AbilityType(_, _) => case ability @ AbilityType(_, _) =>
( (
AbilityType(typeName.value, rf.map(_.`type`)), AbilityType(typeName.value, rf.map(_.`type`)),
Some(AbilityRaw(rf, scope)) Some(AbilityRaw(rf, ability))
) )
} }
) )
@ -339,7 +355,7 @@ class ValuesAlgebra[S[_], Alg[_]: Monad](implicit
callArrowFromAbility(ab.asName, at, callArrow.funcName).pure callArrowFromAbility(ab.asName, at, callArrow.funcName).pure
case _ => case _ =>
(A.getArrow(ab, callArrow.funcName), A.getServiceId(ab)).mapN { (A.getArrow(ab, callArrow.funcName), A.getServiceId(ab)).mapN {
case (Some(at), Right(sid)) => case (Some(at), Right(sid, name)) =>
CallArrowRaw CallArrowRaw
.service( .service(
abilityName = ab.value, abilityName = ab.value,

View File

@ -1,6 +1,7 @@
package aqua.semantics.rules.abilities package aqua.semantics.rules.abilities
import aqua.parser.lexer.{Ability, NamedTypeToken, Name, Token, ValueToken} import aqua.parser.lexer.{Ability, Name, NamedTypeToken, Token, ValueToken}
import aqua.raw.ServiceRaw
import aqua.raw.value.ValueRaw import aqua.raw.value.ValueRaw
import aqua.types.ArrowType import aqua.types.ArrowType
import cats.InjectK import cats.InjectK
@ -19,6 +20,9 @@ trait AbilitiesAlgebra[S[_], Alg[_]] {
def setServiceId(name: NamedTypeToken[S], id: ValueToken[S], vm: ValueRaw): Alg[Boolean] def setServiceId(name: NamedTypeToken[S], id: ValueToken[S], vm: ValueRaw): Alg[Boolean]
def getServiceId(name: NamedTypeToken[S]): Alg[Either[Boolean, ValueRaw]] def getServiceId(name: NamedTypeToken[S]): Alg[Either[Boolean, ValueRaw]]
def getServiceIdByName(name: String): Alg[Option[ValueRaw]]
def getServiceByName(name: Name[S]): Alg[Option[ServiceRaw]]
def beginScope(token: Token[S]): Alg[Unit] def beginScope(token: Token[S]): Alg[Unit]

View File

@ -6,7 +6,7 @@ import aqua.raw.{RawContext, ServiceRaw}
import aqua.semantics.Levenshtein import aqua.semantics.Levenshtein
import aqua.semantics.rules.errors.ReportErrors import aqua.semantics.rules.errors.ReportErrors
import aqua.semantics.rules.locations.LocationsAlgebra import aqua.semantics.rules.locations.LocationsAlgebra
import aqua.semantics.rules.{StackInterpreter, abilities} import aqua.semantics.rules.{abilities, StackInterpreter}
import aqua.types.ArrowType import aqua.types.ArrowType
import cats.data.{NonEmptyMap, State} import cats.data.{NonEmptyMap, State}
import cats.syntax.functor.* import cats.syntax.functor.*
@ -41,24 +41,28 @@ class AbilitiesInterpreter[S[_], X](implicit
} }
case None => case None =>
arrows.toNel.map(_._2).collect { arrows.toNel
case (n, arr) if arr.codomain.length > 1 => .map(_._2)
report(n, "Service functions cannot have multiple results") .collect {
}.sequence.flatMap{ _ => case (n, arr) if arr.codomain.length > 1 =>
modify(s => report(n, "Service functions cannot have multiple results")
s.copy( }
services = s.services .sequence
.updated(name.value, ServiceRaw(name.value, arrows.map(_._2), defaultId)), .flatMap { _ =>
definitions = s.definitions.updated(name.value, name) modify(s =>
) s.copy(
).flatMap { _ => services = s.services
locations.addTokenWithFields( .updated(name.value, ServiceRaw(name.value, arrows.map(_._2), defaultId)),
name.value, definitions = s.definitions.updated(name.value, name)
name, )
arrows.toNel.toList.map(t => t._1 -> t._2._1) ).flatMap { _ =>
) locations.addTokenWithFields(
}.as(true) name.value,
} name,
arrows.toNel.toList.map(t => t._1 -> t._2._1)
)
}.as(true)
}
} }
// adds location from token to its definition // adds location from token to its definition
@ -116,6 +120,22 @@ class AbilitiesInterpreter[S[_], X](implicit
report(name, "Service with this name is not registered, can't set its ID").as(false) report(name, "Service with this name is not registered, can't set its ID").as(false)
} }
def getServiceIdByName(name: String): SX[Option[ValueRaw]] =
getService(name).flatMap {
case Some(_) =>
getState.map(st =>
st.stack
.flatMap(_.serviceIds.get(name).map(_._2))
.headOption orElse st.rootServiceIds
.get(
name
)
.map(_._2) orElse st.services.get(name).flatMap(_.defaultId)
)
case None =>
State.pure(None)
}
override def getServiceId(name: NamedTypeToken[S]): SX[Either[Boolean, ValueRaw]] = override def getServiceId(name: NamedTypeToken[S]): SX[Either[Boolean, ValueRaw]] =
getService(name.value).flatMap { getService(name.value).flatMap {
case Some(_) => case Some(_) =>
@ -147,6 +167,9 @@ class AbilitiesInterpreter[S[_], X](implicit
} }
} }
def getServiceByName(name: Name[S]): SX[Option[ServiceRaw]] =
getService(name.value)
override def beginScope(token: Token[S]): SX[Unit] = override def beginScope(token: Token[S]): SX[Unit] =
stackInt.beginScope(AbilitiesState.Frame[S](token)) stackInt.beginScope(AbilitiesState.Frame[S](token))

View File

@ -10,7 +10,11 @@ trait NamesAlgebra[S[_], Alg[_]] {
def readArrow(name: Name[S]): Alg[Option[ArrowType]] def readArrow(name: Name[S]): Alg[Option[ArrowType]]
def define(name: Name[S], `type`: Type): Alg[Boolean] /**
*
* @param canOverride internal flag that is used for overriding services by serviceId
*/
def define(name: Name[S], `type`: Type, canOverride: Boolean = false): Alg[Boolean]
def derive(name: Name[S], `type`: Type, derivedFrom: Set[String]): Alg[Boolean] def derive(name: Name[S], `type`: Type, derivedFrom: Set[String]): Alg[Boolean]

View File

@ -28,7 +28,7 @@ class NamesInterpreter[S[_], X](implicit
private def readName(name: String): SX[Option[Type]] = private def readName(name: String): SX[Option[Type]] =
getState.map { st => getState.map { st =>
st.stack.collectFirst { st.stack.collectFirst {
case frame if frame.names.contains(name) => frame.names(name) case frame if frame.names.contains(name) => frame.names(name)
case frame if frame.arrows.contains(name) => frame.arrows(name) case frame if frame.arrows.contains(name) => frame.arrows(name)
} orElse st.rootArrows.get(name) orElse st.rootValues.get(name) } orElse st.rootArrows.get(name) orElse st.rootValues.get(name)
@ -84,17 +84,19 @@ class NamesInterpreter[S[_], X](implicit
.headOption orElse st.rootArrows.get(name) .headOption orElse st.rootArrows.get(name)
} }
override def define(name: Name[S], `type`: Type): SX[Boolean] = override def define(name: Name[S], `type`: Type, canOverride: Boolean = false): SX[Boolean] =
readName(name.value).flatMap { readName(name.value).flatMap {
case Some(_) => case Some(_) if !canOverride =>
getState.map(_.definitions.get(name.value).exists(_ == name)).flatMap { getState.map(_.definitions.get(name.value).exists(_ == name)).flatMap {
case true => State.pure(false) case true => State.pure(false)
case false => report(name, "This name was already defined in the scope").as(false) case false => report(name, "This name was already defined in the scope").as(false)
} }
case None => case _ =>
mapStackHead( mapStackHead(
report(name, "Cannot define a variable in the root scope") getState.map { st =>
.as(false) st.rootValues.updated(name.value, `type`)
true
}
)(fr => fr.addName(name, `type`) -> true).flatTap(_ => locations.addToken(name.value, name)) )(fr => fr.addName(name, `type`) -> true).flatTap(_ => locations.addToken(name.value, name))
} }