diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index dd890256a..d7f9c6500 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -11,7 +11,7 @@ import prog8.ast.walk.IAstModification import prog8.compiler.target.ICompilationTarget -internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: ErrorReporter, private val compTarget: ICompilationTarget) : AstWalker() { +internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: IErrorReporter, private val compTarget: ICompilationTarget) : AstWalker() { private val noModifications = emptyList() diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 3e5a15fd8..66401eed6 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -165,7 +165,7 @@ private class BuiltinFunctionsFacade(functions: Map): IBuilt builtinFunctionReturnType(name, args, program) } -private fun parseImports(filepath: Path, errors: ErrorReporter, compTarget: ICompilationTarget): Triple> { +private fun parseImports(filepath: Path, errors: IErrorReporter, compTarget: ICompilationTarget): Triple> { val compilationTargetName = compTarget.name println("Compiler target: $compilationTargetName. Parsing...") val importer = ModuleImporter() @@ -173,7 +173,7 @@ private fun parseImports(filepath: Path, errors: ErrorReporter, compTarget: ICom val programAst = Program(moduleName(filepath.fileName), mutableListOf(), bf, compTarget) bf.program = programAst importer.importModule(programAst, filepath, compTarget, compilationTargetName) - errors.handle() + errors.report() val importedFiles = programAst.modules.filter { !it.source.startsWith("@embedded@") }.map { it.source } val compilerOptions = determineCompilationOptions(programAst, compTarget) @@ -187,7 +187,7 @@ private fun parseImports(filepath: Path, errors: ErrorReporter, compTarget: ICom // always import prog8_lib and math importer.importLibraryModule(programAst, "math", compTarget, compilationTargetName) importer.importLibraryModule(programAst, "prog8_lib", compTarget, compilationTargetName) - errors.handle() + errors.report() return Triple(programAst, compilerOptions, importedFiles) } @@ -242,25 +242,25 @@ private fun determineCompilationOptions(program: Program, compTarget: ICompilati ) } -private fun processAst(programAst: Program, errors: ErrorReporter, compilerOptions: CompilationOptions) { +private fun processAst(programAst: Program, errors: IErrorReporter, compilerOptions: CompilationOptions) { // perform initial syntax checks and processings println("Processing for target ${compilerOptions.compTarget.name}...") programAst.checkIdentifiers(errors, compilerOptions.compTarget) - errors.handle() + errors.report() programAst.constantFold(errors, compilerOptions.compTarget) - errors.handle() + errors.report() programAst.reorderStatements(errors) - errors.handle() + errors.report() programAst.addTypecasts(errors) - errors.handle() + errors.report() programAst.variousCleanups() programAst.checkValid(compilerOptions, errors, compilerOptions.compTarget) - errors.handle() + errors.report() programAst.checkIdentifiers(errors, compilerOptions.compTarget) - errors.handle() + errors.report() } -private fun optimizeAst(programAst: Program, errors: ErrorReporter, functions: IBuiltinFunctions, compTarget: ICompilationTarget) { +private fun optimizeAst(programAst: Program, errors: IErrorReporter, functions: IBuiltinFunctions, compTarget: ICompilationTarget) { // optimize the parse tree println("Optimizing...") while (true) { @@ -269,7 +269,7 @@ private fun optimizeAst(programAst: Program, errors: ErrorReporter, functions: I val optsDone2 = programAst.splitBinaryExpressions(compTarget) val optsDone3 = programAst.optimizeStatements(errors, functions, compTarget) programAst.constantFold(errors, compTarget) // because simplified statements and expressions can result in more constants that can be folded away - errors.handle() + errors.report() if (optsDone1 + optsDone2 + optsDone3 == 0) break } @@ -277,29 +277,29 @@ private fun optimizeAst(programAst: Program, errors: ErrorReporter, functions: I val remover = UnusedCodeRemover(programAst, errors, compTarget) remover.visit(programAst) remover.applyModifications() - errors.handle() + errors.report() } -private fun postprocessAst(programAst: Program, errors: ErrorReporter, compilerOptions: CompilationOptions) { +private fun postprocessAst(programAst: Program, errors: IErrorReporter, compilerOptions: CompilationOptions) { programAst.addTypecasts(errors) - errors.handle() + errors.report() programAst.variousCleanups() programAst.checkValid(compilerOptions, errors, compilerOptions.compTarget) // check if final tree is still valid - errors.handle() + errors.report() val callGraph = CallGraph(programAst) callGraph.checkRecursiveCalls(errors) - errors.handle() + errors.report() programAst.verifyFunctionArgTypes() programAst.moveMainAndStartToFirst() } private fun writeAssembly(programAst: Program, - errors: ErrorReporter, + errors: IErrorReporter, outputDir: Path, compilerOptions: CompilationOptions): String { // asm generation directly from the Ast, programAst.processAstBeforeAsmGeneration(errors, compilerOptions.compTarget) - errors.handle() + errors.report() // printAst(programAst) @@ -311,7 +311,7 @@ private fun writeAssembly(programAst: Program, compilerOptions, outputDir).compileToAssembly() assembly.assemble(compilerOptions) - errors.handle() + errors.report() return assembly.name } diff --git a/compiler/src/prog8/compiler/ErrorReporting.kt b/compiler/src/prog8/compiler/ErrorReporting.kt index 676244f74..509b5ca36 100644 --- a/compiler/src/prog8/compiler/ErrorReporting.kt +++ b/compiler/src/prog8/compiler/ErrorReporting.kt @@ -3,7 +3,16 @@ package prog8.compiler import prog8.ast.base.Position import prog8.parser.ParsingFailedError -class ErrorReporter { + +interface IErrorReporter { + fun err(msg: String, position: Position) + fun warn(msg: String, position: Position) + fun isEmpty(): Boolean + fun report() +} + + +internal class ErrorReporter: IErrorReporter { private enum class MessageSeverity { WARNING, ERROR @@ -13,10 +22,14 @@ class ErrorReporter { private val messages = mutableListOf() private val alreadyReportedMessages = mutableSetOf() - fun err(msg: String, position: Position) = messages.add(CompilerMessage(MessageSeverity.ERROR, msg, position)) - fun warn(msg: String, position: Position) = messages.add(CompilerMessage(MessageSeverity.WARNING, msg, position)) + override fun err(msg: String, position: Position) { + messages.add(CompilerMessage(MessageSeverity.ERROR, msg, position)) + } + override fun warn(msg: String, position: Position) { + messages.add(CompilerMessage(MessageSeverity.WARNING, msg, position)) + } - fun handle() { + override fun report() { var numErrors = 0 var numWarnings = 0 messages.forEach { @@ -40,5 +53,5 @@ class ErrorReporter { throw ParsingFailedError("There are $numErrors errors and $numWarnings warnings.") } - fun isEmpty() = messages.isEmpty() + override fun isEmpty() = messages.isEmpty() } diff --git a/compiler/src/prog8/compiler/Zeropage.kt b/compiler/src/prog8/compiler/Zeropage.kt index cbc8b278b..c92cbea7c 100644 --- a/compiler/src/prog8/compiler/Zeropage.kt +++ b/compiler/src/prog8/compiler/Zeropage.kt @@ -21,7 +21,7 @@ abstract class Zeropage(protected val options: CompilationOptions) { fun available() = if(options.zeropage==ZeropageType.DONTUSE) 0 else free.size - fun allocate(scopedname: String, datatype: DataType, position: Position?, errors: ErrorReporter): Int { + fun allocate(scopedname: String, datatype: DataType, position: Position?, errors: IErrorReporter): Int { assert(scopedname.isEmpty() || !allocations.values.any { it.first==scopedname } ) {"scopedname can't be allocated twice"} if(options.zeropage==ZeropageType.DONTUSE) diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 30a0a158a..b509aee6c 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -8,7 +8,7 @@ import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.walk.IAstVisitor import prog8.compiler.CompilationOptions -import prog8.compiler.ErrorReporter +import prog8.compiler.IErrorReporter import prog8.compiler.functions.BuiltinFunctions import prog8.compiler.functions.builtinFunctionReturnType import prog8.compiler.target.C64Target @@ -18,7 +18,7 @@ import java.io.File internal class AstChecker(private val program: Program, private val compilerOptions: CompilationOptions, - private val errors: ErrorReporter, + private val errors: IErrorReporter, private val compTarget: ICompilationTarget ) : IAstVisitor { @@ -1416,7 +1416,10 @@ internal class AstChecker(private val program: Program, } false } - else -> errors.err("cannot assign new value to variable of type $targetDatatype", position) + else -> { + errors.err("cannot assign new value to variable of type $targetDatatype", position) + false + } } if(result) diff --git a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt index 3b0d90574..f39bb6028 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt @@ -5,28 +5,28 @@ import prog8.ast.base.FatalAstException import prog8.ast.statements.Directive import prog8.compiler.BeforeAsmGenerationAstChanger import prog8.compiler.CompilationOptions -import prog8.compiler.ErrorReporter +import prog8.compiler.IErrorReporter import prog8.compiler.target.ICompilationTarget -internal fun Program.checkValid(compilerOptions: CompilationOptions, errors: ErrorReporter, compTarget: ICompilationTarget) { +internal fun Program.checkValid(compilerOptions: CompilationOptions, errors: IErrorReporter, compTarget: ICompilationTarget) { val checker = AstChecker(this, compilerOptions, errors, compTarget) checker.visit(this) } -internal fun Program.processAstBeforeAsmGeneration(errors: ErrorReporter, compTarget: ICompilationTarget) { +internal fun Program.processAstBeforeAsmGeneration(errors: IErrorReporter, compTarget: ICompilationTarget) { val fixer = BeforeAsmGenerationAstChanger(this, errors, compTarget) fixer.visit(this) fixer.applyModifications() } -internal fun Program.reorderStatements(errors: ErrorReporter) { +internal fun Program.reorderStatements(errors: IErrorReporter) { val reorder = StatementReorderer(this, errors) reorder.visit(this) reorder.applyModifications() } -internal fun Program.addTypecasts(errors: ErrorReporter) { +internal fun Program.addTypecasts(errors: IErrorReporter) { val caster = TypecastsAdder(this, errors) caster.visit(this) caster.applyModifications() @@ -37,7 +37,7 @@ internal fun Program.verifyFunctionArgTypes() { fixer.visit(this) } -internal fun Program.checkIdentifiers(errors: ErrorReporter, compTarget: ICompilationTarget) { +internal fun Program.checkIdentifiers(errors: IErrorReporter, compTarget: ICompilationTarget) { val checker2 = AstIdentifiersChecker(this, errors, compTarget) checker2.visit(this) diff --git a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt index 9c49ef407..dd25ddaed 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt @@ -10,11 +10,11 @@ import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.StringLiteralValue import prog8.ast.statements.* import prog8.ast.walk.IAstVisitor -import prog8.compiler.ErrorReporter +import prog8.compiler.IErrorReporter import prog8.compiler.functions.BuiltinFunctions import prog8.compiler.target.ICompilationTarget -internal class AstIdentifiersChecker(private val program: Program, private val errors: ErrorReporter, private val compTarget: ICompilationTarget) : IAstVisitor { +internal class AstIdentifiersChecker(private val program: Program, private val errors: IErrorReporter, private val compTarget: ICompilationTarget) : IAstVisitor { private var blocks = mutableMapOf() private fun nameError(name: String, position: Position, existing: Statement) { diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index 87d147c61..27bf40763 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -6,11 +6,11 @@ import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification -import prog8.compiler.ErrorReporter +import prog8.compiler.IErrorReporter import prog8.compiler.functions.BuiltinFunctions -internal class StatementReorderer(val program: Program, val errors: ErrorReporter) : AstWalker() { +internal class StatementReorderer(val program: Program, val errors: IErrorReporter) : AstWalker() { // Reorders the statements in a way the compiler needs. // - 'main' block must be the very first statement UNLESS it has an address set. // - library blocks are put last. diff --git a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt index 45059e826..b1c581c36 100644 --- a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt +++ b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt @@ -8,11 +8,11 @@ import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification -import prog8.compiler.ErrorReporter +import prog8.compiler.IErrorReporter import prog8.compiler.functions.BuiltinFunctions -class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalker() { +class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalker() { /* * Make sure any value assignments get the proper type casts if needed to cast them into the target variable's type. * (this includes function call arguments) diff --git a/compiler/src/prog8/compiler/target/ICompilationTarget.kt b/compiler/src/prog8/compiler/target/ICompilationTarget.kt index 33468f2b8..6e305a33b 100644 --- a/compiler/src/prog8/compiler/target/ICompilationTarget.kt +++ b/compiler/src/prog8/compiler/target/ICompilationTarget.kt @@ -8,7 +8,7 @@ import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.NumericLiteralValue import prog8.ast.statements.AssignTarget import prog8.compiler.CompilationOptions -import prog8.compiler.ErrorReporter +import prog8.compiler.IErrorReporter import prog8.compiler.Zeropage import prog8.compiler.target.c64.C64MachineDefinition import prog8.compiler.target.c64.Petscii @@ -108,7 +108,7 @@ internal object Cx16Target: ICompilationTarget { internal fun asmGeneratorFor( compTarget: ICompilationTarget, program: Program, - errors: ErrorReporter, + errors: IErrorReporter, zp: Zeropage, options: CompilationOptions, outputDir: Path diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index 985f17378..99c3e0d31 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -23,7 +23,7 @@ import kotlin.math.absoluteValue internal class AsmGen(private val program: Program, - val errors: ErrorReporter, + val errors: IErrorReporter, val zeropage: Zeropage, val options: CompilationOptions, private val compTarget: ICompilationTarget, @@ -263,7 +263,7 @@ internal class AsmGen(private val program: Program, try { val errors = ErrorReporter() val address = zeropage.allocate(fullName, variable.datatype, null, errors) - errors.handle() + errors.report() out("${variable.name} = $address\t; auto zp ${variable.datatype}") // make sure we add the var to the set of zpvars for this block allocatedZeropageVariables[fullName] = address to variable.datatype diff --git a/compiler/src/prog8/optimizer/CallGraph.kt b/compiler/src/prog8/optimizer/CallGraph.kt index b0d9b936b..d1a6b1af6 100644 --- a/compiler/src/prog8/optimizer/CallGraph.kt +++ b/compiler/src/prog8/optimizer/CallGraph.kt @@ -11,7 +11,7 @@ import prog8.ast.expressions.FunctionCall import prog8.ast.expressions.IdentifierReference import prog8.ast.statements.* import prog8.ast.walk.IAstVisitor -import prog8.compiler.ErrorReporter +import prog8.compiler.IErrorReporter import prog8.compiler.loadAsmIncludeFile private val alwaysKeepSubroutines = setOf( @@ -213,7 +213,7 @@ class CallGraph(private val program: Program) : IAstVisitor { } } - fun checkRecursiveCalls(errors: ErrorReporter) { + fun checkRecursiveCalls(errors: IErrorReporter) { val cycles = recursionCycles() if(cycles.any()) { errors.warn("Program contains recursive subroutine calls. These only works in very specific limited scenarios!", Position.DUMMY) diff --git a/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt b/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt index 6b0b14e7b..e46fd5c08 100644 --- a/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt +++ b/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt @@ -10,11 +10,11 @@ import prog8.ast.statements.ForLoop import prog8.ast.statements.VarDecl import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification -import prog8.compiler.ErrorReporter +import prog8.compiler.IErrorReporter import prog8.compiler.target.ICompilationTarget // Fix up the literal value's type to match that of the vardecl -internal class VarConstantValueTypeAdjuster(private val program: Program, private val errors: ErrorReporter) : AstWalker() { +internal class VarConstantValueTypeAdjuster(private val program: Program, private val errors: IErrorReporter) : AstWalker() { private val noModifications = emptyList() override fun after(decl: VarDecl, parent: Node): Iterable { @@ -39,7 +39,7 @@ internal class VarConstantValueTypeAdjuster(private val program: Program, privat // Replace all constant identifiers with their actual value, // and the array var initializer values and sizes. // This is needed because further constant optimizations depend on those. -internal class ConstantIdentifierReplacer(private val program: Program, private val errors: ErrorReporter, private val compTarget: ICompilationTarget) : AstWalker() { +internal class ConstantIdentifierReplacer(private val program: Program, private val errors: IErrorReporter, private val compTarget: ICompilationTarget) : AstWalker() { private val noModifications = emptyList() override fun after(identifier: IdentifierReference, parent: Node): Iterable { diff --git a/compiler/src/prog8/optimizer/Extensions.kt b/compiler/src/prog8/optimizer/Extensions.kt index dad862b76..145139c12 100644 --- a/compiler/src/prog8/optimizer/Extensions.kt +++ b/compiler/src/prog8/optimizer/Extensions.kt @@ -2,11 +2,11 @@ package prog8.optimizer import prog8.ast.IBuiltinFunctions import prog8.ast.Program -import prog8.compiler.ErrorReporter +import prog8.compiler.IErrorReporter import prog8.compiler.target.ICompilationTarget -internal fun Program.constantFold(errors: ErrorReporter, compTarget: ICompilationTarget) { +internal fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilationTarget) { val valuetypefixer = VarConstantValueTypeAdjuster(this, errors) valuetypefixer.visit(this) if(errors.isEmpty()) { @@ -40,7 +40,7 @@ internal fun Program.constantFold(errors: ErrorReporter, compTarget: ICompilatio } -internal fun Program.optimizeStatements(errors: ErrorReporter, functions: IBuiltinFunctions, compTarget: ICompilationTarget): Int { +internal fun Program.optimizeStatements(errors: IErrorReporter, functions: IBuiltinFunctions, compTarget: ICompilationTarget): Int { val optimizer = StatementOptimizer(this, errors, functions, compTarget) optimizer.visit(this) val optimizationCount = optimizer.applyModifications() diff --git a/compiler/src/prog8/optimizer/StatementOptimizer.kt b/compiler/src/prog8/optimizer/StatementOptimizer.kt index a58da52fa..475a0b479 100644 --- a/compiler/src/prog8/optimizer/StatementOptimizer.kt +++ b/compiler/src/prog8/optimizer/StatementOptimizer.kt @@ -10,13 +10,13 @@ import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstVisitor -import prog8.compiler.ErrorReporter +import prog8.compiler.IErrorReporter import prog8.compiler.target.ICompilationTarget import kotlin.math.floor internal class StatementOptimizer(private val program: Program, - private val errors: ErrorReporter, + private val errors: IErrorReporter, private val functions: IBuiltinFunctions, private val compTarget: ICompilationTarget ) : AstWalker() { diff --git a/compiler/src/prog8/optimizer/UnusedCodeRemover.kt b/compiler/src/prog8/optimizer/UnusedCodeRemover.kt index 331aafff9..f11880a72 100644 --- a/compiler/src/prog8/optimizer/UnusedCodeRemover.kt +++ b/compiler/src/prog8/optimizer/UnusedCodeRemover.kt @@ -10,11 +10,11 @@ import prog8.ast.expressions.TypecastExpression import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification -import prog8.compiler.ErrorReporter +import prog8.compiler.IErrorReporter import prog8.compiler.target.ICompilationTarget -internal class UnusedCodeRemover(private val program: Program, private val errors: ErrorReporter, private val compTarget: ICompilationTarget): AstWalker() { +internal class UnusedCodeRemover(private val program: Program, private val errors: IErrorReporter, private val compTarget: ICompilationTarget): AstWalker() { override fun before(program: Program, parent: Node): Iterable { val callgraph = CallGraph(program)