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.
This commit is contained in:
Irmen de Jong 2021-04-18 22:46:21 +02:00
parent 3d956ef554
commit c70bbdab26
5 changed files with 20 additions and 16 deletions

View File

@ -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.

View File

@ -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
}
}

View File

@ -104,6 +104,13 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
}
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
// ConstValue <associativeoperator> X --> X <associativeoperator> 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).

View File

@ -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),

View File

@ -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 ")
}
}