mirror of
https://github.com/irmen/prog8.git
synced 2025-11-06 08:17:10 +00:00
release 7.4.1 - oops, funcion call arg count validation was broken
This commit is contained in:
@@ -1 +1 @@
|
|||||||
7.4
|
7.4.1
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ private fun processAst(program: Program, errors: IErrorReporter, compilerOptions
|
|||||||
// perform initial syntax checks and processings
|
// perform initial syntax checks and processings
|
||||||
println("Processing for target ${compilerOptions.compTarget.name}...")
|
println("Processing for target ${compilerOptions.compTarget.name}...")
|
||||||
program.preprocessAst(program)
|
program.preprocessAst(program)
|
||||||
program.checkIdentifiers(errors, compilerOptions)
|
program.checkIdentifiers(errors, program, compilerOptions)
|
||||||
errors.report()
|
errors.report()
|
||||||
// TODO: turning char literals into UBYTEs via an encoding should really happen in code gen - but for that we'd need DataType.CHAR
|
// TODO: turning char literals into UBYTEs via an encoding should really happen in code gen - but for that we'd need DataType.CHAR
|
||||||
// ...but what do we gain from this? We can leave it as it is now: where a char literal is no more than syntactic sugar for an UBYTE value.
|
// ...but what do we gain from this? We can leave it as it is now: where a char literal is no more than syntactic sugar for an UBYTE value.
|
||||||
@@ -274,7 +274,7 @@ private fun processAst(program: Program, errors: IErrorReporter, compilerOptions
|
|||||||
errors.report()
|
errors.report()
|
||||||
program.checkValid(errors, compilerOptions)
|
program.checkValid(errors, compilerOptions)
|
||||||
errors.report()
|
errors.report()
|
||||||
program.checkIdentifiers(errors, compilerOptions)
|
program.checkIdentifiers(errors, program, compilerOptions)
|
||||||
errors.report()
|
errors.report()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1015,8 +1015,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val error =
|
val error = VerifyFunctionArgTypes.checkTypes(functionCallStatement, program)
|
||||||
VerifyFunctionArgTypes.checkTypes(functionCallStatement, program)
|
|
||||||
if(error!=null) {
|
if(error!=null) {
|
||||||
errors.err(error, functionCallStatement.args.firstOrNull()?.position ?: functionCallStatement.position)
|
errors.err(error, functionCallStatement.args.firstOrNull()?.position ?: functionCallStatement.position)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,9 +73,9 @@ internal fun Program.preprocessAst(program: Program) {
|
|||||||
mods = transforms.applyModifications()
|
mods = transforms.applyModifications()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Program.checkIdentifiers(errors: IErrorReporter, options: CompilationOptions) {
|
internal fun Program.checkIdentifiers(errors: IErrorReporter, program: Program, options: CompilationOptions) {
|
||||||
|
|
||||||
val checker2 = AstIdentifiersChecker(errors, options.compTarget)
|
val checker2 = AstIdentifiersChecker(errors, program, options.compTarget)
|
||||||
checker2.visit(this)
|
checker2.visit(this)
|
||||||
|
|
||||||
if(errors.noErrors()) {
|
if(errors.noErrors()) {
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
package prog8.compiler.astprocessing
|
package prog8.compiler.astprocessing
|
||||||
|
|
||||||
|
import prog8.ast.IFunctionCall
|
||||||
|
import prog8.ast.Node
|
||||||
|
import prog8.ast.Program
|
||||||
|
import prog8.ast.base.FatalAstException
|
||||||
import prog8.ast.base.Position
|
import prog8.ast.base.Position
|
||||||
|
import prog8.ast.expressions.FunctionCall
|
||||||
import prog8.ast.expressions.StringLiteralValue
|
import prog8.ast.expressions.StringLiteralValue
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.ast.walk.IAstVisitor
|
import prog8.ast.walk.IAstVisitor
|
||||||
@@ -8,7 +13,9 @@ import prog8.compilerinterface.BuiltinFunctions
|
|||||||
import prog8.compilerinterface.ICompilationTarget
|
import prog8.compilerinterface.ICompilationTarget
|
||||||
import prog8.compilerinterface.IErrorReporter
|
import prog8.compilerinterface.IErrorReporter
|
||||||
|
|
||||||
internal class AstIdentifiersChecker(private val errors: IErrorReporter, private val compTarget: ICompilationTarget) : IAstVisitor {
|
internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
||||||
|
private val program: Program,
|
||||||
|
private val compTarget: ICompilationTarget) : IAstVisitor {
|
||||||
private var blocks = mutableMapOf<String, Block>()
|
private var blocks = mutableMapOf<String, Block>()
|
||||||
|
|
||||||
private fun nameError(name: String, position: Position, existing: Statement) {
|
private fun nameError(name: String, position: Position, existing: Statement) {
|
||||||
@@ -121,4 +128,27 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter, private
|
|||||||
|
|
||||||
super.visit(string)
|
super.visit(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visit(functionCall: FunctionCall) = visitFunctionCall(functionCall)
|
||||||
|
override fun visit(functionCallStatement: FunctionCallStatement) = visitFunctionCall(functionCallStatement)
|
||||||
|
|
||||||
|
private fun visitFunctionCall(call: IFunctionCall) {
|
||||||
|
when (val target = call.target.targetStatement(program)) {
|
||||||
|
is Subroutine -> {
|
||||||
|
if(call.args.size != target.parameters.size)
|
||||||
|
errors.err("invalid number of arguments", call.args[0].position)
|
||||||
|
}
|
||||||
|
is BuiltinFunctionStatementPlaceholder -> {
|
||||||
|
val func = BuiltinFunctions.getValue(target.name)
|
||||||
|
if(call.args.size != func.parameters.size)
|
||||||
|
errors.err("invalid number of arguments", call.args[0].position)
|
||||||
|
}
|
||||||
|
is Label -> {
|
||||||
|
if(call.args.isNotEmpty())
|
||||||
|
errors.err("cannot use arguments when calling a label", call.args[0].position)
|
||||||
|
}
|
||||||
|
null -> {}
|
||||||
|
else -> throw FatalAstException("weird call target")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import prog8.ast.walk.IAstVisitor
|
|||||||
import prog8.compilerinterface.BuiltinFunctions
|
import prog8.compilerinterface.BuiltinFunctions
|
||||||
import prog8.compilerinterface.InternalCompilerException
|
import prog8.compilerinterface.InternalCompilerException
|
||||||
|
|
||||||
class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {
|
internal class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {
|
||||||
|
|
||||||
override fun visit(functionCall: FunctionCall) {
|
override fun visit(functionCall: FunctionCall) {
|
||||||
val error = checkTypes(functionCall as IFunctionCall, program)
|
val error = checkTypes(functionCall as IFunctionCall, program)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import io.kotest.matchers.types.instanceOf
|
|||||||
import prog8.ast.base.DataType
|
import prog8.ast.base.DataType
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
|
import prog8.compiler.printProgram
|
||||||
import prog8.compiler.target.C64Target
|
import prog8.compiler.target.C64Target
|
||||||
import prog8tests.helpers.ErrorReporterForTests
|
import prog8tests.helpers.ErrorReporterForTests
|
||||||
import prog8tests.helpers.assertFailure
|
import prog8tests.helpers.assertFailure
|
||||||
@@ -262,4 +263,66 @@ class TestSubroutines: FunSpec({
|
|||||||
addressExpr.operator shouldBe "+"
|
addressExpr.operator shouldBe "+"
|
||||||
(addressExpr.right as NumericLiteralValue).number.toInt() shouldBe 10
|
(addressExpr.right as NumericLiteralValue).number.toInt() shouldBe 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("invalid number of args check on normal subroutine") {
|
||||||
|
val text="""
|
||||||
|
main {
|
||||||
|
sub thing(ubyte a1, ubyte a2) {
|
||||||
|
}
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
thing(1)
|
||||||
|
thing(1,2)
|
||||||
|
thing(1,2,3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
val errors = ErrorReporterForTests()
|
||||||
|
compileText(C64Target, false, text, writeAssembly = false, errors=errors).assertFailure()
|
||||||
|
errors.errors.size shouldBe 2
|
||||||
|
errors.errors[0] shouldContain "7:24: invalid number of arguments"
|
||||||
|
errors.errors[1] shouldContain "9:24: invalid number of arguments"
|
||||||
|
}
|
||||||
|
|
||||||
|
test("invalid number of args check on asm subroutine") {
|
||||||
|
val text="""
|
||||||
|
main {
|
||||||
|
asmsub thing(ubyte a1 @A, ubyte a2 @Y) {
|
||||||
|
}
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
thing(1)
|
||||||
|
thing(1,2)
|
||||||
|
thing(1,2,3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
val errors = ErrorReporterForTests()
|
||||||
|
compileText(C64Target, false, text, writeAssembly = false, errors=errors).assertFailure()
|
||||||
|
errors.errors.size shouldBe 2
|
||||||
|
errors.errors[0] shouldContain "7:24: invalid number of arguments"
|
||||||
|
errors.errors[1] shouldContain "9:24: invalid number of arguments"
|
||||||
|
}
|
||||||
|
|
||||||
|
test("invalid number of args check on call to label and builtin func") {
|
||||||
|
val text="""
|
||||||
|
main {
|
||||||
|
label:
|
||||||
|
sub start() {
|
||||||
|
label()
|
||||||
|
label(1)
|
||||||
|
void rnd()
|
||||||
|
void rnd(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
val errors = ErrorReporterForTests()
|
||||||
|
compileText(C64Target, false, text, writeAssembly = false, errors=errors).assertFailure()
|
||||||
|
errors.errors.size shouldBe 2
|
||||||
|
errors.errors[0] shouldContain "cannot use arguments"
|
||||||
|
errors.errors[1] shouldContain "invalid number of arguments"
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,7 +10,14 @@ main {
|
|||||||
byte b2 = 22
|
byte b2 = 22
|
||||||
word b3 = 3333
|
word b3 = 3333
|
||||||
dummy++
|
dummy++
|
||||||
func(-b1,-b2,-b3)
|
labelz()
|
||||||
|
labelz(1)
|
||||||
|
printz(1)
|
||||||
|
printz(1,2,3,4,5,6)
|
||||||
|
func(-b1,-b2,-b3 , 3, 4, 5)
|
||||||
|
|
||||||
|
labelz:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub printz(word a1, byte a2, word a3) {
|
sub printz(word a1, byte a2, word a3) {
|
||||||
|
|||||||
Reference in New Issue
Block a user