mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 14:40:17 +00:00
Bug fix (#198)
This commit is contained in:
parent
83d5a7b2a3
commit
f455716548
@ -1,34 +0,0 @@
|
||||
service OpH("op"):
|
||||
puk(s: string) -> string
|
||||
pek(s: string, -- trgtr
|
||||
c: string) -> string
|
||||
pyk: []u32 -> string
|
||||
pok: []bool -> string
|
||||
identity: ⊤ -> ⊥
|
||||
|
||||
func a( -- ferkjn
|
||||
b: string, -- fr
|
||||
c: string, -- asdf
|
||||
g: string
|
||||
) -> string: -- rgtr
|
||||
|
||||
try:
|
||||
f = "world"
|
||||
OpH "planet"
|
||||
OpH.pek("TRY THIS", -- gtrg
|
||||
c)
|
||||
catch err:
|
||||
OpH.puk(err.msg)
|
||||
<- f
|
||||
-- hello
|
||||
|
||||
func z(t: ?string, b: []u32, c: *bool):
|
||||
OpH.puk(t!)
|
||||
OpH.pyk(b)
|
||||
OpH.pok(c)
|
||||
c <- OpH.identity(true)
|
||||
c <- OpH.identity("string")
|
||||
|
||||
|
||||
func k():
|
||||
z(nil, nil, nil)
|
11
aqua-src/test.aqua
Normal file
11
aqua-src/test.aqua
Normal file
@ -0,0 +1,11 @@
|
||||
service OpH("op"):
|
||||
get_str(s: string) -> string
|
||||
get_arr() -> []string
|
||||
identity: ⊤ -> ⊥
|
||||
|
||||
func registerKeyPutValue(node_id: string) -> []string:
|
||||
nodes <- OpH.get_arr()
|
||||
for n <- nodes par:
|
||||
on n:
|
||||
OpH.get_str(node_id)
|
||||
<- nodes
|
@ -1,62 +0,0 @@
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class Test1 extends AnyFlatSpec with Matchers {
|
||||
"test" should "run" in {
|
||||
|
||||
import cats.parse.{Parser0 ⇒ P0, Parser => P, Numbers}
|
||||
/*
|
||||
|
||||
def getTime(peer: PeerId, reply: i64 -> string) -> string =
|
||||
on peer:
|
||||
t <- Peer.timestamp()
|
||||
reply(t)
|
||||
|
||||
Scope(Var("peer"), List(
|
||||
Fetch(
|
||||
Var("t"),
|
||||
AbilityCall(
|
||||
CustomType("Peer"),
|
||||
FnName("timestamp"),
|
||||
Nil
|
||||
)
|
||||
)
|
||||
)),
|
||||
Unscoped(
|
||||
FuncCall("reply", List(Var("t"))
|
||||
)
|
||||
|
||||
(seq
|
||||
(call %init_peer_id% ("load" "peer") [] peer)
|
||||
(seq
|
||||
(call peer ("peer" "timestamp") [] t)
|
||||
(call %init_peer_id% ("callback" "reply") [t]) ;; if used in fetch, then put return value
|
||||
)
|
||||
)
|
||||
;; register peer value
|
||||
;; register reply callback
|
||||
|
||||
code block:
|
||||
free variables
|
||||
free functions
|
||||
new variables
|
||||
scope?
|
||||
|
||||
THEN name, types -- maybe bind free to types
|
||||
|
||||
|
||||
line variants:
|
||||
func(...)
|
||||
x <- func(...)
|
||||
Ability.func(...)
|
||||
x <- Ability.func(...)
|
||||
|
||||
par line
|
||||
xor line
|
||||
|
||||
on peer:
|
||||
indented lines*
|
||||
|
||||
*/
|
||||
}
|
||||
}
|
@ -32,8 +32,8 @@ object PathFinder extends LogSupport {
|
||||
findPath(
|
||||
fromOn,
|
||||
toOn,
|
||||
Chain.fromOption(from.currentPeerId),
|
||||
Chain.fromOption(to.currentPeerId)
|
||||
from.currentPeerId,
|
||||
to.currentPeerId
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -49,6 +49,10 @@ object PathFinder extends LogSupport {
|
||||
case (acc, p) if acc.contains(p) => acc.takeWhile(_ != p) :+ p
|
||||
case (acc, p) => acc :+ p
|
||||
}
|
||||
trace(s"PEER IDS: $optimized")
|
||||
trace(s"PREFIX: $prefix")
|
||||
trace(s"SUFFIX: $suffix")
|
||||
trace(s"OPTIMIZED WITH PREFIX AND SUFFIX: $optimized")
|
||||
val noPrefix = skipPrefix(optimized, prefix, optimized)
|
||||
skipSuffix(noPrefix, suffix, noPrefix)
|
||||
}
|
||||
@ -56,19 +60,30 @@ object PathFinder extends LogSupport {
|
||||
def findPath(
|
||||
fromOn: Chain[OnTag],
|
||||
toOn: Chain[OnTag],
|
||||
fromPeer: Chain[ValueModel],
|
||||
toPeer: Chain[ValueModel]
|
||||
fromPeer: Option[ValueModel],
|
||||
toPeer: Option[ValueModel]
|
||||
): Chain[ValueModel] = {
|
||||
trace(s"FROM ON: $fromOn")
|
||||
trace(s"TO ON: $toOn")
|
||||
|
||||
val (from, to) = skipCommonPrefix(fromOn, toOn)
|
||||
val fromFix =
|
||||
if (from.isEmpty && fromPeer != toPeer) Chain.fromOption(fromOn.lastOption) else from
|
||||
val toFix = if (to.isEmpty && fromPeer != toPeer) Chain.fromOption(toOn.lastOption) else to
|
||||
val fromTo = fromFix.reverse.flatMap(_.via.reverse) ++ toFix.flatMap(_.via)
|
||||
val optimized = optimizePath(fromPeer ++ fromTo ++ toPeer, fromPeer, toPeer)
|
||||
|
||||
trace("FIND PATH " + fromFix)
|
||||
trace(" -> " + toFix)
|
||||
trace(s"$fromPeer $toPeer")
|
||||
trace("FIND PATH FROM | " + fromFix)
|
||||
trace(" TO | " + toFix)
|
||||
|
||||
val fromTo = fromFix.reverse.flatMap(_.via.reverse) ++ toFix.flatMap(_.via)
|
||||
trace(s"FROM TO: $fromTo")
|
||||
|
||||
val fromPeerCh = Chain.fromOption(fromPeer)
|
||||
val toPeerCh = Chain.fromOption(toPeer)
|
||||
val optimized = optimizePath(fromPeerCh ++ fromTo ++ toPeerCh, fromPeerCh, toPeerCh)
|
||||
|
||||
trace(
|
||||
s"FROM PEER '${fromPeer.map(_.toString).getOrElse("None")}' TO PEER '${toPeer.map(_.toString).getOrElse("None")}'"
|
||||
)
|
||||
trace(" Optimized: " + optimized)
|
||||
optimized
|
||||
}
|
||||
|
@ -127,27 +127,26 @@ case class RawCursor(tree: NonEmptyList[ChainZipper[FuncOp.Tree]])
|
||||
}
|
||||
|
||||
def cata[A](wrap: ChainZipper[Cofree[Chain, A]] => Chain[Cofree[Chain, A]])(
|
||||
f: RawCursor => OptionT[Eval, ChainZipper[Cofree[Chain, A]]]
|
||||
folder: RawCursor => OptionT[Eval, ChainZipper[Cofree[Chain, A]]]
|
||||
): Eval[Chain[Cofree[Chain, A]]] =
|
||||
f(this).map { case ChainZipper(prev, curr, next) =>
|
||||
val inner = curr.copy(tail =
|
||||
Eval
|
||||
.later(
|
||||
Chain.fromSeq(
|
||||
toFirstChild
|
||||
.map(fc =>
|
||||
LazyList
|
||||
.unfold(fc) { _.toNextSibling.map(c => c -> c) }
|
||||
.prepended(fc)
|
||||
)
|
||||
.getOrElse(LazyList.empty)
|
||||
folder(this).map { case ChainZipper(prev, curr, next) =>
|
||||
val tail = Eval.later {
|
||||
Chain.fromSeq(
|
||||
toFirstChild
|
||||
.map(folderCursor =>
|
||||
LazyList
|
||||
.unfold(folderCursor) { _.toNextSibling.map(cursor => cursor -> cursor) }
|
||||
.prepended(folderCursor)
|
||||
)
|
||||
)
|
||||
// TODO: this can be parallelized
|
||||
.flatMap(_.traverse(_.cata(wrap)(f)))
|
||||
.map(_.flatMap(identity))
|
||||
.flatMap(addition => curr.tail.map(_ ++ addition))
|
||||
)
|
||||
.getOrElse(LazyList.empty)
|
||||
)
|
||||
}
|
||||
// TODO: this can be parallelized
|
||||
.flatMap(_.traverse(_.cata(wrap)(folder)))
|
||||
.map(_.flatMap(identity))
|
||||
.flatMap(addition => curr.tail.map(_ ++ addition))
|
||||
|
||||
val inner = curr.copy(tail = tail)
|
||||
wrap(ChainZipper(prev, inner, next))
|
||||
}.getOrElse(Chain.empty).memoize
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package aqua.model.func.resolved
|
||||
|
||||
import aqua.model.func.Call
|
||||
import aqua.model.topology.Topology.Res
|
||||
import aqua.model.{LiteralModel, ValueModel}
|
||||
import cats.Eval
|
||||
import cats.data.Chain
|
||||
@ -8,24 +9,24 @@ import cats.free.Cofree
|
||||
|
||||
object MakeRes {
|
||||
val nilTail: Eval[Chain[Cofree[Chain, ResolvedOp]]] = Eval.now(Chain.empty)
|
||||
type Cof = Cofree[Chain, ResolvedOp]
|
||||
def leaf(op: ResolvedOp): Cof = Cofree[Chain, ResolvedOp](op, nilTail)
|
||||
|
||||
def next(item: String): Cof =
|
||||
def leaf(op: ResolvedOp): Res = Cofree[Chain, ResolvedOp](op, nilTail)
|
||||
|
||||
def next(item: String): Res =
|
||||
leaf(NextRes(item))
|
||||
|
||||
def seq(first: Cof, second: Cof, more: Cof*): Cof =
|
||||
def seq(first: Res, second: Res, more: Res*): Res =
|
||||
Cofree[Chain, ResolvedOp](SeqRes, Eval.later(first +: second +: Chain.fromSeq(more)))
|
||||
|
||||
def par(first: Cof, second: Cof, more: Cof*): Cof =
|
||||
def par(first: Res, second: Res, more: Res*): Res =
|
||||
Cofree[Chain, ResolvedOp](ParRes, Eval.later(first +: second +: Chain.fromSeq(more)))
|
||||
|
||||
def xor(first: Cof, second: Cof): Cof =
|
||||
def xor(first: Res, second: Res): Res =
|
||||
Cofree[Chain, ResolvedOp](XorRes, Eval.later(Chain(first, second)))
|
||||
|
||||
def fold(item: String, iter: ValueModel, body: Cof): Cof =
|
||||
def fold(item: String, iter: ValueModel, body: Res): Res =
|
||||
Cofree[Chain, ResolvedOp](FoldRes(item, iter), Eval.now(Chain.one(body)))
|
||||
|
||||
def noop(onPeer: ValueModel): Cof =
|
||||
def noop(onPeer: ValueModel): Res =
|
||||
leaf(CallServiceRes(LiteralModel.quote("op"), "noop", Call(Nil, None), onPeer))
|
||||
}
|
||||
|
@ -1,26 +1,27 @@
|
||||
package aqua.model.topology
|
||||
|
||||
import aqua.model.{LiteralModel, ValueModel, VarModel}
|
||||
import aqua.model.func.raw._
|
||||
import cats.Eval
|
||||
import cats.data.{Chain, NonEmptyChain, NonEmptyList, OptionT}
|
||||
import cats.data.Chain.nil
|
||||
import cats.free.Cofree
|
||||
import aqua.model.cursor.ChainZipper
|
||||
import aqua.model.func.raw._
|
||||
import aqua.model.func.resolved._
|
||||
import aqua.model.{LiteralModel, ValueModel, VarModel}
|
||||
import aqua.types.{BoxType, ScalarType}
|
||||
import wvlet.log.LogSupport
|
||||
import cats.Eval
|
||||
import cats.data.Chain.nil
|
||||
import cats.data.{Chain, NonEmptyChain, NonEmptyList, OptionT}
|
||||
import cats.free.Cofree
|
||||
import cats.syntax.traverse._
|
||||
import wvlet.log.LogSupport
|
||||
|
||||
object Topology extends LogSupport {
|
||||
type Tree = Cofree[Chain, RawTag]
|
||||
type Res = Cofree[Chain, ResolvedOp]
|
||||
|
||||
def resolve(op: Tree): Res =
|
||||
def resolve(op: Tree): Res = {
|
||||
val resolved = resolveOnMoves(op).value
|
||||
Cofree
|
||||
.cata[Chain, ResolvedOp, Res](resolveOnMoves(op).value) {
|
||||
.cata[Chain, ResolvedOp, Res](resolved) {
|
||||
case (SeqRes, children) =>
|
||||
Eval.later(
|
||||
Eval.later {
|
||||
children.uncons
|
||||
.filter(_._2.isEmpty)
|
||||
.map(_._1)
|
||||
@ -33,10 +34,11 @@ object Topology extends LogSupport {
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
case (head, children) => Eval.later(Cofree(head, Eval.now(children)))
|
||||
}
|
||||
.value
|
||||
}
|
||||
|
||||
def wrap(cz: ChainZipper[Res]): Chain[Res] =
|
||||
Chain.one(
|
||||
@ -44,60 +46,64 @@ object Topology extends LogSupport {
|
||||
else cz.current
|
||||
)
|
||||
|
||||
def resolveOnMoves(op: Tree): Eval[Res] =
|
||||
RawCursor(NonEmptyList.one(ChainZipper.one(op)))
|
||||
private def rawToResolved(
|
||||
currentPeerId: Option[ValueModel]
|
||||
): PartialFunction[RawTag, ResolvedOp] = {
|
||||
case SeqTag => SeqRes
|
||||
case _: OnTag => SeqRes
|
||||
case MatchMismatchTag(a, b, s) => MatchMismatchRes(a, b, s)
|
||||
case ForTag(item, iter) => FoldRes(item, iter)
|
||||
case ParTag | ParTag.Detach => ParRes
|
||||
case XorTag | XorTag.LeftBiased => XorRes
|
||||
case NextTag(item) => NextRes(item)
|
||||
case CallServiceTag(serviceId, funcName, call) =>
|
||||
CallServiceRes(
|
||||
serviceId,
|
||||
funcName,
|
||||
call,
|
||||
currentPeerId
|
||||
.getOrElse(LiteralModel.initPeerId)
|
||||
)
|
||||
}
|
||||
|
||||
def resolveOnMoves(op: Tree): Eval[Res] = {
|
||||
val cursor = RawCursor(NonEmptyList.one(ChainZipper.one(op)))
|
||||
val resolvedCofree = cursor
|
||||
.cata(wrap) { rc =>
|
||||
debug(s"<:> $rc")
|
||||
OptionT[Eval, ChainZipper[Res]](
|
||||
({
|
||||
case SeqTag => SeqRes
|
||||
case _: OnTag => SeqRes
|
||||
case MatchMismatchTag(a, b, s) => MatchMismatchRes(a, b, s)
|
||||
case ForTag(item, iter) => FoldRes(item, iter)
|
||||
case ParTag | ParTag.Detach => ParRes
|
||||
case XorTag | XorTag.LeftBiased => XorRes
|
||||
case NextTag(item) => NextRes(item)
|
||||
case CallServiceTag(serviceId, funcName, call) =>
|
||||
CallServiceRes(
|
||||
serviceId,
|
||||
funcName,
|
||||
call,
|
||||
rc.currentPeerId
|
||||
.getOrElse(LiteralModel.initPeerId)
|
||||
)
|
||||
}: PartialFunction[RawTag, ResolvedOp]).lift
|
||||
.apply(rc.tag)
|
||||
.map(MakeRes.leaf)
|
||||
.traverse(c =>
|
||||
Eval.later {
|
||||
val cz = ChainZipper(
|
||||
through(rc.pathFromPrev),
|
||||
c,
|
||||
through(rc.pathToNext)
|
||||
)
|
||||
if (cz.next.nonEmpty || cz.prev.nonEmpty) {
|
||||
debug(s"Resolved $rc -> $c")
|
||||
if (cz.prev.nonEmpty)
|
||||
trace("From prev: " + cz.prev.map(_.head).toList.mkString(" -> "))
|
||||
if (cz.next.nonEmpty)
|
||||
trace("To next: " + cz.next.map(_.head).toList.mkString(" -> "))
|
||||
} else debug(s"EMPTY $rc -> $c")
|
||||
cz
|
||||
}
|
||||
val resolved = rawToResolved(rc.currentPeerId).lift
|
||||
.apply(rc.tag)
|
||||
.map(MakeRes.leaf)
|
||||
val chainZipperEv = resolved.traverse(cofree =>
|
||||
Eval.later {
|
||||
val cz = ChainZipper(
|
||||
through(rc.pathFromPrev),
|
||||
cofree,
|
||||
through(rc.pathToNext)
|
||||
)
|
||||
if (cz.next.nonEmpty || cz.prev.nonEmpty) {
|
||||
debug(s"Resolved $rc -> $cofree")
|
||||
if (cz.prev.nonEmpty)
|
||||
trace("From prev: " + cz.prev.map(_.head).toList.mkString(" -> "))
|
||||
if (cz.next.nonEmpty)
|
||||
trace("To next: " + cz.next.map(_.head).toList.mkString(" -> "))
|
||||
} else debug(s"EMPTY $rc -> $cofree")
|
||||
cz
|
||||
}
|
||||
)
|
||||
OptionT[Eval, ChainZipper[Res]](chainZipperEv)
|
||||
}
|
||||
|
||||
}
|
||||
.map(NonEmptyChain.fromChain(_).map(_.uncons))
|
||||
.map {
|
||||
case None =>
|
||||
error("Topology emitted nothing")
|
||||
Cofree(SeqRes, MakeRes.nilTail)
|
||||
case Some((el, `nil`)) => el
|
||||
case Some((el, tail)) =>
|
||||
warn("Topology emitted many nodes, that's unusual")
|
||||
Cofree(SeqRes, Eval.now(el +: tail))
|
||||
}
|
||||
resolvedCofree.map(NonEmptyChain.fromChain(_).map(_.uncons)).map {
|
||||
case None =>
|
||||
error("Topology emitted nothing")
|
||||
Cofree(SeqRes, MakeRes.nilTail)
|
||||
case Some((el, `nil`)) => el
|
||||
case Some((el, tail)) =>
|
||||
warn("Topology emitted many nodes, that's unusual")
|
||||
Cofree(SeqRes, Eval.now(el +: tail))
|
||||
}
|
||||
}
|
||||
|
||||
// Walks through peer IDs, doing a noop function on each
|
||||
// If same IDs are found in a row, does noop only once
|
||||
|
@ -1,13 +1,11 @@
|
||||
package aqua.model.transform
|
||||
|
||||
import aqua.model.{ValueModel, VarModel}
|
||||
import aqua.model.func.{ArgDef, ArgsCall, ArgsDef, Call, FuncCallable}
|
||||
import aqua.model.func.raw.{FuncOp, FuncOps}
|
||||
import aqua.model.func._
|
||||
import aqua.model.{ValueModel, VarModel}
|
||||
import aqua.types.ArrowType
|
||||
import cats.Eval
|
||||
import cats.syntax.apply._
|
||||
import cats.syntax.functor._
|
||||
import wvlet.log.Logger
|
||||
|
||||
case class ResolveFunc(
|
||||
transform: FuncOp => FuncOp,
|
||||
@ -17,9 +15,6 @@ case class ResolveFunc(
|
||||
arrowCallbackPrefix: String = "init_peer_callable_"
|
||||
) {
|
||||
|
||||
private val logger = Logger.of[ResolveFunc]
|
||||
import logger._
|
||||
|
||||
def returnCallback(retModel: ValueModel): FuncOp =
|
||||
callback(
|
||||
respFuncName,
|
||||
|
@ -323,7 +323,6 @@ class TopologySpec extends AnyFlatSpec with Matchers {
|
||||
}
|
||||
|
||||
"topology resolver" should "get back to init peer after a long chain" in {
|
||||
|
||||
val init = on(
|
||||
initPeer,
|
||||
relay :: Nil,
|
||||
|
@ -45,6 +45,7 @@ object Token {
|
||||
val `co`: P[Unit] = P.string("co")
|
||||
val `:` : P[Unit] = P.char(':')
|
||||
val ` : ` : P[Unit] = P.char(':').surroundedBy(` `.?)
|
||||
val `anum_*` : P[Unit] = P.charsWhile(anum_).void
|
||||
|
||||
val `name`: P[String] = (P.charIn(az) ~ P.charsWhile(anum_).?).string
|
||||
|
||||
@ -55,7 +56,7 @@ object Token {
|
||||
val `--` : P[Unit] = ` `.?.with1 *> P.string("--") <* ` `.?
|
||||
|
||||
val ` \n` : P[Unit] =
|
||||
(` `.?.void *> (`--` *> P.charsWhile(_ != '\n')).?.void).with1 *> `\n`
|
||||
(` `.?.void *> (`--` *> P.charsWhile0(_ != '\n')).?.void).with1 *> `\n`
|
||||
|
||||
val ` \n+` : P[Unit] = P.repAs[Unit, Unit](` \n`.backtrack, 1)(Accumulator0.unitAccumulator0)
|
||||
val ` : \n+` : P[Unit] = ` `.?.with1 *> `:` *> ` \n+`
|
||||
|
@ -4,10 +4,10 @@ import aqua.parser.lexer.Token._
|
||||
import aqua.parser.lift.LiftParser
|
||||
import aqua.parser.lift.LiftParser._
|
||||
import aqua.types.LiteralType
|
||||
import cats.{Comonad, Functor}
|
||||
import cats.parse.{Numbers, Parser => P}
|
||||
import cats.syntax.functor._
|
||||
import cats.syntax.comonad._
|
||||
import cats.syntax.functor._
|
||||
import cats.{Comonad, Functor}
|
||||
|
||||
sealed trait Value[F[_]] extends Token[F]
|
||||
|
||||
@ -32,7 +32,7 @@ object Value {
|
||||
P.oneOf(
|
||||
("true" :: "false" :: Nil)
|
||||
.map(t ⇒ P.string(t).lift.map(fu => Literal(fu.as(t), LiteralType.bool)))
|
||||
)
|
||||
) <* P.not(`anum_*`)
|
||||
|
||||
def initPeerId[F[_]: LiftParser: Comonad]: P[Literal[F]] =
|
||||
`%init_peer_id%`.string.lift.map(Literal(_, LiteralType.string))
|
||||
@ -57,7 +57,7 @@ object Value {
|
||||
.map(Literal(_, LiteralType.string))
|
||||
|
||||
def literal[F[_]: LiftParser: Comonad]: P[Literal[F]] =
|
||||
P.oneOf(bool :: float.backtrack :: num :: string :: Nil)
|
||||
P.oneOf(bool.backtrack :: float.backtrack :: num.backtrack :: string :: Nil)
|
||||
|
||||
def `value`[F[_]: LiftParser: Comonad]: P[Value[F]] =
|
||||
P.oneOf(literal.backtrack :: initPeerId.backtrack :: varLambda :: Nil)
|
||||
|
@ -2,8 +2,7 @@ package aqua.parser
|
||||
|
||||
import aqua.AquaSpec
|
||||
import aqua.parser.expr.ArrowTypeExpr
|
||||
import aqua.types.ScalarType.string
|
||||
import aqua.types.ScalarType.u32
|
||||
import aqua.types.ScalarType.{string, u32}
|
||||
import cats.Id
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
@ -21,6 +20,10 @@ class ArrowTypeExprSpec extends AnyFlatSpec with Matchers with AquaSpec {
|
||||
ArrowTypeExpr[Id]("onIn", toArrowType(List("Custom"), Some("Custom2")))
|
||||
)
|
||||
|
||||
parseArrow("onIn(a: Custom, b: Custom2)") should be(
|
||||
ArrowTypeExpr[Id]("onIn", toArrowType(List("Custom", "Custom2"), None))
|
||||
)
|
||||
|
||||
parseArrow("onIn: Custom, string, u32, Custom3 -> Custom2") should be(
|
||||
ArrowTypeExpr[Id](
|
||||
"onIn",
|
||||
|
@ -1,12 +1,12 @@
|
||||
package aqua.parser.lexer
|
||||
|
||||
import org.scalatest.EitherValues
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import aqua.parser.lift.LiftParser.Implicits.idLiftParser
|
||||
import aqua.types.ScalarType
|
||||
import aqua.types.ScalarType.u32
|
||||
import cats.Id
|
||||
import org.scalatest.EitherValues
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
@ -27,6 +27,11 @@ class TypeTokenSpec extends AnyFlatSpec with Matchers with EitherValues {
|
||||
ArrowTypeToken.`arrowdef`.parseAll("A -> B").right.value should be(
|
||||
ArrowTypeToken[Id]((), CustomTypeToken[Id]("A") :: Nil, Some(CustomTypeToken[Id]("B")))
|
||||
)
|
||||
|
||||
ArrowTypeToken.`arrowWithNames`.parseAll("(a: A) -> B").right.value should be(
|
||||
ArrowTypeToken[Id]((), CustomTypeToken[Id]("A") :: Nil, Some(CustomTypeToken[Id]("B")))
|
||||
)
|
||||
|
||||
ArrowTypeToken.`arrowdef`.parseAll("u32 -> Boo").right.value should be(
|
||||
ArrowTypeToken[Id]((), (u32: BasicTypeToken[Id]) :: Nil, Some(CustomTypeToken[Id]("Boo")))
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user