type error tweaks

This commit is contained in:
Irmen de Jong 2023-12-26 18:49:01 +01:00
parent 7530f4407b
commit ffdc658dc8
8 changed files with 58 additions and 41 deletions

View File

@ -160,7 +160,8 @@ val ElementToArrayTypes = mapOf(
DataType.WORD to DataType.ARRAY_W, DataType.WORD to DataType.ARRAY_W,
DataType.UWORD to DataType.ARRAY_UW, DataType.UWORD to DataType.ARRAY_UW,
DataType.FLOAT to DataType.ARRAY_F, DataType.FLOAT to DataType.ARRAY_F,
DataType.BOOL to DataType.ARRAY_BOOL DataType.BOOL to DataType.ARRAY_BOOL,
DataType.STR to DataType.UWORD // array of str is just an array of pointers
) )
val Cx16VirtualRegisters = arrayOf( val Cx16VirtualRegisters = arrayOf(

View File

@ -514,10 +514,6 @@ internal class AstChecker(private val program: Program,
if(assignment.target.identifier?.targetStatement(program)!=null) if(assignment.target.identifier?.targetStatement(program)!=null)
errors.err("target datatype is unknown", assignment.target.position) errors.err("target datatype is unknown", assignment.target.position)
// otherwise, another error about missing symbol is already reported. // otherwise, another error about missing symbol is already reported.
} else {
// allow bitwise operations on different types as long as the size is the same
if (!((assignment.value as? BinaryExpression)?.operator in BitwiseOperators && targetDt.isBytes && valueDt.isBytes || targetDt.isWords && valueDt.isWords))
errors.err("type of value $valueDt doesn't match target $targetDt", assignment.value.position)
} }
} }
} }
@ -1369,7 +1365,6 @@ internal class AstChecker(private val program: Program,
if(target.value is StringLiteral) { if(target.value is StringLiteral) {
// check string lengths for non-memory mapped strings // check string lengths for non-memory mapped strings
val stringLen = (target.value as StringLiteral).value.length val stringLen = (target.value as StringLiteral).value.length
val index = arrayIndexedExpression.indexer.constIndex()
if (index != null && (index < 0 || index >= stringLen)) if (index != null && (index < 0 || index >= stringLen))
errors.err("index out of bounds", arrayIndexedExpression.indexer.position) errors.err("index out of bounds", arrayIndexedExpression.indexer.position)
} }

View File

@ -283,9 +283,10 @@ internal class StatementReorderer(
} else { } else {
if (sourceVar.arraysize!!.constIndex() != targetVar.arraysize!!.constIndex()) if (sourceVar.arraysize!!.constIndex() != targetVar.arraysize!!.constIndex())
errors.err("element count mismatch", assign.position) errors.err("element count mismatch", assign.position)
if (sourceVar.datatype != targetVar.datatype) { val sourceEltDt = ArrayToElementTypes.getValue(sourceVar.datatype)
if(!targetVar.splitArray || (sourceVar.datatype!=DataType.ARRAY_W && sourceVar.datatype!=DataType.ARRAY_UW)) val targetEltDt = ArrayToElementTypes.getValue(targetVar.datatype)
errors.err("element type mismatch", assign.position) if (!sourceEltDt.equalsSize(targetEltDt)) {
errors.err("element size mismatch", assign.position)
} }
} }

View File

@ -525,9 +525,8 @@ class TestOptimization: FunSpec({
""" """
val errors = ErrorReporterForTests() val errors = ErrorReporterForTests()
compileText(C64Target(), optimize=false, src, writeAssembly=false, errors = errors) shouldBe null compileText(C64Target(), optimize=false, src, writeAssembly=false, errors = errors) shouldBe null
errors.errors.size shouldBe 2 errors.errors.size shouldBe 1
errors.errors[0] shouldContain "type of value WORD doesn't match target UBYTE" errors.errors[0] shouldContain "out of range"
errors.errors[1] shouldContain "out of range"
} }
test("out of range cast should give error") { test("out of range cast should give error") {

View File

@ -1062,12 +1062,11 @@ main {
}""" }"""
val errors=ErrorReporterForTests() val errors=ErrorReporterForTests()
compileText(C64Target(), false, src, writeAssembly = false, errors=errors) shouldBe null compileText(C64Target(), false, src, writeAssembly = false, errors=errors) shouldBe null
errors.errors.size shouldBe 5 errors.errors.size shouldBe 4
errors.errors[0] shouldContain "no cast" errors.errors[0] shouldContain "no cast"
errors.errors[1] shouldContain "overflow" errors.errors[1] shouldContain "overflow"
errors.errors[2] shouldContain "LONG doesn't match" errors.errors[2] shouldContain "out of range"
errors.errors[3] shouldContain "out of range" errors.errors[3] shouldContain "overflow"
errors.errors[4] shouldContain "overflow"
} }
}) })

View File

@ -6,7 +6,6 @@ import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldContain import io.kotest.matchers.string.shouldContain
import prog8.code.target.C64Target import prog8.code.target.C64Target
import prog8.code.target.VMTarget import prog8.code.target.VMTarget
import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.compileText import prog8tests.helpers.compileText
import kotlin.io.path.readText import kotlin.io.path.readText
@ -94,23 +93,33 @@ main {
} }
test("split only for word arrays") { test("split only for word arrays") {
val text = """ val srcGood = """
main { main {
ubyte[10] @split sb
uword[10] @split sw uword[10] @split sw
word[10] @split sw2 word[10] @split sw2
sub start() {
}
}"""
compileText(C64Target(), false, srcGood, writeAssembly = false) shouldNotBe null
val srcWrong1 = """
main {
ubyte[10] @split sb
sub start() {
}
}"""
compileText(C64Target(), false, srcWrong1, writeAssembly = false) shouldBe null
val srcWrong2 = """
main {
float[10] @split sf float[10] @split sf
sub start() { sub start() {
} }
}""" }"""
val errors = ErrorReporterForTests() compileText(C64Target(), false, srcWrong2, writeAssembly = false) shouldBe null
compileText(C64Target(), false, text, writeAssembly = false, errors = errors) shouldBe null
errors.errors.size shouldBe 2
errors.errors.forEach {
it shouldContain "split"
it shouldContain "word arrays"
}
} }
test("split word arrays in asm as lsb/msb") { test("split word arrays in asm as lsb/msb") {
@ -141,8 +150,9 @@ main {
str name1 = "name1" str name1 = "name1"
str name2 = "name2" str name2 = "name2"
uword[] @split names = [name1, name2, "name3"] uword[] @split names = [name1, name2, "name3"]
cx16.r0++ uword[] addresses = [0,0,0]
names = [1111,2222,3333] names = [1111,2222,3333]
addresses = names
} }
}""" }"""
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null

View File

@ -2,6 +2,7 @@
TODO TODO
==== ====
- get rid of vardecl.declareddatatype
- get rid of memory mapped variables: treat them as syntactic sugar for a poke/peek to the symbol. - get rid of memory mapped variables: treat them as syntactic sugar for a poke/peek to the symbol.
- add -nowarnunused, or %option ignore_unused (module and block scope), to suppress all warnings about unused symbols. Useful in libraries. - add -nowarnunused, or %option ignore_unused (module and block scope), to suppress all warnings about unused symbols. Useful in libraries.

View File

@ -4,22 +4,33 @@
main { main {
sub start() { sub start() {
sys.push(11) uword zz
sys.pushw(2222) word zz2
floats.push(floats.π) ubyte bb
cx16.r2++ byte bb2
float pi = floats.pop() bb2 |= bb
floats.print_f(pi) bb2 |= zz2
txt.nl()
cx16.r1 = sys.popw() ; uword[20] @split foobar
cx16.r0L = sys.pop() ; ubyte[20] @split foobar2
;
txt.print_ub(cx16.r0L) ; sys.push(11)
txt.nl() ; sys.pushw(2222)
txt.print_uw(cx16.r1) ; floats.push(floats.π)
txt.nl() ; cx16.r2++
;
; float pi = floats.pop()
; floats.print_f(pi)
; txt.nl()
;
; cx16.r1 = sys.popw()
; cx16.r0L = sys.pop()
;
; txt.print_ub(cx16.r0L)
; txt.nl()
; txt.print_uw(cx16.r1)
; txt.nl()
} }
} }