From c70bbdab26ef9479e01bdc2d3126128ccc0ca5c8 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 18 Apr 2021 22:46:21 +0200 Subject: [PATCH] fixed missing type checking in vardecl initializer values. Fixes #29 Also fix wrong assert of 0 const check in assembly gen for if-statement comparisons. --- .../compiler/BeforeAsmGenerationAstChanger.kt | 4 +++- .../prog8/compiler/astprocessing/AstChecker.kt | 4 ++-- .../astprocessing/StatementReorderer.kt | 7 +++++++ .../compiler/astprocessing/TypecastsAdder.kt | 4 ++++ examples/test.p8 | 17 ++++------------- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index d785f75f0..3c9c3b33a 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -194,7 +194,9 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: I return listOf(IAstModification.ReplaceNode(ifStatement.condition, booleanExpr, ifStatement)) } - if((binExpr.left as? NumericLiteralValue)?.number==0) + if((binExpr.operator=="==" || binExpr.operator=="!=") && + (binExpr.left as? NumericLiteralValue)?.number==0 && + (binExpr.right as? NumericLiteralValue)?.number!=0) throw CompilerException("if 0==X should have been swapped to if X==0") // split the conditional expression into separate variables if the operand(s) is not simple. diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 37c77c457..9c5c8dcba 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -409,7 +409,7 @@ internal class AstChecker(private val program: Program, if(targetDt.typeOrElse(DataType.STRUCT) in IterableDatatypes) errors.err("cannot assign value to string or array", assignment.value.position) else if(!(valueDt.istype(DataType.STR) && targetDt.istype(DataType.UWORD))) - errors.err("value's type doesn't match target", assignment.value.position) + errors.err("type of value doesn't match target", assignment.value.position) } if(assignment.value is TypecastExpression) { @@ -562,7 +562,7 @@ internal class AstChecker(private val program: Program, } val memberDt = memberdecl.datatype if(!checkValueTypeAndRange(memberDt, constValue)) { - errors.err("struct member value's type is not compatible with member field '${memberdecl.name}'", value.first.position) + errors.err("type of struct member value is not compatible with member field '${memberdecl.name}'", value.first.position) return } } diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index 82a9e6b77..60fa1cabc 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -104,6 +104,13 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport } override fun after(expr: BinaryExpression, parent: Node): Iterable { + + // ConstValue X --> X ConstValue + // (this should be done by the ExpressionSimplifier when optimizing is enabled, + // but the current assembly code generator for IF statements now also depends on it so we do it here regardless of optimization.) + if (expr.left.constValue(program) != null && expr.operator in associativeOperators && expr.right.constValue(program) == null) + return listOf(IAstModification.SwapOperands(expr)) + // when using a simple bit shift and assigning it to a variable of a different type, // try to make the bit shifting 'wide enough' to fall into the variable's type. // with this, for instance, uword x = 1 << 10 will result in 1024 rather than 0 (the ubyte result). diff --git a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt index 477515ee6..f66514976 100644 --- a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt +++ b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt @@ -28,6 +28,10 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk if(valueDt.typeOrElse(DataType.STRUCT) in IntegerDatatypes && decl.datatype in ArrayDatatypes) return noModifications + // don't add a typecast if the initializer value is inherently not assignable + if(valueDt isNotAssignableTo decl.datatype) + return noModifications + return listOf(IAstModification.ReplaceNode( declValue, TypecastExpression(declValue, decl.datatype, true, declValue.position), diff --git a/examples/test.p8 b/examples/test.p8 index 992a59ab3..6bd687d3b 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,20 +4,11 @@ main { sub start() { - str anim = "1234" - ubyte anim_counter = 0 - - test_stack.test() - - txt.print("loading ") - repeat 100 { - ubyte qq = anim[anim_counter/2] - txt.chrout(qq) - anim_counter = (anim_counter+1) & 7 + ubyte xx=99 + if 0==xx { + txt.print("fout") } - txt.print("done!\n") - - test_stack.test() + txt.print("loading ") } }