mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 14:40:17 +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.transform.{Transform, TransformConfig}
|
||||
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.raw.ops.Call
|
||||
import aqua.raw.ops.CallArrowRawTag
|
||||
|
@ -16,7 +16,7 @@ import aqua.parser.expr.AbilityExpr.p
|
||||
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, LexerError, ParserError}
|
||||
import aqua.raw.ConstantRaw
|
||||
import aqua.raw.ops.Call
|
||||
import aqua.raw.value.ValueRaw
|
||||
|
@ -2,7 +2,6 @@ package aqua.run
|
||||
|
||||
import aqua.backend.air.FuncAirGen
|
||||
import aqua.definitions.{FunctionDef, TypeDefinition}
|
||||
import aqua.io.OutputPrinter
|
||||
import aqua.model.transform.{Transform, TransformConfig}
|
||||
import aqua.model.{FuncArrow, ValueModel, VarModel}
|
||||
import aqua.parser.lexer.CallArrowToken
|
||||
@ -10,6 +9,7 @@ import aqua.parser.lift.Span
|
||||
import aqua.raw.ops.{Call, CallArrowRawTag, SeqTag}
|
||||
import aqua.raw.value.{LiteralRaw, ValueRaw, VarRaw}
|
||||
import aqua.types.*
|
||||
|
||||
import cats.data.Validated.{invalid, invalidNec, invalidNel, validNec, validNel}
|
||||
import cats.data.{NonEmptyList, Validated, ValidatedNec}
|
||||
import cats.effect.kernel.Async
|
||||
@ -18,8 +18,7 @@ import cats.syntax.flatMap.*
|
||||
import cats.syntax.partialOrder.*
|
||||
import cats.syntax.show.*
|
||||
import cats.syntax.traverse.*
|
||||
import cats.{~>, Id}
|
||||
|
||||
import cats.{Id, ~>}
|
||||
import scala.collection.immutable.SortedMap
|
||||
import scala.concurrent.ExecutionContext
|
||||
|
||||
|
@ -6,20 +6,19 @@ import aqua.parser.head.{FilenameExpr, ImportExpr}
|
||||
import aqua.parser.lift.{LiftParser, Span}
|
||||
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.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.{~>, Comonad, Monad}
|
||||
import cats.syntax.validated.*
|
||||
import cats.{Comonad, Monad, ~>}
|
||||
import scribe.Logging
|
||||
|
||||
// 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
|
||||
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
|
||||
}.value.traverse { case (filename, token) =>
|
||||
}.traverse { case (filename, token) =>
|
||||
sources
|
||||
.resolveImport(id, filename)
|
||||
.map(
|
||||
|
@ -89,7 +89,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
|
||||
val src = Map(
|
||||
"index.aqua" ->
|
||||
"""module Foo declares X
|
||||
"""aqua Foo declares 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 {
|
||||
val src = Map(
|
||||
"index.aqua" ->
|
||||
"""service Op("op"):
|
||||
"""aqua Test
|
||||
|
|
||||
|export exec
|
||||
|
|
||||
|service Op("op"):
|
||||
| identity(s: 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 {
|
||||
val src = Map(
|
||||
"index.aqua" ->
|
||||
"""service Op("op"):
|
||||
"""aqua HopBackTest
|
||||
|
|
||||
|export exec
|
||||
|
|
||||
|service Op("op"):
|
||||
| call(s: string)
|
||||
|
|
||||
|func exec(peers: []string):
|
||||
@ -288,7 +296,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
|
||||
val src = Map(
|
||||
"index.aqua" ->
|
||||
"""module Import
|
||||
"""aqua Import
|
||||
|import foobar from "export2.aqua"
|
||||
|
|
||||
|use foo as f from "export2.aqua" as Exp
|
||||
@ -307,7 +315,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
)
|
||||
val imports = Map(
|
||||
"export2.aqua" ->
|
||||
"""module Export declares foobar, foo
|
||||
"""aqua Export declares foobar, foo
|
||||
|
|
||||
|func bar() -> string:
|
||||
| <- " I am MyFooBar bar"
|
||||
@ -323,7 +331,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
|
|
||||
|""".stripMargin,
|
||||
"../gen/OneMore.aqua" ->
|
||||
"""
|
||||
"""aqua Test declares OneMore
|
||||
|service OneMore:
|
||||
| more_call()
|
||||
| consume(s: string)
|
||||
@ -379,7 +387,10 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
|
||||
it should "optimize math inside stream join" in {
|
||||
val src = Map(
|
||||
"main.aqua" -> """
|
||||
"main.aqua" -> """aqua Test
|
||||
|
|
||||
|export main
|
||||
|
|
||||
|func main(i: i32):
|
||||
| stream: *string
|
||||
| stream <<- "a"
|
||||
@ -434,8 +445,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
|
||||
it should "allow returning and passing services as abilities" in {
|
||||
val src = Map(
|
||||
"main.aqua" -> """
|
||||
|aqua Test
|
||||
"main.aqua" -> """aqua 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
|
||||
|
||||
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
|
||||
|
||||
use DECLARE_CONST, decl_bar from "imports_exports/declare.aqua" as Declare
|
||||
|
||||
service SomeService("wed"):
|
||||
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:
|
||||
value: string
|
||||
|
||||
|
@ -1,6 +1,11 @@
|
||||
aqua CallArrow
|
||||
|
||||
export passFunctionAsArg, reproArgsBug426
|
||||
|
||||
import "println.aqua"
|
||||
import "@fluencelabs/aqua-lib/builtin.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
|
||||
func passFunctionAsArg(node: string, str: string, c: string -> string):
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua Canon
|
||||
|
||||
export Ser, bugLng79
|
||||
|
||||
data Record:
|
||||
relay_id: []string
|
||||
peer_id: string
|
||||
|
@ -1,9 +1,9 @@
|
||||
module Closure declares *
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
aqua Closure declares *
|
||||
|
||||
export LocalSrv, closureIn, closureOut, closureBig, closureOut2, lng58Bug, multipleClosuresBugLNG262, lng317Bug
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
service MyOp("op"):
|
||||
identity(s: string) -> string
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua Co
|
||||
|
||||
export CoService, coFunc
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
service CoService("coservice-id"):
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua CollectionSugar
|
||||
|
||||
export arraySugar, streamSugar, optionSugar, GetArr, bugLNG59
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
func arraySugar(n: u32, m: u32) -> []u32, []u32:
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua Complex
|
||||
|
||||
export TestS, doStuff
|
||||
|
||||
import "helloWorld.aqua"
|
||||
import "println.aqua"
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua Constants
|
||||
|
||||
export Getter, callConstant, timestampAndTtl
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
service Getter("test"):
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua DataAlias
|
||||
|
||||
export NodeIdGetter, getAliasedData
|
||||
|
||||
-- set `PeerId` name to be a type alias for `string` type
|
||||
alias PeerId : string
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
aqua Example
|
||||
|
||||
service Peer("peer"):
|
||||
is_connected: string -> bool
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua Fold
|
||||
|
||||
export iterateAndPrint, iterateAndPrintParallel, forBug499
|
||||
|
||||
import "println.aqua"
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
module FoldJoin
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
aqua FoldJoin
|
||||
|
||||
export getTwoResults
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
service Op2("op"):
|
||||
identity(s: u64)
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua Func
|
||||
|
||||
export TestSrv, testFunc
|
||||
|
||||
service TestSrv("test-service-id"):
|
||||
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
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua Functors
|
||||
|
||||
export lng119Bug
|
||||
|
||||
func lng119Bug() -> []u32:
|
||||
nums = [1,2,3,4,5]
|
||||
results: *u32
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua HelloWorld
|
||||
|
||||
export StringExtra, helloWorld
|
||||
|
||||
service StringExtra("service-id"):
|
||||
addNameToHello: string -> string
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua If
|
||||
|
||||
export ifElseCall, ifElseNumCall, ifCorrectXorWrap, bugLNG69
|
||||
|
||||
import "println.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
|
||||
|
||||
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"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
-- exports3.aqua
|
||||
module Export3 declares *
|
||||
aqua Export3 declares *
|
||||
|
||||
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"
|
||||
|
||||
|
@ -1,2 +1,4 @@
|
||||
aqua OneMore declares OneMore
|
||||
|
||||
service OneMore:
|
||||
more_call()
|
@ -1,4 +1,4 @@
|
||||
module Import
|
||||
aqua Import
|
||||
import foobar from "export2.aqua"
|
||||
|
||||
use foo as f from "export2.aqua" as Exp
|
||||
|
@ -1,5 +1,5 @@
|
||||
-- imports3.aqua
|
||||
module Import3 declares *
|
||||
aqua Import3 declares *
|
||||
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
export foo_wrapper
|
||||
|
@ -1,3 +1,5 @@
|
||||
aqua ImportsEmpty
|
||||
|
||||
import decl_foo, decl_bar from "declare.aqua"
|
||||
use DECLARE_CONST, SuperFoo, DECLARE_CONST2 as DC2 from "declare.aqua" as Declare
|
||||
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"
|
||||
use DECLARE_CONST, SuperFoo, DECLARE_CONST2 as DC2 from "declare.aqua" as Declare
|
||||
import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
@ -1,3 +1,4 @@
|
||||
aqua SubImport declares *
|
||||
|
||||
alias SomeString : string
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua Join
|
||||
|
||||
export joinIdxLocal, joinIdxRelay, joinIdx
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
func joinIdxLocal(idx: i16, nodes: []string) -> []string:
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua MultiReturn
|
||||
|
||||
export GetStr, GetNum, multiReturnFunc
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
service GetStr("multiret-test"):
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua NestedData
|
||||
|
||||
export Test, test
|
||||
|
||||
data NestedType:
|
||||
val: string
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua NestedFuncs
|
||||
|
||||
export OpH, d
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
service OpH("opa"):
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua On
|
||||
|
||||
export getPeerExternalAddresses
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
func getPeerExternalAddresses(otherNodePeerId: string) -> []string:
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua OnErrorPropagation
|
||||
|
||||
export Test, onPropagate, nestedOnPropagate, seqOnPropagate
|
||||
|
||||
service Test("test-service"):
|
||||
fail(err: string)
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua Option
|
||||
|
||||
export SomeS, useOptional, returnOptional, returnNone
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
service SomeS("test2"):
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua OptionGen
|
||||
|
||||
export OptionString, emptyString, checkEmpty, checkNoneEmpty
|
||||
|
||||
service OptionString("opt_str"):
|
||||
checkOption(str: ?string) -> string
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua Par
|
||||
|
||||
export ParService, parFunc, testTimeout
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
service ParService("parservice-id"):
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua ParSeq
|
||||
|
||||
export testParSeq
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
service NumOp("op"):
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua PassArgs
|
||||
|
||||
export AquaDHT, create_client_util, bugLNG60
|
||||
|
||||
import Op from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
service AquaDHT("test-dht"):
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua Println declares *
|
||||
|
||||
export Println, print
|
||||
|
||||
service Println("println-service-id"):
|
||||
print: string -> ()
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua PushToStream
|
||||
|
||||
export OpA, get_results
|
||||
|
||||
service OpA("pop"):
|
||||
get_str() -> string
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
aqua ReturnArrow
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
export callReturnedArrow, callReturnedChainArrow
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
func returnCall(arg: string) -> string -> string, string:
|
||||
str <- Op.concat_strings(arg, " literal")
|
||||
closure = (s: string) -> string, string:
|
||||
|
@ -1,2 +1,6 @@
|
||||
aqua ReturnLiteral
|
||||
|
||||
export returnLiteral
|
||||
|
||||
func returnLiteral() -> string:
|
||||
<- "some literal"
|
@ -1,8 +1,5 @@
|
||||
aqua Stream
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
import "println.aqua"
|
||||
|
||||
export Stringer
|
||||
export checkStreams, returnStreamFromFunc
|
||||
export stringEmpty, returnEmptyLiteral
|
||||
@ -10,6 +7,9 @@ export returnNilLength, stringNone
|
||||
export streamFunctor, streamAssignment
|
||||
export streamIntFunctor, streamJoin
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
import "println.aqua"
|
||||
|
||||
service Stringer("stringer-id"):
|
||||
returnString: string -> string
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
module Ret declares *
|
||||
aqua Ret declares *
|
||||
|
||||
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:
|
||||
str: *string
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua StreamRestriction
|
||||
|
||||
export streamFold, streamRes
|
||||
|
||||
func streamFold(arr: []string) -> []string:
|
||||
res: *string
|
||||
for n <- arr:
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua StreamResults
|
||||
|
||||
export DTGetter, use_name1, use_name2
|
||||
|
||||
data DT:
|
||||
field: string
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
aqua Aaa
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
export structuralTypingTest
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
data WideData:
|
||||
s: string
|
||||
n: u32
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua SubImportUsage
|
||||
|
||||
export subImportUsage, ConcatSubs
|
||||
|
||||
import "imports_exports/subImport.aqua"
|
||||
|
||||
service ConcatSubs("concat_subs"):
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua TryCatch
|
||||
|
||||
export tryCatchTest
|
||||
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
service Unexisted("unex"):
|
||||
|
@ -1,3 +1,7 @@
|
||||
aqua TryOtherwise
|
||||
|
||||
export tryOtherwiseTest
|
||||
|
||||
service Unexisted("unex"):
|
||||
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": {},
|
||||
"devDependencies": {
|
||||
"@fluencelabs/aqua-api": "0.13.4",
|
||||
"@fluencelabs/aqua-dht": "0.2.5",
|
||||
"@fluencelabs/aqua-lib": "0.9.0",
|
||||
"@types/jest": "29.5.2",
|
||||
"@types/node": "18.19.3",
|
||||
|
@ -3,16 +3,16 @@ package aqua
|
||||
import aqua.files.FileModuleId
|
||||
import aqua.parser.lift.{FileSpan, Span}
|
||||
import aqua.parser.{Ast, Parser, ParserError}
|
||||
|
||||
import cats.data.*
|
||||
import cats.parse.LocationMap
|
||||
import cats.{~>, Comonad, Eval, Monad, Monoid, Order}
|
||||
import cats.{Comonad, Eval, Monad, Monoid, Order, ~>}
|
||||
|
||||
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 =>
|
||||
{ source =>
|
||||
{
|
||||
source => {
|
||||
logger.trace(s"creating parser for $id...")
|
||||
val nat = new (Span.S ~> FileSpan.F) {
|
||||
override def apply[A](span: Span.S[A]): FileSpan.F[A] = {
|
||||
@ -27,5 +27,3 @@ object SpanParser extends scribe.Logging {
|
||||
parser
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,26 +7,26 @@ import aqua.semantics.rules.locations.LocationsState
|
||||
import aqua.semantics.{CompilerState, RawSemantics, SemanticError, SemanticWarning, Semantics}
|
||||
|
||||
import cats.data.Validated.{Invalid, Valid}
|
||||
import cats.data.{NonEmptyChain, ValidatedNec}
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.apply.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.foldable.*
|
||||
import cats.syntax.either.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.foldable.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.reducible.*
|
||||
import cats.data.{NonEmptyChain, ValidatedNec}
|
||||
import monocle.Lens
|
||||
import monocle.macros.GenLens
|
||||
|
||||
class LspSemantics[S[_]] extends Semantics[S, LspContext[S]] {
|
||||
|
||||
private def getImportTokens(ast: Ast[S]): List[LiteralToken[S]] =
|
||||
ast.collectHead {
|
||||
ast.head.collect {
|
||||
case ImportExpr(fn) => fn
|
||||
case ImportFromExpr(_, fn) => fn
|
||||
case UseExpr(fn, _) => fn
|
||||
case UseFromExpr(_, fn, _) => fn
|
||||
}.value.toList
|
||||
}.toList
|
||||
|
||||
/**
|
||||
* Process the AST and return the semantics result.
|
||||
|
@ -108,22 +108,18 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
def compile(
|
||||
src: Map[String, String],
|
||||
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
|
||||
.compileToLsp[Id, String, String, Span.S](
|
||||
aquaSource(src, imports),
|
||||
id => txt => Parser.parse(Parser.parserSchema)(txt),
|
||||
AquaCompilerConf(ConstantRaw.defaultConstants(None))
|
||||
)
|
||||
.leftMap { errors =>
|
||||
println(errors)
|
||||
errors
|
||||
}
|
||||
}
|
||||
|
||||
it should "return right tokens" in {
|
||||
val main =
|
||||
"""module Import
|
||||
"""aqua Import
|
||||
|
|
||||
|import foo, strFunc, num from "export2.aqua"
|
||||
|
|
||||
|import "../gen/OneMore.aqua"
|
||||
@ -156,7 +152,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
)
|
||||
|
||||
val firstImport =
|
||||
"""module Export declares strFunc, num, foo
|
||||
"""aqua Export declares strFunc, num, foo
|
||||
|
|
||||
|func absb() -> string:
|
||||
| <- "ff"
|
||||
@ -173,7 +169,8 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
|""".stripMargin
|
||||
|
||||
val secondImport =
|
||||
"""
|
||||
"""aqua Export declares OneMore
|
||||
|
|
||||
|service OneMore:
|
||||
| more_call()
|
||||
| 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
|
||||
// OneMore service
|
||||
res.checkTokenLoc(secondImport, "OneMore", 0, serviceType) shouldBe true
|
||||
res.checkTokenLoc(secondImport, "OneMore", 1, serviceType) shouldBe true
|
||||
res.checkTokenLoc(
|
||||
secondImport,
|
||||
"more_call",
|
||||
@ -265,7 +262,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
ProductType(ScalarType.u32 :: Nil)
|
||||
)
|
||||
) 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
|
||||
res.checkTokenLoc(
|
||||
|
@ -1,43 +1,48 @@
|
||||
package aqua.parser
|
||||
|
||||
import aqua.helpers.tree.Tree
|
||||
import aqua.parser.expr.*
|
||||
import aqua.parser.head.{HeadExpr, HeaderExpr}
|
||||
import aqua.parser.lift.{LiftParser, Span}
|
||||
import aqua.parser.lift.LiftParser.*
|
||||
import aqua.parser.head.HeaderExpr
|
||||
import aqua.parser.lexer.Token
|
||||
|
||||
import cats.data.{Chain, Validated, ValidatedNec}
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.data.Chain
|
||||
import cats.free.Cofree
|
||||
import cats.{Comonad, Eval}
|
||||
import cats.~>
|
||||
import cats.Show
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.show.*
|
||||
import cats.{Comonad, ~>}
|
||||
import cats.{Eval, Show}
|
||||
|
||||
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] =
|
||||
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 {
|
||||
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]]
|
||||
|
||||
given [S[_]]: Show[Ast[S]] with {
|
||||
|
||||
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)
|
||||
|
||||
s"$head\n$body"
|
||||
|
@ -1,13 +1,15 @@
|
||||
package aqua.parser
|
||||
|
||||
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.Span.S
|
||||
import aqua.parser.lift.{LiftParser, Span}
|
||||
|
||||
import cats.data.{Validated, ValidatedNec}
|
||||
import cats.free.Cofree
|
||||
import cats.parse.{Parser as P, Parser0 as P0}
|
||||
import cats.syntax.validated.*
|
||||
import cats.{Comonad, ~>}
|
||||
|
||||
object Parser extends scribe.Logging {
|
||||
@ -15,7 +17,7 @@ object Parser extends scribe.Logging {
|
||||
|
||||
def parserSchema: P0[ValidatedNec[ParserError[Span.S], Ast[Span.S]]] = {
|
||||
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, _))
|
||||
}
|
||||
logger.trace("schema created")
|
||||
@ -24,19 +26,15 @@ object Parser extends scribe.Logging {
|
||||
|
||||
def parse[S[_]: LiftParser: Comonad](
|
||||
p: P0[ValidatedNec[ParserError[S], Ast[S]]]
|
||||
)(source: String): ValidatedNec[ParserError[S], Ast[S]] = {
|
||||
p.parseAll(source) match {
|
||||
case Right(value) => value
|
||||
case Left(e) => Validated.invalidNec(LexerError(e.wrapErr))
|
||||
}
|
||||
}
|
||||
)(source: String): ValidatedNec[ParserError[S], Ast[S]] =
|
||||
p.parseAll(source).left.map(e => LexerError(e.wrapErr).invalidNec).merge
|
||||
|
||||
def natParser[S[_]: LiftParser: Comonad, K[_]: Comonad](
|
||||
p: P0[ValidatedNec[ParserError[S], Ast[S]]],
|
||||
nat: S ~> K
|
||||
)(source: String): ValidatedNec[ParserError[K], Ast[K]] =
|
||||
parse[S](p)(source).bimap(
|
||||
parse(p)(source).bimap(
|
||||
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.lexer.Token
|
||||
import aqua.parser.lexer.Token.*
|
||||
import aqua.parser.lift.{LiftParser, Span}
|
||||
import aqua.parser.lift.LiftParser.*
|
||||
import aqua.parser.lift.{LiftParser, Span}
|
||||
import aqua.parser.{Expr, ParserError}
|
||||
|
||||
import cats.data.{Chain, NonEmptyChain, NonEmptyList, Validated, ValidatedNec}
|
||||
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.~>
|
||||
|
||||
@ -24,7 +26,9 @@ object RootExpr extends Expr.Companion {
|
||||
def validChildren: List[Expr.Lexem] =
|
||||
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) {
|
||||
case ((errs, trees), Validated.Valid(tree)) => (errs, trees :+ tree)
|
||||
case ((errs, trees), Validated.Invalid(err)) => (errs ++ err.toChain, trees)
|
||||
@ -54,12 +58,11 @@ object RootExpr extends Expr.Companion {
|
||||
empty.backtrack | ast
|
||||
|
||||
override val ast: P[ValidatedNec[ParserError[Span.S], Tree[Span.S]]] =
|
||||
parserSchema
|
||||
.map { case (point, (errs, trees)) =>
|
||||
parserSchema.map { case (point, (errs, trees)) =>
|
||||
NonEmptyChain
|
||||
.fromChain(errs)
|
||||
.fold[ValidatedNec[ParserError[Span.S], Tree[Span.S]]](
|
||||
Validated.validNec(Cofree(RootExpr[Span.S](point), Eval.now(trees)))
|
||||
)(Validated.invalid)
|
||||
.toInvalid(
|
||||
Cofree(RootExpr(point), Eval.now(trees))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,14 @@ package aqua.parser.head
|
||||
import aqua.parser.lexer.Token.*
|
||||
import aqua.parser.lexer.{LiteralToken, Token, ValueToken}
|
||||
import aqua.parser.lift.LiftParser
|
||||
import aqua.parser.lift.Span
|
||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||
|
||||
import cats.Comonad
|
||||
import cats.data.NonEmptyList
|
||||
import cats.parse.Parser
|
||||
import cats.syntax.either.*
|
||||
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] {
|
||||
|
||||
@ -20,7 +21,7 @@ case class ExportExpr[F[_]](pubs: NonEmptyList[FromExpr.NameOrAbAs[F]]) extends
|
||||
copy(FromExpr.mapK(pubs)(fk))
|
||||
}
|
||||
|
||||
object ExportExpr extends HeaderExpr.Leaf {
|
||||
object ExportExpr extends HeaderExpr.Companion {
|
||||
|
||||
override val p: Parser[ExportExpr[Span.S]] =
|
||||
(`_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.{P0ToSpan, PToSpan}
|
||||
|
||||
import cats.{Comonad, Eval}
|
||||
import cats.Show
|
||||
import cats.data.Chain
|
||||
import cats.free.Cofree
|
||||
import cats.Show
|
||||
import cats.parse.Parser as P
|
||||
import cats.{Comonad, Eval}
|
||||
import cats.~>
|
||||
|
||||
trait HeaderExpr[S[_]] {
|
||||
@ -23,14 +23,6 @@ object HeaderExpr {
|
||||
|
||||
trait Companion {
|
||||
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 {
|
||||
|
@ -3,11 +3,12 @@ package aqua.parser.head
|
||||
import aqua.parser.lexer.Token._
|
||||
import aqua.parser.lexer.{LiteralToken, ValueToken}
|
||||
import aqua.parser.lift.LiftParser
|
||||
import aqua.parser.lift.Span
|
||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||
|
||||
import cats.Comonad
|
||||
import cats.parse.Parser
|
||||
import cats.~>
|
||||
import aqua.parser.lift.Span
|
||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||
|
||||
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}"
|
||||
}
|
||||
|
||||
object ImportExpr extends HeaderExpr.Leaf {
|
||||
object ImportExpr extends HeaderExpr.Companion {
|
||||
|
||||
override val p: Parser[HeaderExpr[Span.S]] =
|
||||
`import` *> ` ` *> ValueToken.string.map(ImportExpr(_))
|
||||
|
@ -3,12 +3,13 @@ package aqua.parser.head
|
||||
import aqua.parser.lexer.Token.*
|
||||
import aqua.parser.lexer.{LiteralToken, ValueToken}
|
||||
import aqua.parser.lift.LiftParser
|
||||
import aqua.parser.lift.Span
|
||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||
|
||||
import cats.Comonad
|
||||
import cats.data.NonEmptyList
|
||||
import cats.parse.Parser
|
||||
import cats.~>
|
||||
import aqua.parser.lift.Span
|
||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||
|
||||
case class ImportFromExpr[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}"
|
||||
}
|
||||
|
||||
object ImportFromExpr extends HeaderExpr.Leaf {
|
||||
object ImportFromExpr extends HeaderExpr.Companion {
|
||||
|
||||
override val p: Parser[HeaderExpr[Span.S]] =
|
||||
(`import` *> FromExpr.importFrom.surroundedBy(` `) ~ ValueToken.string).map {
|
||||
|
@ -1,17 +1,21 @@
|
||||
package aqua.parser.head
|
||||
|
||||
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.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.{P0ToSpan, PToSpan}
|
||||
|
||||
import cats.Comonad
|
||||
import cats.parse.Parser
|
||||
import cats.syntax.comonad.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.~>
|
||||
|
||||
case class ModuleExpr[F[_]](
|
||||
word: ModuleExpr.Word[F],
|
||||
name: Ability[F],
|
||||
declareAll: Option[Token[F]],
|
||||
declareNames: List[Name[F]],
|
||||
@ -21,40 +25,75 @@ case class ModuleExpr[F[_]](
|
||||
|
||||
override def mapK[K[_]: Comonad](fk: F ~> K): ModuleExpr[K] =
|
||||
copy(
|
||||
name.mapK(fk),
|
||||
declareAll.map(_.mapK(fk)),
|
||||
declareNames.map(_.mapK(fk)),
|
||||
declareCustom.map(_.mapK(fk))
|
||||
word = word.mapK(fk),
|
||||
name = name.mapK(fk),
|
||||
declareAll = declareAll.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]]
|
||||
|
||||
val nameOrAb: Parser[NameOrAb[Span.S]] =
|
||||
private val nameOrAb: Parser[NameOrAb[Span.S]] =
|
||||
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)
|
||||
|
||||
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(_))
|
||||
|
||||
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]] =
|
||||
((`module` | `aqua-word`) *> ` ` *> Ability.dotted ~
|
||||
(` declares ` *> nameOrAbListOrAll).?).map {
|
||||
case (name, None) =>
|
||||
ModuleExpr(name, None, Nil, Nil)
|
||||
case (name, Some(Left(exportMembers))) =>
|
||||
(
|
||||
(` *`.with1 *> moduleWord) ~
|
||||
(` ` *> Ability.dotted) ~
|
||||
(` declares ` *> nameOrAbListOrAll).?
|
||||
).map {
|
||||
case ((word, name), None) =>
|
||||
ModuleExpr(word, name, None, Nil, Nil)
|
||||
case ((word, name), Some(Left(exportMembers))) =>
|
||||
ModuleExpr(
|
||||
word,
|
||||
name,
|
||||
None,
|
||||
exportMembers.collect { case Left(x) => x },
|
||||
exportMembers.collect { case Right(x) => x }
|
||||
)
|
||||
case (name, Some(Right(point))) =>
|
||||
case ((word, name), Some(Right(point))) =>
|
||||
ModuleExpr(
|
||||
word,
|
||||
name,
|
||||
Some(point),
|
||||
Nil,
|
||||
|
@ -3,11 +3,12 @@ package aqua.parser.head
|
||||
import aqua.parser.lexer.Token.*
|
||||
import aqua.parser.lexer.{Ability, LiteralToken, ValueToken}
|
||||
import aqua.parser.lift.LiftParser
|
||||
import aqua.parser.lift.Span
|
||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||
|
||||
import cats.Comonad
|
||||
import cats.parse.Parser
|
||||
import cats.~>
|
||||
import aqua.parser.lift.Span
|
||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||
|
||||
case class UseExpr[F[_]](
|
||||
filename: LiteralToken[F],
|
||||
@ -21,7 +22,7 @@ case class UseExpr[F[_]](
|
||||
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]] =
|
||||
(`use` *> ` ` *> ValueToken.string ~ (` as ` *> Ability.ab).?).map {
|
||||
|
@ -3,12 +3,13 @@ package aqua.parser.head
|
||||
import aqua.parser.lexer.Token.*
|
||||
import aqua.parser.lexer.{Ability, LiteralToken, Name, ValueToken}
|
||||
import aqua.parser.lift.LiftParser
|
||||
import aqua.parser.lift.Span
|
||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||
|
||||
import cats.Comonad
|
||||
import cats.data.NonEmptyList
|
||||
import cats.parse.Parser
|
||||
import cats.~>
|
||||
import aqua.parser.lift.Span
|
||||
import aqua.parser.lift.Span.{P0ToSpan, PToSpan}
|
||||
|
||||
case class UseFromExpr[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}"
|
||||
}
|
||||
|
||||
object UseFromExpr extends HeaderExpr.Leaf {
|
||||
object UseFromExpr extends HeaderExpr.Companion {
|
||||
|
||||
override val p: Parser[UseFromExpr[Span.S]] =
|
||||
(`use` *> FromExpr.importFrom.surroundedBy(
|
||||
|
@ -1,7 +1,6 @@
|
||||
package aqua.parser.lexer
|
||||
|
||||
import aqua.parser.Expr
|
||||
import aqua.parser.head.FilenameExpr
|
||||
import aqua.parser.lexer.NamedArg.namedArgs
|
||||
import aqua.parser.lexer.Token.*
|
||||
import aqua.parser.lift.LiftParser
|
||||
|
@ -2,7 +2,6 @@ package aqua.parser.lift
|
||||
|
||||
import cats.parse.{LocationMap, Parser => P, Parser0}
|
||||
import cats.{Comonad, Eval}
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
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 {
|
||||
val script =
|
||||
"""func f() -> string:
|
||||
"""aqua Test
|
||||
|
|
||||
|func f() -> string:
|
||||
| closure = (s: string) -> string:
|
||||
| LocalSrv.inside()
|
||||
| p2Id <- Peer.identify()
|
||||
|
@ -22,7 +22,7 @@ import scala.language.implicitConversions
|
||||
class FuncExprSpec extends AnyFlatSpec with Matchers with Inside with Inspectors with AquaSpec {
|
||||
import AquaSpec.{given, *}
|
||||
|
||||
private val parser = Parser.spanParser
|
||||
private val parser = RootExpr.ast0
|
||||
|
||||
"func header" should "parse" in {
|
||||
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 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))
|
||||
}
|
||||
|
||||
@ -311,8 +311,7 @@ class FuncExprSpec extends AnyFlatSpec with Matchers with Inside with Inspectors
|
||||
|""".stripMargin
|
||||
|
||||
inside(parser.parseAll(script).value) { case Valid(ast) =>
|
||||
ast
|
||||
.cata[Int]((expr, results) =>
|
||||
Cofree.cata[Chain, Expr[Span.S], Int](ast)((expr, results) =>
|
||||
// Count `if`s inside the tree
|
||||
Eval.later(results.sumAll + (expr match {
|
||||
case IfExpr(_) => 1
|
||||
|
@ -5,6 +5,7 @@ import aqua.parser.expr.func.ServiceIdExpr
|
||||
import aqua.parser.lexer.{LiteralToken, Token}
|
||||
import aqua.parser.lift.LiftParser.Implicits.*
|
||||
import aqua.types.LiteralType
|
||||
|
||||
import cats.Id
|
||||
import cats.data.NonEmptyList
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
@ -23,15 +24,9 @@ class ImportFromSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
||||
)
|
||||
)
|
||||
|
||||
HeadExpr.ast
|
||||
.parseAll(s"""import MyModule, func as fn from "file.aqua"
|
||||
|""".stripMargin)
|
||||
ImportFromExpr.p
|
||||
.parseAll("""import MyModule, func as fn from "file.aqua"""")
|
||||
.value
|
||||
.tail
|
||||
.value
|
||||
.headOption
|
||||
.get
|
||||
.head
|
||||
.mapK(spanToId) should be(
|
||||
ImportFromExpr(
|
||||
NonEmptyList.fromListUnsafe(
|
||||
|
@ -3,18 +3,20 @@ package aqua.parser.head
|
||||
import aqua.AquaSpec
|
||||
import aqua.parser.expr.func.ServiceIdExpr
|
||||
import aqua.parser.lexer.{LiteralToken, Token}
|
||||
import aqua.parser.lift.LiftParser.Implicits.*
|
||||
import aqua.types.LiteralType
|
||||
|
||||
import cats.Id
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import aqua.parser.lift.LiftParser.Implicits.*
|
||||
|
||||
class ModuleSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
||||
import AquaSpec.*
|
||||
|
||||
"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.Word[Id](Id(ModuleExpr.Word.Kind.Aqua)),
|
||||
toAb("MyModule"),
|
||||
None,
|
||||
Nil,
|
||||
@ -22,13 +24,16 @@ class ModuleSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
||||
)
|
||||
)
|
||||
|
||||
HeadExpr.ast
|
||||
.parseAll(s"""module MyModule declares *
|
||||
Header.p
|
||||
.parseAll(s"""aqua MyModule declares *
|
||||
|""".stripMargin)
|
||||
.value
|
||||
.head
|
||||
.headers
|
||||
.headOption
|
||||
.get
|
||||
.mapK(spanToId) should be(
|
||||
ModuleExpr(
|
||||
ModuleExpr.Word[Id](Id(ModuleExpr.Word.Kind.Aqua)),
|
||||
toAb("MyModule"),
|
||||
Some(Token.lift[Id, Unit](())),
|
||||
Nil,
|
||||
|
13
pnpm-lock.yaml
generated
13
pnpm-lock.yaml
generated
@ -39,9 +39,6 @@ importers:
|
||||
'@fluencelabs/aqua-api':
|
||||
specifier: 0.13.4
|
||||
version: link:../api/api-npm
|
||||
'@fluencelabs/aqua-dht':
|
||||
specifier: 0.2.5
|
||||
version: 0.2.5
|
||||
'@fluencelabs/aqua-lib':
|
||||
specifier: 0.9.0
|
||||
version: 0.9.0
|
||||
@ -477,16 +474,6 @@ packages:
|
||||
'@jridgewell/trace-mapping': 0.3.9
|
||||
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:
|
||||
resolution: {integrity: sha512-V0xhc0UXBF6kjfL9Y/agWGQuW+ie2zckj37KWv8Dq4teYuo9N94O4Ynm7XULWHaaWtbWvzFcDcc6nc9qG7gxcQ==}
|
||||
dev: true
|
||||
|
@ -18,6 +18,7 @@ import cats.syntax.foldable.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.option.*
|
||||
import cats.syntax.semigroup.*
|
||||
import cats.syntax.traverse.*
|
||||
import cats.syntax.validated.*
|
||||
import cats.{Comonad, Eval, Monoid}
|
||||
|
||||
@ -104,13 +105,11 @@ class HeaderHandler[S[_]: Comonad, C](using
|
||||
)
|
||||
)
|
||||
|
||||
// Handler for every header expression, will be combined later
|
||||
val onExpr: PartialFunction[HeaderExpr[S], Res[S, C]] = {
|
||||
// Module header, like `module A declares *`
|
||||
case ModuleExpr(name, declareAll, declareNames, declareCustom) =>
|
||||
val handleModule: ModuleExpr[S] => Res[S, C] = {
|
||||
case ModuleExpr(word, name, declareAll, declareNames, declareCustom) =>
|
||||
val shouldDeclare = declareNames.map(_.value).toSet ++ declareCustom.map(_.value)
|
||||
validNec(
|
||||
HeaderSem[S, C](
|
||||
|
||||
lazy val sem = HeaderSem(
|
||||
// Save module header info
|
||||
acm.empty.setModule(
|
||||
name.value,
|
||||
@ -118,11 +117,9 @@ class HeaderHandler[S[_]: Comonad, C](using
|
||||
),
|
||||
(ctx, _) =>
|
||||
// When file is handled, check that all the declarations exists
|
||||
if (declareAll.nonEmpty) {
|
||||
validNec(
|
||||
ctx.setModule(name.value, declares = ctx.all)
|
||||
)
|
||||
} else
|
||||
if (declareAll.nonEmpty)
|
||||
ctx.setModule(name.value, declares = ctx.all).validNec
|
||||
else
|
||||
(
|
||||
declareNames.fproductLeft(_.value) ::: declareCustom.fproductLeft(_.value)
|
||||
).map { case (n, t) =>
|
||||
@ -135,24 +132,36 @@ class HeaderHandler[S[_]: Comonad, C](using
|
||||
)
|
||||
)
|
||||
.void
|
||||
}.combineAll
|
||||
.as(
|
||||
}.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(_) =>
|
||||
// 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(_, _) =>
|
||||
// Import, map declarations
|
||||
resolve(f)
|
||||
.andThen(getFrom(f, _))
|
||||
.map { ctx =>
|
||||
HeaderSem[S, C](ctx, (c, _) => validNec(c))
|
||||
HeaderSem(ctx, (c, _) => validNec(c))
|
||||
}
|
||||
|
||||
case f @ UseExpr(_, asModule) =>
|
||||
@ -160,7 +169,7 @@ class HeaderHandler[S[_]: Comonad, C](using
|
||||
resolve(f)
|
||||
.andThen(toModule(_, f.token, asModule))
|
||||
.map { fc =>
|
||||
HeaderSem[S, C](fc, (c, _) => validNec(c))
|
||||
HeaderSem(fc, (c, _) => validNec(c))
|
||||
}
|
||||
|
||||
case f @ UseFromExpr(_, _, asModule) =>
|
||||
@ -169,13 +178,12 @@ class HeaderHandler[S[_]: Comonad, C](using
|
||||
.andThen(getFrom(f, _))
|
||||
.andThen(toModule(_, f.token, Some(asModule)))
|
||||
.map { fc =>
|
||||
HeaderSem[S, C](fc, (c, _) => validNec(c))
|
||||
HeaderSem(fc, (c, _) => validNec(c))
|
||||
}
|
||||
|
||||
case ExportExpr(pubs) =>
|
||||
// Save exports, finally handle them
|
||||
validNec(
|
||||
HeaderSem[S, C](
|
||||
HeaderSem(
|
||||
// Nothing there
|
||||
picker.blank,
|
||||
(ctx, initCtx) =>
|
||||
@ -210,45 +218,26 @@ class HeaderHandler[S[_]: Comonad, C](using
|
||||
.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
|
||||
)
|
||||
)
|
||||
.as(
|
||||
// Export everything
|
||||
ctx.setExports(
|
||||
ctx.all.map(_ -> None).toMap
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
).validNec
|
||||
|
||||
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
|
||||
.cata[Chain, HeaderExpr[S], Res[S, C]](header) { case (expr, children) =>
|
||||
onExpr.lift.apply(expr).fold(Eval.later(children.combineAll))(combineAnd(children))
|
||||
}
|
||||
.value
|
||||
val (module, other) =
|
||||
header.headers.uncons.collect { case (m: ModuleExpr[S], rest) =>
|
||||
(m.some, rest)
|
||||
}.getOrElse((none, header.headers))
|
||||
.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
|
||||
|
||||
import aqua.parser.Ast
|
||||
import aqua.parser.head.{ExportExpr, FromExpr, HeaderExpr, ModuleExpr}
|
||||
import aqua.parser.lexer.Token
|
||||
import aqua.parser.lexer.{Ability, Name}
|
||||
import aqua.raw.RawContext
|
||||
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.free.Cofree
|
||||
import cats.{Eval, Id, Monoid}
|
||||
import cats.syntax.applicative.*
|
||||
import cats.{Eval, Id, Monoid}
|
||||
import org.scalatest.Inside
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
@ -23,26 +25,25 @@ class HeaderSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
|
||||
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))
|
||||
|
||||
/**
|
||||
* aqua TestModule
|
||||
* export <funcName>
|
||||
*/
|
||||
Cofree(
|
||||
Ast.Head(
|
||||
Token.lift(()),
|
||||
Chain(
|
||||
ModuleExpr(
|
||||
word = ModuleExpr.Word[Id](Id(ModuleExpr.Word.Kind.Aqua)),
|
||||
name = Ability[Id]("TestModule"),
|
||||
declareAll = None,
|
||||
declareNames = Nil,
|
||||
declareCustom = Nil
|
||||
),
|
||||
Chain(
|
||||
Cofree(
|
||||
ExportExpr(NonEmptyList.of(exp)),
|
||||
Chain.empty.pure
|
||||
ExportExpr(NonEmptyList.of(exp))
|
||||
)
|
||||
).pure
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,9 @@ class SemanticsSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
|
||||
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)(
|
||||
test: PartialFunction[
|
||||
(
|
||||
@ -41,7 +44,7 @@ class SemanticsSpec extends AnyFlatSpec with Matchers with Inside {
|
||||
),
|
||||
Any
|
||||
]
|
||||
): Unit = inside(parser(script)) { case Validated.Valid(ast) =>
|
||||
): Unit = inside(parser(addAqua(script))) { case Validated.Valid(ast) =>
|
||||
val init = RawContext.blank.copy(
|
||||
parts = Chain
|
||||
.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 =
|
||||
inside(parser(script)) { case Validated.Valid(ast) =>
|
||||
inside(parser(addAqua(script))) { case Validated.Valid(ast) =>
|
||||
val init = RawContext.blank
|
||||
inside(semantics.process(ast, init).value.value) { case Left(errors) =>
|
||||
test(errors)
|
||||
|
@ -1,9 +1,9 @@
|
||||
package aqua.types
|
||||
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import cats.data.NonEmptyMap
|
||||
import cats.syntax.partialOrder._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class IntersectTypesSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
package aqua.types
|
||||
|
||||
import cats.syntax.partialOrder._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import cats.syntax.partialOrder._
|
||||
|
||||
class UniteTypesSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user