mirror of
https://github.com/irmen/prog8.git
synced 2024-05-29 01:41:32 +00:00
nostrictbool array conversions
This commit is contained in:
parent
da1620807f
commit
84afb374e6
|
@ -26,6 +26,7 @@ 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()
|
||||
|
|
|
@ -270,7 +270,11 @@ class VarConstantValueTypeAdjuster(
|
|||
// Replace all constant identifiers with their actual value,
|
||||
// and the array var initializer values and sizes.
|
||||
// This is needed because further constant optimizations depend on those.
|
||||
internal class ConstantIdentifierReplacer(private val program: Program, private val errors: IErrorReporter, private val compTarget: ICompilationTarget) : AstWalker() {
|
||||
internal class ConstantIdentifierReplacer(
|
||||
private val program: Program,
|
||||
private val options: CompilationOptions,
|
||||
private val errors: IErrorReporter
|
||||
) : AstWalker() {
|
||||
|
||||
override fun before(addressOf: AddressOf, parent: Node): Iterable<IAstModification> {
|
||||
val constValue = addressOf.constValue(program)
|
||||
|
@ -472,7 +476,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
|
|||
if(rangeExpr==null && numericLv!=null) {
|
||||
// arraysize initializer is a single int, and we know the array size.
|
||||
val fillvalue = numericLv.number
|
||||
if (fillvalue < compTarget.machine.FLOAT_MAX_NEGATIVE || fillvalue > compTarget.machine.FLOAT_MAX_POSITIVE)
|
||||
if (fillvalue < options.compTarget.machine.FLOAT_MAX_NEGATIVE || fillvalue > options.compTarget.machine.FLOAT_MAX_POSITIVE)
|
||||
errors.err("float value overflow", numericLv.position)
|
||||
else {
|
||||
val array = Array(size) {fillvalue}.map { NumericLiteral(DataType.FLOAT, it, numericLv.position) }.toTypedArray<Expression>()
|
||||
|
@ -486,7 +490,8 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
|
|||
if(numericLv!=null) {
|
||||
// arraysize initializer is a single value, and we know the array size.
|
||||
if(numericLv.type!=DataType.BOOL) {
|
||||
errors.err("initializer value is not a boolean", numericLv.position)
|
||||
if(options.strictBool || numericLv.type !in ByteDatatypes)
|
||||
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>()
|
||||
|
|
|
@ -12,7 +12,7 @@ fun Program.constantFold(errors: IErrorReporter, options: CompilationOptions) {
|
|||
if(errors.noErrors()) {
|
||||
valuetypefixer.applyModifications()
|
||||
|
||||
val replacer = ConstantIdentifierReplacer(this, errors, options.compTarget)
|
||||
val replacer = ConstantIdentifierReplacer(this, options, errors)
|
||||
replacer.visit(this)
|
||||
if (errors.noErrors()) {
|
||||
replacer.applyModifications()
|
||||
|
|
|
@ -44,6 +44,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
|||
val experimentalCodegen by cli.option(ArgType.Boolean, fullName = "expericodegen", description = "use experimental/alternative codegen")
|
||||
val dumpVariables by cli.option(ArgType.Boolean, fullName = "dumpvars", description = "print a dump of the variables in the program")
|
||||
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").default(false)
|
||||
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")
|
||||
|
@ -163,6 +164,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
|||
breakpointCpuInstruction,
|
||||
printAst1 == true,
|
||||
printAst2 == true,
|
||||
noStrictBool == false,
|
||||
processedSymbols,
|
||||
srcdirs,
|
||||
outputPath
|
||||
|
@ -242,6 +244,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
|||
breakpointCpuInstruction,
|
||||
printAst1 == true,
|
||||
printAst2 == true,
|
||||
noStrictBool == false,
|
||||
processedSymbols,
|
||||
srcdirs,
|
||||
outputPath
|
||||
|
|
|
@ -6,10 +6,10 @@ package prog8.buildversion
|
|||
const val MAVEN_GROUP = "prog8"
|
||||
const val MAVEN_NAME = "compiler"
|
||||
const val VERSION = "10.2-BOOLEANS"
|
||||
const val GIT_REVISION = 4512
|
||||
const val GIT_SHA = "a977e3402faab7f2b63af7127fd628cbbdb8a7ad"
|
||||
const val GIT_DATE = "2024-02-25T15:41:16Z"
|
||||
const val GIT_BRANCH = "booleans"
|
||||
const val BUILD_DATE = "2024-02-25T16:07:25Z"
|
||||
const val BUILD_UNIX_TIME = 1708877245670L
|
||||
const val GIT_REVISION = 4530
|
||||
const val GIT_SHA = "c7843b4ed8919870983fdf9d27413caf690d948a"
|
||||
const val GIT_DATE = "2024-03-03T13:01:46Z"
|
||||
const val GIT_BRANCH = "booleans-nostrictbool"
|
||||
const val BUILD_DATE = "2024-03-03T13:12:36Z"
|
||||
const val BUILD_UNIX_TIME = 1709471556477L
|
||||
const val DIRTY = 1
|
||||
|
|
|
@ -48,6 +48,7 @@ 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(""),
|
||||
|
@ -93,6 +94,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
|||
splitWordArrays = args.splitWordArrays
|
||||
outputDir = args.outputDir.normalize()
|
||||
symbolDefs = args.symbolDefs
|
||||
strictBool = args.strictBool
|
||||
}
|
||||
program = programresult
|
||||
importedFiles = imported
|
||||
|
@ -404,7 +406,7 @@ private fun processAst(program: Program, errors: IErrorReporter, compilerOptions
|
|||
errors.report()
|
||||
program.reorderStatements(errors)
|
||||
errors.report()
|
||||
program.desugaring(errors)
|
||||
program.desugaring(errors, compilerOptions)
|
||||
errors.report()
|
||||
program.changeNotExpressionAndIfComparisonExpr(errors, compilerOptions.compTarget)
|
||||
errors.report()
|
||||
|
@ -448,13 +450,13 @@ private fun optimizeAst(program: Program, compilerOptions: CompilationOptions, e
|
|||
}
|
||||
|
||||
private fun postprocessAst(program: Program, errors: IErrorReporter, compilerOptions: CompilationOptions) {
|
||||
program.desugaring(errors)
|
||||
program.desugaring(errors, compilerOptions)
|
||||
program.addTypecasts(errors, compilerOptions)
|
||||
errors.report()
|
||||
program.variousCleanups(errors, compilerOptions)
|
||||
val callGraph = CallGraph(program)
|
||||
callGraph.checkRecursiveCalls(errors)
|
||||
program.verifyFunctionArgTypes(errors)
|
||||
program.verifyFunctionArgTypes(errors, compilerOptions)
|
||||
errors.report()
|
||||
program.moveMainBlockAsFirst()
|
||||
program.checkValid(errors, compilerOptions) // check if final tree is still valid
|
||||
|
|
|
@ -150,8 +150,11 @@ internal class AstChecker(private val program: Program,
|
|||
}
|
||||
|
||||
override fun visit(ifElse: IfElse) {
|
||||
if(!ifElse.condition.inferType(program).isBool)
|
||||
errors.err("condition should be a boolean", ifElse.condition.position)
|
||||
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)
|
||||
}
|
||||
|
||||
val constvalue = ifElse.condition.constValue(program)
|
||||
if(constvalue!=null) {
|
||||
|
@ -476,15 +479,21 @@ internal class AstChecker(private val program: Program,
|
|||
}
|
||||
|
||||
override fun visit(untilLoop: UntilLoop) {
|
||||
if(!untilLoop.condition.inferType(program).isBool)
|
||||
errors.err("condition should be a boolean", untilLoop.condition.position)
|
||||
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)
|
||||
}
|
||||
|
||||
super.visit(untilLoop)
|
||||
}
|
||||
|
||||
override fun visit(whileLoop: WhileLoop) {
|
||||
if(!whileLoop.condition.inferType(program).isBool)
|
||||
errors.err("condition should be a boolean", whileLoop.condition.position)
|
||||
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)
|
||||
}
|
||||
|
||||
super.visit(whileLoop)
|
||||
}
|
||||
|
@ -697,7 +706,9 @@ internal class AstChecker(private val program: Program,
|
|||
if(decl.isArray) {
|
||||
val eltDt = ArrayToElementTypes.getValue(decl.datatype)
|
||||
if(iDt isnot eltDt) {
|
||||
if(!(iDt.isBool && eltDt==DataType.UBYTE || iDt.istype(DataType.UBYTE) && eltDt==DataType.BOOL))
|
||||
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})")
|
||||
}
|
||||
} else {
|
||||
|
@ -1153,7 +1164,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)
|
||||
val error = VerifyFunctionArgTypes.checkTypes(functionCallExpr, program, compilerOptions)
|
||||
if(error!=null)
|
||||
errors.err(error.first, error.second)
|
||||
|
||||
|
@ -1256,7 +1267,7 @@ internal class AstChecker(private val program: Program,
|
|||
|
||||
}
|
||||
|
||||
val error = VerifyFunctionArgTypes.checkTypes(functionCallStatement, program)
|
||||
val error = VerifyFunctionArgTypes.checkTypes(functionCallStatement, program, compilerOptions)
|
||||
if(error!=null)
|
||||
errors.err(error.first, error.second)
|
||||
|
||||
|
@ -1645,8 +1656,10 @@ internal class AstChecker(private val program: Program,
|
|||
return err("value '$number' out of range for word")
|
||||
}
|
||||
DataType.BOOL -> {
|
||||
if(value.type!=DataType.BOOL)
|
||||
err("type of value ${value.type} doesn't match target $targetDt")
|
||||
if (value.type!=DataType.BOOL) {
|
||||
if (compilerOptions.strictBool || value.type !in ByteDatatypes)
|
||||
err("type of value ${value.type} doesn't match target $targetDt")
|
||||
}
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
val eltDt = ArrayToElementTypes.getValue(targetDt)
|
||||
|
@ -1745,6 +1758,14 @@ internal class AstChecker(private val program: Program,
|
|||
else if(targetDatatype==DataType.UWORD && sourceDatatype in PassByReferenceDatatypes) {
|
||||
// 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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
else {
|
||||
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
|
||||
}
|
||||
|
|
|
@ -92,15 +92,15 @@ internal fun Program.addTypecasts(errors: IErrorReporter, options: CompilationOp
|
|||
caster.applyModifications()
|
||||
}
|
||||
|
||||
fun Program.desugaring(errors: IErrorReporter) {
|
||||
val desugar = CodeDesugarer(this, errors)
|
||||
fun Program.desugaring(errors: IErrorReporter, options: CompilationOptions) {
|
||||
val desugar = CodeDesugarer(this, options, errors)
|
||||
desugar.visit(this)
|
||||
while(errors.noErrors() && desugar.applyModifications()>0)
|
||||
desugar.visit(this)
|
||||
}
|
||||
|
||||
internal fun Program.verifyFunctionArgTypes(errors: IErrorReporter) {
|
||||
val fixer = VerifyFunctionArgTypes(this, errors)
|
||||
internal fun Program.verifyFunctionArgTypes(errors: IErrorReporter, options: CompilationOptions) {
|
||||
val fixer = VerifyFunctionArgTypes(this, options, errors)
|
||||
fixer.visit(this)
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ internal fun Program.checkIdentifiers(errors: IErrorReporter, options: Compilati
|
|||
checker2.visit(this)
|
||||
|
||||
if(errors.noErrors()) {
|
||||
val lit2decl = LiteralsToAutoVars(this, options.compTarget, errors)
|
||||
val lit2decl = LiteralsToAutoVars(this, errors)
|
||||
lit2decl.visit(this)
|
||||
if(errors.noErrors())
|
||||
lit2decl.applyModifications()
|
||||
|
|
|
@ -5,13 +5,10 @@ import prog8.ast.expressions.*
|
|||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.ComparisonOperators
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.IErrorReporter
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.core.*
|
||||
|
||||
|
||||
internal class CodeDesugarer(val program: Program, private val errors: IErrorReporter) : AstWalker() {
|
||||
internal class CodeDesugarer(val program: Program, private val options: CompilationOptions, 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 !
|
||||
|
@ -125,8 +122,11 @@ if not CONDITION
|
|||
|
||||
override fun after(whileLoop: WhileLoop, parent: Node): Iterable<IAstModification> {
|
||||
|
||||
if(!whileLoop.condition.inferType(program).isBool)
|
||||
errors.err("condition should be a boolean", whileLoop.condition.position)
|
||||
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)
|
||||
}
|
||||
|
||||
/*
|
||||
while true -> repeat
|
||||
|
|
|
@ -13,13 +13,13 @@ import prog8.ast.statements.VarDecl
|
|||
import prog8.ast.statements.WhenChoice
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.*
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.IErrorReporter
|
||||
import prog8.code.core.NumericDatatypesWithBoolean
|
||||
import prog8.code.core.SplitWordArrayTypes
|
||||
|
||||
|
||||
internal class LiteralsToAutoVars(private val program: Program,
|
||||
private val target: ICompilationTarget,
|
||||
private val errors: IErrorReporter
|
||||
) : AstWalker() {
|
||||
internal class LiteralsToAutoVars(private val program: Program, private val errors: IErrorReporter) : AstWalker() {
|
||||
|
||||
override fun after(string: StringLiteral, parent: Node): Iterable<IAstModification> {
|
||||
if(string.parent !is VarDecl && string.parent !is WhenChoice) {
|
||||
|
|
|
@ -24,6 +24,10 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
|||
val valueDt = declValue.inferType(program)
|
||||
if(valueDt isnot decl.datatype) {
|
||||
|
||||
if(decl.isArray && !options.strictBool) {
|
||||
tryConvertBooleanArrays(decl, declValue, parent)
|
||||
}
|
||||
|
||||
if(valueDt.isInteger && decl.isArray) {
|
||||
if(decl.datatype == DataType.ARRAY_BOOL) {
|
||||
val integer = declValue.constValue(program)?.number
|
||||
|
@ -49,6 +53,62 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
|||
return noModifications
|
||||
}
|
||||
|
||||
private fun tryConvertBooleanArrays(decl: VarDecl, declValue: Expression, parent: Node) {
|
||||
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)
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_B -> {
|
||||
if(valueNumber!=null) {
|
||||
decl.value = NumericLiteral(DataType.BYTE, if(valueNumber.asBooleanValue) 1.0 else 0.0, declValue.position)
|
||||
decl.linkParents(parent)
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_UB -> {
|
||||
if(valueNumber!=null) {
|
||||
decl.value = NumericLiteral(DataType.UBYTE, if(valueNumber.asBooleanValue) 1.0 else 0.0, declValue.position)
|
||||
decl.linkParents(parent)
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
else -> { /* no casting possible */ }
|
||||
}
|
||||
}
|
||||
|
||||
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
||||
val leftDt = expr.left.inferType(program)
|
||||
val rightDt = expr.right.inferType(program)
|
||||
|
@ -192,6 +252,17 @@ 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) {
|
||||
return castLiteral(cvalue)
|
||||
}
|
||||
if (targettype == DataType.UBYTE && valuetype == DataType.BOOL) {
|
||||
return castLiteral(cvalue)
|
||||
}
|
||||
if (targettype == DataType.BYTE && valuetype == DataType.BOOL) {
|
||||
return castLiteral(cvalue)
|
||||
}
|
||||
}
|
||||
if (valuetype == DataType.BYTE && targettype == DataType.UBYTE) {
|
||||
if(number>0)
|
||||
return castLiteral(cvalue)
|
||||
|
|
|
@ -7,7 +7,7 @@ import prog8.ast.statements.*
|
|||
import prog8.ast.walk.IAstVisitor
|
||||
import prog8.code.core.*
|
||||
|
||||
internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorReporter) : IAstVisitor {
|
||||
internal class VerifyFunctionArgTypes(val program: Program, val options: CompilationOptions, val errors: IErrorReporter) : IAstVisitor {
|
||||
|
||||
override fun visit(program: Program) {
|
||||
super.visit(program)
|
||||
|
@ -41,7 +41,7 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
|
|||
private val memorySlabs = mutableListOf<Slab>()
|
||||
|
||||
override fun visit(functionCallExpr: FunctionCallExpression) {
|
||||
val error = checkTypes(functionCallExpr as IFunctionCall, program)
|
||||
val error = checkTypes(functionCallExpr as IFunctionCall, program, options)
|
||||
if(error!=null)
|
||||
errors.err(error.first, error.second)
|
||||
else {
|
||||
|
@ -62,7 +62,7 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
|
|||
}
|
||||
|
||||
override fun visit(functionCallStatement: FunctionCallStatement) {
|
||||
val error = checkTypes(functionCallStatement as IFunctionCall, program)
|
||||
val error = checkTypes(functionCallStatement as IFunctionCall, program, options)
|
||||
if(error!=null)
|
||||
errors.err(error.first, error.second)
|
||||
|
||||
|
@ -85,7 +85,7 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
|
|||
return false
|
||||
}
|
||||
|
||||
fun checkTypes(call: IFunctionCall, program: Program): Pair<String, Position>? {
|
||||
fun checkTypes(call: IFunctionCall, program: Program, options: CompilationOptions): Pair<String, Position>? {
|
||||
val argITypes = call.args.map { it.inferType(program) }
|
||||
val firstUnknownDt = argITypes.indexOfFirst { it.isUnknown }
|
||||
if(firstUnknownDt>=0) {
|
||||
|
@ -105,7 +105,12 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
|
|||
if(mismatch>=0) {
|
||||
val actual = argtypes[mismatch]
|
||||
val expected = consideredParamTypes[mismatch]
|
||||
return Pair("argument ${mismatch + 1} type mismatch, was: $actual expected: $expected", call.args[mismatch].position)
|
||||
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)
|
||||
}
|
||||
if(target.isAsmSubroutine) {
|
||||
if(target.asmReturnvaluesRegisters.size>1) {
|
||||
|
|
|
@ -42,6 +42,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
|
|||
breakpointCpuInstruction = null,
|
||||
printAst1 = false,
|
||||
printAst2 = false,
|
||||
strictBool = true,
|
||||
symbolDefs = emptyMap(),
|
||||
outputDir = outputDir
|
||||
)
|
||||
|
|
|
@ -40,6 +40,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
|
|||
breakpointCpuInstruction = null,
|
||||
printAst1 = false,
|
||||
printAst2 = false,
|
||||
strictBool = true,
|
||||
symbolDefs = emptyMap(),
|
||||
sourceDirs,
|
||||
outputDir
|
||||
|
|
|
@ -41,7 +41,8 @@ internal fun compileFile(
|
|||
splitWordArrays = false,
|
||||
breakpointCpuInstruction = null,
|
||||
printAst1 = false,
|
||||
printAst2 = false
|
||||
printAst2 = false,
|
||||
strictBool = true
|
||||
)
|
||||
return compileProgram(args)
|
||||
}
|
||||
|
|
|
@ -5,22 +5,34 @@
|
|||
|
||||
main {
|
||||
sub start() {
|
||||
word @shared w = -20
|
||||
word[] warr = [-1111, -2222, -3333]
|
||||
word[] @split swarr = [-1111, -2222, -3333]
|
||||
cx16.r0L = true
|
||||
cx16.r1L = false
|
||||
|
||||
cx16.r0L=1
|
||||
if warr[cx16.r0L] > 0
|
||||
txt.print("yep1")
|
||||
bool @shared bzz = 1
|
||||
ubyte @shared ubb = true
|
||||
|
||||
if warr[cx16.r0L] <= 0
|
||||
txt.print("yep2")
|
||||
bool @shared bb1, bb2
|
||||
bb1 = 0
|
||||
bb2 = 44
|
||||
|
||||
if swarr[cx16.r0L] > 0
|
||||
txt.print("yep3")
|
||||
; bool[3] barr1 = 42
|
||||
byte[3] @shared sbarr1 = true
|
||||
ubyte[3] @shared ubarr1 = true
|
||||
|
||||
if swarr[cx16.r0L] <= 0
|
||||
txt.print("yep4")
|
||||
bool[] @shared boolarray = [1,0]
|
||||
bool[] @shared boolarray2 = [42,0,false]
|
||||
byte[] @shared sba = [true, false]
|
||||
byte[] @shared sba2 = [true, false, 42]
|
||||
ubyte[] @shared uba = [true, false]
|
||||
ubyte[] @shared uba2 = [true, false, 42]
|
||||
|
||||
txt.print_ubhex(bb1, 1)
|
||||
txt.print_ubhex(bb2, 42)
|
||||
txt.print_ubhex(bb2, cx16.r0L)
|
||||
|
||||
if cx16.r0L {
|
||||
cx16.r0L++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ class RequestParser : Take {
|
|||
breakpointCpuInstruction = null,
|
||||
printAst1 = false,
|
||||
printAst2 = false,
|
||||
strictBool = true,
|
||||
varsHighBank = null,
|
||||
varsGolden = false,
|
||||
slabsHighBank = null,
|
||||
|
|
Loading…
Reference in New Issue
Block a user