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,18 +13,23 @@ import prog8.ast.statements.VarDecl
import prog8.compiler.target.CompilationTarget
// 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>()
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
val declConstValue = decl.value?.constValue(program)
if(declConstValue!=null && (decl.type==VarDeclType.VAR || decl.type==VarDeclType.CONST)
try {
val declConstValue = decl.value?.constValue(program)
if(declConstValue!=null && (decl.type==VarDeclType.VAR || decl.type==VarDeclType.CONST)
&& !declConstValue.inferType(program).istype(decl.datatype)) {
// cast the numeric literal to the appropriate datatype of the variable
val cast = declConstValue.cast(decl.datatype)
if(cast.isValid)
return listOf(IAstModification.ReplaceNode(decl.value!!, cast.valueOrZero(), decl))
// cast the numeric literal to the appropriate datatype of the variable
val cast = declConstValue.cast(decl.datatype)
if(cast.isValid)
return listOf(IAstModification.ReplaceNode(decl.value!!, cast.valueOrZero(), decl))
}
} catch (x: UndefinedSymbolError) {
errors.err(x.message, x.position)
}
return noModifications
}
}
@ -47,11 +52,22 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
if(forloop!=null && identifier===forloop.loopVar)
return noModifications
val cval = identifier.constValue(program) ?: return noModifications
return when (cval.type) {
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")
else -> noModifications
try {
val cval = identifier.constValue(program) ?: return noModifications
return when (cval.type) {
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")
else -> noModifications
}
} catch (x: UndefinedSymbolError) {
errors.err(x.message, x.position)
return noModifications
}
}
@ -78,11 +94,16 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
}
} else if(arraysize.constIndex()==null) {
// see if we can calculate the size from other fields
val cval = arraysize.indexVar?.constValue(program) ?: arraysize.origExpression?.constValue(program)
if(cval!=null) {
arraysize.indexVar = null
arraysize.origExpression = null
arraysize.indexNum = cval
try {
val cval = arraysize.indexVar?.constValue(program) ?: arraysize.origExpression?.constValue(program)
if (cval != null) {
arraysize.indexVar = null
arraysize.origExpression = null
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) {
val valuetypefixer = VarConstantValueTypeAdjuster(this)
val valuetypefixer = VarConstantValueTypeAdjuster(this, errors)
valuetypefixer.visit(this)
if(errors.isEmpty()) {
valuetypefixer.applyModifications()

View File

@ -2,7 +2,6 @@
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.
- 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 '_'

View File

@ -8,7 +8,14 @@
main {
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
}
}