From 9d7eb3be5aaa37252a3714d05e496a2ecaa9b91e Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 15 Mar 2020 01:10:08 +0100 Subject: [PATCH] fix error reporting of constantfolding, and number of errors printed --- compiler/src/prog8/ast/AstToplevel.kt | 2 +- compiler/src/prog8/ast/base/ErrorReporting.kt | 13 ++++--- compiler/src/prog8/ast/base/Errors.kt | 8 ++--- compiler/src/prog8/compiler/Main.kt | 3 +- .../src/prog8/optimizer/ConstantFolding.kt | 36 +++++++------------ compiler/src/prog8/optimizer/Extensions.kt | 20 +++-------- 6 files changed, 32 insertions(+), 50 deletions(-) diff --git a/compiler/src/prog8/ast/AstToplevel.kt b/compiler/src/prog8/ast/AstToplevel.kt index 4e013af40..eeefb6809 100644 --- a/compiler/src/prog8/ast/AstToplevel.kt +++ b/compiler/src/prog8/ast/AstToplevel.kt @@ -270,7 +270,7 @@ class GlobalNamespace(val modules: List): Node, INameScope { return when (val stmt = localContext.definingModule().lookup(scopedName, localContext)) { is Label, is VarDecl, is Block, is Subroutine -> stmt null -> null - else -> throw NameError("wrong identifier target: $stmt", stmt.position) + else -> throw SyntaxError("wrong identifier target: $stmt", stmt.position) } } } diff --git a/compiler/src/prog8/ast/base/ErrorReporting.kt b/compiler/src/prog8/ast/base/ErrorReporting.kt index e760f0408..24da8ea6e 100644 --- a/compiler/src/prog8/ast/base/ErrorReporting.kt +++ b/compiler/src/prog8/ast/base/ErrorReporting.kt @@ -17,6 +17,8 @@ class ErrorReporter { fun warn(msg: String, position: Position?) = messages.add(CompilerMessage(MessageSeverity.WARNING, msg, position)) fun handle() { + var numErrors = 0 + var numWarnings = 0 messages.forEach { when(it.severity) { MessageSeverity.ERROR -> System.err.print("\u001b[91m") // bright red @@ -26,14 +28,17 @@ class ErrorReporter { if(msg !in alreadyReportedMessages) { System.err.println(msg) alreadyReportedMessages.add(msg) + when(it.severity) { + MessageSeverity.WARNING -> numWarnings++ + MessageSeverity.ERROR -> numErrors++ + } } System.err.print("\u001b[0m") // reset color } - val numErrors = messages.count { it.severity==MessageSeverity.ERROR } messages.clear() if(numErrors>0) - throw ParsingFailedError("There are $numErrors errors.") + throw ParsingFailedError("There are $numErrors errors and $numWarnings warnings.") } + + fun isEmpty() = messages.isEmpty() } - - diff --git a/compiler/src/prog8/ast/base/Errors.kt b/compiler/src/prog8/ast/base/Errors.kt index 18dc2e0e7..0c2f24978 100644 --- a/compiler/src/prog8/ast/base/Errors.kt +++ b/compiler/src/prog8/ast/base/Errors.kt @@ -6,17 +6,13 @@ class FatalAstException (override var message: String) : Exception(message) open class AstException (override var message: String) : Exception(message) -class SyntaxError(override var message: String, val position: Position) : AstException(message) { +open class SyntaxError(override var message: String, val position: Position) : AstException(message) { override fun toString() = "$position Syntax error: $message" } -open class NameError(override var message: String, val position: Position) : AstException(message) { - override fun toString() = "$position Name error: $message" -} - class ExpressionError(message: String, val position: Position) : AstException(message) { override fun toString() = "$position Error: $message" } class UndefinedSymbolError(symbol: IdentifierReference) - : NameError("undefined symbol: ${symbol.nameInSource.joinToString(".")}", symbol.position) + : SyntaxError("undefined symbol: ${symbol.nameInSource.joinToString(".")}", symbol.position) diff --git a/compiler/src/prog8/compiler/Main.kt b/compiler/src/prog8/compiler/Main.kt index 38694e767..da04af66c 100644 --- a/compiler/src/prog8/compiler/Main.kt +++ b/compiler/src/prog8/compiler/Main.kt @@ -71,7 +71,8 @@ fun compileProgram(filepath: Path, //println(" time1: $time1") val time2 = measureTimeMillis { - programAst.constantFold() + programAst.constantFold(errors) + errors.handle() } //println(" time2: $time2") val time3 = measureTimeMillis { diff --git a/compiler/src/prog8/optimizer/ConstantFolding.kt b/compiler/src/prog8/optimizer/ConstantFolding.kt index 01b7b506e..a84147c07 100644 --- a/compiler/src/prog8/optimizer/ConstantFolding.kt +++ b/compiler/src/prog8/optimizer/ConstantFolding.kt @@ -11,24 +11,14 @@ import prog8.functions.BuiltinFunctions import kotlin.math.floor -class ConstantFolding(private val program: Program) : IAstModifyingVisitor { +class ConstantFolding(private val program: Program, private val errors: ErrorReporter) : IAstModifyingVisitor { var optimizationsDone: Int = 0 - var errors : MutableList = mutableListOf() - private val reportedErrorMessages = mutableSetOf() - - fun addError(x: AstException) { - // check that we don't add the isSameAs error more than once - if(x.toString() !in reportedErrorMessages) { - reportedErrorMessages.add(x.toString()) - errors.add(x) - } - } override fun visit(decl: VarDecl): Statement { // the initializer value can't refer to the variable itself (recursive definition) // TODO: use call tree for this? if(decl.value?.referencesIdentifiers(decl.name) == true || decl.arraysize?.index?.referencesIdentifiers(decl.name) == true) { - errors.add(ExpressionError("recursive var declaration", decl.position)) + errors.err("recursive var declaration", decl.position) return decl } @@ -69,7 +59,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor { // convert the initializer range expression to an actual array val declArraySize = decl.arraysize?.size() if(declArraySize!=null && declArraySize!=rangeExpr.size()) - errors.add(ExpressionError("range expression size doesn't match declared array size", decl.value?.position!!)) + errors.err("range expression size doesn't match declared array size", decl.value?.position!!) val constRange = rangeExpr.toConstantIntegerRange() if(constRange!=null) { val eltType = rangeExpr.inferType(program).typeOrElse(DataType.UBYTE) @@ -88,7 +78,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor { } } if(numericLv!=null && numericLv.type== DataType.FLOAT) - errors.add(ExpressionError("arraysize requires only integers here", numericLv.position)) + errors.err("arraysize requires only integers here", numericLv.position) val size = decl.arraysize?.size() ?: return decl if (rangeExpr==null && numericLv!=null) { // arraysize initializer is empty or a single int, and we know the size; create the arraysize. @@ -96,19 +86,19 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor { when(decl.datatype){ DataType.ARRAY_UB -> { if(fillvalue !in 0..255) - errors.add(ExpressionError("ubyte value overflow", numericLv.position)) + errors.err("ubyte value overflow", numericLv.position) } DataType.ARRAY_B -> { if(fillvalue !in -128..127) - errors.add(ExpressionError("byte value overflow", numericLv.position)) + errors.err("byte value overflow", numericLv.position) } DataType.ARRAY_UW -> { if(fillvalue !in 0..65535) - errors.add(ExpressionError("uword value overflow", numericLv.position)) + errors.err("uword value overflow", numericLv.position) } DataType.ARRAY_W -> { if(fillvalue !in -32768..32767) - errors.add(ExpressionError("word value overflow", numericLv.position)) + errors.err("word value overflow", numericLv.position) } else -> {} } @@ -131,7 +121,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor { // arraysize initializer is a single int, and we know the size. val fillvalue = litval.number.toDouble() if (fillvalue < CompilationTarget.machine.FLOAT_MAX_NEGATIVE || fillvalue > CompilationTarget.machine.FLOAT_MAX_POSITIVE) - errors.add(ExpressionError("float value overflow", litval.position)) + errors.err("float value overflow", litval.position) else { // create the array itself, filled with the fillvalue. val array = Array(size) {fillvalue}.map { NumericLiteralValue(DataType.FLOAT, it, litval.position) as Expression}.toTypedArray() @@ -178,7 +168,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor { else -> identifier } } catch (ax: AstException) { - addError(ax) + errors.err("unhandled AST error: $ax", identifier.position) identifier } } @@ -189,7 +179,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor { return try { functionCall.constValue(program) ?: functionCall } catch (ax: AstException) { - addError(ax) + errors.err("unhandled AST error: $ax", functionCall.position) functionCall } } @@ -284,7 +274,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor { } return prefixExpr } catch (ax: AstException) { - addError(ax) + errors.err("unhandled AST error: $ax", expr.position) expr } } @@ -344,7 +334,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor { else -> expr } } catch (ax: AstException) { - addError(ax) + errors.err("unhandled AST error: $ax", expr.position) expr } } diff --git a/compiler/src/prog8/optimizer/Extensions.kt b/compiler/src/prog8/optimizer/Extensions.kt index 9447cf9f5..fdaa6c275 100644 --- a/compiler/src/prog8/optimizer/Extensions.kt +++ b/compiler/src/prog8/optimizer/Extensions.kt @@ -1,30 +1,20 @@ package prog8.optimizer import prog8.ast.Program -import prog8.ast.base.AstException import prog8.ast.base.ErrorReporter -import prog8.parser.ParsingFailedError -internal fun Program.constantFold() { - val optimizer = ConstantFolding(this) - try { - optimizer.visit(this) - } catch (ax: AstException) { - optimizer.addError(ax) - } +internal fun Program.constantFold(errors: ErrorReporter) { + val optimizer = ConstantFolding(this, errors) + optimizer.visit(this) - while(optimizer.errors.isEmpty() && optimizer.optimizationsDone>0) { + while(errors.isEmpty() && optimizer.optimizationsDone>0) { optimizer.optimizationsDone = 0 optimizer.visit(this) } - if(optimizer.errors.isNotEmpty()) { - optimizer.errors.forEach { System.err.println(it) } - throw ParsingFailedError("There are ${optimizer.errors.size} errors.") - } else { + if(errors.isEmpty()) modules.forEach { it.linkParents(namespace) } // re-link in final configuration - } }