mirror of
https://github.com/fluencelabs/aqua.git
synced 2025-04-25 15:02:14 +00:00
108 option type (#146)
* Option type support: arguments, values * Aqua version 0.1.4 * Fix for optional return value in TS * Tiny fixes * Example for declaring local options
This commit is contained in:
parent
d1e76c1fd3
commit
807c26619f
@ -13,7 +13,13 @@ service Test("test"):
|
|||||||
getUserList: -> []User
|
getUserList: -> []User
|
||||||
doSomething: -> bool
|
doSomething: -> bool
|
||||||
|
|
||||||
func betterMessage(relay: string, arr: []string) -> string:
|
func include(opt: ?string) -> string:
|
||||||
|
Peer.is_connected(opt!)
|
||||||
|
for i <- opt:
|
||||||
|
Peer.is_connected(i)
|
||||||
|
<- opt!
|
||||||
|
|
||||||
|
func betterMessage(relay: string, arr: []string, opt: ?string, str: *string) -> ?string:
|
||||||
on relay:
|
on relay:
|
||||||
Peer.is_connected("something")
|
Peer.is_connected("something")
|
||||||
par isOnline <- Peer.is_connected(relay)
|
par isOnline <- Peer.is_connected(relay)
|
||||||
@ -22,10 +28,16 @@ func betterMessage(relay: string, arr: []string) -> string:
|
|||||||
|
|
||||||
stream: *string
|
stream: *string
|
||||||
|
|
||||||
|
localOpt: ?string
|
||||||
|
|
||||||
if isOnline:
|
if isOnline:
|
||||||
try:
|
try:
|
||||||
Test.doSomething()
|
Test.doSomething()
|
||||||
else:
|
else:
|
||||||
Peer.is_connected(stream!)
|
Peer.is_connected(stream!)
|
||||||
|
|
||||||
<- stream!2
|
x <- include(arr)
|
||||||
|
y <- include(opt)
|
||||||
|
localOpt <- include(str)
|
||||||
|
|
||||||
|
<- opt
|
@ -3,7 +3,7 @@ package aqua.backend.air
|
|||||||
import aqua.model._
|
import aqua.model._
|
||||||
import aqua.model.func.Call
|
import aqua.model.func.Call
|
||||||
import aqua.model.func.body._
|
import aqua.model.func.body._
|
||||||
import aqua.types.StreamType
|
import aqua.types.{OptionType, StreamType}
|
||||||
import cats.Eval
|
import cats.Eval
|
||||||
import cats.data.Chain
|
import cats.data.Chain
|
||||||
import cats.free.Cofree
|
import cats.free.Cofree
|
||||||
@ -30,6 +30,7 @@ object AirGen {
|
|||||||
case VarModel(name, t, lambda) =>
|
case VarModel(name, t, lambda) =>
|
||||||
val n = t match {
|
val n = t match {
|
||||||
case _: StreamType => "$" + name
|
case _: StreamType => "$" + name
|
||||||
|
case _: OptionType => "$" + name
|
||||||
case _ => name
|
case _ => name
|
||||||
}
|
}
|
||||||
if (lambda.isEmpty) DataView.Variable(n)
|
if (lambda.isEmpty) DataView.Variable(n)
|
||||||
|
@ -18,16 +18,25 @@ case class TypescriptFunc(func: FuncCallable) {
|
|||||||
|
|
||||||
val tsAir = FuncAirGen(func).generateClientAir(conf)
|
val tsAir = FuncAirGen(func).generateClientAir(conf)
|
||||||
|
|
||||||
val returnCallback = func.ret.as {
|
val returnCallback = func.ret.map(_._2).map {
|
||||||
s"""h.onEvent('${conf.callbackService}', '${conf.respFuncName}', (args) => {
|
case OptionType(_) =>
|
||||||
| const [res] = args;
|
s"""h.onEvent('${conf.callbackService}', '${conf.respFuncName}', (args) => {
|
||||||
| resolve(res);
|
| const [res] = args;
|
||||||
|});
|
| resolve(res.length === 0 ? null : res[0]);
|
||||||
|""".stripMargin
|
|});
|
||||||
|
|""".stripMargin
|
||||||
|
case _ =>
|
||||||
|
s"""h.onEvent('${conf.callbackService}', '${conf.respFuncName}', (args) => {
|
||||||
|
| const [res] = args;
|
||||||
|
| resolve(res);
|
||||||
|
|});
|
||||||
|
|""".stripMargin
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val setCallbacks = func.args.args.map {
|
val setCallbacks = func.args.args.map {
|
||||||
|
case ArgDef.Data(argName, OptionType(_)) =>
|
||||||
|
s"""h.on('${conf.getDataService}', '$argName', () => {return $argName === null ? [] : [$argName];});"""
|
||||||
case ArgDef.Data(argName, _) =>
|
case ArgDef.Data(argName, _) =>
|
||||||
s"""h.on('${conf.getDataService}', '$argName', () => {return $argName;});"""
|
s"""h.on('${conf.getDataService}', '$argName', () => {return $argName;});"""
|
||||||
case ArgDef.Arrow(argName, at) =>
|
case ArgDef.Arrow(argName, at) =>
|
||||||
@ -88,6 +97,7 @@ case class TypescriptFunc(func: FuncCallable) {
|
|||||||
object TypescriptFunc {
|
object TypescriptFunc {
|
||||||
|
|
||||||
def typeToTs(t: Type): String = t match {
|
def typeToTs(t: Type): String = t match {
|
||||||
|
case OptionType(t) => typeToTs(t) + " | null"
|
||||||
case ArrayType(t) => typeToTs(t) + "[]"
|
case ArrayType(t) => typeToTs(t) + "[]"
|
||||||
case StreamType(t) => typeToTs(t) + "[]"
|
case StreamType(t) => typeToTs(t) + "[]"
|
||||||
case pt: ProductType =>
|
case pt: ProductType =>
|
||||||
|
20
build.sbt
20
build.sbt
@ -1,32 +1,32 @@
|
|||||||
val dottyVersion = "2.13.5"
|
val dottyVersion = "2.13.5"
|
||||||
|
|
||||||
//val dottyVersion = "3.0.0-RC3"
|
//val dottyVersion = "3.0.0"
|
||||||
|
|
||||||
scalaVersion := dottyVersion
|
scalaVersion := dottyVersion
|
||||||
|
|
||||||
val baseAquaVersion = settingKey[String]("base aqua version")
|
val baseAquaVersion = settingKey[String]("base aqua version")
|
||||||
|
|
||||||
val catsV = "2.6.0"
|
val catsV = "2.6.1"
|
||||||
val catsParseV = "0.3.3"
|
val catsParseV = "0.3.4"
|
||||||
val monocleV = "3.0.0-M5"
|
val monocleV = "3.0.0-M5"
|
||||||
val scalaTestV = "3.2.7" // TODO update version for scala 3-RC3
|
val scalaTestV = "3.2.9"
|
||||||
val fs2V = "3.0.2"
|
val fs2V = "3.0.4"
|
||||||
val catsEffectV = "3.1.0"
|
val catsEffectV = "3.1.1"
|
||||||
val airframeLogV = "21.5.4"
|
val airframeLogV = "21.5.4"
|
||||||
val log4catsV = "2.1.1"
|
val log4catsV = "2.1.1"
|
||||||
val enumeratumV = "1.6.1"
|
val enumeratumV = "1.6.1" // Scala3 issue: https://github.com/lloydmeta/enumeratum/issues/300
|
||||||
val slf4jV = "1.7.25"
|
val slf4jV = "1.7.30"
|
||||||
val declineV = "2.0.0-RC1" // Scala3 issue: https://github.com/bkirwi/decline/issues/260
|
val declineV = "2.0.0-RC1" // Scala3 issue: https://github.com/bkirwi/decline/issues/260
|
||||||
val declineEnumV = "1.3.0"
|
val declineEnumV = "1.3.0"
|
||||||
|
|
||||||
name := "aqua-hll"
|
name := "aqua-hll"
|
||||||
|
|
||||||
val commons = Seq(
|
val commons = Seq(
|
||||||
baseAquaVersion := "0.1.3",
|
baseAquaVersion := "0.1.4",
|
||||||
version := baseAquaVersion.value + "-" + sys.env.getOrElse("BUILD_NUMBER", "SNAPSHOT"),
|
version := baseAquaVersion.value + "-" + sys.env.getOrElse("BUILD_NUMBER", "SNAPSHOT"),
|
||||||
scalaVersion := dottyVersion,
|
scalaVersion := dottyVersion,
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"org.typelevel" %% "log4cats-core" % "2.1.1",
|
"org.typelevel" %% "log4cats-core" % log4catsV,
|
||||||
"org.scalatest" %% "scalatest" % scalaTestV % Test
|
"org.scalatest" %% "scalatest" % scalaTestV % Test
|
||||||
),
|
),
|
||||||
addCompilerPlugin("org.typelevel" %% "kind-projector" % "0.11.3" cross CrossVersion.full)
|
addCompilerPlugin("org.typelevel" %% "kind-projector" % "0.11.3" cross CrossVersion.full)
|
||||||
|
@ -10,6 +10,11 @@ object FuncOps {
|
|||||||
def noop(peerId: ValueModel): FuncOp =
|
def noop(peerId: ValueModel): FuncOp =
|
||||||
FuncOp.leaf(CallServiceTag(LiteralModel.quote("op"), "identity", Call(Nil, None), Some(peerId)))
|
FuncOp.leaf(CallServiceTag(LiteralModel.quote("op"), "identity", Call(Nil, None), Some(peerId)))
|
||||||
|
|
||||||
|
def identity(what: ValueModel, to: Call.Export): FuncOp =
|
||||||
|
FuncOp.leaf(
|
||||||
|
CallServiceTag(LiteralModel.quote("op"), "identity", Call(what :: Nil, Some(to)), None)
|
||||||
|
)
|
||||||
|
|
||||||
def callService(srvId: ValueModel, funcName: String, call: Call): FuncOp =
|
def callService(srvId: ValueModel, funcName: String, call: Call): FuncOp =
|
||||||
FuncOp.leaf(
|
FuncOp.leaf(
|
||||||
CallServiceTag(
|
CallServiceTag(
|
||||||
@ -48,4 +53,13 @@ object FuncOps {
|
|||||||
|
|
||||||
def xor(left: FuncOp, right: FuncOp): FuncOp =
|
def xor(left: FuncOp, right: FuncOp): FuncOp =
|
||||||
FuncOp.node(XorTag, Chain(left, right))
|
FuncOp.node(XorTag, Chain(left, right))
|
||||||
|
|
||||||
|
def fold(item: String, iter: ValueModel, op: FuncOp): FuncOp =
|
||||||
|
FuncOp.wrap(
|
||||||
|
ForTag(item, iter),
|
||||||
|
op
|
||||||
|
)
|
||||||
|
|
||||||
|
def next(item: String): FuncOp =
|
||||||
|
FuncOp.leaf(NextTag(item))
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package aqua.model.transform
|
package aqua.model.transform
|
||||||
|
|
||||||
import aqua.model.ValueModel
|
import aqua.model.{ValueModel, VarModel}
|
||||||
import aqua.model.func.Call
|
import aqua.model.func.Call
|
||||||
import aqua.model.func.body.{FuncOp, FuncOps}
|
import aqua.model.func.body.{FuncOp, FuncOps}
|
||||||
import aqua.types.DataType
|
import aqua.types.{ArrayType, DataType, OptionType, StreamType, Type}
|
||||||
|
import cats.data.Chain
|
||||||
|
|
||||||
trait ArgsProvider {
|
trait ArgsProvider {
|
||||||
def transform(op: FuncOp): FuncOp
|
def transform(op: FuncOp): FuncOp
|
||||||
@ -12,12 +13,39 @@ trait ArgsProvider {
|
|||||||
case class ArgsFromService(dataServiceId: ValueModel, names: List[(String, DataType)])
|
case class ArgsFromService(dataServiceId: ValueModel, names: List[(String, DataType)])
|
||||||
extends ArgsProvider {
|
extends ArgsProvider {
|
||||||
|
|
||||||
def getDataOp(name: String, t: DataType): FuncOp =
|
private def getDataElOp(name: String, t: DataType, el: Type): FuncOp = {
|
||||||
FuncOps.callService(
|
val iter = s"$name-iter"
|
||||||
dataServiceId,
|
val item = s"$name-item"
|
||||||
name,
|
FuncOps.seq(
|
||||||
Call(Nil, Some(Call.Export(name, t)))
|
FuncOps.callService(
|
||||||
|
dataServiceId,
|
||||||
|
name,
|
||||||
|
Call(Nil, Some(Call.Export(iter, t)))
|
||||||
|
),
|
||||||
|
FuncOps.fold(
|
||||||
|
item,
|
||||||
|
VarModel(iter, ArrayType(el), Chain.empty),
|
||||||
|
FuncOps.seq(
|
||||||
|
FuncOps.identity(VarModel(item, el), Call.Export(name, t)),
|
||||||
|
FuncOps.next(item)
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
def getDataOp(name: String, t: DataType): FuncOp =
|
||||||
|
t match {
|
||||||
|
case StreamType(el) =>
|
||||||
|
getDataElOp(name, t, el)
|
||||||
|
case OptionType(el) =>
|
||||||
|
getDataElOp(name, StreamType(el), el)
|
||||||
|
case _ =>
|
||||||
|
FuncOps.callService(
|
||||||
|
dataServiceId,
|
||||||
|
name,
|
||||||
|
Call(Nil, Some(Call.Export(name, t)))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
def transform(op: FuncOp): FuncOp =
|
def transform(op: FuncOp): FuncOp =
|
||||||
FuncOps.seq(
|
FuncOps.seq(
|
||||||
|
@ -29,6 +29,18 @@ object StreamTypeToken {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case class OptionTypeToken[F[_]: Comonad](override val unit: F[Unit], data: DataTypeToken[F])
|
||||||
|
extends DataTypeToken[F] {
|
||||||
|
override def as[T](v: T): F[T] = unit.as(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
object OptionTypeToken {
|
||||||
|
|
||||||
|
def `optiontypedef`[F[_]: LiftParser: Comonad]: P[OptionTypeToken[F]] =
|
||||||
|
(`?`.lift ~ DataTypeToken.`datatypedef`[F]).map(ud => OptionTypeToken(ud._1, ud._2))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
case class CustomTypeToken[F[_]: Comonad](name: F[String]) extends DataTypeToken[F] {
|
case class CustomTypeToken[F[_]: Comonad](name: F[String]) extends DataTypeToken[F] {
|
||||||
override def as[T](v: T): F[T] = name.as(v)
|
override def as[T](v: T): F[T] = name.as(v)
|
||||||
|
|
||||||
@ -94,7 +106,9 @@ object DataTypeToken {
|
|||||||
|
|
||||||
def `datatypedef`[F[_]: LiftParser: Comonad]: P[DataTypeToken[F]] =
|
def `datatypedef`[F[_]: LiftParser: Comonad]: P[DataTypeToken[F]] =
|
||||||
P.oneOf(
|
P.oneOf(
|
||||||
P.defer(`arraytypedef`[F]) :: P.defer(StreamTypeToken.`streamtypedef`) :: BasicTypeToken
|
P.defer(`arraytypedef`[F]) :: P.defer(StreamTypeToken.`streamtypedef`) :: P.defer(
|
||||||
|
OptionTypeToken.`optiontypedef`
|
||||||
|
) :: BasicTypeToken
|
||||||
.`basictypedef`[F] :: CustomTypeToken.ct[F] :: Nil
|
.`basictypedef`[F] :: CustomTypeToken.ct[F] :: Nil
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import aqua.parser.expr.DeclareStreamExpr
|
|||||||
import aqua.semantics.Prog
|
import aqua.semantics.Prog
|
||||||
import aqua.semantics.rules.names.NamesAlgebra
|
import aqua.semantics.rules.names.NamesAlgebra
|
||||||
import aqua.semantics.rules.types.TypesAlgebra
|
import aqua.semantics.rules.types.TypesAlgebra
|
||||||
import aqua.types.{ArrayType, StreamType}
|
import aqua.types.{ArrayType, OptionType, StreamType}
|
||||||
import cats.free.Free
|
import cats.free.Free
|
||||||
|
|
||||||
class DeclareStreamSem[F[_]](val expr: DeclareStreamExpr[F]) {
|
class DeclareStreamSem[F[_]](val expr: DeclareStreamExpr[F]) {
|
||||||
@ -19,6 +19,8 @@ class DeclareStreamSem[F[_]](val expr: DeclareStreamExpr[F]) {
|
|||||||
.flatMap {
|
.flatMap {
|
||||||
case Some(t: StreamType) =>
|
case Some(t: StreamType) =>
|
||||||
N.define(expr.name, t)
|
N.define(expr.name, t)
|
||||||
|
case Some(t: OptionType) =>
|
||||||
|
N.define(expr.name, StreamType(t.element))
|
||||||
case Some(at @ ArrayType(t)) =>
|
case Some(at @ ArrayType(t)) =>
|
||||||
T.ensureTypeMatches(expr.`type`, StreamType(t), at)
|
T.ensureTypeMatches(expr.`type`, StreamType(t), at)
|
||||||
case Some(t) =>
|
case Some(t) =>
|
||||||
|
@ -7,7 +7,7 @@ import aqua.semantics.Prog
|
|||||||
import aqua.semantics.rules.ValuesAlgebra
|
import aqua.semantics.rules.ValuesAlgebra
|
||||||
import aqua.semantics.rules.names.NamesAlgebra
|
import aqua.semantics.rules.names.NamesAlgebra
|
||||||
import aqua.semantics.rules.types.TypesAlgebra
|
import aqua.semantics.rules.types.TypesAlgebra
|
||||||
import aqua.types.{ArrayType, StreamType, Type}
|
import aqua.types.{ArrayType, BoxType}
|
||||||
import cats.data.Chain
|
import cats.data.Chain
|
||||||
import cats.free.Free
|
import cats.free.Free
|
||||||
import cats.syntax.flatMap._
|
import cats.syntax.flatMap._
|
||||||
@ -24,10 +24,8 @@ class ForSem[F[_]](val expr: ForExpr[F]) extends AnyVal {
|
|||||||
N.beginScope(expr.item) >> V.valueToModel(expr.iterable).flatMap[Option[ValueModel]] {
|
N.beginScope(expr.item) >> V.valueToModel(expr.iterable).flatMap[Option[ValueModel]] {
|
||||||
case Some(vm) =>
|
case Some(vm) =>
|
||||||
vm.lastType match {
|
vm.lastType match {
|
||||||
case at @ ArrayType(t) =>
|
case t: BoxType =>
|
||||||
N.define(expr.item, t).as(Option(vm))
|
N.define(expr.item, t.element).as(Option(vm))
|
||||||
case st @ StreamType(t) =>
|
|
||||||
N.define(expr.item, t).as(Option(vm))
|
|
||||||
case dt =>
|
case dt =>
|
||||||
T.ensureTypeMatches(expr.iterable, ArrayType(dt), dt).as(Option.empty[ValueModel])
|
T.ensureTypeMatches(expr.iterable, ArrayType(dt), dt).as(Option.empty[ValueModel])
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,12 @@ import aqua.parser.lexer.{
|
|||||||
IntoIndex,
|
IntoIndex,
|
||||||
LambdaOp,
|
LambdaOp,
|
||||||
Name,
|
Name,
|
||||||
|
OptionTypeToken,
|
||||||
StreamTypeToken,
|
StreamTypeToken,
|
||||||
Token,
|
Token,
|
||||||
TypeToken
|
TypeToken
|
||||||
}
|
}
|
||||||
import aqua.types.{ArrayType, ArrowType, DataType, ProductType, StreamType, Type}
|
import aqua.types.{ArrayType, ArrowType, DataType, OptionType, ProductType, StreamType, Type}
|
||||||
import cats.data.Validated.{Invalid, Valid}
|
import cats.data.Validated.{Invalid, Valid}
|
||||||
import cats.data.{Chain, NonEmptyChain, ValidatedNec}
|
import cats.data.{Chain, NonEmptyChain, ValidatedNec}
|
||||||
import cats.kernel.Monoid
|
import cats.kernel.Monoid
|
||||||
@ -37,6 +38,10 @@ case class TypesState[F[_]](
|
|||||||
resolveTypeToken(dtt).collect { case it: DataType =>
|
resolveTypeToken(dtt).collect { case it: DataType =>
|
||||||
StreamType(it)
|
StreamType(it)
|
||||||
}
|
}
|
||||||
|
case OptionTypeToken(_, dtt) =>
|
||||||
|
resolveTypeToken(dtt).collect { case it: DataType =>
|
||||||
|
OptionType(it)
|
||||||
|
}
|
||||||
case ctt: CustomTypeToken[F] => strict.get(ctt.value)
|
case ctt: CustomTypeToken[F] => strict.get(ctt.value)
|
||||||
case btt: BasicTypeToken[F] => Some(btt.value)
|
case btt: BasicTypeToken[F] => Some(btt.value)
|
||||||
case ArrowTypeToken(_, args, res) =>
|
case ArrowTypeToken(_, args, res) =>
|
||||||
@ -99,7 +104,15 @@ case class TypesState[F[_]](
|
|||||||
resolveOps(intern, tail).map(IntoIndexModel(i.value, intern) :: _)
|
resolveOps(intern, tail).map(IntoIndexModel(i.value, intern) :: _)
|
||||||
case StreamType(intern) =>
|
case StreamType(intern) =>
|
||||||
resolveOps(intern, tail).map(IntoIndexModel(i.value, intern) :: _)
|
resolveOps(intern, tail).map(IntoIndexModel(i.value, intern) :: _)
|
||||||
case _ => Left(i -> s"Expected $rootT to be an array")
|
case OptionType(intern) =>
|
||||||
|
i.value match {
|
||||||
|
case 0 =>
|
||||||
|
resolveOps(intern, tail).map(IntoIndexModel(i.value, intern) :: _)
|
||||||
|
case _ =>
|
||||||
|
Left(i -> s"Option might have only one element, use ! to get it")
|
||||||
|
}
|
||||||
|
|
||||||
|
case _ => Left(i -> s"Expected $rootT to be an array or a stream")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,10 +83,18 @@ object LiteralType {
|
|||||||
val string = LiteralType(Set(ScalarType.string), "string")
|
val string = LiteralType(Set(ScalarType.string), "string")
|
||||||
}
|
}
|
||||||
|
|
||||||
case class ArrayType(element: Type) extends DataType {
|
sealed trait BoxType extends DataType {
|
||||||
|
def element: Type
|
||||||
|
}
|
||||||
|
|
||||||
|
case class ArrayType(element: Type) extends BoxType {
|
||||||
override def toString: String = "[]" + element
|
override def toString: String = "[]" + element
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case class OptionType(element: Type) extends BoxType {
|
||||||
|
override def toString: String = "?" + element
|
||||||
|
}
|
||||||
|
|
||||||
case class ProductType(name: String, fields: NonEmptyMap[String, Type]) extends DataType {
|
case class ProductType(name: String, fields: NonEmptyMap[String, Type]) extends DataType {
|
||||||
|
|
||||||
override def toString: String =
|
override def toString: String =
|
||||||
@ -104,7 +112,7 @@ case class ArrowType(args: List[Type], res: Option[Type]) extends Type {
|
|||||||
args.map(_.toString).mkString(", ") + " -> " + res.map(_.toString).getOrElse("()")
|
args.map(_.toString).mkString(", ") + " -> " + res.map(_.toString).getOrElse("()")
|
||||||
}
|
}
|
||||||
|
|
||||||
case class StreamType(element: Type) extends DataType
|
case class StreamType(element: Type) extends BoxType
|
||||||
|
|
||||||
object Type {
|
object Type {
|
||||||
import Double.NaN
|
import Double.NaN
|
||||||
@ -149,6 +157,9 @@ object Type {
|
|||||||
case (x: ScalarType, LiteralType(ys, _)) if ys(x) => 1.0
|
case (x: ScalarType, LiteralType(ys, _)) if ys(x) => 1.0
|
||||||
case (x: ArrayType, y: ArrayType) => cmp(x.element, y.element)
|
case (x: ArrayType, y: ArrayType) => cmp(x.element, y.element)
|
||||||
case (x: ArrayType, y: StreamType) => cmp(x.element, y.element)
|
case (x: ArrayType, y: StreamType) => cmp(x.element, y.element)
|
||||||
|
case (x: ArrayType, y: OptionType) => cmp(x.element, y.element)
|
||||||
|
case (x: OptionType, y: StreamType) => cmp(x.element, y.element)
|
||||||
|
case (x: OptionType, y: ArrayType) => cmp(x.element, y.element)
|
||||||
case (x: StreamType, y: StreamType) => cmp(x.element, y.element)
|
case (x: StreamType, y: StreamType) => cmp(x.element, y.element)
|
||||||
case (ProductType(_, xFields), ProductType(_, yFields)) =>
|
case (ProductType(_, xFields), ProductType(_, yFields)) =>
|
||||||
cmpProd(xFields, yFields)
|
cmpProd(xFields, yFields)
|
||||||
|
@ -12,6 +12,8 @@ class TypeSpec extends AnyFlatSpec with Matchers {
|
|||||||
import aqua.types.ScalarType._
|
import aqua.types.ScalarType._
|
||||||
|
|
||||||
def `[]`(t: DataType): DataType = ArrayType(t)
|
def `[]`(t: DataType): DataType = ArrayType(t)
|
||||||
|
def `?`(t: DataType): DataType = OptionType(t)
|
||||||
|
def `*`(t: DataType): DataType = StreamType(t)
|
||||||
|
|
||||||
def accepts(recv: Type, incoming: Type) =
|
def accepts(recv: Type, incoming: Type) =
|
||||||
recv >= incoming
|
recv >= incoming
|
||||||
@ -103,4 +105,13 @@ class TypeSpec extends AnyFlatSpec with Matchers {
|
|||||||
accepts(stream, stream) should be(true)
|
accepts(stream, stream) should be(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"streams" should "be accepted as an option, but not vice versa" in {
|
||||||
|
val stream: Type = StreamType(bool)
|
||||||
|
val opt: Type = OptionType(bool)
|
||||||
|
|
||||||
|
accepts(opt, stream) should be(true)
|
||||||
|
accepts(stream, opt) should be(false)
|
||||||
|
accepts(opt, opt) should be(true)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user