mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
removed the -nostrictbool compiler option
boolean types and bytes are no longer implicitly interchangeable using this option
This commit is contained in:
parent
6516d7cb15
commit
bdeac74cfc
@ -27,7 +27,6 @@ class CompilationOptions(val output: OutputType,
|
||||
var slabsHighBank: Int? = null,
|
||||
var slabsGolden: Boolean = false,
|
||||
var splitWordArrays: Boolean = false,
|
||||
var strictBool: Boolean = true,
|
||||
var breakpointCpuInstruction: String? = null,
|
||||
var outputDir: Path = Path(""),
|
||||
var symbolDefs: Map<String, String> = emptyMap()
|
||||
|
@ -232,7 +232,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, options, anyExprGen, allocator)
|
||||
private val assignmentAsmGen = AssignmentAsmGen(program, this, anyExprGen, allocator)
|
||||
private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, this, assignmentAsmGen)
|
||||
private val ifElseAsmgen = IfElseAsmGen(program, symbolTable, this, allocator, assignmentAsmGen, errors)
|
||||
|
||||
|
@ -11,11 +11,12 @@ import prog8.codegen.cpu6502.VariableAllocator
|
||||
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) {
|
||||
internal class AssignmentAsmGen(
|
||||
private val program: PtProgram,
|
||||
private val asmgen: AsmGen6502Internal,
|
||||
private val anyExprGen: AnyExprAsmGen,
|
||||
private val allocator: VariableAllocator
|
||||
) {
|
||||
private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen, allocator)
|
||||
|
||||
fun translate(assignment: PtAssignment) {
|
||||
@ -201,7 +202,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 || !options.strictBool) assignVariableByte(assign.target, variable)
|
||||
if (assign.source.datatype == DataType.BOOL) 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)
|
||||
|
@ -490,8 +490,7 @@ internal class ConstantIdentifierReplacer(
|
||||
if(numericLv!=null) {
|
||||
// arraysize initializer is a single value, and we know the array size.
|
||||
if(numericLv.type!=DataType.BOOL) {
|
||||
if(options.strictBool || numericLv.type !in ByteDatatypes)
|
||||
errors.err("initializer value is not a boolean", numericLv.position)
|
||||
errors.err("initializer value is not a boolean", numericLv.position)
|
||||
return null
|
||||
}
|
||||
val array = Array(size) {numericLv.number}.map { NumericLiteral(DataType.BOOL, it, numericLv.position) }.toTypedArray<Expression>()
|
||||
|
@ -11,9 +11,9 @@ import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.*
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.log2
|
||||
import kotlin.math.pow
|
||||
|
||||
class ExpressionSimplifier(private val program: Program, private val options: CompilationOptions, private val errors: IErrorReporter) : AstWalker() {
|
||||
|
||||
class ExpressionSimplifier(private val program: Program, private val errors: IErrorReporter) : AstWalker() {
|
||||
override fun after(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> {
|
||||
val mods = mutableListOf<IAstModification>()
|
||||
|
||||
@ -246,20 +246,15 @@ class ExpressionSimplifier(private val program: Program, private val options: Co
|
||||
}
|
||||
}
|
||||
if (rightVal?.number == 1.0) {
|
||||
if (options.strictBool) {
|
||||
if (rightDt != leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
} else
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
if (rightDt != leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
}
|
||||
else if (rightVal?.number == 0.0) {
|
||||
if (options.strictBool) {
|
||||
if (rightDt != leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
if (rightDt != leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -274,21 +269,16 @@ class ExpressionSimplifier(private val program: Program, private val options: Co
|
||||
}
|
||||
}
|
||||
if (rightVal?.number == 1.0) {
|
||||
if(options.strictBool) {
|
||||
if(rightDt!=leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
if(rightDt!=leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
}
|
||||
else if (rightVal?.number == 0.0) {
|
||||
if(options.strictBool) {
|
||||
if(rightDt!=leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
} else
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
if(rightDt!=leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,8 +59,8 @@ fun Program.inlineSubroutines(options: CompilationOptions): Int {
|
||||
return inliner.applyModifications()
|
||||
}
|
||||
|
||||
fun Program.simplifyExpressions(errors: IErrorReporter, options: CompilationOptions) : Int {
|
||||
val opti = ExpressionSimplifier(this, options, errors)
|
||||
fun Program.simplifyExpressions(errors: IErrorReporter) : Int {
|
||||
val opti = ExpressionSimplifier(this, errors)
|
||||
opti.visit(this)
|
||||
return opti.applyModifications()
|
||||
}
|
||||
|
@ -45,7 +45,6 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
val dumpVariables by cli.option(ArgType.Boolean, fullName = "dumpvars", description = "print a dump of the variables in the program")
|
||||
val dumpSymbols by cli.option(ArgType.Boolean, fullName = "dumpsymbols", description = "print a dump of the variable declarations and subroutine signatures")
|
||||
val dontWriteAssembly by cli.option(ArgType.Boolean, fullName = "noasm", description="don't create assembly code")
|
||||
val noStrictBool by cli.option(ArgType.Boolean, fullName = "nostrictbool", description = "allow implicit conversions between bool and bytes")
|
||||
val dontOptimize by cli.option(ArgType.Boolean, fullName = "noopt", description = "don't perform code optimizations")
|
||||
val outputDir by cli.option(ArgType.String, fullName = "out", description = "directory for output files instead of current directory").default(".")
|
||||
val quietAssembler by cli.option(ArgType.Boolean, fullName = "quietasm", description = "don't print assembler output results")
|
||||
@ -178,7 +177,6 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
breakpointCpuInstruction,
|
||||
printAst1 == true,
|
||||
printAst2 == true,
|
||||
noStrictBool != true,
|
||||
processedSymbols,
|
||||
srcdirs,
|
||||
outputPath
|
||||
@ -259,7 +257,6 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
breakpointCpuInstruction,
|
||||
printAst1 == true,
|
||||
printAst2 == true,
|
||||
noStrictBool != true,
|
||||
processedSymbols,
|
||||
srcdirs,
|
||||
outputPath
|
||||
|
@ -54,7 +54,6 @@ class CompilerArguments(val filepath: Path,
|
||||
val breakpointCpuInstruction: String?,
|
||||
val printAst1: Boolean,
|
||||
val printAst2: Boolean,
|
||||
val strictBool: Boolean,
|
||||
val symbolDefs: Map<String, String>,
|
||||
val sourceDirs: List<String> = emptyList(),
|
||||
val outputDir: Path = Path(""),
|
||||
@ -91,7 +90,6 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
||||
splitWordArrays = args.splitWordArrays
|
||||
outputDir = args.outputDir.normalize()
|
||||
symbolDefs = args.symbolDefs
|
||||
strictBool = args.strictBool
|
||||
}
|
||||
resultingProgram = program
|
||||
importedFiles = imported
|
||||
@ -412,7 +410,7 @@ private fun processAst(program: Program, errors: IErrorReporter, compilerOptions
|
||||
errors.report()
|
||||
program.reorderStatements(errors)
|
||||
errors.report()
|
||||
program.desugaring(errors, compilerOptions)
|
||||
program.desugaring(errors)
|
||||
errors.report()
|
||||
program.changeNotExpressionAndIfComparisonExpr(errors, compilerOptions.compTarget)
|
||||
errors.report()
|
||||
@ -438,7 +436,7 @@ private fun optimizeAst(program: Program, compilerOptions: CompilationOptions, e
|
||||
removeUnusedCode(program, errors,compilerOptions)
|
||||
while (true) {
|
||||
// keep optimizing expressions and statements until no more steps remain
|
||||
val optsDone1 = program.simplifyExpressions(errors, compilerOptions)
|
||||
val optsDone1 = program.simplifyExpressions(errors)
|
||||
val optsDone2 = program.optimizeStatements(errors, functions, compilerOptions)
|
||||
val optsDone3 = program.inlineSubroutines(compilerOptions)
|
||||
program.constantFold(errors, compilerOptions) // because simplified statements and expressions can result in more constants that can be folded away
|
||||
@ -452,7 +450,7 @@ private fun optimizeAst(program: Program, compilerOptions: CompilationOptions, e
|
||||
removeUnusedCode(program, errors, compilerOptions)
|
||||
if(errors.noErrors()) {
|
||||
// last round of optimizations because constFold may have enabled more...
|
||||
program.simplifyExpressions(errors, compilerOptions)
|
||||
program.simplifyExpressions(errors)
|
||||
program.optimizeStatements(errors, functions, compilerOptions)
|
||||
program.constantFold(errors, compilerOptions) // because simplified statements and expressions can result in more constants that can be folded away
|
||||
}
|
||||
@ -461,7 +459,7 @@ private fun optimizeAst(program: Program, compilerOptions: CompilationOptions, e
|
||||
}
|
||||
|
||||
private fun postprocessAst(program: Program, errors: IErrorReporter, compilerOptions: CompilationOptions) {
|
||||
program.desugaring(errors, compilerOptions)
|
||||
program.desugaring(errors)
|
||||
program.addTypecasts(errors, compilerOptions)
|
||||
errors.report()
|
||||
program.variousCleanups(errors, compilerOptions)
|
||||
|
@ -163,9 +163,7 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
override fun visit(ifElse: IfElse) {
|
||||
if(!ifElse.condition.inferType(program).isBool) {
|
||||
val ctype = ifElse.condition.inferType(program).getOr(DataType.UNDEFINED)
|
||||
if(compilerOptions.strictBool || ctype !in ByteDatatypes)
|
||||
errors.err("condition should be a boolean", ifElse.condition.position)
|
||||
errors.err("condition should be a boolean", ifElse.condition.position)
|
||||
}
|
||||
|
||||
val constvalue = ifElse.condition.constValue(program)
|
||||
@ -506,9 +504,7 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
override fun visit(untilLoop: UntilLoop) {
|
||||
if(!untilLoop.condition.inferType(program).isBool) {
|
||||
val ctype = untilLoop.condition.inferType(program).getOr(DataType.UNDEFINED)
|
||||
if(compilerOptions.strictBool || ctype !in ByteDatatypes)
|
||||
errors.err("condition should be a boolean", untilLoop.condition.position)
|
||||
errors.err("condition should be a boolean", untilLoop.condition.position)
|
||||
}
|
||||
|
||||
super.visit(untilLoop)
|
||||
@ -516,9 +512,7 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
override fun visit(whileLoop: WhileLoop) {
|
||||
if(!whileLoop.condition.inferType(program).isBool) {
|
||||
val ctype = whileLoop.condition.inferType(program).getOr(DataType.UNDEFINED)
|
||||
if(compilerOptions.strictBool || ctype !in ByteDatatypes)
|
||||
errors.err("condition should be a boolean", whileLoop.condition.position)
|
||||
errors.err("condition should be a boolean", whileLoop.condition.position)
|
||||
}
|
||||
|
||||
super.visit(whileLoop)
|
||||
@ -780,12 +774,8 @@ internal class AstChecker(private val program: Program,
|
||||
if (iDt isnot decl.datatype) {
|
||||
if(decl.isArray) {
|
||||
val eltDt = ArrayToElementTypes.getValue(decl.datatype)
|
||||
if(iDt isnot eltDt) {
|
||||
if(compilerOptions.strictBool)
|
||||
err("initialisation value has incompatible type ($iDt) for the variable (${decl.datatype})")
|
||||
else if(!(iDt.isBool && eltDt==DataType.UBYTE || iDt.istype(DataType.UBYTE) && eltDt==DataType.BOOL))
|
||||
err("initialisation value has incompatible type ($iDt) for the variable (${decl.datatype})")
|
||||
}
|
||||
if(iDt isnot eltDt)
|
||||
err("initialisation value has incompatible type ($iDt) for the variable (${decl.datatype})")
|
||||
} else {
|
||||
if(!(iDt.isBool && decl.datatype==DataType.UBYTE || iDt.istype(DataType.UBYTE) && decl.datatype==DataType.BOOL))
|
||||
err("initialisation value has incompatible type ($iDt) for the variable (${decl.datatype})")
|
||||
@ -1048,8 +1038,7 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
else if(expr.operator == "not") {
|
||||
if(dt!=DataType.BOOL) {
|
||||
if(compilerOptions.strictBool || dt !in ByteDatatypes)
|
||||
errors.err("logical not is for booleans", expr.position)
|
||||
errors.err("logical not is for booleans", expr.position)
|
||||
}
|
||||
}
|
||||
super.visit(expr)
|
||||
@ -1168,8 +1157,7 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
if(expr.operator in LogicalOperators) {
|
||||
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)
|
||||
errors.err("logical operator requires boolean operands", expr.right.position)
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -1248,7 +1236,7 @@ internal class AstChecker(private val program: Program,
|
||||
errors.warn("sgn() of unsigned type is always 0 or 1, this is perhaps not what was intended", functionCallExpr.args.first().position)
|
||||
}
|
||||
|
||||
val error = VerifyFunctionArgTypes.checkTypes(functionCallExpr, program, compilerOptions)
|
||||
val error = VerifyFunctionArgTypes.checkTypes(functionCallExpr, program)
|
||||
if(error!=null)
|
||||
errors.err(error.first, error.second)
|
||||
|
||||
@ -1339,7 +1327,7 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
}
|
||||
|
||||
val error = VerifyFunctionArgTypes.checkTypes(functionCallStatement, program, compilerOptions)
|
||||
val error = VerifyFunctionArgTypes.checkTypes(functionCallStatement, program)
|
||||
if(error!=null)
|
||||
errors.err(error.first, error.second)
|
||||
|
||||
@ -1727,8 +1715,7 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
DataType.BOOL -> {
|
||||
if (value.type!=DataType.BOOL) {
|
||||
if (compilerOptions.strictBool || value.type !in ByteDatatypes)
|
||||
err("type of value ${value.type} doesn't match target $targetDt")
|
||||
err("type of value ${value.type} doesn't match target $targetDt")
|
||||
}
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
@ -1829,12 +1816,10 @@ internal class AstChecker(private val program: Program,
|
||||
// this is allowed: a pass-by-reference datatype into a uword (pointer value).
|
||||
}
|
||||
else if(sourceDatatype==DataType.BOOL && targetDatatype!=DataType.BOOL) {
|
||||
if(compilerOptions.strictBool || targetDatatype !in ByteDatatypes)
|
||||
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
|
||||
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
|
||||
}
|
||||
else if(targetDatatype==DataType.BOOL && sourceDatatype!=DataType.BOOL) {
|
||||
if(compilerOptions.strictBool || sourceDatatype !in ByteDatatypes)
|
||||
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
|
||||
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
|
||||
}
|
||||
else {
|
||||
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
|
||||
|
@ -92,8 +92,8 @@ internal fun Program.addTypecasts(errors: IErrorReporter, options: CompilationOp
|
||||
caster.applyModifications()
|
||||
}
|
||||
|
||||
fun Program.desugaring(errors: IErrorReporter, options: CompilationOptions) {
|
||||
val desugar = CodeDesugarer(this, options, errors)
|
||||
fun Program.desugaring(errors: IErrorReporter) {
|
||||
val desugar = CodeDesugarer(this, errors)
|
||||
desugar.visit(this)
|
||||
while(errors.noErrors() && desugar.applyModifications()>0)
|
||||
desugar.visit(this)
|
||||
|
@ -8,7 +8,7 @@ import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.*
|
||||
|
||||
|
||||
internal class CodeDesugarer(val program: Program, private val options: CompilationOptions, private val errors: IErrorReporter) : AstWalker() {
|
||||
internal class CodeDesugarer(val program: Program, private val errors: IErrorReporter) : AstWalker() {
|
||||
|
||||
// Some more code shuffling to simplify the Ast that the codegenerator has to process.
|
||||
// Several changes have already been done by the StatementReorderer !
|
||||
@ -123,9 +123,7 @@ if not CONDITION
|
||||
override fun after(whileLoop: WhileLoop, parent: Node): Iterable<IAstModification> {
|
||||
|
||||
if(!whileLoop.condition.inferType(program).isBool) {
|
||||
val ctype = whileLoop.condition.inferType(program).getOr(DataType.UNDEFINED)
|
||||
if(options.strictBool || ctype !in ByteDatatypes)
|
||||
errors.err("condition should be a boolean", whileLoop.condition.position)
|
||||
errors.err("condition should be a boolean", whileLoop.condition.position)
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -24,11 +24,6 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
val valueDt = declValue.inferType(program)
|
||||
if(valueDt isnot decl.datatype) {
|
||||
|
||||
if(decl.isArray && !options.strictBool) {
|
||||
if(tryConvertBooleanArrays(decl, declValue, parent))
|
||||
return noModifications
|
||||
}
|
||||
|
||||
if(valueDt.isInteger && decl.isArray) {
|
||||
if(decl.datatype == DataType.ARRAY_BOOL) {
|
||||
val integer = declValue.constValue(program)?.number
|
||||
@ -54,69 +49,6 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
return noModifications
|
||||
}
|
||||
|
||||
private fun tryConvertBooleanArrays(decl: VarDecl, declValue: Expression, parent: Node): Boolean {
|
||||
val valueNumber = declValue.constValue(program)
|
||||
val valueArray = declValue as? ArrayLiteral
|
||||
when (decl.datatype) {
|
||||
DataType.ARRAY_BOOL -> {
|
||||
if(valueNumber!=null) {
|
||||
decl.value = NumericLiteral.fromBoolean(valueNumber.number!=0.0, declValue.position)
|
||||
decl.linkParents(parent)
|
||||
return true
|
||||
} else if(valueArray!=null) {
|
||||
val newArray = valueArray.value.map {
|
||||
if(it.inferType(program).isBytes) {
|
||||
TypecastExpression(it, DataType.BOOL, false, it.position)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
decl.value = ArrayLiteral(InferredTypes.InferredType.known(DataType.ARRAY_BOOL), newArray.toTypedArray(), valueArray.position)
|
||||
decl.linkParents(parent)
|
||||
return true
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_B -> {
|
||||
if(valueNumber!=null) {
|
||||
decl.value = NumericLiteral(DataType.BYTE, if(valueNumber.asBooleanValue) 1.0 else 0.0, declValue.position)
|
||||
decl.linkParents(parent)
|
||||
return true
|
||||
} else if(valueArray!=null) {
|
||||
val newArray = valueArray.value.map {
|
||||
if(it.inferType(program).isBool) {
|
||||
TypecastExpression(it, DataType.BYTE, false, it.position)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
decl.value = ArrayLiteral(InferredTypes.InferredType.known(DataType.ARRAY_B), newArray.toTypedArray(), valueArray.position)
|
||||
decl.linkParents(parent)
|
||||
return true
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_UB -> {
|
||||
if(valueNumber!=null) {
|
||||
decl.value = NumericLiteral(DataType.UBYTE, if(valueNumber.asBooleanValue) 1.0 else 0.0, declValue.position)
|
||||
decl.linkParents(parent)
|
||||
return true
|
||||
} else if(valueArray!=null) {
|
||||
val newArray = valueArray.value.map {
|
||||
if(it.inferType(program).isBool) {
|
||||
TypecastExpression(it, DataType.UBYTE, false, it.position)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
decl.value = ArrayLiteral(InferredTypes.InferredType.known(DataType.ARRAY_UB), newArray.toTypedArray(), valueArray.position)
|
||||
decl.linkParents(parent)
|
||||
return true
|
||||
}
|
||||
}
|
||||
else -> { /* no casting possible */ }
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
||||
val leftDt = expr.left.inferType(program)
|
||||
val rightDt = expr.right.inferType(program)
|
||||
@ -155,26 +87,6 @@ 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) {
|
||||
@ -280,16 +192,6 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
if(cvalue!=null) {
|
||||
val number = cvalue.number
|
||||
// more complex comparisons if the type is different, but the constant value is compatible
|
||||
if(!options.strictBool) {
|
||||
if (targettype == DataType.BOOL && valuetype in ByteDatatypes) {
|
||||
val cast = NumericLiteral.fromBoolean(number!=0.0, cvalue.position)
|
||||
return listOf(IAstModification.ReplaceNode(assignment.value, cast, assignment))
|
||||
}
|
||||
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) {
|
||||
if(number>0)
|
||||
return castLiteral(cvalue)
|
||||
@ -303,17 +205,6 @@ 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -365,8 +256,7 @@ 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
|
||||
@ -432,18 +322,6 @@ 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) {
|
||||
@ -488,14 +366,6 @@ 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>,
|
||||
expressionToCast: Expression,
|
||||
@ -505,18 +375,6 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
val sourceDt = expressionToCast.inferType(program).getOr(DataType.UNDEFINED)
|
||||
if(sourceDt == requiredType)
|
||||
return
|
||||
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
|
||||
}
|
||||
|
@ -97,16 +97,6 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.expression, parent))
|
||||
}
|
||||
|
||||
if(!options.strictBool && expr.operator=="not") {
|
||||
if(expr.expression.inferType(program).isBytes) {
|
||||
// not bytevalue --> bytevalue==0
|
||||
val cmp = BinaryExpression(expr.expression, "==",
|
||||
NumericLiteral(expr.expression.inferType(program).getOr(DataType.UNDEFINED), 0.0, expr.expression.position),
|
||||
expr.expression.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, cmp, parent))
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ internal class VerifyFunctionArgTypes(val program: Program, val options: Compila
|
||||
private val memorySlabs = mutableListOf<Slab>()
|
||||
|
||||
override fun visit(functionCallExpr: FunctionCallExpression) {
|
||||
val error = checkTypes(functionCallExpr as IFunctionCall, program, options)
|
||||
val error = checkTypes(functionCallExpr as IFunctionCall, program)
|
||||
if(error!=null)
|
||||
errors.err(error.first, error.second)
|
||||
else {
|
||||
@ -62,7 +62,7 @@ internal class VerifyFunctionArgTypes(val program: Program, val options: Compila
|
||||
}
|
||||
|
||||
override fun visit(functionCallStatement: FunctionCallStatement) {
|
||||
val error = checkTypes(functionCallStatement as IFunctionCall, program, options)
|
||||
val error = checkTypes(functionCallStatement as IFunctionCall, program)
|
||||
if(error!=null)
|
||||
errors.err(error.first, error.second)
|
||||
|
||||
@ -85,7 +85,7 @@ internal class VerifyFunctionArgTypes(val program: Program, val options: Compila
|
||||
return false
|
||||
}
|
||||
|
||||
fun checkTypes(call: IFunctionCall, program: Program, options: CompilationOptions): Pair<String, Position>? {
|
||||
fun checkTypes(call: IFunctionCall, program: Program): Pair<String, Position>? {
|
||||
val argITypes = call.args.map { it.inferType(program) }
|
||||
val firstUnknownDt = argITypes.indexOfFirst { it.isUnknown }
|
||||
if(firstUnknownDt>=0) {
|
||||
@ -105,12 +105,7 @@ internal class VerifyFunctionArgTypes(val program: Program, val options: Compila
|
||||
if(mismatch>=0) {
|
||||
val actual = argtypes[mismatch]
|
||||
val expected = consideredParamTypes[mismatch]
|
||||
return if(expected==DataType.BOOL && !options.strictBool && actual in ByteDatatypes)
|
||||
null
|
||||
else if(expected in ByteDatatypes && !options.strictBool && actual==DataType.BOOL)
|
||||
null
|
||||
else
|
||||
Pair("argument ${mismatch + 1} type mismatch, was: $actual expected: $expected", call.args[mismatch].position)
|
||||
return Pair("argument ${mismatch + 1} type mismatch, was: $actual expected: $expected", call.args[mismatch].position)
|
||||
}
|
||||
if(target.isAsmSubroutine) {
|
||||
if(target.asmReturnvaluesRegisters.size>1) {
|
||||
|
@ -43,7 +43,6 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
|
||||
breakpointCpuInstruction = null,
|
||||
printAst1 = false,
|
||||
printAst2 = false,
|
||||
strictBool = true,
|
||||
symbolDefs = emptyMap(),
|
||||
outputDir = outputDir
|
||||
)
|
||||
|
@ -41,7 +41,6 @@ class TestCompilerOptionSourcedirs: FunSpec({
|
||||
breakpointCpuInstruction = null,
|
||||
printAst1 = false,
|
||||
printAst2 = false,
|
||||
strictBool = true,
|
||||
symbolDefs = emptyMap(),
|
||||
sourceDirs,
|
||||
outputDir
|
||||
|
@ -43,7 +43,6 @@ internal fun compileFile(
|
||||
breakpointCpuInstruction = null,
|
||||
printAst1 = false,
|
||||
printAst2 = false,
|
||||
strictBool = true
|
||||
)
|
||||
return compileProgram(args)
|
||||
}
|
||||
|
@ -155,10 +155,6 @@ 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.
|
||||
|
@ -5,4 +5,4 @@ org.gradle.daemon=true
|
||||
kotlin.code.style=official
|
||||
javaVersion=11
|
||||
kotlinVersion=2.0.20
|
||||
version=10.4
|
||||
version=10.5-SNAPSHOT
|
||||
|
Loading…
x
Reference in New Issue
Block a user