improved bool type checking

This commit is contained in:
Irmen de Jong 2022-07-08 22:29:13 +02:00
parent d2d08bf143
commit 211e2bb37a
3 changed files with 7 additions and 15 deletions

View File

@ -80,10 +80,11 @@ internal class AstChecker(private val program: Program,
} else {
if (expectedReturnValues[0] != valueDt.getOr(DataType.UNDEFINED)) {
if(valueDt istype DataType.BOOL && expectedReturnValues[0] == DataType.UBYTE) {
// if the return value is a bool and the return type is ubyte, allow this.
// if the return value is a bool and the return type is ubyte, allow this. But give a warning.
errors.warn("return type of the subroutine should probably be bool instead of ubyte", returnStmt.position)
} else if(valueDt istype DataType.UBYTE && expectedReturnValues[0] == DataType.BOOL) {
// if the return value is ubyte and the return type is bool, allow this only if value is 0 or 1
val returnValue = returnStmt.value?.constValue(program)
val returnValue = returnStmt.value as? NumericLiteral
if (returnValue == null || returnValue.type != DataType.UBYTE || (returnValue.number!=0.0 && returnValue.number!=1.0)) {
errors.err("type $valueDt of return value doesn't match subroutine's return type ${expectedReturnValues[0]}",returnStmt.value!!.position)
}

View File

@ -185,16 +185,6 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
val leftDt = left.inferType(program)
val rightDt = right.inferType(program)
fun dynamicBooleanType(): InferredTypes.InferredType {
// as a special case, an expression yielding a boolean result, adapts the result
// type to what is required (byte or word), to avoid useless type casting
return when (parent) {
is TypecastExpression -> InferredTypes.InferredType.known((parent as TypecastExpression).type)
is Assignment -> (parent as Assignment).target.inferType(program)
else -> InferredTypes.InferredType.known(DataType.BOOL)
}
}
return when (operator) {
"+", "-", "*", "%", "/" -> {
if (!leftDt.isKnown || !rightDt.isKnown)
@ -214,10 +204,10 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
}
}
"&", "|", "^" -> if(leftDt istype DataType.BOOL) InferredTypes.knownFor(DataType.UBYTE) else leftDt
"and", "or", "xor", "not" -> InferredTypes.knownFor(DataType.UBYTE) // note: don't use BOOL type here to avoid type errors later! Will be replaced anyway.
"and", "or", "xor", "not" -> InferredTypes.knownFor(DataType.BOOL)
"<", ">",
"<=", ">=",
"==", "!=", "in" -> dynamicBooleanType()
"==", "!=", "in" -> InferredTypes.knownFor(DataType.BOOL)
"<<", ">>" -> leftDt
else -> throw FatalAstException("resulting datatype check for invalid operator $operator")
}

View File

@ -10,8 +10,9 @@ main {
return key=='a'
}
sub func2() -> bool {
return key=='z'
return key==2
}
sub start() {