undefined symbol errors are no longer reported one at a time but all at once

This commit is contained in:
Irmen de Jong 2020-12-21 13:03:56 +01:00
parent 7f2aea60c9
commit 50213f146a
5 changed files with 48 additions and 21 deletions

View File

@ -1 +1 @@
5.4 5.5-SNAPSHOT

View File

@ -13,10 +13,11 @@ import prog8.ast.statements.VarDecl
import prog8.compiler.target.CompilationTarget import prog8.compiler.target.CompilationTarget
// Fix up the literal value's type to match that of the vardecl // Fix up the literal value's type to match that of the vardecl
internal class VarConstantValueTypeAdjuster(private val program: Program) : AstWalker() { internal class VarConstantValueTypeAdjuster(private val program: Program, private val errors: ErrorReporter) : AstWalker() {
private val noModifications = emptyList<IAstModification>() private val noModifications = emptyList<IAstModification>()
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> { override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
try {
val declConstValue = decl.value?.constValue(program) val declConstValue = decl.value?.constValue(program)
if(declConstValue!=null && (decl.type==VarDeclType.VAR || decl.type==VarDeclType.CONST) if(declConstValue!=null && (decl.type==VarDeclType.VAR || decl.type==VarDeclType.CONST)
&& !declConstValue.inferType(program).istype(decl.datatype)) { && !declConstValue.inferType(program).istype(decl.datatype)) {
@ -25,6 +26,10 @@ internal class VarConstantValueTypeAdjuster(private val program: Program) : AstW
if(cast.isValid) if(cast.isValid)
return listOf(IAstModification.ReplaceNode(decl.value!!, cast.valueOrZero(), decl)) return listOf(IAstModification.ReplaceNode(decl.value!!, cast.valueOrZero(), decl))
} }
} catch (x: UndefinedSymbolError) {
errors.err(x.message, x.position)
}
return noModifications return noModifications
} }
} }
@ -47,12 +52,23 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
if(forloop!=null && identifier===forloop.loopVar) if(forloop!=null && identifier===forloop.loopVar)
return noModifications return noModifications
try {
val cval = identifier.constValue(program) ?: return noModifications val cval = identifier.constValue(program) ?: return noModifications
return when (cval.type) { return when (cval.type) {
in NumericDatatypes -> listOf(IAstModification.ReplaceNode(identifier, NumericLiteralValue(cval.type, cval.number, identifier.position), identifier.parent)) in NumericDatatypes -> listOf(
IAstModification.ReplaceNode(
identifier,
NumericLiteralValue(cval.type, cval.number, identifier.position),
identifier.parent
)
)
in PassByReferenceDatatypes -> throw FatalAstException("pass-by-reference type should not be considered a constant") in PassByReferenceDatatypes -> throw FatalAstException("pass-by-reference type should not be considered a constant")
else -> noModifications else -> noModifications
} }
} catch (x: UndefinedSymbolError) {
errors.err(x.message, x.position)
return noModifications
}
} }
override fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> { override fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> {
@ -78,12 +94,17 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
} }
} else if(arraysize.constIndex()==null) { } else if(arraysize.constIndex()==null) {
// see if we can calculate the size from other fields // see if we can calculate the size from other fields
try {
val cval = arraysize.indexVar?.constValue(program) ?: arraysize.origExpression?.constValue(program) val cval = arraysize.indexVar?.constValue(program) ?: arraysize.origExpression?.constValue(program)
if(cval!=null) { if (cval != null) {
arraysize.indexVar = null arraysize.indexVar = null
arraysize.origExpression = null arraysize.origExpression = null
arraysize.indexNum = cval arraysize.indexNum = cval
} }
} catch (x: UndefinedSymbolError) {
errors.err(x.message, x.position)
return noModifications
}
} }
} }

View File

@ -5,7 +5,7 @@ import prog8.ast.base.ErrorReporter
internal fun Program.constantFold(errors: ErrorReporter) { internal fun Program.constantFold(errors: ErrorReporter) {
val valuetypefixer = VarConstantValueTypeAdjuster(this) val valuetypefixer = VarConstantValueTypeAdjuster(this, errors)
valuetypefixer.visit(this) valuetypefixer.visit(this)
if(errors.isEmpty()) { if(errors.isEmpty()) {
valuetypefixer.applyModifications() valuetypefixer.applyModifications()

View File

@ -2,7 +2,6 @@
TODO TODO
==== ====
- see if we can group some errors together for instance the (now single) errors about unidentified symbols
- Cx16 target: support full-screen 640x480 and 320x240 graphics? That requires our own custom graphics routines though to draw lines. - Cx16 target: support full-screen 640x480 and 320x240 graphics? That requires our own custom graphics routines though to draw lines.
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine) - hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_' - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'

View File

@ -8,7 +8,14 @@
main { main {
sub start () { sub start () {
float x = floo()
floats.print_f(x2)
test_stack.test2()
blerp=foobar+xxx
}
test_stack.test() sub floo() -> float {
float fl = 1.1
return flxxx * 2
} }
} }