add missing unit tests and type checking for 'in' expression

This commit is contained in:
Irmen de Jong 2022-01-06 00:01:49 +01:00
parent b697375573
commit 02c315c194
4 changed files with 64 additions and 12 deletions

View File

@ -1208,12 +1208,26 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(containment: ContainmentCheck) { override fun visit(containment: ContainmentCheck) {
if(!containment.iterable.inferType(program).isIterable) val elementDt = containment.element.inferType(program)
errors.err("value set for containment check must be an iterable type", containment.iterable.position) val iterableDt = containment.iterable.inferType(program)
if(containment.parent is BinaryExpression) if(containment.parent is BinaryExpression)
errors.err("containment check is currently not supported in complex expressions", containment.position) errors.err("containment check is currently not supported in complex expressions", containment.position)
// TODO check that iterable contains the same types as the element that is searched if(iterableDt.isIterable) {
val iterableEltDt = ArrayToElementTypes.getValue(iterableDt.getOr(DataType.UNDEFINED))
val invalidDt = if (elementDt.isBytes) {
iterableEltDt !in ByteDatatypes
} else if (elementDt.isWords) {
iterableEltDt !in WordDatatypes
} else {
false
}
if (invalidDt)
errors.err("element datatype doesn't match iterable datatype", containment.position)
} else {
errors.err("value set for containment check must be an iterable type", containment.iterable.position)
}
super.visit(containment) super.visit(containment)
} }

View File

@ -134,11 +134,4 @@ _after:
} }
return noModifications return noModifications
} }
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
if(expr.operator=="in") {
println("IN-TEST: $expr\n in: $parent")
}
return noModifications
}
} }

View File

@ -800,4 +800,50 @@ class TestProg8Parser: FunSpec( {
val encodedletter = Petscii.encodePetscii("A", true).getOrElse { fail("petscii error") }.single() val encodedletter = Petscii.encodePetscii("A", true).getOrElse { fail("petscii error") }.single()
letter.value shouldBe NumericLiteralValue(DataType.UBYTE, encodedletter.toDouble(), Position.DUMMY) letter.value shouldBe NumericLiteralValue(DataType.UBYTE, encodedletter.toDouble(), Position.DUMMY)
} }
test("`in` containment checks") {
val text="""
main {
sub start() {
str string = "hello"
ubyte[] array = [1,2,3,4]
ubyte cc
if cc in [' ', '@', 0] {
}
if cc in "email" {
}
cc = 99 in array
cc = '@' in string
}
}
"""
val result = compileText(C64Target, false, text, writeAssembly = false).assertSuccess()
val start = result.program.entrypoint
val containmentChecks = start.statements.takeLast(4)
(containmentChecks[0] as IfElse).condition shouldBe instanceOf<ContainmentCheck>()
(containmentChecks[1] as IfElse).condition shouldBe instanceOf<ContainmentCheck>()
(containmentChecks[2] as Assignment).value shouldBe instanceOf<ContainmentCheck>()
(containmentChecks[3] as Assignment).value shouldBe instanceOf<ContainmentCheck>()
}
test("invalid `in` containment checks") {
val text="""
main {
sub start() {
ubyte cc
ubyte[] array = [1,2,3]
cc = 99 in 12345
cc = 9999 in array
}
}
"""
val errors = ErrorReporterForTests()
compileText(C64Target, false, text, writeAssembly = false, errors = errors).assertFailure()
errors.errors.size shouldBe 2
errors.errors[0] shouldContain "must be an iterable type"
errors.errors[1] shouldContain "datatype doesn't match"
}
}) })

View File

@ -3,8 +3,7 @@ TODO
For next compiler release (7.7) For next compiler release (7.7)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- add unit tests for correctly parsing the "in" operator ...
Need help with Need help with
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^