diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index d301a7d0e..2f56834db 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -599,6 +599,8 @@ internal class AstChecker(private val program: Program, } if (p.type.isPointer) { + if(p.type.sub==BaseDataType.STR) + errors.err("^^str is not a valid pointer type, use ^^ubyte?", p.position) if (p.type.subType == null && p.type.subTypeFromAntlr!=null) errors.err("cannot find struct type ${p.type.subTypeFromAntlr?.joinToString(".")}", p.position) } @@ -613,6 +615,9 @@ internal class AstChecker(private val program: Program, if(r.isStructInstance) err("structs can only be returned via a pointer") + + if(r.isPointer && r.sub==BaseDataType.STR) + err("^^str is not a valid return type, use ^^ubyte?") } } @@ -876,17 +881,22 @@ internal class AstChecker(private val program: Program, } // ARRAY without size specifier MUST have an iterable initializer value - if(decl.isArray && decl.arraysize==null) { - if(decl.type== VarDeclType.MEMORY) { - err("memory mapped array must have a size specification") - return + if (decl.isArray) { + if (decl.arraysize == null) { + if(decl.type== VarDeclType.MEMORY) { + err("memory mapped array must have a size specification") + return + } + if(decl.value==null || decl.value is NumericLiteral) { + err("array variable is missing a size specification") + return + } + if(decl.value is RangeExpression) + throw InternalCompilerException("range expressions in vardecls should have been converted into array values during constFolding $decl") } - if(decl.value==null || decl.value is NumericLiteral) { - err("array variable is missing a size specification") - return - } - if(decl.value is RangeExpression) - throw InternalCompilerException("range expressions in vardecls should have been converted into array values during constFolding $decl") + + if(decl.datatype.isPointerArray && decl.datatype.sub==BaseDataType.STR) + err("^^str is not a valid pointer type, use ^^ubyte?") } when(decl.type) { @@ -973,6 +983,9 @@ internal class AstChecker(private val program: Program, } } + if(decl.datatype.isPointer && decl.datatype.sub==BaseDataType.STR) + err("^^str is not a valid pointer type, use ^^ubyte?") + if(decl.datatype.isString) { if(decl.value==null) { // complain about uninitialized str, but only if it's a regular variable diff --git a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt index 2b30f89bd..407c57048 100644 --- a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt +++ b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt @@ -33,15 +33,6 @@ internal class CodeDesugarer(val program: Program, private val target: ICompilat return listOf(IAstModification.Remove(alias, parent as IStatementContainer)) } - override fun after(decl: VarDecl, parent: Node): Iterable { - if(decl.datatype.isPointer && decl.datatype.sub==BaseDataType.STR) { - errors.info("^^str replaced by ^^ubyte", decl.position) - val decl2 = decl.copy(DataType.pointer(BaseDataType.UBYTE)) - return listOf(IAstModification.ReplaceNode(decl, decl2, parent)) - } - return noModifications - } - override fun before(breakStmt: Break, parent: Node): Iterable { fun jumpAfter(stmt: Statement): Iterable { val label = program.makeLabel("after", breakStmt.position) @@ -731,24 +722,6 @@ _after: return noModifications } - override fun after(subroutine: Subroutine, parent: Node): Iterable { - subroutine.returntypes.withIndex().forEach { (idx, rt) -> - if(rt.isPointer && rt.sub==BaseDataType.STR) { - errors.info("^^str replaced by ^^ubyte in return type(s)", subroutine.position) - subroutine.returntypes[idx] = DataType.pointer(BaseDataType.UBYTE) - } - } - - subroutine.parameters.withIndex().forEach { (idx, param) -> - if(param.type.isPointer && param.type.sub==BaseDataType.STR) { - errors.info("^^str replaced by ^^ubyte", param.position) - subroutine.parameters[idx] = SubroutineParameter(param.name, DataType.pointer(BaseDataType.UBYTE), param.zp, param.registerOrPair, param.position) - } - } - - return noModifications - } - override fun after(assignment: Assignment, parent: Node): Iterable { val targetDt = assignment.target.inferType(program) val sourceDt = assignment.value.inferType(program) diff --git a/compiler/test/TestPointers.kt b/compiler/test/TestPointers.kt index 3c541cf17..cd62e0076 100644 --- a/compiler/test/TestPointers.kt +++ b/compiler/test/TestPointers.kt @@ -1305,7 +1305,6 @@ main { ^^uword[4] array5 ^^float[4] array6 ^^long[4] array7 - ^^str[4] array8 ok(array1) ok(array2) @@ -1314,7 +1313,6 @@ main { ok(array5) ok(array6) ok(array7) - ok(array8) } sub ok(^^ubyte ptr) { @@ -1495,7 +1493,6 @@ main { ^^uword[4] array5 = [1000, 1100, 1200, 1300] ^^float[4] array6 = [1000, 1100, 1200, 1300] ^^long[4] array7 = [1000, 1100, 1200, 1300] - ^^str[4] array8 = [1000, 1100, 1200, 1300] cx16.r0 = array1[2] cx16.r1 = array2[2] @@ -1504,7 +1501,6 @@ main { cx16.r4 = array5[2] cx16.r5 = array6[2] cx16.r6 = array7[2] - cx16.r7 = array8[2] } }""" @@ -1664,6 +1660,29 @@ main { compileText(VMTarget(), false, src, outputDir) shouldNotBe null } + test("^^str is not valid") { + val src=""" +main { + sub start() { + str name = "test" + ^^str ptr = &name + ^^str[4] array + ptr = foo(&name) + } + + sub foo(^^str arg) -> ^^str { + return arg+2 + } +}""" + val errors=ErrorReporterForTests() + compileText(VMTarget(), false, src, outputDir, errors=errors, writeAssembly = false) shouldBe null + errors.errors.size shouldBe 4 + errors.errors[0] shouldContain "^^str is not a valid pointer type" + errors.errors[1] shouldContain "^^str is not a valid pointer type" + errors.errors[2] shouldContain "^^str is not a valid pointer type" + errors.errors[3] shouldContain "^^str is not a valid return type" + } + test("various miscellaneous pointer syntax tests") { val src=""" main { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index aa65db9c5..7644baad8 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,9 +1,6 @@ TODO ==== -disallow ^^str - - STRUCTS and TYPED POINTERS -------------------------- diff --git a/examples/test.p8 b/examples/test.p8 index be33a181f..c638eb23d 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,57 +1,16 @@ -%import textio - main { - struct Node { - ^^Node next - ubyte weight - } - ^^Node nodes = 2000 - sub start() { - init() - cx16.r0L = nodes[2].weight - cx16.r1L = thing.things[2].weight - - txt.print_ub(cx16.r0L) - txt.spc() - txt.print_ub(cx16.r1L) - txt.nl() - - cx16.r9L = 3 - cx16.r0L = nodes[cx16.r9L].weight - cx16.r1L = thing.things[cx16.r9L].weight - - txt.print_ub(cx16.r0L) - txt.spc() - txt.print_ub(cx16.r1L) - txt.nl() + str name = "test" + ^^str ptr = &name + ^^str[4] array + ptr = foo(&name) } - sub init() { - sys.memset(2000, 100, 99) - sys.memset(3000, 100, 99) - - ; NNW NNW NNW NNW - @(2000+2) = 11 - @(2000+5) = 22 - @(2000+8) = 33 - @(2000+11) = 44 - - @(3000+2) = 101 - @(3000+5) = 102 - @(3000+8) = 103 - @(3000+11) = 104 + sub foo(^^str arg) -> ^^str { + return arg+2 } } -thing { - struct Thing { - ^^Thing next - ubyte weight - } - ^^Thing things = 3000 -} - ;%import floats ;%import textio