fix(compiler): Error on not arrow call after <- (#876)

* Add error report

* Add tests
This commit is contained in:
InversionSpaces 2023-09-08 14:21:19 +02:00 committed by GitHub
parent df111adf21
commit 69a808e243
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 8 deletions

View File

@ -40,11 +40,8 @@ class CallArrowSem[S[_]](val expr: CallArrowExpr[S]) extends AnyVal {
T: TypesAlgebra[S, Alg],
V: ValuesAlgebra[S, Alg]
): Alg[Option[FuncOp]] = for {
callArrowRaw <- V.valueToRaw(callArrow).map {
// TODO: Refactor this to support other results
case Some(car: CallArrowRaw) => car.some
case _ => none
}
// TODO: Accept other expressions
callArrowRaw <- V.valueToCallArrowRaw(expr.callArrow)
maybeOp <- callArrowRaw.traverse(car =>
variables
.drop(car.baseType.codomain.length)

View File

@ -7,6 +7,7 @@ import aqua.raw.value.*
import aqua.semantics.rules.abilities.AbilitiesAlgebra
import aqua.semantics.rules.names.NamesAlgebra
import aqua.semantics.rules.types.TypesAlgebra
import aqua.semantics.rules.errors.ErrorsAlgebra
import aqua.types.*
import cats.Monad
@ -25,9 +26,10 @@ import scribe.Logging
import scala.collection.immutable.SortedMap
class ValuesAlgebra[S[_], Alg[_]: Monad](implicit
class ValuesAlgebra[S[_], Alg[_]: Monad](using
N: NamesAlgebra[S, Alg],
T: TypesAlgebra[S, Alg],
E: ErrorsAlgebra[S, Alg],
A: AbilitiesAlgebra[S, Alg]
) extends Logging {
@ -310,6 +312,15 @@ class ValuesAlgebra[S[_], Alg[_]: Monad](implicit
}
}
def valueToCallArrowRaw(v: ValueToken[S]): Alg[Option[CallArrowRaw]] =
valueToRaw(v).flatMap(
_.flatTraverse {
case ca: CallArrowRaw => ca.some.pure[Alg]
// TODO: better error message (`raw` formatting)
case raw => E.report(v, s"Expected arrow call, got $raw").as(none)
}
)
private def callArrowFromAbility(
ab: Name[S],
at: AbilityType,
@ -402,10 +413,11 @@ class ValuesAlgebra[S[_], Alg[_]: Monad](implicit
object ValuesAlgebra {
implicit def deriveValuesAlgebra[S[_], Alg[_]: Monad](implicit
given [S[_], Alg[_]: Monad](using
N: NamesAlgebra[S, Alg],
T: TypesAlgebra[S, Alg],
A: AbilitiesAlgebra[S, Alg]
A: AbilitiesAlgebra[S, Alg],
E: ErrorsAlgebra[S, Alg]
): ValuesAlgebra[S, Alg] =
new ValuesAlgebra[S, Alg]
}

View File

@ -4,4 +4,7 @@ import aqua.parser.lexer.Token
trait ErrorsAlgebra[S[_], Alg[_]] {
def report(token: Token[S], hints: List[String]): Alg[Unit]
def report(token: Token[S], hint: String): Alg[Unit] =
report(token, hint :: Nil)
}

View File

@ -611,4 +611,43 @@ class SemanticsSpec extends AnyFlatSpec with Matchers with Inside {
atLeast(1, errors.toChain.toList) shouldBe a[RulesViolated[Span.S]]
}
}
it should "forbid not arrow calls after <-" in {
def scriptPush(prefix: String, what: String) =
s"""
|func main() -> []string:
| stream: *string
|${prefix.split("\n").map(" " + _).mkString("\n")}
| stream <- $what
| <- stream
|""".stripMargin
val scriptLiteral = scriptPush("", "\"a\"")
insideSemErrors(scriptLiteral) { errors =>
atLeast(1, errors.toChain.toList) shouldBe a[RulesViolated[Span.S]]
}
val scriptVar = scriptPush(
"""
|variable = "value"
|""".stripMargin,
"variable"
)
insideSemErrors(scriptVar) { errors =>
atLeast(1, errors.toChain.toList) shouldBe a[RulesViolated[Span.S]]
}
val scriptArrayElement = scriptPush(
"""
|arr = ["a", "b", "c"]
|""".stripMargin,
"arr[0]"
)
insideSemErrors(scriptArrayElement) { errors =>
atLeast(1, errors.toChain.toList) shouldBe a[RulesViolated[Span.S]]
}
}
}