Skip to content

Commit

Permalink
release 7.4.1 - oops, funcion call arg count validation was broken
Browse files Browse the repository at this point in the history
  • Loading branch information
irmen committed Dec 1, 2021
1 parent 1f34623 commit b7fffbb
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 10 deletions.
2 changes: 1 addition & 1 deletion compiler/res/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.4
7.4.1
4 changes: 2 additions & 2 deletions compiler/src/prog8/compiler/Compiler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ private fun processAst(program: Program, errors: IErrorReporter, compilerOptions
// perform initial syntax checks and processings
println("Processing for target ${compilerOptions.compTarget.name}...")
program.preprocessAst(program)
program.checkIdentifiers(errors, compilerOptions)
program.checkIdentifiers(errors, program, compilerOptions)
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
// ...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.
Expand All @@ -274,7 +274,7 @@ private fun processAst(program: Program, errors: IErrorReporter, compilerOptions
errors.report()
program.checkValid(errors, compilerOptions)
errors.report()
program.checkIdentifiers(errors, compilerOptions)
program.checkIdentifiers(errors, program, compilerOptions)
errors.report()
}

Expand Down
3 changes: 1 addition & 2 deletions compiler/src/prog8/compiler/astprocessing/AstChecker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1015,8 +1015,7 @@ internal class AstChecker(private val program: Program,

}

val error =
VerifyFunctionArgTypes.checkTypes(functionCallStatement, program)
val error = VerifyFunctionArgTypes.checkTypes(functionCallStatement, program)
if(error!=null) {
errors.err(error, functionCallStatement.args.firstOrNull()?.position ?: functionCallStatement.position)
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/prog8/compiler/astprocessing/AstExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ internal fun Program.preprocessAst(program: Program) {
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)

if(errors.noErrors()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
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.expressions.FunctionCall
import prog8.ast.expressions.StringLiteralValue
import prog8.ast.statements.*
import prog8.ast.walk.IAstVisitor
import prog8.compilerinterface.BuiltinFunctions
import prog8.compilerinterface.ICompilationTarget
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 fun nameError(name: String, position: Position, existing: Statement) {
Expand Down Expand Up @@ -121,4 +128,27 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter, private

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")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import prog8.ast.walk.IAstVisitor
import prog8.compilerinterface.BuiltinFunctions
import prog8.compilerinterface.InternalCompilerException

class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {
internal class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {

override fun visit(functionCall: FunctionCall) {
val error = checkTypes(functionCall as IFunctionCall, program)
Expand Down
63 changes: 63 additions & 0 deletions compiler/test/TestSubroutines.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import io.kotest.matchers.types.instanceOf
import prog8.ast.base.DataType
import prog8.ast.expressions.*
import prog8.ast.statements.*
import prog8.compiler.printProgram
import prog8.compiler.target.C64Target
import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.assertFailure
Expand Down Expand Up @@ -262,4 +263,66 @@ class TestSubroutines: FunSpec({
addressExpr.operator shouldBe "+"
(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"
}
})
9 changes: 8 additions & 1 deletion examples/test.p8
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ main {
byte b2 = 22
word b3 = 3333
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) {
Expand Down

0 comments on commit b7fffbb

Please sign in to comment.