mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 22:50:18 +00:00
refactor: Move LSP logic to LSP package (#701)
This commit is contained in:
parent
5f00b1ea8d
commit
dac8fb5774
@ -8,9 +8,8 @@ import aqua.parser.{Ast, ParserError}
|
|||||||
import aqua.raw.RawPart.Parts
|
import aqua.raw.RawPart.Parts
|
||||||
import aqua.raw.{RawContext, RawPart}
|
import aqua.raw.{RawContext, RawPart}
|
||||||
import aqua.res.AquaRes
|
import aqua.res.AquaRes
|
||||||
import aqua.semantics.{CompilerState, LspSemantics, RawSemantics, Semantics}
|
import aqua.semantics.{CompilerState, RawSemantics, Semantics}
|
||||||
import aqua.semantics.header.{HeaderHandler, HeaderSem}
|
import aqua.semantics.header.{HeaderHandler, HeaderSem}
|
||||||
import aqua.semantics.lsp.LspContext
|
|
||||||
import cats.data.*
|
import cats.data.*
|
||||||
import cats.data.Validated.{validNec, Invalid, Valid, invalid}
|
import cats.data.Validated.{validNec, Invalid, Valid, invalid}
|
||||||
import cats.parse.Parser0
|
import cats.parse.Parser0
|
||||||
@ -66,41 +65,6 @@ object CompilerAPI extends Logging {
|
|||||||
._1
|
._1
|
||||||
}
|
}
|
||||||
|
|
||||||
private def getLspAquaCompiler[F[_]: Monad, E, I: Order, S[_]: Comonad](
|
|
||||||
config: AquaCompilerConf
|
|
||||||
): AquaCompiler[F, E, I, S, LspContext[S]] = {
|
|
||||||
implicit val rc: Monoid[LspContext[S]] = LspContext
|
|
||||||
.implicits(
|
|
||||||
LspContext
|
|
||||||
.blank[S]
|
|
||||||
.copy(raw =
|
|
||||||
RawContext.blank.copy(parts =
|
|
||||||
Chain.fromSeq(config.constantsList).map(const => RawContext.blank -> const)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.lspContextMonoid
|
|
||||||
|
|
||||||
implicit val headerSemMonoid: Monoid[HeaderSem[S, LspContext[S]]] =
|
|
||||||
new Monoid[HeaderSem[S, LspContext[S]]] {
|
|
||||||
override def empty: HeaderSem[S, LspContext[S]] = HeaderSem(rc.empty, (c, _) => validNec(c))
|
|
||||||
|
|
||||||
override def combine(
|
|
||||||
a: HeaderSem[S, LspContext[S]],
|
|
||||||
b: HeaderSem[S, LspContext[S]]
|
|
||||||
): HeaderSem[S, LspContext[S]] = {
|
|
||||||
HeaderSem(
|
|
||||||
a.initCtx |+| b.initCtx,
|
|
||||||
(c, i) => a.finInitCtx(c, i).andThen(b.finInitCtx(_, i))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val semantics = new LspSemantics[S]()
|
|
||||||
|
|
||||||
new AquaCompiler[F, E, I, S, LspContext[S]](new HeaderHandler[S, LspContext[S]](), semantics)
|
|
||||||
}
|
|
||||||
|
|
||||||
private def getAquaCompiler[F[_]: Monad, E, I: Order, S[_]: Comonad](
|
private def getAquaCompiler[F[_]: Monad, E, I: Order, S[_]: Comonad](
|
||||||
config: AquaCompilerConf
|
config: AquaCompilerConf
|
||||||
): AquaCompiler[F, E, I, S, RawContext] = {
|
): AquaCompiler[F, E, I, S, RawContext] = {
|
||||||
@ -204,28 +168,6 @@ object CompilerAPI extends Logging {
|
|||||||
Validated.invalid[NonEmptyChain[AquaError[I, E, S]], Chain[T]](errs).pure[F]
|
Validated.invalid[NonEmptyChain[AquaError[I, E, S]], Chain[T]](errs).pure[F]
|
||||||
}
|
}
|
||||||
|
|
||||||
def compileToLsp[F[_]: Monad, E, I: Order, S[_]: Comonad](
|
|
||||||
sources: AquaSources[F, E, I],
|
|
||||||
parser: I => String => ValidatedNec[ParserError[S], Ast[S]],
|
|
||||||
config: AquaCompilerConf
|
|
||||||
): F[Validated[NonEmptyChain[AquaError[I, E, S]], Map[I, Validated[NonEmptyChain[
|
|
||||||
AquaError[I, E, S]
|
|
||||||
], Map[I, LspContext[S]]]]]] = {
|
|
||||||
|
|
||||||
val compiler = getLspAquaCompiler[F, E, I, S](config)
|
|
||||||
compiler
|
|
||||||
.compileRaw(sources, parser)
|
|
||||||
.map { v =>
|
|
||||||
v.map { innerMap =>
|
|
||||||
innerMap.view.mapValues { vCtx =>
|
|
||||||
vCtx.map {
|
|
||||||
_.toSortedMap.toMap
|
|
||||||
}
|
|
||||||
}.toMap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def compileToContext[F[_]: Monad, E, I: Order, S[_]: Comonad](
|
def compileToContext[F[_]: Monad, E, I: Order, S[_]: Comonad](
|
||||||
sources: AquaSources[F, E, I],
|
sources: AquaSources[F, E, I],
|
||||||
parser: I => String => ValidatedNec[ParserError[S], Ast[S]],
|
parser: I => String => ValidatedNec[ParserError[S], Ast[S]],
|
||||||
|
@ -31,7 +31,6 @@ import aqua.res.{
|
|||||||
SeqRes,
|
SeqRes,
|
||||||
XorRes
|
XorRes
|
||||||
}
|
}
|
||||||
import aqua.semantics.lsp.LspContext
|
|
||||||
import aqua.types.{ArrayType, CanonStreamType, LiteralType, ScalarType, StreamType, Type}
|
import aqua.types.{ArrayType, CanonStreamType, LiteralType, ScalarType, StreamType, Type}
|
||||||
import org.scalatest.flatspec.AnyFlatSpec
|
import org.scalatest.flatspec.AnyFlatSpec
|
||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
@ -68,14 +67,6 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers {
|
|||||||
AquaCompilerConf()
|
AquaCompilerConf()
|
||||||
)
|
)
|
||||||
|
|
||||||
private def compileToLsp(src: Map[String, String], imports: Map[String, String]) =
|
|
||||||
CompilerAPI
|
|
||||||
.compileToLsp[Id, String, String, Span.S](
|
|
||||||
aquaSource(src, imports),
|
|
||||||
id => txt => Parser.parse(Parser.parserSchema)(txt),
|
|
||||||
AquaCompilerConf()
|
|
||||||
)
|
|
||||||
|
|
||||||
"aqua compiler" should "compile a simple snipped to the right context" in {
|
"aqua compiler" should "compile a simple snipped to the right context" in {
|
||||||
|
|
||||||
val res = compileToContext(
|
val res = compileToContext(
|
||||||
|
@ -7,8 +7,8 @@ import aqua.parser.lexer.{LiteralToken, Token}
|
|||||||
import aqua.parser.lift.FileSpan.F
|
import aqua.parser.lift.FileSpan.F
|
||||||
import aqua.parser.lift.{FileSpan, Span}
|
import aqua.parser.lift.{FileSpan, Span}
|
||||||
import aqua.parser.{ArrowReturnError, BlockIndentError, LexerError, ParserError}
|
import aqua.parser.{ArrowReturnError, BlockIndentError, LexerError, ParserError}
|
||||||
import aqua.semantics.lsp.{LspContext, TokenInfo}
|
import aqua.semantics.lsp.TokenInfo
|
||||||
import aqua.semantics.{CompilerState, HeaderError, RulesViolated, WrongAST}
|
import aqua.semantics.{HeaderError, RulesViolated, WrongAST}
|
||||||
import aqua.{AquaIO, SpanParser}
|
import aqua.{AquaIO, SpanParser}
|
||||||
import cats.data.{NonEmptyChain, Validated}
|
import cats.data.{NonEmptyChain, Validated}
|
||||||
import cats.data.Validated.{invalidNec, validNec, Invalid, Valid}
|
import cats.data.Validated.{invalidNec, validNec, Invalid, Valid}
|
||||||
@ -142,7 +142,7 @@ object AquaLSP extends App with Logging {
|
|||||||
|
|
||||||
val proc = for {
|
val proc = for {
|
||||||
|
|
||||||
res <- CompilerAPI
|
res <- LSPCompiler
|
||||||
.compileToLsp[IO, AquaFileError, FileModuleId, FileSpan.F](
|
.compileToLsp[IO, AquaFileError, FileModuleId, FileSpan.F](
|
||||||
sources,
|
sources,
|
||||||
SpanParser.parser,
|
SpanParser.parser,
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
package aqua.lsp
|
||||||
|
|
||||||
|
import aqua.compiler.{AquaCompiler, AquaCompilerConf, AquaError, AquaSources}
|
||||||
|
import aqua.parser.{Ast, ParserError}
|
||||||
|
import aqua.raw.RawContext
|
||||||
|
import aqua.semantics.header.{HeaderHandler, HeaderSem}
|
||||||
|
import cats.data.Validated.validNec
|
||||||
|
import cats.syntax.semigroup.*
|
||||||
|
import cats.syntax.applicative.*
|
||||||
|
import cats.syntax.flatMap.*
|
||||||
|
import cats.syntax.functor.*
|
||||||
|
import cats.syntax.monoid.*
|
||||||
|
import cats.syntax.traverse.*
|
||||||
|
import cats.{Comonad, Monad, Monoid, Order}
|
||||||
|
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}
|
||||||
|
|
||||||
|
object LSPCompiler {
|
||||||
|
|
||||||
|
private def getLspAquaCompiler[F[_]: Monad, E, I: Order, S[_]: Comonad](
|
||||||
|
config: AquaCompilerConf
|
||||||
|
): AquaCompiler[F, E, I, S, LspContext[S]] = {
|
||||||
|
implicit val rc: Monoid[LspContext[S]] = LspContext
|
||||||
|
.implicits(
|
||||||
|
LspContext
|
||||||
|
.blank[S]
|
||||||
|
.copy(raw =
|
||||||
|
RawContext.blank.copy(parts =
|
||||||
|
Chain.fromSeq(config.constantsList).map(const => RawContext.blank -> const)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.lspContextMonoid
|
||||||
|
|
||||||
|
implicit val headerSemMonoid: Monoid[HeaderSem[S, LspContext[S]]] =
|
||||||
|
new Monoid[HeaderSem[S, LspContext[S]]] {
|
||||||
|
override def empty: HeaderSem[S, LspContext[S]] = HeaderSem(rc.empty, (c, _) => validNec(c))
|
||||||
|
|
||||||
|
override def combine(
|
||||||
|
a: HeaderSem[S, LspContext[S]],
|
||||||
|
b: HeaderSem[S, LspContext[S]]
|
||||||
|
): HeaderSem[S, LspContext[S]] = {
|
||||||
|
HeaderSem(
|
||||||
|
a.initCtx |+| b.initCtx,
|
||||||
|
(c, i) => a.finInitCtx(c, i).andThen(b.finInitCtx(_, i))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val semantics = new LspSemantics[S]()
|
||||||
|
|
||||||
|
new AquaCompiler[F, E, I, S, LspContext[S]](new HeaderHandler[S, LspContext[S]](), semantics)
|
||||||
|
}
|
||||||
|
|
||||||
|
def compileToLsp[F[_]: Monad, E, I: Order, S[_]: Comonad](
|
||||||
|
sources: AquaSources[F, E, I],
|
||||||
|
parser: I => String => ValidatedNec[ParserError[S], Ast[S]],
|
||||||
|
config: AquaCompilerConf
|
||||||
|
): F[Validated[NonEmptyChain[AquaError[I, E, S]], Map[I, Validated[NonEmptyChain[
|
||||||
|
AquaError[I, E, S]
|
||||||
|
], Map[I, LspContext[S]]]]]] = {
|
||||||
|
|
||||||
|
val compiler = getLspAquaCompiler[F, E, I, S](config)
|
||||||
|
compiler
|
||||||
|
.compileRaw(sources, parser)
|
||||||
|
.map { v =>
|
||||||
|
v.map { innerMap =>
|
||||||
|
innerMap.view.mapValues { vCtx =>
|
||||||
|
vCtx.map {
|
||||||
|
_.toSortedMap.toMap
|
||||||
|
}
|
||||||
|
}.toMap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package aqua.lsp
|
||||||
|
|
||||||
|
import aqua.parser.lexer.Token
|
||||||
|
import aqua.semantics.lsp.{TokenInfo, TokenType}
|
||||||
|
import aqua.semantics.rules.locations.{LocationsAlgebra, LocationsState}
|
||||||
|
import cats.data.State
|
||||||
|
import monocle.Lens
|
||||||
|
|
||||||
|
class LocationsInterpreter[S[_], X](implicit
|
||||||
|
lens: Lens[X, LocationsState[S]]
|
||||||
|
) extends LocationsAlgebra[S, State[X, *]] {
|
||||||
|
|
||||||
|
type SX[A] = State[X, A]
|
||||||
|
|
||||||
|
private def getState = State.get.map(lens.get)
|
||||||
|
|
||||||
|
private def modify(f: LocationsState[S] => LocationsState[S]): SX[Unit] =
|
||||||
|
State.modify(lens.modify(f))
|
||||||
|
|
||||||
|
override def addNameLocations(locs: List[(Token[S], TokenType[S])]): State[X, Unit] =
|
||||||
|
modify(st => st.copy(nameLocations = st.nameLocations ++ locs))
|
||||||
|
|
||||||
|
override def addNameLocation(token: Token[S], tokenType: TokenType[S]): State[X, Unit] =
|
||||||
|
modify(st => st.copy(nameLocations = st.nameLocations :+ (token, tokenType)))
|
||||||
|
|
||||||
|
override def addTypeLocations(locs: List[(Token[S], TokenInfo[S])]): State[X, Unit] =
|
||||||
|
modify(st => st.copy(typeLocations = st.nameLocations ++ locs))
|
||||||
|
|
||||||
|
override def addTypeLocation(token: Token[S], tokenInfo: TokenInfo[S]): State[X, Unit] =
|
||||||
|
modify(st => st.copy(typeLocations = st.typeLocations :+ (token, tokenInfo)))
|
||||||
|
|
||||||
|
override def addServiceLocations(locs: List[(Token[S], TokenInfo[S])]): State[X, Unit] =
|
||||||
|
modify(st => st.copy(serviceLocations = st.nameLocations ++ locs))
|
||||||
|
|
||||||
|
override def addServiceLocation(token: Token[S], tokenInfo: TokenInfo[S]): State[X, Unit] =
|
||||||
|
modify(st => st.copy(serviceLocations = st.serviceLocations :+ (token, tokenInfo)))
|
||||||
|
}
|
@ -1,9 +1,10 @@
|
|||||||
package aqua.semantics.lsp
|
package aqua.lsp
|
||||||
|
|
||||||
import aqua.parser.lexer.{Ability, LiteralToken, Name, Token}
|
import aqua.parser.lexer.{Ability, LiteralToken, Name, Token}
|
||||||
import aqua.raw.{RawContext, RawPart}
|
import aqua.raw.{RawContext, RawPart}
|
||||||
import aqua.types.ArrowType
|
import aqua.types.ArrowType
|
||||||
import cats.{Monoid, Semigroup}
|
import cats.{Monoid, Semigroup}
|
||||||
|
import aqua.semantics.lsp.{TokenArrowInfo, TokenType, TokenInfo}
|
||||||
import cats.syntax.monoid.*
|
import cats.syntax.monoid.*
|
||||||
import RawContext.semiRC
|
import RawContext.semiRC
|
||||||
import aqua.semantics.header.{Picker, PickerOps}
|
import aqua.semantics.header.{Picker, PickerOps}
|
@ -0,0 +1,78 @@
|
|||||||
|
package aqua.lsp
|
||||||
|
|
||||||
|
import aqua.parser.Ast
|
||||||
|
import aqua.parser.head.{ImportExpr, ImportFromExpr}
|
||||||
|
import aqua.parser.lexer.LiteralToken
|
||||||
|
import aqua.semantics.rules.locations.LocationsState
|
||||||
|
import aqua.semantics.{CompilerState, SemanticError, Semantics}
|
||||||
|
import cats.data.Validated.{Invalid, Valid}
|
||||||
|
import cats.syntax.applicative.*
|
||||||
|
import cats.syntax.apply.*
|
||||||
|
import cats.syntax.flatMap.*
|
||||||
|
import cats.syntax.functor.*
|
||||||
|
import cats.syntax.foldable.*
|
||||||
|
import cats.syntax.reducible.*
|
||||||
|
import cats.data.{NonEmptyChain, ValidatedNec}
|
||||||
|
import monocle.Lens
|
||||||
|
import monocle.macros.GenLens
|
||||||
|
|
||||||
|
class LspSemantics[S[_]] extends Semantics[S, LspContext[S]] {
|
||||||
|
|
||||||
|
def getImportTokens(ast: Ast[S]): List[LiteralToken[S]] = {
|
||||||
|
ast.head.foldLeft[List[LiteralToken[S]]](Nil) { case (l, header) =>
|
||||||
|
header match {
|
||||||
|
case ImportExpr(fn) =>
|
||||||
|
println("import: " + fn)
|
||||||
|
l :+ fn
|
||||||
|
case ImportFromExpr(_, fn) => l :+ fn
|
||||||
|
case _ => l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def process(
|
||||||
|
ast: Ast[S],
|
||||||
|
init: LspContext[S]
|
||||||
|
): ValidatedNec[SemanticError[S], LspContext[S]] = {
|
||||||
|
|
||||||
|
val rawState = CompilerState.init[S](init.raw)
|
||||||
|
val initState = rawState.copy(
|
||||||
|
names = rawState.names.copy(
|
||||||
|
rootArrows = rawState.names.rootArrows ++ init.rootArrows,
|
||||||
|
constants = rawState.names.constants ++ init.constants
|
||||||
|
),
|
||||||
|
abilities = rawState.abilities.copy(
|
||||||
|
definitions = rawState.abilities.definitions ++ init.abDefinitions
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val importTokens = getImportTokens(ast)
|
||||||
|
|
||||||
|
implicit val ls: Lens[CompilerState[S], LocationsState[S]] =
|
||||||
|
GenLens[CompilerState[S]](_.locations)
|
||||||
|
|
||||||
|
implicit val locationsInterpreter: LocationsInterpreter[S, CompilerState[S]] =
|
||||||
|
new LocationsInterpreter[S, CompilerState[S]]()
|
||||||
|
|
||||||
|
Semantics
|
||||||
|
.interpret(ast, initState, init.raw)
|
||||||
|
.map { case (state, ctx) =>
|
||||||
|
NonEmptyChain
|
||||||
|
.fromChain(state.errors)
|
||||||
|
.fold[ValidatedNec[SemanticError[S], LspContext[S]]] {
|
||||||
|
Valid(
|
||||||
|
LspContext(
|
||||||
|
raw = ctx,
|
||||||
|
rootArrows = state.names.rootArrows,
|
||||||
|
constants = state.names.constants,
|
||||||
|
abDefinitions = state.abilities.definitions,
|
||||||
|
locations = state.locations.allLocations,
|
||||||
|
importTokens = importTokens
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}(Invalid(_))
|
||||||
|
}
|
||||||
|
// TODO: return as Eval
|
||||||
|
.value
|
||||||
|
}
|
||||||
|
}
|
19
model/raw/src/main/scala/aqua/raw/ScopeRaw.scala
Normal file
19
model/raw/src/main/scala/aqua/raw/ScopeRaw.scala
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package aqua.raw
|
||||||
|
|
||||||
|
import aqua.raw.arrow.FuncRaw
|
||||||
|
import aqua.types.{ArrowType, StructType, Type}
|
||||||
|
import cats.data.NonEmptyMap
|
||||||
|
import aqua.raw.value.ValueRaw
|
||||||
|
|
||||||
|
import scala.collection.immutable.SortedMap
|
||||||
|
|
||||||
|
case class ScopeRaw(
|
||||||
|
name: String,
|
||||||
|
fieldsAndArrows: NonEmptyMap[String, Type]
|
||||||
|
) extends RawPart {
|
||||||
|
lazy val rawPartType: StructType = StructType(name, fieldsAndArrows)
|
||||||
|
|
||||||
|
|
||||||
|
override def rename(s: String): RawPart = copy(name = s)
|
||||||
|
|
||||||
|
}
|
25
parser/src/main/scala/aqua/parser/expr/ScopeExpr.scala
Normal file
25
parser/src/main/scala/aqua/parser/expr/ScopeExpr.scala
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package aqua.parser.expr
|
||||||
|
|
||||||
|
import aqua.parser.Expr
|
||||||
|
import aqua.parser.lexer.Token.*
|
||||||
|
import aqua.parser.lexer.{Ability, Name, ValueToken}
|
||||||
|
import aqua.parser.lift.LiftParser
|
||||||
|
import cats.Comonad
|
||||||
|
import cats.parse.Parser
|
||||||
|
import cats.~>
|
||||||
|
import aqua.parser.lift.Span
|
||||||
|
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||||
|
|
||||||
|
case class ScopeExpr[F[_]](name: Ability[F]) extends Expr[F](ScopeExpr, name) {
|
||||||
|
|
||||||
|
override def mapK[K[_]: Comonad](fk: F ~> K): ScopeExpr[K] =
|
||||||
|
copy(name.mapK(fk))
|
||||||
|
}
|
||||||
|
|
||||||
|
object ScopeExpr extends Expr.AndIndented {
|
||||||
|
|
||||||
|
override def validChildren: List[Expr.Lexem] = FieldTypeExpr :: ArrowTypeExpr :: Nil
|
||||||
|
|
||||||
|
override val p: Parser[ScopeExpr[Span.S]] =
|
||||||
|
(`scope` *> ` ` *> Ability.ab).map(ScopeExpr(_))
|
||||||
|
}
|
@ -49,6 +49,7 @@ object Token {
|
|||||||
val ` as ` : P[Unit] = `as`.surroundedBy(` `)
|
val ` as ` : P[Unit] = `as`.surroundedBy(` `)
|
||||||
val `alias`: P[Unit] = P.string("alias")
|
val `alias`: P[Unit] = P.string("alias")
|
||||||
val `service`: P[Unit] = P.string("service")
|
val `service`: P[Unit] = P.string("service")
|
||||||
|
val `scope`: P[Unit] = P.string("scope")
|
||||||
val `func`: P[Unit] = P.string("func")
|
val `func`: P[Unit] = P.string("func")
|
||||||
val `on`: P[Unit] = P.string("on")
|
val `on`: P[Unit] = P.string("on")
|
||||||
val `via`: P[Unit] = P.string("via")
|
val `via`: P[Unit] = P.string("via")
|
||||||
|
@ -5,6 +5,7 @@ import aqua.raw.Raw
|
|||||||
import aqua.raw.RawContext
|
import aqua.raw.RawContext
|
||||||
import aqua.semantics.lsp.{TokenInfo, TokenType}
|
import aqua.semantics.lsp.{TokenInfo, TokenType}
|
||||||
import aqua.semantics.rules.abilities.AbilitiesState
|
import aqua.semantics.rules.abilities.AbilitiesState
|
||||||
|
import aqua.semantics.rules.locations.LocationsState
|
||||||
import aqua.semantics.rules.names.NamesState
|
import aqua.semantics.rules.names.NamesState
|
||||||
import aqua.semantics.rules.types.TypesState
|
import aqua.semantics.rules.types.TypesState
|
||||||
import cats.Semigroup
|
import cats.Semigroup
|
||||||
@ -16,9 +17,9 @@ case class CompilerState[S[_]](
|
|||||||
errors: Chain[SemanticError[S]] = Chain.empty[SemanticError[S]],
|
errors: Chain[SemanticError[S]] = Chain.empty[SemanticError[S]],
|
||||||
names: NamesState[S] = NamesState[S](),
|
names: NamesState[S] = NamesState[S](),
|
||||||
abilities: AbilitiesState[S] = AbilitiesState[S](),
|
abilities: AbilitiesState[S] = AbilitiesState[S](),
|
||||||
types: TypesState[S] = TypesState[S]()
|
types: TypesState[S] = TypesState[S](),
|
||||||
|
locations: LocationsState[S] = LocationsState[S]()
|
||||||
) {
|
) {
|
||||||
lazy val locations: List[(Token[S], TokenInfo[S])] = names.locations ++ abilities.locations ++ types.locations
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object CompilerState {
|
object CompilerState {
|
||||||
|
@ -47,6 +47,7 @@ object ExprSem {
|
|||||||
case expr: JoinExpr[S] => new JoinSem(expr).program[G]
|
case expr: JoinExpr[S] => new JoinSem(expr).program[G]
|
||||||
case expr: ReturnExpr[S] => new ReturnSem(expr).program[G]
|
case expr: ReturnExpr[S] => new ReturnSem(expr).program[G]
|
||||||
case expr: ServiceExpr[S] => new ServiceSem(expr).program[G]
|
case expr: ServiceExpr[S] => new ServiceSem(expr).program[G]
|
||||||
|
case expr: ScopeExpr[S] => new ScopeSem(expr).program[G]
|
||||||
case expr: RootExpr[S] => new RootSem(expr).program[G]
|
case expr: RootExpr[S] => new RootSem(expr).program[G]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,8 +7,9 @@ import aqua.raw.ops.{FuncOp, SeqGroupTag}
|
|||||||
import aqua.raw.{Raw, RawContext, RawPart}
|
import aqua.raw.{Raw, RawContext, RawPart}
|
||||||
import aqua.semantics.header.Picker
|
import aqua.semantics.header.Picker
|
||||||
import aqua.semantics.header.Picker.*
|
import aqua.semantics.header.Picker.*
|
||||||
import aqua.semantics.lsp.{LspContext, TokenDef, TokenInfo, TokenType}
|
import aqua.semantics.lsp.{TokenDef, TokenInfo, TokenType}
|
||||||
import aqua.semantics.rules.abilities.{AbilitiesAlgebra, AbilitiesInterpreter, AbilitiesState}
|
import aqua.semantics.rules.abilities.{AbilitiesAlgebra, AbilitiesInterpreter, AbilitiesState}
|
||||||
|
import aqua.semantics.rules.locations.{DummyLocationsInterpreter, LocationsAlgebra, LocationsState}
|
||||||
import aqua.semantics.rules.names.{NamesAlgebra, NamesInterpreter, NamesState}
|
import aqua.semantics.rules.names.{NamesAlgebra, NamesInterpreter, NamesState}
|
||||||
import aqua.semantics.rules.types.{TypesAlgebra, TypesInterpreter, TypesState}
|
import aqua.semantics.rules.types.{TypesAlgebra, TypesInterpreter, TypesState}
|
||||||
import aqua.semantics.rules.{ReportError, ValuesAlgebra}
|
import aqua.semantics.rules.{ReportError, ValuesAlgebra}
|
||||||
@ -31,7 +32,7 @@ import monocle.macros.GenLens
|
|||||||
import scribe.{Logging, log}
|
import scribe.{Logging, log}
|
||||||
import cats.free.Cofree
|
import cats.free.Cofree
|
||||||
|
|
||||||
sealed trait Semantics[S[_], C] {
|
trait Semantics[S[_], C] {
|
||||||
|
|
||||||
def process(
|
def process(
|
||||||
ast: Ast[S],
|
ast: Ast[S],
|
||||||
@ -44,7 +45,11 @@ class RawSemantics[S[_]](implicit p: Picker[RawContext]) extends Semantics[S, Ra
|
|||||||
def process(
|
def process(
|
||||||
ast: Ast[S],
|
ast: Ast[S],
|
||||||
init: RawContext
|
init: RawContext
|
||||||
): ValidatedNec[SemanticError[S], RawContext] =
|
): ValidatedNec[SemanticError[S], RawContext] = {
|
||||||
|
|
||||||
|
implicit val locationsInterpreter: DummyLocationsInterpreter[S, CompilerState[S]] =
|
||||||
|
new DummyLocationsInterpreter[S, CompilerState[S]]()
|
||||||
|
|
||||||
Semantics
|
Semantics
|
||||||
.interpret(ast, CompilerState.init(init), init)
|
.interpret(ast, CompilerState.init(init), init)
|
||||||
.map { case (state, ctx) =>
|
.map { case (state, ctx) =>
|
||||||
@ -56,61 +61,6 @@ class RawSemantics[S[_]](implicit p: Picker[RawContext]) extends Semantics[S, Ra
|
|||||||
}
|
}
|
||||||
// TODO: return as Eval
|
// TODO: return as Eval
|
||||||
.value
|
.value
|
||||||
}
|
|
||||||
|
|
||||||
class LspSemantics[S[_]] extends Semantics[S, LspContext[S]] {
|
|
||||||
|
|
||||||
def getImportTokens(ast: Ast[S]): List[LiteralToken[S]] = {
|
|
||||||
ast.head.foldLeft[List[LiteralToken[S]]](Nil){ case (l, header) =>
|
|
||||||
header match {
|
|
||||||
case ImportExpr(fn) =>
|
|
||||||
println("import: " + fn)
|
|
||||||
l :+ fn
|
|
||||||
case ImportFromExpr(_, fn) => l :+ fn
|
|
||||||
case _ => l
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def process(
|
|
||||||
ast: Ast[S],
|
|
||||||
init: LspContext[S]
|
|
||||||
): ValidatedNec[SemanticError[S], LspContext[S]] = {
|
|
||||||
|
|
||||||
val rawState = CompilerState.init[S](init.raw)
|
|
||||||
val initState = rawState.copy(
|
|
||||||
names = rawState.names.copy(
|
|
||||||
rootArrows = rawState.names.rootArrows ++ init.rootArrows,
|
|
||||||
constants = rawState.names.constants ++ init.constants
|
|
||||||
),
|
|
||||||
abilities = rawState.abilities.copy(
|
|
||||||
definitions = rawState.abilities.definitions ++ init.abDefinitions
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
val importTokens = getImportTokens(ast)
|
|
||||||
|
|
||||||
|
|
||||||
Semantics
|
|
||||||
.interpret(ast, initState, init.raw)
|
|
||||||
.map { case (state, ctx) =>
|
|
||||||
NonEmptyChain
|
|
||||||
.fromChain(state.errors)
|
|
||||||
.fold[ValidatedNec[SemanticError[S], LspContext[S]]] {
|
|
||||||
Valid(
|
|
||||||
LspContext(
|
|
||||||
raw = ctx,
|
|
||||||
rootArrows = state.names.rootArrows,
|
|
||||||
constants = state.names.constants,
|
|
||||||
abDefinitions = state.abilities.definitions,
|
|
||||||
locations = state.locations,
|
|
||||||
importTokens = importTokens
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}(Invalid(_))
|
|
||||||
}
|
|
||||||
// TODO: return as Eval
|
|
||||||
.value
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +93,7 @@ object Semantics extends Logging {
|
|||||||
|
|
||||||
type Interpreter[S[_], A] = State[CompilerState[S], A]
|
type Interpreter[S[_], A] = State[CompilerState[S], A]
|
||||||
|
|
||||||
def transpile[S[_]](ast: Ast[S]): Interpreter[S, Raw] = {
|
def transpile[S[_]](ast: Ast[S])(implicit locations: LocationsAlgebra[S, Interpreter[S, *]]): Interpreter[S, Raw] = {
|
||||||
import monocle.syntax.all.*
|
import monocle.syntax.all.*
|
||||||
|
|
||||||
implicit val re: ReportError[S, CompilerState[S]] =
|
implicit val re: ReportError[S, CompilerState[S]] =
|
||||||
@ -166,7 +116,7 @@ object Semantics extends Logging {
|
|||||||
ast.cata(folder[S, Interpreter[S, *]]).value
|
ast.cata(folder[S, Interpreter[S, *]]).value
|
||||||
}
|
}
|
||||||
|
|
||||||
private def astToState[S[_]](ast: Ast[S]): Interpreter[S, Raw] =
|
private def astToState[S[_]](ast: Ast[S])(implicit locations: LocationsAlgebra[S, Interpreter[S, *]]): Interpreter[S, Raw] =
|
||||||
transpile[S](ast)
|
transpile[S](ast)
|
||||||
|
|
||||||
// If there are any errors, they're inside CompilerState[S]
|
// If there are any errors, they're inside CompilerState[S]
|
||||||
@ -174,7 +124,7 @@ object Semantics extends Logging {
|
|||||||
ast: Ast[S],
|
ast: Ast[S],
|
||||||
initState: CompilerState[S],
|
initState: CompilerState[S],
|
||||||
init: RawContext
|
init: RawContext
|
||||||
): Eval[(CompilerState[S], RawContext)] =
|
)(implicit locations: LocationsAlgebra[S, Interpreter[S, *]]): Eval[(CompilerState[S], RawContext)] =
|
||||||
astToState[S](ast)
|
astToState[S](ast)
|
||||||
.run(initState)
|
.run(initState)
|
||||||
.map {
|
.map {
|
||||||
|
32
semantics/src/main/scala/aqua/semantics/expr/ScopeSem.scala
Normal file
32
semantics/src/main/scala/aqua/semantics/expr/ScopeSem.scala
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package aqua.semantics.expr
|
||||||
|
|
||||||
|
import aqua.parser.expr.ScopeExpr
|
||||||
|
import aqua.parser.lexer.{CustomTypeToken, Name}
|
||||||
|
import aqua.raw.{Raw, ServiceRaw}
|
||||||
|
import aqua.semantics.Prog
|
||||||
|
import aqua.semantics.rules.ValuesAlgebra
|
||||||
|
import aqua.semantics.rules.abilities.AbilitiesAlgebra
|
||||||
|
import aqua.semantics.rules.names.NamesAlgebra
|
||||||
|
import aqua.semantics.rules.types.TypesAlgebra
|
||||||
|
import aqua.types.{ArrowType, Type}
|
||||||
|
import aqua.raw.ScopeRaw
|
||||||
|
import cats.syntax.apply.*
|
||||||
|
import cats.syntax.flatMap.*
|
||||||
|
import cats.syntax.functor.*
|
||||||
|
import cats.syntax.applicative.*
|
||||||
|
import cats.Monad
|
||||||
|
import cats.data.NonEmptyList
|
||||||
|
|
||||||
|
class ScopeSem[S[_]](val expr: ScopeExpr[S]) extends AnyVal {
|
||||||
|
|
||||||
|
def program[Alg[_]: Monad](implicit
|
||||||
|
A: AbilitiesAlgebra[S, Alg],
|
||||||
|
N: NamesAlgebra[S, Alg],
|
||||||
|
T: TypesAlgebra[S, Alg],
|
||||||
|
V: ValuesAlgebra[S, Alg]
|
||||||
|
): Prog[Alg, Raw] =
|
||||||
|
Prog.around(
|
||||||
|
A.beginScope(expr.name),
|
||||||
|
(_: Unit, _: Raw) =>
|
||||||
|
Raw.error("Undefined").pure[Alg])
|
||||||
|
}
|
@ -2,7 +2,7 @@ package aqua.semantics.header
|
|||||||
|
|
||||||
import aqua.raw.{RawContext, RawPart}
|
import aqua.raw.{RawContext, RawPart}
|
||||||
import aqua.semantics.CompilerState
|
import aqua.semantics.CompilerState
|
||||||
import aqua.semantics.lsp.{LspContext, TokenArrowInfo, TokenTypeInfo}
|
import aqua.semantics.lsp.{TokenArrowInfo, TokenTypeInfo}
|
||||||
import aqua.semantics.rules.abilities.AbilitiesState
|
import aqua.semantics.rules.abilities.AbilitiesState
|
||||||
import aqua.semantics.rules.names.NamesState
|
import aqua.semantics.rules.names.NamesState
|
||||||
import aqua.semantics.rules.types.TypesState
|
import aqua.semantics.rules.types.TypesState
|
||||||
|
@ -6,6 +6,7 @@ import aqua.raw.RawContext
|
|||||||
import aqua.raw.value.ValueRaw
|
import aqua.raw.value.ValueRaw
|
||||||
import aqua.semantics.lsp.{TokenArrowInfo, TokenDef, TokenTypeInfo}
|
import aqua.semantics.lsp.{TokenArrowInfo, TokenDef, TokenTypeInfo}
|
||||||
import aqua.semantics.Levenshtein
|
import aqua.semantics.Levenshtein
|
||||||
|
import aqua.semantics.rules.locations.LocationsAlgebra
|
||||||
import aqua.semantics.rules.{abilities, ReportError, StackInterpreter}
|
import aqua.semantics.rules.{abilities, ReportError, StackInterpreter}
|
||||||
import aqua.types.ArrowType
|
import aqua.types.ArrowType
|
||||||
import cats.data.{NonEmptyList, NonEmptyMap, State}
|
import cats.data.{NonEmptyList, NonEmptyMap, State}
|
||||||
@ -16,7 +17,8 @@ import monocle.macros.GenLens
|
|||||||
|
|
||||||
class AbilitiesInterpreter[S[_], X](implicit
|
class AbilitiesInterpreter[S[_], X](implicit
|
||||||
lens: Lens[X, AbilitiesState[S]],
|
lens: Lens[X, AbilitiesState[S]],
|
||||||
error: ReportError[S, X]
|
error: ReportError[S, X],
|
||||||
|
locations: LocationsAlgebra[S, State[X, *]]
|
||||||
) extends AbilitiesAlgebra[S, State[X, *]] {
|
) extends AbilitiesAlgebra[S, State[X, *]] {
|
||||||
|
|
||||||
type SX[A] = State[X, A]
|
type SX[A] = State[X, A]
|
||||||
@ -78,17 +80,13 @@ class AbilitiesInterpreter[S[_], X](implicit
|
|||||||
getState.flatMap { st =>
|
getState.flatMap { st =>
|
||||||
st.definitions.get(name.value) match {
|
st.definitions.get(name.value) match {
|
||||||
case Some((ab, arrows)) =>
|
case Some((ab, arrows)) =>
|
||||||
modify(st =>
|
locations.addServiceLocations(
|
||||||
st.copy(locations =
|
(name, TokenDef(Some(ab))) :: (
|
||||||
st.locations ++ (
|
arrow,
|
||||||
(name, TokenDef(Some(ab))) :: (
|
TokenDef(
|
||||||
arrow,
|
arrows.find(_._1.value == arrow.value).map(_._1)
|
||||||
TokenDef(
|
|
||||||
arrows.find(_._1.value == arrow.value).map(_._1)
|
|
||||||
)
|
|
||||||
) :: Nil
|
|
||||||
)
|
)
|
||||||
)
|
) :: Nil
|
||||||
)
|
)
|
||||||
case None =>
|
case None =>
|
||||||
State.pure(())
|
State.pure(())
|
||||||
@ -127,8 +125,7 @@ class AbilitiesInterpreter[S[_], X](implicit
|
|||||||
) { fn =>
|
) { fn =>
|
||||||
// TODO: add name and arrow separately
|
// TODO: add name and arrow separately
|
||||||
// TODO: find tokens somewhere
|
// TODO: find tokens somewhere
|
||||||
// addServiceArrowLocation(name, arrow).as(Some(fn.arrow.`type`))
|
addServiceArrowLocation(name, arrow).as(Some(fn.arrow.`type`))
|
||||||
State.pure(Some(fn.arrow.`type`))
|
|
||||||
}
|
}
|
||||||
case None =>
|
case None =>
|
||||||
report(name, "Ability with this name is undefined").as(Option.empty[ArrowType])
|
report(name, "Ability with this name is undefined").as(Option.empty[ArrowType])
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package aqua.semantics.rules.locations
|
||||||
|
import aqua.parser.lexer.Token
|
||||||
|
import aqua.semantics.lsp.{TokenInfo, TokenType}
|
||||||
|
|
||||||
|
trait LocationsAlgebra[S[_], Alg[_]] {
|
||||||
|
def addNameLocations(locs: List[(Token[S], TokenType[S])]): Alg[Unit]
|
||||||
|
def addNameLocation(token: Token[S], tokenType: TokenType[S]): Alg[Unit]
|
||||||
|
|
||||||
|
def addTypeLocations(locs: List[(Token[S], TokenInfo[S])]): Alg[Unit]
|
||||||
|
def addTypeLocation(token: Token[S], tokenInfo: TokenInfo[S]): Alg[Unit]
|
||||||
|
|
||||||
|
def addServiceLocations(locs: List[(Token[S], TokenInfo[S])]): Alg[Unit]
|
||||||
|
def addServiceLocation(token: Token[S], tokenInfo: TokenInfo[S]): Alg[Unit]
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package aqua.semantics.rules.locations
|
||||||
|
|
||||||
|
import aqua.parser.lexer.Token
|
||||||
|
import aqua.semantics.lsp.{TokenInfo, TokenType}
|
||||||
|
import aqua.semantics.rules.StackInterpreter
|
||||||
|
import aqua.semantics.rules.types.TypesState
|
||||||
|
import monocle.Lens
|
||||||
|
import monocle.macros.GenLens
|
||||||
|
import cats.data.{NonEmptyList, NonEmptyMap, State}
|
||||||
|
|
||||||
|
class DummyLocationsInterpreter[S[_], X] extends LocationsAlgebra[S, State[X, *]] {
|
||||||
|
|
||||||
|
override def addNameLocations(locs: List[(Token[S], TokenType[S])]): State[X, Unit] = State.pure(())
|
||||||
|
|
||||||
|
override def addNameLocation(token: Token[S], tokenType: TokenType[S]): State[X, Unit] = State.pure(())
|
||||||
|
|
||||||
|
override def addTypeLocations(locs: List[(Token[S], TokenInfo[S])]): State[X, Unit] = State.pure(())
|
||||||
|
|
||||||
|
override def addTypeLocation(token: Token[S], tokenInfo: TokenInfo[S]): State[X, Unit] = State.pure(())
|
||||||
|
|
||||||
|
override def addServiceLocations(locs: List[(Token[S], TokenInfo[S])]): State[X, Unit] = State.pure(())
|
||||||
|
|
||||||
|
override def addServiceLocation(token: Token[S], tokenInfo: TokenInfo[S]): State[X, Unit] = State.pure(())
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package aqua.semantics.rules.locations
|
||||||
|
|
||||||
|
import aqua.parser.lexer.Token
|
||||||
|
import aqua.semantics.lsp.{TokenInfo, TokenType}
|
||||||
|
|
||||||
|
case class LocationsState[S[_]](
|
||||||
|
nameLocations: List[(Token[S], TokenType[S])] = Nil,
|
||||||
|
typeLocations: List[(Token[S], TokenInfo[S])] = Nil,
|
||||||
|
serviceLocations: List[(Token[S], TokenInfo[S])] = Nil
|
||||||
|
) {
|
||||||
|
|
||||||
|
lazy val allLocations: List[(Token[S], TokenInfo[S])] =
|
||||||
|
nameLocations ++ typeLocations ++ serviceLocations
|
||||||
|
}
|
@ -3,6 +3,7 @@ package aqua.semantics.rules.names
|
|||||||
import aqua.parser.lexer.{Name, Token}
|
import aqua.parser.lexer.{Name, Token}
|
||||||
import aqua.semantics.lsp.{TokenArrowInfo, TokenType, TokenTypeInfo}
|
import aqua.semantics.lsp.{TokenArrowInfo, TokenType, TokenTypeInfo}
|
||||||
import aqua.semantics.Levenshtein
|
import aqua.semantics.Levenshtein
|
||||||
|
import aqua.semantics.rules.locations.LocationsAlgebra
|
||||||
import aqua.semantics.rules.{ReportError, StackInterpreter}
|
import aqua.semantics.rules.{ReportError, StackInterpreter}
|
||||||
import aqua.types.{ArrowType, StreamType, Type}
|
import aqua.types.{ArrowType, StreamType, Type}
|
||||||
import cats.data.{OptionT, State}
|
import cats.data.{OptionT, State}
|
||||||
@ -12,8 +13,11 @@ import cats.~>
|
|||||||
import monocle.Lens
|
import monocle.Lens
|
||||||
import monocle.macros.GenLens
|
import monocle.macros.GenLens
|
||||||
|
|
||||||
class NamesInterpreter[S[_], X](implicit lens: Lens[X, NamesState[S]], error: ReportError[S, X])
|
class NamesInterpreter[S[_], X](implicit
|
||||||
extends NamesAlgebra[S, State[X, *]] {
|
lens: Lens[X, NamesState[S]],
|
||||||
|
error: ReportError[S, X],
|
||||||
|
locations: LocationsAlgebra[S, State[X, *]]
|
||||||
|
) extends NamesAlgebra[S, State[X, *]] {
|
||||||
|
|
||||||
val stackInt = new StackInterpreter[S, X, NamesState[S], NamesState.Frame[S]](
|
val stackInt = new StackInterpreter[S, X, NamesState[S], NamesState.Frame[S]](
|
||||||
GenLens[NamesState[S]](_.stack)
|
GenLens[NamesState[S]](_.stack)
|
||||||
@ -49,7 +53,7 @@ class NamesInterpreter[S[_], X](implicit lens: Lens[X, NamesState[S]], error: Re
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
case Some(tokenInfo) =>
|
case Some(tokenInfo) =>
|
||||||
modify(st => st.copy(locations = st.locations :+ (name, tokenInfo)))
|
locations.addNameLocation(name, tokenInfo)
|
||||||
case _ => State.pure(())
|
case _ => State.pure(())
|
||||||
}
|
}
|
||||||
.map(_.map(_.tokenType))
|
.map(_.map(_.tokenType))
|
||||||
@ -63,12 +67,12 @@ class NamesInterpreter[S[_], X](implicit lens: Lens[X, NamesState[S]], error: Re
|
|||||||
def readArrow(name: Name[S]): SX[Option[ArrowType]] =
|
def readArrow(name: Name[S]): SX[Option[ArrowType]] =
|
||||||
readArrowHelper(name.value).flatMap {
|
readArrowHelper(name.value).flatMap {
|
||||||
case Some(g) =>
|
case Some(g) =>
|
||||||
modify(st => st.copy(locations = st.locations :+ (name, g))).map(_ => Option(g.tokenType))
|
locations.addNameLocation(name, g).map(_ => Option(g.tokenType))
|
||||||
case None =>
|
case None =>
|
||||||
// check if we have arrow in variable
|
// check if we have arrow in variable
|
||||||
readName(name.value).flatMap {
|
readName(name.value).flatMap {
|
||||||
case Some(tt@TokenTypeInfo(_, at@ArrowType(_, _))) =>
|
case Some(tt @ TokenTypeInfo(_, at @ ArrowType(_, _))) =>
|
||||||
modify(st => st.copy(locations = st.locations :+ (name, tt))).map(_ => Option(at))
|
locations.addNameLocation(name, tt).map(_ => Option(at))
|
||||||
case _ =>
|
case _ =>
|
||||||
getState.flatMap(st =>
|
getState.flatMap(st =>
|
||||||
report(
|
report(
|
||||||
|
@ -3,6 +3,7 @@ package aqua.semantics.rules.types
|
|||||||
import aqua.parser.lexer.*
|
import aqua.parser.lexer.*
|
||||||
import aqua.raw.value.{FunctorRaw, IntoCopyRaw, IntoFieldRaw, IntoIndexRaw, PropertyRaw, ValueRaw}
|
import aqua.raw.value.{FunctorRaw, IntoCopyRaw, IntoFieldRaw, IntoIndexRaw, PropertyRaw, ValueRaw}
|
||||||
import aqua.semantics.lsp.{TokenDef, TokenTypeInfo}
|
import aqua.semantics.lsp.{TokenDef, TokenTypeInfo}
|
||||||
|
import aqua.semantics.rules.locations.LocationsAlgebra
|
||||||
import aqua.semantics.rules.{ReportError, StackInterpreter}
|
import aqua.semantics.rules.{ReportError, StackInterpreter}
|
||||||
import aqua.types.{
|
import aqua.types.{
|
||||||
ArrayType,
|
ArrayType,
|
||||||
@ -30,8 +31,11 @@ import monocle.macros.GenLens
|
|||||||
|
|
||||||
import scala.collection.immutable.SortedMap
|
import scala.collection.immutable.SortedMap
|
||||||
|
|
||||||
class TypesInterpreter[S[_], X](implicit lens: Lens[X, TypesState[S]], error: ReportError[S, X])
|
class TypesInterpreter[S[_], X](implicit
|
||||||
extends TypesAlgebra[S, State[X, *]] {
|
lens: Lens[X, TypesState[S]],
|
||||||
|
error: ReportError[S, X],
|
||||||
|
locations: LocationsAlgebra[S, State[X, *]]
|
||||||
|
) extends TypesAlgebra[S, State[X, *]] {
|
||||||
|
|
||||||
val stack = new StackInterpreter[S, X, TypesState[S], TypesState.Frame[S]](
|
val stack = new StackInterpreter[S, X, TypesState[S], TypesState.Frame[S]](
|
||||||
GenLens[TypesState[S]](_.stack)
|
GenLens[TypesState[S]](_.stack)
|
||||||
@ -41,27 +45,33 @@ class TypesInterpreter[S[_], X](implicit lens: Lens[X, TypesState[S]], error: Re
|
|||||||
|
|
||||||
type ST[A] = State[X, A]
|
type ST[A] = State[X, A]
|
||||||
|
|
||||||
|
val resolver: (TypesState[S], CustomTypeToken[S]) => Option[
|
||||||
|
(Type, List[(Token[S], CustomTypeToken[S])])
|
||||||
|
] = { (state, ctt) =>
|
||||||
|
state.strict.get(ctt.value).map(t => (t, state.definitions.get(ctt.value).toList.map(ctt -> _)))
|
||||||
|
}
|
||||||
|
|
||||||
override def resolveType(token: TypeToken[S]): State[X, Option[Type]] =
|
override def resolveType(token: TypeToken[S]): State[X, Option[Type]] =
|
||||||
getState.map(_.resolveTypeToken(token)).flatMap {
|
getState.map(st => TypesStateHelper.resolveTypeToken(token, st, resolver)).flatMap {
|
||||||
case Some(t) =>
|
case Some(t) =>
|
||||||
val (tt, tokens) = t
|
val (tt, tokens) = t
|
||||||
modify(st =>
|
locations
|
||||||
st.copy(locations = st.locations ++ tokens.map { case (t, td) =>
|
.addTypeLocations(tokens.map { case (t, td) =>
|
||||||
(t, TokenDef(Some(td)))
|
(t, TokenDef(Some(td)))
|
||||||
})
|
})
|
||||||
).map(_ => Some(tt))
|
.map(_ => Some(tt))
|
||||||
case None => report(token, s"Unresolved type").as(None)
|
case None => report(token, s"Unresolved type").as(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def resolveArrowDef(arrowDef: ArrowTypeToken[S]): State[X, Option[ArrowType]] =
|
override def resolveArrowDef(arrowDef: ArrowTypeToken[S]): State[X, Option[ArrowType]] =
|
||||||
getState.map(_.resolveArrowDef(arrowDef)).flatMap {
|
getState.map(st => TypesStateHelper.resolveArrowDef(arrowDef, st, resolver)).flatMap {
|
||||||
case Valid(t) =>
|
case Valid(t) =>
|
||||||
val (tt, tokens) = t
|
val (tt, tokens) = t
|
||||||
modify(st =>
|
locations
|
||||||
st.copy(locations = st.locations ++ tokens.map { case (t, td) =>
|
.addTypeLocations(tokens.map { case (t, td) =>
|
||||||
(t, TokenDef(Some(td)))
|
(t, TokenDef(Some(td)))
|
||||||
})
|
})
|
||||||
).map(_ => Some(tt))
|
.map(_ => Some(tt))
|
||||||
case Invalid(errs) =>
|
case Invalid(errs) =>
|
||||||
errs
|
errs
|
||||||
.foldLeft[ST[Option[ArrowType]]](State.pure(None)) { case (n, (tkn, hint)) =>
|
.foldLeft[ST[Option[ArrowType]]](State.pure(None)) { case (n, (tkn, hint)) =>
|
||||||
@ -137,13 +147,12 @@ class TypesInterpreter[S[_], X](implicit lens: Lens[X, TypesState[S]], error: Re
|
|||||||
s"Field `${op.value}` not found in type `$name`, available: ${fields.toNel.toList.map(_._1).mkString(", ")}"
|
s"Field `${op.value}` not found in type `$name`, available: ${fields.toNel.toList.map(_._1).mkString(", ")}"
|
||||||
).as(None)
|
).as(None)
|
||||||
) { t =>
|
) { t =>
|
||||||
modify { st =>
|
getState.flatMap { st =>
|
||||||
st.fieldsToken.get(name + "." + op.value) match {
|
(st.fieldsToken.get(name + "." + op.value) match {
|
||||||
case Some(td) => st.copy(locations = st.locations :+ (op, td))
|
case Some(td) => locations.addTypeLocation(op, td).map(_ => st)
|
||||||
case None => st
|
case None => State.pure(st)
|
||||||
|
}).as(Some(IntoFieldRaw(op.value, t)))
|
||||||
}
|
}
|
||||||
|
|
||||||
}.as(Some(IntoFieldRaw(op.value, t)))
|
|
||||||
}
|
}
|
||||||
case t =>
|
case t =>
|
||||||
t.properties
|
t.properties
|
||||||
|
@ -39,40 +39,52 @@ case class TypesState[S[_]](
|
|||||||
strict: Map[String, Type] = Map.empty[String, Type],
|
strict: Map[String, Type] = Map.empty[String, Type],
|
||||||
definitions: Map[String, CustomTypeToken[S]] = Map.empty[String, CustomTypeToken[S]],
|
definitions: Map[String, CustomTypeToken[S]] = Map.empty[String, CustomTypeToken[S]],
|
||||||
fieldsToken: Map[String, TokenTypeInfo[S]] = Map.empty[String, TokenTypeInfo[S]],
|
fieldsToken: Map[String, TokenTypeInfo[S]] = Map.empty[String, TokenTypeInfo[S]],
|
||||||
stack: List[TypesState.Frame[S]] = Nil,
|
stack: List[TypesState.Frame[S]] = Nil
|
||||||
locations: List[(Token[S], TokenInfo[S])] = Nil
|
|
||||||
) {
|
) {
|
||||||
def isDefined(t: String): Boolean = strict.contains(t)
|
def isDefined(t: String): Boolean = strict.contains(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
object TypesStateHelper {
|
||||||
|
|
||||||
// TODO: an ugly return type, refactoring
|
// TODO: an ugly return type, refactoring
|
||||||
// Returns type and a token with its definition
|
// Returns type and a token with its definition
|
||||||
def resolveTypeToken(tt: TypeToken[S]): Option[(Type, List[(Token[S], CustomTypeToken[S])])] =
|
def resolveTypeToken[S[_]](
|
||||||
|
tt: TypeToken[S],
|
||||||
|
state: TypesState[S],
|
||||||
|
resolver: (
|
||||||
|
TypesState[S],
|
||||||
|
CustomTypeToken[S]
|
||||||
|
) => Option[(Type, List[(Token[S], CustomTypeToken[S])])]
|
||||||
|
): Option[(Type, List[(Token[S], CustomTypeToken[S])])] =
|
||||||
tt match {
|
tt match {
|
||||||
case TopBottomToken(_, isTop) =>
|
case TopBottomToken(_, isTop) =>
|
||||||
Option((if (isTop) TopType else BottomType, Nil))
|
Option((if (isTop) TopType else BottomType, Nil))
|
||||||
case ArrayTypeToken(_, dtt) =>
|
case ArrayTypeToken(_, dtt) =>
|
||||||
resolveTypeToken(dtt).collect { case (it: DataType, t) =>
|
resolveTypeToken(dtt, state, resolver).collect { case (it: DataType, t) =>
|
||||||
(ArrayType(it), t)
|
(ArrayType(it), t)
|
||||||
}
|
}
|
||||||
case StreamTypeToken(_, dtt) =>
|
case StreamTypeToken(_, dtt) =>
|
||||||
resolveTypeToken(dtt).collect { case (it: DataType, t) =>
|
resolveTypeToken(dtt, state, resolver).collect { case (it: DataType, t) =>
|
||||||
(StreamType(it), t)
|
(StreamType(it), t)
|
||||||
}
|
}
|
||||||
case OptionTypeToken(_, dtt) =>
|
case OptionTypeToken(_, dtt) =>
|
||||||
resolveTypeToken(dtt).collect { case (it: DataType, t) =>
|
resolveTypeToken(dtt, state, resolver).collect { case (it: DataType, t) =>
|
||||||
(OptionType(it), t)
|
(OptionType(it), t)
|
||||||
}
|
}
|
||||||
case ctt: CustomTypeToken[S] =>
|
case ctt: CustomTypeToken[S] =>
|
||||||
strict.get(ctt.value).map(t => (t, definitions.get(ctt.value).toList.map(ctt -> _)))
|
resolver(state, ctt)
|
||||||
|
// strict.get(ctt.value).map(t => (t, definitions.get(ctt.value).toList.map(ctt -> _)))
|
||||||
case btt: BasicTypeToken[S] => Some((btt.value, Nil))
|
case btt: BasicTypeToken[S] => Some((btt.value, Nil))
|
||||||
case ArrowTypeToken(_, args, res) =>
|
case ArrowTypeToken(_, args, res) =>
|
||||||
val strictArgs =
|
val strictArgs =
|
||||||
args.map(_._2).map(resolveTypeToken).collect { case Some((dt: DataType, t)) =>
|
args.map(_._2).map(resolveTypeToken(_, state, resolver)).collect {
|
||||||
|
case Some((dt: DataType, t)) =>
|
||||||
|
(dt, t)
|
||||||
|
}
|
||||||
|
val strictRes =
|
||||||
|
res.map(resolveTypeToken(_, state, resolver)).collect { case Some((dt: DataType, t)) =>
|
||||||
(dt, t)
|
(dt, t)
|
||||||
}
|
}
|
||||||
val strictRes = res.map(resolveTypeToken).collect { case Some((dt: DataType, t)) =>
|
|
||||||
(dt, t)
|
|
||||||
}
|
|
||||||
Option.when(strictRes.length == res.length && strictArgs.length == args.length) {
|
Option.when(strictRes.length == res.length && strictArgs.length == args.length) {
|
||||||
val (sArgs, argTokens) = strictArgs.unzip
|
val (sArgs, argTokens) = strictArgs.unzip
|
||||||
val (sRes, resTokens) = strictRes.unzip
|
val (sRes, resTokens) = strictRes.unzip
|
||||||
@ -80,18 +92,23 @@ case class TypesState[S[_]](
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def resolveArrowDef(
|
def resolveArrowDef[S[_]](
|
||||||
ad: ArrowTypeToken[S]
|
arrowTypeToken: ArrowTypeToken[S],
|
||||||
|
state: TypesState[S],
|
||||||
|
resolver: (
|
||||||
|
TypesState[S],
|
||||||
|
CustomTypeToken[S]
|
||||||
|
) => Option[(Type, List[(Token[S], CustomTypeToken[S])])]
|
||||||
): ValidatedNec[(Token[S], String), (ArrowType, List[(Token[S], CustomTypeToken[S])])] = {
|
): ValidatedNec[(Token[S], String), (ArrowType, List[(Token[S], CustomTypeToken[S])])] = {
|
||||||
val resType = ad.res.map(resolveTypeToken)
|
val resType = arrowTypeToken.res.map(resolveTypeToken(_, state, resolver))
|
||||||
|
|
||||||
NonEmptyChain
|
NonEmptyChain
|
||||||
.fromChain(Chain.fromSeq(ad.res.zip(resType).collect { case (dt, None) =>
|
.fromChain(Chain.fromSeq(arrowTypeToken.res.zip(resType).collect { case (dt, None) =>
|
||||||
dt -> "Cannot resolve the result type"
|
dt -> "Cannot resolve the result type"
|
||||||
}))
|
}))
|
||||||
.fold[ValidatedNec[(Token[S], String), (ArrowType, List[(Token[S], CustomTypeToken[S])])]] {
|
.fold[ValidatedNec[(Token[S], String), (ArrowType, List[(Token[S], CustomTypeToken[S])])]] {
|
||||||
val (errs, argTypes) = ad.args.map { (argName, tt) =>
|
val (errs, argTypes) = arrowTypeToken.args.map { (argName, tt) =>
|
||||||
resolveTypeToken(tt)
|
resolveTypeToken(tt, state, resolver)
|
||||||
.toRight(tt -> s"Type unresolved")
|
.toRight(tt -> s"Type unresolved")
|
||||||
.map(argName.map(_.value) -> _)
|
.map(argName.map(_.value) -> _)
|
||||||
}
|
}
|
||||||
@ -124,7 +141,7 @@ case class TypesState[S[_]](
|
|||||||
ProductType.maybeLabelled(labels.zip(types.map(_._1))),
|
ProductType.maybeLabelled(labels.zip(types.map(_._1))),
|
||||||
ProductType(resTypes)
|
ProductType(resTypes)
|
||||||
),
|
),
|
||||||
types.map(_._2).flatten ++ resTokens.flatten
|
types.flatMap(_._2) ++ resTokens.flatten
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)(Invalid(_))
|
)(Invalid(_))
|
||||||
|
@ -7,11 +7,12 @@ import aqua.raw.{Raw, RawContext}
|
|||||||
import aqua.semantics.expr.func.ClosureSem
|
import aqua.semantics.expr.func.ClosureSem
|
||||||
import aqua.semantics.rules.ReportError
|
import aqua.semantics.rules.ReportError
|
||||||
import aqua.semantics.rules.abilities.{AbilitiesInterpreter, AbilitiesState}
|
import aqua.semantics.rules.abilities.{AbilitiesInterpreter, AbilitiesState}
|
||||||
|
import aqua.semantics.rules.locations.DummyLocationsInterpreter
|
||||||
import aqua.semantics.rules.names.{NamesInterpreter, NamesState}
|
import aqua.semantics.rules.names.{NamesInterpreter, NamesState}
|
||||||
import aqua.semantics.rules.types.{TypesInterpreter, TypesState}
|
import aqua.semantics.rules.types.{TypesInterpreter, TypesState}
|
||||||
import aqua.types.*
|
import aqua.types.*
|
||||||
import cats.data.State
|
import cats.data.State
|
||||||
import cats.{~>, Id}
|
import cats.{Id, ~>}
|
||||||
import monocle.Lens
|
import monocle.Lens
|
||||||
import monocle.macros.GenLens
|
import monocle.macros.GenLens
|
||||||
import monocle.syntax.all.*
|
import monocle.syntax.all.*
|
||||||
@ -22,6 +23,9 @@ object Utils {
|
|||||||
(st: CompilerState[Id], token: Token[Id], hints: List[String]) =>
|
(st: CompilerState[Id], token: Token[Id], hints: List[String]) =>
|
||||||
st.focus(_.errors).modify(_.append(RulesViolated(token, hints)))
|
st.focus(_.errors).modify(_.append(RulesViolated(token, hints)))
|
||||||
|
|
||||||
|
implicit val locationsInterpreter: DummyLocationsInterpreter[Id, CompilerState[Id]] =
|
||||||
|
new DummyLocationsInterpreter[Id, CompilerState[Id]]()
|
||||||
|
|
||||||
implicit val ns: Lens[CompilerState[Id], NamesState[Id]] = GenLens[CompilerState[Id]](_.names)
|
implicit val ns: Lens[CompilerState[Id], NamesState[Id]] = GenLens[CompilerState[Id]](_.names)
|
||||||
|
|
||||||
implicit val as: Lens[CompilerState[Id], AbilitiesState[Id]] =
|
implicit val as: Lens[CompilerState[Id], AbilitiesState[Id]] =
|
||||||
|
Loading…
Reference in New Issue
Block a user