mirror of
https://github.com/irmen/prog8.git
synced 2025-02-22 01:29:07 +00:00
more nonstrictbool conversions
This commit is contained in:
parent
84afb374e6
commit
e55cde2a81
@ -233,7 +233,7 @@ class AsmGen6502Internal (
|
||||
private val functioncallAsmGen = FunctionCallAsmGen(program, this)
|
||||
private val programGen = ProgramAndVarsGen(program, options, errors, symbolTable, functioncallAsmGen, this, allocator, zeropage)
|
||||
private val anyExprGen = AnyExprAsmGen(this)
|
||||
private val assignmentAsmGen = AssignmentAsmGen(program, this, anyExprGen, allocator)
|
||||
private val assignmentAsmGen = AssignmentAsmGen(program, this, options, anyExprGen, allocator)
|
||||
private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, this, assignmentAsmGen)
|
||||
private val ifElseAsmgen = IfElseAsmGen(program, symbolTable, this, allocator, assignmentAsmGen, errors)
|
||||
|
||||
|
@ -11,6 +11,7 @@ import prog8.codegen.cpu6502.returnsWhatWhere
|
||||
|
||||
internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
private val asmgen: AsmGen6502Internal,
|
||||
private val options: CompilationOptions,
|
||||
private val anyExprGen: AnyExprAsmGen,
|
||||
private val allocator: VariableAllocator) {
|
||||
private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen, allocator)
|
||||
@ -59,7 +60,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
val variable = assign.source.asmVarname
|
||||
when (assign.target.datatype) {
|
||||
DataType.BOOL -> {
|
||||
if (assign.source.datatype == DataType.BOOL) assignVariableByte(assign.target, variable)
|
||||
if (assign.source.datatype == DataType.BOOL || !options.strictBool) assignVariableByte(assign.target, variable)
|
||||
else throw AssemblyError("assigning non-bool variable to boolean, should have been typecasted")
|
||||
}
|
||||
DataType.UBYTE, DataType.BYTE -> assignVariableByte(assign.target, variable)
|
||||
|
@ -158,7 +158,7 @@ sub setchr (ubyte col, ubyte row, ubyte char) {
|
||||
|
||||
sub petscii2scr(ubyte petscii_char) -> ubyte {
|
||||
; -- convert petscii character to screencode
|
||||
byte[8] offsets = [128, 0, 64, 32, 64, 192, 128, 128]
|
||||
ubyte[8] offsets = [128, 0, 64, 32, 64, 192, 128, 128]
|
||||
return petscii_char ^ offsets[petscii_char>>5]
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,9 @@ const val MAVEN_GROUP = "prog8"
|
||||
const val MAVEN_NAME = "compiler"
|
||||
const val VERSION = "10.2-BOOLEANS"
|
||||
const val GIT_REVISION = 4530
|
||||
const val GIT_SHA = "c7843b4ed8919870983fdf9d27413caf690d948a"
|
||||
const val GIT_DATE = "2024-03-03T13:01:46Z"
|
||||
const val GIT_SHA = "26102becb7ed4f9875d83fbd3e1c0b59420f81d1"
|
||||
const val GIT_DATE = "2024-03-03T17:58:39Z"
|
||||
const val GIT_BRANCH = "booleans-nostrictbool"
|
||||
const val BUILD_DATE = "2024-03-03T13:12:36Z"
|
||||
const val BUILD_UNIX_TIME = 1709471556477L
|
||||
const val BUILD_DATE = "2024-03-03T18:28:38Z"
|
||||
const val BUILD_UNIX_TIME = 1709490518135L
|
||||
const val DIRTY = 1
|
||||
|
@ -967,8 +967,10 @@ internal class AstChecker(private val program: Program,
|
||||
errors.err("bitwise invert is for integer types, use 'not' on booleans", expr.position)
|
||||
}
|
||||
else if(expr.operator == "not") {
|
||||
if(dt!=DataType.BOOL)
|
||||
errors.err("logical not is for booleans", expr.position)
|
||||
if(dt!=DataType.BOOL) {
|
||||
if(compilerOptions.strictBool || dt !in ByteDatatypes)
|
||||
errors.err("logical not is for booleans", expr.position)
|
||||
}
|
||||
}
|
||||
super.visit(expr)
|
||||
}
|
||||
@ -1085,8 +1087,10 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
|
||||
if(expr.operator in LogicalOperators) {
|
||||
if (leftDt != DataType.BOOL || rightDt != DataType.BOOL)
|
||||
errors.err("logical operator requires boolean operands", expr.right.position)
|
||||
if (leftDt != DataType.BOOL || rightDt != DataType.BOOL) {
|
||||
if(compilerOptions.strictBool || leftDt !in ByteDatatypes || rightDt !in ByteDatatypes)
|
||||
errors.err("logical operator requires boolean operands", expr.right.position)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (leftDt == DataType.BOOL || rightDt == DataType.BOOL) {
|
||||
|
@ -147,6 +147,26 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
}
|
||||
|
||||
if(leftDt!=rightDt) {
|
||||
if(!options.strictBool) {
|
||||
if (expr.operator in LogicalOperators) {
|
||||
if (leftDt.isBool) {
|
||||
val cast = TypecastExpression(expr.right, DataType.BOOL, false, expr.right.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, cast, expr))
|
||||
} else {
|
||||
val cast = TypecastExpression(expr.left, DataType.BOOL, false, expr.left.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.left, cast, expr))
|
||||
}
|
||||
} else {
|
||||
if(leftDt.isBool && rightDt.isBytes) {
|
||||
val cast = TypecastExpression(expr.left, rightDt.getOr(DataType.UNDEFINED), false, expr.left.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.left, cast, expr))
|
||||
} else if(rightDt.isBool && leftDt.isBytes) {
|
||||
val cast = TypecastExpression(expr.right, leftDt.getOr(DataType.UNDEFINED), false, expr.right.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, cast, expr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert a negative operand for bitwise operator to the 2's complement positive number instead
|
||||
if(expr.operator in BitwiseOperators && leftDt.isInteger && rightDt.isInteger) {
|
||||
if(leftCv!=null && leftCv.number<0) {
|
||||
@ -254,13 +274,12 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
// more complex comparisons if the type is different, but the constant value is compatible
|
||||
if(!options.strictBool) {
|
||||
if (targettype == DataType.BOOL && valuetype in ByteDatatypes) {
|
||||
return castLiteral(cvalue)
|
||||
val cast = NumericLiteral.fromBoolean(number!=0.0, cvalue.position)
|
||||
return listOf(IAstModification.ReplaceNode(assignment.value, cast, assignment))
|
||||
}
|
||||
if (targettype == DataType.UBYTE && valuetype == DataType.BOOL) {
|
||||
return castLiteral(cvalue)
|
||||
}
|
||||
if (targettype == DataType.BYTE && valuetype == DataType.BOOL) {
|
||||
return castLiteral(cvalue)
|
||||
if (targettype in ByteDatatypes && valuetype == DataType.BOOL) {
|
||||
val cast = NumericLiteral(targettype, if(cvalue.asBooleanValue) 1.0 else 0.0, cvalue.position)
|
||||
return listOf(IAstModification.ReplaceNode(assignment.value, cast, assignment))
|
||||
}
|
||||
}
|
||||
if (valuetype == DataType.BYTE && targettype == DataType.UBYTE) {
|
||||
@ -276,6 +295,17 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
if(number<0x8000)
|
||||
return castLiteral(cvalue)
|
||||
}
|
||||
} else {
|
||||
if(!options.strictBool) {
|
||||
if (targettype == DataType.BOOL && valuetype in ByteDatatypes) {
|
||||
val cast = TypecastExpression(assignment.value, targettype, false, assignment.value.position)
|
||||
return listOf(IAstModification.ReplaceNode(assignment.value, cast, assignment))
|
||||
}
|
||||
if (targettype in ByteDatatypes && valuetype == DataType.BOOL) {
|
||||
val cast = TypecastExpression(assignment.value, targettype, false, assignment.value.position)
|
||||
return listOf(IAstModification.ReplaceNode(assignment.value, cast, assignment))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -328,7 +358,8 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
} else if(argDt isAssignableTo targetDt) {
|
||||
if(argDt!=DataType.STR || targetDt!=DataType.UWORD)
|
||||
addTypecastOrCastedValueModification(modifications, it.second, targetDt, call as Node)
|
||||
}
|
||||
} else if(!options.strictBool && targetDt in ByteDatatypes && argDt==DataType.BOOL)
|
||||
addTypecastOrCastedValueModification(modifications, it.second, targetDt, call as Node)
|
||||
}
|
||||
} else {
|
||||
val identifier = it.second as? IdentifierReference
|
||||
@ -394,6 +425,18 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
if(subroutine.returntypes.size==1) {
|
||||
val subReturnType = subroutine.returntypes.first()
|
||||
val returnDt = returnValue.inferType(program)
|
||||
|
||||
if(!options.strictBool) {
|
||||
if(subReturnType==DataType.BOOL && returnDt.isBytes) {
|
||||
val cast = TypecastExpression(returnValue, DataType.BOOL, false, returnValue.position)
|
||||
return listOf(IAstModification.ReplaceNode(returnValue, cast, returnStmt))
|
||||
}
|
||||
if(subReturnType in ByteDatatypes && returnDt.isBool) {
|
||||
val cast = TypecastExpression(returnValue, subReturnType, false, returnValue.position)
|
||||
return listOf(IAstModification.ReplaceNode(returnValue, cast, returnStmt))
|
||||
}
|
||||
}
|
||||
|
||||
if (returnDt istype subReturnType or returnDt.isNotAssignableTo(subReturnType))
|
||||
return noModifications
|
||||
if (returnValue is NumericLiteral) {
|
||||
@ -436,6 +479,14 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
return modifications
|
||||
}
|
||||
|
||||
override fun after(ifElse: IfElse, parent: Node): Iterable<IAstModification> {
|
||||
if(!options.strictBool && ifElse.condition.inferType(program).isBytes) {
|
||||
val cast = TypecastExpression(ifElse.condition, DataType.BOOL, false, ifElse.condition.position)
|
||||
return listOf(IAstModification.ReplaceNode(ifElse.condition, cast, ifElse))
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
||||
|
||||
private fun addTypecastOrCastedValueModification(
|
||||
modifications: MutableList<IAstModification>,
|
||||
@ -446,8 +497,21 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
val sourceDt = expressionToCast.inferType(program).getOr(DataType.UNDEFINED)
|
||||
if(sourceDt == requiredType)
|
||||
return
|
||||
if(requiredType==DataType.BOOL)
|
||||
if(!options.strictBool) {
|
||||
if(requiredType==DataType.BOOL && sourceDt in ByteDatatypes) {
|
||||
val cast = TypecastExpression(expressionToCast, DataType.BOOL, false, expressionToCast.position)
|
||||
modifications.add(IAstModification.ReplaceNode(expressionToCast, cast, parent))
|
||||
return
|
||||
}
|
||||
if(requiredType in ByteDatatypes && sourceDt==DataType.BOOL) {
|
||||
val cast = TypecastExpression(expressionToCast, requiredType, false, expressionToCast.position)
|
||||
modifications.add(IAstModification.ReplaceNode(expressionToCast, cast, parent))
|
||||
return
|
||||
}
|
||||
}
|
||||
if(requiredType==DataType.BOOL) {
|
||||
return
|
||||
}
|
||||
if(expressionToCast is NumericLiteral && expressionToCast.type!=DataType.FLOAT) { // refuse to automatically truncate floats
|
||||
val castedValue = expressionToCast.cast(requiredType, true)
|
||||
if (castedValue.isValid) {
|
||||
|
@ -155,6 +155,10 @@ One or more .p8 module files
|
||||
Don't perform any code optimizations.
|
||||
Useful for debugging or faster compilation cycles.
|
||||
|
||||
``-nostrictbool``
|
||||
Relax the strict boolean type checks: bytes and booleans can be interchanged again without explicit type casts.
|
||||
*This option will likely disappear in a future prog8 version, so you may want to prepare for that in your code!*
|
||||
|
||||
``-optfloatx``
|
||||
Also optimize float expressions if optimizations are enabled.
|
||||
Warning: can increase program size significantly if a lot of floating point expressions are used.
|
||||
|
@ -14,10 +14,15 @@ main {
|
||||
bool @shared bb1, bb2
|
||||
bb1 = 0
|
||||
bb2 = 44
|
||||
bb1 = cx16.r0L
|
||||
|
||||
bb2 = bb1 and cx16.r0L
|
||||
cx16.r0L = bb1 ^ cx16.r0L
|
||||
|
||||
; bool[3] barr1 = 42
|
||||
byte[3] @shared sbarr1 = true
|
||||
ubyte[3] @shared ubarr1 = true
|
||||
ubyte[3] @shared ubarr2 = bb2
|
||||
|
||||
bool[] @shared boolarray = [1,0]
|
||||
bool[] @shared boolarray2 = [42,0,false]
|
||||
@ -26,6 +31,9 @@ main {
|
||||
ubyte[] @shared uba = [true, false]
|
||||
ubyte[] @shared uba2 = [true, false, 42]
|
||||
|
||||
if cx16.r0L >= 44 and not cx16.r0L
|
||||
cx16.r0L++
|
||||
|
||||
txt.print_ubhex(bb1, 1)
|
||||
txt.print_ubhex(bb2, 42)
|
||||
txt.print_ubhex(bb2, cx16.r0L)
|
||||
@ -33,6 +41,23 @@ main {
|
||||
if cx16.r0L {
|
||||
cx16.r0L++
|
||||
}
|
||||
|
||||
if cx16.r0 {
|
||||
cx16.r0L++
|
||||
}
|
||||
|
||||
kapoof()
|
||||
kapoof2()
|
||||
}
|
||||
|
||||
sub kapoof() -> bool {
|
||||
cx16.r0L++
|
||||
return cx16.r0L
|
||||
}
|
||||
|
||||
sub kapoof2() -> ubyte {
|
||||
cx16.r0L++
|
||||
return cx16.r0L==0
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user