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:
|
data Peer:
|
||||||
result = ?[amount! / 10, 0]
|
id: string
|
||||||
<- result!
|
|
||||||
|
|
||||||
func main(a: u32) -> u32:
|
func aaa() -> Peer:
|
||||||
<- reward(?[a])
|
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())
|
def blank[S[_]]: LspContext[S] = LspContext[S](raw = RawContext())
|
||||||
|
|
||||||
given [S[_]]: Monoid[LspContext[S]] with {
|
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](
|
LspContext[S](
|
||||||
raw = x.raw |+| y.raw,
|
raw = x.raw |+| y.raw,
|
||||||
abDefinitions = x.abDefinitions ++ y.abDefinitions,
|
abDefinitions = x.abDefinitions ++ y.abDefinitions,
|
||||||
@ -52,7 +52,7 @@ object LspContext {
|
|||||||
given [S[_]]: Picker[LspContext[S]] with {
|
given [S[_]]: Picker[LspContext[S]] with {
|
||||||
import aqua.semantics.header.Picker.*
|
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 exports(ctx: LspContext[S]): Map[String, Option[String]] = ctx.raw.exports
|
||||||
|
|
||||||
override def isAbility(ctx: LspContext[S], name: String): Boolean =
|
override def isAbility(ctx: LspContext[S], name: String): Boolean =
|
||||||
|
@ -2,21 +2,15 @@ package aqua.lsp
|
|||||||
|
|
||||||
import aqua.parser.Ast
|
import aqua.parser.Ast
|
||||||
import aqua.parser.head.{ImportExpr, ImportFromExpr, UseExpr, UseFromExpr}
|
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.raw.ConstantRaw
|
||||||
|
import aqua.semantics.*
|
||||||
import aqua.semantics.header.Picker.*
|
import aqua.semantics.header.Picker.*
|
||||||
import aqua.semantics.rules.locations.LocationsState
|
import aqua.semantics.rules.locations.LocationsState
|
||||||
import aqua.semantics.{CompilerState, RawSemantics, SemanticError, SemanticWarning, Semantics}
|
|
||||||
|
|
||||||
import cats.data.Validated.{Invalid, Valid}
|
import cats.data.{EitherT, NonEmptyChain, Writer}
|
||||||
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.syntax.functor.*
|
import cats.syntax.functor.*
|
||||||
import cats.syntax.reducible.*
|
import cats.syntax.applicative.*
|
||||||
import monocle.Lens
|
import monocle.Lens
|
||||||
import monocle.macros.GenLens
|
import monocle.macros.GenLens
|
||||||
|
|
||||||
@ -74,7 +68,6 @@ class LspSemantics[S[_]](
|
|||||||
warnings = state.warnings.toList
|
warnings = state.warnings.toList
|
||||||
).pure[Result]
|
).pure[Result]
|
||||||
}
|
}
|
||||||
// TODO: return as Eval
|
|
||||||
.value
|
.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,12 @@ package aqua.lsp
|
|||||||
import aqua.compiler.FileIdString.given_FileId_String
|
import aqua.compiler.FileIdString.given_FileId_String
|
||||||
import aqua.compiler.{AquaCompilerConf, AquaError, AquaSources}
|
import aqua.compiler.{AquaCompilerConf, AquaError, AquaSources}
|
||||||
import aqua.parser.Parser
|
import aqua.parser.Parser
|
||||||
|
import aqua.parser.lexer.Token
|
||||||
import aqua.parser.lift.Span
|
import aqua.parser.lift.Span
|
||||||
import aqua.parser.lift.Span.S
|
import aqua.parser.lift.Span.S
|
||||||
import aqua.raw.ConstantRaw
|
import aqua.raw.ConstantRaw
|
||||||
import aqua.semantics.rules.locations.{DefinitionInfo, TokenLocation, VariableInfo}
|
import aqua.semantics.rules.locations.{DefinitionInfo, TokenLocation, VariableInfo}
|
||||||
|
import aqua.semantics.{RulesViolated, SemanticError}
|
||||||
import aqua.types.*
|
import aqua.types.*
|
||||||
|
|
||||||
import cats.Id
|
import cats.Id
|
||||||
@ -131,6 +133,16 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
ee
|
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 {
|
it should "return right tokens" in {
|
||||||
val main =
|
val main =
|
||||||
"""aqua Import declares foo_wrapper, Ab, Str, useAbAndStruct, SOME_CONST
|
"""aqua Import declares foo_wrapper, Ab, Str, useAbAndStruct, SOME_CONST
|
||||||
@ -153,6 +165,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
| num(someVar)
|
| num(someVar)
|
||||||
| OneMore fooResult
|
| OneMore fooResult
|
||||||
| OneMore.more_call()
|
| OneMore.more_call()
|
||||||
|
| <- "123"
|
||||||
|
|
|
|
||||||
|ability Ab:
|
|ability Ab:
|
||||||
| someField: u32
|
| someField: u32
|
||||||
@ -362,26 +375,26 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
| a: SomeAlias
|
| a: SomeAlias
|
||||||
|
|
|
|
||||||
|data SomeStruct:
|
|data SomeStruct:
|
||||||
| al: SomeAlias
|
| al11: SomeAlias
|
||||||
| nested: NestedStruct
|
| nested: NestedStruct
|
||||||
|
|
|
|
||||||
|ability SomeAbility:
|
|ability SomeAbility:
|
||||||
| someStr: SomeStruct
|
| someStr: SomeStruct
|
||||||
| nested: NestedStruct
|
| nested: NestedStruct
|
||||||
| al: SomeAlias
|
| al11: SomeAlias
|
||||||
| someFunc(ss: SomeStruct, nest: NestedStruct, al: SomeAlias) -> NestedStruct, SomeStruct, SomeAlias
|
| someFunc(ss: SomeStruct, nest: NestedStruct, al11: SomeAlias) -> NestedStruct, SomeStruct, SomeAlias
|
||||||
|
|
|
|
||||||
|service Srv("a"):
|
|service Srv("a"):
|
||||||
| check(ss: SomeStruct, nest: NestedStruct, al: SomeAlias) -> NestedStruct
|
| check(ss: SomeStruct, nest: NestedStruct, al11: SomeAlias) -> NestedStruct
|
||||||
| check2() -> SomeStruct
|
| check2() -> SomeStruct
|
||||||
| check3() -> SomeAlias
|
| check3() -> SomeAlias
|
||||||
|
|
|
|
||||||
|func withAb{SomeAbility}() -> SomeStruct:
|
|func withAb{SomeAbility}() -> SomeStruct:
|
||||||
| Srv.check()
|
| Srv.check(SomeAbility.someStr, SomeAbility.nested, SomeAbility.al11)
|
||||||
| Srv.check2()
|
| Srv.check2()
|
||||||
| <- SomeAbility.someStr
|
| <- SomeAbility.someStr
|
||||||
|
|
|
|
||||||
|func main(ss: SomeStruct, nest: NestedStruct, al: SomeAlias) -> string:
|
|func main(ss: SomeStruct, nest: NestedStruct, al11: SomeAlias) -> string:
|
||||||
| Srv.check3()
|
| Srv.check3()
|
||||||
| <- ""
|
| <- ""
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
@ -394,11 +407,11 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
|
|
||||||
val nestedType = StructType("NestedStruct", NonEmptyMap.of(("a", ScalarType.string)))
|
val nestedType = StructType("NestedStruct", NonEmptyMap.of(("a", ScalarType.string)))
|
||||||
val someStr =
|
val someStr =
|
||||||
StructType("SomeStruct", NonEmptyMap.of(("nested", nestedType), ("al", ScalarType.string)))
|
StructType("SomeStruct", NonEmptyMap.of(("nested", nestedType), ("al11", ScalarType.string)))
|
||||||
|
|
||||||
val abFuncType = ArrowType(
|
val abFuncType = ArrowType(
|
||||||
ProductType.labelled(
|
ProductType.labelled(
|
||||||
("ss", someStr) :: ("nest", nestedType) :: ("al", ScalarType.string) :: Nil
|
("ss", someStr) :: ("nest", nestedType) :: ("al11", ScalarType.string) :: Nil
|
||||||
),
|
),
|
||||||
ProductType(nestedType :: someStr :: ScalarType.string :: Nil)
|
ProductType(nestedType :: someStr :: ScalarType.string :: Nil)
|
||||||
)
|
)
|
||||||
@ -407,7 +420,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
NonEmptyMap.of(
|
NonEmptyMap.of(
|
||||||
("someStr", someStr),
|
("someStr", someStr),
|
||||||
("nested", nestedType),
|
("nested", nestedType),
|
||||||
("al", ScalarType.string),
|
("al11", ScalarType.string),
|
||||||
("someFunc", abFuncType)
|
("someFunc", abFuncType)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -419,7 +432,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
"check",
|
"check",
|
||||||
ArrowType(
|
ArrowType(
|
||||||
ProductType.labelled(
|
ProductType.labelled(
|
||||||
("ss", someStr) :: ("nest", nestedType) :: ("al", ScalarType.string) :: Nil
|
("ss", someStr) :: ("nest", nestedType) :: ("al11", ScalarType.string) :: Nil
|
||||||
),
|
),
|
||||||
ProductType(nestedType :: Nil)
|
ProductType(nestedType :: Nil)
|
||||||
)
|
)
|
||||||
@ -445,10 +458,14 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res.checkTokenLoc(main, "SomeAbility", 0, someAb) shouldBe true
|
res.checkTokenLoc(main, "SomeAbility", 0, someAb) shouldBe true
|
||||||
// from {SomeAbility} to 'ability SomeAbility'
|
Range.inclusive(1, 5).foreach { n =>
|
||||||
res.checkLocations("SomeAbility", 0, 1, main) shouldBe true
|
res.checkLocations("SomeAbility", 0, n, main) shouldBe true
|
||||||
// from 'SomeAbility.someStr' to {SomeAbility}
|
}
|
||||||
res.checkLocations("SomeAbility", 0, 2, 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
|
res.checkTokenLoc(main, "Srv", 0, srvType) shouldBe true
|
||||||
Range.inclusive(1, 3).foreach { n =>
|
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, 2, main) shouldBe true
|
||||||
res.checkLocations("Abilyy", 0, 3, 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
|
parts.map { case (_, p) => p.name }.toList.toSet
|
||||||
|
|
||||||
lazy val declaredNames: Set[String] =
|
lazy val declaredNames: Set[String] =
|
||||||
allNames.filter(declares.contains)
|
allNames.intersect(declares)
|
||||||
|
|
||||||
override def toString: String =
|
override def toString: String =
|
||||||
s"""|module: ${module.getOrElse("unnamed")}
|
s"""|module: ${module.getOrElse("unnamed")}
|
||||||
@ -109,7 +109,7 @@ object RawContext {
|
|||||||
|
|
||||||
override def empty: RawContext = blank
|
override def empty: RawContext = blank
|
||||||
|
|
||||||
override def combine(x: RawContext, y: RawContext) =
|
override def combine(x: RawContext, y: RawContext): RawContext =
|
||||||
RawContext(
|
RawContext(
|
||||||
x.module orElse y.module,
|
x.module orElse y.module,
|
||||||
x.declares ++ y.declares,
|
x.declares ++ y.declares,
|
||||||
|
@ -56,7 +56,6 @@ class RawSemantics[S[_]](
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// TODO: return as Eval
|
|
||||||
.value
|
.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,15 @@
|
|||||||
package aqua.semantics.expr
|
package aqua.semantics.expr
|
||||||
|
|
||||||
import aqua.parser.expr.AbilityExpr
|
import aqua.parser.expr.AbilityExpr
|
||||||
import aqua.raw.{Raw, TypeRaw}
|
import aqua.raw.{ErroredPart, Raw, TypeRaw}
|
||||||
import aqua.parser.lexer.{Name, NamedTypeToken}
|
|
||||||
import aqua.semantics.Prog
|
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.definitions.DefinitionsAlgebra
|
||||||
import aqua.semantics.rules.names.NamesAlgebra
|
|
||||||
import aqua.semantics.rules.types.TypesAlgebra
|
import aqua.semantics.rules.types.TypesAlgebra
|
||||||
import aqua.types.{AbilityType, ArrowType, Type}
|
|
||||||
|
|
||||||
|
import cats.Monad
|
||||||
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.semigroupal.*
|
|
||||||
import cats.syntax.traverse.*
|
|
||||||
import cats.Monad
|
|
||||||
import cats.data.{NonEmptyList, NonEmptyMap}
|
|
||||||
|
|
||||||
class AbilitySem[S[_]](val expr: AbilityExpr[S]) extends AnyVal {
|
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
|
fields = defs.view.mapValues(d => d.name -> d.`type`).toMap
|
||||||
abilityType <- T.defineAbilityType(expr.name, fields)
|
abilityType <- T.defineAbilityType(expr.name, fields)
|
||||||
result = abilityType.map(st => TypeRaw(expr.name.value, st))
|
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
|
package aqua.semantics.expr
|
||||||
|
|
||||||
import aqua.parser.expr.AliasExpr
|
import aqua.parser.expr.AliasExpr
|
||||||
import aqua.raw.{Raw, TypeRaw}
|
import aqua.raw.{ErroredPart, Raw, TypeRaw}
|
||||||
import aqua.semantics.Prog
|
import aqua.semantics.Prog
|
||||||
import aqua.semantics.rules.types.TypesAlgebra
|
import aqua.semantics.rules.types.TypesAlgebra
|
||||||
|
|
||||||
import cats.Applicative
|
import cats.Applicative
|
||||||
import cats.Monad
|
import cats.Monad
|
||||||
import cats.syntax.flatMap.*
|
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] =
|
def program[Alg[_]: Monad](using T: TypesAlgebra[S, Alg]): Prog[Alg, Raw] =
|
||||||
T.resolveType(expr.target).flatMap {
|
T.resolveType(expr.target).flatMap {
|
||||||
case Some(t) => T.defineAlias(expr.name, t) as (TypeRaw(expr.name.value, t): Raw)
|
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
|
package aqua.semantics.expr
|
||||||
|
|
||||||
import aqua.parser.expr.ConstantExpr
|
import aqua.parser.expr.ConstantExpr
|
||||||
import aqua.raw.{ConstantRaw, Raw}
|
import aqua.raw.{ConstantRaw, ErroredPart, Raw}
|
||||||
import aqua.semantics.Prog
|
import aqua.semantics.Prog
|
||||||
import aqua.semantics.rules.ValuesAlgebra
|
import aqua.semantics.rules.ValuesAlgebra
|
||||||
import aqua.semantics.rules.names.NamesAlgebra
|
import aqua.semantics.rules.names.NamesAlgebra
|
||||||
@ -27,12 +27,12 @@ class ConstantSem[S[_]](val expr: ConstantExpr[S]) extends AnyVal {
|
|||||||
case true =>
|
case true =>
|
||||||
Raw.empty(s"Constant with name ${expr.name} was already defined, skipping")
|
Raw.empty(s"Constant with name ${expr.name} was already defined, skipping")
|
||||||
case false =>
|
case false =>
|
||||||
Raw.error(s"Constant with name ${expr.name} was defined with different type")
|
ErroredPart(expr.name.value)
|
||||||
}
|
}
|
||||||
case (Some(_), _, _) =>
|
case (Some(_), _, _) =>
|
||||||
Raw.error(s"Name '${expr.name.value}' was already defined").pure[Alg]
|
Raw.error(s"Name '${expr.name.value}' was already defined").pure[Alg]
|
||||||
case (_, None, _) =>
|
case (_, None, _) =>
|
||||||
Raw.error(s"There is no such variable ${expr.value}").pure[Alg]
|
ErroredPart(expr.name.value).pure[Alg]
|
||||||
case (_, Some(t), _) =>
|
case (_, Some(t), _) =>
|
||||||
N.defineConstant(expr.name, t._2) as (ConstantRaw(
|
N.defineConstant(expr.name, t._2) as (ConstantRaw(
|
||||||
expr.name.value,
|
expr.name.value,
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
package aqua.semantics.expr
|
package aqua.semantics.expr
|
||||||
|
|
||||||
import aqua.parser.expr.DataStructExpr
|
import aqua.parser.expr.DataStructExpr
|
||||||
import aqua.raw.{Raw, TypeRaw}
|
import aqua.raw.{ErroredPart, Raw, TypeRaw}
|
||||||
import aqua.semantics.Prog
|
import aqua.semantics.Prog
|
||||||
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.StructType
|
import aqua.types.StructType
|
||||||
|
|
||||||
import cats.syntax.functor.*
|
import cats.syntax.functor.*
|
||||||
import cats.syntax.applicative.*
|
import cats.syntax.applicative.*
|
||||||
import cats.syntax.traverse.*
|
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
|
fields = defs.view.mapValues(d => d.name -> d.`type`).toMap
|
||||||
structType <- T.defineStructType(expr.name, fields)
|
structType <- T.defineStructType(expr.name, fields)
|
||||||
result = structType.map(st => TypeRaw(expr.name.value, st))
|
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
|
package aqua.semantics.expr
|
||||||
|
|
||||||
|
import aqua.helpers.syntax.optiont.withFilterF
|
||||||
import aqua.parser.expr.ServiceExpr
|
import aqua.parser.expr.ServiceExpr
|
||||||
import aqua.raw.{Raw, ServiceRaw}
|
import aqua.raw.{ErroredPart, Raw, ServiceRaw}
|
||||||
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
|
||||||
@ -9,16 +10,16 @@ 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 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.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 {
|
class ServiceSem[S[_]](val expr: ServiceExpr[S]) extends AnyVal {
|
||||||
|
|
||||||
@ -27,44 +28,30 @@ class ServiceSem[S[_]](val expr: ServiceExpr[S]) extends AnyVal {
|
|||||||
T: TypesAlgebra[S, Alg],
|
T: TypesAlgebra[S, Alg],
|
||||||
V: ValuesAlgebra[S, Alg],
|
V: ValuesAlgebra[S, Alg],
|
||||||
D: DefinitionsAlgebra[S, Alg]
|
D: DefinitionsAlgebra[S, Alg]
|
||||||
): EitherT[Alg, Raw, ServiceRaw] = for {
|
): EitherT[Alg, Raw, ServiceRaw] = {
|
||||||
arrows <- EitherT.fromOptionF(
|
(
|
||||||
// TODO: Move to purgeDefs here, allow not only arrows
|
for {
|
||||||
// from parsing, throw errors here
|
arrows <- OptionT(D.purgeArrows(expr.name))
|
||||||
D.purgeArrows(expr.name),
|
arrowsByName = arrows.map { case (name, arrow) =>
|
||||||
Raw.error("Service has no arrows")
|
name.value -> (name, arrow)
|
||||||
)
|
}.toNem
|
||||||
arrowsByName = arrows.map { case (name, arrow) =>
|
defaultId <- expr.id.traverse(id => OptionT(V.valueToStringRaw(id)))
|
||||||
name.value -> (name, arrow)
|
serviceType <- OptionT(T.defineServiceType(expr.name, arrowsByName.toSortedMap))
|
||||||
}.toNem
|
arrowsDefs = arrows.map { case (name, _) => name.value -> name }.toNem
|
||||||
defaultId <- expr.id.traverse(id =>
|
_ <- OptionT.withFilterF(
|
||||||
EitherT.fromOptionF(
|
A.defineService(
|
||||||
V.valueToStringRaw(id),
|
expr.name,
|
||||||
Raw.error("Failed to resolve default service id")
|
arrowsDefs,
|
||||||
)
|
defaultId
|
||||||
)
|
)
|
||||||
serviceType <- EitherT.fromOptionF(
|
)
|
||||||
T.defineServiceType(expr.name, arrowsByName.toSortedMap),
|
} yield ServiceRaw(
|
||||||
Raw.error("Failed to define service type")
|
expr.name.value,
|
||||||
)
|
serviceType,
|
||||||
arrowsDefs = arrows.map { case (name, _) => name.value -> name }.toNem
|
|
||||||
_ <- EitherT(
|
|
||||||
A.defineService(
|
|
||||||
expr.name,
|
|
||||||
arrowsDefs,
|
|
||||||
defaultId
|
defaultId
|
||||||
).map(defined =>
|
|
||||||
Raw
|
|
||||||
.error("Service not created due to validation errors")
|
|
||||||
.asLeft
|
|
||||||
.whenA(!defined)
|
|
||||||
)
|
)
|
||||||
)
|
).toRight(ErroredPart(expr.name.value))
|
||||||
} yield ServiceRaw(
|
}
|
||||||
expr.name.value,
|
|
||||||
serviceType,
|
|
||||||
defaultId
|
|
||||||
)
|
|
||||||
|
|
||||||
def program[Alg[_]: Monad](using
|
def program[Alg[_]: Monad](using
|
||||||
A: AbilitiesAlgebra[S, Alg],
|
A: AbilitiesAlgebra[S, Alg],
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package aqua.semantics.expr.func
|
package aqua.semantics.expr.func
|
||||||
|
|
||||||
import aqua.raw.Raw
|
import aqua.raw.{ErroredPart, Raw}
|
||||||
import aqua.raw.arrow.{ArrowRaw, FuncRaw}
|
import aqua.raw.arrow.{ArrowRaw, FuncRaw}
|
||||||
import aqua.parser.expr.FuncExpr
|
import aqua.parser.expr.FuncExpr
|
||||||
import aqua.parser.lexer.Arg
|
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)
|
N.defineArrow(expr.name, arrow.`type`, isRoot = true) as FuncRaw(expr.name.value, arrow)
|
||||||
|
|
||||||
case _ =>
|
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