From f21dcaa6fbac41700ea3140158ad54ec7a4a0711 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 29 Oct 2021 02:42:10 +0200 Subject: [PATCH] split out the code optimizers into own project submodule --- .idea/kotlinc.xml | 6 - .idea/libraries/KotlinJavaRuntime__2_.xml | 15 +++ .idea/libraries/KotlinJavaRuntime__3_.xml | 15 +++ .idea/modules.xml | 2 + codeOptimizers/build.gradle | 66 +++++++++++ codeOptimizers/codeOptimizers.iml | 14 +++ .../src/prog8/optimizer/BinExprSplitter.kt | 6 +- .../src/prog8/optimizer/CallGraph.kt | 2 +- .../src/prog8/optimizer/ConstExprEvaluator.kt | 0 .../optimizer/ConstantFoldingOptimizer.kt | 2 +- .../optimizer/ConstantIdentifierReplacer.kt | 10 +- .../prog8/optimizer/ExpressionSimplifier.kt | 2 +- .../src/prog8/optimizer/Extensions.kt | 17 +-- .../src/prog8/optimizer/StatementOptimizer.kt | 11 +- .../src/prog8/optimizer/UnusedCodeRemover.kt | 13 ++- compiler/build.gradle | 2 + compiler/compiler.iml | 2 + .../compiler/BeforeAsmGenerationAstChanger.kt | 6 +- compiler/src/prog8/compiler/Compiler.kt | 53 +++------ compiler/src/prog8/compiler/ErrorReporting.kt | 14 +-- compiler/src/prog8/compiler/ModuleImporter.kt | 1 + .../compiler/astprocessing/AstChecker.kt | 8 +- .../compiler/astprocessing/AstExtensions.kt | 105 +----------------- .../astprocessing/AstIdentifiersChecker.kt | 4 +- .../astprocessing/StatementReorderer.kt | 2 +- .../compiler/astprocessing/TypecastsAdder.kt | 2 +- .../compiler/astprocessing/VariousCleanups.kt | 2 +- .../astprocessing/VerifyFunctionArgTypes.kt | 2 +- .../compiler/functions/BuiltinFunctions.kt | 4 +- .../src/prog8/compiler/target/C64Target.kt | 35 ++++++ .../src/prog8/compiler/target/Cx16Target.kt | 36 ++++++ .../compiler/target/IAssemblyGenerator.kt | 17 --- .../compiler/target/ICompilationTarget.kt | 89 --------------- .../target/c64/C64MachineDefinition.kt | 11 +- .../compiler/target/cbm/AssemblyProgram.kt | 8 +- .../compiler/target/cpu6502/codegen/AsmGen.kt | 1 + .../cpu6502/codegen/BuiltinFunctionsAsmGen.kt | 5 +- .../cpu6502/codegen/ExpressionsAsmGen.kt | 4 +- .../target/cpu6502/codegen/ForLoopsAsmGen.kt | 2 +- .../cpu6502/codegen/FunctionCallAsmGen.kt | 2 +- .../codegen/assignment/AsmAssignment.kt | 2 +- .../codegen/assignment/AssignmentAsmGen.kt | 2 +- .../assignment/AugmentableAssignmentAsmGen.kt | 2 +- .../target/cx16/CX16MachineDefinition.kt | 4 +- compiler/test/AsmgenTests.kt | 4 + compiler/test/ModuleImporterTests.kt | 2 +- compiler/test/TestCompilerOnExamples.kt | 2 +- compiler/test/TestCompilerOnRanges.kt | 4 +- .../TestImportedModulesOrderAndOptions.kt | 2 +- compiler/test/TestMemory.kt | 2 +- compiler/test/TestNumbers.kt | 2 +- compiler/test/ZeropageTests.kt | 1 + .../test/helpers/ErrorReporterForTests.kt | 2 +- compiler/test/helpers/compileXyz.kt | 8 +- compilerAst/src/prog8/ast/AstToplevel.kt | 4 +- .../src/prog8/ast/IBuiltinFunctions.kt | 3 +- .../prog8/ast/expressions/AstExpressions.kt | 1 + .../src/prog8/{ast => compiler}/IMemSizer.kt | 4 +- compilerAst/test/helpers/DummyFunctions.kt | 4 +- compilerAst/test/helpers/DummyMemsizer.kt | 4 +- compilerInterfaces/build.gradle | 66 +++++++++++ compilerInterfaces/compilerInterfaces.iml | 13 +++ .../prog8/compilerinterface/AstExtensions.kt | 99 +++++++++++++++++ .../compilerinterface/CompilationOptions.kt | 31 ++++++ .../compilerinterface/CompilerException.kt | 3 + .../compilerinterface/IAssemblyGenerator.kt | 15 +++ .../compilerinterface/ICompilationTarget.kt | 10 ++ .../prog8/compilerinterface/IErrorReporter.kt | 16 +++ .../compilerinterface}/IMachineDefinition.kt | 4 +- .../compilerinterface}/IStringEncoding.kt | 4 +- .../src/prog8/compilerinterface}/Zeropage.kt | 12 +- docs/source/todo.rst | 1 - httpCompilerService/build.gradle | 1 + httpCompilerService/httpCompilerService.iml | 1 + settings.gradle | 2 + 75 files changed, 575 insertions(+), 360 deletions(-) delete mode 100644 .idea/kotlinc.xml create mode 100644 .idea/libraries/KotlinJavaRuntime__2_.xml create mode 100644 .idea/libraries/KotlinJavaRuntime__3_.xml create mode 100644 codeOptimizers/build.gradle create mode 100644 codeOptimizers/codeOptimizers.iml rename {compiler => codeOptimizers}/src/prog8/optimizer/BinExprSplitter.kt (94%) rename {compiler => codeOptimizers}/src/prog8/optimizer/CallGraph.kt (99%) rename {compiler => codeOptimizers}/src/prog8/optimizer/ConstExprEvaluator.kt (100%) rename {compiler => codeOptimizers}/src/prog8/optimizer/ConstantFoldingOptimizer.kt (99%) rename {compiler => codeOptimizers}/src/prog8/optimizer/ConstantIdentifierReplacer.kt (97%) rename {compiler => codeOptimizers}/src/prog8/optimizer/ExpressionSimplifier.kt (99%) rename {compiler => codeOptimizers}/src/prog8/optimizer/Extensions.kt (75%) rename {compiler => codeOptimizers}/src/prog8/optimizer/StatementOptimizer.kt (99%) rename {compiler => codeOptimizers}/src/prog8/optimizer/UnusedCodeRemover.kt (94%) create mode 100644 compiler/src/prog8/compiler/target/C64Target.kt create mode 100644 compiler/src/prog8/compiler/target/Cx16Target.kt delete mode 100644 compiler/src/prog8/compiler/target/IAssemblyGenerator.kt delete mode 100644 compiler/src/prog8/compiler/target/ICompilationTarget.kt rename compilerAst/src/prog8/{ast => compiler}/IMemSizer.kt (78%) create mode 100644 compilerInterfaces/build.gradle create mode 100644 compilerInterfaces/compilerInterfaces.iml create mode 100644 compilerInterfaces/src/prog8/compilerinterface/AstExtensions.kt create mode 100644 compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt create mode 100644 compilerInterfaces/src/prog8/compilerinterface/CompilerException.kt create mode 100644 compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt create mode 100644 compilerInterfaces/src/prog8/compilerinterface/ICompilationTarget.kt create mode 100644 compilerInterfaces/src/prog8/compilerinterface/IErrorReporter.kt rename {compiler/src/prog8/compiler/target => compilerInterfaces/src/prog8/compilerinterface}/IMachineDefinition.kt (89%) rename {compiler/src/prog8/compiler => compilerInterfaces/src/prog8/compilerinterface}/IStringEncoding.kt (83%) rename {compiler/src/prog8/compiler => compilerInterfaces/src/prog8/compilerinterface}/Zeropage.kt (90%) diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml deleted file mode 100644 index 9b02d599e..000000000 --- a/.idea/kotlinc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/libraries/KotlinJavaRuntime__2_.xml b/.idea/libraries/KotlinJavaRuntime__2_.xml new file mode 100644 index 000000000..45205327d --- /dev/null +++ b/.idea/libraries/KotlinJavaRuntime__2_.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/KotlinJavaRuntime__3_.xml b/.idea/libraries/KotlinJavaRuntime__3_.xml new file mode 100644 index 000000000..6cfba67ce --- /dev/null +++ b/.idea/libraries/KotlinJavaRuntime__3_.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 5865164f7..0c4720f74 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,8 +2,10 @@ + + diff --git a/codeOptimizers/build.gradle b/codeOptimizers/build.gradle new file mode 100644 index 000000000..08fff1115 --- /dev/null +++ b/codeOptimizers/build.gradle @@ -0,0 +1,66 @@ + +plugins { + id 'java' + id 'application' + id "org.jetbrains.kotlin.jvm" +} + +targetCompatibility = 11 +sourceCompatibility = 11 + +repositories { + mavenLocal() + mavenCentral() + maven { url "https://kotlin.bintray.com/kotlinx" } +} + +dependencies { + implementation project(':compilerInterfaces') + implementation project(':compilerAst') + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + // implementation "org.jetbrains.kotlin:kotlin-reflect" + +} + +compileKotlin { + kotlinOptions { + jvmTarget = "11" + // verbose = true + // freeCompilerArgs += "-XXLanguage:+NewInference" + } +} + +compileTestKotlin { + kotlinOptions { + jvmTarget = "11" + } +} + +sourceSets { + main { + java { + srcDirs = ["${project.projectDir}/src"] + } + resources { + srcDirs = ["${project.projectDir}/res"] + } + } + test { + java { + srcDirs = ["${project.projectDir}/test"] + } + } +} + +test { + // Enable JUnit 5 (Gradle 4.6+). + useJUnitPlatform() + + // Always run tests, even when nothing changed. + dependsOn 'cleanTest' + + // Show test results. + testLogging { + events "skipped", "failed" + } +} diff --git a/codeOptimizers/codeOptimizers.iml b/codeOptimizers/codeOptimizers.iml new file mode 100644 index 000000000..aadd52214 --- /dev/null +++ b/codeOptimizers/codeOptimizers.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/compiler/src/prog8/optimizer/BinExprSplitter.kt b/codeOptimizers/src/prog8/optimizer/BinExprSplitter.kt similarity index 94% rename from compiler/src/prog8/optimizer/BinExprSplitter.kt rename to codeOptimizers/src/prog8/optimizer/BinExprSplitter.kt index 0eb519797..8faec57fa 100644 --- a/compiler/src/prog8/optimizer/BinExprSplitter.kt +++ b/codeOptimizers/src/prog8/optimizer/BinExprSplitter.kt @@ -9,11 +9,11 @@ import prog8.ast.statements.AssignTarget import prog8.ast.statements.Assignment import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification -import prog8.compiler.astprocessing.isInRegularRAMof -import prog8.compiler.target.ICompilationTarget +import prog8.compilerinterface.ICompilationTarget +import prog8.compilerinterface.isInRegularRAMof -internal class BinExprSplitter(private val program: Program, private val compTarget: ICompilationTarget) : AstWalker() { +class BinExprSplitter(private val program: Program, private val compTarget: ICompilationTarget) : AstWalker() { // override fun after(decl: VarDecl, parent: Node): Iterable { // TODO somehow if we do this, the resulting code for some programs (cube3d.p8) gets hundreds of bytes larger...: diff --git a/compiler/src/prog8/optimizer/CallGraph.kt b/codeOptimizers/src/prog8/optimizer/CallGraph.kt similarity index 99% rename from compiler/src/prog8/optimizer/CallGraph.kt rename to codeOptimizers/src/prog8/optimizer/CallGraph.kt index f19197250..7786b5ad7 100644 --- a/compiler/src/prog8/optimizer/CallGraph.kt +++ b/codeOptimizers/src/prog8/optimizer/CallGraph.kt @@ -10,7 +10,7 @@ import prog8.ast.expressions.FunctionCall import prog8.ast.expressions.IdentifierReference import prog8.ast.statements.* import prog8.ast.walk.IAstVisitor -import prog8.compiler.IErrorReporter +import prog8.compilerinterface.IErrorReporter class CallGraph(private val program: Program) : IAstVisitor { diff --git a/compiler/src/prog8/optimizer/ConstExprEvaluator.kt b/codeOptimizers/src/prog8/optimizer/ConstExprEvaluator.kt similarity index 100% rename from compiler/src/prog8/optimizer/ConstExprEvaluator.kt rename to codeOptimizers/src/prog8/optimizer/ConstExprEvaluator.kt diff --git a/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt b/codeOptimizers/src/prog8/optimizer/ConstantFoldingOptimizer.kt similarity index 99% rename from compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt rename to codeOptimizers/src/prog8/optimizer/ConstantFoldingOptimizer.kt index 605672bd0..608844607 100644 --- a/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt +++ b/codeOptimizers/src/prog8/optimizer/ConstantFoldingOptimizer.kt @@ -12,7 +12,7 @@ import prog8.ast.walk.IAstModification import kotlin.math.pow -internal class ConstantFoldingOptimizer(private val program: Program) : AstWalker() { +class ConstantFoldingOptimizer(private val program: Program) : AstWalker() { override fun before(memread: DirectMemoryRead, parent: Node): Iterable { // @( &thing ) --> thing diff --git a/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt similarity index 97% rename from compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt rename to codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt index 39fddf54a..107447170 100644 --- a/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt +++ b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt @@ -7,14 +7,14 @@ import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification -import prog8.compiler.IErrorReporter -import prog8.compiler.astprocessing.size -import prog8.compiler.astprocessing.toConstantIntegerRange -import prog8.compiler.target.ICompilationTarget +import prog8.compilerinterface.ICompilationTarget +import prog8.compilerinterface.IErrorReporter +import prog8.compilerinterface.size +import prog8.compilerinterface.toConstantIntegerRange // Fix up the literal value's type to match that of the vardecl // (also check range literal operands types before they get expanded into arrays for instance) -internal class VarConstantValueTypeAdjuster(private val program: Program, private val errors: IErrorReporter) : AstWalker() { +class VarConstantValueTypeAdjuster(private val program: Program, private val errors: IErrorReporter) : AstWalker() { override fun after(decl: VarDecl, parent: Node): Iterable { diff --git a/compiler/src/prog8/optimizer/ExpressionSimplifier.kt b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt similarity index 99% rename from compiler/src/prog8/optimizer/ExpressionSimplifier.kt rename to codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt index 58eba0492..608a6398d 100644 --- a/compiler/src/prog8/optimizer/ExpressionSimplifier.kt +++ b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt @@ -22,7 +22,7 @@ import kotlin.math.pow */ -internal class ExpressionSimplifier(private val program: Program) : AstWalker() { +class ExpressionSimplifier(private val program: Program) : AstWalker() { private val powersOfTwo = (1..16).map { (2.0).pow(it) }.toSet() private val negativePowersOfTwo = powersOfTwo.map { -it }.toSet() diff --git a/compiler/src/prog8/optimizer/Extensions.kt b/codeOptimizers/src/prog8/optimizer/Extensions.kt similarity index 75% rename from compiler/src/prog8/optimizer/Extensions.kt rename to codeOptimizers/src/prog8/optimizer/Extensions.kt index b69be66a7..430b7ab86 100644 --- a/compiler/src/prog8/optimizer/Extensions.kt +++ b/codeOptimizers/src/prog8/optimizer/Extensions.kt @@ -2,11 +2,11 @@ package prog8.optimizer import prog8.ast.IBuiltinFunctions import prog8.ast.Program -import prog8.compiler.IErrorReporter -import prog8.compiler.target.ICompilationTarget +import prog8.compilerinterface.ICompilationTarget +import prog8.compilerinterface.IErrorReporter -internal fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilationTarget) { +fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilationTarget) { val valuetypefixer = VarConstantValueTypeAdjuster(this, errors) valuetypefixer.visit(this) if(errors.noErrors()) { @@ -40,9 +40,10 @@ internal fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilati } -internal fun Program.optimizeStatements(errors: IErrorReporter, - functions: IBuiltinFunctions, - compTarget: ICompilationTarget): Int { +fun Program.optimizeStatements(errors: IErrorReporter, + functions: IBuiltinFunctions, + compTarget: ICompilationTarget +): Int { val optimizer = StatementOptimizer(this, errors, functions, compTarget) optimizer.visit(this) val optimizationCount = optimizer.applyModifications() @@ -52,13 +53,13 @@ internal fun Program.optimizeStatements(errors: IErrorReporter, return optimizationCount } -internal fun Program.simplifyExpressions() : Int { +fun Program.simplifyExpressions() : Int { val opti = ExpressionSimplifier(this) opti.visit(this) return opti.applyModifications() } -internal fun Program.splitBinaryExpressions(compTarget: ICompilationTarget) : Int { +fun Program.splitBinaryExpressions(compTarget: ICompilationTarget) : Int { val opti = BinExprSplitter(this, compTarget) opti.visit(this) return opti.applyModifications() diff --git a/compiler/src/prog8/optimizer/StatementOptimizer.kt b/codeOptimizers/src/prog8/optimizer/StatementOptimizer.kt similarity index 99% rename from compiler/src/prog8/optimizer/StatementOptimizer.kt rename to codeOptimizers/src/prog8/optimizer/StatementOptimizer.kt index 92561bbb9..6f7d89402 100644 --- a/compiler/src/prog8/optimizer/StatementOptimizer.kt +++ b/codeOptimizers/src/prog8/optimizer/StatementOptimizer.kt @@ -10,18 +10,19 @@ import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstVisitor -import prog8.compiler.IErrorReporter -import prog8.compiler.astprocessing.size -import prog8.compiler.target.ICompilationTarget +import prog8.compilerinterface.ICompilationTarget +import prog8.compilerinterface.IErrorReporter +import prog8.compilerinterface.size import kotlin.math.floor internal const val retvarName = "prog8_retval" -internal class StatementOptimizer(private val program: Program, +class StatementOptimizer(private val program: Program, private val errors: IErrorReporter, private val functions: IBuiltinFunctions, - private val compTarget: ICompilationTarget) : AstWalker() { + private val compTarget: ICompilationTarget +) : AstWalker() { private val subsThatNeedReturnVariable = mutableSetOf>() diff --git a/compiler/src/prog8/optimizer/UnusedCodeRemover.kt b/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt similarity index 94% rename from compiler/src/prog8/optimizer/UnusedCodeRemover.kt rename to codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt index 4e92eef22..2845b7bb8 100644 --- a/compiler/src/prog8/optimizer/UnusedCodeRemover.kt +++ b/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt @@ -9,14 +9,15 @@ import prog8.ast.expressions.TypecastExpression import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification -import prog8.compiler.IErrorReporter -import prog8.compiler.astprocessing.isInRegularRAMof -import prog8.compiler.target.ICompilationTarget +import prog8.compilerinterface.ICompilationTarget +import prog8.compilerinterface.IErrorReporter +import prog8.compilerinterface.isInRegularRAMof -internal class UnusedCodeRemover(private val program: Program, - private val errors: IErrorReporter, - private val compTarget: ICompilationTarget): AstWalker() { +class UnusedCodeRemover(private val program: Program, + private val errors: IErrorReporter, + private val compTarget: ICompilationTarget +): AstWalker() { private val callgraph = CallGraph(program) diff --git a/compiler/build.gradle b/compiler/build.gradle index b4afc5714..b4651dd9f 100644 --- a/compiler/build.gradle +++ b/compiler/build.gradle @@ -18,6 +18,8 @@ repositories { def prog8version = rootProject.file('compiler/res/version.txt').text.trim() dependencies { + implementation project(':compilerInterfaces') + implementation project(':codeOptimizers') implementation project(':compilerAst') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" // implementation "org.jetbrains.kotlin:kotlin-reflect" diff --git a/compiler/compiler.iml b/compiler/compiler.iml index 3bfbcdad9..289d7a8ea 100644 --- a/compiler/compiler.iml +++ b/compiler/compiler.iml @@ -22,5 +22,7 @@ + + \ No newline at end of file diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index 17849da75..8c0d0d51a 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -10,9 +10,11 @@ import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstVisitor -import prog8.compiler.astprocessing.isInRegularRAMof import prog8.compiler.astprocessing.isSubroutineParameter -import prog8.compiler.target.ICompilationTarget +import prog8.compilerinterface.CompilerException +import prog8.compilerinterface.ICompilationTarget +import prog8.compilerinterface.IErrorReporter +import prog8.compilerinterface.isInRegularRAMof internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: IErrorReporter, private val compTarget: ICompilationTarget) : AstWalker() { diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 0195577f8..7394618ea 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -3,7 +3,6 @@ package prog8.compiler import com.github.michaelbull.result.* import prog8.ast.AstToSourceTextConverter import prog8.ast.IBuiltinFunctions -import prog8.ast.IMemSizer import prog8.ast.Program import prog8.ast.base.AstException import prog8.ast.base.Position @@ -14,8 +13,8 @@ import prog8.compiler.astprocessing.* import prog8.compiler.functions.* import prog8.compiler.target.C64Target import prog8.compiler.target.Cx16Target -import prog8.compiler.target.ICompilationTarget -import prog8.compiler.target.asmGeneratorFor +import prog8.compiler.target.cpu6502.codegen.AsmGen +import prog8.compilerinterface.* import prog8.optimizer.* import prog8.parser.ParseError import prog8.parser.ParsingFailedError @@ -29,38 +28,6 @@ import kotlin.io.path.nameWithoutExtension import kotlin.system.measureTimeMillis -enum class OutputType { - RAW, - PRG -} - -enum class LauncherType { - BASIC, - NONE -} - -enum class ZeropageType { - BASICSAFE, - FLOATSAFE, - KERNALSAFE, - FULL, - DONTUSE -} - -data class CompilationOptions(val output: OutputType, - val launcher: LauncherType, - val zeropage: ZeropageType, - val zpReserved: List, - val floats: Boolean, - val noSysInit: Boolean, - val compTarget: ICompilationTarget) { - var slowCodegenWarnings = false - var optimize = false -} - - -class CompilerException(message: String?) : Exception(message) - class CompilationResult(val success: Boolean, val programAst: Program, val programName: String, @@ -347,7 +314,8 @@ private sealed class WriteAssemblyResult { private fun writeAssembly(programAst: Program, errors: IErrorReporter, outputDir: Path, - compilerOptions: CompilationOptions): WriteAssemblyResult { + compilerOptions: CompilationOptions +): WriteAssemblyResult { // asm generation directly from the Ast programAst.processAstBeforeAsmGeneration(errors, compilerOptions.compTarget) errors.report() @@ -396,3 +364,16 @@ internal fun loadAsmIncludeFile(filename: String, source: SourceCode): Result0) - throw ParsingFailedError("There are $numErrors errors and $numWarnings warnings.") - } -} +import prog8.compilerinterface.IErrorReporter internal class ErrorReporter: IErrorReporter { diff --git a/compiler/src/prog8/compiler/ModuleImporter.kt b/compiler/src/prog8/compiler/ModuleImporter.kt index 8ebbb7c48..0015988ec 100644 --- a/compiler/src/prog8/compiler/ModuleImporter.kt +++ b/compiler/src/prog8/compiler/ModuleImporter.kt @@ -7,6 +7,7 @@ import prog8.ast.base.Position import prog8.ast.base.SyntaxError import prog8.ast.statements.Directive import prog8.ast.statements.DirectiveArg +import prog8.compilerinterface.IErrorReporter import prog8.parser.Prog8Parser import prog8.parser.SourceCode import java.io.File diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 2fadeef69..dface238f 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -8,12 +8,12 @@ import prog8.ast.base.* import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.walk.IAstVisitor -import prog8.compiler.CompilationOptions -import prog8.compiler.IErrorReporter -import prog8.compiler.ZeropageType +import prog8.compilerinterface.CompilationOptions +import prog8.compilerinterface.ICompilationTarget +import prog8.compilerinterface.IErrorReporter +import prog8.compilerinterface.ZeropageType import prog8.compiler.functions.BuiltinFunctions import prog8.compiler.functions.builtinFunctionReturnType -import prog8.compiler.target.ICompilationTarget import java.io.CharConversionException import java.io.File import java.util.* diff --git a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt index 745bb393d..2700bf5c8 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt @@ -3,65 +3,16 @@ package prog8.compiler.astprocessing import prog8.ast.Node import prog8.ast.Program import prog8.ast.base.DataType -import prog8.ast.base.VarDeclType import prog8.ast.expressions.* -import prog8.ast.statements.AssignTarget import prog8.ast.statements.Directive import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification +import prog8.compiler.* import prog8.compiler.BeforeAsmGenerationAstChanger -import prog8.compiler.CompilationOptions -import prog8.compiler.IErrorReporter -import prog8.compiler.IStringEncoding -import prog8.compiler.target.ICompilationTarget -import prog8.compiler.target.IMachineDefinition -import kotlin.math.abs - - -fun RangeExpr.size(encoding: IStringEncoding): Int? { - val fromLv = (from as? NumericLiteralValue) - val toLv = (to as? NumericLiteralValue) - if(fromLv==null || toLv==null) - return null - return toConstantIntegerRange(encoding)?.count() -} - -fun RangeExpr.toConstantIntegerRange(encoding: IStringEncoding): IntProgression? { - val fromVal: Int - val toVal: Int - val fromString = from as? StringLiteralValue - val toString = to as? StringLiteralValue - if(fromString!=null && toString!=null ) { - // string range -> int range over character values - fromVal = encoding.encodeString(fromString.value, fromString.altEncoding)[0].toInt() - toVal = encoding.encodeString(toString.value, fromString.altEncoding)[0].toInt() - } else { - val fromLv = from as? NumericLiteralValue - val toLv = to as? NumericLiteralValue - if(fromLv==null || toLv==null) - return null // non-constant range - // integer range - fromVal = fromLv.number.toInt() - toVal = toLv.number.toInt() - } - val stepVal = (step as? NumericLiteralValue)?.number?.toInt() ?: 1 - return makeRange(fromVal, toVal, stepVal) -} - -private fun makeRange(fromVal: Int, toVal: Int, stepVal: Int): IntProgression { - return when { - fromVal <= toVal -> when { - stepVal <= 0 -> IntRange.EMPTY - stepVal == 1 -> fromVal..toVal - else -> fromVal..toVal step stepVal - } - else -> when { - stepVal >= 0 -> IntRange.EMPTY - stepVal == -1 -> fromVal downTo toVal - else -> fromVal downTo toVal step abs(stepVal) - } - } -} +import prog8.compilerinterface.CompilationOptions +import prog8.compilerinterface.ICompilationTarget +import prog8.compilerinterface.IErrorReporter +import prog8.compilerinterface.IStringEncoding internal fun Program.checkValid(compilerOptions: CompilationOptions, errors: IErrorReporter, compTarget: ICompilationTarget) { @@ -143,7 +94,6 @@ internal fun Program.variousCleanups(program: Program, errors: IErrorReporter) { process.applyModifications() } - internal fun Program.moveMainAndStartToFirst() { // the module containing the program entrypoint is moved to the first in the sequence. // the "main" block containing the entrypoint is moved to the top in there, @@ -174,51 +124,6 @@ internal fun Program.moveMainAndStartToFirst() { } } -internal fun AssignTarget.isInRegularRAMof(machine: IMachineDefinition): Boolean { - val memAddr = memoryAddress - val arrayIdx = arrayindexed - val ident = identifier - when { - memAddr != null -> { - return when (memAddr.addressExpression) { - is NumericLiteralValue -> { - machine.isRegularRAMaddress((memAddr.addressExpression as NumericLiteralValue).number.toInt()) - } - is IdentifierReference -> { - val program = definingModule.program - val decl = (memAddr.addressExpression as IdentifierReference).targetVarDecl(program) - if ((decl?.type == VarDeclType.VAR || decl?.type == VarDeclType.CONST) && decl.value is NumericLiteralValue) - machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt()) - else - false - } - else -> false - } - } - arrayIdx != null -> { - val program = definingModule.program - val targetStmt = arrayIdx.arrayvar.targetVarDecl(program) - return if (targetStmt?.type == VarDeclType.MEMORY) { - val addr = targetStmt.value as? NumericLiteralValue - if (addr != null) - machine.isRegularRAMaddress(addr.number.toInt()) - else - false - } else true - } - ident != null -> { - val program = definingModule.program - val decl = ident.targetVarDecl(program)!! - return if (decl.type == VarDeclType.MEMORY && decl.value is NumericLiteralValue) - machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt()) - else - true - } - else -> return true - } -} - - internal fun IdentifierReference.isSubroutineParameter(program: Program): Boolean { val vardecl = this.targetVarDecl(program) if(vardecl!=null && vardecl.autogeneratedDontRemove) { diff --git a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt index bbb49c31f..cbabaaa96 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt @@ -4,9 +4,9 @@ import prog8.ast.base.Position import prog8.ast.expressions.StringLiteralValue import prog8.ast.statements.* import prog8.ast.walk.IAstVisitor -import prog8.compiler.IErrorReporter +import prog8.compilerinterface.ICompilationTarget +import prog8.compilerinterface.IErrorReporter import prog8.compiler.functions.BuiltinFunctions -import prog8.compiler.target.ICompilationTarget internal class AstIdentifiersChecker(private val errors: IErrorReporter, private val compTarget: ICompilationTarget) : IAstVisitor { private var blocks = mutableMapOf() diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index bd875846f..b4b9892ec 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -10,7 +10,7 @@ import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification -import prog8.compiler.IErrorReporter +import prog8.compilerinterface.IErrorReporter import prog8.compiler.functions.BuiltinFunctions diff --git a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt index 8bd0115b4..3d0529d3e 100644 --- a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt +++ b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt @@ -8,7 +8,7 @@ import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification -import prog8.compiler.IErrorReporter +import prog8.compilerinterface.IErrorReporter import prog8.compiler.functions.BuiltinFunctions diff --git a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt index ec501d7cf..2ffd8a867 100644 --- a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt +++ b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt @@ -10,7 +10,7 @@ import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification -import prog8.compiler.IErrorReporter +import prog8.compilerinterface.IErrorReporter internal class VariousCleanups(val program: Program, val errors: IErrorReporter): AstWalker() { diff --git a/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt b/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt index e5d74ee10..58bbf09d9 100644 --- a/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt +++ b/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt @@ -8,7 +8,7 @@ import prog8.ast.expressions.FunctionCall import prog8.ast.expressions.TypecastExpression import prog8.ast.statements.* import prog8.ast.walk.IAstVisitor -import prog8.compiler.CompilerException +import prog8.compilerinterface.CompilerException import prog8.compiler.functions.BuiltinFunctions class VerifyFunctionArgTypes(val program: Program) : IAstVisitor { diff --git a/compiler/src/prog8/compiler/functions/BuiltinFunctions.kt b/compiler/src/prog8/compiler/functions/BuiltinFunctions.kt index 3e0b28444..981eec3d6 100644 --- a/compiler/src/prog8/compiler/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/compiler/functions/BuiltinFunctions.kt @@ -1,11 +1,11 @@ package prog8.compiler.functions -import prog8.ast.IMemSizer import prog8.ast.Program import prog8.ast.base.* import prog8.ast.expressions.* import prog8.ast.statements.VarDecl -import prog8.compiler.CompilerException +import prog8.compilerinterface.CompilerException +import prog8.compiler.IMemSizer import kotlin.math.* diff --git a/compiler/src/prog8/compiler/target/C64Target.kt b/compiler/src/prog8/compiler/target/C64Target.kt new file mode 100644 index 000000000..73109ded2 --- /dev/null +++ b/compiler/src/prog8/compiler/target/C64Target.kt @@ -0,0 +1,35 @@ +package prog8.compiler.target + +import com.github.michaelbull.result.fold +import prog8.ast.base.ByteDatatypes +import prog8.ast.base.DataType +import prog8.ast.base.PassByReferenceDatatypes +import prog8.ast.base.WordDatatypes +import prog8.compiler.target.c64.C64MachineDefinition +import prog8.compiler.target.cbm.Petscii +import prog8.compilerinterface.* + + +internal object C64Target: ICompilationTarget { + override val name = "c64" + override val machine = C64MachineDefinition + override fun encodeString(str: String, altEncoding: Boolean): List { + val coded = if (altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true) + return coded.fold( + failure = { throw it }, + success = { it } + ) + } + override fun decodeString(bytes: List, altEncoding: Boolean) = + if (altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true) + + override fun memorySize(dt: DataType): Int { + return when(dt) { + in ByteDatatypes -> 1 + in WordDatatypes -> 2 + DataType.FLOAT -> machine.FLOAT_MEM_SIZE + in PassByReferenceDatatypes -> machine.POINTER_MEM_SIZE + else -> -9999999 + } + } +} diff --git a/compiler/src/prog8/compiler/target/Cx16Target.kt b/compiler/src/prog8/compiler/target/Cx16Target.kt new file mode 100644 index 000000000..63ae67582 --- /dev/null +++ b/compiler/src/prog8/compiler/target/Cx16Target.kt @@ -0,0 +1,36 @@ +package prog8.compiler.target + +import com.github.michaelbull.result.fold +import prog8.ast.base.ByteDatatypes +import prog8.ast.base.DataType +import prog8.ast.base.PassByReferenceDatatypes +import prog8.ast.base.WordDatatypes +import prog8.compiler.target.cbm.Petscii +import prog8.compiler.target.cx16.CX16MachineDefinition +import prog8.compilerinterface.* + + +internal object Cx16Target: ICompilationTarget { + override val name = "cx16" + override val machine = CX16MachineDefinition + override fun encodeString(str: String, altEncoding: Boolean): List { + val coded= if (altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true) + return coded.fold( + failure = { throw it }, + success = { it } + ) + } + override fun decodeString(bytes: List, altEncoding: Boolean) = + if (altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true) + + override fun memorySize(dt: DataType): Int { + return when(dt) { + in ByteDatatypes -> 1 + in WordDatatypes -> 2 + DataType.FLOAT -> machine.FLOAT_MEM_SIZE + in PassByReferenceDatatypes -> machine.POINTER_MEM_SIZE + else -> -9999999 + } + } +} + diff --git a/compiler/src/prog8/compiler/target/IAssemblyGenerator.kt b/compiler/src/prog8/compiler/target/IAssemblyGenerator.kt deleted file mode 100644 index d184d05ca..000000000 --- a/compiler/src/prog8/compiler/target/IAssemblyGenerator.kt +++ /dev/null @@ -1,17 +0,0 @@ -package prog8.compiler.target - -import prog8.compiler.CompilationOptions - -internal interface IAssemblyGenerator { - fun compileToAssembly(): IAssemblyProgram -} - -internal const val generatedLabelPrefix = "_prog8_label_" -internal const val subroutineFloatEvalResultVar1 = "_prog8_float_eval_result1" -internal const val subroutineFloatEvalResultVar2 = "_prog8_float_eval_result2" - -internal interface IAssemblyProgram { - val valid: Boolean - val name: String - fun assemble(options: CompilationOptions): Int -} diff --git a/compiler/src/prog8/compiler/target/ICompilationTarget.kt b/compiler/src/prog8/compiler/target/ICompilationTarget.kt deleted file mode 100644 index ab1eb474e..000000000 --- a/compiler/src/prog8/compiler/target/ICompilationTarget.kt +++ /dev/null @@ -1,89 +0,0 @@ -package prog8.compiler.target - -import com.github.michaelbull.result.fold -import prog8.ast.IMemSizer -import prog8.ast.Program -import prog8.ast.base.ByteDatatypes -import prog8.ast.base.DataType -import prog8.ast.base.PassByReferenceDatatypes -import prog8.ast.base.WordDatatypes -import prog8.compiler.CompilationOptions -import prog8.compiler.IErrorReporter -import prog8.compiler.IStringEncoding -import prog8.compiler.Zeropage -import prog8.compiler.target.c64.C64MachineDefinition -import prog8.compiler.target.cbm.Petscii -import prog8.compiler.target.cpu6502.codegen.AsmGen -import prog8.compiler.target.cx16.CX16MachineDefinition -import java.nio.file.Path - - -interface ICompilationTarget: IStringEncoding, IMemSizer { - val name: String - val machine: IMachineDefinition - override fun encodeString(str: String, altEncoding: Boolean): List - override fun decodeString(bytes: List, altEncoding: Boolean): String -} - - -internal object C64Target: ICompilationTarget { - override val name = "c64" - override val machine = C64MachineDefinition - override fun encodeString(str: String, altEncoding: Boolean): List { - val coded = if (altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true) - return coded.fold( - failure = { throw it }, - success = { it } - ) - } - override fun decodeString(bytes: List, altEncoding: Boolean) = - if (altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true) - - override fun memorySize(dt: DataType): Int { - return when(dt) { - in ByteDatatypes -> 1 - in WordDatatypes -> 2 - DataType.FLOAT -> machine.FLOAT_MEM_SIZE - in PassByReferenceDatatypes -> machine.POINTER_MEM_SIZE - else -> -9999999 - } - } -} - -internal object Cx16Target: ICompilationTarget { - override val name = "cx16" - override val machine = CX16MachineDefinition - override fun encodeString(str: String, altEncoding: Boolean): List { - val coded= if (altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true) - return coded.fold( - failure = { throw it }, - success = { it } - ) - } - override fun decodeString(bytes: List, altEncoding: Boolean) = - if (altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true) - - override fun memorySize(dt: DataType): Int { - return when(dt) { - in ByteDatatypes -> 1 - in WordDatatypes -> 2 - DataType.FLOAT -> machine.FLOAT_MEM_SIZE - in PassByReferenceDatatypes -> machine.POINTER_MEM_SIZE - else -> -9999999 - } - } -} - - -internal fun asmGeneratorFor( - compTarget: ICompilationTarget, - program: Program, - errors: IErrorReporter, - zp: Zeropage, - options: CompilationOptions, - outputDir: Path -): IAssemblyGenerator -{ - // at the moment we only have one code generation backend (for 6502 and 65c02) - return AsmGen(program, errors, zp, options, compTarget, outputDir) -} diff --git a/compiler/src/prog8/compiler/target/c64/C64MachineDefinition.kt b/compiler/src/prog8/compiler/target/c64/C64MachineDefinition.kt index 2588e0b22..8c74f20c5 100644 --- a/compiler/src/prog8/compiler/target/c64/C64MachineDefinition.kt +++ b/compiler/src/prog8/compiler/target/c64/C64MachineDefinition.kt @@ -1,10 +1,8 @@ package prog8.compiler.target.c64 import prog8.compiler.* -import prog8.compiler.target.CpuType -import prog8.compiler.target.IMachineDefinition -import prog8.compiler.target.IMachineFloat import prog8.compiler.target.cbm.viceMonListPostfix +import prog8.compilerinterface.* import java.io.IOException import java.nio.file.Path import kotlin.math.absoluteValue @@ -30,7 +28,7 @@ internal object C64MachineDefinition: IMachineDefinition { override fun getFloat(num: Number) = Mflpt5.fromNumber(num) - override fun importLibs(compilerOptions: CompilationOptions,compilationTargetName: String): List { + override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List { return if (compilerOptions.launcher == LauncherType.BASIC || compilerOptions.output == OutputType.PRG) listOf("syslib") else @@ -125,7 +123,7 @@ internal object C64MachineDefinition: IMachineDefinition { )) } - if(options.zeropage!=ZeropageType.DONTUSE) { + if(options.zeropage!= ZeropageType.DONTUSE) { // add the free Zp addresses // these are valid for the C-64 but allow BASIC to keep running fully *as long as you don't use tape I/O* free.addAll(listOf(0x04, 0x05, 0x06, 0x0a, 0x0e, @@ -146,7 +144,8 @@ internal object C64MachineDefinition: IMachineDefinition { } } - internal data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, val b4: Short): IMachineFloat { + internal data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, val b4: Short): + IMachineFloat { companion object { val zero = Mflpt5(0, 0, 0, 0, 0) diff --git a/compiler/src/prog8/compiler/target/cbm/AssemblyProgram.kt b/compiler/src/prog8/compiler/target/cbm/AssemblyProgram.kt index 30bba8159..5f2ba9ef0 100644 --- a/compiler/src/prog8/compiler/target/cbm/AssemblyProgram.kt +++ b/compiler/src/prog8/compiler/target/cbm/AssemblyProgram.kt @@ -1,9 +1,9 @@ package prog8.compiler.target.cbm -import prog8.compiler.CompilationOptions -import prog8.compiler.OutputType -import prog8.compiler.target.IAssemblyProgram -import prog8.compiler.target.generatedLabelPrefix +import prog8.compilerinterface.CompilationOptions +import prog8.compilerinterface.IAssemblyProgram +import prog8.compilerinterface.OutputType +import prog8.compilerinterface.generatedLabelPrefix import java.nio.file.Path diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt index d973919b0..33ceb7a2e 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt @@ -13,6 +13,7 @@ import prog8.compiler.target.* import prog8.compiler.target.cbm.AssemblyProgram import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment import prog8.compiler.target.cpu6502.codegen.assignment.AssignmentAsmGen +import prog8.compilerinterface.* import prog8.optimizer.CallGraph import prog8.parser.SourceCode import java.nio.file.Path diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt index 8a4c2d210..502d07aae 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt @@ -11,11 +11,11 @@ import prog8.ast.statements.FunctionCallStatement import prog8.ast.statements.Subroutine import prog8.ast.toHex import prog8.compiler.AssemblyError +import prog8.compilerinterface.CpuType import prog8.compiler.functions.FSignature -import prog8.compiler.target.CpuType import prog8.compiler.target.Cx16Target import prog8.compiler.target.cpu6502.codegen.assignment.* -import prog8.compiler.target.subroutineFloatEvalResultVar2 +import prog8.compilerinterface.subroutineFloatEvalResultVar2 internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val assignAsmGen: AssignmentAsmGen) { @@ -785,7 +785,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val && (firstOffset is NumericLiteralValue || firstOffset is IdentifierReference || firstOffset is TypecastExpression) && (secondOffset is NumericLiteralValue || secondOffset is IdentifierReference || secondOffset is TypecastExpression) ) { - val pointerVar = firstExpr.left as IdentifierReference if(firstOffset is NumericLiteralValue && secondOffset is NumericLiteralValue) { if(firstOffset!=secondOffset) { swapArrayValues( diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt index c67ef0fbd..532d7ebb4 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt @@ -8,9 +8,9 @@ import prog8.ast.statements.BuiltinFunctionStatementPlaceholder import prog8.ast.statements.Subroutine import prog8.ast.toHex import prog8.compiler.AssemblyError +import prog8.compilerinterface.CpuType import prog8.compiler.functions.BuiltinFunctions -import prog8.compiler.target.CpuType -import prog8.compiler.target.subroutineFloatEvalResultVar1 +import prog8.compilerinterface.subroutineFloatEvalResultVar1 import kotlin.math.absoluteValue internal class ExpressionsAsmGen(private val program: Program, private val asmgen: AsmGen) { diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt index b35e3656c..4f5acdf66 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt @@ -9,7 +9,7 @@ import prog8.ast.expressions.RangeExpr import prog8.ast.statements.ForLoop import prog8.ast.toHex import prog8.compiler.AssemblyError -import prog8.compiler.astprocessing.toConstantIntegerRange +import prog8.compilerinterface.toConstantIntegerRange import kotlin.math.absoluteValue internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) { diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt index e5562d199..8157d9598 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt @@ -10,7 +10,7 @@ import prog8.ast.statements.RegisterOrStatusflag import prog8.ast.statements.Subroutine import prog8.ast.statements.SubroutineParameter import prog8.compiler.AssemblyError -import prog8.compiler.target.CpuType +import prog8.compilerinterface.CpuType import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignSource import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt index 45f06d49c..d120b750e 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt @@ -1,11 +1,11 @@ package prog8.compiler.target.cpu6502.codegen.assignment -import prog8.ast.IMemSizer import prog8.ast.Program import prog8.ast.base.* import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.compiler.AssemblyError +import prog8.compiler.IMemSizer import prog8.compiler.target.cpu6502.codegen.AsmGen diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt index ffe867104..848917aaf 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt @@ -6,9 +6,9 @@ import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.toHex import prog8.compiler.AssemblyError +import prog8.compilerinterface.CpuType import prog8.compiler.functions.BuiltinFunctions import prog8.compiler.functions.builtinFunctionReturnType -import prog8.compiler.target.CpuType import prog8.compiler.target.cpu6502.codegen.AsmGen import prog8.compiler.target.cpu6502.codegen.ExpressionsAsmGen diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt index c034afeab..4c4ef447e 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -6,7 +6,7 @@ import prog8.ast.expressions.* import prog8.ast.statements.Subroutine import prog8.ast.toHex import prog8.compiler.AssemblyError -import prog8.compiler.target.CpuType +import prog8.compilerinterface.CpuType import prog8.compiler.target.cpu6502.codegen.AsmGen import prog8.compiler.target.cpu6502.codegen.ExpressionsAsmGen diff --git a/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt b/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt index d0e45eb62..99f89ad9d 100644 --- a/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt +++ b/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt @@ -1,13 +1,13 @@ package prog8.compiler.target.cx16 import prog8.compiler.* -import prog8.compiler.target.CpuType -import prog8.compiler.target.IMachineDefinition import prog8.compiler.target.c64.C64MachineDefinition import prog8.compiler.target.cbm.viceMonListPostfix +import prog8.compilerinterface.* import java.io.IOException import java.nio.file.Path + internal object CX16MachineDefinition: IMachineDefinition { override val cpu = CpuType.CPU65c02 diff --git a/compiler/test/AsmgenTests.kt b/compiler/test/AsmgenTests.kt index 61ee2676d..ffed6a188 100644 --- a/compiler/test/AsmgenTests.kt +++ b/compiler/test/AsmgenTests.kt @@ -18,6 +18,10 @@ import prog8.compiler.* import prog8.compiler.target.C64Target import prog8.compiler.target.c64.C64MachineDefinition import prog8.compiler.target.cpu6502.codegen.AsmGen +import prog8.compilerinterface.CompilationOptions +import prog8.compilerinterface.LauncherType +import prog8.compilerinterface.OutputType +import prog8.compilerinterface.ZeropageType import prog8.parser.SourceCode import prog8tests.helpers.DummyFunctions import prog8tests.helpers.DummyMemsizer diff --git a/compiler/test/ModuleImporterTests.kt b/compiler/test/ModuleImporterTests.kt index a9419dc3e..ea3677297 100644 --- a/compiler/test/ModuleImporterTests.kt +++ b/compiler/test/ModuleImporterTests.kt @@ -9,7 +9,7 @@ import org.hamcrest.core.Is import org.junit.jupiter.api.* import prog8.ast.Program import prog8.ast.internedStringsModuleName -import prog8.compiler.IErrorReporter +import prog8.compilerinterface.IErrorReporter import prog8.compiler.ModuleImporter import prog8.parser.ParseError import prog8.parser.SourceCode diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index 7a222f3fa..6aac841f6 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -4,10 +4,10 @@ import org.junit.jupiter.api.DynamicTest import org.junit.jupiter.api.DynamicTest.dynamicTest import org.junit.jupiter.api.TestFactory import org.junit.jupiter.api.TestInstance +import prog8.compilerinterface.ICompilationTarget import prog8.compiler.compileProgram import prog8.compiler.target.C64Target import prog8.compiler.target.Cx16Target -import prog8.compiler.target.ICompilationTarget import prog8tests.helpers.* import kotlin.io.path.absolute import kotlin.io.path.exists diff --git a/compiler/test/TestCompilerOnRanges.kt b/compiler/test/TestCompilerOnRanges.kt index 7470bfbf0..d648eac61 100644 --- a/compiler/test/TestCompilerOnRanges.kt +++ b/compiler/test/TestCompilerOnRanges.kt @@ -9,10 +9,10 @@ import prog8.ast.expressions.* import prog8.ast.statements.ForLoop import prog8.ast.statements.Subroutine import prog8.ast.statements.VarDecl -import prog8.compiler.astprocessing.size -import prog8.compiler.astprocessing.toConstantIntegerRange +import prog8.compilerinterface.size import prog8.compiler.target.C64Target import prog8.compiler.target.Cx16Target +import prog8.compilerinterface.toConstantIntegerRange import prog8tests.helpers.* import kotlin.test.assertContains import kotlin.test.assertEquals diff --git a/compiler/test/TestImportedModulesOrderAndOptions.kt b/compiler/test/TestImportedModulesOrderAndOptions.kt index e85ef6fcc..ec9aa9e4b 100644 --- a/compiler/test/TestImportedModulesOrderAndOptions.kt +++ b/compiler/test/TestImportedModulesOrderAndOptions.kt @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import prog8.ast.internedStringsModuleName import prog8.compiler.ErrorReporter -import prog8.compiler.ZeropageType +import prog8.compilerinterface.ZeropageType import prog8.compiler.determineCompilationOptions import prog8.compiler.parseImports import prog8.compiler.target.C64Target diff --git a/compiler/test/TestMemory.kt b/compiler/test/TestMemory.kt index 21dff8654..49a5c5323 100644 --- a/compiler/test/TestMemory.kt +++ b/compiler/test/TestMemory.kt @@ -12,7 +12,7 @@ import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.PrefixExpression import prog8.ast.statements.* -import prog8.compiler.astprocessing.isInRegularRAMof +import prog8.compilerinterface.isInRegularRAMof import prog8.compiler.target.C64Target import prog8.parser.SourceCode import prog8tests.helpers.DummyFunctions diff --git a/compiler/test/TestNumbers.kt b/compiler/test/TestNumbers.kt index 1de09e330..6e14f5346 100644 --- a/compiler/test/TestNumbers.kt +++ b/compiler/test/TestNumbers.kt @@ -6,7 +6,7 @@ import org.hamcrest.Matchers.equalTo import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import prog8.ast.toHex -import prog8.compiler.CompilerException +import prog8.compilerinterface.CompilerException import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_NEGATIVE import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_POSITIVE import prog8.compiler.target.c64.C64MachineDefinition.Mflpt5 diff --git a/compiler/test/ZeropageTests.kt b/compiler/test/ZeropageTests.kt index 8e2a3a6b7..6b341e817 100644 --- a/compiler/test/ZeropageTests.kt +++ b/compiler/test/ZeropageTests.kt @@ -8,6 +8,7 @@ import prog8.compiler.target.C64Target import prog8.compiler.target.Cx16Target import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage import prog8.compiler.target.cx16.CX16MachineDefinition.CX16Zeropage +import prog8.compilerinterface.* import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertFalse diff --git a/compiler/test/helpers/ErrorReporterForTests.kt b/compiler/test/helpers/ErrorReporterForTests.kt index f6f47e81a..baa727e65 100644 --- a/compiler/test/helpers/ErrorReporterForTests.kt +++ b/compiler/test/helpers/ErrorReporterForTests.kt @@ -1,7 +1,7 @@ package prog8tests.helpers import prog8.ast.base.Position -import prog8.compiler.IErrorReporter +import prog8.compilerinterface.IErrorReporter class ErrorReporterForTests(private val throwExceptionAtReportIfErrors: Boolean=true): IErrorReporter { diff --git a/compiler/test/helpers/compileXyz.kt b/compiler/test/helpers/compileXyz.kt index aafc1fe8e..699df20f8 100644 --- a/compiler/test/helpers/compileXyz.kt +++ b/compiler/test/helpers/compileXyz.kt @@ -1,10 +1,8 @@ package prog8tests.helpers -import prog8.compiler.CompilationResult -import prog8.compiler.ErrorReporter -import prog8.compiler.IErrorReporter -import prog8.compiler.compileProgram -import prog8.compiler.target.ICompilationTarget +import prog8.compiler.* +import prog8.compilerinterface.ICompilationTarget +import prog8.compilerinterface.IErrorReporter import java.nio.file.Path import kotlin.io.path.name import kotlin.test.assertFalse diff --git a/compilerAst/src/prog8/ast/AstToplevel.kt b/compilerAst/src/prog8/ast/AstToplevel.kt index 2ab14f6d2..ff7103278 100644 --- a/compilerAst/src/prog8/ast/AstToplevel.kt +++ b/compilerAst/src/prog8/ast/AstToplevel.kt @@ -7,6 +7,7 @@ import prog8.ast.expressions.StringLiteralValue import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstVisitor +import prog8.compiler.IMemSizer import prog8.parser.SourceCode const val internedStringsModuleName = "prog8_interned_strings" @@ -286,7 +287,8 @@ interface Node { class Program(val name: String, val builtinFunctions: IBuiltinFunctions, - val memsizer: IMemSizer): Node { + val memsizer: IMemSizer +): Node { private val _modules = mutableListOf() val modules: List = _modules diff --git a/compilerAst/src/prog8/ast/IBuiltinFunctions.kt b/compilerAst/src/prog8/ast/IBuiltinFunctions.kt index b9d19cf58..f4473a1d6 100644 --- a/compilerAst/src/prog8/ast/IBuiltinFunctions.kt +++ b/compilerAst/src/prog8/ast/IBuiltinFunctions.kt @@ -4,10 +4,11 @@ import prog8.ast.base.Position import prog8.ast.expressions.Expression import prog8.ast.expressions.InferredTypes import prog8.ast.expressions.NumericLiteralValue +import prog8.compiler.IMemSizer interface IBuiltinFunctions { val names: Set val purefunctionNames: Set fun constValue(name: String, args: List, position: Position, memsizer: IMemSizer): NumericLiteralValue? fun returnType(name: String, args: MutableList): InferredTypes.InferredType -} \ No newline at end of file +} diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 7e4b8a647..c178c3b68 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -6,6 +6,7 @@ import prog8.ast.base.* import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstVisitor +import prog8.compiler.IMemSizer import java.util.* diff --git a/compilerAst/src/prog8/ast/IMemSizer.kt b/compilerAst/src/prog8/compiler/IMemSizer.kt similarity index 78% rename from compilerAst/src/prog8/ast/IMemSizer.kt rename to compilerAst/src/prog8/compiler/IMemSizer.kt index 9ba6767e3..b0bf03dbf 100644 --- a/compilerAst/src/prog8/ast/IMemSizer.kt +++ b/compilerAst/src/prog8/compiler/IMemSizer.kt @@ -1,7 +1,7 @@ -package prog8.ast +package prog8.compiler import prog8.ast.base.DataType interface IMemSizer { fun memorySize(dt: DataType): Int -} \ No newline at end of file +} diff --git a/compilerAst/test/helpers/DummyFunctions.kt b/compilerAst/test/helpers/DummyFunctions.kt index e212ea9ea..b58c7d0bf 100644 --- a/compilerAst/test/helpers/DummyFunctions.kt +++ b/compilerAst/test/helpers/DummyFunctions.kt @@ -1,11 +1,11 @@ package prog8tests.helpers import prog8.ast.IBuiltinFunctions -import prog8.ast.IMemSizer import prog8.ast.base.Position import prog8.ast.expressions.Expression import prog8.ast.expressions.InferredTypes import prog8.ast.expressions.NumericLiteralValue +import prog8.compiler.IMemSizer val DummyFunctions = object : IBuiltinFunctions { override val names: Set = emptySet() @@ -18,4 +18,4 @@ val DummyFunctions = object : IBuiltinFunctions { ): NumericLiteralValue? = null override fun returnType(name: String, args: MutableList) = InferredTypes.InferredType.unknown() -} \ No newline at end of file +} diff --git a/compilerAst/test/helpers/DummyMemsizer.kt b/compilerAst/test/helpers/DummyMemsizer.kt index 3d226437d..929514a5b 100644 --- a/compilerAst/test/helpers/DummyMemsizer.kt +++ b/compilerAst/test/helpers/DummyMemsizer.kt @@ -1,8 +1,8 @@ package prog8tests.helpers -import prog8.ast.IMemSizer import prog8.ast.base.DataType +import prog8.compiler.IMemSizer val DummyMemsizer = object : IMemSizer { override fun memorySize(dt: DataType): Int = 0 -} \ No newline at end of file +} diff --git a/compilerInterfaces/build.gradle b/compilerInterfaces/build.gradle new file mode 100644 index 000000000..68d9db7bc --- /dev/null +++ b/compilerInterfaces/build.gradle @@ -0,0 +1,66 @@ + +plugins { + id 'java' + id 'application' + id "org.jetbrains.kotlin.jvm" +} + +targetCompatibility = 11 +sourceCompatibility = 11 + +repositories { + mavenLocal() + mavenCentral() + maven { url "https://kotlin.bintray.com/kotlinx" } +} + +dependencies { + implementation project(':compilerAst') + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + // implementation "org.jetbrains.kotlin:kotlin-reflect" + +} + +compileKotlin { + kotlinOptions { + jvmTarget = "11" + // verbose = true + // freeCompilerArgs += "-XXLanguage:+NewInference" + } +} + +compileTestKotlin { + kotlinOptions { + jvmTarget = "11" + } +} + +sourceSets { + main { + java { + srcDirs = ["${project.projectDir}/src"] + } + resources { + srcDirs = ["${project.projectDir}/res"] + } + } + test { + java { + srcDirs = ["${project.projectDir}/test"] + } + } +} + + +test { + // Enable JUnit 5 (Gradle 4.6+). + useJUnitPlatform() + + // Always run tests, even when nothing changed. + dependsOn 'cleanTest' + + // Show test results. + testLogging { + events "skipped", "failed" + } +} diff --git a/compilerInterfaces/compilerInterfaces.iml b/compilerInterfaces/compilerInterfaces.iml new file mode 100644 index 000000000..f9ace27ff --- /dev/null +++ b/compilerInterfaces/compilerInterfaces.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/compilerInterfaces/src/prog8/compilerinterface/AstExtensions.kt b/compilerInterfaces/src/prog8/compilerinterface/AstExtensions.kt new file mode 100644 index 000000000..999ebd569 --- /dev/null +++ b/compilerInterfaces/src/prog8/compilerinterface/AstExtensions.kt @@ -0,0 +1,99 @@ +package prog8.compilerinterface + +import prog8.ast.base.VarDeclType +import prog8.ast.expressions.IdentifierReference +import prog8.ast.expressions.NumericLiteralValue +import prog8.ast.expressions.RangeExpr +import prog8.ast.expressions.StringLiteralValue +import prog8.ast.statements.AssignTarget +import kotlin.math.abs + +fun AssignTarget.isInRegularRAMof(machine: IMachineDefinition): Boolean { + val memAddr = memoryAddress + val arrayIdx = arrayindexed + val ident = identifier + when { + memAddr != null -> { + return when (memAddr.addressExpression) { + is NumericLiteralValue -> { + machine.isRegularRAMaddress((memAddr.addressExpression as NumericLiteralValue).number.toInt()) + } + is IdentifierReference -> { + val program = definingModule.program + val decl = (memAddr.addressExpression as IdentifierReference).targetVarDecl(program) + if ((decl?.type == VarDeclType.VAR || decl?.type == VarDeclType.CONST) && decl.value is NumericLiteralValue) + machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt()) + else + false + } + else -> false + } + } + arrayIdx != null -> { + val program = definingModule.program + val targetStmt = arrayIdx.arrayvar.targetVarDecl(program) + return if (targetStmt?.type == VarDeclType.MEMORY) { + val addr = targetStmt.value as? NumericLiteralValue + if (addr != null) + machine.isRegularRAMaddress(addr.number.toInt()) + else + false + } else true + } + ident != null -> { + val program = definingModule.program + val decl = ident.targetVarDecl(program)!! + return if (decl.type == VarDeclType.MEMORY && decl.value is NumericLiteralValue) + machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt()) + else + true + } + else -> return true + } +} + +fun RangeExpr.toConstantIntegerRange(encoding: IStringEncoding): IntProgression? { + + fun makeRange(fromVal: Int, toVal: Int, stepVal: Int): IntProgression { + return when { + fromVal <= toVal -> when { + stepVal <= 0 -> IntRange.EMPTY + stepVal == 1 -> fromVal..toVal + else -> fromVal..toVal step stepVal + } + else -> when { + stepVal >= 0 -> IntRange.EMPTY + stepVal == -1 -> fromVal downTo toVal + else -> fromVal downTo toVal step abs(stepVal) + } + } + } + + val fromVal: Int + val toVal: Int + val fromString = from as? StringLiteralValue + val toString = to as? StringLiteralValue + if(fromString!=null && toString!=null ) { + // string range -> int range over character values + fromVal = encoding.encodeString(fromString.value, fromString.altEncoding)[0].toInt() + toVal = encoding.encodeString(toString.value, fromString.altEncoding)[0].toInt() + } else { + val fromLv = from as? NumericLiteralValue + val toLv = to as? NumericLiteralValue + if(fromLv==null || toLv==null) + return null // non-constant range + // integer range + fromVal = fromLv.number.toInt() + toVal = toLv.number.toInt() + } + val stepVal = (step as? NumericLiteralValue)?.number?.toInt() ?: 1 + return makeRange(fromVal, toVal, stepVal) +} + +fun RangeExpr.size(encoding: IStringEncoding): Int? { + val fromLv = (from as? NumericLiteralValue) + val toLv = (to as? NumericLiteralValue) + if(fromLv==null || toLv==null) + return null + return toConstantIntegerRange(encoding)?.count() +} diff --git a/compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt b/compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt new file mode 100644 index 000000000..5ffe26eea --- /dev/null +++ b/compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt @@ -0,0 +1,31 @@ +package prog8.compilerinterface + +enum class OutputType { + RAW, + PRG +} + +enum class LauncherType { + BASIC, + NONE +} + +enum class ZeropageType { + BASICSAFE, + FLOATSAFE, + KERNALSAFE, + FULL, + DONTUSE +} + +data class CompilationOptions(val output: OutputType, + val launcher: LauncherType, + val zeropage: ZeropageType, + val zpReserved: List, + val floats: Boolean, + val noSysInit: Boolean, + val compTarget: ICompilationTarget +) { + var slowCodegenWarnings = false + var optimize = false +} diff --git a/compilerInterfaces/src/prog8/compilerinterface/CompilerException.kt b/compilerInterfaces/src/prog8/compilerinterface/CompilerException.kt new file mode 100644 index 000000000..288d8573e --- /dev/null +++ b/compilerInterfaces/src/prog8/compilerinterface/CompilerException.kt @@ -0,0 +1,3 @@ +package prog8.compilerinterface + +class CompilerException(message: String?) : Exception(message) diff --git a/compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt b/compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt new file mode 100644 index 000000000..934485fec --- /dev/null +++ b/compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt @@ -0,0 +1,15 @@ +package prog8.compilerinterface + +interface IAssemblyGenerator { + fun compileToAssembly(): IAssemblyProgram +} + +const val generatedLabelPrefix = "_prog8_label_" +const val subroutineFloatEvalResultVar1 = "_prog8_float_eval_result1" +const val subroutineFloatEvalResultVar2 = "_prog8_float_eval_result2" + +interface IAssemblyProgram { + val valid: Boolean + val name: String + fun assemble(options: CompilationOptions): Int +} diff --git a/compilerInterfaces/src/prog8/compilerinterface/ICompilationTarget.kt b/compilerInterfaces/src/prog8/compilerinterface/ICompilationTarget.kt new file mode 100644 index 000000000..496ac65ab --- /dev/null +++ b/compilerInterfaces/src/prog8/compilerinterface/ICompilationTarget.kt @@ -0,0 +1,10 @@ +package prog8.compilerinterface + +import prog8.compiler.IMemSizer + +interface ICompilationTarget: IStringEncoding, IMemSizer { + val name: String + val machine: IMachineDefinition + override fun encodeString(str: String, altEncoding: Boolean): List + override fun decodeString(bytes: List, altEncoding: Boolean): String +} diff --git a/compilerInterfaces/src/prog8/compilerinterface/IErrorReporter.kt b/compilerInterfaces/src/prog8/compilerinterface/IErrorReporter.kt new file mode 100644 index 000000000..a4247c1d7 --- /dev/null +++ b/compilerInterfaces/src/prog8/compilerinterface/IErrorReporter.kt @@ -0,0 +1,16 @@ +package prog8.compilerinterface + +import prog8.ast.base.Position +import prog8.parser.ParsingFailedError + + +interface IErrorReporter { + fun err(msg: String, position: Position) + fun warn(msg: String, position: Position) + fun noErrors(): Boolean + fun report() + fun finalizeNumErrors(numErrors: Int, numWarnings: Int) { + if(numErrors>0) + throw ParsingFailedError("There are $numErrors errors and $numWarnings warnings.") + } +} diff --git a/compiler/src/prog8/compiler/target/IMachineDefinition.kt b/compilerInterfaces/src/prog8/compilerinterface/IMachineDefinition.kt similarity index 89% rename from compiler/src/prog8/compiler/target/IMachineDefinition.kt rename to compilerInterfaces/src/prog8/compilerinterface/IMachineDefinition.kt index b80555b78..82294b855 100644 --- a/compiler/src/prog8/compiler/target/IMachineDefinition.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/IMachineDefinition.kt @@ -1,7 +1,5 @@ -package prog8.compiler.target +package prog8.compilerinterface -import prog8.compiler.CompilationOptions -import prog8.compiler.Zeropage import java.nio.file.Path diff --git a/compiler/src/prog8/compiler/IStringEncoding.kt b/compilerInterfaces/src/prog8/compilerinterface/IStringEncoding.kt similarity index 83% rename from compiler/src/prog8/compiler/IStringEncoding.kt rename to compilerInterfaces/src/prog8/compilerinterface/IStringEncoding.kt index a69e9ba62..1d91a63f0 100644 --- a/compiler/src/prog8/compiler/IStringEncoding.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/IStringEncoding.kt @@ -1,6 +1,6 @@ -package prog8.compiler +package prog8.compilerinterface interface IStringEncoding { fun encodeString(str: String, altEncoding: Boolean): List fun decodeString(bytes: List, altEncoding: Boolean): String -} \ No newline at end of file +} diff --git a/compiler/src/prog8/compiler/Zeropage.kt b/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt similarity index 90% rename from compiler/src/prog8/compiler/Zeropage.kt rename to compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt index ce300bddc..ef35d144b 100644 --- a/compiler/src/prog8/compiler/Zeropage.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt @@ -1,4 +1,4 @@ -package prog8.compiler +package prog8.compilerinterface import prog8.ast.base.* @@ -19,10 +19,10 @@ abstract class Zeropage(protected val options: CompilationOptions) { val allowedDatatypes = NumericDatatypes - fun availableBytes() = if(options.zeropage==ZeropageType.DONTUSE) 0 else free.size - fun hasByteAvailable() = if(options.zeropage==ZeropageType.DONTUSE) false else free.isNotEmpty() + fun availableBytes() = if(options.zeropage== ZeropageType.DONTUSE) 0 else free.size + fun hasByteAvailable() = if(options.zeropage== ZeropageType.DONTUSE) false else free.isNotEmpty() fun availableWords(): Int { - if(options.zeropage==ZeropageType.DONTUSE) + if(options.zeropage== ZeropageType.DONTUSE) return 0 val words = free.windowed(2).filter { it[0] == it[1]-1 } @@ -37,7 +37,7 @@ abstract class Zeropage(protected val options: CompilationOptions) { return nonOverlappingWordsCount } fun hasWordAvailable(): Boolean { - if(options.zeropage==ZeropageType.DONTUSE) + if(options.zeropage== ZeropageType.DONTUSE) return false return free.windowed(2).any { it[0] == it[1] - 1 } @@ -46,7 +46,7 @@ abstract class Zeropage(protected val options: CompilationOptions) { 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) + if(options.zeropage== ZeropageType.DONTUSE) throw CompilerException("zero page usage has been disabled") val size = diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 761c88715..801c11849 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -27,7 +27,6 @@ Future - add a diskio.f_seek() routine for the Cx16 that uses its seek dos api? - make it possible for diskio to read and write from more than one file at the same time (= use multiple io channels)? - refactor the asmgen into own project submodule -- refactor the compiler optimizers into own project submodule - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``v_`` - [problematic due to 64tass:] add a compiler option to not remove unused subroutines. this allows for building library programs. But this won't work with 64tass's .proc ... Perhaps replace all uses of .proc/.pend by .block/.bend will fix that? diff --git a/httpCompilerService/build.gradle b/httpCompilerService/build.gradle index fe8d8324d..8926488b3 100644 --- a/httpCompilerService/build.gradle +++ b/httpCompilerService/build.gradle @@ -16,6 +16,7 @@ repositories { } dependencies { + implementation project(':compilerInterfaces') implementation project(':compiler') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" // implementation "org.jetbrains.kotlin:kotlin-reflect" diff --git a/httpCompilerService/httpCompilerService.iml b/httpCompilerService/httpCompilerService.iml index b77b1991c..e0bcb3d99 100644 --- a/httpCompilerService/httpCompilerService.iml +++ b/httpCompilerService/httpCompilerService.iml @@ -14,5 +14,6 @@ + \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index a716211fb..17558290d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,7 @@ include ':parser' +include ':compilerInterfaces' include ':compilerAst' +include ':codeOptimizers' include ':compiler' include ':dbusCompilerService' include ':httpCompilerService'