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)
func main():
ss: *string
dd: *string
peerId = "peerId"
relay = "relay"
parsec s <- ss on peerId via relay:
Console.print(s)
for d <- dd par:
Console.print(d)
-- NewConsole = Console.??id??("new id")
-- NewConsole.print("")
Console "new id"
NewAb = Ab(print = Console.print)
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)]
): State[S, Unit] = {
for {
res <- fields.toNel.traverse {
_ <- fields.toNel.traverse {
case (n, (Ability(abilityName, _, _), _)) =>
val leftName = AbilityType.fullName(name, n)
Exports[S].copyWithAbilityPrefix(abilityName, leftName)

View File

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

View File

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

View File

@ -277,15 +277,6 @@ object EmptyTag extends NoExecTag {
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 {
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
}
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 {
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)))
}
case class AbilityRaw(fieldsAndArrows: NonEmptyMap[String, ValueRaw], abilityType: AbilityType)
extends ValueRaw {
case class AbilityRaw(
fieldsAndArrows: NonEmptyMap[String, ValueRaw],
abilityType: AbilityType
) extends ValueRaw {
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(
// TODO: ability should hold a type, not name
ability: Option[String],

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
package aqua.parser.expr.func
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.{Ability, NamedTypeToken, ValueToken}
import aqua.parser.lift.LiftParser
@ -10,19 +10,19 @@ import cats.{Comonad, ~>}
import aqua.parser.lift.Span
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
case class AbilityIdExpr[F[_]](ability: NamedTypeToken[F], id: ValueToken[F])
extends Expr[F](AbilityIdExpr, ability) {
case class ServiceIdExpr[F[_]](ability: NamedTypeToken[F], id: ValueToken[F])
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))
}
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) =>
AbilityIdExpr(ability, id)
ServiceIdExpr(ability, id)
}
}

View File

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

View File

@ -2,7 +2,7 @@ package aqua.parser
import aqua.AquaSpec
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.{
ArrowTypeToken,
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(
CallArrowExpr(Nil, CallArrowToken("call", List(toBool(true))))
)

View File

@ -1,31 +1,31 @@
package aqua.parser
import aqua.AquaSpec
import aqua.parser.expr.func.AbilityIdExpr
import aqua.parser.expr.func.ServiceIdExpr
import aqua.parser.lexer.LiteralToken
import aqua.types.LiteralType
import cats.Id
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class AbilityIdExprSpec extends AnyFlatSpec with Matchers with AquaSpec {
class ServiceIdExprSpec extends AnyFlatSpec with Matchers with AquaSpec {
import AquaSpec._
"abilities" should "be parsed" in {
parseAbId("Ab a") should be(
AbilityIdExpr[Id](toNamedType("Ab"), toVar("a"))
ServiceIdExpr[Id](toNamedType("Ab"), toVar("a"))
)
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(
AbilityIdExpr[Id](toNamedType("Ab"), toNumber(1))
ServiceIdExpr[Id](toNamedType("Ab"), toNumber(1))
)
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
import aqua.AquaSpec
import aqua.parser.expr.func.AbilityIdExpr
import aqua.parser.expr.func.ServiceIdExpr
import aqua.parser.lexer.{LiteralToken, Token}
import aqua.parser.lift.LiftParser.Implicits.*
import aqua.types.LiteralType

View File

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

View File

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

View File

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

View File

@ -27,7 +27,7 @@ object ExprSem {
L: LocationsAlgebra[S, G]
): Prog[G, Raw] =
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: PushToStreamExpr[S] => new PushToStreamSem(expr).program[G]
case expr: AliasExpr[S] => new AliasSem(expr).program[G]

View File

@ -1,21 +1,119 @@
package aqua.semantics.expr
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.rules.ValuesAlgebra
import aqua.semantics.rules.abilities.AbilitiesAlgebra
import aqua.semantics.rules.definitions.DefinitionsAlgebra
import aqua.semantics.rules.names.NamesAlgebra
import aqua.semantics.rules.types.TypesAlgebra
import aqua.types.{AbilityType, ArrowType}
import cats.syntax.apply.*
import cats.syntax.flatMap.*
import cats.syntax.functor.*
import cats.syntax.applicative.*
import cats.syntax.traverse.*
import cats.Monad
import cats.data.Chain
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
A: AbilitiesAlgebra[S, Alg],
N: NamesAlgebra[S, Alg],
@ -23,34 +121,34 @@ class ServiceSem[S[_]](val expr: ServiceExpr[S]) extends AnyVal {
V: ValuesAlgebra[S, Alg],
D: DefinitionsAlgebra[S, Alg]
): Prog[Alg, Raw] =
Prog.after(
_ =>
D.purgeArrows(expr.name).flatMap {
case Some(nel) =>
val arrows = nel.map(kv => kv._1.value -> (kv._1, kv._2)).toNem
for {
defaultId <- expr.id
.map(v => V.valueToRaw(v))
.getOrElse(None.pure[Alg])
defineResult <- A.defineService(
expr.name,
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")
Prog.after(_ =>
D.purgeArrows(expr.name).flatMap {
case Some(nel) =>
val arrows = nel.map(kv => kv._1.value -> kv._2).toNem
val abType = AbilityType(expr.name.value, arrows)
for {
_ <- T.defineNamedType(expr.name, abType)
defaultId <- expr.id
.map(v => V.valueToRaw(v))
.getOrElse(None.pure[Alg])
_ <- expr.id.traverse(id => V.ensureIsString(id))
case None =>
Raw.error("Service has no arrows, fails").pure[Alg]
serviceArrows = defaultId match {
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
import aqua.parser.expr.func.ServiceIdExpr
import aqua.raw.Raw
import aqua.raw.ops.AbilityIdTag
import aqua.parser.expr.func.AbilityIdExpr
import aqua.raw.ops.EmptyTag
import aqua.semantics.Prog
import aqua.semantics.rules.ValuesAlgebra
import aqua.semantics.rules.abilities.AbilitiesAlgebra
@ -11,7 +11,7 @@ import cats.syntax.applicative.*
import cats.syntax.flatMap.*
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
A: AbilitiesAlgebra[S, Alg],
@ -21,10 +21,7 @@ class AbilityIdSem[S[_]](val expr: AbilityIdExpr[S]) extends AnyVal {
expr.id
) >>= {
case Some(id) =>
A.setServiceId(expr.ability, expr.id, id) as (AbilityIdTag(
id,
expr.ability.value
).funcOpLeaf: Raw)
A.setServiceId(expr.ability, expr.id, id) as (EmptyTag.funcOpLeaf: Raw)
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.PrefixToken.Op as PrefOp
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.names.NamesAlgebra
import aqua.semantics.rules.types.TypesAlgebra
import aqua.types.*
import cats.Monad
import cats.data.Chain
import cats.syntax.applicative.*
@ -48,6 +50,8 @@ class ValuesAlgebra[S[_], Alg[_]: Monad](implicit
def resolveType(v: ValueToken[S]): Alg[Option[Type]] =
valueToRaw(v).map(_.map(_.`type`))
//
private def resolveSingleProperty(rootType: Type, op: PropertyOp[S]): Alg[Option[PropertyRaw]] =
op match {
case op: IntoField[S] =>
@ -81,11 +85,23 @@ class ValuesAlgebra[S[_], Alg[_]: Monad](implicit
LiteralRaw(l.value, t).some.pure[Alg]
case VarToken(name) =>
N.read(name).flatMap {
N.read(name, false).flatMap {
case Some(t) =>
VarRaw(name.value, t).some.pure[Alg]
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) =>
@ -121,10 +137,10 @@ class ValuesAlgebra[S[_], Alg[_]: Monad](implicit
StructType(typeName.value, rf.map(_.`type`)),
Some(MakeStructRaw(rf, struct))
)
case scope @ AbilityType(_, _) =>
case ability @ AbilityType(_, _) =>
(
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
case _ =>
(A.getArrow(ab, callArrow.funcName), A.getServiceId(ab)).mapN {
case (Some(at), Right(sid)) =>
case (Some(at), Right(sid, name)) =>
CallArrowRaw
.service(
abilityName = ab.value,

View File

@ -1,6 +1,7 @@
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.types.ArrowType
import cats.InjectK
@ -19,6 +20,9 @@ trait AbilitiesAlgebra[S[_], Alg[_]] {
def setServiceId(name: NamedTypeToken[S], id: ValueToken[S], vm: ValueRaw): Alg[Boolean]
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]

View File

@ -6,7 +6,7 @@ import aqua.raw.{RawContext, ServiceRaw}
import aqua.semantics.Levenshtein
import aqua.semantics.rules.errors.ReportErrors
import aqua.semantics.rules.locations.LocationsAlgebra
import aqua.semantics.rules.{StackInterpreter, abilities}
import aqua.semantics.rules.{abilities, StackInterpreter}
import aqua.types.ArrowType
import cats.data.{NonEmptyMap, State}
import cats.syntax.functor.*
@ -41,24 +41,28 @@ class AbilitiesInterpreter[S[_], X](implicit
}
case None =>
arrows.toNel.map(_._2).collect {
case (n, arr) if arr.codomain.length > 1 =>
report(n, "Service functions cannot have multiple results")
}.sequence.flatMap{ _ =>
modify(s =>
s.copy(
services = s.services
.updated(name.value, ServiceRaw(name.value, arrows.map(_._2), defaultId)),
definitions = s.definitions.updated(name.value, name)
)
).flatMap { _ =>
locations.addTokenWithFields(
name.value,
name,
arrows.toNel.toList.map(t => t._1 -> t._2._1)
)
}.as(true)
}
arrows.toNel
.map(_._2)
.collect {
case (n, arr) if arr.codomain.length > 1 =>
report(n, "Service functions cannot have multiple results")
}
.sequence
.flatMap { _ =>
modify(s =>
s.copy(
services = s.services
.updated(name.value, ServiceRaw(name.value, arrows.map(_._2), defaultId)),
definitions = s.definitions.updated(name.value, name)
)
).flatMap { _ =>
locations.addTokenWithFields(
name.value,
name,
arrows.toNel.toList.map(t => t._1 -> t._2._1)
)
}.as(true)
}
}
// 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)
}
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]] =
getService(name.value).flatMap {
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] =
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 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]

View File

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