diff --git a/codeCore/src/prog8/code/ast/AstPrinter.kt b/codeCore/src/prog8/code/ast/AstPrinter.kt index defd79957..ecea1933b 100644 --- a/codeCore/src/prog8/code/ast/AstPrinter.kt +++ b/codeCore/src/prog8/code/ast/AstPrinter.kt @@ -127,7 +127,7 @@ fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Uni str } is PtVariable -> { - val split = if(node.type.isSplitWordArray) "@split" else "" + val split = if(node.type.isSplitWordArray) "" else "@nosplit" val align = when(node.align) { 0u -> "" 2u -> "@alignword" diff --git a/codeCore/src/prog8/code/core/CompilationOptions.kt b/codeCore/src/prog8/code/core/CompilationOptions.kt index 06c0ab0aa..66502ae8c 100644 --- a/codeCore/src/prog8/code/core/CompilationOptions.kt +++ b/codeCore/src/prog8/code/core/CompilationOptions.kt @@ -27,7 +27,7 @@ class CompilationOptions(val output: OutputType, var varsGolden: Boolean = false, var slabsHighBank: Int? = null, var slabsGolden: Boolean = false, - var splitWordArrays: Boolean = false, + var dontSplitWordArrays: Boolean = false, var breakpointCpuInstruction: String? = null, var ignoreFootguns: Boolean = false, var outputDir: Path = Path(""), diff --git a/codeCore/src/prog8/code/core/Enumerations.kt b/codeCore/src/prog8/code/core/Enumerations.kt index 4cff77a25..fcd42dac0 100644 --- a/codeCore/src/prog8/code/core/Enumerations.kt +++ b/codeCore/src/prog8/code/core/Enumerations.kt @@ -117,19 +117,18 @@ class DataType private constructor(val base: BaseDataType, val sub: SubType?) { fun forDt(dt: BaseDataType) = simpletypes.getValue(dt) - fun arrayFor(elementDt: BaseDataType, split: Boolean=false): DataType { + fun arrayFor(elementDt: BaseDataType, splitwordarray: Boolean=true): DataType { val actualElementDt = if(elementDt==BaseDataType.STR) BaseDataType.UWORD else elementDt // array of strings is actually just an array of UWORD pointers - if(split) return DataType(BaseDataType.ARRAY_SPLITW, SubType.forDt(actualElementDt)) - else return DataType(BaseDataType.ARRAY, SubType.forDt(actualElementDt)) + return if(splitwordarray && elementDt.isWord) + DataType(BaseDataType.ARRAY_SPLITW, SubType.forDt(actualElementDt)) + else + DataType(BaseDataType.ARRAY, SubType.forDt(actualElementDt)) } } - fun elementToArray(split: Boolean = false): DataType { - if(split) { - return if (base == BaseDataType.UWORD || base == BaseDataType.WORD || base == BaseDataType.STR) arrayFor(base, true) - else throw IllegalArgumentException("invalid split array elt dt") - } - return arrayFor(base) + fun elementToArray(splitwords: Boolean = true): DataType { + return if (base == BaseDataType.UWORD || base == BaseDataType.WORD || base == BaseDataType.STR) arrayFor(base, splitwords) + else arrayFor(base, false) } fun elementType(): DataType = @@ -152,8 +151,8 @@ class DataType private constructor(val base: BaseDataType, val sub: SubType?) { } BaseDataType.ARRAY_SPLITW -> { when(sub) { - SubSignedWord -> "@split word[]" - SubUnsignedWord -> "@split uword[]" + SubSignedWord -> "word[] (split)" + SubUnsignedWord -> "uword[] (split)" else -> throw IllegalArgumentException("invalid sub type") } } @@ -172,18 +171,18 @@ class DataType private constructor(val base: BaseDataType, val sub: SubType?) { BaseDataType.ARRAY -> { when(sub) { SubUnsignedByte -> "ubyte[" - SubUnsignedWord -> "uword[" + SubUnsignedWord -> "@nosplit uword[" SubBool -> "bool[" SubSignedByte -> "byte[" - SubSignedWord -> "word[" + SubSignedWord -> "@nosplit word[" SubFloat -> "float[" null -> throw IllegalArgumentException("invalid sub type") } } BaseDataType.ARRAY_SPLITW -> { when(sub) { - SubUnsignedWord -> "@split uword[" - SubSignedWord -> "@split word[" + SubUnsignedWord -> "uword[" + SubSignedWord -> "word[" else -> throw IllegalArgumentException("invalid sub type") } } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index bd2237f6c..1ce5bbfd8 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -670,7 +670,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, val msbAdd: Int if(indexer.splitWords) { val arrayVariable = indexer.variable - indexer.children[0] = PtIdentifier(arrayVariable.name + if(msb) "_msb" else "_lsb", DataType.arrayFor(BaseDataType.UBYTE), arrayVariable.position) + indexer.children[0] = PtIdentifier(arrayVariable.name + if(msb) "_msb" else "_lsb", DataType.arrayFor(BaseDataType.UBYTE, false), arrayVariable.position) indexer.children[0].parent = indexer elementSize = 1 msbAdd = 0 diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 379c71c9f..dbeb5bafb 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -1939,11 +1939,14 @@ $endLabel""") asmgen.out(" ldy #$numElements") asmgen.out(" jsr prog8_lib.containment_bytearray") } - dt.isWordArray && !dt.isSplitWordArray -> { + dt.isWordArray -> { assignExpressionToVariable(containment.needle, "P8ZP_SCRATCH_W1", elementDt) assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName, null, null) asmgen.out(" ldy #$numElements") - asmgen.out(" jsr prog8_lib.containment_wordarray") + if(dt.isSplitWordArray) + asmgen.out(" jsr prog8_lib.containment_splitwordarray") + else + asmgen.out(" jsr prog8_lib.containment_wordarray") } else -> throw AssemblyError("invalid dt") } diff --git a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt index e0335e899..74c2fecbe 100644 --- a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt +++ b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt @@ -70,7 +70,7 @@ class VarConstantValueTypeAdjuster( if (declValue != null) { // variable is never written to, so it can be replaced with a constant, IF the value is a constant errors.info("variable '${decl.name}' is never written to and was replaced by a constant", decl.position) - val const = VarDecl(VarDeclType.CONST, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, decl.names, declValue, decl.sharedWithAsm, decl.splitArray, decl.alignment, decl.dirty, decl.position) + val const = VarDecl(VarDeclType.CONST, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, decl.names, declValue, decl.sharedWithAsm, decl.alignment, decl.dirty, decl.position) decl.value = null return listOf( IAstModification.ReplaceNode(decl, const, parent) @@ -90,7 +90,7 @@ class VarConstantValueTypeAdjuster( } // variable only has a single write, and it is the initialization value, so it can be replaced with a constant, IF the value is a constant errors.info("variable '${decl.name}' is never written to and was replaced by a constant", decl.position) - val const = VarDecl(VarDeclType.CONST, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, decl.names, singleAssignment.value, decl.sharedWithAsm, decl.splitArray, decl.alignment, decl.dirty, decl.position) + val const = VarDecl(VarDeclType.CONST, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, decl.names, singleAssignment.value, decl.sharedWithAsm, decl.alignment, decl.dirty, decl.position) return listOf( IAstModification.ReplaceNode(decl, const, parent), IAstModification.Remove(singleAssignment, singleAssignment.parent as IStatementContainer) @@ -392,7 +392,7 @@ internal class ConstantIdentifierReplacer( if(targetDatatype.isArray) { val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.ARRAYLITERAL, targetDatatype.getOrUndef(), ZeropageWish.DONTCARE, null, "dummy", emptyList(), - assignment.value, false, false, 0u, false, Position.DUMMY) + assignment.value, false, 0u, false, Position.DUMMY) val replaceValue = createConstArrayInitializerValue(decl) if(replaceValue!=null) { return listOf(IAstModification.ReplaceNode(assignment.value, replaceValue, assignment)) @@ -447,7 +447,7 @@ internal class ConstantIdentifierReplacer( if(declArraySize!=null && declArraySize!=rangeExpr.size()) errors.err("range expression size (${rangeExpr.size()}) doesn't match declared array size ($declArraySize)", decl.value?.position!!) if(constRange!=null) { - return ArrayLiteral(InferredTypes.InferredType.known(DataType.arrayFor(BaseDataType.FLOAT)), + return ArrayLiteral(InferredTypes.InferredType.known(DataType.arrayFor(BaseDataType.FLOAT, false)), constRange.map { NumericLiteral(BaseDataType.FLOAT, it.toDouble(), decl.value!!.position) }.toTypedArray(), position = decl.value!!.position) } diff --git a/compiler/res/prog8lib/anyall.p8 b/compiler/res/prog8lib/anyall.p8 index bda206275..40bca3dbf 100644 --- a/compiler/res/prog8lib/anyall.p8 +++ b/compiler/res/prog8lib/anyall.p8 @@ -42,7 +42,7 @@ anyall { sub anyw(uword arrayptr, uword num_elements) -> bool { ; -- returns true if any word in the array is not zero. - ; doesn't work on @split arrays. + ; TODO FIX: doesn't work on @split arrays. cx16.r1 = arrayptr if msb(num_elements)==0 { repeat lsb(num_elements) { @@ -62,7 +62,7 @@ anyall { sub allw(uword arrayptr, uword num_elements) -> bool { ; -- returns true if all words in the array are not zero. - ; doesn't work on @split arrays. + ; TODO FIX: doesn't work on @split arrays. cx16.r1 = arrayptr if msb(num_elements)==0 { repeat lsb(num_elements) { diff --git a/compiler/res/prog8lib/c128/syslib.p8 b/compiler/res/prog8lib/c128/syslib.p8 index fcc7f32df..229de4f51 100644 --- a/compiler/res/prog8lib/c128/syslib.p8 +++ b/compiler/res/prog8lib/c128/syslib.p8 @@ -188,7 +188,7 @@ c64 { &ubyte SP7X = $d00e &ubyte SP7Y = $d00f &ubyte[16] SPXY = $d000 ; the 8 sprite X and Y registers as an array. - &uword[8] SPXYW = $d000 ; the 8 sprite X and Y registers as a combined xy word array. + &uword[8] @nosplit SPXYW = $d000 ; the 8 sprite X and Y registers as a combined xy word array. &ubyte MSIGX = $d010 &ubyte SCROLY = $d011 diff --git a/compiler/res/prog8lib/c64/syslib.p8 b/compiler/res/prog8lib/c64/syslib.p8 index 9e2f8509f..53d28a63f 100644 --- a/compiler/res/prog8lib/c64/syslib.p8 +++ b/compiler/res/prog8lib/c64/syslib.p8 @@ -189,7 +189,7 @@ c64 { &ubyte SP7X = $d00e &ubyte SP7Y = $d00f &ubyte[16] SPXY = $d000 ; the 8 sprite X and Y registers as an array. - &uword[8] SPXYW = $d000 ; the 8 sprite X and Y registers as a combined xy word array. + &uword[8] @nosplit SPXYW = $d000 ; the 8 sprite X and Y registers as a combined xy word array. &ubyte MSIGX = $d010 &ubyte SCROLY = $d011 diff --git a/compiler/res/prog8lib/cx16/psg.p8 b/compiler/res/prog8lib/cx16/psg.p8 index d9bbf7f5b..81ea44c54 100644 --- a/compiler/res/prog8lib/cx16/psg.p8 +++ b/compiler/res/prog8lib/cx16/psg.p8 @@ -174,7 +174,7 @@ psg { } ubyte[16] envelope_states - uword[16] @split envelope_volumes ; scaled by 256 + uword[16] envelope_volumes ; scaled by 256 ubyte[16] envelope_attacks ubyte[16] envelope_sustains ubyte[16] envelope_releases diff --git a/compiler/res/prog8lib/prog8_lib.asm b/compiler/res/prog8lib/prog8_lib.asm index fa90b0d59..91941e877 100644 --- a/compiler/res/prog8lib/prog8_lib.asm +++ b/compiler/res/prog8lib/prog8_lib.asm @@ -318,8 +318,8 @@ containment_bytearray .proc .pend containment_wordarray .proc - ; -- check if a value exists in a word array. - ; parameters: P8ZP_SCRATCH_W1: value to check, P8ZP_SCRATCH_W2: address of the word array, Y = length of array (>=1). + ; -- check if a value exists in a linear word array. + ; parameters: P8ZP_SCRATCH_W1: value to check, P8ZP_SCRATCH_W2: address of the word array, Y = number of elements in the array (>=1). ; returns boolean 0/1 in A. dey tya @@ -343,6 +343,34 @@ _found lda #1 rts .pend +containment_splitwordarray .proc + ; -- check if a value exists in a split lsb/msb word array. (Assuming lsb array comes first, immediately followed by msb array) + ; parameters: P8ZP_SCRATCH_W1: value to check, P8ZP_SCRATCH_W2: start address of the lsb word array, Y = number of elements in the array (>=1). + ; returns boolean 0/1 in A. + + ; TODO FIX THIS! + dey + tya + asl a + tay +- lda P8ZP_SCRATCH_W1 + cmp (P8ZP_SCRATCH_W2),y + bne + + lda P8ZP_SCRATCH_W1+1 + iny + cmp (P8ZP_SCRATCH_W2),y + beq _found + dey ++ dey + dey + cpy #254 + bne - + lda #0 + rts +_found lda #1 + rts + .pend + arraycopy_split_to_normal_words .proc ; P8ZP_SCRATCH_W1 = start of lsb array diff --git a/compiler/src/prog8/CompilerMain.kt b/compiler/src/prog8/CompilerMain.kt index 8f804ffa1..ba8d92211 100644 --- a/compiler/src/prog8/CompilerMain.kt +++ b/compiler/src/prog8/CompilerMain.kt @@ -66,7 +66,7 @@ private fun compileMain(args: Array): Boolean { val slabsGolden by cli.option(ArgType.Boolean, fullName = "slabsgolden", description = "put memory() slabs in 'golden ram' memory area instead of at the end of the program. On the cx16 target this is $0400-07ff. This is unavailable on other systems.") val slabsHighBank by cli.option(ArgType.Int, fullName = "slabshigh", description = "put memory() slabs in high memory area instead of at the end of the program. On the cx16 target the value specifies the HiRAM bank to use, on other systems this value is ignored.") val includeSourcelines by cli.option(ArgType.Boolean, fullName = "sourcelines", description = "include original Prog8 source lines in generated asm code") - val splitWordArrays by cli.option(ArgType.Boolean, fullName = "splitarrays", description = "treat all word arrays as tagged with @split to make them lsb/msb split in memory") + val dontSplitWordArrays by cli.option(ArgType.Boolean, fullName = "dontsplitarrays", description = "don't store any word array as split lsb/msb in memory, as if all of those have @nosplit") val sourceDirs by cli.option(ArgType.String, fullName="srcdirs", description = "list of extra paths, separated with ${File.pathSeparator}, to search in for imported modules").multiple().delimiter(File.pathSeparator) val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of ${CompilationTargets.joinToString(",")}) (required)") val varsGolden by cli.option(ArgType.Boolean, fullName = "varsgolden", description = "put uninitialized variables in 'golden ram' memory area instead of at the end of the program. On the cx16 target this is $0400-07ff. This is unavailable on other systems.") @@ -184,7 +184,7 @@ private fun compileMain(args: Array): Boolean { slabsHighBank, slabsGolden == true, compilationTarget!!, - splitWordArrays == true, + dontSplitWordArrays == true, breakpointCpuInstruction, printAst1 == true, printAst2 == true, @@ -267,7 +267,7 @@ private fun compileMain(args: Array): Boolean { slabsHighBank, slabsGolden == true, compilationTarget!!, - splitWordArrays == true, + dontSplitWordArrays == true, breakpointCpuInstruction, printAst1 == true, printAst2 == true, diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index bbedf970a..69eab8cd7 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -48,7 +48,7 @@ class CompilerArguments(val filepath: Path, val slabsHighBank: Int?, val slabsGolden: Boolean, val compilationTarget: String, - val splitWordArrays: Boolean, + val dontSplitWordArrays: Boolean, val breakpointCpuInstruction: String?, val printAst1: Boolean, val printAst2: Boolean, @@ -87,7 +87,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? { varsGolden = args.varsGolden slabsHighBank = args.slabsHighBank slabsGolden = args.slabsGolden - splitWordArrays = args.splitWordArrays + dontSplitWordArrays = args.dontSplitWordArrays outputDir = args.outputDir.normalize() symbolDefs = args.symbolDefs } diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index b5b21a109..9273ff2f9 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -703,7 +703,7 @@ internal class AstChecker(private val program: Program, if (variable!=null) { if (variable.type == VarDeclType.CONST && addressOf.arrayIndex == null) errors.err("invalid pointer-of operand type",addressOf.position) - if (variable.splitArray) + if (variable.datatype.isSplitWordArray) errors.err("cannot take address of split word array",addressOf.position) } super.visit(addressOf) @@ -888,8 +888,8 @@ internal class AstChecker(private val program: Program, } } - if(decl.splitArray && decl.type==VarDeclType.MEMORY) - err("@split can't be used on memory mapped arrays") + if(decl.datatype.isSplitWordArray && decl.type==VarDeclType.MEMORY) + err("memory mapped word arrays cannot be split, should have @nosplit") } if(decl.datatype.isString) { @@ -911,7 +911,7 @@ internal class AstChecker(private val program: Program, if(compilerOptions.zeropage==ZeropageType.DONTUSE && decl.zeropage == ZeropageWish.REQUIRE_ZEROPAGE) err("zeropage usage has been disabled by options") - if(decl.splitArray) { + if(decl.datatype.isSplitWordArray) { if (!decl.datatype.isWordArray) { errors.err("split can only be used on word arrays", decl.position) } @@ -1044,14 +1044,14 @@ internal class AstChecker(private val program: Program, err("this directive may only occur in a block or at module level") if(directive.args.isEmpty()) err("missing option directive argument(s)") - else if(directive.args.map{it.name in arrayOf("enable_floats", "force_output", "no_sysinit", "merge", "verafxmuls", "splitarrays", "no_symbol_prefixing", "ignore_unused")}.any { !it }) + else if(directive.args.map{it.name in arrayOf("enable_floats", "force_output", "no_sysinit", "merge", "verafxmuls", "no_symbol_prefixing", "ignore_unused")}.any { !it }) err("invalid option directive argument(s)") if(directive.parent is Block) { - if(directive.args.any {it.name !in arrayOf("force_output", "merge", "verafxmuls", "splitarrays", "no_symbol_prefixing", "ignore_unused")}) + if(directive.args.any {it.name !in arrayOf("force_output", "merge", "verafxmuls", "no_symbol_prefixing", "ignore_unused")}) err("using an option that is not valid for blocks") } if(directive.parent is Module) { - if(directive.args.any {it.name !in arrayOf("enable_floats", "no_sysinit", "splitarrays", "no_symbol_prefixing", "ignore_unused")}) + if(directive.args.any {it.name !in arrayOf("enable_floats", "no_sysinit", "no_symbol_prefixing", "ignore_unused")}) err("using an option that is not valid for modules") } if(directive.args.any { it.name=="verafxmuls" } && compilerOptions.compTarget.name != Cx16Target.NAME) diff --git a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt index 8e120a544..f643ed339 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt @@ -112,8 +112,8 @@ class AstPreprocessor(val program: Program, val replacements = mutableListOf() for(decl in vars) { - if(shouldSplitArray(decl)) - continue // splitting must be done first + if(shouldUnSplitArray(decl)) + continue // unsplitting must be done first if(decl.type != VarDeclType.VAR) { movements.add(IAstModification.InsertFirst(decl, parentscope)) replacements.add(IAstModification.Remove(decl, scope)) @@ -181,28 +181,21 @@ class AstPreprocessor(val program: Program, } } - if(shouldSplitArray(decl)) { - return makeSplitArray(decl) - } - - if(decl.datatype.isWordArray) { - if ("splitarrays" in decl.definingBlock.options()) - return makeSplitArray(decl) - if ("splitarrays" in decl.definingModule.options()) - return makeSplitArray(decl) + if(shouldUnSplitArray(decl)) { + return makeUnSplitArray(decl) } return noModifications } - private fun shouldSplitArray(decl: VarDecl): Boolean = - options.splitWordArrays && (decl.datatype.isWordArray && !decl.datatype.isSplitWordArray) && !decl.definingBlock.isInLibrary + private fun shouldUnSplitArray(decl: VarDecl): Boolean = + options.dontSplitWordArrays && decl.datatype.isSplitWordArray - private fun makeSplitArray(decl: VarDecl): Iterable { - val splitDt = DataType.arrayFor(decl.datatype.sub!!.dt, true) + private fun makeUnSplitArray(decl: VarDecl): Iterable { + val splitDt = DataType.arrayFor(decl.datatype.sub!!.dt, false) val newDecl = VarDecl( decl.type, decl.origin, splitDt, decl.zeropage, decl.arraysize, decl.name, emptyList(), - decl.value?.copy(), decl.sharedWithAsm, true, decl.alignment, false, decl.position + decl.value?.copy(), decl.sharedWithAsm, decl.alignment, false, decl.position ) return listOf(IAstModification.ReplaceNode(decl, newDecl, decl.parent)) } diff --git a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt index ffc6c4c2e..8ff02a299 100644 --- a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt +++ b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt @@ -202,7 +202,7 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr "no_symbol_prefixing" -> noSymbolPrefixing = true "ignore_unused" -> ignoreUnused = true "force_output" -> forceOutput = true - "merge", "splitarrays" -> { /* ignore this one */ } + "merge" -> { /* ignore this one */ } "verafxmuls" -> veraFxMuls = true else -> throw FatalAstException("weird directive option: ${arg.name}") } diff --git a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt index 16b84b8b9..7c95e7a75 100644 --- a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt +++ b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt @@ -66,7 +66,7 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro // turn the array literal it into an identifier reference val litval2 = array.cast(targetDt.getOrUndef()) if (litval2 != null) { - val vardecl2 = VarDecl.createAuto(litval2, targetDt.getOrUndef().isSplitWordArray) + val vardecl2 = VarDecl.createAuto(litval2) val identifier = IdentifierReference(listOf(vardecl2.name), vardecl2.position) return listOf( IAstModification.ReplaceNode(array, identifier, parent), @@ -81,7 +81,7 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro val mods = mutableListOf() for(elt in array.value.filterIsInstance()) { val decl = elt.targetVarDecl(program) - if(decl!=null && decl.splitArray) { + if(decl!=null && decl.datatype.isSplitWordArray) { // you can't take the adress of a split-word array. // instead of a fatal error, we give a warning and turn it back into a regular array. errors.warn("cannot take address of split word array - the array is turned back into a regular word array", decl.position) @@ -158,7 +158,7 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro override fun after(addressOf: AddressOf, parent: Node): Iterable { val variable=addressOf.identifier.targetVarDecl(program) if (variable!=null) { - if (variable.splitArray) { + if (variable.datatype.isSplitWordArray) { // you can't take the adress of a split-word array. // instead of giving a fatal error, we remove the // instead of a fatal error, we give a warning and turn it back into a regular array. @@ -174,7 +174,7 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro val normalDt = DataType.arrayFor(variable.datatype.sub!!.dt, false) return VarDecl( variable.type, variable.origin, normalDt, variable.zeropage, variable.arraysize, variable.name, emptyList(), - variable.value?.copy(), variable.sharedWithAsm, false, variable.alignment, variable.dirty, variable.position + variable.value?.copy(), variable.sharedWithAsm, variable.alignment, variable.dirty, variable.position ) } diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index 7bae13b02..4d99e9a0b 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -222,7 +222,6 @@ internal class StatementReorderer( emptyList(), null, it.sharedWithAsm, - it.splitArray, it.alignment, it.dirty, it.position diff --git a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt index 19cdc35bc..756991ed8 100644 --- a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt +++ b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt @@ -15,7 +15,7 @@ import prog8.code.core.* internal class VariousCleanups(val program: Program, val errors: IErrorReporter, val options: CompilationOptions): AstWalker() { override fun after(block: Block, parent: Node): Iterable { - val inheritOptions = block.definingModule.options() intersect setOf("splitarrays", "no_symbol_prefixing", "ignore_unused") subtract block.options() + val inheritOptions = block.definingModule.options() intersect setOf("no_symbol_prefixing", "ignore_unused") subtract block.options() if(inheritOptions.isNotEmpty()) { val directive = Directive("%option", inheritOptions.map{ DirectiveArg(null, it, null, block.position) }, block.position) return listOf(IAstModification.InsertFirst(directive, block)) @@ -223,7 +223,7 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter, // replace x==1 or x==2 or x==3 with a containment check x in [1,2,3] val valueCopies = values.sortedBy { it.number }.map { it.copy() } - val arrayType = DataType.arrayFor(elementType.base) + val arrayType = DataType.arrayFor(elementType.base, true) val valuesArray = ArrayLiteral(InferredTypes.InferredType.known(arrayType), valueCopies.toTypedArray(), expr.position) val containment = ContainmentCheck(needle, valuesArray, expr.position) return listOf(IAstModification.ReplaceNode(expr, containment, parent)) diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index e8a1e8fc5..47ea0e57e 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -39,7 +39,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat slabsHighBank = null, slabsGolden = false, compilationTarget = target.name, - splitWordArrays = false, + dontSplitWordArrays = false, breakpointCpuInstruction = null, printAst1 = false, printAst2 = false, diff --git a/compiler/test/TestCompilerOnRanges.kt b/compiler/test/TestCompilerOnRanges.kt index 515d9d85c..a33dbe171 100644 --- a/compiler/test/TestCompilerOnRanges.kt +++ b/compiler/test/TestCompilerOnRanges.kt @@ -339,6 +339,7 @@ class TestCompilerOnRanges: FunSpec({ str name = "irmen" ubyte[] values = [1,2,3,4,5,6,7] uword[] wvalues = [1000,2000,3000] + uword[] @nosplit wnsvalues = [1000,2000,3000] if 'm' in name { xx++ @@ -376,6 +377,10 @@ class TestCompilerOnRanges: FunSpec({ xx++ } + if ww in wnsvalues { + xx++ + } + if xx in 10 to 20 { xx++ } @@ -387,7 +392,7 @@ class TestCompilerOnRanges: FunSpec({ }""", writeAssembly = true) shouldNotBe null } - test("containment check in expressions") { + test("containment check expressions") { compileText( C64Target(), false, """ main { @@ -397,6 +402,7 @@ class TestCompilerOnRanges: FunSpec({ str name = "irmen" ubyte[] values = [1,2,3,4,5,6,7] uword[] wvalues = [1000,2000,3000] + uword[] @nosplit wnsvalues = [1000,2000,3000] xx = 'm' in name xx = 5 in values @@ -408,6 +414,7 @@ class TestCompilerOnRanges: FunSpec({ xx = xx in [2,4,6,8] xx = ww in [9000,8000,7000] xx = ww in wvalues + xx = ww in wnsvalues } }""", writeAssembly = true) shouldNotBe null } diff --git a/compiler/test/TestCompilerOptionLibdirs.kt b/compiler/test/TestCompilerOptionLibdirs.kt index f17748f46..c47f26775 100644 --- a/compiler/test/TestCompilerOptionLibdirs.kt +++ b/compiler/test/TestCompilerOptionLibdirs.kt @@ -37,7 +37,7 @@ class TestCompilerOptionSourcedirs: FunSpec({ slabsHighBank = null, slabsGolden = false, compilationTarget = Cx16Target.NAME, - splitWordArrays = false, + dontSplitWordArrays = false, breakpointCpuInstruction = null, printAst1 = false, printAst2 = false, diff --git a/compiler/test/TestMemory.kt b/compiler/test/TestMemory.kt index 1c25e3d8e..9aec6e95f 100644 --- a/compiler/test/TestMemory.kt +++ b/compiler/test/TestMemory.kt @@ -111,7 +111,7 @@ class TestMemory: FunSpec({ } fun createTestProgramForMemoryRefViaVar(address: UInt, vartype: VarDeclType): AssignTarget { - val decl = VarDecl(vartype, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, 0u, false, Position.DUMMY) + val decl = VarDecl(vartype, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, 0u, false, Position.DUMMY) val memexpr = IdentifierReference(listOf("address"), Position.DUMMY) val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), null, false, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) @@ -149,7 +149,7 @@ class TestMemory: FunSpec({ } test("regular variable not in mapped IO ram on C64") { - val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, false, 0u, false, Position.DUMMY) + val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, 0u, false, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, null, false, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, mutableListOf(decl, assignment), Position.DUMMY) @@ -161,7 +161,7 @@ class TestMemory: FunSpec({ test("memory mapped variable not in mapped IO ram on C64") { val address = 0x1000u - val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, 0u, false, Position.DUMMY) + val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, 0u, false, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, null, false, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, mutableListOf(decl, assignment), Position.DUMMY) @@ -173,7 +173,7 @@ class TestMemory: FunSpec({ test("memory mapped variable in mapped IO ram on C64") { val address = 0xd020u - val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, 0u, false, Position.DUMMY) + val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, 0u, false, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, null, false, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, mutableListOf(decl, assignment), Position.DUMMY) @@ -184,7 +184,7 @@ class TestMemory: FunSpec({ } test("array not in mapped IO ram") { - val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, false, 0u, false, Position.DUMMY) + val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, 0u, false, Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, null, false, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) @@ -197,7 +197,7 @@ class TestMemory: FunSpec({ test("memory mapped array not in mapped IO ram") { val address = 0x1000u - val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, 0u, false, Position.DUMMY) + val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, 0u, false, Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, null, false, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) @@ -210,7 +210,7 @@ class TestMemory: FunSpec({ test("memory mapped array in mapped IO ram") { val address = 0xd800u - val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, 0u, false, Position.DUMMY) + val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, 0u, false, Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, null, false, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) diff --git a/compiler/test/ast/TestConst.kt b/compiler/test/ast/TestConst.kt index df73797ee..469da7c17 100644 --- a/compiler/test/ast/TestConst.kt +++ b/compiler/test/ast/TestConst.kt @@ -261,9 +261,9 @@ main { val src=""" main { sub start() { - &uword[30] wb = ${'$'}2000 - &uword[100] array1 = ${'$'}9e00 - &uword[30] array2 = &array1[len(wb)] + &uword[30] @nosplit wb = ${'$'}2000 + &uword[100] @nosplit array1 = ${'$'}9e00 + &uword[30] @nosplit array2 = &array1[len(wb)] cx16.r0 = &array1 ; ${'$'}9e00 cx16.r1 = &array1[len(wb)] ; ${'$'}9e3c @@ -291,7 +291,7 @@ main { cx16.r0 = &array const uword HIGH_MEMORY_START = 40960 - &uword[20] @shared wa = HIGH_MEMORY_START + &uword[20] @shared @nosplit wa = HIGH_MEMORY_START } }""" val result = compileText(Cx16Target(), optimize=false, src, writeAssembly=true)!! diff --git a/compiler/test/ast/TestVariousCompilerAst.kt b/compiler/test/ast/TestVariousCompilerAst.kt index 6fbc6e088..2c19fd198 100644 --- a/compiler/test/ast/TestVariousCompilerAst.kt +++ b/compiler/test/ast/TestVariousCompilerAst.kt @@ -87,32 +87,6 @@ main { }""" compileText(VMTarget(), optimize=false, src, writeAssembly=false) shouldNotBe null } - - test("split arrays back to normal when address is taken") { - val src=""" -main { - sub start() { - cx16.r0L=0 - if cx16.r0L==0 { - uword[] addresses = [scores2, start] - uword[] @split scores1 = [10, 25, 50, 100] - uword[] @split scores2 = [100, 250, 500, 1000] - - cx16.r0 = &scores1 - cx16.r1 = &scores2 - cx16.r2 = &addresses - } - } -}""" - val errors = ErrorReporterForTests(keepMessagesAfterReporting = true) - compileText(C64Target(), optimize=false, src, writeAssembly=true, errors=errors) shouldNotBe null - errors.errors.size shouldBe 0 - errors.warnings.size shouldBe 2 - errors.warnings[0] shouldContain("address") - errors.warnings[1] shouldContain("address") - errors.warnings[0] shouldContain("split") - errors.warnings[1] shouldContain("split") - } } context("alias") { @@ -911,16 +885,12 @@ main { shouldThrow { DataType.arrayFor(BaseDataType.UNDEFINED) } - shouldThrow { - DataType.arrayFor(BaseDataType.UBYTE, true) - } - + DataType.arrayFor(BaseDataType.UBYTE, true).isUnsignedByteArray shouldBe true DataType.arrayFor(BaseDataType.FLOAT).isFloatArray shouldBe true DataType.arrayFor(BaseDataType.UWORD).isUnsignedWordArray shouldBe true DataType.arrayFor(BaseDataType.UWORD).isArray shouldBe true - DataType.arrayFor(BaseDataType.UWORD).isSplitWordArray shouldBe false - DataType.arrayFor(BaseDataType.UWORD, true).isArray shouldBe true - DataType.arrayFor(BaseDataType.UWORD, true).isSplitWordArray shouldBe true + DataType.arrayFor(BaseDataType.UWORD).isSplitWordArray shouldBe true + DataType.arrayFor(BaseDataType.UWORD, false).isSplitWordArray shouldBe false } test("array of strings becomes array of uword pointers") { diff --git a/compiler/test/codegeneration/TestArrayThings.kt b/compiler/test/codegeneration/TestArrayThings.kt index f945ea433..1111df653 100644 --- a/compiler/test/codegeneration/TestArrayThings.kt +++ b/compiler/test/codegeneration/TestArrayThings.kt @@ -98,8 +98,8 @@ main { test("split only for word arrays") { val srcGood = """ main { - uword[10] @split sw - word[10] @split sw2 + uword[10] @nosplit sw + word[10] @nosplit sw2 sub start() { } @@ -108,7 +108,7 @@ main { val srcWrong1 = """ main { - ubyte[10] @split sb + ubyte[10] @nosplit sb sub start() { } @@ -116,12 +116,12 @@ main { val errors = ErrorReporterForTests() compileText(C64Target(), false, srcWrong1, writeAssembly = false, errors=errors) shouldBe null errors.errors.size shouldBe 1 - errors.errors[0] shouldContain "split can only be used on word arrays" + errors.errors[0] shouldContain "nosplit can only be used on word arrays" val srcWrong2 = """ %option enable_floats main { - float[10] @split sf + float[10] @nosplit sf sub start() { } @@ -129,15 +129,15 @@ main { errors.clear() compileText(C64Target(), false, srcWrong2, writeAssembly = false, errors=errors) shouldBe null errors.errors.size shouldBe 1 - errors.errors[0] shouldContain "split can only be used on word arrays" + errors.errors[0] shouldContain "nosplit can only be used on word arrays" } - test("split word arrays in asm as lsb/msb") { + test("split word arrays in asm as lsb/msb, nosplit as single linear") { val text = """ main { - uword[10] @split @shared uw - word[10] @split @shared sw - uword[10] @shared normal + uword[10] @shared uw + word[10] @shared sw + uword[10] @shared @nosplit normal sub start() { %asm {{ @@ -170,7 +170,8 @@ main { val text = """ main { sub start() { - uword[3] @zp @split @shared thearray + uword[3] @zp @shared thearray + uword[3] @zp @nosplit @shared thearray2 } }""" val result = compileText(C64Target(), false, text, writeAssembly = true)!! @@ -178,6 +179,7 @@ main { val assembly = assemblyFile.readText() assembly shouldContain "thearray_lsb" assembly shouldContain "thearray_msb" + assembly shouldContain "thearray2" } test("indexing str or pointervar with expression") { @@ -419,5 +421,31 @@ main { compileText(VMTarget(), false, src, writeAssembly = true) shouldNotBe null compileText(C64Target(), false, src, writeAssembly = true) shouldNotBe null } + + test("taking address of split arrays") { + val src=""" +main { + sub start() { + cx16.r0L=0 + if cx16.r0L==0 { + uword[] addresses = [scores2, start] + uword[] scores1 = [10, 25, 50, 100] + uword[] scores2 = [100, 250, 500, 1000] + + cx16.r0 = &scores1 + cx16.r1 = &scores2 + cx16.r2 = &addresses + } + } +}""" + val errors = ErrorReporterForTests(keepMessagesAfterReporting = true) + compileText(C64Target(), optimize=false, src, writeAssembly=true, errors=errors) shouldNotBe null + errors.errors.size shouldBe 0 + errors.warnings.size shouldBe 2 + errors.warnings[0] shouldContain("address") + errors.warnings[1] shouldContain("address") + errors.warnings[0] shouldContain("split") + errors.warnings[1] shouldContain("split") + } }) diff --git a/compiler/test/codegeneration/TestAsmGenSymbols.kt b/compiler/test/codegeneration/TestAsmGenSymbols.kt index 4848d5437..0b79ca8c8 100644 --- a/compiler/test/codegeneration/TestAsmGenSymbols.kt +++ b/compiler/test/codegeneration/TestAsmGenSymbols.kt @@ -46,8 +46,8 @@ class TestAsmGenSymbols: StringSpec({ } */ - val varInSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "localvar", emptyList(), NumericLiteral.optimalInteger(1234, Position.DUMMY), false, false, 0u, false, Position.DUMMY) - val var2InSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "tgt", emptyList(), null, false, false, 0u, false, Position.DUMMY) + val varInSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "localvar", emptyList(), NumericLiteral.optimalInteger(1234, Position.DUMMY), false, 0u, false, Position.DUMMY) + val var2InSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "tgt", emptyList(), null, false, 0u, false, Position.DUMMY) val labelInSub = Label("locallabel", Position.DUMMY) val tgt = AssignTarget(IdentifierReference(listOf("tgt"), Position.DUMMY), null, null, null, false, Position.DUMMY) @@ -63,7 +63,7 @@ class TestAsmGenSymbols: StringSpec({ val statements = mutableListOf(varInSub, var2InSub, labelInSub, assign1, assign2, assign3, assign4, assign5, assign6, assign7, assign8) val subroutine = Subroutine("start", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, statements, Position.DUMMY) val labelInBlock = Label("label_outside", Position.DUMMY) - val varInBlock = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "var_outside", emptyList(),null, false, false, 0u, false, Position.DUMMY) + val varInBlock = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "var_outside", emptyList(),null, false, 0u, false, Position.DUMMY) val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY) val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test")) diff --git a/compiler/test/helpers/compileXyz.kt b/compiler/test/helpers/compileXyz.kt index 9a3025d3c..1da5ca37c 100644 --- a/compiler/test/helpers/compileXyz.kt +++ b/compiler/test/helpers/compileXyz.kt @@ -39,7 +39,7 @@ internal fun compileFile( symbolDefs = emptyMap(), outputDir = outputDir, errors = errors ?: ErrorReporterForTests(), - splitWordArrays = false, + dontSplitWordArrays = false, breakpointCpuInstruction = null, printAst1 = false, printAst2 = false, diff --git a/compilerAst/src/prog8/ast/Program.kt b/compilerAst/src/prog8/ast/Program.kt index 36ab6efee..48af21843 100644 --- a/compilerAst/src/prog8/ast/Program.kt +++ b/compilerAst/src/prog8/ast/Program.kt @@ -88,7 +88,7 @@ class Program(val name: String, val varName = "string_${internedStringsBlock.statements.size}" val decl = VarDecl( VarDeclType.VAR, VarDeclOrigin.STRINGLITERAL, DataType.forDt(BaseDataType.STR), ZeropageWish.NOT_IN_ZEROPAGE, null, varName, emptyList(), string, - sharedWithAsm = false, splitArray = false, alignment = 0u, dirty = false, position = string.position + sharedWithAsm = false, alignment = 0u, dirty = false, position = string.position ) internedStringsBlock.statements.add(decl) decl.linkParents(internedStringsBlock) diff --git a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt index 505fa814a..d51b0f2a0 100644 --- a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt +++ b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt @@ -758,20 +758,14 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl val identifiername = identifiers[0].NAME() ?: identifiers[0].UNDERSCORENAME() val name = if(identifiers.size==1) identifiername.text else "" val isArray = ARRAYSIG() != null || arrayindex() != null - val split = options.SPLIT().isNotEmpty() + val nosplit = options.NOSPLIT().isNotEmpty() val alignword = options.ALIGNWORD().isNotEmpty() val align64 = options.ALIGN64().isNotEmpty() val alignpage = options.ALIGNPAGE().isNotEmpty() if(alignpage && alignword) throw SyntaxError("choose a single alignment option", toPosition()) val baseDt = datatype()?.toAst() ?: BaseDataType.UNDEFINED - val origDt = DataType.forDt(baseDt) - val dt = if(isArray) { - if(split && origDt.isWord) - origDt.elementToArray(split) - else - origDt.elementToArray(false) // type error will be generated later in the ast check - } else origDt + val dt = if(isArray) DataType.arrayFor(baseDt, nosplit!=true) else DataType.forDt(baseDt) return VarDecl( type, VarDeclOrigin.USERCODE, @@ -785,7 +779,6 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl }, value, options.SHARED().isNotEmpty(), - split, if(alignword) 2u else if(align64) 64u else if(alignpage) 256u else 0u, options.DIRTY().isNotEmpty(), toPosition() diff --git a/compilerAst/src/prog8/ast/expressions/InferredTypes.kt b/compilerAst/src/prog8/ast/expressions/InferredTypes.kt index f060a9bad..016a5d790 100644 --- a/compilerAst/src/prog8/ast/expressions/InferredTypes.kt +++ b/compilerAst/src/prog8/ast/expressions/InferredTypes.kt @@ -91,7 +91,7 @@ object InferredTypes { } } type.isArray -> { - InferredType.known(DataType.arrayFor(type.sub!!.dt)) + InferredType.known(DataType.arrayFor(type.sub!!.dt, false)) } else -> throw IllegalArgumentException("invalid type") } diff --git a/compilerAst/src/prog8/ast/statements/AstStatements.kt b/compilerAst/src/prog8/ast/statements/AstStatements.kt index 72306ce56..4eec17d75 100644 --- a/compilerAst/src/prog8/ast/statements/AstStatements.kt +++ b/compilerAst/src/prog8/ast/statements/AstStatements.kt @@ -247,7 +247,6 @@ class VarDecl(val type: VarDeclType, val names: List, var value: Expression?, val sharedWithAsm: Boolean, - val splitArray: Boolean, val alignment: UInt, val dirty: Boolean, override val position: Position) : Statement(), INamedStatement { @@ -273,27 +272,21 @@ class VarDecl(val type: VarDeclType, val dt = if(param.type.isArray) DataType.forDt(BaseDataType.UWORD) else param.type return VarDecl(decltype, VarDeclOrigin.SUBROUTINEPARAM, dt, param.zp, null, param.name, emptyList(), value, sharedWithAsm = false, - splitArray = false, alignment = 0u, dirty = false, position = param.position ) } - fun createAuto(array: ArrayLiteral, splitArray: Boolean): VarDecl { + fun createAuto(array: ArrayLiteral): VarDecl { val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}" val arrayDt = array.type.getOrElse { throw FatalAstException("unknown dt") } val arraysize = ArrayIndex.forArray(array) return VarDecl(VarDeclType.VAR, VarDeclOrigin.ARRAYLITERAL, arrayDt, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, emptyList(), array, - sharedWithAsm = false, splitArray = splitArray, alignment = 0u, dirty = false, position = array.position) + sharedWithAsm = false, alignment = 0u, dirty = false, position = array.position) } } - init { - if(datatype.isSplitWordArray) - require(splitArray) - } - val isArray: Boolean get() = datatype.isArray @@ -329,7 +322,7 @@ class VarDecl(val type: VarDeclType, if(names.size>1) throw FatalAstException("should not copy a vardecl that still has multiple names") val copy = VarDecl(type, origin, newDatatype, zeropage, arraysize?.copy(), name, names, value?.copy(), - sharedWithAsm, splitArray, alignment, dirty, position) + sharedWithAsm, alignment, dirty, position) copy.allowInitializeWithZero = this.allowInitializeWithZero return copy } @@ -344,19 +337,19 @@ class VarDecl(val type: VarDeclType, // just copy the initialization value to a separate vardecl for each component return names.map { val copy = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), it, emptyList(), value?.copy(), - sharedWithAsm, splitArray, alignment, dirty, position) + sharedWithAsm, alignment, dirty, position) copy.allowInitializeWithZero = this.allowInitializeWithZero copy } } else { // evaluate the value once in the vardecl for the first component, and set the other components to the first val first = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), names[0], emptyList(), value?.copy(), - sharedWithAsm, splitArray, alignment, dirty, position) + sharedWithAsm, alignment, dirty, position) first.allowInitializeWithZero = this.allowInitializeWithZero val firstVar = firstVarAsValue(first) return listOf(first) + names.drop(1 ).map { val copy = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), it, emptyList(), firstVar.copy(), - sharedWithAsm, splitArray, alignment, dirty, position) + sharedWithAsm, alignment, dirty, position) copy.allowInitializeWithZero = this.allowInitializeWithZero copy } diff --git a/docs/source/compiling.rst b/docs/source/compiling.rst index a1fbc129a..1f0d5eb1c 100644 --- a/docs/source/compiling.rst +++ b/docs/source/compiling.rst @@ -156,6 +156,10 @@ One or more .p8 module files Add this user-defined symbol directly to the beginning of the generated assembly file. Can be repeated to define multiple symbols. +``-dontsplitarrays`` + Treat all word arrays as tagged with @nosplit so they are all stored linearly in memory, + instead of splitting them in separate lsb and msb arrays. + ``-dumpsymbols`` print a dump of the variable declarations and subroutine signatures @@ -219,11 +223,6 @@ One or more .p8 module files mixed in between the actual generated assembly code. This can be useful for debugging purposes to see what assembly was generated for what prog8 source code. -``-splitarrays`` - Treat all word arrays as tagged with @split so they are all lsb/msb split into memory. - This removes the need to add @split yourself but some programs may fail to compile with - this option as not all array operations are implemented yet on split arrays. - ``-srcdirs `` Specify a list of extra paths (separated with ':'), to search in for imported modules. Useful if you have library modules somewhere that you want to re-use, diff --git a/docs/source/programming.rst b/docs/source/programming.rst index 9608665f9..020475b41 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -403,7 +403,6 @@ Directives Overriding (monkeypatching) happens only if the signature of the subroutine exactly matches the original subroutine, including the exact names and types of the parameters. Where blocks with this option are merged into is intricate: it looks for the first other block with the same name that does not have %option merge, if that can't be found, select the first occurrence regardless. If no other blocks are found, no merge is done. Blocks in libraries are considered first to merge into. - - ``splitarrays`` (block or module) makes all word-arrays in this scope lsb/msb split arrays (as if they all have the @split tag). See Arrays. - ``no_symbol_prefixing`` (block or module) makes the compiler *not* use symbol-prefixing when translating prog8 code into assembly. Only use this if you know what you're doing because it could result in invalid assembly code being generated. This option can be useful when writing library modules that you don't want to be exposing prefixed assembly symbols. diff --git a/docs/source/todo.rst b/docs/source/todo.rst index e9fd37427..7e754fc0a 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,9 +1,15 @@ TODO ==== -- make word arrays split by default (remove @split tag) and use new @nosplit tag to make an array use the old storage format? Also invert -splitarrays command line option. -- add &< and &> operators to get the address of the lsb-array and msb-array, respectively. Regular & will just return the start of the split array in memory whatever byte comes first. +- DONE: make word arrays split by default (remove @split tag) and use new @nosplit tag to make an array use the old storage format? Also invert -splitarrays command line option. +- DONE: remove "splitarrays" %option switch +- Regular & will just return the start of the split array in memory whatever byte comes first. +- add &< and &> operators to get the address of the lsb-array and msb-array, respectively. +- fix containment_splitwordarray +- fix sprites.pos_batch +- fix anyall.anyw/allw - update Syntax files + Document all of this (also that word arrays can then have length 256 by default as well, and that @linear will reduce it to half.) +- test all examples ... diff --git a/docs/source/variables.rst b/docs/source/variables.rst index b19606eb0..32b3eec07 100644 --- a/docs/source/variables.rst +++ b/docs/source/variables.rst @@ -61,7 +61,7 @@ Tag Effect @requirezp force the variable into Zero page. If ZP is full, compilation will fail. @nozp force the variable to normal system ram, never place it into zeropage. @shared means the variable is shared with some assembly code and that it cannot be optimized away if not used elsewhere. -@split (only valid on (u)word arrays) Makes the array to be placed in memory as 2 separate byte arrays; one with the LSBs one with the MSBs of the word values. Usually improves performance and code size. +@nosplit (only valid on (u)word arrays) Store the array as a single inear array instead of a separate array for lsb and msb values @alignword aligns string or array variable on an even memory address @align64 aligns string or array variable on a 64 byte address interval (example: for C64 sprite data) @alignpage aligns string or array variable on a 256 byte address interval (example: to avoid page boundaries) diff --git a/examples/c64/bdmusic.p8 b/examples/c64/bdmusic.p8 index 4efb79444..4155e9829 100644 --- a/examples/c64/bdmusic.p8 +++ b/examples/c64/bdmusic.p8 @@ -71,7 +71,7 @@ sub print_notes(ubyte n1, ubyte n2) { ] - uword[] @split music_freq_table = [ + uword[] music_freq_table = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 732, 778, 826, 876, 928, 978, 1042, 1100, 1170, 1238, 1312, 1390, 1464, 1556, 1652, 1752, 1856, 1956, 2084, 2200, 2340, 2476, 2624, 2780, 2928, 3112, 3304, diff --git a/examples/c64/cube3d-sprites.p8 b/examples/c64/cube3d-sprites.p8 index 3c07ca064..0973e1ee4 100644 --- a/examples/c64/cube3d-sprites.p8 +++ b/examples/c64/cube3d-sprites.p8 @@ -8,14 +8,14 @@ main { const uword height = 200 ; vertices - word[] @split xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ] - word[] @split ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ] - word[] @split zcoor = [ -100, 100, -100, 100, -100, 100, -100, 100 ] + word[] xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ] + word[] ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ] + word[] zcoor = [ -100, 100, -100, 100, -100, 100, -100, 100 ] ; storage for rotated coordinates - word[len(xcoor)] @split rotatedx - word[len(ycoor)] @split rotatedy - word[len(zcoor)] @split rotatedz + word[len(xcoor)] rotatedx + word[len(ycoor)] rotatedy + word[len(zcoor)] rotatedz sub start() { diff --git a/examples/c64/cube3d.p8 b/examples/c64/cube3d.p8 index 4eed0a328..d3f0a652f 100644 --- a/examples/c64/cube3d.p8 +++ b/examples/c64/cube3d.p8 @@ -6,14 +6,14 @@ main { ; vertices - word[] @split xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ] - word[] @split ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ] - word[] @split zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ] + word[] xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ] + word[] ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ] + word[] zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ] ; storage for rotated coordinates - word[len(xcoor)] @split rotatedx - word[len(ycoor)] @split rotatedy - word[len(zcoor)] @split rotatedz + word[len(xcoor)] rotatedx + word[len(ycoor)] rotatedy + word[len(zcoor)] rotatedz sub start() { diff --git a/examples/cube3d-gfx.p8 b/examples/cube3d-gfx.p8 index ecedf3553..6d78f906e 100644 --- a/examples/cube3d-gfx.p8 +++ b/examples/cube3d-gfx.p8 @@ -7,14 +7,14 @@ main { ; vertices - word[] @split xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ] - word[] @split ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ] - word[] @split zcoor = [ -100, 100, -100, 100, -100, 100, -100, 100 ] + word[] xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ] + word[] ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ] + word[] zcoor = [ -100, 100, -100, 100, -100, 100, -100, 100 ] ; storage for rotated coordinates - word[len(xcoor)] @split rotatedx - word[len(ycoor)] @split rotatedy - word[len(zcoor)] @split rotatedz + word[len(xcoor)] rotatedx + word[len(ycoor)] rotatedy + word[len(zcoor)] rotatedz ; edges ubyte[] edgesFrom = [ 0, 2, 6, 4, 1, 3, 7, 5, 0, 2, 6, 4] diff --git a/examples/cx16/bdmusic.p8 b/examples/cx16/bdmusic.p8 index d34e61bdd..28813322b 100644 --- a/examples/cx16/bdmusic.p8 +++ b/examples/cx16/bdmusic.p8 @@ -115,7 +115,7 @@ main { $3532, $322e, $2e29, $2926, $2730, $242c, $2027, $1420 ] - uword[] @split vera_freqs = [ + uword[] vera_freqs = [ 0,0,0,0,0,0,0,0,0,0, ; first 10 notes are not used 120, 127, 135, 143, 152, 160, 170, 180, 191, 203, 215, 227, 240, 255, 270, 287, 304, 320, 341, 360, diff --git a/examples/cx16/circles.p8 b/examples/cx16/circles.p8 index 6ff1353d4..c69036480 100644 --- a/examples/cx16/circles.p8 +++ b/examples/cx16/circles.p8 @@ -5,8 +5,8 @@ main { const ubyte MAX_NUM_CIRCLES = 80 const ubyte GROWTH_RATE = 2 - uword[MAX_NUM_CIRCLES] @split circle_x - uword[MAX_NUM_CIRCLES] @split circle_y + uword[MAX_NUM_CIRCLES] circle_x + uword[MAX_NUM_CIRCLES] circle_y ubyte[MAX_NUM_CIRCLES] circle_radius ubyte num_circles = 0 ubyte background_color diff --git a/examples/cx16/cobramk3-gfx.p8 b/examples/cx16/cobramk3-gfx.p8 index 154e1aeb9..5f484c540 100644 --- a/examples/cx16/cobramk3-gfx.p8 +++ b/examples/cx16/cobramk3-gfx.p8 @@ -165,9 +165,9 @@ matrix_math { %option verafxmuls ; accellerate all word-multiplications in this block using Vera FX hardware muls ; storage for rotated coordinates - word[shipdata.totalNumberOfPoints] @split rotatedx - word[shipdata.totalNumberOfPoints] @split rotatedy - word[shipdata.totalNumberOfPoints] @split rotatedz + word[shipdata.totalNumberOfPoints] rotatedx + word[shipdata.totalNumberOfPoints] rotatedy + word[shipdata.totalNumberOfPoints] rotatedz sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) { ; rotate around origin (0,0,0) @@ -230,9 +230,9 @@ const ubyte totalNumberOfFaces = 22 const ubyte totalNumberOfPoints = 34 str shipName = "cobra-mk3" ; vertices -word[totalNumberOfPoints] @split xcoor = [ 32,-32,0,-120,120,-88,88,128,-128,0,-32,32,-36,-8,8,36,36,8,-8,-36,-1,-1,-80,-80,-88,80,88,80,1,1,1,1,-1,-1 ] -word[totalNumberOfPoints] @split ycoor = [ 0,0,26,-3,-3,16,16,-8,-8,26,-24,-24,8,12,12,8,-12,-16,-16,-12,-1,-1,-6,6,0,6,0,-6,-1,-1,1,1,1,1 ] -word[totalNumberOfPoints] @split zcoor = [ 76,76,24,-8,-8,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,76,90,-40,-40,-40,-40,-40,-40,76,90,76,90,76,90 ] +word[totalNumberOfPoints] xcoor = [ 32,-32,0,-120,120,-88,88,128,-128,0,-32,32,-36,-8,8,36,36,8,-8,-36,-1,-1,-80,-80,-88,80,88,80,1,1,1,1,-1,-1 ] +word[totalNumberOfPoints] ycoor = [ 0,0,26,-3,-3,16,16,-8,-8,26,-24,-24,8,12,12,8,-12,-16,-16,-12,-1,-1,-6,6,0,6,0,-6,-1,-1,1,1,1,1 ] +word[totalNumberOfPoints] zcoor = [ 76,76,24,-8,-8,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,76,90,-40,-40,-40,-40,-40,-40,76,90,76,90,76,90 ] ; edges and faces ubyte[totalNumberOfEdges] edgesFrom = [ 0,1,0,10,1,0,2,0,4,0,4,7,2,1,1,3,8,3,2,5,6,5,6,16,15,14,14,18,13,12,12,26,25,25,22,23,22,20,28,21,20,28,29,30,31,30,32,20,21,20,20 ] ubyte[totalNumberOfEdges] edgesTo = [ 1,2,2,11,10,11,6,6,6,4,7,11,5,5,3,5,10,8,9,9,9,8,7,17,16,15,17,19,18,13,19,27,26,27,23,24,24,28,29,29,21,30,31,31,33,32,33,32,33,33,29 ] diff --git a/examples/cx16/cube3d.p8 b/examples/cx16/cube3d.p8 index 2ce556560..74794b6dd 100644 --- a/examples/cx16/cube3d.p8 +++ b/examples/cx16/cube3d.p8 @@ -58,14 +58,14 @@ matrix_math { %option verafxmuls ; accellerate all word-multiplications in this block using Vera FX hardware muls ; vertices - word[] @split xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ] - word[] @split ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ] - word[] @split zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ] + word[] xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ] + word[] ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ] + word[] zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ] ; storage for rotated coordinates - word[len(xcoor)] @split rotatedx - word[len(ycoor)] @split rotatedy - word[len(zcoor)] @split rotatedz + word[len(xcoor)] rotatedx + word[len(ycoor)] rotatedy + word[len(zcoor)] rotatedz sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) { ; rotate around origin (0,0,0) diff --git a/examples/cx16/pcmaudio/adpcm.p8 b/examples/cx16/pcmaudio/adpcm.p8 index cdd3a30d2..8dee50793 100644 --- a/examples/cx16/pcmaudio/adpcm.p8 +++ b/examples/cx16/pcmaudio/adpcm.p8 @@ -29,7 +29,7 @@ adpcm { byte[] t_index = [ -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8] - uword[] @split t_step = [ + uword[] t_step = [ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, diff --git a/examples/cx16/pcmaudio/vumeter.p8 b/examples/cx16/pcmaudio/vumeter.p8 index c32e0e1b8..eeb02b7c7 100644 --- a/examples/cx16/pcmaudio/vumeter.p8 +++ b/examples/cx16/pcmaudio/vumeter.p8 @@ -316,8 +316,8 @@ main { cx16.VERA_DATA0 = msb(fill_rgb) } - uword[22] @split outline_color = [$090,$190,$290,$390,$490,$590,$690,$790,$990,$980,$970,$960,$950,$940,$a30,$a00,$a00,$a00,$a00,$a00, $111, $148] - uword[22] @split fill_color = [$0f0,$2f0,$4f0,$6f0,$8f0,$af0,$cf0,$ef0,$ff0,$fe0,$fc0,$fa0,$f80,$f60,$f40,$f00,$f01,$f02,$f03,$f04, $000, $28f] + uword[22] outline_color = [$090,$190,$290,$390,$490,$590,$690,$790,$990,$980,$970,$960,$950,$940,$a30,$a00,$a00,$a00,$a00,$a00, $111, $148] + uword[22] fill_color = [$0f0,$2f0,$4f0,$6f0,$8f0,$af0,$cf0,$ef0,$ff0,$fe0,$fc0,$fa0,$f80,$f60,$f40,$f00,$f01,$f02,$f03,$f04, $000, $28f] } } diff --git a/examples/cx16/snow.p8 b/examples/cx16/snow.p8 index babf6af02..8d7d850a0 100644 --- a/examples/cx16/snow.p8 +++ b/examples/cx16/snow.p8 @@ -5,9 +5,9 @@ main { sub start() { gfx_lores.graphics_mode() - uword[128] @split flakes1_xx + uword[128] flakes1_xx ubyte[128] flakes1_yy - uword[128] @split flakes2_xx + uword[128] flakes2_xx ubyte[128] flakes2_yy ubyte @zp idx diff --git a/examples/cx16/starszoom.p8 b/examples/cx16/starszoom.p8 index 42e3181e7..bf3968a96 100644 --- a/examples/cx16/starszoom.p8 +++ b/examples/cx16/starszoom.p8 @@ -18,10 +18,10 @@ main { const ubyte CIRCLE_SKIP = 256/NUM_STARS ubyte[NUM_STARS] color - uword[NUM_STARS] @split radius - uword[NUM_STARS] @split accel - uword[NUM_STARS] @split speed - uword[NUM_STARS] @split prev_x + uword[NUM_STARS] radius + uword[NUM_STARS] accel + uword[NUM_STARS] speed + uword[NUM_STARS] prev_x ubyte[NUM_STARS] prev_y gfx_lores.graphics_mode() diff --git a/examples/test.p8 b/examples/test.p8 index 10f056a1e..d32e5d3ab 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,18 +1,15 @@ +%import textio +%zeropage basicsafe + main { + uword[] array = [1000, 2000, 9000, 8000, 5000] sub start() { - goto $3000 - goto labeltje - - goto cx16.r0 - - goto cx16.r0+cx16.r1 - - if cx16.r0==0 - goto cx16.r0+cx16.r1 - - if cx16.r0>2000 - goto cx16.r0+cx16.r1 - -labeltje: + txt.print_bool(1000 in array) + txt.spc() + txt.print_bool(9000 in array) + txt.spc() + txt.print_bool(5000 in array) + txt.spc() + txt.print_bool(9001 in array) } } diff --git a/examples/vm/bouncegfx.p8 b/examples/vm/bouncegfx.p8 index 9ba030fe3..ecf946eda 100644 --- a/examples/vm/bouncegfx.p8 +++ b/examples/vm/bouncegfx.p8 @@ -5,8 +5,8 @@ main { sub start() { - word[128] @split particleX - word[128] @split particleY + word[128] particleX + word[128] particleY byte[128] particleDX byte[128] particleDY diff --git a/intermediate/src/prog8/intermediate/IRFileReader.kt b/intermediate/src/prog8/intermediate/IRFileReader.kt index 148953bae..8925fe7c2 100644 --- a/intermediate/src/prog8/intermediate/IRFileReader.kt +++ b/intermediate/src/prog8/intermediate/IRFileReader.kt @@ -289,7 +289,7 @@ class IRFileReader { val (name, size, align) = match.destructured val dummyNode = PtVariable( name, - DataType.arrayFor(BaseDataType.UBYTE), + DataType.arrayFor(BaseDataType.UBYTE, false), ZeropageWish.NOT_IN_ZEROPAGE, 0u, null, @@ -514,14 +514,12 @@ class IRFileReader { private fun parseDatatype(type: String, isArray: Boolean): DataType { if(isArray) { return when(type) { - "bool" -> DataType.arrayFor(BaseDataType.BOOL) - "byte" -> DataType.arrayFor(BaseDataType.BYTE) - "ubyte", "str" -> DataType.arrayFor(BaseDataType.UBYTE) - "word" -> DataType.arrayFor(BaseDataType.WORD) - "uword" -> DataType.arrayFor(BaseDataType.UWORD) - "float" -> DataType.arrayFor(BaseDataType.FLOAT) - "uword_split" -> DataType.arrayFor(BaseDataType.UWORD, true) - "word_split" -> DataType.arrayFor(BaseDataType.WORD, true) + "bool" -> DataType.arrayFor(BaseDataType.BOOL, false) + "byte" -> DataType.arrayFor(BaseDataType.BYTE, false) + "ubyte", "str" -> DataType.arrayFor(BaseDataType.UBYTE, false) + "word" -> DataType.arrayFor(BaseDataType.WORD, false) + "uword" -> DataType.arrayFor(BaseDataType.UWORD, false) + "float" -> DataType.arrayFor(BaseDataType.FLOAT, false) else -> throw IRParseException("invalid dt $type") } } else { diff --git a/intermediate/src/prog8/intermediate/Utils.kt b/intermediate/src/prog8/intermediate/Utils.kt index 1904773b0..d667892d5 100644 --- a/intermediate/src/prog8/intermediate/Utils.kt +++ b/intermediate/src/prog8/intermediate/Utils.kt @@ -30,8 +30,8 @@ fun DataType.typeString(length: Int?): String { } BaseDataType.ARRAY_SPLITW -> { when(this.sub?.dt) { - BaseDataType.UWORD -> "@split uword[$lengthStr]" // should be 2 separate byte arrays by now really? - BaseDataType.WORD -> "@split word[$lengthStr]" // should be 2 separate byte arrays by now really? + BaseDataType.UWORD -> "uword[$lengthStr]" // should be 2 separate byte arrays by now really? + BaseDataType.WORD -> "word[$lengthStr]" // should be 2 separate byte arrays by now really? else -> throw IllegalArgumentException("invalid sub type") } } diff --git a/parser/src/main/antlr/Prog8ANTLR.g4 b/parser/src/main/antlr/Prog8ANTLR.g4 index 1b138ee89..9e3c6cbd6 100644 --- a/parser/src/main/antlr/Prog8ANTLR.g4 +++ b/parser/src/main/antlr/Prog8ANTLR.g4 @@ -61,7 +61,7 @@ ZEROPAGENOT: '@nozp' ; SHARED : '@shared' ; -SPLIT: '@split' ; +NOSPLIT: '@nosplit' ; ALIGNWORD: '@alignword' ; @@ -159,7 +159,7 @@ directivearg : stringliteral | identifier | integerliteral ; vardecl: datatype (arrayindex | ARRAYSIG)? decloptions identifier (',' identifier)* ; -decloptions: (SHARED | ZEROPAGE | ZEROPAGEREQUIRE | ZEROPAGENOT | SPLIT | ALIGNWORD | ALIGN64 | ALIGNPAGE | DIRTY)* ; +decloptions: (SHARED | ZEROPAGE | ZEROPAGEREQUIRE | ZEROPAGENOT | NOSPLIT | ALIGNWORD | ALIGN64 | ALIGNPAGE | DIRTY)* ; varinitializer : vardecl '=' expression ;