diff --git a/codeCore/src/prog8/code/core/Enumerations.kt b/codeCore/src/prog8/code/core/Enumerations.kt index 09f010ad1..a5e9a0d38 100644 --- a/codeCore/src/prog8/code/core/Enumerations.kt +++ b/codeCore/src/prog8/code/core/Enumerations.kt @@ -530,6 +530,5 @@ enum class ZeropageWish { enum class SplitWish { DONTCARE, - SPLIT, NOSPLIT } \ No newline at end of file diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index a5686ee11..2edfae3e6 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -1261,12 +1261,12 @@ $repeatLabel""") // print a message when more optimal code is possible for 65C02 cpu val variable = symbolTable.lookup(arrayVariable.name)!! if(variable is StStaticVariable && variable.length!!<=128u) - errors.info("the jump address array is @split, but @nosplit would create more efficient code here", jump.position) + errors.info("the jump address array is split, but @nosplit would create more efficient code here", jump.position) } } else { // print a message when more optimal code is possible for 6502 cpu if(!arrayIdx.splitWords) - errors.info("the jump address array is @nosplit, but @split would create more efficient code here", jump.position) + errors.info("the jump address array is @nosplit, but split would create more efficient code here", jump.position) } } // we can do the address evaluation right now and just use a temporary pointer variable diff --git a/compiler/res/prog8lib/cx16/monogfx.p8 b/compiler/res/prog8lib/cx16/monogfx.p8 index 519544e86..bff9d8b49 100644 --- a/compiler/res/prog8lib/cx16/monogfx.p8 +++ b/compiler/res/prog8lib/cx16/monogfx.p8 @@ -1038,7 +1038,7 @@ _doplot beq + ; y*40 lookup table. Pretty compact because it all fits in a word and we only need 240 y positions. ; a y*80 lookup table would be very large (lo,mid,hi for 480 values...) - uword[240] @split @shared times40 = [ + uword[240] @shared times40 = [ 0, 40, 80, 120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 680, 720, 760, 800, 840, 880, 920, 960, 1000, 1040, 1080, 1120, 1160, 1200, 1240, 1280, 1320, 1360, 1400, 1440, 1480, 1520, 1560, 1600, 1640, 1680, diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 23a223e1d..be0bbab22 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -1090,8 +1090,8 @@ internal class AstChecker(private val program: Program, } if(decl.datatype.isPointerArray) { - if(decl.splitwordarray!= SplitWish.SPLIT) - errors.err("pointer arrays can only be @split", decl.position) + if(decl.splitwordarray==SplitWish.NOSPLIT) + errors.err("pointer arrays can only be split", decl.position) } if(decl.datatype.isStructInstance && decl.origin!=VarDeclOrigin.SUBROUTINEPARAM) { diff --git a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt index f770c5cae..0e0f072c8 100644 --- a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt +++ b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt @@ -71,12 +71,11 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter, // check splitting of word arrays if(decl.splitwordarray != SplitWish.DONTCARE && !decl.datatype.isWordArray && !decl.datatype.isPointerArray) { if(decl.origin != VarDeclOrigin.ARRAYLITERAL) - errors.err("@split and @nosplit are for word or pointer arrays only", decl.position) + errors.err("@nosplit is for word or pointer arrays only", decl.position) } if(decl.datatype.isWordArray) { var changeDataType: DataType? - var changeSplit: SplitWish = decl.splitwordarray when(decl.splitwordarray) { SplitWish.DONTCARE -> { changeDataType = if(decl.datatype.isSplitWordArray) null else { @@ -86,16 +85,6 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter, else DataType.arrayFor(eltDt.base) } - changeSplit = SplitWish.SPLIT - } - SplitWish.SPLIT -> { - changeDataType = if(decl.datatype.isSplitWordArray) null else { - val eltDt = decl.datatype.elementType() - if(eltDt.isPointer) - TODO("convert array of pointers to split words array type") - else - DataType.arrayFor(eltDt.base) - } } SplitWish.NOSPLIT -> { changeDataType = if(decl.datatype.isSplitWordArray && !decl.datatype.elementType().isPointer) @@ -109,7 +98,7 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter, value = ArrayLiteral(InferredTypes.knownFor(changeDataType), value.value, value.position) } val newDecl = VarDecl(decl.type, decl.origin, changeDataType, decl.zeropage, - changeSplit, decl.arraysize, decl.name, decl.names, + decl.splitwordarray, decl.arraysize, decl.name, decl.names, value, decl.sharedWithAsm, decl.alignment, decl.dirty, decl.position) return listOf(IAstModification.ReplaceNode(decl, newDecl, parent)) } diff --git a/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt b/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt index d8d171540..3bd2dfc8f 100644 --- a/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt +++ b/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt @@ -145,7 +145,7 @@ internal class VerifyFunctionArgTypes(val program: Program, val options: Compila if(addrOf!=null) { val identType = addrOf.identifier?.inferType(program)?.getOrUndef() if(identType?.isSplitWordArray==true) { - return Pair("argument ${mismatch + 1} type mismatch, was: $actual (because arg is a @split word array) expected: $expected", call.args[mismatch].position) + return Pair("argument ${mismatch + 1} type mismatch, was: $actual (because arg is a split word array) expected: $expected", call.args[mismatch].position) } } } diff --git a/compiler/test/TestPointers.kt b/compiler/test/TestPointers.kt index 168d6c0cc..ab2effec8 100644 --- a/compiler/test/TestPointers.kt +++ b/compiler/test/TestPointers.kt @@ -1951,7 +1951,7 @@ main { val src=""" main { sub start() { - uword[10] @split @shared splitarray + uword[10] @shared splitarray uword[10] @nosplit @shared nosplitarray ^^uword ptr1 = &&splitarray @@ -1992,9 +1992,9 @@ main { errors.errors.size shouldBe 3 errors.warnings.size shouldBe 0 errors.infos.size shouldBe 0 - errors.errors[0] shouldContain "pointer arrays can only be @split" - errors.errors[1] shouldContain "was: ^^ubyte (because arg is a @split word array) expected: ^^main.Node" - errors.errors[2] shouldContain "was: ^^ubyte (because arg is a @split word array) expected: ^^main.Node" + errors.errors[0] shouldContain "pointer arrays can only be split" + errors.errors[1] shouldContain "was: ^^ubyte (because arg is a split word array) expected: ^^main.Node" + errors.errors[2] shouldContain "was: ^^ubyte (because arg is a split word array) expected: ^^main.Node" } test("passing split array of structpointers to a subroutine in various forms should be param type ptr to ubyte (the lsb part of the split array)") { @@ -2005,7 +2005,7 @@ main { } sub start() { - ^^Node[10] @split nodearray + ^^Node[10] nodearray func(&&nodearray) func(&nodearray) func(nodearray) diff --git a/compiler/test/ast/TestVariousCompilerAst.kt b/compiler/test/ast/TestVariousCompilerAst.kt index c38647b8a..a5c1a04b4 100644 --- a/compiler/test/ast/TestVariousCompilerAst.kt +++ b/compiler/test/ast/TestVariousCompilerAst.kt @@ -1129,30 +1129,26 @@ thing { } } - test("pointer arrays are always split") { + test("pointer arrays are split by default") { val src=""" %option enable_floats main { sub start() { - ^^bool[10] @split @shared barray - ^^word[10] @split @shared warray - ^^float[10] @split @shared farray - - ^^bool[10] @shared barrayns - ^^word[10] @shared warrayns - ^^float[10] @shared farrayns + ^^bool[10] @shared barray + ^^word[10] @shared warray + ^^float[10] @shared farray } }""" val result = compileText(VMTarget(), optimize=false, src, outputDir, writeAssembly=false)!! val st = result.compilerAst.entrypoint.statements - st.size shouldBe 7 + st.size shouldBe 4 val decls = st.filterIsInstance() - decls.size shouldBe 6 + decls.size shouldBe 3 decls.all { it.datatype.sub!=null } shouldBe true decls.all { it.datatype.isPointerArray } shouldBe true - decls.all { it.datatype.isPointerArray } shouldBe true + decls.all { it.datatype.isSplitWordArray } shouldBe true } test("on..call in nested scope compiles correctly with temp variable introduced") { diff --git a/compiler/test/comparisons/make_cmp_tests_splitw.py b/compiler/test/comparisons/make_cmp_tests_splitw.py index 2d4c2da6a..6a2b0a9af 100644 --- a/compiler/test/comparisons/make_cmp_tests_splitw.py +++ b/compiler/test/comparisons/make_cmp_tests_splitw.py @@ -80,8 +80,8 @@ def make_test_array(datatype, comparison: C): numbers = testnumbers[datatype] print(" sub test_cmp_array() {") print(f""" {datatype} @shared x - {datatype}[] @split values = [0, 0] - {datatype}[] @split sources = [0, 0] + {datatype}[] values = [0, 0] + {datatype}[] sources = [0, 0] success = 0""") expected = 0 test_index = 0 diff --git a/compiler/test/comparisons/make_eq_tests_splitw.py b/compiler/test/comparisons/make_eq_tests_splitw.py index c5cb31555..2af87d959 100644 --- a/compiler/test/comparisons/make_eq_tests_splitw.py +++ b/compiler/test/comparisons/make_eq_tests_splitw.py @@ -36,9 +36,9 @@ main {{ test_is_var() txt.print("\\n!=var: ") test_not_var() - txt.print("\\n==array[] @split: ") + txt.print("\\n==array[] split: ") test_is_array_splitw() - txt.print("\\n!=array[] @split: ") + txt.print("\\n!=array[] split: ") test_not_array_splitw() txt.print("\\n==expr: ") test_is_expr() @@ -97,7 +97,7 @@ nonzero_values = { def make_test_is_zero(datatype): print(f""" sub test_is_zero() {{ - {datatype}[] @split sources = [9999, 9999] + {datatype}[] sources = [9999, 9999] success = 0 sources[1]={zero_values[datatype]} @@ -155,7 +155,7 @@ skip4: def make_test_not_zero(datatype): print(f""" sub test_not_zero() {{ - {datatype}[] @split sources = [9999, 9999] + {datatype}[] sources = [9999, 9999] success = 0 sources[1]={nonzero_values[datatype]} @@ -229,7 +229,7 @@ testnumbers = { def make_test_is_number(datatype, equals): numbers = testnumbers[datatype] print(" sub test_is_number() {" if equals else " sub test_not_number() {") - print(f""" {datatype}[] @split sources = [9999, 9999] + print(f""" {datatype}[] sources = [9999, 9999] success = 0""") expected = 0 test_index = 0 @@ -286,8 +286,8 @@ skip{test_index}b: def make_test_is_var(datatype, equals): numbers = testnumbers[datatype] print(" sub test_is_var() {" if equals else " sub test_not_var() {") - print(f""" {datatype}[] @split sources = [9999, 9999] - {datatype}[] @split values = [8888,8888] + print(f""" {datatype}[] sources = [9999, 9999] + {datatype}[] values = [8888,8888] success = 0""") expected = 0 test_index = 0 @@ -346,8 +346,8 @@ def make_test_is_array(datatype, equals): numbers = testnumbers[datatype] print(" sub test_is_array_splitw() {" if equals else " sub test_not_array_splitw() {") print(f""" - {datatype}[] @split values = [9999, 8888] - {datatype}[] @split sources = [9999, 8888] + {datatype}[] values = [9999, 8888] + {datatype}[] sources = [9999, 8888] success = 0""") expected = 0 test_index = 0 @@ -441,7 +441,7 @@ skip{test_index}d: def make_test_is_expr(datatype, equals): numbers = testnumbers[datatype] print(" sub test_is_expr() {" if equals else " sub test_not_expr() {") - print(f""" {datatype}[] @split sources = [9999, 9999] + print(f""" {datatype}[] sources = [9999, 9999] cx16.r4 = 1 cx16.r5 = 1 success = 0""") diff --git a/compilerAst/src/prog8/ast/antlr/Antlr2KotlinVisitor.kt b/compilerAst/src/prog8/ast/antlr/Antlr2KotlinVisitor.kt index 520884d69..308de5ef4 100644 --- a/compilerAst/src/prog8/ast/antlr/Antlr2KotlinVisitor.kt +++ b/compilerAst/src/prog8/ast/antlr/Antlr2KotlinVisitor.kt @@ -137,7 +137,7 @@ class Antlr2KotlinVisitor(val source: SourceCode): AbstractParseTreeVisitor t.text } - val validTags = arrayOf("@zp", "@requirezp", "@nozp", "@split", "@nosplit", "@shared") + val validTags = arrayOf("@zp", "@requirezp", "@nozp", "@nosplit", "@shared") for(tag in tags) { if(tag !in validTags) throw SyntaxError("invalid parameter tag '$tag'", pctx.toPosition()) @@ -724,7 +719,6 @@ class Antlr2KotlinVisitor(val source: SourceCode): AbstractParseTreeVisitor): SplitWish { return when { "@nosplit" in tags -> SplitWish.NOSPLIT - "@split" in tags -> SplitWish.SPLIT else -> SplitWish.DONTCARE } } diff --git a/compilerAst/src/prog8/ast/statements/AstStatements.kt b/compilerAst/src/prog8/ast/statements/AstStatements.kt index 165e55aa9..e2b54d1e1 100644 --- a/compilerAst/src/prog8/ast/statements/AstStatements.kt +++ b/compilerAst/src/prog8/ast/statements/AstStatements.kt @@ -305,7 +305,7 @@ class VarDecl( fun createAutoOptionalSplit(array: ArrayLiteral): VarDecl { val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}" val arrayDt = array.type.getOrElse { throw FatalAstException("unknown dt") } - val split = if(arrayDt.isSplitWordArray) SplitWish.SPLIT else if(arrayDt.isWordArray) SplitWish.NOSPLIT else SplitWish.DONTCARE + val split = if(arrayDt.isSplitWordArray) SplitWish.DONTCARE else if(arrayDt.isWordArray) SplitWish.NOSPLIT else SplitWish.DONTCARE val arraysize = ArrayIndex.forArray(array) return VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, arrayDt, ZeropageWish.NOT_IN_ZEROPAGE, split, arraysize, autoVarName, emptyList(), array, diff --git a/docs/source/todo.rst b/docs/source/todo.rst index a53edd1e8..a7bfac1b7 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,10 +1,6 @@ TODO ==== -remove "@split" tag SplitWish.NOSPLIT - - - LONG TYPE --------- - implement the other comparison operators (<,>,<=,>=) on longs diff --git a/docs/source/variables.rst b/docs/source/variables.rst index eb7b2c25a..c3064f105 100644 --- a/docs/source/variables.rst +++ b/docs/source/variables.rst @@ -358,7 +358,7 @@ See also :ref:`pointervars` and the chapter about it :ref:`pointers`. **LSB/MSB split word and str arrays:** -As an optimization, (u)word arrays and str arrays are split by the compiler in memory as two separate arrays, +As an optimization, (u)word arrays, pointer arrays, and str arrays are split by the compiler in memory as two separate arrays, one with the LSBs and one with the MSBs of the word values. This is more efficient to access by the 6502 cpu. It also allows a maximum length of 256 for word arrays, where normally it would have been 128. @@ -366,13 +366,14 @@ For normal prog8 array indexing, the compiler takes care of the distiction for y *But for assembly code, or code that otherwise accesses the array elements directly, you have to be aware of the distinction from 'normal' arrays.* In the assembly code, the array is generated as two byte arrays namely ``name_lsb`` and ``name_msb``, immediately following eachother in memory. -The ``@nosplit`` tag can be added to the variable declaration to *never* split the array. This is useful for compatibility with +The ``@nosplit`` tag can be added to the variable declaration to *not* split the array. This is useful for compatibility with code that expects the words to be sequentially in memory (such as the cx16.FB_set_palette routine). .. note:: - Most but not all array operations are supported yet on "split word arrays". - If you get a compiler error message, simply revert to a regular sequential word array using ``@nosplit``, - and please report the issue. + Some obscure array operations may not yet be supported on "split word arrays". + If you get a compiler error message hinting that this is the case, + simply revert to a regular sequential word array using ``@nosplit``, and please report the issue so that + the missing function can be added. .. note:: Array literals are stored as split arrays if they're initializing a split word array, otherwise, diff --git a/syntax-files/Jetbrains-IDEs/Prog8.xml b/syntax-files/Jetbrains-IDEs/Prog8.xml index 83524c434..ba5a18386 100644 --- a/syntax-files/Jetbrains-IDEs/Prog8.xml +++ b/syntax-files/Jetbrains-IDEs/Prog8.xml @@ -12,7 +12,7 @@