mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 22:50:18 +00:00
throw an error if assign to a variable result of a function that returns nothing. refactoring (#174)
This commit is contained in:
parent
8586d70364
commit
896cf7a228
@ -9,12 +9,13 @@ import aqua.semantics.rules.ValuesAlgebra
|
||||
import aqua.semantics.rules.abilities.AbilitiesAlgebra
|
||||
import aqua.semantics.rules.names.NamesAlgebra
|
||||
import aqua.semantics.rules.types.TypesAlgebra
|
||||
import aqua.types.{ArrowType, ScalarType, StreamType, Type}
|
||||
import aqua.types.{ArrowType, StreamType, Type}
|
||||
import cats.Traverse
|
||||
import cats.free.Free
|
||||
import cats.syntax.apply._
|
||||
import cats.syntax.flatMap._
|
||||
import cats.syntax.functor._
|
||||
import cats.syntax.traverse._
|
||||
|
||||
class CallArrowSem[F[_]](val expr: CallArrowExpr[F]) extends AnyVal {
|
||||
|
||||
@ -57,37 +58,47 @@ class CallArrowSem[F[_]](val expr: CallArrowExpr[F]) extends AnyVal {
|
||||
case (Some(at), Some(sid)) =>
|
||||
Option(at -> sid) // Here we assume that Ability is a Service that must be resolved
|
||||
case _ => None
|
||||
}.flatMap(_.fold(Free.pure[Alg, Option[FuncOp]](None)) { case (arrowType, serviceId) =>
|
||||
checkArgsRes(arrowType).map {
|
||||
case (argsResolved, t) =>
|
||||
Option(
|
||||
FuncOp.leaf(
|
||||
CallServiceTag(
|
||||
serviceId = serviceId,
|
||||
funcName = funcName.value,
|
||||
Call(argsResolved, (variable.map(_.value), t).mapN(Call.Export))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
case _ => None
|
||||
|
||||
}
|
||||
})
|
||||
}.flatMap(_.map { case (arrowType, serviceId) =>
|
||||
callServiceTag(arrowType, Option(serviceId))
|
||||
}.traverse(identity))
|
||||
case None =>
|
||||
N.readArrow(funcName)
|
||||
.flatMap(_.fold(Free.pure[Alg, Option[FuncOp]](None)) { arrowType =>
|
||||
checkArgsRes(arrowType).map { case (argsResolved, t) =>
|
||||
FuncOp.leaf(
|
||||
.flatMap(_.map { arrowType =>
|
||||
callServiceTag(arrowType, None)
|
||||
}.traverse(identity))
|
||||
}
|
||||
|
||||
def callServiceTag[Alg[_]](arrowType: ArrowType, serviceId: Option[ValueModel])(implicit
|
||||
N: NamesAlgebra[F, Alg],
|
||||
A: AbilitiesAlgebra[F, Alg],
|
||||
T: TypesAlgebra[F, Alg],
|
||||
V: ValuesAlgebra[F, Alg]
|
||||
): Free[Alg, FuncOp] = {
|
||||
checkArgsRes(arrowType).flatMap { case (argsResolved, tOp) =>
|
||||
((variable, tOp) match {
|
||||
case (Some(v), Some(t)) =>
|
||||
Free.pure[Alg, Option[Call.Export]](Option(Call.Export(v.value, t)))
|
||||
case (Some(v), None) =>
|
||||
T.expectNoExport(v).map(_ => None)
|
||||
case _ =>
|
||||
Free.pure[Alg, Option[Call.Export]](None)
|
||||
|
||||
}).map(call =>
|
||||
FuncOp.leaf(serviceId match {
|
||||
case Some(sid) =>
|
||||
CallServiceTag(
|
||||
serviceId = sid,
|
||||
funcName = funcName.value,
|
||||
Call(argsResolved, call)
|
||||
)
|
||||
case None =>
|
||||
CallArrowTag(
|
||||
funcName = funcName.value,
|
||||
Call(argsResolved, (variable.map(_.value), t).mapN(Call.Export))
|
||||
Call(argsResolved, call)
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
.map(Option(_))
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
def program[Alg[_]](implicit
|
||||
|
@ -1,7 +1,7 @@
|
||||
package aqua.semantics.rules.types
|
||||
|
||||
import aqua.model.LambdaModel
|
||||
import aqua.parser.lexer.{ArrowTypeToken, CustomTypeToken, LambdaOp, Name, Token, TypeToken}
|
||||
import aqua.parser.lexer._
|
||||
import aqua.types.{ArrowType, Type}
|
||||
import cats.data.NonEmptyMap
|
||||
|
||||
@ -23,5 +23,7 @@ case class ResolveLambda[F[_]](root: Type, ops: List[LambdaOp[F]])
|
||||
case class EnsureTypeMatches[F[_]](token: Token[F], expected: Type, given: Type)
|
||||
extends TypeOp[F, Boolean]
|
||||
|
||||
case class ExpectNoExport[F[_]](token: Token[F]) extends TypeOp[F, Unit]
|
||||
|
||||
case class CheckArgumentsNum[F[_]](token: Token[F], expected: Int, given: Int)
|
||||
extends TypeOp[F, Boolean]
|
||||
|
@ -1,7 +1,7 @@
|
||||
package aqua.semantics.rules.types
|
||||
|
||||
import aqua.model.LambdaModel
|
||||
import aqua.parser.lexer.{ArrowTypeToken, CustomTypeToken, LambdaOp, Name, Token, TypeToken}
|
||||
import aqua.parser.lexer._
|
||||
import aqua.types.{ArrowType, Type}
|
||||
import cats.InjectK
|
||||
import cats.data.NonEmptyMap
|
||||
@ -36,6 +36,9 @@ class TypesAlgebra[F[_], Alg[_]](implicit T: InjectK[TypeOp[F, *], Alg]) {
|
||||
def ensureTypeMatches(token: Token[F], expected: Type, given: Type): Free[Alg, Boolean] =
|
||||
Free.liftInject[Alg](EnsureTypeMatches[F](token, expected, given))
|
||||
|
||||
def expectNoExport(token: Token[F]): Free[Alg, Unit] =
|
||||
Free.liftInject[Alg](ExpectNoExport[F](token))
|
||||
|
||||
def checkArgumentsNumber(token: Token[F], expected: Int, given: Int): Free[Alg, Boolean] =
|
||||
Free.liftInject[Alg](CheckArgumentsNum(token, expected, given))
|
||||
}
|
||||
|
@ -1,15 +1,14 @@
|
||||
package aqua.semantics.rules.types
|
||||
|
||||
import aqua.semantics.rules.ReportError
|
||||
import aqua.parser.lexer.Token
|
||||
|
||||
import aqua.semantics.rules.ReportError
|
||||
import aqua.types.{ArrowType, ProductType}
|
||||
import cats.data.Validated.{Invalid, Valid}
|
||||
import cats.data.{NonEmptyMap, State}
|
||||
import cats.syntax.flatMap._
|
||||
import cats.syntax.functor._
|
||||
import cats.~>
|
||||
import monocle.Lens
|
||||
import cats.syntax.functor._
|
||||
import cats.syntax.flatMap._
|
||||
|
||||
import scala.collection.immutable.SortedMap
|
||||
|
||||
@ -105,6 +104,12 @@ class TypesInterpreter[F[_], X](implicit lens: Lens[X, TypesState[F]], error: Re
|
||||
report(etm.token, s"Types mismatch, expected: ${etm.expected}, given: ${etm.`given`}")
|
||||
.as(false)
|
||||
|
||||
case ene: ExpectNoExport[F] =>
|
||||
report(
|
||||
ene.token,
|
||||
"Types mismatch. Cannot assign to a variable the result of a call that returns nothing"
|
||||
).as(())
|
||||
|
||||
case ca: CheckArgumentsNum[F] =>
|
||||
if (ca.expected == ca.given) State.pure(true)
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user