mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 22:50:18 +00:00
feat(compiler)!: Force aqua
header [LNG-308] (#1028)
* Refactor * deprecate `module`, force `aqua`, fix integration and unit tests * fix ImportFromSpec * Savepoint * Fix * Semantic error on module header * Refactor * Add begin token * Fix tests * Remove DHT examples * Use git aqua-lib * Fix headers * Fix headers * Fix headers * Fix headers * Fix headers * Fix headers * Fix headers * Fix test * Unignore tests * Update aqua-lib --------- Co-authored-by: DieMyst <dmitry.shakhtarin@fluence.ai>
This commit is contained in:
parent
34e274d45e
commit
d057a5e695
@ -19,8 +19,6 @@ import aqua.logging.{LogFormatter, LogLevels}
|
|||||||
import aqua.model.AquaContext
|
import aqua.model.AquaContext
|
||||||
import aqua.model.transform.{Transform, TransformConfig}
|
import aqua.model.transform.{Transform, TransformConfig}
|
||||||
import aqua.parser.lexer.{LiteralToken, Token}
|
import aqua.parser.lexer.{LiteralToken, Token}
|
||||||
import aqua.parser.lift.FileSpan.F
|
|
||||||
import aqua.parser.lift.{FileSpan, Span}
|
|
||||||
import aqua.parser.{ArrowReturnError, BlockIndentError, LexerError, ParserError}
|
import aqua.parser.{ArrowReturnError, BlockIndentError, LexerError, ParserError}
|
||||||
import aqua.raw.ops.Call
|
import aqua.raw.ops.Call
|
||||||
import aqua.raw.ops.CallArrowRawTag
|
import aqua.raw.ops.CallArrowRawTag
|
||||||
|
@ -16,7 +16,7 @@ import aqua.parser.expr.AbilityExpr.p
|
|||||||
import aqua.parser.lexer.{LiteralToken, Token}
|
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, LexerError, ParserError}
|
||||||
import aqua.raw.ConstantRaw
|
import aqua.raw.ConstantRaw
|
||||||
import aqua.raw.ops.Call
|
import aqua.raw.ops.Call
|
||||||
import aqua.raw.value.ValueRaw
|
import aqua.raw.value.ValueRaw
|
||||||
|
@ -2,7 +2,6 @@ package aqua.run
|
|||||||
|
|
||||||
import aqua.backend.air.FuncAirGen
|
import aqua.backend.air.FuncAirGen
|
||||||
import aqua.definitions.{FunctionDef, TypeDefinition}
|
import aqua.definitions.{FunctionDef, TypeDefinition}
|
||||||
import aqua.io.OutputPrinter
|
|
||||||
import aqua.model.transform.{Transform, TransformConfig}
|
import aqua.model.transform.{Transform, TransformConfig}
|
||||||
import aqua.model.{FuncArrow, ValueModel, VarModel}
|
import aqua.model.{FuncArrow, ValueModel, VarModel}
|
||||||
import aqua.parser.lexer.CallArrowToken
|
import aqua.parser.lexer.CallArrowToken
|
||||||
@ -10,6 +9,7 @@ import aqua.parser.lift.Span
|
|||||||
import aqua.raw.ops.{Call, CallArrowRawTag, SeqTag}
|
import aqua.raw.ops.{Call, CallArrowRawTag, SeqTag}
|
||||||
import aqua.raw.value.{LiteralRaw, ValueRaw, VarRaw}
|
import aqua.raw.value.{LiteralRaw, ValueRaw, VarRaw}
|
||||||
import aqua.types.*
|
import aqua.types.*
|
||||||
|
|
||||||
import cats.data.Validated.{invalid, invalidNec, invalidNel, validNec, validNel}
|
import cats.data.Validated.{invalid, invalidNec, invalidNel, validNec, validNel}
|
||||||
import cats.data.{NonEmptyList, Validated, ValidatedNec}
|
import cats.data.{NonEmptyList, Validated, ValidatedNec}
|
||||||
import cats.effect.kernel.Async
|
import cats.effect.kernel.Async
|
||||||
@ -18,8 +18,7 @@ import cats.syntax.flatMap.*
|
|||||||
import cats.syntax.partialOrder.*
|
import cats.syntax.partialOrder.*
|
||||||
import cats.syntax.show.*
|
import cats.syntax.show.*
|
||||||
import cats.syntax.traverse.*
|
import cats.syntax.traverse.*
|
||||||
import cats.{~>, Id}
|
import cats.{Id, ~>}
|
||||||
|
|
||||||
import scala.collection.immutable.SortedMap
|
import scala.collection.immutable.SortedMap
|
||||||
import scala.concurrent.ExecutionContext
|
import scala.concurrent.ExecutionContext
|
||||||
|
|
||||||
|
@ -6,20 +6,19 @@ import aqua.parser.head.{FilenameExpr, ImportExpr}
|
|||||||
import aqua.parser.lift.{LiftParser, Span}
|
import aqua.parser.lift.{LiftParser, Span}
|
||||||
import aqua.parser.{Ast, ParserError}
|
import aqua.parser.{Ast, ParserError}
|
||||||
|
|
||||||
import cats.data.{Chain, EitherNec, EitherT, NonEmptyChain, Validated, ValidatedNec}
|
|
||||||
import cats.parse.Parser0
|
|
||||||
import cats.syntax.either.*
|
|
||||||
import cats.syntax.applicative.*
|
|
||||||
import cats.syntax.flatMap.*
|
|
||||||
import cats.syntax.functor.*
|
|
||||||
import cats.syntax.monad.*
|
|
||||||
import cats.syntax.foldable.*
|
|
||||||
import cats.syntax.traverse.*
|
|
||||||
import cats.syntax.validated.*
|
|
||||||
import cats.data.Chain.*
|
import cats.data.Chain.*
|
||||||
import cats.data.Validated.*
|
import cats.data.Validated.*
|
||||||
|
import cats.data.{Chain, EitherNec, EitherT, NonEmptyChain, Validated, ValidatedNec}
|
||||||
|
import cats.parse.Parser0
|
||||||
|
import cats.syntax.applicative.*
|
||||||
|
import cats.syntax.either.*
|
||||||
|
import cats.syntax.flatMap.*
|
||||||
|
import cats.syntax.foldable.*
|
||||||
|
import cats.syntax.functor.*
|
||||||
|
import cats.syntax.monad.*
|
||||||
import cats.syntax.traverse.*
|
import cats.syntax.traverse.*
|
||||||
import cats.{~>, Comonad, Monad}
|
import cats.syntax.validated.*
|
||||||
|
import cats.{Comonad, Monad, ~>}
|
||||||
import scribe.Logging
|
import scribe.Logging
|
||||||
|
|
||||||
// TODO: add tests
|
// TODO: add tests
|
||||||
@ -48,9 +47,9 @@ class AquaParser[F[_]: Monad, E, I, S[_]: Comonad](
|
|||||||
|
|
||||||
// Resolve imports (not parse, just resolve) of the given file
|
// Resolve imports (not parse, just resolve) of the given file
|
||||||
private def resolveImports(id: I, ast: Body): F[ValidatedNec[Err, AquaModule[I, Err, Body]]] =
|
private def resolveImports(id: I, ast: Body): F[ValidatedNec[Err, AquaModule[I, Err, Body]]] =
|
||||||
ast.collectHead { case fe: FilenameExpr[S] =>
|
ast.head.collect { case fe: FilenameExpr[S] =>
|
||||||
fe.fileValue -> fe.token
|
fe.fileValue -> fe.token
|
||||||
}.value.traverse { case (filename, token) =>
|
}.traverse { case (filename, token) =>
|
||||||
sources
|
sources
|
||||||
.resolveImport(id, filename)
|
.resolveImport(id, filename)
|
||||||
.map(
|
.map(
|
||||||
|
@ -89,7 +89,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
|
|
||||||
val src = Map(
|
val src = Map(
|
||||||
"index.aqua" ->
|
"index.aqua" ->
|
||||||
"""module Foo declares X
|
"""aqua Foo declares X
|
||||||
|
|
|
|
||||||
|export foo, foo2 as foo_two, X
|
|export foo, foo2 as foo_two, X
|
||||||
|
|
|
|
||||||
@ -135,7 +135,11 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
it should "create right topology" in {
|
it should "create right topology" in {
|
||||||
val src = Map(
|
val src = Map(
|
||||||
"index.aqua" ->
|
"index.aqua" ->
|
||||||
"""service Op("op"):
|
"""aqua Test
|
||||||
|
|
|
||||||
|
|export exec
|
||||||
|
|
|
||||||
|
|service Op("op"):
|
||||||
| identity(s: string) -> string
|
| identity(s: string) -> string
|
||||||
|
|
|
|
||||||
|func exec(peers: []string) -> []string:
|
|func exec(peers: []string) -> []string:
|
||||||
@ -224,7 +228,11 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
it should "not generate hop back with empty response" in {
|
it should "not generate hop back with empty response" in {
|
||||||
val src = Map(
|
val src = Map(
|
||||||
"index.aqua" ->
|
"index.aqua" ->
|
||||||
"""service Op("op"):
|
"""aqua HopBackTest
|
||||||
|
|
|
||||||
|
|export exec
|
||||||
|
|
|
||||||
|
|service Op("op"):
|
||||||
| call(s: string)
|
| call(s: string)
|
||||||
|
|
|
|
||||||
|func exec(peers: []string):
|
|func exec(peers: []string):
|
||||||
@ -288,7 +296,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
|
|
||||||
val src = Map(
|
val src = Map(
|
||||||
"index.aqua" ->
|
"index.aqua" ->
|
||||||
"""module Import
|
"""aqua Import
|
||||||
|import foobar from "export2.aqua"
|
|import foobar from "export2.aqua"
|
||||||
|
|
|
|
||||||
|use foo as f from "export2.aqua" as Exp
|
|use foo as f from "export2.aqua" as Exp
|
||||||
@ -307,7 +315,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
)
|
)
|
||||||
val imports = Map(
|
val imports = Map(
|
||||||
"export2.aqua" ->
|
"export2.aqua" ->
|
||||||
"""module Export declares foobar, foo
|
"""aqua Export declares foobar, foo
|
||||||
|
|
|
|
||||||
|func bar() -> string:
|
|func bar() -> string:
|
||||||
| <- " I am MyFooBar bar"
|
| <- " I am MyFooBar bar"
|
||||||
@ -323,7 +331,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
|
|
|
|
||||||
|""".stripMargin,
|
|""".stripMargin,
|
||||||
"../gen/OneMore.aqua" ->
|
"../gen/OneMore.aqua" ->
|
||||||
"""
|
"""aqua Test declares OneMore
|
||||||
|service OneMore:
|
|service OneMore:
|
||||||
| more_call()
|
| more_call()
|
||||||
| consume(s: string)
|
| consume(s: string)
|
||||||
@ -379,7 +387,10 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
|
|
||||||
it should "optimize math inside stream join" in {
|
it should "optimize math inside stream join" in {
|
||||||
val src = Map(
|
val src = Map(
|
||||||
"main.aqua" -> """
|
"main.aqua" -> """aqua Test
|
||||||
|
|
|
||||||
|
|export main
|
||||||
|
|
|
||||||
|func main(i: i32):
|
|func main(i: i32):
|
||||||
| stream: *string
|
| stream: *string
|
||||||
| stream <<- "a"
|
| stream <<- "a"
|
||||||
@ -434,8 +445,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
|
|
||||||
it should "allow returning and passing services as abilities" in {
|
it should "allow returning and passing services as abilities" in {
|
||||||
val src = Map(
|
val src = Map(
|
||||||
"main.aqua" -> """
|
"main.aqua" -> """aqua Test
|
||||||
|aqua Test
|
|
||||||
|
|
|
|
||||||
|export test
|
|export test
|
||||||
|
|
|
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
import "@fluencelabs/aqua-dht/pubsub.aqua"
|
|
||||||
import "@fluencelabs/aqua-dht/dht.aqua"
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
|
||||||
|
|
||||||
export getNeighbours, initTopicAndSubscribe, findSubscribers
|
|
||||||
|
|
||||||
func put_value(initial_peer: string, value: string) -> string:
|
|
||||||
initTopicAndSubscribe(initial_peer, value, nil, nil)
|
|
||||||
<- "OK"
|
|
||||||
|
|
||||||
func registerKeyPutValue(node_id: string, key: string, value: string, relay_id: ?string, service_id: ?string) -> []string:
|
|
||||||
nodes <- getNeighbours(key)
|
|
||||||
for n <- nodes par:
|
|
||||||
on n:
|
|
||||||
t <- Peer.timestamp_sec()
|
|
||||||
<- nodes
|
|
@ -1,9 +1,9 @@
|
|||||||
aqua Main
|
aqua Main
|
||||||
|
|
||||||
use DECLARE_CONST, decl_bar from "imports_exports/declare.aqua" as Declare
|
|
||||||
|
|
||||||
export handleAb, SomeService, bug214, checkAbCalls, bugLNG258_1, bugLNG258_2, bugLNG258_3, multipleAbilityWithClosure, MySrv, returnSrvAsAbility
|
export handleAb, SomeService, bug214, checkAbCalls, bugLNG258_1, bugLNG258_2, bugLNG258_3, multipleAbilityWithClosure, MySrv, returnSrvAsAbility
|
||||||
|
|
||||||
|
use DECLARE_CONST, decl_bar from "imports_exports/declare.aqua" as Declare
|
||||||
|
|
||||||
service SomeService("wed"):
|
service SomeService("wed"):
|
||||||
getStr(s: string) -> string
|
getStr(s: string) -> string
|
||||||
|
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
data SomeData:
|
|
||||||
value: string
|
|
||||||
otherValue: u64
|
|
||||||
|
|
||||||
data SubData:
|
|
||||||
someStr: string
|
|
||||||
someNum: i32
|
|
||||||
|
|
||||||
data SecondData:
|
|
||||||
value: string
|
|
||||||
complex: SubData
|
|
||||||
|
|
||||||
data ThirdData:
|
|
||||||
value: string
|
|
||||||
complex: SomeData
|
|
||||||
|
|
||||||
service ComplexService("op-ha"):
|
|
||||||
call(d: SomeData, sd: SecondData) -> SubData
|
|
||||||
identity() -> SecondData
|
|
||||||
|
|
||||||
func doSmth(d: SomeData, d2: SomeData, sd: SecondData, c: SubData, SecondData -> ThirdData) -> ThirdData:
|
|
||||||
res <- ComplexService.call(d, sd)
|
|
||||||
res2 <- c(res, sd)
|
|
||||||
<- res2
|
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Assignment
|
||||||
|
|
||||||
|
export doSmth
|
||||||
|
|
||||||
data Prod:
|
data Prod:
|
||||||
value: string
|
value: string
|
||||||
|
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
|
aqua CallArrow
|
||||||
|
|
||||||
|
export passFunctionAsArg, reproArgsBug426
|
||||||
|
|
||||||
import "println.aqua"
|
import "println.aqua"
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
|
|
||||||
-- functions like `c` are called an 'arrow function' in Aqua
|
-- functions like `c` are called an 'arrow function' in Aqua
|
||||||
-- `c` passed to a function from a client, so, it could be called only on a client
|
-- `c` passed to a function from a client, so, it could be called only on a client
|
||||||
func passFunctionAsArg(node: string, str: string, c: string -> string):
|
func passFunctionAsArg(node: string, str: string, c: string -> string):
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Canon
|
||||||
|
|
||||||
|
export Ser, bugLng79
|
||||||
|
|
||||||
data Record:
|
data Record:
|
||||||
relay_id: []string
|
relay_id: []string
|
||||||
peer_id: string
|
peer_id: string
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
module Closure declares *
|
aqua Closure declares *
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
|
||||||
|
|
||||||
export LocalSrv, closureIn, closureOut, closureBig, closureOut2, lng58Bug, multipleClosuresBugLNG262, lng317Bug
|
export LocalSrv, closureIn, closureOut, closureBig, closureOut2, lng58Bug, multipleClosuresBugLNG262, lng317Bug
|
||||||
|
|
||||||
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
service MyOp("op"):
|
service MyOp("op"):
|
||||||
identity(s: string) -> string
|
identity(s: string) -> string
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Co
|
||||||
|
|
||||||
|
export CoService, coFunc
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
service CoService("coservice-id"):
|
service CoService("coservice-id"):
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua CollectionSugar
|
||||||
|
|
||||||
|
export arraySugar, streamSugar, optionSugar, GetArr, bugLNG59
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
func arraySugar(n: u32, m: u32) -> []u32, []u32:
|
func arraySugar(n: u32, m: u32) -> []u32, []u32:
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Complex
|
||||||
|
|
||||||
|
export TestS, doStuff
|
||||||
|
|
||||||
import "helloWorld.aqua"
|
import "helloWorld.aqua"
|
||||||
import "println.aqua"
|
import "println.aqua"
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Constants
|
||||||
|
|
||||||
|
export Getter, callConstant, timestampAndTtl
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
service Getter("test"):
|
service Getter("test"):
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua DataAlias
|
||||||
|
|
||||||
|
export NodeIdGetter, getAliasedData
|
||||||
|
|
||||||
-- set `PeerId` name to be a type alias for `string` type
|
-- set `PeerId` name to be a type alias for `string` type
|
||||||
alias PeerId : string
|
alias PeerId : string
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
aqua Example
|
||||||
|
|
||||||
service Peer("peer"):
|
service Peer("peer"):
|
||||||
is_connected: string -> bool
|
is_connected: string -> bool
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Fold
|
||||||
|
|
||||||
|
export iterateAndPrint, iterateAndPrintParallel, forBug499
|
||||||
|
|
||||||
import "println.aqua"
|
import "println.aqua"
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
module FoldJoin
|
aqua FoldJoin
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
|
||||||
|
|
||||||
export getTwoResults
|
export getTwoResults
|
||||||
|
|
||||||
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
service Op2("op"):
|
service Op2("op"):
|
||||||
identity(s: u64)
|
identity(s: u64)
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Func
|
||||||
|
|
||||||
|
export TestSrv, testFunc
|
||||||
|
|
||||||
service TestSrv("test-service-id"):
|
service TestSrv("test-service-id"):
|
||||||
str: -> string
|
str: -> string
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
module Funcs declares main, A, calc
|
aqua Funcs declares main, A, calc
|
||||||
|
|
||||||
export main, A, calc, calc2, ifCalc, bugLNG260
|
export main, A, calc, calc2, ifCalc, bugLNG260
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Functors
|
||||||
|
|
||||||
|
export lng119Bug
|
||||||
|
|
||||||
func lng119Bug() -> []u32:
|
func lng119Bug() -> []u32:
|
||||||
nums = [1,2,3,4,5]
|
nums = [1,2,3,4,5]
|
||||||
results: *u32
|
results: *u32
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua HelloWorld
|
||||||
|
|
||||||
|
export StringExtra, helloWorld
|
||||||
|
|
||||||
service StringExtra("service-id"):
|
service StringExtra("service-id"):
|
||||||
addNameToHello: string -> string
|
addNameToHello: string -> string
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua If
|
||||||
|
|
||||||
|
export ifElseCall, ifElseNumCall, ifCorrectXorWrap, bugLNG69
|
||||||
|
|
||||||
import "println.aqua"
|
import "println.aqua"
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
module FooBars declares decl_foo, decl_bar, SuperFoo, DECLARE_CONST, DECLARE_CONST2
|
aqua FooBars declares decl_foo, decl_bar, SuperFoo, DECLARE_CONST, DECLARE_CONST2
|
||||||
export SuperFoo
|
export SuperFoo
|
||||||
|
|
||||||
const DECLARE_CONST = "declare_const"
|
const DECLARE_CONST = "declare_const"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
module Export declares foobar, foo
|
aqua Export declares foobar, foo
|
||||||
|
|
||||||
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
-- exports3.aqua
|
-- exports3.aqua
|
||||||
module Export3 declares *
|
aqua Export3 declares *
|
||||||
|
|
||||||
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
module Exports declares some_string, MyExportSrv, EXPORT_CONST, some_random_func
|
aqua Exports declares some_string, MyExportSrv, EXPORT_CONST, some_random_func
|
||||||
|
|
||||||
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
|
aqua OneMore declares OneMore
|
||||||
|
|
||||||
service OneMore:
|
service OneMore:
|
||||||
more_call()
|
more_call()
|
@ -1,4 +1,4 @@
|
|||||||
module Import
|
aqua Import
|
||||||
import foobar from "export2.aqua"
|
import foobar from "export2.aqua"
|
||||||
|
|
||||||
use foo as f from "export2.aqua" as Exp
|
use foo as f from "export2.aqua" as Exp
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
-- imports3.aqua
|
-- imports3.aqua
|
||||||
module Import3 declares *
|
aqua Import3 declares *
|
||||||
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
export foo_wrapper
|
export foo_wrapper
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
aqua ImportsEmpty
|
||||||
|
|
||||||
import decl_foo, decl_bar from "declare.aqua"
|
import decl_foo, decl_bar from "declare.aqua"
|
||||||
use DECLARE_CONST, SuperFoo, DECLARE_CONST2 as DC2 from "declare.aqua" as Declare
|
use DECLARE_CONST, SuperFoo, DECLARE_CONST2 as DC2 from "declare.aqua" as Declare
|
||||||
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Imports
|
||||||
|
|
||||||
|
export StringService, concat_foobars
|
||||||
|
|
||||||
import decl_foo, decl_bar from "declare.aqua"
|
import decl_foo, decl_bar from "declare.aqua"
|
||||||
use DECLARE_CONST, SuperFoo, DECLARE_CONST2 as DC2 from "declare.aqua" as Declare
|
use DECLARE_CONST, SuperFoo, DECLARE_CONST2 as DC2 from "declare.aqua" as Declare
|
||||||
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
aqua SubImport declares *
|
||||||
|
|
||||||
alias SomeString : string
|
alias SomeString : string
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Join
|
||||||
|
|
||||||
|
export joinIdxLocal, joinIdxRelay, joinIdx
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
func joinIdxLocal(idx: i16, nodes: []string) -> []string:
|
func joinIdxLocal(idx: i16, nodes: []string) -> []string:
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua MultiReturn
|
||||||
|
|
||||||
|
export GetStr, GetNum, multiReturnFunc
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
service GetStr("multiret-test"):
|
service GetStr("multiret-test"):
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua NestedData
|
||||||
|
|
||||||
|
export Test, test
|
||||||
|
|
||||||
data NestedType:
|
data NestedType:
|
||||||
val: string
|
val: string
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua NestedFuncs
|
||||||
|
|
||||||
|
export OpH, d
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
service OpH("opa"):
|
service OpH("opa"):
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua On
|
||||||
|
|
||||||
|
export getPeerExternalAddresses
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
func getPeerExternalAddresses(otherNodePeerId: string) -> []string:
|
func getPeerExternalAddresses(otherNodePeerId: string) -> []string:
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua OnErrorPropagation
|
||||||
|
|
||||||
|
export Test, onPropagate, nestedOnPropagate, seqOnPropagate
|
||||||
|
|
||||||
service Test("test-service"):
|
service Test("test-service"):
|
||||||
fail(err: string)
|
fail(err: string)
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Option
|
||||||
|
|
||||||
|
export SomeS, useOptional, returnOptional, returnNone
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
service SomeS("test2"):
|
service SomeS("test2"):
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua OptionGen
|
||||||
|
|
||||||
|
export OptionString, emptyString, checkEmpty, checkNoneEmpty
|
||||||
|
|
||||||
service OptionString("opt_str"):
|
service OptionString("opt_str"):
|
||||||
checkOption(str: ?string) -> string
|
checkOption(str: ?string) -> string
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Par
|
||||||
|
|
||||||
|
export ParService, parFunc, testTimeout
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
service ParService("parservice-id"):
|
service ParService("parservice-id"):
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua ParSeq
|
||||||
|
|
||||||
|
export testParSeq
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
service NumOp("op"):
|
service NumOp("op"):
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua PassArgs
|
||||||
|
|
||||||
|
export AquaDHT, create_client_util, bugLNG60
|
||||||
|
|
||||||
import Op from "@fluencelabs/aqua-lib/builtin.aqua"
|
import Op from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
service AquaDHT("test-dht"):
|
service AquaDHT("test-dht"):
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua Println declares *
|
||||||
|
|
||||||
|
export Println, print
|
||||||
|
|
||||||
service Println("println-service-id"):
|
service Println("println-service-id"):
|
||||||
print: string -> ()
|
print: string -> ()
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua PushToStream
|
||||||
|
|
||||||
|
export OpA, get_results
|
||||||
|
|
||||||
service OpA("pop"):
|
service OpA("pop"):
|
||||||
get_str() -> string
|
get_str() -> string
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
aqua ReturnArrow
|
aqua ReturnArrow
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
|
||||||
|
|
||||||
export callReturnedArrow, callReturnedChainArrow
|
export callReturnedArrow, callReturnedChainArrow
|
||||||
|
|
||||||
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
func returnCall(arg: string) -> string -> string, string:
|
func returnCall(arg: string) -> string -> string, string:
|
||||||
str <- Op.concat_strings(arg, " literal")
|
str <- Op.concat_strings(arg, " literal")
|
||||||
closure = (s: string) -> string, string:
|
closure = (s: string) -> string, string:
|
||||||
|
@ -1,2 +1,6 @@
|
|||||||
|
aqua ReturnLiteral
|
||||||
|
|
||||||
|
export returnLiteral
|
||||||
|
|
||||||
func returnLiteral() -> string:
|
func returnLiteral() -> string:
|
||||||
<- "some literal"
|
<- "some literal"
|
@ -1,8 +1,5 @@
|
|||||||
aqua Stream
|
aqua Stream
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
|
||||||
import "println.aqua"
|
|
||||||
|
|
||||||
export Stringer
|
export Stringer
|
||||||
export checkStreams, returnStreamFromFunc
|
export checkStreams, returnStreamFromFunc
|
||||||
export stringEmpty, returnEmptyLiteral
|
export stringEmpty, returnEmptyLiteral
|
||||||
@ -10,6 +7,9 @@ export returnNilLength, stringNone
|
|||||||
export streamFunctor, streamAssignment
|
export streamFunctor, streamAssignment
|
||||||
export streamIntFunctor, streamJoin
|
export streamIntFunctor, streamJoin
|
||||||
|
|
||||||
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
import "println.aqua"
|
||||||
|
|
||||||
service Stringer("stringer-id"):
|
service Stringer("stringer-id"):
|
||||||
returnString: string -> string
|
returnString: string -> string
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
module Ret declares *
|
aqua Ret declares *
|
||||||
|
|
||||||
export someFunc
|
export someFunc
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export accumRes, bugLNG63, bugLNG63_2
|
aqua StreamCan
|
||||||
|
|
||||||
|
export accumRes, bugLNG63, bugLNG63_2, bugLNG63_3
|
||||||
|
|
||||||
func toOpt(s: string) -> ?string:
|
func toOpt(s: string) -> ?string:
|
||||||
str: *string
|
str: *string
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua StreamRestriction
|
||||||
|
|
||||||
|
export streamFold, streamRes
|
||||||
|
|
||||||
func streamFold(arr: []string) -> []string:
|
func streamFold(arr: []string) -> []string:
|
||||||
res: *string
|
res: *string
|
||||||
for n <- arr:
|
for n <- arr:
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua StreamResults
|
||||||
|
|
||||||
|
export DTGetter, use_name1, use_name2
|
||||||
|
|
||||||
data DT:
|
data DT:
|
||||||
field: string
|
field: string
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
aqua Aaa
|
aqua Aaa
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
|
||||||
|
|
||||||
export structuralTypingTest
|
export structuralTypingTest
|
||||||
|
|
||||||
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
data WideData:
|
data WideData:
|
||||||
s: string
|
s: string
|
||||||
n: u32
|
n: u32
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua SubImportUsage
|
||||||
|
|
||||||
|
export subImportUsage, ConcatSubs
|
||||||
|
|
||||||
import "imports_exports/subImport.aqua"
|
import "imports_exports/subImport.aqua"
|
||||||
|
|
||||||
service ConcatSubs("concat_subs"):
|
service ConcatSubs("concat_subs"):
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua TryCatch
|
||||||
|
|
||||||
|
export tryCatchTest
|
||||||
|
|
||||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||||
|
|
||||||
service Unexisted("unex"):
|
service Unexisted("unex"):
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
aqua TryOtherwise
|
||||||
|
|
||||||
|
export tryOtherwiseTest
|
||||||
|
|
||||||
service Unexisted("unex"):
|
service Unexisted("unex"):
|
||||||
getStr() -> string
|
getStr() -> string
|
||||||
|
|
||||||
|
6818
integration-tests/package-lock.json
generated
Normal file
6818
integration-tests/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,6 @@
|
|||||||
"prettier": {},
|
"prettier": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@fluencelabs/aqua-api": "0.13.4",
|
"@fluencelabs/aqua-api": "0.13.4",
|
||||||
"@fluencelabs/aqua-dht": "0.2.5",
|
|
||||||
"@fluencelabs/aqua-lib": "0.9.0",
|
"@fluencelabs/aqua-lib": "0.9.0",
|
||||||
"@types/jest": "29.5.2",
|
"@types/jest": "29.5.2",
|
||||||
"@types/node": "18.19.3",
|
"@types/node": "18.19.3",
|
||||||
|
@ -3,29 +3,27 @@ package aqua
|
|||||||
import aqua.files.FileModuleId
|
import aqua.files.FileModuleId
|
||||||
import aqua.parser.lift.{FileSpan, Span}
|
import aqua.parser.lift.{FileSpan, Span}
|
||||||
import aqua.parser.{Ast, Parser, ParserError}
|
import aqua.parser.{Ast, Parser, ParserError}
|
||||||
|
|
||||||
import cats.data.*
|
import cats.data.*
|
||||||
import cats.parse.LocationMap
|
import cats.parse.LocationMap
|
||||||
import cats.{~>, Comonad, Eval, Monad, Monoid, Order}
|
import cats.{Comonad, Eval, Monad, Monoid, Order, ~>}
|
||||||
|
|
||||||
object SpanParser extends scribe.Logging {
|
object SpanParser extends scribe.Logging {
|
||||||
|
|
||||||
def parser: FileModuleId => String => ValidatedNec[ParserError[FileSpan.F], Ast[FileSpan.F]] = {
|
def parser: FileModuleId => String => ValidatedNec[ParserError[FileSpan.F], Ast[FileSpan.F]] =
|
||||||
id =>
|
id =>
|
||||||
{ source =>
|
source => {
|
||||||
{
|
logger.trace(s"creating parser for $id...")
|
||||||
logger.trace(s"creating parser for $id...")
|
val nat = new (Span.S ~> FileSpan.F) {
|
||||||
val nat = new (Span.S ~> FileSpan.F) {
|
override def apply[A](span: Span.S[A]): FileSpan.F[A] = {
|
||||||
override def apply[A](span: Span.S[A]): FileSpan.F[A] = {
|
(
|
||||||
(
|
FileSpan(id.file.absolute.toString, Eval.later(LocationMap(source)), span._1),
|
||||||
FileSpan(id.file.absolute.toString, Eval.later(LocationMap(source)), span._1),
|
span._2
|
||||||
span._2
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val parser = Parser.natParser(Parser.spanParser, nat)(source)
|
|
||||||
logger.trace("parser created")
|
|
||||||
parser
|
|
||||||
}
|
}
|
||||||
|
val parser = Parser.natParser(Parser.spanParser, nat)(source)
|
||||||
|
logger.trace("parser created")
|
||||||
|
parser
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,26 +7,26 @@ import aqua.semantics.rules.locations.LocationsState
|
|||||||
import aqua.semantics.{CompilerState, RawSemantics, SemanticError, SemanticWarning, Semantics}
|
import aqua.semantics.{CompilerState, RawSemantics, SemanticError, SemanticWarning, Semantics}
|
||||||
|
|
||||||
import cats.data.Validated.{Invalid, Valid}
|
import cats.data.Validated.{Invalid, Valid}
|
||||||
|
import cats.data.{NonEmptyChain, ValidatedNec}
|
||||||
import cats.syntax.applicative.*
|
import cats.syntax.applicative.*
|
||||||
import cats.syntax.apply.*
|
import cats.syntax.apply.*
|
||||||
import cats.syntax.flatMap.*
|
|
||||||
import cats.syntax.functor.*
|
|
||||||
import cats.syntax.foldable.*
|
|
||||||
import cats.syntax.either.*
|
import cats.syntax.either.*
|
||||||
|
import cats.syntax.flatMap.*
|
||||||
|
import cats.syntax.foldable.*
|
||||||
|
import cats.syntax.functor.*
|
||||||
import cats.syntax.reducible.*
|
import cats.syntax.reducible.*
|
||||||
import cats.data.{NonEmptyChain, ValidatedNec}
|
|
||||||
import monocle.Lens
|
import monocle.Lens
|
||||||
import monocle.macros.GenLens
|
import monocle.macros.GenLens
|
||||||
|
|
||||||
class LspSemantics[S[_]] extends Semantics[S, LspContext[S]] {
|
class LspSemantics[S[_]] extends Semantics[S, LspContext[S]] {
|
||||||
|
|
||||||
private def getImportTokens(ast: Ast[S]): List[LiteralToken[S]] =
|
private def getImportTokens(ast: Ast[S]): List[LiteralToken[S]] =
|
||||||
ast.collectHead {
|
ast.head.collect {
|
||||||
case ImportExpr(fn) => fn
|
case ImportExpr(fn) => fn
|
||||||
case ImportFromExpr(_, fn) => fn
|
case ImportFromExpr(_, fn) => fn
|
||||||
case UseExpr(fn, _) => fn
|
case UseExpr(fn, _) => fn
|
||||||
case UseFromExpr(_, fn, _) => fn
|
case UseFromExpr(_, fn, _) => fn
|
||||||
}.value.toList
|
}.toList
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the AST and return the semantics result.
|
* Process the AST and return the semantics result.
|
||||||
|
@ -108,22 +108,18 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
def compile(
|
def compile(
|
||||||
src: Map[String, String],
|
src: Map[String, String],
|
||||||
imports: Map[String, String] = Map.empty
|
imports: Map[String, String] = Map.empty
|
||||||
): ValidatedNec[AquaError[String, String, S], Map[String, LspContext[S]]] = {
|
): ValidatedNec[AquaError[String, String, S], Map[String, LspContext[S]]] =
|
||||||
LSPCompiler
|
LSPCompiler
|
||||||
.compileToLsp[Id, String, String, Span.S](
|
.compileToLsp[Id, String, String, Span.S](
|
||||||
aquaSource(src, imports),
|
aquaSource(src, imports),
|
||||||
id => txt => Parser.parse(Parser.parserSchema)(txt),
|
id => txt => Parser.parse(Parser.parserSchema)(txt),
|
||||||
AquaCompilerConf(ConstantRaw.defaultConstants(None))
|
AquaCompilerConf(ConstantRaw.defaultConstants(None))
|
||||||
)
|
)
|
||||||
.leftMap { errors =>
|
|
||||||
println(errors)
|
|
||||||
errors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
it should "return right tokens" in {
|
it should "return right tokens" in {
|
||||||
val main =
|
val main =
|
||||||
"""module Import
|
"""aqua Import
|
||||||
|
|
|
||||||
|import foo, strFunc, num from "export2.aqua"
|
|import foo, strFunc, num from "export2.aqua"
|
||||||
|
|
|
|
||||||
|import "../gen/OneMore.aqua"
|
|import "../gen/OneMore.aqua"
|
||||||
@ -156,7 +152,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val firstImport =
|
val firstImport =
|
||||||
"""module Export declares strFunc, num, foo
|
"""aqua Export declares strFunc, num, foo
|
||||||
|
|
|
|
||||||
|func absb() -> string:
|
|func absb() -> string:
|
||||||
| <- "ff"
|
| <- "ff"
|
||||||
@ -173,7 +169,8 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
|
|
||||||
val secondImport =
|
val secondImport =
|
||||||
"""
|
"""aqua Export declares OneMore
|
||||||
|
|
|
||||||
|service OneMore:
|
|service OneMore:
|
||||||
| more_call()
|
| more_call()
|
||||||
| consume(s: string)
|
| consume(s: string)
|
||||||
@ -226,7 +223,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
|
|
||||||
// this is tokens from imports, if we will use `FileSpan.F` file names will be different
|
// this is tokens from imports, if we will use `FileSpan.F` file names will be different
|
||||||
// OneMore service
|
// OneMore service
|
||||||
res.checkTokenLoc(secondImport, "OneMore", 0, serviceType) shouldBe true
|
res.checkTokenLoc(secondImport, "OneMore", 1, serviceType) shouldBe true
|
||||||
res.checkTokenLoc(
|
res.checkTokenLoc(
|
||||||
secondImport,
|
secondImport,
|
||||||
"more_call",
|
"more_call",
|
||||||
@ -265,7 +262,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
ProductType(ScalarType.u32 :: Nil)
|
ProductType(ScalarType.u32 :: Nil)
|
||||||
)
|
)
|
||||||
) shouldBe true
|
) shouldBe true
|
||||||
res.checkTokenLoc(firstImport, "someVar", 2, ScalarType.u32, None, true) shouldBe true
|
res.checkTokenLoc(firstImport, "someVar", 2, ScalarType.u32, None) shouldBe true
|
||||||
|
|
||||||
// foo function
|
// foo function
|
||||||
res.checkTokenLoc(
|
res.checkTokenLoc(
|
||||||
|
@ -1,43 +1,48 @@
|
|||||||
package aqua.parser
|
package aqua.parser
|
||||||
|
|
||||||
import aqua.helpers.tree.Tree
|
import aqua.helpers.tree.Tree
|
||||||
import aqua.parser.expr.*
|
import aqua.parser.head.HeaderExpr
|
||||||
import aqua.parser.head.{HeadExpr, HeaderExpr}
|
import aqua.parser.lexer.Token
|
||||||
import aqua.parser.lift.{LiftParser, Span}
|
|
||||||
import aqua.parser.lift.LiftParser.*
|
|
||||||
|
|
||||||
import cats.data.{Chain, Validated, ValidatedNec}
|
import cats.data.Chain
|
||||||
import cats.syntax.flatMap.*
|
|
||||||
import cats.free.Cofree
|
import cats.free.Cofree
|
||||||
import cats.{Comonad, Eval}
|
import cats.syntax.flatMap.*
|
||||||
import cats.~>
|
import cats.syntax.show.*
|
||||||
import cats.Show
|
import cats.{Comonad, ~>}
|
||||||
|
import cats.{Eval, Show}
|
||||||
|
|
||||||
case class Ast[S[_]](head: Ast.Head[S], tree: Ast.Tree[S]) {
|
case class Ast[S[_]](head: Ast.Head[S], tree: Ast.Tree[S]) {
|
||||||
|
|
||||||
|
def mapK[K[_]: Comonad](nt: S ~> K): Ast[K] =
|
||||||
|
Ast(head.mapK(nt), tree.map(_.mapK(nt)))
|
||||||
|
|
||||||
def cata[T](folder: (Expr[S], Chain[T]) => Eval[T]): Eval[T] =
|
def cata[T](folder: (Expr[S], Chain[T]) => Eval[T]): Eval[T] =
|
||||||
Cofree.cata[Chain, Expr[S], T](tree)(folder)
|
Cofree.cata[Chain, Expr[S], T](tree)(folder)
|
||||||
|
|
||||||
def cataHead[T](folder: (HeaderExpr[S], Chain[T]) => Eval[T]): Eval[T] =
|
|
||||||
Cofree.cata[Chain, HeaderExpr[S], T](head)(folder)
|
|
||||||
|
|
||||||
def collectHead[T](pf: PartialFunction[HeaderExpr[S], T]): Eval[Chain[T]] =
|
|
||||||
cataHead((e, acc: Chain[Chain[T]]) =>
|
|
||||||
Eval.later {
|
|
||||||
val flatAcc = acc.flatten
|
|
||||||
if (pf.isDefinedAt(e)) flatAcc :+ pf(e) else flatAcc
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object Ast {
|
object Ast {
|
||||||
type Head[S[_]] = Cofree[Chain, HeaderExpr[S]]
|
|
||||||
|
final case class Head[S[_]](
|
||||||
|
begin: Token[S],
|
||||||
|
headers: Chain[HeaderExpr[S]]
|
||||||
|
) {
|
||||||
|
|
||||||
|
def mapK[K[_]: Comonad](nt: S ~> K): Head[K] =
|
||||||
|
copy(
|
||||||
|
begin = begin.mapK(nt),
|
||||||
|
headers = headers.map(_.mapK(nt))
|
||||||
|
)
|
||||||
|
|
||||||
|
def collect[T](pf: PartialFunction[HeaderExpr[S], T]): Chain[T] =
|
||||||
|
headers.collect(pf)
|
||||||
|
}
|
||||||
|
|
||||||
type Tree[S[_]] = Cofree[Chain, Expr[S]]
|
type Tree[S[_]] = Cofree[Chain, Expr[S]]
|
||||||
|
|
||||||
given [S[_]]: Show[Ast[S]] with {
|
given [S[_]]: Show[Ast[S]] with {
|
||||||
|
|
||||||
def show(ast: Ast[S]): String = {
|
def show(ast: Ast[S]): String = {
|
||||||
val head = Tree.show(ast.head)
|
val head = ast.head.headers.map(_.show).toList.mkString("\n")
|
||||||
val body = Tree.show(ast.tree)
|
val body = Tree.show(ast.tree)
|
||||||
|
|
||||||
s"$head\n$body"
|
s"$head\n$body"
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
package aqua.parser
|
package aqua.parser
|
||||||
|
|
||||||
import aqua.parser.expr.RootExpr
|
import aqua.parser.expr.RootExpr
|
||||||
import aqua.parser.head.HeadExpr
|
import aqua.parser.head.Header
|
||||||
import aqua.parser.lift.LiftParser.LiftErrorOps
|
import aqua.parser.lift.LiftParser.LiftErrorOps
|
||||||
import aqua.parser.lift.Span.S
|
import aqua.parser.lift.Span.S
|
||||||
import aqua.parser.lift.{LiftParser, Span}
|
import aqua.parser.lift.{LiftParser, Span}
|
||||||
|
|
||||||
import cats.data.{Validated, ValidatedNec}
|
import cats.data.{Validated, ValidatedNec}
|
||||||
|
import cats.free.Cofree
|
||||||
import cats.parse.{Parser as P, Parser0 as P0}
|
import cats.parse.{Parser as P, Parser0 as P0}
|
||||||
|
import cats.syntax.validated.*
|
||||||
import cats.{Comonad, ~>}
|
import cats.{Comonad, ~>}
|
||||||
|
|
||||||
object Parser extends scribe.Logging {
|
object Parser extends scribe.Logging {
|
||||||
@ -15,7 +17,7 @@ object Parser extends scribe.Logging {
|
|||||||
|
|
||||||
def parserSchema: P0[ValidatedNec[ParserError[Span.S], Ast[Span.S]]] = {
|
def parserSchema: P0[ValidatedNec[ParserError[Span.S], Ast[Span.S]]] = {
|
||||||
logger.trace("creating schema...")
|
logger.trace("creating schema...")
|
||||||
val parser = (HeadExpr.ast ~ RootExpr.ast0).map { case (head, bodyMaybe) =>
|
val parser = (Header.p ~ RootExpr.ast0).map { case (head, bodyMaybe) =>
|
||||||
bodyMaybe.map(Ast(head, _))
|
bodyMaybe.map(Ast(head, _))
|
||||||
}
|
}
|
||||||
logger.trace("schema created")
|
logger.trace("schema created")
|
||||||
@ -24,19 +26,15 @@ object Parser extends scribe.Logging {
|
|||||||
|
|
||||||
def parse[S[_]: LiftParser: Comonad](
|
def parse[S[_]: LiftParser: Comonad](
|
||||||
p: P0[ValidatedNec[ParserError[S], Ast[S]]]
|
p: P0[ValidatedNec[ParserError[S], Ast[S]]]
|
||||||
)(source: String): ValidatedNec[ParserError[S], Ast[S]] = {
|
)(source: String): ValidatedNec[ParserError[S], Ast[S]] =
|
||||||
p.parseAll(source) match {
|
p.parseAll(source).left.map(e => LexerError(e.wrapErr).invalidNec).merge
|
||||||
case Right(value) => value
|
|
||||||
case Left(e) => Validated.invalidNec(LexerError(e.wrapErr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def natParser[S[_]: LiftParser: Comonad, K[_]: Comonad](
|
def natParser[S[_]: LiftParser: Comonad, K[_]: Comonad](
|
||||||
p: P0[ValidatedNec[ParserError[S], Ast[S]]],
|
p: P0[ValidatedNec[ParserError[S], Ast[S]]],
|
||||||
nat: S ~> K
|
nat: S ~> K
|
||||||
)(source: String): ValidatedNec[ParserError[K], Ast[K]] =
|
)(source: String): ValidatedNec[ParserError[K], Ast[K]] =
|
||||||
parse[S](p)(source).bimap(
|
parse(p)(source).bimap(
|
||||||
e => e.map(_.mapK(nat)),
|
e => e.map(_.mapK(nat)),
|
||||||
ast => Ast[K](ast.head.map(_.mapK(nat)), ast.tree.map(_.mapK(nat)))
|
ast => ast.mapK(nat)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,14 @@ package aqua.parser.expr
|
|||||||
import aqua.parser.Ast.Tree
|
import aqua.parser.Ast.Tree
|
||||||
import aqua.parser.lexer.Token
|
import aqua.parser.lexer.Token
|
||||||
import aqua.parser.lexer.Token.*
|
import aqua.parser.lexer.Token.*
|
||||||
import aqua.parser.lift.{LiftParser, Span}
|
|
||||||
import aqua.parser.lift.LiftParser.*
|
import aqua.parser.lift.LiftParser.*
|
||||||
|
import aqua.parser.lift.{LiftParser, Span}
|
||||||
import aqua.parser.{Expr, ParserError}
|
import aqua.parser.{Expr, ParserError}
|
||||||
|
|
||||||
import cats.data.{Chain, NonEmptyChain, NonEmptyList, Validated, ValidatedNec}
|
import cats.data.{Chain, NonEmptyChain, NonEmptyList, Validated, ValidatedNec}
|
||||||
import cats.free.Cofree
|
import cats.free.Cofree
|
||||||
import cats.parse.{Parser0 as P0, Parser as P}
|
import cats.parse.{Parser as P, Parser0 as P0}
|
||||||
|
import cats.syntax.option.*
|
||||||
import cats.{Comonad, Eval}
|
import cats.{Comonad, Eval}
|
||||||
import cats.~>
|
import cats.~>
|
||||||
|
|
||||||
@ -24,7 +26,9 @@ object RootExpr extends Expr.Companion {
|
|||||||
def validChildren: List[Expr.Lexem] =
|
def validChildren: List[Expr.Lexem] =
|
||||||
ServiceExpr :: AliasExpr :: DataStructExpr :: AbilityExpr :: ConstantExpr :: FuncExpr :: Nil
|
ServiceExpr :: AliasExpr :: DataStructExpr :: AbilityExpr :: ConstantExpr :: FuncExpr :: Nil
|
||||||
|
|
||||||
private def gatherResults[F[_]: LiftParser: Comonad](results: NonEmptyList[ValidatedNec[ParserError[F], Tree[F]]]): (Chain[ParserError[F]], Chain[Tree[F]]) = {
|
private def gatherResults[F[_]: LiftParser: Comonad](
|
||||||
|
results: NonEmptyList[ValidatedNec[ParserError[F], Tree[F]]]
|
||||||
|
): (Chain[ParserError[F]], Chain[Tree[F]]) = {
|
||||||
results.foldLeft[(Chain[ParserError[F]], Chain[Tree[F]])](Chain.empty -> Chain.empty) {
|
results.foldLeft[(Chain[ParserError[F]], Chain[Tree[F]])](Chain.empty -> Chain.empty) {
|
||||||
case ((errs, trees), Validated.Valid(tree)) => (errs, trees :+ tree)
|
case ((errs, trees), Validated.Valid(tree)) => (errs, trees :+ tree)
|
||||||
case ((errs, trees), Validated.Invalid(err)) => (errs ++ err.toChain, trees)
|
case ((errs, trees), Validated.Invalid(err)) => (errs ++ err.toChain, trees)
|
||||||
@ -54,12 +58,11 @@ object RootExpr extends Expr.Companion {
|
|||||||
empty.backtrack | ast
|
empty.backtrack | ast
|
||||||
|
|
||||||
override val ast: P[ValidatedNec[ParserError[Span.S], Tree[Span.S]]] =
|
override val ast: P[ValidatedNec[ParserError[Span.S], Tree[Span.S]]] =
|
||||||
parserSchema
|
parserSchema.map { case (point, (errs, trees)) =>
|
||||||
.map { case (point, (errs, trees)) =>
|
|
||||||
NonEmptyChain
|
NonEmptyChain
|
||||||
.fromChain(errs)
|
.fromChain(errs)
|
||||||
.fold[ValidatedNec[ParserError[Span.S], Tree[Span.S]]](
|
.toInvalid(
|
||||||
Validated.validNec(Cofree(RootExpr[Span.S](point), Eval.now(trees)))
|
Cofree(RootExpr(point), Eval.now(trees))
|
||||||
)(Validated.invalid)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,14 @@ package aqua.parser.head
|
|||||||
import aqua.parser.lexer.Token.*
|
import aqua.parser.lexer.Token.*
|
||||||
import aqua.parser.lexer.{LiteralToken, Token, ValueToken}
|
import aqua.parser.lexer.{LiteralToken, Token, ValueToken}
|
||||||
import aqua.parser.lift.LiftParser
|
import aqua.parser.lift.LiftParser
|
||||||
|
import aqua.parser.lift.Span
|
||||||
|
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||||
|
|
||||||
import cats.Comonad
|
import cats.Comonad
|
||||||
import cats.data.NonEmptyList
|
import cats.data.NonEmptyList
|
||||||
import cats.parse.Parser
|
import cats.parse.Parser
|
||||||
import cats.syntax.either.*
|
import cats.syntax.either.*
|
||||||
import cats.~>
|
import cats.~>
|
||||||
import aqua.parser.lift.Span
|
|
||||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
|
||||||
|
|
||||||
case class ExportExpr[F[_]](pubs: NonEmptyList[FromExpr.NameOrAbAs[F]]) extends HeaderExpr[F] {
|
case class ExportExpr[F[_]](pubs: NonEmptyList[FromExpr.NameOrAbAs[F]]) extends HeaderExpr[F] {
|
||||||
|
|
||||||
@ -20,7 +21,7 @@ case class ExportExpr[F[_]](pubs: NonEmptyList[FromExpr.NameOrAbAs[F]]) extends
|
|||||||
copy(FromExpr.mapK(pubs)(fk))
|
copy(FromExpr.mapK(pubs)(fk))
|
||||||
}
|
}
|
||||||
|
|
||||||
object ExportExpr extends HeaderExpr.Leaf {
|
object ExportExpr extends HeaderExpr.Companion {
|
||||||
|
|
||||||
override val p: Parser[ExportExpr[Span.S]] =
|
override val p: Parser[ExportExpr[Span.S]] =
|
||||||
(`_export` *> ` `) *> comma(FromExpr.nameOrAbAs).map(ExportExpr(_))
|
(`_export` *> ` `) *> comma(FromExpr.nameOrAbAs).map(ExportExpr(_))
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
package aqua.parser.head
|
|
||||||
|
|
||||||
import aqua.parser.Ast
|
|
||||||
import aqua.parser.lexer.Token.` \n+`
|
|
||||||
import aqua.parser.lift.LiftParser
|
|
||||||
import aqua.parser.lift.LiftParser.*
|
|
||||||
import cats.{Comonad, Eval}
|
|
||||||
import cats.data.Chain
|
|
||||||
import cats.free.Cofree
|
|
||||||
import cats.parse.{Parser => P, Parser0 => P0}
|
|
||||||
import aqua.parser.lexer.Token
|
|
||||||
import cats.~>
|
|
||||||
import aqua.parser.lift.Span
|
|
||||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
|
||||||
|
|
||||||
case class HeadExpr[S[_]](token: Token[S]) extends HeaderExpr[S] {
|
|
||||||
|
|
||||||
def mapK[K[_]: Comonad](fk: S ~> K): HeadExpr[K] =
|
|
||||||
copy(token.mapK(fk))
|
|
||||||
}
|
|
||||||
|
|
||||||
object HeadExpr {
|
|
||||||
|
|
||||||
def headExprs: List[HeaderExpr.Companion] =
|
|
||||||
UseFromExpr :: UseExpr :: ImportFromExpr :: ImportExpr :: ExportExpr :: Nil
|
|
||||||
|
|
||||||
val ast: P0[Ast.Head[Span.S]] =
|
|
||||||
(P.unit.lift0.map(Token.lift) ~ ((ModuleExpr.p <* ` \n+`).? ~
|
|
||||||
P.repSep0(P.oneOf(headExprs.map(_.ast.backtrack)), ` \n+`).map(Chain.fromSeq))
|
|
||||||
.surroundedBy(` \n+`.?)
|
|
||||||
.?).map {
|
|
||||||
case (p, Some((maybeMod, exprs))) =>
|
|
||||||
Cofree(
|
|
||||||
maybeMod.getOrElse(HeadExpr[Span.S](p)),
|
|
||||||
Eval.now(exprs)
|
|
||||||
)
|
|
||||||
case (p, None) => Cofree(HeadExpr[Span.S](p), Eval.now(Chain.nil))
|
|
||||||
}
|
|
||||||
}
|
|
31
parser/src/main/scala/aqua/parser/head/Header.scala
Normal file
31
parser/src/main/scala/aqua/parser/head/Header.scala
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package aqua.parser.head
|
||||||
|
|
||||||
|
import aqua.parser.Ast
|
||||||
|
import aqua.parser.lexer.Token
|
||||||
|
import aqua.parser.lexer.Token.` \n+`
|
||||||
|
import aqua.parser.lift.LiftParser
|
||||||
|
import aqua.parser.lift.LiftParser.*
|
||||||
|
import aqua.parser.lift.Span
|
||||||
|
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||||
|
|
||||||
|
import cats.data.Chain
|
||||||
|
import cats.free.Cofree
|
||||||
|
import cats.parse.{Parser => P, Parser0 => P0}
|
||||||
|
import cats.{Comonad, Eval}
|
||||||
|
import cats.~>
|
||||||
|
|
||||||
|
object Header {
|
||||||
|
|
||||||
|
def headExprs: List[HeaderExpr.Companion] =
|
||||||
|
ModuleExpr :: UseFromExpr :: UseExpr :: ImportFromExpr :: ImportExpr :: ExportExpr :: Nil
|
||||||
|
|
||||||
|
val p: P0[Ast.Head[Span.S]] = (
|
||||||
|
P.unit.lift0 ~
|
||||||
|
P.repSep0(
|
||||||
|
P.oneOf(headExprs.map(_.p.backtrack)),
|
||||||
|
` \n+`
|
||||||
|
).surroundedBy(` \n+`.?)
|
||||||
|
).map { case (point, headers) =>
|
||||||
|
Ast.Head(Token.lift(point), Chain.fromSeq(headers))
|
||||||
|
}
|
||||||
|
}
|
@ -6,11 +6,11 @@ import aqua.parser.lift.LiftParser
|
|||||||
import aqua.parser.lift.Span
|
import aqua.parser.lift.Span
|
||||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||||
|
|
||||||
import cats.{Comonad, Eval}
|
import cats.Show
|
||||||
import cats.data.Chain
|
import cats.data.Chain
|
||||||
import cats.free.Cofree
|
import cats.free.Cofree
|
||||||
import cats.Show
|
|
||||||
import cats.parse.Parser as P
|
import cats.parse.Parser as P
|
||||||
|
import cats.{Comonad, Eval}
|
||||||
import cats.~>
|
import cats.~>
|
||||||
|
|
||||||
trait HeaderExpr[S[_]] {
|
trait HeaderExpr[S[_]] {
|
||||||
@ -23,14 +23,6 @@ object HeaderExpr {
|
|||||||
|
|
||||||
trait Companion {
|
trait Companion {
|
||||||
def p: P[HeaderExpr[Span.S]]
|
def p: P[HeaderExpr[Span.S]]
|
||||||
|
|
||||||
def ast: P[Ast.Head[Span.S]]
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Leaf extends Companion {
|
|
||||||
|
|
||||||
override def ast: P[Ast.Head[Span.S]] =
|
|
||||||
p.map(Cofree[Chain, HeaderExpr[Span.S]](_, Eval.now(Chain.empty)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
given [S[_]]: Show[HeaderExpr[S]] with {
|
given [S[_]]: Show[HeaderExpr[S]] with {
|
||||||
|
@ -3,11 +3,12 @@ package aqua.parser.head
|
|||||||
import aqua.parser.lexer.Token._
|
import aqua.parser.lexer.Token._
|
||||||
import aqua.parser.lexer.{LiteralToken, ValueToken}
|
import aqua.parser.lexer.{LiteralToken, ValueToken}
|
||||||
import aqua.parser.lift.LiftParser
|
import aqua.parser.lift.LiftParser
|
||||||
|
import aqua.parser.lift.Span
|
||||||
|
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||||
|
|
||||||
import cats.Comonad
|
import cats.Comonad
|
||||||
import cats.parse.Parser
|
import cats.parse.Parser
|
||||||
import cats.~>
|
import cats.~>
|
||||||
import aqua.parser.lift.Span
|
|
||||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
|
||||||
|
|
||||||
case class ImportExpr[F[_]](filename: LiteralToken[F]) extends FilenameExpr[F] {
|
case class ImportExpr[F[_]](filename: LiteralToken[F]) extends FilenameExpr[F] {
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ case class ImportExpr[F[_]](filename: LiteralToken[F]) extends FilenameExpr[F] {
|
|||||||
override def toString: String = s"import ${filename.value}"
|
override def toString: String = s"import ${filename.value}"
|
||||||
}
|
}
|
||||||
|
|
||||||
object ImportExpr extends HeaderExpr.Leaf {
|
object ImportExpr extends HeaderExpr.Companion {
|
||||||
|
|
||||||
override val p: Parser[HeaderExpr[Span.S]] =
|
override val p: Parser[HeaderExpr[Span.S]] =
|
||||||
`import` *> ` ` *> ValueToken.string.map(ImportExpr(_))
|
`import` *> ` ` *> ValueToken.string.map(ImportExpr(_))
|
||||||
|
@ -3,12 +3,13 @@ package aqua.parser.head
|
|||||||
import aqua.parser.lexer.Token.*
|
import aqua.parser.lexer.Token.*
|
||||||
import aqua.parser.lexer.{LiteralToken, ValueToken}
|
import aqua.parser.lexer.{LiteralToken, ValueToken}
|
||||||
import aqua.parser.lift.LiftParser
|
import aqua.parser.lift.LiftParser
|
||||||
|
import aqua.parser.lift.Span
|
||||||
|
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||||
|
|
||||||
import cats.Comonad
|
import cats.Comonad
|
||||||
import cats.data.NonEmptyList
|
import cats.data.NonEmptyList
|
||||||
import cats.parse.Parser
|
import cats.parse.Parser
|
||||||
import cats.~>
|
import cats.~>
|
||||||
import aqua.parser.lift.Span
|
|
||||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
|
||||||
|
|
||||||
case class ImportFromExpr[F[_]](
|
case class ImportFromExpr[F[_]](
|
||||||
imports: NonEmptyList[FromExpr.NameOrAbAs[F]],
|
imports: NonEmptyList[FromExpr.NameOrAbAs[F]],
|
||||||
@ -21,7 +22,7 @@ case class ImportFromExpr[F[_]](
|
|||||||
override def toString: String = s"import ${FromExpr.show(imports)} from ${filename.value}"
|
override def toString: String = s"import ${FromExpr.show(imports)} from ${filename.value}"
|
||||||
}
|
}
|
||||||
|
|
||||||
object ImportFromExpr extends HeaderExpr.Leaf {
|
object ImportFromExpr extends HeaderExpr.Companion {
|
||||||
|
|
||||||
override val p: Parser[HeaderExpr[Span.S]] =
|
override val p: Parser[HeaderExpr[Span.S]] =
|
||||||
(`import` *> FromExpr.importFrom.surroundedBy(` `) ~ ValueToken.string).map {
|
(`import` *> FromExpr.importFrom.surroundedBy(` `) ~ ValueToken.string).map {
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
package aqua.parser.head
|
package aqua.parser.head
|
||||||
|
|
||||||
import aqua.parser.lexer.Token.*
|
|
||||||
import aqua.parser.lexer.Token
|
import aqua.parser.lexer.Token
|
||||||
|
import aqua.parser.lexer.Token.*
|
||||||
import aqua.parser.lexer.{Ability, LiteralToken, Name, ValueToken}
|
import aqua.parser.lexer.{Ability, LiteralToken, Name, ValueToken}
|
||||||
import aqua.parser.lift.LiftParser
|
import aqua.parser.lift.LiftParser
|
||||||
import aqua.parser.lift.LiftParser.*
|
import aqua.parser.lift.LiftParser.*
|
||||||
import cats.Comonad
|
|
||||||
import cats.parse.Parser
|
|
||||||
import cats.~>
|
|
||||||
import aqua.parser.lift.Span
|
import aqua.parser.lift.Span
|
||||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||||
|
|
||||||
|
import cats.Comonad
|
||||||
|
import cats.parse.Parser
|
||||||
|
import cats.syntax.comonad.*
|
||||||
|
import cats.syntax.functor.*
|
||||||
|
import cats.~>
|
||||||
|
|
||||||
case class ModuleExpr[F[_]](
|
case class ModuleExpr[F[_]](
|
||||||
|
word: ModuleExpr.Word[F],
|
||||||
name: Ability[F],
|
name: Ability[F],
|
||||||
declareAll: Option[Token[F]],
|
declareAll: Option[Token[F]],
|
||||||
declareNames: List[Name[F]],
|
declareNames: List[Name[F]],
|
||||||
@ -21,40 +25,75 @@ case class ModuleExpr[F[_]](
|
|||||||
|
|
||||||
override def mapK[K[_]: Comonad](fk: F ~> K): ModuleExpr[K] =
|
override def mapK[K[_]: Comonad](fk: F ~> K): ModuleExpr[K] =
|
||||||
copy(
|
copy(
|
||||||
name.mapK(fk),
|
word = word.mapK(fk),
|
||||||
declareAll.map(_.mapK(fk)),
|
name = name.mapK(fk),
|
||||||
declareNames.map(_.mapK(fk)),
|
declareAll = declareAll.map(_.mapK(fk)),
|
||||||
declareCustom.map(_.mapK(fk))
|
declareNames = declareNames.map(_.mapK(fk)),
|
||||||
|
declareCustom = declareCustom.map(_.mapK(fk))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
object ModuleExpr extends HeaderExpr.Leaf {
|
object ModuleExpr extends HeaderExpr.Companion {
|
||||||
|
|
||||||
|
final case class Word[F[_]: Comonad](
|
||||||
|
token: F[Word.Kind]
|
||||||
|
) extends Token[F] {
|
||||||
|
override def mapK[K[_]: Comonad](fk: F ~> K): Word[K] = copy(fk(token))
|
||||||
|
|
||||||
|
override def as[T](v: T): F[T] = token.as(v)
|
||||||
|
|
||||||
|
def value: Word.Kind = token.extract
|
||||||
|
}
|
||||||
|
|
||||||
|
object Word {
|
||||||
|
|
||||||
|
enum Kind {
|
||||||
|
case Module, Aqua
|
||||||
|
|
||||||
|
def fold[A](
|
||||||
|
module: => A,
|
||||||
|
aqua: => A
|
||||||
|
): A = this match {
|
||||||
|
case Kind.Module => module
|
||||||
|
case Kind.Aqua => aqua
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type NameOrAb[F[_]] = Either[Name[F], Ability[F]]
|
type NameOrAb[F[_]] = Either[Name[F], Ability[F]]
|
||||||
|
|
||||||
val nameOrAb: Parser[NameOrAb[Span.S]] =
|
private val nameOrAb: Parser[NameOrAb[Span.S]] =
|
||||||
Name.p.map(Left(_)) | Ability.ab.map(Right(_))
|
Name.p.map(Left(_)) | Ability.ab.map(Right(_))
|
||||||
|
|
||||||
val nameOrAbList: Parser[List[NameOrAb[Span.S]]] =
|
private val nameOrAbList: Parser[List[NameOrAb[Span.S]]] =
|
||||||
comma[NameOrAb[Span.S]](nameOrAb).map(_.toList)
|
comma[NameOrAb[Span.S]](nameOrAb).map(_.toList)
|
||||||
|
|
||||||
val nameOrAbListOrAll: Parser[Either[List[NameOrAb[Span.S]], Token[Span.S]]] =
|
private val nameOrAbListOrAll: Parser[Either[List[NameOrAb[Span.S]], Token[Span.S]]] =
|
||||||
nameOrAbList.map(Left(_)) | `star`.lift.map(Token.lift(_)).map(Right(_))
|
nameOrAbList.map(Left(_)) | `star`.lift.map(Token.lift(_)).map(Right(_))
|
||||||
|
|
||||||
|
private val moduleWord: Parser[Word[Span.S]] =
|
||||||
|
(`module`.as(Word.Kind.Module).lift.backtrack |
|
||||||
|
`aqua-word`.as(Word.Kind.Aqua).lift).map(Word(_))
|
||||||
|
|
||||||
override val p: Parser[ModuleExpr[Span.S]] =
|
override val p: Parser[ModuleExpr[Span.S]] =
|
||||||
((`module` | `aqua-word`) *> ` ` *> Ability.dotted ~
|
(
|
||||||
(` declares ` *> nameOrAbListOrAll).?).map {
|
(` *`.with1 *> moduleWord) ~
|
||||||
case (name, None) =>
|
(` ` *> Ability.dotted) ~
|
||||||
ModuleExpr(name, None, Nil, Nil)
|
(` declares ` *> nameOrAbListOrAll).?
|
||||||
case (name, Some(Left(exportMembers))) =>
|
).map {
|
||||||
|
case ((word, name), None) =>
|
||||||
|
ModuleExpr(word, name, None, Nil, Nil)
|
||||||
|
case ((word, name), Some(Left(exportMembers))) =>
|
||||||
ModuleExpr(
|
ModuleExpr(
|
||||||
|
word,
|
||||||
name,
|
name,
|
||||||
None,
|
None,
|
||||||
exportMembers.collect { case Left(x) => x },
|
exportMembers.collect { case Left(x) => x },
|
||||||
exportMembers.collect { case Right(x) => x }
|
exportMembers.collect { case Right(x) => x }
|
||||||
)
|
)
|
||||||
case (name, Some(Right(point))) =>
|
case ((word, name), Some(Right(point))) =>
|
||||||
ModuleExpr(
|
ModuleExpr(
|
||||||
|
word,
|
||||||
name,
|
name,
|
||||||
Some(point),
|
Some(point),
|
||||||
Nil,
|
Nil,
|
||||||
|
@ -3,11 +3,12 @@ package aqua.parser.head
|
|||||||
import aqua.parser.lexer.Token.*
|
import aqua.parser.lexer.Token.*
|
||||||
import aqua.parser.lexer.{Ability, LiteralToken, ValueToken}
|
import aqua.parser.lexer.{Ability, LiteralToken, ValueToken}
|
||||||
import aqua.parser.lift.LiftParser
|
import aqua.parser.lift.LiftParser
|
||||||
|
import aqua.parser.lift.Span
|
||||||
|
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||||
|
|
||||||
import cats.Comonad
|
import cats.Comonad
|
||||||
import cats.parse.Parser
|
import cats.parse.Parser
|
||||||
import cats.~>
|
import cats.~>
|
||||||
import aqua.parser.lift.Span
|
|
||||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
|
||||||
|
|
||||||
case class UseExpr[F[_]](
|
case class UseExpr[F[_]](
|
||||||
filename: LiteralToken[F],
|
filename: LiteralToken[F],
|
||||||
@ -21,7 +22,7 @@ case class UseExpr[F[_]](
|
|||||||
s"use ${filename.value}${asModule.map(_.value).fold("")(" as " + _)}"
|
s"use ${filename.value}${asModule.map(_.value).fold("")(" as " + _)}"
|
||||||
}
|
}
|
||||||
|
|
||||||
object UseExpr extends HeaderExpr.Leaf {
|
object UseExpr extends HeaderExpr.Companion {
|
||||||
|
|
||||||
override val p: Parser[HeaderExpr[Span.S]] =
|
override val p: Parser[HeaderExpr[Span.S]] =
|
||||||
(`use` *> ` ` *> ValueToken.string ~ (` as ` *> Ability.ab).?).map {
|
(`use` *> ` ` *> ValueToken.string ~ (` as ` *> Ability.ab).?).map {
|
||||||
|
@ -3,12 +3,13 @@ package aqua.parser.head
|
|||||||
import aqua.parser.lexer.Token.*
|
import aqua.parser.lexer.Token.*
|
||||||
import aqua.parser.lexer.{Ability, LiteralToken, Name, ValueToken}
|
import aqua.parser.lexer.{Ability, LiteralToken, Name, ValueToken}
|
||||||
import aqua.parser.lift.LiftParser
|
import aqua.parser.lift.LiftParser
|
||||||
|
import aqua.parser.lift.Span
|
||||||
|
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||||
|
|
||||||
import cats.Comonad
|
import cats.Comonad
|
||||||
import cats.data.NonEmptyList
|
import cats.data.NonEmptyList
|
||||||
import cats.parse.Parser
|
import cats.parse.Parser
|
||||||
import cats.~>
|
import cats.~>
|
||||||
import aqua.parser.lift.Span
|
|
||||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
|
||||||
|
|
||||||
case class UseFromExpr[F[_]](
|
case class UseFromExpr[F[_]](
|
||||||
imports: NonEmptyList[FromExpr.NameOrAbAs[F]],
|
imports: NonEmptyList[FromExpr.NameOrAbAs[F]],
|
||||||
@ -23,7 +24,7 @@ case class UseFromExpr[F[_]](
|
|||||||
s"use ${FromExpr.show(imports)} from ${filename.value} as ${asModule.value}"
|
s"use ${FromExpr.show(imports)} from ${filename.value} as ${asModule.value}"
|
||||||
}
|
}
|
||||||
|
|
||||||
object UseFromExpr extends HeaderExpr.Leaf {
|
object UseFromExpr extends HeaderExpr.Companion {
|
||||||
|
|
||||||
override val p: Parser[UseFromExpr[Span.S]] =
|
override val p: Parser[UseFromExpr[Span.S]] =
|
||||||
(`use` *> FromExpr.importFrom.surroundedBy(
|
(`use` *> FromExpr.importFrom.surroundedBy(
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package aqua.parser.lexer
|
package aqua.parser.lexer
|
||||||
|
|
||||||
import aqua.parser.Expr
|
import aqua.parser.Expr
|
||||||
import aqua.parser.head.FilenameExpr
|
|
||||||
import aqua.parser.lexer.NamedArg.namedArgs
|
import aqua.parser.lexer.NamedArg.namedArgs
|
||||||
import aqua.parser.lexer.Token.*
|
import aqua.parser.lexer.Token.*
|
||||||
import aqua.parser.lift.LiftParser
|
import aqua.parser.lift.LiftParser
|
||||||
|
@ -2,7 +2,6 @@ package aqua.parser.lift
|
|||||||
|
|
||||||
import cats.parse.{LocationMap, Parser => P, Parser0}
|
import cats.parse.{LocationMap, Parser => P, Parser0}
|
||||||
import cats.{Comonad, Eval}
|
import cats.{Comonad, Eval}
|
||||||
|
|
||||||
import scala.language.implicitConversions
|
import scala.language.implicitConversions
|
||||||
|
|
||||||
// TODO: rewrite FileSpan and Span under one trait
|
// TODO: rewrite FileSpan and Span under one trait
|
||||||
@ -56,29 +55,4 @@ object FileSpan {
|
|||||||
override def map[A, B](fa: F[A])(f: A ⇒ B): F[B] = fa.copy(_2 = f(fa._2))
|
override def map[A, B](fa: F[A])(f: A ⇒ B): F[B] = fa.copy(_2 = f(fa._2))
|
||||||
}
|
}
|
||||||
|
|
||||||
def fileSpanLiftParser(name: String, source: String): LiftParser[F] = new LiftParser[F] {
|
|
||||||
|
|
||||||
private val memoizedLocationMap = Eval.later(LocationMap(source)).memoize
|
|
||||||
|
|
||||||
override def lift[T](p: P[T]): P[F[T]] = {
|
|
||||||
implicitly[LiftParser[Span.S]].lift(p).map { case (span, value) =>
|
|
||||||
(FileSpan(name, memoizedLocationMap, span), value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def lift0[T](p0: Parser0[T]): Parser0[(FileSpan, T)] = {
|
|
||||||
implicitly[LiftParser[Span.S]].lift0(p0).map { case (span, value) =>
|
|
||||||
(FileSpan(name, memoizedLocationMap, span), value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def wrapErr(e: P.Error): (FileSpan, P.Error) = (
|
|
||||||
FileSpan(
|
|
||||||
name,
|
|
||||||
memoizedLocationMap,
|
|
||||||
Span(e.failedAtOffset, e.failedAtOffset + 1)
|
|
||||||
),
|
|
||||||
e
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,9 @@ class ClosureExprSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
|||||||
|
|
||||||
"closure" should "parse" in {
|
"closure" should "parse" in {
|
||||||
val script =
|
val script =
|
||||||
"""func f() -> string:
|
"""aqua Test
|
||||||
|
|
|
||||||
|
|func f() -> string:
|
||||||
| closure = (s: string) -> string:
|
| closure = (s: string) -> string:
|
||||||
| LocalSrv.inside()
|
| LocalSrv.inside()
|
||||||
| p2Id <- Peer.identify()
|
| p2Id <- Peer.identify()
|
||||||
|
@ -22,7 +22,7 @@ import scala.language.implicitConversions
|
|||||||
class FuncExprSpec extends AnyFlatSpec with Matchers with Inside with Inspectors with AquaSpec {
|
class FuncExprSpec extends AnyFlatSpec with Matchers with Inside with Inspectors with AquaSpec {
|
||||||
import AquaSpec.{given, *}
|
import AquaSpec.{given, *}
|
||||||
|
|
||||||
private val parser = Parser.spanParser
|
private val parser = RootExpr.ast0
|
||||||
|
|
||||||
"func header" should "parse" in {
|
"func header" should "parse" in {
|
||||||
funcExpr("func some") should be(
|
funcExpr("func some") should be(
|
||||||
@ -237,7 +237,7 @@ class FuncExprSpec extends AnyFlatSpec with Matchers with Inside with Inspectors
|
|||||||
|
|
||||||
val tree = parser.parseAll(script).value.toEither.value
|
val tree = parser.parseAll(script).value.toEither.value
|
||||||
|
|
||||||
val qTree = tree.tree.foldLeft(mutable.Queue.empty[Expr[Id]]) { case (acc, tag) =>
|
val qTree = tree.foldLeft(mutable.Queue.empty[Expr[Id]]) { case (acc, tag) =>
|
||||||
acc.enqueue(tag.mapK(nat))
|
acc.enqueue(tag.mapK(nat))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,8 +311,7 @@ class FuncExprSpec extends AnyFlatSpec with Matchers with Inside with Inspectors
|
|||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
|
|
||||||
inside(parser.parseAll(script).value) { case Valid(ast) =>
|
inside(parser.parseAll(script).value) { case Valid(ast) =>
|
||||||
ast
|
Cofree.cata[Chain, Expr[Span.S], Int](ast)((expr, results) =>
|
||||||
.cata[Int]((expr, results) =>
|
|
||||||
// Count `if`s inside the tree
|
// Count `if`s inside the tree
|
||||||
Eval.later(results.sumAll + (expr match {
|
Eval.later(results.sumAll + (expr match {
|
||||||
case IfExpr(_) => 1
|
case IfExpr(_) => 1
|
||||||
|
@ -5,6 +5,7 @@ import aqua.parser.expr.func.ServiceIdExpr
|
|||||||
import aqua.parser.lexer.{LiteralToken, Token}
|
import aqua.parser.lexer.{LiteralToken, Token}
|
||||||
import aqua.parser.lift.LiftParser.Implicits.*
|
import aqua.parser.lift.LiftParser.Implicits.*
|
||||||
import aqua.types.LiteralType
|
import aqua.types.LiteralType
|
||||||
|
|
||||||
import cats.Id
|
import cats.Id
|
||||||
import cats.data.NonEmptyList
|
import cats.data.NonEmptyList
|
||||||
import org.scalatest.flatspec.AnyFlatSpec
|
import org.scalatest.flatspec.AnyFlatSpec
|
||||||
@ -23,15 +24,9 @@ class ImportFromSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
HeadExpr.ast
|
ImportFromExpr.p
|
||||||
.parseAll(s"""import MyModule, func as fn from "file.aqua"
|
.parseAll("""import MyModule, func as fn from "file.aqua"""")
|
||||||
|""".stripMargin)
|
|
||||||
.value
|
.value
|
||||||
.tail
|
|
||||||
.value
|
|
||||||
.headOption
|
|
||||||
.get
|
|
||||||
.head
|
|
||||||
.mapK(spanToId) should be(
|
.mapK(spanToId) should be(
|
||||||
ImportFromExpr(
|
ImportFromExpr(
|
||||||
NonEmptyList.fromListUnsafe(
|
NonEmptyList.fromListUnsafe(
|
||||||
|
@ -3,18 +3,20 @@ package aqua.parser.head
|
|||||||
import aqua.AquaSpec
|
import aqua.AquaSpec
|
||||||
import aqua.parser.expr.func.ServiceIdExpr
|
import aqua.parser.expr.func.ServiceIdExpr
|
||||||
import aqua.parser.lexer.{LiteralToken, Token}
|
import aqua.parser.lexer.{LiteralToken, Token}
|
||||||
|
import aqua.parser.lift.LiftParser.Implicits.*
|
||||||
import aqua.types.LiteralType
|
import aqua.types.LiteralType
|
||||||
|
|
||||||
import cats.Id
|
import cats.Id
|
||||||
import org.scalatest.flatspec.AnyFlatSpec
|
import org.scalatest.flatspec.AnyFlatSpec
|
||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
import aqua.parser.lift.LiftParser.Implicits.*
|
|
||||||
|
|
||||||
class ModuleSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
class ModuleSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
||||||
import AquaSpec.*
|
import AquaSpec.*
|
||||||
|
|
||||||
"module header" should "be parsed" in {
|
"module header" should "be parsed" in {
|
||||||
ModuleExpr.p.parseAll("module MyModule").value.mapK(spanToId) should be(
|
ModuleExpr.p.parseAll("aqua MyModule").value.mapK(spanToId) should be(
|
||||||
ModuleExpr(
|
ModuleExpr(
|
||||||
|
ModuleExpr.Word[Id](Id(ModuleExpr.Word.Kind.Aqua)),
|
||||||
toAb("MyModule"),
|
toAb("MyModule"),
|
||||||
None,
|
None,
|
||||||
Nil,
|
Nil,
|
||||||
@ -22,13 +24,16 @@ class ModuleSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
HeadExpr.ast
|
Header.p
|
||||||
.parseAll(s"""module MyModule declares *
|
.parseAll(s"""aqua MyModule declares *
|
||||||
|""".stripMargin)
|
|""".stripMargin)
|
||||||
.value
|
.value
|
||||||
.head
|
.headers
|
||||||
|
.headOption
|
||||||
|
.get
|
||||||
.mapK(spanToId) should be(
|
.mapK(spanToId) should be(
|
||||||
ModuleExpr(
|
ModuleExpr(
|
||||||
|
ModuleExpr.Word[Id](Id(ModuleExpr.Word.Kind.Aqua)),
|
||||||
toAb("MyModule"),
|
toAb("MyModule"),
|
||||||
Some(Token.lift[Id, Unit](())),
|
Some(Token.lift[Id, Unit](())),
|
||||||
Nil,
|
Nil,
|
||||||
|
13
pnpm-lock.yaml
generated
13
pnpm-lock.yaml
generated
@ -39,9 +39,6 @@ importers:
|
|||||||
'@fluencelabs/aqua-api':
|
'@fluencelabs/aqua-api':
|
||||||
specifier: 0.13.4
|
specifier: 0.13.4
|
||||||
version: link:../api/api-npm
|
version: link:../api/api-npm
|
||||||
'@fluencelabs/aqua-dht':
|
|
||||||
specifier: 0.2.5
|
|
||||||
version: 0.2.5
|
|
||||||
'@fluencelabs/aqua-lib':
|
'@fluencelabs/aqua-lib':
|
||||||
specifier: 0.9.0
|
specifier: 0.9.0
|
||||||
version: 0.9.0
|
version: 0.9.0
|
||||||
@ -477,16 +474,6 @@ packages:
|
|||||||
'@jridgewell/trace-mapping': 0.3.9
|
'@jridgewell/trace-mapping': 0.3.9
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@fluencelabs/aqua-dht@0.2.5:
|
|
||||||
resolution: {integrity: sha512-8jWUCeAftRtafqD6MgC7vkCnLOD6pwJspGHykPbXpg2pKbwANAAzAb/w8XbIScBzbIonZ5N7FfSVlTet383A3w==}
|
|
||||||
dependencies:
|
|
||||||
'@fluencelabs/aqua-lib': 0.1.14
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@fluencelabs/aqua-lib@0.1.14:
|
|
||||||
resolution: {integrity: sha512-H2Q4gIvociUxc4J2mwmH0D+mrU2N2Z+enKCHgBCanMVEE2wZDsZ80GTbDKsQjEq+gpqbnJIk8lJBYW6lyvLJTg==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@fluencelabs/aqua-lib@0.9.0:
|
/@fluencelabs/aqua-lib@0.9.0:
|
||||||
resolution: {integrity: sha512-V0xhc0UXBF6kjfL9Y/agWGQuW+ie2zckj37KWv8Dq4teYuo9N94O4Ynm7XULWHaaWtbWvzFcDcc6nc9qG7gxcQ==}
|
resolution: {integrity: sha512-V0xhc0UXBF6kjfL9Y/agWGQuW+ie2zckj37KWv8Dq4teYuo9N94O4Ynm7XULWHaaWtbWvzFcDcc6nc9qG7gxcQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -18,6 +18,7 @@ import cats.syntax.foldable.*
|
|||||||
import cats.syntax.functor.*
|
import cats.syntax.functor.*
|
||||||
import cats.syntax.option.*
|
import cats.syntax.option.*
|
||||||
import cats.syntax.semigroup.*
|
import cats.syntax.semigroup.*
|
||||||
|
import cats.syntax.traverse.*
|
||||||
import cats.syntax.validated.*
|
import cats.syntax.validated.*
|
||||||
import cats.{Comonad, Eval, Monoid}
|
import cats.{Comonad, Eval, Monoid}
|
||||||
|
|
||||||
@ -104,55 +105,63 @@ class HeaderHandler[S[_]: Comonad, C](using
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler for every header expression, will be combined later
|
val handleModule: ModuleExpr[S] => Res[S, C] = {
|
||||||
val onExpr: PartialFunction[HeaderExpr[S], Res[S, C]] = {
|
case ModuleExpr(word, name, declareAll, declareNames, declareCustom) =>
|
||||||
// Module header, like `module A declares *`
|
|
||||||
case ModuleExpr(name, declareAll, declareNames, declareCustom) =>
|
|
||||||
val shouldDeclare = declareNames.map(_.value).toSet ++ declareCustom.map(_.value)
|
val shouldDeclare = declareNames.map(_.value).toSet ++ declareCustom.map(_.value)
|
||||||
validNec(
|
|
||||||
HeaderSem[S, C](
|
lazy val sem = HeaderSem(
|
||||||
// Save module header info
|
// Save module header info
|
||||||
acm.empty.setModule(
|
acm.empty.setModule(
|
||||||
name.value,
|
name.value,
|
||||||
shouldDeclare
|
shouldDeclare
|
||||||
),
|
),
|
||||||
(ctx, _) =>
|
(ctx, _) =>
|
||||||
// When file is handled, check that all the declarations exists
|
// When file is handled, check that all the declarations exists
|
||||||
if (declareAll.nonEmpty) {
|
if (declareAll.nonEmpty)
|
||||||
validNec(
|
ctx.setModule(name.value, declares = ctx.all).validNec
|
||||||
ctx.setModule(name.value, declares = ctx.all)
|
else
|
||||||
)
|
(
|
||||||
} else
|
declareNames.fproductLeft(_.value) ::: declareCustom.fproductLeft(_.value)
|
||||||
(
|
).map { case (n, t) =>
|
||||||
declareNames.fproductLeft(_.value) ::: declareCustom.fproductLeft(_.value)
|
ctx
|
||||||
).map { case (n, t) =>
|
.pick(n, None, ctx.module.nonEmpty)
|
||||||
ctx
|
.toValidNec(
|
||||||
.pick(n, None, ctx.module.nonEmpty)
|
error(
|
||||||
.toValidNec(
|
t,
|
||||||
error(
|
s"`$n` is expected to be declared, but declaration is not found in the file"
|
||||||
t,
|
|
||||||
s"`$n` is expected to be declared, but declaration is not found in the file"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
.void
|
|
||||||
}.combineAll
|
|
||||||
.as(
|
|
||||||
// TODO: why module name and declares is lost? where is it lost?
|
|
||||||
ctx.setModule(name.value, declares = shouldDeclare)
|
|
||||||
)
|
)
|
||||||
)
|
.void
|
||||||
|
}.combineAll.as(
|
||||||
|
// TODO: why module name and declares is lost? where is it lost?
|
||||||
|
ctx.setModule(name.value, declares = shouldDeclare)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
word.value.fold(
|
||||||
|
module = error(
|
||||||
|
word,
|
||||||
|
"Keyword `module` is deprecated, use `aqua` instead"
|
||||||
|
).invalidNec,
|
||||||
|
aqua = sem.validNec
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler for every header expression, will be combined later
|
||||||
|
val onExpr: HeaderExpr[S] => Res[S, C] = {
|
||||||
|
case m: ModuleExpr[S] =>
|
||||||
|
error(m.token, "Module header is expected to be at the top").invalidNec
|
||||||
|
|
||||||
case f @ ImportExpr(_) =>
|
case f @ ImportExpr(_) =>
|
||||||
// Import everything from a file
|
// Import everything from a file
|
||||||
resolve(f).map(fc => HeaderSem[S, C](fc, (c, _) => validNec(c)))
|
resolve(f).map(fc => HeaderSem(fc, (c, _) => validNec(c)))
|
||||||
|
|
||||||
case f @ ImportFromExpr(_, _) =>
|
case f @ ImportFromExpr(_, _) =>
|
||||||
// Import, map declarations
|
// Import, map declarations
|
||||||
resolve(f)
|
resolve(f)
|
||||||
.andThen(getFrom(f, _))
|
.andThen(getFrom(f, _))
|
||||||
.map { ctx =>
|
.map { ctx =>
|
||||||
HeaderSem[S, C](ctx, (c, _) => validNec(c))
|
HeaderSem(ctx, (c, _) => validNec(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
case f @ UseExpr(_, asModule) =>
|
case f @ UseExpr(_, asModule) =>
|
||||||
@ -160,7 +169,7 @@ class HeaderHandler[S[_]: Comonad, C](using
|
|||||||
resolve(f)
|
resolve(f)
|
||||||
.andThen(toModule(_, f.token, asModule))
|
.andThen(toModule(_, f.token, asModule))
|
||||||
.map { fc =>
|
.map { fc =>
|
||||||
HeaderSem[S, C](fc, (c, _) => validNec(c))
|
HeaderSem(fc, (c, _) => validNec(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
case f @ UseFromExpr(_, _, asModule) =>
|
case f @ UseFromExpr(_, _, asModule) =>
|
||||||
@ -169,86 +178,66 @@ class HeaderHandler[S[_]: Comonad, C](using
|
|||||||
.andThen(getFrom(f, _))
|
.andThen(getFrom(f, _))
|
||||||
.andThen(toModule(_, f.token, Some(asModule)))
|
.andThen(toModule(_, f.token, Some(asModule)))
|
||||||
.map { fc =>
|
.map { fc =>
|
||||||
HeaderSem[S, C](fc, (c, _) => validNec(c))
|
HeaderSem(fc, (c, _) => validNec(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
case ExportExpr(pubs) =>
|
case ExportExpr(pubs) =>
|
||||||
// Save exports, finally handle them
|
// Save exports, finally handle them
|
||||||
validNec(
|
HeaderSem(
|
||||||
HeaderSem[S, C](
|
// Nothing there
|
||||||
// Nothing there
|
picker.blank,
|
||||||
picker.blank,
|
(ctx, initCtx) =>
|
||||||
(ctx, initCtx) =>
|
val sumCtx = initCtx |+| ctx
|
||||||
val sumCtx = initCtx |+| ctx
|
|
||||||
|
|
||||||
pubs
|
pubs
|
||||||
.map(
|
.map(
|
||||||
_.bimap(
|
_.bimap(
|
||||||
_.bimap(n => (n, n.value), _.map(_.value)),
|
_.bimap(n => (n, n.value), _.map(_.value)),
|
||||||
_.bimap(n => (n, n.value), _.map(_.value))
|
_.bimap(n => (n, n.value), _.map(_.value))
|
||||||
).merge
|
).merge
|
||||||
)
|
)
|
||||||
.map { case ((token, name), rename) =>
|
.map { case ((token, name), rename) =>
|
||||||
sumCtx
|
sumCtx
|
||||||
.pick(name, rename, declared = false)
|
.pick(name, rename, declared = false)
|
||||||
.as(Map(name -> rename))
|
.as(Map(name -> rename))
|
||||||
.toValid(
|
.toValid(
|
||||||
error(
|
error(
|
||||||
token,
|
token,
|
||||||
s"File has no $name declaration or import, " +
|
s"File has no $name declaration or import, " +
|
||||||
s"cannot export, available functions: ${sumCtx.funcNames.mkString(", ")}"
|
s"cannot export, available functions: ${sumCtx.funcNames.mkString(", ")}"
|
||||||
)
|
|
||||||
)
|
)
|
||||||
.ensure(
|
|
||||||
error(
|
|
||||||
token,
|
|
||||||
s"Can not export '$name' as it is an ability"
|
|
||||||
)
|
|
||||||
)(_ => !sumCtx.isAbility(name))
|
|
||||||
.toValidatedNec <* exportFuncChecks(sumCtx, token, name)
|
|
||||||
}
|
|
||||||
.prepend(validNec(ctx.exports))
|
|
||||||
.combineAll
|
|
||||||
.map(ctx.setExports)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
case HeadExpr(token) =>
|
|
||||||
// Old file exports everything that it declares
|
|
||||||
validNec(
|
|
||||||
HeaderSem[S, C](
|
|
||||||
acm.empty,
|
|
||||||
(ctx, initCtx) => {
|
|
||||||
val sumCtx = initCtx |+| ctx
|
|
||||||
ctx.funcNames.toList
|
|
||||||
.traverse_(name =>
|
|
||||||
// TODO: Provide better token for this error
|
|
||||||
exportFuncChecks(sumCtx, token, name)
|
|
||||||
)
|
|
||||||
.combine(
|
|
||||||
ctx.definedAbilityNames.toList.traverse_(name =>
|
|
||||||
// TODO: Provide better token for this error
|
|
||||||
error(token, s"Can not export '$name' as it is an ability ").invalidNec
|
|
||||||
)
|
)
|
||||||
)
|
.ensure(
|
||||||
.as(
|
error(
|
||||||
// Export everything
|
token,
|
||||||
ctx.setExports(
|
s"Can not export '$name' as it is an ability"
|
||||||
ctx.all.map(_ -> None).toMap
|
)
|
||||||
)
|
)(_ => !sumCtx.isAbility(name))
|
||||||
)
|
.toValidatedNec <* exportFuncChecks(sumCtx, token, name)
|
||||||
}
|
}
|
||||||
)
|
.prepend(validNec(ctx.exports))
|
||||||
)
|
.combineAll
|
||||||
|
.map(ctx.setExports)
|
||||||
|
).validNec
|
||||||
|
|
||||||
case f: FilenameExpr[S] =>
|
case f: FilenameExpr[S] =>
|
||||||
resolve(f).map(fc => HeaderSem[S, C](fc, (c, _) => validNec(c)))
|
resolve(f).map(fc => HeaderSem(fc, (c, _) => validNec(c)))
|
||||||
}
|
}
|
||||||
|
|
||||||
Cofree
|
val (module, other) =
|
||||||
.cata[Chain, HeaderExpr[S], Res[S, C]](header) { case (expr, children) =>
|
header.headers.uncons.collect { case (m: ModuleExpr[S], rest) =>
|
||||||
onExpr.lift.apply(expr).fold(Eval.later(children.combineAll))(combineAnd(children))
|
(m.some, rest)
|
||||||
}
|
}.getOrElse((none, header.headers))
|
||||||
.value
|
.bimap(
|
||||||
|
_.toValidNec(
|
||||||
|
error(
|
||||||
|
header.begin,
|
||||||
|
"Missing module header at the top of the file"
|
||||||
|
)
|
||||||
|
).andThen(handleModule),
|
||||||
|
_.foldMap(onExpr)
|
||||||
|
)
|
||||||
|
|
||||||
|
module |+| other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package aqua.semantics
|
package aqua.semantics
|
||||||
|
|
||||||
|
import aqua.parser.Ast
|
||||||
import aqua.parser.head.{ExportExpr, FromExpr, HeaderExpr, ModuleExpr}
|
import aqua.parser.head.{ExportExpr, FromExpr, HeaderExpr, ModuleExpr}
|
||||||
|
import aqua.parser.lexer.Token
|
||||||
import aqua.parser.lexer.{Ability, Name}
|
import aqua.parser.lexer.{Ability, Name}
|
||||||
import aqua.raw.RawContext
|
import aqua.raw.RawContext
|
||||||
import aqua.raw.arrow.{ArrowRaw, FuncRaw}
|
import aqua.raw.arrow.{ArrowRaw, FuncRaw}
|
||||||
@ -11,8 +13,8 @@ import aqua.types.{AbilityType, ArrowType, NilType, ProductType, ScalarType}
|
|||||||
|
|
||||||
import cats.data.{Chain, NonEmptyList, NonEmptyMap, Validated}
|
import cats.data.{Chain, NonEmptyList, NonEmptyMap, Validated}
|
||||||
import cats.free.Cofree
|
import cats.free.Cofree
|
||||||
import cats.{Eval, Id, Monoid}
|
|
||||||
import cats.syntax.applicative.*
|
import cats.syntax.applicative.*
|
||||||
|
import cats.{Eval, Id, Monoid}
|
||||||
import org.scalatest.Inside
|
import org.scalatest.Inside
|
||||||
import org.scalatest.flatspec.AnyFlatSpec
|
import org.scalatest.flatspec.AnyFlatSpec
|
||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
@ -23,26 +25,25 @@ class HeaderSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
|
|
||||||
val handler = new HeaderHandler[Id, RawContext]()
|
val handler = new HeaderHandler[Id, RawContext]()
|
||||||
|
|
||||||
def exportHeader(funcName: String): Cofree[Chain, HeaderExpr[Id]] = {
|
def exportHeader(funcName: String): Ast.Head[Id] = {
|
||||||
val exp: FromExpr.NameOrAbAs[Id] = Left((Name(funcName), None))
|
val exp: FromExpr.NameOrAbAs[Id] = Left((Name(funcName), None))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* aqua TestModule
|
* aqua TestModule
|
||||||
* export <funcName>
|
* export <funcName>
|
||||||
*/
|
*/
|
||||||
Cofree(
|
Ast.Head(
|
||||||
ModuleExpr(
|
Token.lift(()),
|
||||||
name = Ability[Id]("TestModule"),
|
|
||||||
declareAll = None,
|
|
||||||
declareNames = Nil,
|
|
||||||
declareCustom = Nil
|
|
||||||
),
|
|
||||||
Chain(
|
Chain(
|
||||||
Cofree(
|
ModuleExpr(
|
||||||
ExportExpr(NonEmptyList.of(exp)),
|
word = ModuleExpr.Word[Id](Id(ModuleExpr.Word.Kind.Aqua)),
|
||||||
Chain.empty.pure
|
name = Ability[Id]("TestModule"),
|
||||||
)
|
declareAll = None,
|
||||||
).pure
|
declareNames = Nil,
|
||||||
|
declareCustom = Nil
|
||||||
|
),
|
||||||
|
ExportExpr(NonEmptyList.of(exp))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,9 @@ class SemanticsSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
|
|
||||||
val semantics = new RawSemantics[Span.S]()
|
val semantics = new RawSemantics[Span.S]()
|
||||||
|
|
||||||
|
private def addAqua(script: String) =
|
||||||
|
if (script.startsWith("aqua")) script else "aqua Test\n" + script
|
||||||
|
|
||||||
def insideResult(script: String)(
|
def insideResult(script: String)(
|
||||||
test: PartialFunction[
|
test: PartialFunction[
|
||||||
(
|
(
|
||||||
@ -41,7 +44,7 @@ class SemanticsSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
),
|
),
|
||||||
Any
|
Any
|
||||||
]
|
]
|
||||||
): Unit = inside(parser(script)) { case Validated.Valid(ast) =>
|
): Unit = inside(parser(addAqua(script))) { case Validated.Valid(ast) =>
|
||||||
val init = RawContext.blank.copy(
|
val init = RawContext.blank.copy(
|
||||||
parts = Chain
|
parts = Chain
|
||||||
.fromSeq(ConstantRaw.defaultConstants())
|
.fromSeq(ConstantRaw.defaultConstants())
|
||||||
@ -60,7 +63,7 @@ class SemanticsSpec extends AnyFlatSpec with Matchers with Inside {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def insideSemErrors(script: String)(test: NonEmptyChain[SemanticError[Span.S]] => Any): Unit =
|
def insideSemErrors(script: String)(test: NonEmptyChain[SemanticError[Span.S]] => Any): Unit =
|
||||||
inside(parser(script)) { case Validated.Valid(ast) =>
|
inside(parser(addAqua(script))) { case Validated.Valid(ast) =>
|
||||||
val init = RawContext.blank
|
val init = RawContext.blank
|
||||||
inside(semantics.process(ast, init).value.value) { case Left(errors) =>
|
inside(semantics.process(ast, init).value.value) { case Left(errors) =>
|
||||||
test(errors)
|
test(errors)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package aqua.types
|
package aqua.types
|
||||||
|
|
||||||
import org.scalatest.flatspec.AnyFlatSpec
|
|
||||||
import org.scalatest.matchers.should.Matchers
|
|
||||||
import cats.data.NonEmptyMap
|
import cats.data.NonEmptyMap
|
||||||
import cats.syntax.partialOrder._
|
import cats.syntax.partialOrder._
|
||||||
|
import org.scalatest.flatspec.AnyFlatSpec
|
||||||
|
import org.scalatest.matchers.should.Matchers
|
||||||
|
|
||||||
class IntersectTypesSpec extends AnyFlatSpec with Matchers {
|
class IntersectTypesSpec extends AnyFlatSpec with Matchers {
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package aqua.types
|
package aqua.types
|
||||||
|
|
||||||
|
import cats.syntax.partialOrder._
|
||||||
import org.scalatest.flatspec.AnyFlatSpec
|
import org.scalatest.flatspec.AnyFlatSpec
|
||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
import cats.syntax.partialOrder._
|
|
||||||
|
|
||||||
class UniteTypesSpec extends AnyFlatSpec with Matchers {
|
class UniteTypesSpec extends AnyFlatSpec with Matchers {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user