1
0
mirror of https://github.com/irmen/prog8.git synced 2025-02-17 13:31:01 +00:00

now correctly requires using & (address-of) when assigning the address of a label or subroutine, used to generate invalid code when it was omitted

This commit is contained in:
Irmen de Jong 2022-01-23 02:23:30 +01:00
parent 7bb41a30ed
commit 7afc96112b
5 changed files with 38 additions and 5 deletions
compiler
src/prog8/compiler/astprocessing
test
compilerAst/src/prog8/ast/expressions
docs/source
examples

@ -497,7 +497,7 @@ internal class AstChecker(private val program: Program,
val sourceDatatype = assignment.value.inferType(program) val sourceDatatype = assignment.value.inferType(program)
if (sourceDatatype.isUnknown) { if (sourceDatatype.isUnknown) {
if (assignment.value !is FunctionCallExpression) if (assignment.value !is FunctionCallExpression)
errors.err("assignment value is invalid or has no proper datatype", assignment.value.position) errors.err("assignment value is invalid or has no proper datatype, maybe forgot '&' (address-of)", assignment.value.position)
} else { } else {
checkAssignmentCompatible(targetDatatype.getOr(DataType.BYTE), checkAssignmentCompatible(targetDatatype.getOr(DataType.BYTE),
sourceDatatype.getOr(DataType.BYTE), assignment.value) sourceDatatype.getOr(DataType.BYTE), assignment.value)

@ -5,6 +5,7 @@ import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain import io.kotest.matchers.string.shouldContain
import prog8.codegen.target.C64Target import prog8.codegen.target.C64Target
import prog8tests.helpers.ErrorReporterForTests import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.assertFailure
import prog8tests.helpers.assertSuccess import prog8tests.helpers.assertSuccess
import prog8tests.helpers.compileText import prog8tests.helpers.compileText
@ -30,4 +31,29 @@ class TestAstChecks: FunSpec({
errors.warnings[0] shouldContain "converted to float" errors.warnings[0] shouldContain "converted to float"
errors.warnings[1] shouldContain "converted to float" errors.warnings[1] shouldContain "converted to float"
} }
test("can't assign label or subroutine without using address-of") {
val text = """
main {
sub start() {
label:
uword @shared addr
addr = label
addr = thing
addr = &label
addr = &thing
}
sub thing() {
}
}
"""
val errors = ErrorReporterForTests()
compileText(C64Target, true, text, writeAssembly = true, errors=errors).assertFailure()
errors.errors.size shouldBe 2
errors.warnings.size shouldBe 0
errors.errors[0] shouldContain ":7:28) assignment value is invalid"
errors.errors[1] shouldContain ":8:28) assignment value is invalid"
}
}) })

@ -896,7 +896,6 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
override fun inferType(program: Program): InferredTypes.InferredType { override fun inferType(program: Program): InferredTypes.InferredType {
return when (val targetStmt = targetStatement(program)) { return when (val targetStmt = targetStatement(program)) {
is VarDecl -> InferredTypes.knownFor(targetStmt.datatype) is VarDecl -> InferredTypes.knownFor(targetStmt.datatype)
is Label -> InferredTypes.InferredType.known(DataType.UWORD)
else -> InferredTypes.InferredType.unknown() else -> InferredTypes.InferredType.unknown()
} }
} }

@ -3,7 +3,6 @@ TODO
For next release For next release
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
- Fix: uword addr = label ; addr will be 0! required to use &label!
- Fix compiler stack overflow crash: - Fix compiler stack overflow crash:
sub sprite_y_for_row(ubyte row) -> word { sub sprite_y_for_row(ubyte row) -> word {
return (8-row as byte) return (8-row as byte)
@ -44,6 +43,7 @@ Blocked by an official Commander-x16 r39 release
Future Things and Ideas Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
- Fix: don't report as recursion if code assign address of its own subroutine to something, rather than calling it
- allow "xxx" * constexpr (where constexpr is not a number literal, now gives expression error not same type) - allow "xxx" * constexpr (where constexpr is not a number literal, now gives expression error not same type)
- can we promise a left-to-right function call argument evaluation? without sacrificing performance - can we promise a left-to-right function call argument evaluation? without sacrificing performance
- unify FunctioncallExpression + FunctioncallStatement and PipeExpression + Pipe statement, may require moving Expression/Statement into interfaces instead of abstract base classes - unify FunctioncallExpression + FunctioncallStatement and PipeExpression + Pipe statement, may require moving Expression/Statement into interfaces instead of abstract base classes

@ -3,7 +3,15 @@
main { main {
sub start() { sub start() {
uword @shared qq = $2ff33
cx16.r0 = $1fc0f label:
uword @shared addr
addr = label
addr = thing
addr = &label
addr = &thing
}
sub thing() {
} }
} }