mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 14:40:17 +00:00
fix(compiler): Return error if SemanticError occures [LNG-356] (#1126)
This commit is contained in:
parent
f29e44e52a
commit
e6c5d0039f
@ -1,10 +1,29 @@
|
||||
aqua Main
|
||||
aqua Job declares *
|
||||
|
||||
export main
|
||||
export aaa, bbb
|
||||
|
||||
func reward(amount: ?u32) -> u32:
|
||||
result = ?[amount! / 10, 0]
|
||||
<- result!
|
||||
data Peer:
|
||||
id: string
|
||||
|
||||
func main(a: u32) -> u32:
|
||||
<- reward(?[a])
|
||||
func aaa() -> Peer:
|
||||
peer1 = Peer(id = "123")
|
||||
peer2 = Peer(id = peer1.id)
|
||||
<- peer2
|
||||
|
||||
data BrokenStruct:
|
||||
fff: UnknownType
|
||||
|
||||
alias BrokenAlias: str3ng
|
||||
|
||||
ability BrokenAbility:
|
||||
fff: str4ng
|
||||
|
||||
const BROKEN_CONST = UNKNOWN_CONST
|
||||
|
||||
func bbb() -> string:
|
||||
<- 323
|
||||
|
||||
func ccc() -> Peer:
|
||||
peer1 = Peer(id = "123")
|
||||
peer2 = Peer(id = peer1.id)
|
||||
<- peer2
|
@ -33,9 +33,9 @@ object LspContext {
|
||||
def blank[S[_]]: LspContext[S] = LspContext[S](raw = RawContext())
|
||||
|
||||
given [S[_]]: Monoid[LspContext[S]] with {
|
||||
override def empty = blank[S]
|
||||
override def empty: LspContext[S] = blank[S]
|
||||
|
||||
override def combine(x: LspContext[S], y: LspContext[S]) =
|
||||
override def combine(x: LspContext[S], y: LspContext[S]): LspContext[S] =
|
||||
LspContext[S](
|
||||
raw = x.raw |+| y.raw,
|
||||
abDefinitions = x.abDefinitions ++ y.abDefinitions,
|
||||
@ -52,7 +52,7 @@ object LspContext {
|
||||
given [S[_]]: Picker[LspContext[S]] with {
|
||||
import aqua.semantics.header.Picker.*
|
||||
|
||||
override def blank: LspContext[S] = LspContext[S](Picker[RawContext].blank, Map.empty)
|
||||
override def blank: LspContext[S] = LspContext.blank[S]
|
||||
override def exports(ctx: LspContext[S]): Map[String, Option[String]] = ctx.raw.exports
|
||||
|
||||
override def isAbility(ctx: LspContext[S], name: String): Boolean =
|
||||
|
@ -2,21 +2,15 @@ package aqua.lsp
|
||||
|
||||
import aqua.parser.Ast
|
||||
import aqua.parser.head.{ImportExpr, ImportFromExpr, UseExpr, UseFromExpr}
|
||||
import aqua.parser.lexer.{LiteralToken, Token}
|
||||
import aqua.parser.lexer.LiteralToken
|
||||
import aqua.raw.ConstantRaw
|
||||
import aqua.semantics.*
|
||||
import aqua.semantics.header.Picker.*
|
||||
import aqua.semantics.rules.locations.LocationsState
|
||||
import aqua.semantics.{CompilerState, RawSemantics, SemanticError, SemanticWarning, Semantics}
|
||||
|
||||
import cats.data.Validated.{Invalid, Valid}
|
||||
import cats.data.{NonEmptyChain, ValidatedNec}
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.apply.*
|
||||
import cats.syntax.either.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.foldable.*
|
||||
import cats.data.{EitherT, NonEmptyChain, Writer}
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.reducible.*
|
||||
import cats.syntax.applicative.*
|
||||
import monocle.Lens
|
||||
import monocle.macros.GenLens
|
||||
|
||||
@ -74,7 +68,6 @@ class LspSemantics[S[_]](
|
||||
warnings = state.warnings.toList
|
||||
).pure[Result]
|
||||
}
|
||||
// TODO: return as Eval
|
||||
.value
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,12 @@ package aqua.lsp
|
||||
import aqua.compiler.FileIdString.given_FileId_String
|
||||
import aqua.compiler.{AquaCompilerConf, AquaError, AquaSources}
|
||||
import aqua.parser.Parser
|
||||
import aqua.parser.lexer.Token
|
||||
import aqua.parser.lift.Span
|
||||
import aqua.parser.lift.Span.S
|
||||
import aqua.raw.ConstantRaw
|
||||
import aqua.semantics.rules.locations.{DefinitionInfo, TokenLocation, VariableInfo}
|
||||
import aqua.semantics.{RulesViolated, SemanticError}
|
||||
import aqua.types.*
|
||||
|
||||
import cats.Id
|
||||
@ -131,6 +133,16 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
ee
|
||||
}
|
||||
|
||||
def insideError(err: SemanticError[S], str: String, pos: Int, code: String) = {
|
||||
inside(err) { case RulesViolated(token, _) =>
|
||||
val span = token.unit._1
|
||||
val locatedOp = getByPosition(code, str, pos)
|
||||
locatedOp shouldBe defined
|
||||
val located = locatedOp.get
|
||||
(span.startIndex, span.endIndex) shouldBe (located._1, located._2)
|
||||
}
|
||||
}
|
||||
|
||||
it should "return right tokens" in {
|
||||
val main =
|
||||
"""aqua Import declares foo_wrapper, Ab, Str, useAbAndStruct, SOME_CONST
|
||||
@ -153,6 +165,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
| num(someVar)
|
||||
| OneMore fooResult
|
||||
| OneMore.more_call()
|
||||
| <- "123"
|
||||
|
|
||||
|ability Ab:
|
||||
| someField: u32
|
||||
@ -362,26 +375,26 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
| a: SomeAlias
|
||||
|
|
||||
|data SomeStruct:
|
||||
| al: SomeAlias
|
||||
| al11: SomeAlias
|
||||
| nested: NestedStruct
|
||||
|
|
||||
|ability SomeAbility:
|
||||
| someStr: SomeStruct
|
||||
| nested: NestedStruct
|
||||
| al: SomeAlias
|
||||
| someFunc(ss: SomeStruct, nest: NestedStruct, al: SomeAlias) -> NestedStruct, SomeStruct, SomeAlias
|
||||
| al11: SomeAlias
|
||||
| someFunc(ss: SomeStruct, nest: NestedStruct, al11: SomeAlias) -> NestedStruct, SomeStruct, SomeAlias
|
||||
|
|
||||
|service Srv("a"):
|
||||
| check(ss: SomeStruct, nest: NestedStruct, al: SomeAlias) -> NestedStruct
|
||||
| check(ss: SomeStruct, nest: NestedStruct, al11: SomeAlias) -> NestedStruct
|
||||
| check2() -> SomeStruct
|
||||
| check3() -> SomeAlias
|
||||
|
|
||||
|func withAb{SomeAbility}() -> SomeStruct:
|
||||
| Srv.check()
|
||||
| Srv.check(SomeAbility.someStr, SomeAbility.nested, SomeAbility.al11)
|
||||
| Srv.check2()
|
||||
| <- SomeAbility.someStr
|
||||
|
|
||||
|func main(ss: SomeStruct, nest: NestedStruct, al: SomeAlias) -> string:
|
||||
|func main(ss: SomeStruct, nest: NestedStruct, al11: SomeAlias) -> string:
|
||||
| Srv.check3()
|
||||
| <- ""
|
||||
|""".stripMargin
|
||||
@ -394,11 +407,11 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
|
||||
val nestedType = StructType("NestedStruct", NonEmptyMap.of(("a", ScalarType.string)))
|
||||
val someStr =
|
||||
StructType("SomeStruct", NonEmptyMap.of(("nested", nestedType), ("al", ScalarType.string)))
|
||||
StructType("SomeStruct", NonEmptyMap.of(("nested", nestedType), ("al11", ScalarType.string)))
|
||||
|
||||
val abFuncType = ArrowType(
|
||||
ProductType.labelled(
|
||||
("ss", someStr) :: ("nest", nestedType) :: ("al", ScalarType.string) :: Nil
|
||||
("ss", someStr) :: ("nest", nestedType) :: ("al11", ScalarType.string) :: Nil
|
||||
),
|
||||
ProductType(nestedType :: someStr :: ScalarType.string :: Nil)
|
||||
)
|
||||
@ -407,7 +420,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
NonEmptyMap.of(
|
||||
("someStr", someStr),
|
||||
("nested", nestedType),
|
||||
("al", ScalarType.string),
|
||||
("al11", ScalarType.string),
|
||||
("someFunc", abFuncType)
|
||||
)
|
||||
)
|
||||
@ -419,7 +432,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
"check",
|
||||
ArrowType(
|
||||
ProductType.labelled(
|
||||
("ss", someStr) :: ("nest", nestedType) :: ("al", ScalarType.string) :: Nil
|
||||
("ss", someStr) :: ("nest", nestedType) :: ("al11", ScalarType.string) :: Nil
|
||||
),
|
||||
ProductType(nestedType :: Nil)
|
||||
)
|
||||
@ -445,10 +458,14 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
}
|
||||
|
||||
res.checkTokenLoc(main, "SomeAbility", 0, someAb) shouldBe true
|
||||
// from {SomeAbility} to 'ability SomeAbility'
|
||||
res.checkLocations("SomeAbility", 0, 1, main) shouldBe true
|
||||
// from 'SomeAbility.someStr' to {SomeAbility}
|
||||
res.checkLocations("SomeAbility", 0, 2, main) shouldBe true
|
||||
Range.inclusive(1, 5).foreach { n =>
|
||||
res.checkLocations("SomeAbility", 0, n, main) shouldBe true
|
||||
}
|
||||
|
||||
res.checkLocations("someStr", 0, 1, main) shouldBe true
|
||||
res.checkLocations("someStr", 0, 2, main) shouldBe true
|
||||
res.checkLocations("nested", 1, 2, main) shouldBe true
|
||||
res.checkLocations("al11", 1, 4, main) shouldBe true
|
||||
|
||||
res.checkTokenLoc(main, "Srv", 0, srvType) shouldBe true
|
||||
Range.inclusive(1, 3).foreach { n =>
|
||||
@ -538,4 +555,99 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
res.checkLocations("Abilyy", 0, 2, main) shouldBe true
|
||||
res.checkLocations("Abilyy", 0, 3, main) shouldBe true
|
||||
}
|
||||
|
||||
it should "return correct locations of errors on exported functions (LNG-356)" in {
|
||||
val main =
|
||||
"""aqua Job declares *
|
||||
|
|
||||
|export aaa
|
||||
|
|
||||
|data Peer:
|
||||
| id: string
|
||||
|
|
||||
|func aaa() -> string:
|
||||
| peer = Pe2er(id = "123")
|
||||
| <- peer.id""".stripMargin
|
||||
val src = Map(
|
||||
"index.aqua" -> main
|
||||
)
|
||||
|
||||
val imports = Map.empty[String, String]
|
||||
|
||||
val res = compile(src, imports).toEither.toOption.get.values.head
|
||||
|
||||
val errors = res.errors
|
||||
|
||||
insideError(errors.head, "Pe2er", 0, main)
|
||||
insideError(errors(1), "peer", 1, main)
|
||||
insideError(errors(2), "string", 1, main)
|
||||
}
|
||||
|
||||
it should "return correct locations in functions even if there is errors in other parts of a code" in {
|
||||
val main =
|
||||
"""aqua Job declares *
|
||||
|
|
||||
|export aaa, bbb
|
||||
|
|
||||
|data Peer:
|
||||
| id: string
|
||||
|
|
||||
|func aaa() -> Peer:
|
||||
| peer1 = Peer(id = "123")
|
||||
| peer2 = Peer(id = peer1.id)
|
||||
| <- peer2
|
||||
|
|
||||
|data BrokenStruct:
|
||||
| fff: UnknownType1
|
||||
|
|
||||
|alias BrokenAlias: UnknownType2
|
||||
|
|
||||
|ability BrokenAbility:
|
||||
| fff: UnknownType3
|
||||
|
|
||||
|const BROKEN_CONST = UNKNOWN_CONST
|
||||
|
|
||||
|func bbb() -> string:
|
||||
| <- 323
|
||||
|
|
||||
|func ccc() -> Peer:
|
||||
| peer1 = Peer(id = "123")
|
||||
| peer2 = Peer(id = peer1.id)
|
||||
| <- peer2
|
||||
|
|
||||
|""".stripMargin
|
||||
val src = Map(
|
||||
"index.aqua" -> main
|
||||
)
|
||||
|
||||
val imports = Map.empty[String, String]
|
||||
|
||||
val res = compile(src, imports).toOption.get.values.head
|
||||
val errors = res.errors
|
||||
|
||||
// 'aaa' function
|
||||
res.checkLocations("Peer", 0, 1, main) shouldBe true
|
||||
res.checkLocations("Peer", 0, 2, main) shouldBe true
|
||||
res.checkLocations("Peer", 0, 3, main) shouldBe true
|
||||
res.checkLocations("peer1", 0, 1, main) shouldBe true
|
||||
res.checkLocations("peer1", 0, 1, main) shouldBe true
|
||||
|
||||
// 'ccc' function
|
||||
res.checkLocations("Peer", 0, 4, main) shouldBe true
|
||||
res.checkLocations("Peer", 0, 5, main) shouldBe true
|
||||
res.checkLocations("Peer", 0, 6, main) shouldBe true
|
||||
res.checkLocations("peer1", 2, 3, main) shouldBe true
|
||||
res.checkLocations("peer1", 2, 3, main) shouldBe true
|
||||
|
||||
// errors
|
||||
insideError(errors.head, "UnknownType1", 0, main)
|
||||
insideError(errors(1), "BrokenStruct", 0, main)
|
||||
insideError(errors(2), "UnknownType2", 0, main)
|
||||
insideError(errors(3), "UnknownType3", 0, main)
|
||||
insideError(errors(4), "BrokenAbility", 0, main)
|
||||
insideError(errors(5), "UNKNOWN_CONST", 0, main)
|
||||
insideError(errors(6), "323", 0, main)
|
||||
insideError(errors(7), "string", 1, main)
|
||||
}
|
||||
|
||||
}
|
||||
|
10
model/raw/src/main/scala/aqua/raw/ErroredPart.scala
Normal file
10
model/raw/src/main/scala/aqua/raw/ErroredPart.scala
Normal file
@ -0,0 +1,10 @@
|
||||
package aqua.raw
|
||||
|
||||
import aqua.types.{BottomType, Type}
|
||||
|
||||
// Part for structures that have errors inside but must be registered in context
|
||||
case class ErroredPart(name: String) extends RawPart {
|
||||
override def rawPartType: Type = BottomType
|
||||
|
||||
override def rename(s: String): RawPart = copy(name = s)
|
||||
}
|
@ -90,7 +90,7 @@ case class RawContext(
|
||||
parts.map { case (_, p) => p.name }.toList.toSet
|
||||
|
||||
lazy val declaredNames: Set[String] =
|
||||
allNames.filter(declares.contains)
|
||||
allNames.intersect(declares)
|
||||
|
||||
override def toString: String =
|
||||
s"""|module: ${module.getOrElse("unnamed")}
|
||||
@ -109,7 +109,7 @@ object RawContext {
|
||||
|
||||
override def empty: RawContext = blank
|
||||
|
||||
override def combine(x: RawContext, y: RawContext) =
|
||||
override def combine(x: RawContext, y: RawContext): RawContext =
|
||||
RawContext(
|
||||
x.module orElse y.module,
|
||||
x.declares ++ y.declares,
|
||||
|
@ -56,7 +56,6 @@ class RawSemantics[S[_]](
|
||||
)
|
||||
)
|
||||
}
|
||||
// TODO: return as Eval
|
||||
.value
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,15 @@
|
||||
package aqua.semantics.expr
|
||||
|
||||
import aqua.parser.expr.AbilityExpr
|
||||
import aqua.raw.{Raw, TypeRaw}
|
||||
import aqua.parser.lexer.{Name, NamedTypeToken}
|
||||
import aqua.raw.{ErroredPart, Raw, 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, Type}
|
||||
|
||||
import cats.Monad
|
||||
import cats.syntax.apply.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.semigroupal.*
|
||||
import cats.syntax.traverse.*
|
||||
import cats.Monad
|
||||
import cats.data.{NonEmptyList, NonEmptyMap}
|
||||
|
||||
class AbilitySem[S[_]](val expr: AbilityExpr[S]) extends AnyVal {
|
||||
|
||||
@ -32,7 +23,7 @@ class AbilitySem[S[_]](val expr: AbilityExpr[S]) extends AnyVal {
|
||||
fields = defs.view.mapValues(d => d.name -> d.`type`).toMap
|
||||
abilityType <- T.defineAbilityType(expr.name, fields)
|
||||
result = abilityType.map(st => TypeRaw(expr.name.value, st))
|
||||
} yield result.getOrElse(Raw.error("Ability types unresolved"))
|
||||
} yield result.getOrElse(ErroredPart(expr.name.value))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
package aqua.semantics.expr
|
||||
|
||||
import aqua.parser.expr.AliasExpr
|
||||
import aqua.raw.{Raw, TypeRaw}
|
||||
import aqua.raw.{ErroredPart, Raw, TypeRaw}
|
||||
import aqua.semantics.Prog
|
||||
import aqua.semantics.rules.types.TypesAlgebra
|
||||
|
||||
import cats.Applicative
|
||||
import cats.Monad
|
||||
import cats.syntax.flatMap.*
|
||||
@ -15,6 +14,6 @@ class AliasSem[S[_]](val expr: AliasExpr[S]) extends AnyVal {
|
||||
def program[Alg[_]: Monad](using T: TypesAlgebra[S, Alg]): Prog[Alg, Raw] =
|
||||
T.resolveType(expr.target).flatMap {
|
||||
case Some(t) => T.defineAlias(expr.name, t) as (TypeRaw(expr.name.value, t): Raw)
|
||||
case None => Applicative[Alg].pure(Raw.error("Alias type unresolved"))
|
||||
case None => Applicative[Alg].pure(ErroredPart(expr.name.value))
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package aqua.semantics.expr
|
||||
|
||||
import aqua.parser.expr.ConstantExpr
|
||||
import aqua.raw.{ConstantRaw, Raw}
|
||||
import aqua.raw.{ConstantRaw, ErroredPart, Raw}
|
||||
import aqua.semantics.Prog
|
||||
import aqua.semantics.rules.ValuesAlgebra
|
||||
import aqua.semantics.rules.names.NamesAlgebra
|
||||
@ -27,12 +27,12 @@ class ConstantSem[S[_]](val expr: ConstantExpr[S]) extends AnyVal {
|
||||
case true =>
|
||||
Raw.empty(s"Constant with name ${expr.name} was already defined, skipping")
|
||||
case false =>
|
||||
Raw.error(s"Constant with name ${expr.name} was defined with different type")
|
||||
ErroredPart(expr.name.value)
|
||||
}
|
||||
case (Some(_), _, _) =>
|
||||
Raw.error(s"Name '${expr.name.value}' was already defined").pure[Alg]
|
||||
case (_, None, _) =>
|
||||
Raw.error(s"There is no such variable ${expr.value}").pure[Alg]
|
||||
ErroredPart(expr.name.value).pure[Alg]
|
||||
case (_, Some(t), _) =>
|
||||
N.defineConstant(expr.name, t._2) as (ConstantRaw(
|
||||
expr.name.value,
|
||||
|
@ -1,13 +1,12 @@
|
||||
package aqua.semantics.expr
|
||||
|
||||
import aqua.parser.expr.DataStructExpr
|
||||
import aqua.raw.{Raw, TypeRaw}
|
||||
import aqua.raw.{ErroredPart, Raw, TypeRaw}
|
||||
import aqua.semantics.Prog
|
||||
import aqua.semantics.rules.definitions.DefinitionsAlgebra
|
||||
import aqua.semantics.rules.names.NamesAlgebra
|
||||
import aqua.semantics.rules.types.TypesAlgebra
|
||||
import aqua.types.StructType
|
||||
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.traverse.*
|
||||
@ -26,7 +25,7 @@ class DataStructSem[S[_]](val expr: DataStructExpr[S]) extends AnyVal {
|
||||
fields = defs.view.mapValues(d => d.name -> d.`type`).toMap
|
||||
structType <- T.defineStructType(expr.name, fields)
|
||||
result = structType.map(st => TypeRaw(expr.name.value, st))
|
||||
} yield result.getOrElse(Raw.error("Data struct types unresolved"))
|
||||
} yield result.getOrElse(ErroredPart(expr.name.value))
|
||||
)
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
package aqua.semantics.expr
|
||||
|
||||
import aqua.helpers.syntax.optiont.withFilterF
|
||||
import aqua.parser.expr.ServiceExpr
|
||||
import aqua.raw.{Raw, ServiceRaw}
|
||||
import aqua.raw.{ErroredPart, Raw, ServiceRaw}
|
||||
import aqua.semantics.Prog
|
||||
import aqua.semantics.rules.ValuesAlgebra
|
||||
import aqua.semantics.rules.abilities.AbilitiesAlgebra
|
||||
@ -9,16 +10,16 @@ import aqua.semantics.rules.definitions.DefinitionsAlgebra
|
||||
import aqua.semantics.rules.names.NamesAlgebra
|
||||
import aqua.semantics.rules.types.TypesAlgebra
|
||||
|
||||
import cats.data.EitherT
|
||||
import cats.syntax.either.*
|
||||
import cats.syntax.option.*
|
||||
import cats.syntax.apply.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.traverse.*
|
||||
import cats.syntax.foldable.*
|
||||
import cats.syntax.applicative.*
|
||||
import cats.Monad
|
||||
import cats.data.{EitherT, OptionT}
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.apply.*
|
||||
import cats.syntax.either.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.foldable.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.option.*
|
||||
import cats.syntax.traverse.*
|
||||
|
||||
class ServiceSem[S[_]](val expr: ServiceExpr[S]) extends AnyVal {
|
||||
|
||||
@ -27,37 +28,21 @@ class ServiceSem[S[_]](val expr: ServiceExpr[S]) extends AnyVal {
|
||||
T: TypesAlgebra[S, Alg],
|
||||
V: ValuesAlgebra[S, Alg],
|
||||
D: DefinitionsAlgebra[S, Alg]
|
||||
): EitherT[Alg, Raw, ServiceRaw] = for {
|
||||
arrows <- EitherT.fromOptionF(
|
||||
// TODO: Move to purgeDefs here, allow not only arrows
|
||||
// from parsing, throw errors here
|
||||
D.purgeArrows(expr.name),
|
||||
Raw.error("Service has no arrows")
|
||||
)
|
||||
): EitherT[Alg, Raw, ServiceRaw] = {
|
||||
(
|
||||
for {
|
||||
arrows <- OptionT(D.purgeArrows(expr.name))
|
||||
arrowsByName = arrows.map { case (name, arrow) =>
|
||||
name.value -> (name, arrow)
|
||||
}.toNem
|
||||
defaultId <- expr.id.traverse(id =>
|
||||
EitherT.fromOptionF(
|
||||
V.valueToStringRaw(id),
|
||||
Raw.error("Failed to resolve default service id")
|
||||
)
|
||||
)
|
||||
serviceType <- EitherT.fromOptionF(
|
||||
T.defineServiceType(expr.name, arrowsByName.toSortedMap),
|
||||
Raw.error("Failed to define service type")
|
||||
)
|
||||
defaultId <- expr.id.traverse(id => OptionT(V.valueToStringRaw(id)))
|
||||
serviceType <- OptionT(T.defineServiceType(expr.name, arrowsByName.toSortedMap))
|
||||
arrowsDefs = arrows.map { case (name, _) => name.value -> name }.toNem
|
||||
_ <- EitherT(
|
||||
_ <- OptionT.withFilterF(
|
||||
A.defineService(
|
||||
expr.name,
|
||||
arrowsDefs,
|
||||
defaultId
|
||||
).map(defined =>
|
||||
Raw
|
||||
.error("Service not created due to validation errors")
|
||||
.asLeft
|
||||
.whenA(!defined)
|
||||
)
|
||||
)
|
||||
} yield ServiceRaw(
|
||||
@ -65,6 +50,8 @@ class ServiceSem[S[_]](val expr: ServiceExpr[S]) extends AnyVal {
|
||||
serviceType,
|
||||
defaultId
|
||||
)
|
||||
).toRight(ErroredPart(expr.name.value))
|
||||
}
|
||||
|
||||
def program[Alg[_]: Monad](using
|
||||
A: AbilitiesAlgebra[S, Alg],
|
||||
|
@ -1,6 +1,6 @@
|
||||
package aqua.semantics.expr.func
|
||||
|
||||
import aqua.raw.Raw
|
||||
import aqua.raw.{ErroredPart, Raw}
|
||||
import aqua.raw.arrow.{ArrowRaw, FuncRaw}
|
||||
import aqua.parser.expr.FuncExpr
|
||||
import aqua.parser.lexer.Arg
|
||||
@ -22,7 +22,7 @@ class FuncSem[S[_]](val expr: FuncExpr[S]) extends AnyVal {
|
||||
N.defineArrow(expr.name, arrow.`type`, isRoot = true) as FuncRaw(expr.name.value, arrow)
|
||||
|
||||
case _ =>
|
||||
Raw.error("Func must continue with an arrow definition").pure[Alg]
|
||||
ErroredPart(expr.name.value).pure[Alg]
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user