From 7afc96112b56499c92dcaeace0750583c947037a Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 23 Jan 2022 02:23:30 +0100 Subject: [PATCH] now correctly requires using & (address-of) when assigning the address of a label or subroutine, used to generate invalid code when it was omitted --- .../compiler/astprocessing/AstChecker.kt | 2 +- compiler/test/TestAstChecks.kt | 26 +++++++++++++++++++ .../prog8/ast/expressions/AstExpressions.kt | 1 - docs/source/todo.rst | 2 +- examples/test.p8 | 12 +++++++-- 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index ae1ede7d1..2db3c8c0d 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -497,7 +497,7 @@ internal class AstChecker(private val program: Program, val sourceDatatype = assignment.value.inferType(program) if (sourceDatatype.isUnknown) { 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 { checkAssignmentCompatible(targetDatatype.getOr(DataType.BYTE), sourceDatatype.getOr(DataType.BYTE), assignment.value) diff --git a/compiler/test/TestAstChecks.kt b/compiler/test/TestAstChecks.kt index dad3afbc0..8c8e9532f 100644 --- a/compiler/test/TestAstChecks.kt +++ b/compiler/test/TestAstChecks.kt @@ -5,6 +5,7 @@ import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldContain import prog8.codegen.target.C64Target import prog8tests.helpers.ErrorReporterForTests +import prog8tests.helpers.assertFailure import prog8tests.helpers.assertSuccess import prog8tests.helpers.compileText @@ -30,4 +31,29 @@ class TestAstChecks: FunSpec({ errors.warnings[0] 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" + } }) diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 497c55ef2..8cf270e14 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -896,7 +896,6 @@ data class IdentifierReference(val nameInSource: List, override val posi override fun inferType(program: Program): InferredTypes.InferredType { return when (val targetStmt = targetStatement(program)) { is VarDecl -> InferredTypes.knownFor(targetStmt.datatype) - is Label -> InferredTypes.InferredType.known(DataType.UWORD) else -> InferredTypes.InferredType.unknown() } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index c70b607b1..53c792054 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- Fix: uword addr = label ; addr will be 0! required to use &label! - Fix compiler stack overflow crash: sub sprite_y_for_row(ubyte row) -> word { return (8-row as byte) @@ -44,6 +43,7 @@ Blocked by an official Commander-x16 r39 release 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) - 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 diff --git a/examples/test.p8 b/examples/test.p8 index cb9f40973..22fe9c3d9 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -3,7 +3,15 @@ main { sub start() { - uword @shared qq = $2ff33 - cx16.r0 = $1fc0f + +label: + uword @shared addr + addr = label + addr = thing + addr = &label + addr = &thing + } + + sub thing() { } }