fixed function argument type cast bug

This commit is contained in:
Irmen de Jong 2020-07-03 17:24:43 +02:00
parent c07907e7bd
commit a6d789cfbc
4 changed files with 70 additions and 17 deletions

View File

@ -38,6 +38,12 @@ internal fun Program.addTypecasts(errors: ErrorReporter) {
caster.applyModifications() caster.applyModifications()
} }
internal fun Program.simplifyNumericCasts() {
val fixer = TypecastsSimplifier(this)
fixer.visit(this)
fixer.applyModifications()
}
internal fun Program.transformAssignments(errors: ErrorReporter) { internal fun Program.transformAssignments(errors: ErrorReporter) {
val transform = AssignmentTransformer(this, errors) val transform = AssignmentTransformer(this, errors)
transform.visit(this) transform.visit(this)

View File

@ -7,6 +7,7 @@ import prog8.ast.Program
import prog8.ast.base.* import prog8.ast.base.*
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.compiler.CompilerException
import prog8.functions.BuiltinFunctions import prog8.functions.BuiltinFunctions
@ -125,8 +126,6 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
} }
is BuiltinFunctionStatementPlaceholder -> { is BuiltinFunctionStatementPlaceholder -> {
val func = BuiltinFunctions.getValue(sub.name) val func = BuiltinFunctions.getValue(sub.name)
if(func.pure) {
// non-pure functions don't get automatic typecasts because sometimes they act directly on their parameters
for (arg in func.parameters.zip(call.args.withIndex())) { for (arg in func.parameters.zip(call.args.withIndex())) {
val argItype = arg.second.value.inferType(program) val argItype = arg.second.value.inferType(program)
if (argItype.isKnown) { if (argItype.isKnown) {
@ -144,7 +143,6 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
} }
} }
} }
}
null -> { } null -> { }
else -> throw FatalAstException("call to something weird $sub ${call.target}") else -> throw FatalAstException("call to something weird $sub ${call.target}")
} }
@ -249,3 +247,52 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
return noModifications return noModifications
} }
} }
class TypecastsSimplifier(val program: Program) : AstWalker() {
/*
* Typecasts of a numeric literal value can be replaced by the numeric value of the type directly.
*/
private val noModifications = emptyList<IAstModification>()
override fun before(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> {
if(typecast.expression is NumericLiteralValue) {
val value = (typecast.expression as NumericLiteralValue).cast(typecast.type)
return listOf(IAstModification.ReplaceNode(typecast, value, parent))
}
return noModifications
}
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification>
= checkCallArgTypes(functionCallStatement as IFunctionCall, functionCallStatement.definingScope())
override fun after(functionCall: FunctionCall, parent: Node): Iterable<IAstModification>
= checkCallArgTypes(functionCall as IFunctionCall, functionCall.definingScope())
private fun checkCallArgTypes(call: IFunctionCall, scope: INameScope): Iterable<IAstModification> {
val argtypes = call.args.map { it.inferType(program).typeOrElse(DataType.STRUCT) }
val target = call.target.targetStatement(scope)
when(target) {
is Subroutine -> {
val paramtypes = target.parameters.map { it.type }
if(argtypes!=paramtypes)
throw CompilerException("parameter type mismatch $call")
}
is BuiltinFunctionStatementPlaceholder -> {
val func = BuiltinFunctions.getValue(target.name)
val paramtypes = func.parameters.map { it.possibleDatatypes }
for(x in argtypes.zip(paramtypes)) {
if(x.first !in x.second)
throw CompilerException("parameter type mismatch $call")
}
}
else -> {}
}
println("**** $target")
return noModifications
}
}

View File

@ -180,6 +180,7 @@ private fun postprocessAst(programAst: Program, errors: ErrorReporter, compilerO
errors.handle() errors.handle()
programAst.addTypecasts(errors) programAst.addTypecasts(errors)
errors.handle() errors.handle()
programAst.simplifyNumericCasts()
programAst.removeNopsFlattenAnonScopes() programAst.removeNopsFlattenAnonScopes()
programAst.checkValid(compilerOptions, errors) // check if final tree is still valid programAst.checkValid(compilerOptions, errors) // check if final tree is still valid
errors.handle() errors.handle()

View File

@ -9,8 +9,7 @@
; TODO fix crash when piece reaches bottom. (codegen issue). ; TODO fix wrong block behavior at bottom when compiled without optimizations (codegen issue).
; TODO fix wrong behavior when compiled without optimizations (codegen issue).
main { main {