mirror of
https://github.com/irmen/prog8.git
synced 2024-11-23 07:32:10 +00:00
fixed function argument type cast bug
This commit is contained in:
parent
c07907e7bd
commit
a6d789cfbc
@ -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)
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user