From a0bc97b90c5a9e19d916c3c7d6789324ef37a547 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 9 Feb 2020 00:45:53 +0100 Subject: [PATCH] fix byte array iteration for bb in [1,2,3] improved array literal datatype detection --- .../prog8/ast/expressions/AstExpressions.kt | 22 +++++++++++++++++- .../src/prog8/ast/processing/AstChecker.kt | 5 +++- .../ast/processing/AstIdentifiersChecker.kt | 23 ++++++++++++------- docs/source/todo.rst | 1 - 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/compiler/src/prog8/ast/expressions/AstExpressions.kt b/compiler/src/prog8/ast/expressions/AstExpressions.kt index 857a0447c..996130b7d 100644 --- a/compiler/src/prog8/ast/expressions/AstExpressions.kt +++ b/compiler/src/prog8/ast/expressions/AstExpressions.kt @@ -63,7 +63,27 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this) override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun referencesIdentifiers(vararg name: String) = expression.referencesIdentifiers(*name) - override fun inferType(program: Program): InferredTypes.InferredType = expression.inferType(program) + override fun inferType(program: Program): InferredTypes.InferredType { + val inferred = expression.inferType(program) + return when(operator) { + "+" -> inferred + "~", "not" -> { + when(inferred.typeOrElse(DataType.STRUCT)) { + in ByteDatatypes -> InferredTypes.knownFor(DataType.UBYTE) + in WordDatatypes -> InferredTypes.knownFor(DataType.UWORD) + else -> inferred + } + } + "-" -> { + when(inferred.typeOrElse(DataType.STRUCT)) { + in ByteDatatypes -> InferredTypes.knownFor(DataType.BYTE) + in WordDatatypes -> InferredTypes.knownFor(DataType.WORD) + else -> inferred + } + } + else -> throw FatalAstException("weird prefix expression operator") + } + } override fun toString(): String { return "Prefix($operator $expression)" diff --git a/compiler/src/prog8/ast/processing/AstChecker.kt b/compiler/src/prog8/ast/processing/AstChecker.kt index 1b629c23c..da6e1565e 100644 --- a/compiler/src/prog8/ast/processing/AstChecker.kt +++ b/compiler/src/prog8/ast/processing/AstChecker.kt @@ -144,7 +144,6 @@ internal class AstChecker(private val program: Program, checkResult.add(ExpressionError("uword loop variable can only loop over unsigned bytes, words or strings", forLoop.position)) } DataType.BYTE -> { - // TODO fix this, it should allow: for bb in [1,2,3] if(iterableDt!= DataType.BYTE && iterableDt!= DataType.ARRAY_B) checkResult.add(ExpressionError("byte loop variable can only loop over bytes", forLoop.position)) } @@ -1200,6 +1199,10 @@ internal class AstChecker(private val program: Program, when (it) { is NumericLiteralValue -> it.number.toInt() is AddressOf -> it.identifier.heapId(program.namespace) + is TypecastExpression -> { + val constVal = it.expression.constValue(program) + constVal?.cast(it.type)?.number?.toInt() ?: -9999999 + } else -> -9999999 } } diff --git a/compiler/src/prog8/ast/processing/AstIdentifiersChecker.kt b/compiler/src/prog8/ast/processing/AstIdentifiersChecker.kt index 93637725a..fc159ce2e 100644 --- a/compiler/src/prog8/ast/processing/AstIdentifiersChecker.kt +++ b/compiler/src/prog8/ast/processing/AstIdentifiersChecker.kt @@ -235,10 +235,12 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi // fix the datatype of the array (also on the heap) to the 'biggest' datatype in the array // (we don't know the desired datatype here exactly so we guess) val datatype = determineArrayDt(array.value) - val litval2 = array.cast(datatype)!! - litval2.parent = array.parent - // finally, replace the literal array by a identifier reference. - makeIdentifierFromRefLv(litval2) + val litval2 = array.cast(datatype) + if(litval2!=null) { + litval2.parent = array.parent + // finally, replace the literal array by a identifier reference. + makeIdentifierFromRefLv(litval2) + } else array } } return array @@ -366,10 +368,15 @@ internal fun fixupArrayEltDatatypes(array: ArrayLiteralValue, program: Program): // convert values and array type val elementType = ArrayElementTypes.getValue(dt) - val values = array.value.map { (it as NumericLiteralValue).cast(elementType) as Expression}.toTypedArray() - val array2 = ArrayLiteralValue(dt, values, array.position) - array2.linkParents(array.parent) - return array2 + val allNumerics = array.value.all { it is NumericLiteralValue } + if(allNumerics) { + val values = array.value.map { (it as NumericLiteralValue).cast(elementType) as Expression }.toTypedArray() + val array2 = ArrayLiteralValue(dt, values, array.position) + array2.linkParents(array.parent) + return array2 + } + + return array } internal fun fixupArrayEltDatatypesFromVardecl(array: ArrayLiteralValue, vardecl: VarDecl): ArrayLiteralValue { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index b9a98f2de..fb643b9aa 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -4,7 +4,6 @@ TODO - @"zzz" screencode encoded strings + add this to docs too - add 'void' keyword to explicitly ignore subroutine return values -- allow: for bb in [1,2,3] + docs? Memory Block Operations integrated in language?