split out the code optimizers into own project submodule

This commit is contained in:
Irmen de Jong 2021-10-29 02:42:10 +02:00
parent 2c940de598
commit f21dcaa6fb
75 changed files with 575 additions and 360 deletions

6
.idea/kotlinc.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Kotlin2JvmCompilerArguments">
<option name="jvmTarget" value="11" />
</component>
</project>

View File

@ -0,0 +1,15 @@
<component name="libraryTable">
<library name="KotlinJavaRuntime (2)">
<CLASSES>
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-sources.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect-sources.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -0,0 +1,15 @@
<component name="libraryTable">
<library name="KotlinJavaRuntime (3)">
<CLASSES>
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-sources.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect-sources.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test-sources.jar!/" />
</SOURCES>
</library>
</component>

2
.idea/modules.xml generated
View File

@ -2,8 +2,10 @@
<project version="4"> <project version="4">
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/codeOptimizers/codeOptimizers.iml" filepath="$PROJECT_DIR$/codeOptimizers/codeOptimizers.iml" />
<module fileurl="file://$PROJECT_DIR$/compiler/compiler.iml" filepath="$PROJECT_DIR$/compiler/compiler.iml" /> <module fileurl="file://$PROJECT_DIR$/compiler/compiler.iml" filepath="$PROJECT_DIR$/compiler/compiler.iml" />
<module fileurl="file://$PROJECT_DIR$/compilerAst/compilerAst.iml" filepath="$PROJECT_DIR$/compilerAst/compilerAst.iml" /> <module fileurl="file://$PROJECT_DIR$/compilerAst/compilerAst.iml" filepath="$PROJECT_DIR$/compilerAst/compilerAst.iml" />
<module fileurl="file://$PROJECT_DIR$/compilerInterfaces/compilerInterfaces.iml" filepath="$PROJECT_DIR$/compilerInterfaces/compilerInterfaces.iml" />
<module fileurl="file://$PROJECT_DIR$/dbusCompilerService/dbusCompilerService.iml" filepath="$PROJECT_DIR$/dbusCompilerService/dbusCompilerService.iml" /> <module fileurl="file://$PROJECT_DIR$/dbusCompilerService/dbusCompilerService.iml" filepath="$PROJECT_DIR$/dbusCompilerService/dbusCompilerService.iml" />
<module fileurl="file://$PROJECT_DIR$/docs/docs.iml" filepath="$PROJECT_DIR$/docs/docs.iml" /> <module fileurl="file://$PROJECT_DIR$/docs/docs.iml" filepath="$PROJECT_DIR$/docs/docs.iml" />
<module fileurl="file://$PROJECT_DIR$/examples/examples.iml" filepath="$PROJECT_DIR$/examples/examples.iml" /> <module fileurl="file://$PROJECT_DIR$/examples/examples.iml" filepath="$PROJECT_DIR$/examples/examples.iml" />

View File

@ -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"
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="openjdk-11" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="KotlinJavaRuntime (2)" level="project" />
<orderEntry type="module" module-name="compilerInterfaces" />
<orderEntry type="module" module-name="compilerAst" />
</component>
</module>

View File

@ -9,11 +9,11 @@ import prog8.ast.statements.AssignTarget
import prog8.ast.statements.Assignment import prog8.ast.statements.Assignment
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.compiler.astprocessing.isInRegularRAMof import prog8.compilerinterface.ICompilationTarget
import prog8.compiler.target.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<IAstModification> { // override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
// TODO somehow if we do this, the resulting code for some programs (cube3d.p8) gets hundreds of bytes larger...: // TODO somehow if we do this, the resulting code for some programs (cube3d.p8) gets hundreds of bytes larger...:

View File

@ -10,7 +10,7 @@ import prog8.ast.expressions.FunctionCall
import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.IdentifierReference
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
import prog8.compiler.IErrorReporter import prog8.compilerinterface.IErrorReporter
class CallGraph(private val program: Program) : IAstVisitor { class CallGraph(private val program: Program) : IAstVisitor {

View File

@ -12,7 +12,7 @@ import prog8.ast.walk.IAstModification
import kotlin.math.pow 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<IAstModification> { override fun before(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> {
// @( &thing ) --> thing // @( &thing ) --> thing

View File

@ -7,14 +7,14 @@ import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.compiler.IErrorReporter import prog8.compilerinterface.ICompilationTarget
import prog8.compiler.astprocessing.size import prog8.compilerinterface.IErrorReporter
import prog8.compiler.astprocessing.toConstantIntegerRange import prog8.compilerinterface.size
import prog8.compiler.target.ICompilationTarget import prog8.compilerinterface.toConstantIntegerRange
// Fix up the literal value's type to match that of the vardecl // Fix up the literal value's type to match that of the vardecl
// (also check range literal operands types before they get expanded into arrays for instance) // (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<IAstModification> { override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {

View File

@ -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 powersOfTwo = (1..16).map { (2.0).pow(it) }.toSet()
private val negativePowersOfTwo = powersOfTwo.map { -it }.toSet() private val negativePowersOfTwo = powersOfTwo.map { -it }.toSet()

View File

@ -2,11 +2,11 @@ package prog8.optimizer
import prog8.ast.IBuiltinFunctions import prog8.ast.IBuiltinFunctions
import prog8.ast.Program import prog8.ast.Program
import prog8.compiler.IErrorReporter import prog8.compilerinterface.ICompilationTarget
import prog8.compiler.target.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) val valuetypefixer = VarConstantValueTypeAdjuster(this, errors)
valuetypefixer.visit(this) valuetypefixer.visit(this)
if(errors.noErrors()) { if(errors.noErrors()) {
@ -40,9 +40,10 @@ internal fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilati
} }
internal fun Program.optimizeStatements(errors: IErrorReporter, fun Program.optimizeStatements(errors: IErrorReporter,
functions: IBuiltinFunctions, functions: IBuiltinFunctions,
compTarget: ICompilationTarget): Int { compTarget: ICompilationTarget
): Int {
val optimizer = StatementOptimizer(this, errors, functions, compTarget) val optimizer = StatementOptimizer(this, errors, functions, compTarget)
optimizer.visit(this) optimizer.visit(this)
val optimizationCount = optimizer.applyModifications() val optimizationCount = optimizer.applyModifications()
@ -52,13 +53,13 @@ internal fun Program.optimizeStatements(errors: IErrorReporter,
return optimizationCount return optimizationCount
} }
internal fun Program.simplifyExpressions() : Int { fun Program.simplifyExpressions() : Int {
val opti = ExpressionSimplifier(this) val opti = ExpressionSimplifier(this)
opti.visit(this) opti.visit(this)
return opti.applyModifications() return opti.applyModifications()
} }
internal fun Program.splitBinaryExpressions(compTarget: ICompilationTarget) : Int { fun Program.splitBinaryExpressions(compTarget: ICompilationTarget) : Int {
val opti = BinExprSplitter(this, compTarget) val opti = BinExprSplitter(this, compTarget)
opti.visit(this) opti.visit(this)
return opti.applyModifications() return opti.applyModifications()

View File

@ -10,18 +10,19 @@ import prog8.ast.statements.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
import prog8.compiler.IErrorReporter import prog8.compilerinterface.ICompilationTarget
import prog8.compiler.astprocessing.size import prog8.compilerinterface.IErrorReporter
import prog8.compiler.target.ICompilationTarget import prog8.compilerinterface.size
import kotlin.math.floor import kotlin.math.floor
internal const val retvarName = "prog8_retval" 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 errors: IErrorReporter,
private val functions: IBuiltinFunctions, private val functions: IBuiltinFunctions,
private val compTarget: ICompilationTarget) : AstWalker() { private val compTarget: ICompilationTarget
) : AstWalker() {
private val subsThatNeedReturnVariable = mutableSetOf<Triple<IStatementContainer, DataType, Position>>() private val subsThatNeedReturnVariable = mutableSetOf<Triple<IStatementContainer, DataType, Position>>()

View File

@ -9,14 +9,15 @@ import prog8.ast.expressions.TypecastExpression
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.compiler.IErrorReporter import prog8.compilerinterface.ICompilationTarget
import prog8.compiler.astprocessing.isInRegularRAMof import prog8.compilerinterface.IErrorReporter
import prog8.compiler.target.ICompilationTarget import prog8.compilerinterface.isInRegularRAMof
internal class UnusedCodeRemover(private val program: Program, class UnusedCodeRemover(private val program: Program,
private val errors: IErrorReporter, private val errors: IErrorReporter,
private val compTarget: ICompilationTarget): AstWalker() { private val compTarget: ICompilationTarget
): AstWalker() {
private val callgraph = CallGraph(program) private val callgraph = CallGraph(program)

View File

@ -18,6 +18,8 @@ repositories {
def prog8version = rootProject.file('compiler/res/version.txt').text.trim() def prog8version = rootProject.file('compiler/res/version.txt').text.trim()
dependencies { dependencies {
implementation project(':compilerInterfaces')
implementation project(':codeOptimizers')
implementation project(':compilerAst') implementation project(':compilerAst')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect" // implementation "org.jetbrains.kotlin:kotlin-reflect"

View File

@ -22,5 +22,7 @@
<orderEntry type="library" name="jetbrains.kotlinx.cli.jvm" level="project" /> <orderEntry type="library" name="jetbrains.kotlinx.cli.jvm" level="project" />
<orderEntry type="library" name="junit.jupiter" level="project" /> <orderEntry type="library" name="junit.jupiter" level="project" />
<orderEntry type="library" name="michael.bull.kotlin.result.jvm" level="project" /> <orderEntry type="library" name="michael.bull.kotlin.result.jvm" level="project" />
<orderEntry type="module" module-name="codeOptimizers" />
<orderEntry type="module" module-name="compilerInterfaces" />
</component> </component>
</module> </module>

View File

@ -10,9 +10,11 @@ import prog8.ast.statements.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
import prog8.compiler.astprocessing.isInRegularRAMof
import prog8.compiler.astprocessing.isSubroutineParameter 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() { internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: IErrorReporter, private val compTarget: ICompilationTarget) : AstWalker() {

View File

@ -3,7 +3,6 @@ package prog8.compiler
import com.github.michaelbull.result.* import com.github.michaelbull.result.*
import prog8.ast.AstToSourceTextConverter import prog8.ast.AstToSourceTextConverter
import prog8.ast.IBuiltinFunctions import prog8.ast.IBuiltinFunctions
import prog8.ast.IMemSizer
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.base.AstException import prog8.ast.base.AstException
import prog8.ast.base.Position import prog8.ast.base.Position
@ -14,8 +13,8 @@ import prog8.compiler.astprocessing.*
import prog8.compiler.functions.* import prog8.compiler.functions.*
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target
import prog8.compiler.target.Cx16Target import prog8.compiler.target.Cx16Target
import prog8.compiler.target.ICompilationTarget import prog8.compiler.target.cpu6502.codegen.AsmGen
import prog8.compiler.target.asmGeneratorFor import prog8.compilerinterface.*
import prog8.optimizer.* import prog8.optimizer.*
import prog8.parser.ParseError import prog8.parser.ParseError
import prog8.parser.ParsingFailedError import prog8.parser.ParsingFailedError
@ -29,38 +28,6 @@ import kotlin.io.path.nameWithoutExtension
import kotlin.system.measureTimeMillis 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<IntRange>,
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, class CompilationResult(val success: Boolean,
val programAst: Program, val programAst: Program,
val programName: String, val programName: String,
@ -347,7 +314,8 @@ private sealed class WriteAssemblyResult {
private fun writeAssembly(programAst: Program, private fun writeAssembly(programAst: Program,
errors: IErrorReporter, errors: IErrorReporter,
outputDir: Path, outputDir: Path,
compilerOptions: CompilationOptions): WriteAssemblyResult { compilerOptions: CompilationOptions
): WriteAssemblyResult {
// asm generation directly from the Ast // asm generation directly from the Ast
programAst.processAstBeforeAsmGeneration(errors, compilerOptions.compTarget) programAst.processAstBeforeAsmGeneration(errors, compilerOptions.compTarget)
errors.report() errors.report()
@ -396,3 +364,16 @@ internal fun loadAsmIncludeFile(filename: String, source: SourceCode): Result<St
Ok(SourceCode.File(Path(filename)).readText()) Ok(SourceCode.File(Path(filename)).readText())
} }
} }
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)
}

View File

@ -1,19 +1,7 @@
package prog8.compiler package prog8.compiler
import prog8.ast.base.Position import prog8.ast.base.Position
import prog8.parser.ParsingFailedError import prog8.compilerinterface.IErrorReporter
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.")
}
}
internal class ErrorReporter: IErrorReporter { internal class ErrorReporter: IErrorReporter {

View File

@ -7,6 +7,7 @@ import prog8.ast.base.Position
import prog8.ast.base.SyntaxError import prog8.ast.base.SyntaxError
import prog8.ast.statements.Directive import prog8.ast.statements.Directive
import prog8.ast.statements.DirectiveArg import prog8.ast.statements.DirectiveArg
import prog8.compilerinterface.IErrorReporter
import prog8.parser.Prog8Parser import prog8.parser.Prog8Parser
import prog8.parser.SourceCode import prog8.parser.SourceCode
import java.io.File import java.io.File

View File

@ -8,12 +8,12 @@ import prog8.ast.base.*
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
import prog8.compiler.CompilationOptions import prog8.compilerinterface.CompilationOptions
import prog8.compiler.IErrorReporter import prog8.compilerinterface.ICompilationTarget
import prog8.compiler.ZeropageType import prog8.compilerinterface.IErrorReporter
import prog8.compilerinterface.ZeropageType
import prog8.compiler.functions.BuiltinFunctions import prog8.compiler.functions.BuiltinFunctions
import prog8.compiler.functions.builtinFunctionReturnType import prog8.compiler.functions.builtinFunctionReturnType
import prog8.compiler.target.ICompilationTarget
import java.io.CharConversionException import java.io.CharConversionException
import java.io.File import java.io.File
import java.util.* import java.util.*

View File

@ -3,65 +3,16 @@ package prog8.compiler.astprocessing
import prog8.ast.Node import prog8.ast.Node
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.base.DataType import prog8.ast.base.DataType
import prog8.ast.base.VarDeclType
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.AssignTarget
import prog8.ast.statements.Directive import prog8.ast.statements.Directive
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.compiler.*
import prog8.compiler.BeforeAsmGenerationAstChanger import prog8.compiler.BeforeAsmGenerationAstChanger
import prog8.compiler.CompilationOptions import prog8.compilerinterface.CompilationOptions
import prog8.compiler.IErrorReporter import prog8.compilerinterface.ICompilationTarget
import prog8.compiler.IStringEncoding import prog8.compilerinterface.IErrorReporter
import prog8.compiler.target.ICompilationTarget import prog8.compilerinterface.IStringEncoding
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)
}
}
}
internal fun Program.checkValid(compilerOptions: CompilationOptions, errors: IErrorReporter, compTarget: ICompilationTarget) { internal fun Program.checkValid(compilerOptions: CompilationOptions, errors: IErrorReporter, compTarget: ICompilationTarget) {
@ -143,7 +94,6 @@ internal fun Program.variousCleanups(program: Program, errors: IErrorReporter) {
process.applyModifications() process.applyModifications()
} }
internal fun Program.moveMainAndStartToFirst() { internal fun Program.moveMainAndStartToFirst() {
// the module containing the program entrypoint is moved to the first in the sequence. // 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, // 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 { internal fun IdentifierReference.isSubroutineParameter(program: Program): Boolean {
val vardecl = this.targetVarDecl(program) val vardecl = this.targetVarDecl(program)
if(vardecl!=null && vardecl.autogeneratedDontRemove) { if(vardecl!=null && vardecl.autogeneratedDontRemove) {

View File

@ -4,9 +4,9 @@ import prog8.ast.base.Position
import prog8.ast.expressions.StringLiteralValue import prog8.ast.expressions.StringLiteralValue
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.IAstVisitor 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.functions.BuiltinFunctions
import prog8.compiler.target.ICompilationTarget
internal class AstIdentifiersChecker(private val errors: IErrorReporter, private val compTarget: ICompilationTarget) : IAstVisitor { internal class AstIdentifiersChecker(private val errors: IErrorReporter, private val compTarget: ICompilationTarget) : IAstVisitor {
private var blocks = mutableMapOf<String, Block>() private var blocks = mutableMapOf<String, Block>()

View File

@ -10,7 +10,7 @@ import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.compiler.IErrorReporter import prog8.compilerinterface.IErrorReporter
import prog8.compiler.functions.BuiltinFunctions import prog8.compiler.functions.BuiltinFunctions

View File

@ -8,7 +8,7 @@ import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.compiler.IErrorReporter import prog8.compilerinterface.IErrorReporter
import prog8.compiler.functions.BuiltinFunctions import prog8.compiler.functions.BuiltinFunctions

View File

@ -10,7 +10,7 @@ import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.compiler.IErrorReporter import prog8.compilerinterface.IErrorReporter
internal class VariousCleanups(val program: Program, val errors: IErrorReporter): AstWalker() { internal class VariousCleanups(val program: Program, val errors: IErrorReporter): AstWalker() {

View File

@ -8,7 +8,7 @@ import prog8.ast.expressions.FunctionCall
import prog8.ast.expressions.TypecastExpression import prog8.ast.expressions.TypecastExpression
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
import prog8.compiler.CompilerException import prog8.compilerinterface.CompilerException
import prog8.compiler.functions.BuiltinFunctions import prog8.compiler.functions.BuiltinFunctions
class VerifyFunctionArgTypes(val program: Program) : IAstVisitor { class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {

View File

@ -1,11 +1,11 @@
package prog8.compiler.functions package prog8.compiler.functions
import prog8.ast.IMemSizer
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.base.* import prog8.ast.base.*
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.VarDecl import prog8.ast.statements.VarDecl
import prog8.compiler.CompilerException import prog8.compilerinterface.CompilerException
import prog8.compiler.IMemSizer
import kotlin.math.* import kotlin.math.*

View File

@ -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<Short> {
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<Short>, 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
}
}
}

View File

@ -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<Short> {
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<Short>, 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
}
}
}

View File

@ -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
}

View File

@ -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<Short>
override fun decodeString(bytes: List<Short>, altEncoding: Boolean): String
}
internal object C64Target: ICompilationTarget {
override val name = "c64"
override val machine = C64MachineDefinition
override fun encodeString(str: String, altEncoding: Boolean): List<Short> {
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<Short>, 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<Short> {
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<Short>, 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)
}

View File

@ -1,10 +1,8 @@
package prog8.compiler.target.c64 package prog8.compiler.target.c64
import prog8.compiler.* 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.compiler.target.cbm.viceMonListPostfix
import prog8.compilerinterface.*
import java.io.IOException import java.io.IOException
import java.nio.file.Path import java.nio.file.Path
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
@ -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 { companion object {
val zero = Mflpt5(0, 0, 0, 0, 0) val zero = Mflpt5(0, 0, 0, 0, 0)

View File

@ -1,9 +1,9 @@
package prog8.compiler.target.cbm package prog8.compiler.target.cbm
import prog8.compiler.CompilationOptions import prog8.compilerinterface.CompilationOptions
import prog8.compiler.OutputType import prog8.compilerinterface.IAssemblyProgram
import prog8.compiler.target.IAssemblyProgram import prog8.compilerinterface.OutputType
import prog8.compiler.target.generatedLabelPrefix import prog8.compilerinterface.generatedLabelPrefix
import java.nio.file.Path import java.nio.file.Path

View File

@ -13,6 +13,7 @@ import prog8.compiler.target.*
import prog8.compiler.target.cbm.AssemblyProgram import prog8.compiler.target.cbm.AssemblyProgram
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment
import prog8.compiler.target.cpu6502.codegen.assignment.AssignmentAsmGen import prog8.compiler.target.cpu6502.codegen.assignment.AssignmentAsmGen
import prog8.compilerinterface.*
import prog8.optimizer.CallGraph import prog8.optimizer.CallGraph
import prog8.parser.SourceCode import prog8.parser.SourceCode
import java.nio.file.Path import java.nio.file.Path

View File

@ -11,11 +11,11 @@ import prog8.ast.statements.FunctionCallStatement
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.toHex import prog8.ast.toHex
import prog8.compiler.AssemblyError import prog8.compiler.AssemblyError
import prog8.compilerinterface.CpuType
import prog8.compiler.functions.FSignature import prog8.compiler.functions.FSignature
import prog8.compiler.target.CpuType
import prog8.compiler.target.Cx16Target import prog8.compiler.target.Cx16Target
import prog8.compiler.target.cpu6502.codegen.assignment.* 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) { 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) && (firstOffset is NumericLiteralValue || firstOffset is IdentifierReference || firstOffset is TypecastExpression)
&& (secondOffset is NumericLiteralValue || secondOffset is IdentifierReference || secondOffset 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 is NumericLiteralValue && secondOffset is NumericLiteralValue) {
if(firstOffset!=secondOffset) { if(firstOffset!=secondOffset) {
swapArrayValues( swapArrayValues(

View File

@ -8,9 +8,9 @@ import prog8.ast.statements.BuiltinFunctionStatementPlaceholder
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.toHex import prog8.ast.toHex
import prog8.compiler.AssemblyError import prog8.compiler.AssemblyError
import prog8.compilerinterface.CpuType
import prog8.compiler.functions.BuiltinFunctions import prog8.compiler.functions.BuiltinFunctions
import prog8.compiler.target.CpuType import prog8.compilerinterface.subroutineFloatEvalResultVar1
import prog8.compiler.target.subroutineFloatEvalResultVar1
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
internal class ExpressionsAsmGen(private val program: Program, private val asmgen: AsmGen) { internal class ExpressionsAsmGen(private val program: Program, private val asmgen: AsmGen) {

View File

@ -9,7 +9,7 @@ import prog8.ast.expressions.RangeExpr
import prog8.ast.statements.ForLoop import prog8.ast.statements.ForLoop
import prog8.ast.toHex import prog8.ast.toHex
import prog8.compiler.AssemblyError import prog8.compiler.AssemblyError
import prog8.compiler.astprocessing.toConstantIntegerRange import prog8.compilerinterface.toConstantIntegerRange
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) { internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) {

View File

@ -10,7 +10,7 @@ import prog8.ast.statements.RegisterOrStatusflag
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.statements.SubroutineParameter import prog8.ast.statements.SubroutineParameter
import prog8.compiler.AssemblyError 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.AsmAssignSource
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment

View File

@ -1,11 +1,11 @@
package prog8.compiler.target.cpu6502.codegen.assignment package prog8.compiler.target.cpu6502.codegen.assignment
import prog8.ast.IMemSizer
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.base.* import prog8.ast.base.*
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.compiler.AssemblyError import prog8.compiler.AssemblyError
import prog8.compiler.IMemSizer
import prog8.compiler.target.cpu6502.codegen.AsmGen import prog8.compiler.target.cpu6502.codegen.AsmGen

View File

@ -6,9 +6,9 @@ import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.toHex import prog8.ast.toHex
import prog8.compiler.AssemblyError import prog8.compiler.AssemblyError
import prog8.compilerinterface.CpuType
import prog8.compiler.functions.BuiltinFunctions import prog8.compiler.functions.BuiltinFunctions
import prog8.compiler.functions.builtinFunctionReturnType import prog8.compiler.functions.builtinFunctionReturnType
import prog8.compiler.target.CpuType
import prog8.compiler.target.cpu6502.codegen.AsmGen import prog8.compiler.target.cpu6502.codegen.AsmGen
import prog8.compiler.target.cpu6502.codegen.ExpressionsAsmGen import prog8.compiler.target.cpu6502.codegen.ExpressionsAsmGen

View File

@ -6,7 +6,7 @@ import prog8.ast.expressions.*
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.toHex import prog8.ast.toHex
import prog8.compiler.AssemblyError 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.AsmGen
import prog8.compiler.target.cpu6502.codegen.ExpressionsAsmGen import prog8.compiler.target.cpu6502.codegen.ExpressionsAsmGen

View File

@ -1,13 +1,13 @@
package prog8.compiler.target.cx16 package prog8.compiler.target.cx16
import prog8.compiler.* import prog8.compiler.*
import prog8.compiler.target.CpuType
import prog8.compiler.target.IMachineDefinition
import prog8.compiler.target.c64.C64MachineDefinition import prog8.compiler.target.c64.C64MachineDefinition
import prog8.compiler.target.cbm.viceMonListPostfix import prog8.compiler.target.cbm.viceMonListPostfix
import prog8.compilerinterface.*
import java.io.IOException import java.io.IOException
import java.nio.file.Path import java.nio.file.Path
internal object CX16MachineDefinition: IMachineDefinition { internal object CX16MachineDefinition: IMachineDefinition {
override val cpu = CpuType.CPU65c02 override val cpu = CpuType.CPU65c02

View File

@ -18,6 +18,10 @@ import prog8.compiler.*
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target
import prog8.compiler.target.c64.C64MachineDefinition import prog8.compiler.target.c64.C64MachineDefinition
import prog8.compiler.target.cpu6502.codegen.AsmGen 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 prog8.parser.SourceCode
import prog8tests.helpers.DummyFunctions import prog8tests.helpers.DummyFunctions
import prog8tests.helpers.DummyMemsizer import prog8tests.helpers.DummyMemsizer

View File

@ -9,7 +9,7 @@ import org.hamcrest.core.Is
import org.junit.jupiter.api.* import org.junit.jupiter.api.*
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.internedStringsModuleName import prog8.ast.internedStringsModuleName
import prog8.compiler.IErrorReporter import prog8.compilerinterface.IErrorReporter
import prog8.compiler.ModuleImporter import prog8.compiler.ModuleImporter
import prog8.parser.ParseError import prog8.parser.ParseError
import prog8.parser.SourceCode import prog8.parser.SourceCode

View File

@ -4,10 +4,10 @@ import org.junit.jupiter.api.DynamicTest
import org.junit.jupiter.api.DynamicTest.dynamicTest import org.junit.jupiter.api.DynamicTest.dynamicTest
import org.junit.jupiter.api.TestFactory import org.junit.jupiter.api.TestFactory
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
import prog8.compilerinterface.ICompilationTarget
import prog8.compiler.compileProgram import prog8.compiler.compileProgram
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target
import prog8.compiler.target.Cx16Target import prog8.compiler.target.Cx16Target
import prog8.compiler.target.ICompilationTarget
import prog8tests.helpers.* import prog8tests.helpers.*
import kotlin.io.path.absolute import kotlin.io.path.absolute
import kotlin.io.path.exists import kotlin.io.path.exists

View File

@ -9,10 +9,10 @@ import prog8.ast.expressions.*
import prog8.ast.statements.ForLoop import prog8.ast.statements.ForLoop
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.statements.VarDecl import prog8.ast.statements.VarDecl
import prog8.compiler.astprocessing.size import prog8.compilerinterface.size
import prog8.compiler.astprocessing.toConstantIntegerRange
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target
import prog8.compiler.target.Cx16Target import prog8.compiler.target.Cx16Target
import prog8.compilerinterface.toConstantIntegerRange
import prog8tests.helpers.* import prog8tests.helpers.*
import kotlin.test.assertContains import kotlin.test.assertContains
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
import prog8.ast.internedStringsModuleName import prog8.ast.internedStringsModuleName
import prog8.compiler.ErrorReporter import prog8.compiler.ErrorReporter
import prog8.compiler.ZeropageType import prog8.compilerinterface.ZeropageType
import prog8.compiler.determineCompilationOptions import prog8.compiler.determineCompilationOptions
import prog8.compiler.parseImports import prog8.compiler.parseImports
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target

View File

@ -12,7 +12,7 @@ import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.expressions.PrefixExpression import prog8.ast.expressions.PrefixExpression
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.compiler.astprocessing.isInRegularRAMof import prog8.compilerinterface.isInRegularRAMof
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target
import prog8.parser.SourceCode import prog8.parser.SourceCode
import prog8tests.helpers.DummyFunctions import prog8tests.helpers.DummyFunctions

View File

@ -6,7 +6,7 @@ import org.hamcrest.Matchers.equalTo
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
import prog8.ast.toHex 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_NEGATIVE
import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_POSITIVE import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_POSITIVE
import prog8.compiler.target.c64.C64MachineDefinition.Mflpt5 import prog8.compiler.target.c64.C64MachineDefinition.Mflpt5

View File

@ -8,6 +8,7 @@ import prog8.compiler.target.C64Target
import prog8.compiler.target.Cx16Target import prog8.compiler.target.Cx16Target
import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage
import prog8.compiler.target.cx16.CX16MachineDefinition.CX16Zeropage import prog8.compiler.target.cx16.CX16MachineDefinition.CX16Zeropage
import prog8.compilerinterface.*
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
import kotlin.test.assertFalse import kotlin.test.assertFalse

View File

@ -1,7 +1,7 @@
package prog8tests.helpers package prog8tests.helpers
import prog8.ast.base.Position import prog8.ast.base.Position
import prog8.compiler.IErrorReporter import prog8.compilerinterface.IErrorReporter
class ErrorReporterForTests(private val throwExceptionAtReportIfErrors: Boolean=true): IErrorReporter { class ErrorReporterForTests(private val throwExceptionAtReportIfErrors: Boolean=true): IErrorReporter {

View File

@ -1,10 +1,8 @@
package prog8tests.helpers package prog8tests.helpers
import prog8.compiler.CompilationResult import prog8.compiler.*
import prog8.compiler.ErrorReporter import prog8.compilerinterface.ICompilationTarget
import prog8.compiler.IErrorReporter import prog8.compilerinterface.IErrorReporter
import prog8.compiler.compileProgram
import prog8.compiler.target.ICompilationTarget
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.name import kotlin.io.path.name
import kotlin.test.assertFalse import kotlin.test.assertFalse

View File

@ -7,6 +7,7 @@ import prog8.ast.expressions.StringLiteralValue
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
import prog8.compiler.IMemSizer
import prog8.parser.SourceCode import prog8.parser.SourceCode
const val internedStringsModuleName = "prog8_interned_strings" const val internedStringsModuleName = "prog8_interned_strings"
@ -286,7 +287,8 @@ interface Node {
class Program(val name: String, class Program(val name: String,
val builtinFunctions: IBuiltinFunctions, val builtinFunctions: IBuiltinFunctions,
val memsizer: IMemSizer): Node { val memsizer: IMemSizer
): Node {
private val _modules = mutableListOf<Module>() private val _modules = mutableListOf<Module>()
val modules: List<Module> = _modules val modules: List<Module> = _modules

View File

@ -4,6 +4,7 @@ import prog8.ast.base.Position
import prog8.ast.expressions.Expression import prog8.ast.expressions.Expression
import prog8.ast.expressions.InferredTypes import prog8.ast.expressions.InferredTypes
import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.NumericLiteralValue
import prog8.compiler.IMemSizer
interface IBuiltinFunctions { interface IBuiltinFunctions {
val names: Set<String> val names: Set<String>

View File

@ -6,6 +6,7 @@ import prog8.ast.base.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
import prog8.compiler.IMemSizer
import java.util.* import java.util.*

View File

@ -1,4 +1,4 @@
package prog8.ast package prog8.compiler
import prog8.ast.base.DataType import prog8.ast.base.DataType

View File

@ -1,11 +1,11 @@
package prog8tests.helpers package prog8tests.helpers
import prog8.ast.IBuiltinFunctions import prog8.ast.IBuiltinFunctions
import prog8.ast.IMemSizer
import prog8.ast.base.Position import prog8.ast.base.Position
import prog8.ast.expressions.Expression import prog8.ast.expressions.Expression
import prog8.ast.expressions.InferredTypes import prog8.ast.expressions.InferredTypes
import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.NumericLiteralValue
import prog8.compiler.IMemSizer
val DummyFunctions = object : IBuiltinFunctions { val DummyFunctions = object : IBuiltinFunctions {
override val names: Set<String> = emptySet() override val names: Set<String> = emptySet()

View File

@ -1,7 +1,7 @@
package prog8tests.helpers package prog8tests.helpers
import prog8.ast.IMemSizer
import prog8.ast.base.DataType import prog8.ast.base.DataType
import prog8.compiler.IMemSizer
val DummyMemsizer = object : IMemSizer { val DummyMemsizer = object : IMemSizer {
override fun memorySize(dt: DataType): Int = 0 override fun memorySize(dt: DataType): Int = 0

View File

@ -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"
}
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="openjdk-11" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="KotlinJavaRuntime (3)" level="project" />
<orderEntry type="module" module-name="compilerAst" />
</component>
</module>

View File

@ -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()
}

View File

@ -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<IntRange>,
val floats: Boolean,
val noSysInit: Boolean,
val compTarget: ICompilationTarget
) {
var slowCodegenWarnings = false
var optimize = false
}

View File

@ -0,0 +1,3 @@
package prog8.compilerinterface
class CompilerException(message: String?) : Exception(message)

View File

@ -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
}

View File

@ -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<Short>
override fun decodeString(bytes: List<Short>, altEncoding: Boolean): String
}

View File

@ -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.")
}
}

View File

@ -1,7 +1,5 @@
package prog8.compiler.target package prog8.compilerinterface
import prog8.compiler.CompilationOptions
import prog8.compiler.Zeropage
import java.nio.file.Path import java.nio.file.Path

View File

@ -1,4 +1,4 @@
package prog8.compiler package prog8.compilerinterface
interface IStringEncoding { interface IStringEncoding {
fun encodeString(str: String, altEncoding: Boolean): List<Short> fun encodeString(str: String, altEncoding: Boolean): List<Short>

View File

@ -1,4 +1,4 @@
package prog8.compiler package prog8.compilerinterface
import prog8.ast.base.* import prog8.ast.base.*

View File

@ -27,7 +27,6 @@ Future
- add a diskio.f_seek() routine for the Cx16 that uses its seek dos api? - 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)? - 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 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_`` - 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 ... - [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? Perhaps replace all uses of .proc/.pend by .block/.bend will fix that?

View File

@ -16,6 +16,7 @@ repositories {
} }
dependencies { dependencies {
implementation project(':compilerInterfaces')
implementation project(':compiler') implementation project(':compiler')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect" // implementation "org.jetbrains.kotlin:kotlin-reflect"

View File

@ -14,5 +14,6 @@
<orderEntry type="library" name="glassfish.javax.json" level="project" /> <orderEntry type="library" name="glassfish.javax.json" level="project" />
<orderEntry type="library" name="takes" level="project" /> <orderEntry type="library" name="takes" level="project" />
<orderEntry type="library" name="slf4j.simple" level="project" /> <orderEntry type="library" name="slf4j.simple" level="project" />
<orderEntry type="module" module-name="compilerInterfaces" />
</component> </component>
</module> </module>

View File

@ -1,5 +1,7 @@
include ':parser' include ':parser'
include ':compilerInterfaces'
include ':compilerAst' include ':compilerAst'
include ':codeOptimizers'
include ':compiler' include ':compiler'
include ':dbusCompilerService' include ':dbusCompilerService'
include ':httpCompilerService' include ':httpCompilerService'