diff --git a/codeCore/src/prog8/code/core/Enumerations.kt b/codeCore/src/prog8/code/core/Enumerations.kt index 750ac8304..e5b8fd0a9 100644 --- a/codeCore/src/prog8/code/core/Enumerations.kt +++ b/codeCore/src/prog8/code/core/Enumerations.kt @@ -161,7 +161,7 @@ val ElementToArrayTypes = mapOf( DataType.UWORD to DataType.ARRAY_UW, DataType.FLOAT to DataType.ARRAY_F, DataType.BOOL to DataType.ARRAY_BOOL, - DataType.STR to DataType.UWORD // array of str is just an array of pointers + DataType.STR to DataType.ARRAY_UW // array of str is just an array of pointers ) val Cx16VirtualRegisters = arrayOf( diff --git a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt index 6d7840e8d..e90d5c3c3 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt @@ -45,8 +45,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter, } override fun visit(decl: VarDecl) { - decl.datatypeErrors.forEach { errors.err(it.message, it.position) } - if(decl.name in BuiltinFunctions) errors.err("builtin function cannot be redefined", decl.position) diff --git a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt index eae3fb5e7..4561166e2 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt @@ -195,9 +195,8 @@ class AstPreprocessor(val program: Program, } private fun makeSplitArray(decl: VarDecl): Iterable { - val splitDt = ArrayToElementTypes.getValue(decl.datatype) val newDecl = VarDecl( - decl.type, decl.origin, splitDt, decl.zeropage, decl.arraysize, decl.name, emptyList(), + decl.type, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, emptyList(), decl.value, true, decl.sharedWithAsm, true, decl.position ) return listOf(IAstModification.ReplaceNode(decl, newDecl, decl.parent)) diff --git a/compiler/src/prog8/compiler/astprocessing/BoolRemover.kt b/compiler/src/prog8/compiler/astprocessing/BoolRemover.kt index e16edd6cf..3e39fcb0c 100644 --- a/compiler/src/prog8/compiler/astprocessing/BoolRemover.kt +++ b/compiler/src/prog8/compiler/astprocessing/BoolRemover.kt @@ -29,8 +29,8 @@ internal class BoolRemover(val program: Program) : AstWalker() { if(newvalue.number!=0.0) newvalue = NumericLiteral(DataType.UBYTE, 1.0, newvalue.position) } - val ubyteDecl = VarDecl(decl.type, decl.origin, DataType.UBYTE, decl.zeropage, decl.arraysize, decl.name, emptyList(), - newvalue, decl.isArray, decl.sharedWithAsm, decl.splitArray, decl.position) + val ubyteDecl = VarDecl(decl.type, decl.origin, DataType.UBYTE, decl.zeropage, null, decl.name, emptyList(), + newvalue, false, decl.sharedWithAsm, false, decl.position) return listOf(IAstModification.ReplaceNode(decl, ubyteDecl, parent)) } diff --git a/compiler/test/TestMemory.kt b/compiler/test/TestMemory.kt index 205556623..7b88a02d2 100644 --- a/compiler/test/TestMemory.kt +++ b/compiler/test/TestMemory.kt @@ -185,7 +185,7 @@ class TestMemory: FunSpec({ } test("array not in mapped IO ram") { - val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, false, false, Position.DUMMY) + val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), null, true, false, 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, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) @@ -198,7 +198,7 @@ class TestMemory: FunSpec({ test("memory mapped array not in mapped IO ram") { val address = 0x1000u - val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), true, false, 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, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) @@ -211,7 +211,7 @@ class TestMemory: FunSpec({ test("memory mapped array in mapped IO ram") { val address = 0xd800u - val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), true, false, 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, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) diff --git a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt index 7e51cda2d..251b5d065 100644 --- a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt +++ b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt @@ -654,18 +654,31 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl } val identifiers = identifier() val name = if(identifiers.size==1) identifiers[0].NAME().text else "" + val isArray = ARRAYSIG() != null || arrayindex() != null + val split = options.SPLIT().isNotEmpty() + val origDt = datatype()?.toAst() ?: DataType.UNDEFINED + val dt = if(isArray) { + val arrayDt = ElementToArrayTypes.getValue(origDt) + if(split) { + when(arrayDt) { + DataType.ARRAY_UW -> DataType.ARRAY_UW_SPLIT + DataType.ARRAY_W -> DataType.ARRAY_W_SPLIT + else -> throw SyntaxError("split can only be used on word arrays", toPosition()) + } + } else arrayDt + } else origDt return VarDecl( type, VarDeclOrigin.USERCODE, - datatype()?.toAst() ?: DataType.UNDEFINED, + dt, zp, arrayindex()?.toAst(), name, if(identifiers.size==1) emptyList() else identifiers.map { it.NAME().text }, value, - ARRAYSIG() != null || arrayindex() != null, + isArray, options.SHARED().isNotEmpty(), - options.SPLIT().isNotEmpty(), + split, toPosition() ) } diff --git a/compilerAst/src/prog8/ast/statements/AstStatements.kt b/compilerAst/src/prog8/ast/statements/AstStatements.kt index 8ce695e77..03a7f9d2a 100644 --- a/compilerAst/src/prog8/ast/statements/AstStatements.kt +++ b/compilerAst/src/prog8/ast/statements/AstStatements.kt @@ -2,7 +2,6 @@ package prog8.ast.statements import prog8.ast.* import prog8.ast.base.FatalAstException -import prog8.ast.base.SyntaxError import prog8.ast.expressions.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstVisitor @@ -204,7 +203,7 @@ enum class VarDeclType { class VarDecl(val type: VarDeclType, val origin: VarDeclOrigin, - private val declaredDatatype: DataType, + val datatype: DataType, var zeropage: ZeropageWish, var arraysize: ArrayIndex?, override val name: String, @@ -217,13 +216,19 @@ class VarDecl(val type: VarDeclType, override lateinit var parent: Node var allowInitializeWithZero = true - // prefix for literal values that are turned into a variable on the heap + init { + if(isArray) + require(datatype in ArrayDatatypes) { "array dt mismatch" } + else + require(datatype !in ArrayDatatypes) { "array dt mismatch" } + } companion object { private var autoHeapValueSequenceNumber = 0 fun fromParameter(param: SubroutineParameter): VarDecl { - return VarDecl(VarDeclType.VAR, VarDeclOrigin.SUBROUTINEPARAM, param.type, ZeropageWish.DONTCARE, null, param.name, emptyList(), null, + val dt = if(param.type in ArrayDatatypes) DataType.UWORD else param.type + return VarDecl(VarDeclType.VAR, VarDeclOrigin.SUBROUTINEPARAM, dt, ZeropageWish.DONTCARE, null, param.name, emptyList(), null, isArray = false, sharedWithAsm = false, splitArray = false, @@ -234,45 +239,12 @@ class VarDecl(val type: VarDeclType, fun createAuto(array: ArrayLiteral, splitArray: Boolean): VarDecl { val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}" val arrayDt = array.type.getOrElse { throw FatalAstException("unknown dt") } - val declaredType = ArrayToElementTypes.getValue(arrayDt) val arraysize = ArrayIndex.forArray(array) - return VarDecl(VarDeclType.VAR, VarDeclOrigin.ARRAYLITERAL, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, emptyList(), array, + return VarDecl(VarDeclType.VAR, VarDeclOrigin.ARRAYLITERAL, arrayDt, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, emptyList(), array, isArray = true, sharedWithAsm = false, splitArray = splitArray, position = array.position) } } - val datatypeErrors = mutableListOf() // don't crash at init time, report them in the AstChecker - val datatype: DataType - - init { - val dt = - if (!isArray) declaredDatatype - else when (declaredDatatype) { - DataType.UBYTE -> DataType.ARRAY_UB - DataType.BYTE -> DataType.ARRAY_B - DataType.UWORD -> DataType.ARRAY_UW - DataType.WORD -> DataType.ARRAY_W - DataType.FLOAT -> DataType.ARRAY_F - DataType.BOOL -> DataType.ARRAY_BOOL - DataType.STR -> DataType.ARRAY_UW // use memory address of the string instead - else -> { - datatypeErrors.add(SyntaxError("array can only contain bytes/words/floats/strings(ptrs)", position)) - DataType.ARRAY_UB - } - } - - datatype = if(splitArray) { - when(dt) { - DataType.ARRAY_UW -> DataType.ARRAY_UW_SPLIT - DataType.ARRAY_W -> DataType.ARRAY_W_SPLIT - else -> { - datatypeErrors.add(SyntaxError("split can only be used on word arrays", position)) - DataType.UNDEFINED - } - } - } else dt - } - override fun linkParents(parent: Node) { this.parent = parent arraysize?.linkParents(this) @@ -291,8 +263,10 @@ class VarDecl(val type: VarDeclType, "VarDecl(name=$name, vartype=$type, datatype=$datatype, value=$value, pos=$position)" fun zeroElementValue(): NumericLiteral { - if(allowInitializeWithZero) - return defaultZero(declaredDatatype, position) + if(allowInitializeWithZero) { + return if(isArray) defaultZero(ArrayToElementTypes.getValue(datatype), position) + else defaultZero(datatype, position) + } else throw IllegalArgumentException("attempt to get zero value for vardecl that shouldn't get it") } @@ -300,7 +274,7 @@ class VarDecl(val type: VarDeclType, override fun copy(): VarDecl { if(names.size>1) throw FatalAstException("should not copy a vardecl that still has multiple names") - val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), name, names, value?.copy(), + val copy = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), name, names, value?.copy(), isArray, sharedWithAsm, splitArray, position) copy.allowInitializeWithZero = this.allowInitializeWithZero return copy @@ -320,19 +294,19 @@ class VarDecl(val type: VarDeclType, if(value?.isSimple==true) { // just copy the initialization value to a separata vardecl for each component return names.map { - val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), it, emptyList(), value?.copy(), + val copy = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), it, emptyList(), value?.copy(), isArray, sharedWithAsm, splitArray, 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, declaredDatatype, zeropage, arraysize?.copy(), names[0], emptyList(), value?.copy(), + val first = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), names[0], emptyList(), value?.copy(), isArray, sharedWithAsm, splitArray, position) first.allowInitializeWithZero = this.allowInitializeWithZero val firstVar = firstVarAsValue(first) return listOf(first) + names.drop(1 ).map { - val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), it, emptyList(), firstVar.copy(), + val copy = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), it, emptyList(), firstVar.copy(), isArray, sharedWithAsm, splitArray, position) copy.allowInitializeWithZero = this.allowInitializeWithZero copy diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 3f85226cb..5b57b5e57 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -2,9 +2,6 @@ TODO ==== -- get rid of vardecl.declareddatatype -- get rid of memory mapped variables: treat them as syntactic sugar for a poke/peek to the symbol. - - add -nowarnunused, or %option ignore_unused (module and block scope), to suppress all warnings about unused symbols. Useful in libraries. put this in all library code, like %option no_symbol_prefixing, and get rid of the "trick" it uses currently to suppress unused symbol warnings for library modules. diff --git a/examples/test.p8 b/examples/test.p8 index b88e1caed..51782d0da 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,36 +1,10 @@ %import textio -%import floats %zeropage basicsafe main { sub start() { - uword zz - word zz2 - ubyte bb - byte bb2 - - bb2 |= bb - bb2 |= zz2 - -; uword[20] @split foobar -; ubyte[20] @split foobar2 -; -; sys.push(11) -; sys.pushw(2222) -; floats.push(floats.π) -; cx16.r2++ -; -; float pi = floats.pop() -; floats.print_f(pi) -; txt.nl() -; -; cx16.r1 = sys.popw() -; cx16.r0L = sys.pop() -; -; txt.print_ub(cx16.r0L) -; txt.nl() -; txt.print_uw(cx16.r1) -; txt.nl() - + str[] names = ["irmen", "de", "jong"] + uword zz = names[1] + txt.print(names[1]) } }