mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
more helpful error messages
This commit is contained in:
parent
a6107fcfdf
commit
413b86cc4a
@ -585,14 +585,22 @@ internal class AstChecker(private val program: Program,
|
||||
checkMultiAssignment(assignment, fcall, fcallTarget)
|
||||
} else if(fcallTarget!=null) {
|
||||
if(fcallTarget.returntypes.size!=1) {
|
||||
errors.err("number of assignment targets doesn't match number of return values from the subroutine", fcall.position)
|
||||
return
|
||||
return numberOfReturnValuesError(1, fcallTarget.returntypes, fcall.position)
|
||||
}
|
||||
}
|
||||
|
||||
super.visit(assignment)
|
||||
}
|
||||
|
||||
private fun numberOfReturnValuesError(actual: Int, expectedTypes: List<DataType>, position: Position) {
|
||||
if(actual<expectedTypes.size) {
|
||||
val missing = expectedTypes.drop(actual).joinToString(", ")
|
||||
errors.err("some return values are not assigned: expected ${expectedTypes.size} got $actual, missing assignments for: $missing", position)
|
||||
}
|
||||
else
|
||||
errors.err("too many return values are assigned: expected ${expectedTypes.size} got $actual", position)
|
||||
}
|
||||
|
||||
private fun checkMultiAssignment(assignment: Assignment, fcall: IFunctionCall?, fcallTarget: Subroutine?) {
|
||||
// multi-assign: check the number of assign targets vs. the number of return values of the subroutine
|
||||
// also check the types of the variables vs the types of each return value
|
||||
@ -602,8 +610,7 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
val targets = assignment.target.multi!!
|
||||
if(fcallTarget.returntypes.size!=targets.size) {
|
||||
errors.err("number of assignment targets doesn't match number of return values from the subroutine", fcall.position)
|
||||
return
|
||||
return numberOfReturnValuesError(targets.size, fcallTarget.returntypes, fcall.position)
|
||||
}
|
||||
fcallTarget.returntypes.zip(targets).withIndex().forEach { (index, p) ->
|
||||
val (returnType, target) = p
|
||||
|
@ -27,6 +27,15 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
||||
errors.warn("name '$name' shadows the definition at ${existing.position.file} line ${existing.position.line}", position)
|
||||
}
|
||||
|
||||
private fun invalidNumberOfArgsError(pos: Position, numArgs: Int, params: List<String>) {
|
||||
if(numArgs<params.size) {
|
||||
val missing = params.drop(numArgs).joinToString(", ")
|
||||
errors.err("invalid number of arguments: expected ${params.size} got $numArgs, missing: $missing", pos)
|
||||
}
|
||||
else
|
||||
errors.err("invalid number of arguments: expected ${params.size} got $numArgs", pos)
|
||||
}
|
||||
|
||||
override fun visit(block: Block) {
|
||||
val existing = blocks[block.name]
|
||||
if(existing!=null) {
|
||||
@ -166,7 +175,7 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
||||
val expectedNumberOfArgs: Int = target.parameters.size
|
||||
if(call.args.size != expectedNumberOfArgs) {
|
||||
val pos = (if(call.args.any()) call.args[0] else (call as Node)).position
|
||||
errors.err("invalid number of arguments", pos)
|
||||
invalidNumberOfArgsError(pos, call.args.size, target.parameters.map { it.name })
|
||||
}
|
||||
}
|
||||
is BuiltinFunctionPlaceholder -> {
|
||||
@ -174,7 +183,7 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
||||
val expectedNumberOfArgs: Int = func.parameters.size
|
||||
if(call.args.size != expectedNumberOfArgs) {
|
||||
val pos = (if(call.args.any()) call.args[0] else (call as Node)).position
|
||||
errors.err("invalid number of arguments", pos)
|
||||
invalidNumberOfArgsError(pos, call.args.size, func.parameters.map {it.name })
|
||||
}
|
||||
if(target.name=="memory") {
|
||||
val name = call.args[0] as? StringLiteral
|
||||
|
@ -3,12 +3,6 @@ TODO
|
||||
|
||||
Regenerate skeleton doc files.
|
||||
|
||||
"invalid number of arguments" -> print the list of missing arguments
|
||||
|
||||
callfar() should allow setting an argument in the X register as well?
|
||||
|
||||
Add a new SublimeText syntax file for prog8, and also install this for bat: https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
|
||||
|
||||
Improve register load order in subroutine call args assignments:
|
||||
in certain situations, the "wrong" order of evaluation of function call arguments is done which results
|
||||
in overwriting registers that already got their value, which requires a lot of stack juggling (especially on plain 6502 cpu!)
|
||||
@ -17,8 +11,9 @@ Maybe this routine can be made more intelligent. See usesOtherRegistersWhileEva
|
||||
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Compiler:
|
||||
|
||||
- Add a new SublimeText syntax file for prog8, and also install this for bat: https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
|
||||
- callfar() should allow setting an argument in the X register as well?
|
||||
- AST weirdness: why is call(...) a normal FunctionCallStatement and not a BuiltinFunctionCall? What does ror() produce for instance?
|
||||
- Can we support signed % (remainder) somehow?
|
||||
- Don't add "random" rts to %asm blocks but instead give a warning about it? (but this breaks existing behavior that others already depend on... command line switch? block directive?)
|
||||
|
@ -1,48 +1,19 @@
|
||||
%import textio
|
||||
%import string
|
||||
%import compression
|
||||
%import test_stack
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
test_stack.test()
|
||||
cx16.r0L = returns3()
|
||||
cx16.r0L, cx16.r1L, cx16.r2L, cx16.r3L = returns3()
|
||||
txt.print_uwhex()
|
||||
txt.print_uwhex(1, true, 2, 3)
|
||||
}
|
||||
|
||||
txt.print_uwhex(cbm.CHROUT, true)
|
||||
txt.print_uwhex(&cbm.CHROUT, true)
|
||||
txt.nl()
|
||||
|
||||
cx16.r0 = &function1
|
||||
callfar(0, $ffd2, $0031)
|
||||
callfar(0, cbm.CHROUT, $000d)
|
||||
callfar(0, function1, $6660)
|
||||
callfar(0, cx16.r0, $ffff)
|
||||
cx16.r0 -=10
|
||||
callfar(0, cx16.r0+10, $eeee)
|
||||
|
||||
cx16.r0 = &function2
|
||||
callfar(0, $ffd2, $0032)
|
||||
callfar(0, cbm.CHROUT, $000d)
|
||||
callfar(0, function2, $6660)
|
||||
callfar(0, cx16.r0, $ffff)
|
||||
cx16.r0 -=10
|
||||
callfar(0, cx16.r0+10, $eeee)
|
||||
|
||||
test_stack.test()
|
||||
cx16.r0++
|
||||
|
||||
sub function1(uword arg) {
|
||||
txt.print("function 1 arg=")
|
||||
txt.print_uwhex(arg, false)
|
||||
txt.nl()
|
||||
}
|
||||
|
||||
sub function2(uword arg) {
|
||||
txt.print("function 2 arg=")
|
||||
txt.print_uwhex(arg, false)
|
||||
txt.nl()
|
||||
}
|
||||
asmsub returns3() -> ubyte @A, ubyte @X, bool @Pc {
|
||||
%asm {{
|
||||
rts
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user