mirror of
https://github.com/irmen/prog8.git
synced 2024-11-25 19:31:36 +00:00
split out the code generator into own project submodule
This commit is contained in:
parent
82da8f4946
commit
0b5ddcdc9b
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@ -2,6 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/codeGeneration/codeGeneration.iml" filepath="$PROJECT_DIR$/codeGeneration/codeGeneration.iml" />
|
||||
<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$/compilerAst/compilerAst.iml" filepath="$PROJECT_DIR$/compilerAst/compilerAst.iml" />
|
||||
|
73
codeGeneration/build.gradle
Normal file
73
codeGeneration/build.gradle
Normal file
@ -0,0 +1,73 @@
|
||||
|
||||
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"
|
||||
implementation "com.michael-bull.kotlin-result:kotlin-result-jvm:1.1.12"
|
||||
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-test-junit5"
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2'
|
||||
testImplementation 'org.hamcrest:hamcrest:2.2'
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
|
||||
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
18
codeGeneration/codeGeneration.iml
Normal file
18
codeGeneration/codeGeneration.iml
Normal file
@ -0,0 +1,18 @@
|
||||
<?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" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="openjdk-11" jdkType="JavaSDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
<orderEntry type="library" name="michael.bull.kotlin.result.jvm" level="project" />
|
||||
<orderEntry type="module" module-name="compilerInterfaces" />
|
||||
<orderEntry type="module" module-name="compilerAst" />
|
||||
<orderEntry type="library" scope="TEST" name="hamcrest" level="project" />
|
||||
<orderEntry type="library" name="junit.jupiter" level="project" />
|
||||
</component>
|
||||
</module>
|
@ -0,0 +1,3 @@
|
||||
package prog8.compiler.target
|
||||
|
||||
class AssemblyError(msg: String) : RuntimeException(msg)
|
@ -10,7 +10,7 @@ import prog8.compiler.target.cbm.Petscii
|
||||
import prog8.compilerinterface.*
|
||||
|
||||
|
||||
internal object C64Target: ICompilationTarget {
|
||||
object C64Target: ICompilationTarget {
|
||||
override val name = "c64"
|
||||
override val machine = C64MachineDefinition
|
||||
override fun encodeString(str: String, altEncoding: Boolean): List<Short> {
|
@ -10,7 +10,7 @@ import prog8.compiler.target.cx16.CX16MachineDefinition
|
||||
import prog8.compilerinterface.*
|
||||
|
||||
|
||||
internal object Cx16Target: ICompilationTarget {
|
||||
object Cx16Target: ICompilationTarget {
|
||||
override val name = "cx16"
|
||||
override val machine = CX16MachineDefinition
|
||||
override fun encodeString(str: String, altEncoding: Boolean): List<Short> {
|
@ -1,6 +1,5 @@
|
||||
package prog8.compiler.target.c64
|
||||
|
||||
import prog8.compiler.*
|
||||
import prog8.compiler.target.cbm.viceMonListPostfix
|
||||
import prog8.compilerinterface.*
|
||||
import java.io.IOException
|
||||
@ -8,7 +7,7 @@ import java.nio.file.Path
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.pow
|
||||
|
||||
internal object C64MachineDefinition: IMachineDefinition {
|
||||
object C64MachineDefinition: IMachineDefinition {
|
||||
|
||||
override val cpu = CpuType.CPU6502
|
||||
|
||||
@ -75,7 +74,7 @@ internal object C64MachineDefinition: IMachineDefinition {
|
||||
"sta", "stx", "sty", "tas", "tax", "tay", "tsx", "txa", "txs", "tya", "xaa")
|
||||
|
||||
|
||||
internal class C64Zeropage(options: CompilationOptions) : Zeropage(options) {
|
||||
class C64Zeropage(options: CompilationOptions) : Zeropage(options) {
|
||||
|
||||
override val SCRATCH_B1 = 0x02 // temp storage for a single byte
|
||||
override val SCRATCH_REG = 0x03 // temp storage for a register, must be B1+1
|
||||
@ -144,7 +143,7 @@ internal object C64MachineDefinition: IMachineDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
internal data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, val b4: Short):
|
||||
data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, val b4: Short):
|
||||
IMachineFloat {
|
||||
|
||||
companion object {
|
@ -1,10 +1,17 @@
|
||||
package prog8.compiler.target.cbm
|
||||
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
import com.github.michaelbull.result.mapError
|
||||
import prog8.compilerinterface.CompilationOptions
|
||||
import prog8.compilerinterface.IAssemblyProgram
|
||||
import prog8.compilerinterface.OutputType
|
||||
import prog8.compilerinterface.generatedLabelPrefix
|
||||
import prog8.parser.SourceCode
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.isRegularFile
|
||||
|
||||
|
||||
internal const val viceMonListPostfix = "vice-mon-list"
|
||||
@ -76,3 +83,18 @@ class AssemblyProgram(
|
||||
viceMonListFile.toFile().appendText(breakpoints.joinToString("\n") + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal fun loadAsmIncludeFile(filename: String, source: SourceCode): Result<String, NoSuchFileException> {
|
||||
return if (filename.startsWith(SourceCode.libraryFilePrefix)) {
|
||||
return com.github.michaelbull.result.runCatching {
|
||||
SourceCode.Resource("/prog8lib/${filename.substring(SourceCode.libraryFilePrefix.length)}").readText()
|
||||
}.mapError { NoSuchFileException(File(filename)) }
|
||||
} else {
|
||||
val sib = Path(source.origin).resolveSibling(filename)
|
||||
if (sib.isRegularFile())
|
||||
Ok(SourceCode.File(sib).readText())
|
||||
else
|
||||
Ok(SourceCode.File(Path(filename)).readText())
|
||||
}
|
||||
}
|
@ -1098,7 +1098,7 @@ object Petscii {
|
||||
fun decodePetscii(petscii: Iterable<Short>, lowercase: Boolean = false): String {
|
||||
return petscii.map {
|
||||
val code = it.toInt()
|
||||
if(code<0 || code>=decodingPetsciiLowercase.size)
|
||||
if(code<0 || code>= decodingPetsciiLowercase.size)
|
||||
throw CharConversionException("petscii $code out of range 0..${decodingPetsciiLowercase.size-1}")
|
||||
if(lowercase) decodingPetsciiLowercase[code] else decodingPetsciiUppercase[code]
|
||||
}.joinToString("")
|
||||
@ -1137,7 +1137,7 @@ object Petscii {
|
||||
fun decodeScreencode(screencode: Iterable<Short>, lowercase: Boolean = false): String {
|
||||
return screencode.map {
|
||||
val code = it.toInt()
|
||||
if(code<0 || code>=decodingScreencodeLowercase.size)
|
||||
if(code<0 || code>= decodingScreencodeLowercase.size)
|
||||
throw CharConversionException("screencode $code out of range 0..${decodingScreencodeLowercase.size-1}")
|
||||
if (lowercase) decodingScreencodeLowercase[code] else decodingScreencodeUppercase[code]
|
||||
}.joinToString("")
|
@ -7,14 +7,12 @@ import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.compiler.*
|
||||
import prog8.compiler.functions.BuiltinFunctions
|
||||
import prog8.compiler.functions.FSignature
|
||||
import prog8.compiler.target.*
|
||||
import prog8.compiler.target.cbm.AssemblyProgram
|
||||
import prog8.compiler.target.cbm.loadAsmIncludeFile
|
||||
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
|
||||
import java.time.LocalDate
|
||||
@ -24,7 +22,7 @@ import kotlin.io.path.Path
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
|
||||
internal class AsmGen(private val program: Program,
|
||||
class AsmGen(private val program: Program,
|
||||
val errors: IErrorReporter,
|
||||
val zeropage: Zeropage,
|
||||
val options: CompilationOptions,
|
||||
@ -275,7 +273,7 @@ internal class AsmGen(private val program: Program,
|
||||
&& variable.datatype != DataType.FLOAT
|
||||
&& options.zeropage != ZeropageType.DONTUSE) {
|
||||
try {
|
||||
val errors = ErrorReporter()
|
||||
val errors = ErrorReporter() // TODO why not just use this.errors? then we can clean up the visibility of ErrorReporter class again too
|
||||
val address = zeropage.allocate(fullName, variable.datatype, null, errors)
|
||||
errors.report()
|
||||
out("${variable.name} = $address\t; auto zp ${variable.datatype}")
|
||||
@ -500,7 +498,7 @@ internal class AsmGen(private val program: Program,
|
||||
return newName
|
||||
}
|
||||
|
||||
internal fun asmSymbolName(identifier: IdentifierReference): String {
|
||||
fun asmSymbolName(identifier: IdentifierReference): String {
|
||||
if(identifier.nameInSource.size==2 && identifier.nameInSource[0]=="prog8_slabs")
|
||||
return identifier.nameInSource.joinToString(".")
|
||||
|
||||
@ -531,7 +529,7 @@ internal class AsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
internal fun asmVariableName(identifier: IdentifierReference) =
|
||||
fun asmVariableName(identifier: IdentifierReference) =
|
||||
fixNameSymbols(identifier.nameInSource.joinToString("."))
|
||||
|
||||
private fun getScopedSymbolNameForTarget(actualName: String, target: Statement): MutableList<String> {
|
||||
@ -546,16 +544,16 @@ internal class AsmGen(private val program: Program,
|
||||
return scopedName
|
||||
}
|
||||
|
||||
internal fun asmSymbolName(regs: RegisterOrPair): String =
|
||||
fun asmSymbolName(regs: RegisterOrPair): String =
|
||||
if (regs in Cx16VirtualRegisters)
|
||||
"cx16." + regs.toString().lowercase()
|
||||
else
|
||||
throw AssemblyError("no symbol name for register $regs")
|
||||
|
||||
internal fun asmSymbolName(name: String) = fixNameSymbols(name)
|
||||
internal fun asmVariableName(name: String) = fixNameSymbols(name)
|
||||
internal fun asmSymbolName(name: Iterable<String>) = fixNameSymbols(name.joinToString("."))
|
||||
internal fun asmVariableName(name: Iterable<String>) = fixNameSymbols(name.joinToString("."))
|
||||
fun asmSymbolName(name: String) = fixNameSymbols(name)
|
||||
fun asmVariableName(name: String) = fixNameSymbols(name)
|
||||
fun asmSymbolName(name: Iterable<String>) = fixNameSymbols(name.joinToString("."))
|
||||
fun asmVariableName(name: Iterable<String>) = fixNameSymbols(name.joinToString("."))
|
||||
|
||||
|
||||
internal fun loadByteFromPointerIntoA(pointervar: IdentifierReference): String {
|
@ -10,11 +10,11 @@ import prog8.ast.statements.DirectMemoryWrite
|
||||
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.AssemblyError
|
||||
import prog8.compiler.target.Cx16Target
|
||||
import prog8.compiler.target.cpu6502.codegen.assignment.*
|
||||
import prog8.compilerinterface.FSignature
|
||||
import prog8.compilerinterface.subroutineFloatEvalResultVar2
|
||||
|
||||
internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val assignAsmGen: AssignmentAsmGen) {
|
||||
@ -1532,7 +1532,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
||||
AsmAssignSource.fromAstSource(value, program, asmgen)
|
||||
}
|
||||
}
|
||||
val tgt = AsmAssignTarget.fromRegisters(conv.reg, null, program, asmgen)
|
||||
val tgt = AsmAssignTarget.fromRegisters(conv.reg!!, null, program, asmgen)
|
||||
val assign = AsmAssignment(src, tgt, false, program.memsizer, value.position)
|
||||
asmgen.translateNormalAssignment(assign)
|
||||
}
|
@ -7,9 +7,9 @@ import prog8.ast.statements.ArrayIndex
|
||||
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.AssemblyError
|
||||
import prog8.compilerinterface.BuiltinFunctions
|
||||
import prog8.compilerinterface.subroutineFloatEvalResultVar1
|
||||
import kotlin.math.absoluteValue
|
||||
|
@ -8,7 +8,7 @@ import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.RangeExpr
|
||||
import prog8.ast.statements.ForLoop
|
||||
import prog8.ast.toHex
|
||||
import prog8.compiler.AssemblyError
|
||||
import prog8.compiler.target.AssemblyError
|
||||
import prog8.compilerinterface.toConstantIntegerRange
|
||||
import kotlin.math.absoluteValue
|
||||
|
@ -9,7 +9,7 @@ import prog8.ast.statements.InlineAssembly
|
||||
import prog8.ast.statements.RegisterOrStatusflag
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.ast.statements.SubroutineParameter
|
||||
import prog8.compiler.AssemblyError
|
||||
import prog8.compiler.target.AssemblyError
|
||||
import prog8.compilerinterface.CpuType
|
||||
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignSource
|
||||
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget
|
@ -6,7 +6,7 @@ import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.NumericLiteralValue
|
||||
import prog8.ast.statements.PostIncrDecr
|
||||
import prog8.ast.toHex
|
||||
import prog8.compiler.AssemblyError
|
||||
import prog8.compiler.target.AssemblyError
|
||||
|
||||
|
||||
internal class PostIncrDecrAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
@ -4,8 +4,8 @@ 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.AssemblyError
|
||||
import prog8.compiler.target.cpu6502.codegen.AsmGen
|
||||
|
||||
|
||||
@ -61,9 +61,9 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
|
||||
throw AssemblyError("unknown dt")
|
||||
val dt = idt.getOr(DataType.UNDEFINED)
|
||||
when {
|
||||
identifier != null -> AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, dt, assign.definingSubroutine, variableAsmName = asmgen.asmVariableName(identifier!!), origAstTarget = this)
|
||||
arrayindexed != null -> AsmAssignTarget(TargetStorageKind.ARRAY, program, asmgen, dt, assign.definingSubroutine, array = arrayindexed, origAstTarget = this)
|
||||
memoryAddress != null -> AsmAssignTarget(TargetStorageKind.MEMORY, program, asmgen, dt, assign.definingSubroutine, memory = memoryAddress, origAstTarget = this)
|
||||
identifier != null -> AsmAssignTarget(prog8.compiler.target.cpu6502.codegen.assignment.TargetStorageKind.VARIABLE, program, asmgen, dt, assign.definingSubroutine, variableAsmName = asmgen.asmVariableName(identifier!!), origAstTarget = this)
|
||||
arrayindexed != null -> AsmAssignTarget(prog8.compiler.target.cpu6502.codegen.assignment.TargetStorageKind.ARRAY, program, asmgen, dt, assign.definingSubroutine, array = arrayindexed, origAstTarget = this)
|
||||
memoryAddress != null -> AsmAssignTarget(prog8.compiler.target.cpu6502.codegen.assignment.TargetStorageKind.MEMORY, program, asmgen, dt, assign.definingSubroutine, memory = memoryAddress, origAstTarget = this)
|
||||
else -> throw AssemblyError("weird target")
|
||||
}
|
||||
}
|
@ -5,12 +5,12 @@ import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.toHex
|
||||
import prog8.compiler.AssemblyError
|
||||
import prog8.compiler.target.AssemblyError
|
||||
import prog8.compilerinterface.CpuType
|
||||
import prog8.compiler.functions.BuiltinFunctions
|
||||
import prog8.compiler.functions.builtinFunctionReturnType
|
||||
import prog8.compiler.target.cpu6502.codegen.AsmGen
|
||||
import prog8.compiler.target.cpu6502.codegen.ExpressionsAsmGen
|
||||
import prog8.compilerinterface.BuiltinFunctions
|
||||
import prog8.compilerinterface.builtinFunctionReturnType
|
||||
|
||||
|
||||
internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen,
|
||||
@ -21,7 +21,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
|
||||
fun translate(assignment: Assignment) {
|
||||
val target = AsmAssignTarget.fromAstAssignment(assignment, program, asmgen)
|
||||
val source = AsmAssignSource.fromAstSource(assignment.value, program, asmgen).adjustSignedUnsigned(target)
|
||||
val source = AsmAssignSource.Companion.fromAstSource(assignment.value, program, asmgen).adjustSignedUnsigned(target)
|
||||
|
||||
val assign = AsmAssignment(source, target, assignment.isAugmentable, program.memsizer, assignment.position)
|
||||
target.origAssign = assign
|
||||
@ -1363,7 +1363,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
// these will be correctly typecasted from a byte to a word value
|
||||
if(target.register !in Cx16VirtualRegisters &&
|
||||
target.register!=RegisterOrPair.AX && target.register!=RegisterOrPair.AY && target.register!=RegisterOrPair.XY) {
|
||||
if(target.kind==TargetStorageKind.VARIABLE) {
|
||||
if(target.kind== TargetStorageKind.VARIABLE) {
|
||||
val parts = target.asmVarname.split('.')
|
||||
if (parts.size != 2 || parts[0] != "cx16")
|
||||
require(target.datatype in ByteDatatypes)
|
||||
@ -2158,14 +2158,14 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
}
|
||||
|
||||
internal fun assignExpressionToRegister(expr: Expression, register: RegisterOrPair) {
|
||||
val src = AsmAssignSource.fromAstSource(expr, program, asmgen)
|
||||
val src = AsmAssignSource.Companion.fromAstSource(expr, program, asmgen)
|
||||
val tgt = AsmAssignTarget.fromRegisters(register, null, program, asmgen)
|
||||
val assign = AsmAssignment(src, tgt, false, program.memsizer, expr.position)
|
||||
translateNormalAssignment(assign)
|
||||
}
|
||||
|
||||
internal fun assignExpressionToVariable(expr: Expression, asmVarName: String, dt: DataType, scope: Subroutine?) {
|
||||
val src = AsmAssignSource.fromAstSource(expr, program, asmgen)
|
||||
val src = AsmAssignSource.Companion.fromAstSource(expr, program, asmgen)
|
||||
val tgt = AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, dt, scope, variableAsmName = asmVarName)
|
||||
val assign = AsmAssignment(src, tgt, false, program.memsizer, expr.position)
|
||||
translateNormalAssignment(assign)
|
@ -5,7 +5,7 @@ import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.ast.toHex
|
||||
import prog8.compiler.AssemblyError
|
||||
import prog8.compiler.target.AssemblyError
|
||||
import prog8.compilerinterface.CpuType
|
||||
import prog8.compiler.target.cpu6502.codegen.AsmGen
|
||||
import prog8.compiler.target.cpu6502.codegen.ExpressionsAsmGen
|
||||
@ -246,19 +246,37 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
indexVar!=null -> {
|
||||
when (target.datatype) {
|
||||
in ByteDatatypes -> {
|
||||
val tgt = AsmAssignTarget.fromRegisters(RegisterOrPair.A, null, program, asmgen)
|
||||
val tgt =
|
||||
prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget.fromRegisters(
|
||||
RegisterOrPair.A,
|
||||
null,
|
||||
program,
|
||||
asmgen
|
||||
)
|
||||
val assign = AsmAssignment(target.origAssign.source, tgt, false, program.memsizer, value.position)
|
||||
assignmentAsmGen.translateNormalAssignment(assign)
|
||||
assignmentAsmGen.assignRegisterByte(target, CpuRegister.A)
|
||||
}
|
||||
in WordDatatypes -> {
|
||||
val tgt = AsmAssignTarget.fromRegisters(RegisterOrPair.AY, null, program, asmgen)
|
||||
val tgt =
|
||||
prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget.fromRegisters(
|
||||
RegisterOrPair.AY,
|
||||
null,
|
||||
program,
|
||||
asmgen
|
||||
)
|
||||
val assign = AsmAssignment(target.origAssign.source, tgt, false, program.memsizer, value.position)
|
||||
assignmentAsmGen.translateNormalAssignment(assign)
|
||||
assignmentAsmGen.assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
val tgt = AsmAssignTarget.fromRegisters(RegisterOrPair.FAC1, null, program, asmgen)
|
||||
val tgt =
|
||||
prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget.fromRegisters(
|
||||
RegisterOrPair.FAC1,
|
||||
null,
|
||||
program,
|
||||
asmgen
|
||||
)
|
||||
val assign = AsmAssignment(target.origAssign.source, tgt, false, program.memsizer, value.position)
|
||||
assignmentAsmGen.translateNormalAssignment(assign)
|
||||
assignmentAsmGen.assignFAC1float(target)
|
@ -8,7 +8,7 @@ import java.io.IOException
|
||||
import java.nio.file.Path
|
||||
|
||||
|
||||
internal object CX16MachineDefinition: IMachineDefinition {
|
||||
object CX16MachineDefinition: IMachineDefinition {
|
||||
|
||||
override val cpu = CpuType.CPU65c02
|
||||
|
||||
@ -88,7 +88,7 @@ internal object CX16MachineDefinition: IMachineDefinition {
|
||||
"rmb", "smb", "stp", "wai")
|
||||
|
||||
|
||||
internal class CX16Zeropage(options: CompilationOptions) : Zeropage(options) {
|
||||
class CX16Zeropage(options: CompilationOptions) : Zeropage(options) {
|
||||
|
||||
override val SCRATCH_B1 = 0x7a // temp storage for a single byte
|
||||
override val SCRATCH_REG = 0x7b // temp storage for a register, must be B1+1
|
21
codeGeneration/test/TestCodeGeneration.kt
Normal file
21
codeGeneration/test/TestCodeGeneration.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package prog8tests
|
||||
|
||||
import org.junit.jupiter.api.Disabled
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class TestCodeGeneration {
|
||||
|
||||
@Test
|
||||
@Disabled("for future implementation")
|
||||
fun dummy() {
|
||||
fail("dummy")
|
||||
}
|
||||
|
||||
}
|
@ -9,6 +9,7 @@ import prog8.ast.expressions.TypecastExpression
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.compilerinterface.CallGraph
|
||||
import prog8.compilerinterface.ICompilationTarget
|
||||
import prog8.compilerinterface.IErrorReporter
|
||||
import prog8.compilerinterface.isInRegularRAMof
|
||||
|
@ -21,6 +21,7 @@ dependencies {
|
||||
implementation project(':compilerInterfaces')
|
||||
implementation project(':codeOptimizers')
|
||||
implementation project(':compilerAst')
|
||||
implementation project(':codeGeneration')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
||||
// implementation "org.jetbrains.kotlin:kotlin-reflect"
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-cli:0.3.3'
|
||||
|
@ -24,5 +24,6 @@
|
||||
<orderEntry type="library" name="michael.bull.kotlin.result.jvm" level="project" />
|
||||
<orderEntry type="module" module-name="codeOptimizers" />
|
||||
<orderEntry type="module" module-name="compilerInterfaces" />
|
||||
<orderEntry type="module" module-name="codeGeneration" />
|
||||
</component>
|
||||
</module>
|
@ -1,3 +0,0 @@
|
||||
package prog8.compiler
|
||||
|
||||
internal class AssemblyError(msg: String) : RuntimeException(msg)
|
@ -10,7 +10,6 @@ import prog8.ast.expressions.Expression
|
||||
import prog8.ast.expressions.NumericLiteralValue
|
||||
import prog8.ast.statements.Directive
|
||||
import prog8.compiler.astprocessing.*
|
||||
import prog8.compiler.functions.*
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.compiler.target.Cx16Target
|
||||
import prog8.compiler.target.cpu6502.codegen.AsmGen
|
||||
@ -18,12 +17,8 @@ import prog8.compilerinterface.*
|
||||
import prog8.optimizer.*
|
||||
import prog8.parser.ParseError
|
||||
import prog8.parser.ParsingFailedError
|
||||
import prog8.parser.SourceCode
|
||||
import prog8.parser.SourceCode.Companion.libraryFilePrefix
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.isRegularFile
|
||||
import kotlin.io.path.nameWithoutExtension
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
@ -351,20 +346,6 @@ fun printAst(programAst: Program) {
|
||||
println()
|
||||
}
|
||||
|
||||
internal fun loadAsmIncludeFile(filename: String, source: SourceCode): Result<String, NoSuchFileException> {
|
||||
return if (filename.startsWith(libraryFilePrefix)) {
|
||||
return runCatching {
|
||||
SourceCode.Resource("/prog8lib/${filename.substring(libraryFilePrefix.length)}").readText()
|
||||
}.mapError { NoSuchFileException(File(filename)) }
|
||||
} else {
|
||||
val sib = Path(source.origin).resolveSibling(filename)
|
||||
if (sib.isRegularFile())
|
||||
Ok(SourceCode.File(sib).readText())
|
||||
else
|
||||
Ok(SourceCode.File(Path(filename)).readText())
|
||||
}
|
||||
}
|
||||
|
||||
internal fun asmGeneratorFor(
|
||||
compTarget: ICompilationTarget,
|
||||
program: Program,
|
||||
|
@ -1,48 +0,0 @@
|
||||
package prog8.compiler
|
||||
|
||||
import prog8.ast.base.Position
|
||||
import prog8.compilerinterface.IErrorReporter
|
||||
|
||||
|
||||
internal class ErrorReporter: IErrorReporter {
|
||||
private enum class MessageSeverity {
|
||||
WARNING,
|
||||
ERROR
|
||||
}
|
||||
private class CompilerMessage(val severity: MessageSeverity, val message: String, val position: Position)
|
||||
|
||||
private val messages = mutableListOf<CompilerMessage>()
|
||||
private val alreadyReportedMessages = mutableSetOf<String>()
|
||||
|
||||
override fun err(msg: String, position: Position) {
|
||||
messages.add(CompilerMessage(MessageSeverity.ERROR, msg, position))
|
||||
}
|
||||
override fun warn(msg: String, position: Position) {
|
||||
messages.add(CompilerMessage(MessageSeverity.WARNING, msg, position))
|
||||
}
|
||||
|
||||
override fun report() {
|
||||
var numErrors = 0
|
||||
var numWarnings = 0
|
||||
messages.forEach {
|
||||
when(it.severity) {
|
||||
MessageSeverity.ERROR -> System.err.print("\u001b[91m") // bright red
|
||||
MessageSeverity.WARNING -> System.err.print("\u001b[93m") // bright yellow
|
||||
}
|
||||
val msg = "${it.position.toClickableStr()} ${it.severity} ${it.message}".trim()
|
||||
if(msg !in alreadyReportedMessages) {
|
||||
System.err.println(msg)
|
||||
alreadyReportedMessages.add(msg)
|
||||
when(it.severity) {
|
||||
MessageSeverity.WARNING -> numWarnings++
|
||||
MessageSeverity.ERROR -> numErrors++
|
||||
}
|
||||
}
|
||||
System.err.print("\u001b[0m") // reset color
|
||||
}
|
||||
messages.clear()
|
||||
finalizeNumErrors(numErrors, numWarnings)
|
||||
}
|
||||
|
||||
override fun noErrors() = messages.none { it.severity==MessageSeverity.ERROR }
|
||||
}
|
@ -8,12 +8,7 @@ import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.IAstVisitor
|
||||
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.compilerinterface.*
|
||||
import java.io.CharConversionException
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
@ -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.compilerinterface.BuiltinFunctions
|
||||
import prog8.compilerinterface.ICompilationTarget
|
||||
import prog8.compilerinterface.IErrorReporter
|
||||
import prog8.compiler.functions.BuiltinFunctions
|
||||
|
||||
internal class AstIdentifiersChecker(private val errors: IErrorReporter, private val compTarget: ICompilationTarget) : IAstVisitor {
|
||||
private var blocks = mutableMapOf<String, Block>()
|
||||
|
@ -10,8 +10,8 @@ import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.compilerinterface.BuiltinFunctions
|
||||
import prog8.compilerinterface.IErrorReporter
|
||||
import prog8.compiler.functions.BuiltinFunctions
|
||||
|
||||
|
||||
internal class StatementReorderer(val program: Program, val errors: IErrorReporter) : AstWalker() {
|
||||
|
@ -8,8 +8,8 @@ import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.compilerinterface.BuiltinFunctions
|
||||
import prog8.compilerinterface.IErrorReporter
|
||||
import prog8.compiler.functions.BuiltinFunctions
|
||||
|
||||
|
||||
class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalker() {
|
||||
|
@ -8,8 +8,8 @@ import prog8.ast.expressions.FunctionCall
|
||||
import prog8.ast.expressions.TypecastExpression
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.IAstVisitor
|
||||
import prog8.compilerinterface.BuiltinFunctions
|
||||
import prog8.compilerinterface.CompilerException
|
||||
import prog8.compiler.functions.BuiltinFunctions
|
||||
|
||||
class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {
|
||||
|
||||
|
@ -14,19 +14,17 @@ import prog8.ast.expressions.AddressOf
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.NumericLiteralValue
|
||||
import prog8.ast.statements.*
|
||||
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.compilerinterface.*
|
||||
import prog8.parser.SourceCode
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.ast.helpers.DummyFunctions
|
||||
import prog8tests.ast.helpers.DummyMemsizer
|
||||
import java.nio.file.Path
|
||||
|
||||
// TODO move to codegen project, readjust symbol protection levels
|
||||
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class TestAsmGen6502 {
|
||||
|
@ -13,6 +13,7 @@ import prog8.compilerinterface.IErrorReporter
|
||||
import prog8.compiler.ModuleImporter
|
||||
import prog8.parser.ParseError
|
||||
import prog8.parser.SourceCode
|
||||
import prog8tests.ast.helpers.*
|
||||
import prog8tests.helpers.*
|
||||
import kotlin.io.path.*
|
||||
import kotlin.test.assertContains
|
||||
|
@ -5,7 +5,7 @@ import org.junit.jupiter.api.TestInstance
|
||||
import prog8.ast.statements.Block
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.optimizer.CallGraph
|
||||
import prog8.compilerinterface.CallGraph
|
||||
import prog8tests.helpers.assertSuccess
|
||||
import prog8tests.helpers.compileText
|
||||
import kotlin.test.assertEquals
|
||||
|
@ -8,6 +8,10 @@ import prog8.compilerinterface.ICompilationTarget
|
||||
import prog8.compiler.compileProgram
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.compiler.target.Cx16Target
|
||||
import prog8tests.ast.helpers.assumeDirectory
|
||||
import prog8tests.ast.helpers.mapCombinations
|
||||
import prog8tests.ast.helpers.outputDir
|
||||
import prog8tests.ast.helpers.workingDir
|
||||
import prog8tests.helpers.*
|
||||
import kotlin.io.path.absolute
|
||||
import kotlin.io.path.exists
|
||||
|
@ -8,6 +8,7 @@ import prog8.ast.expressions.StringLiteralValue
|
||||
import prog8.ast.statements.FunctionCallStatement
|
||||
import prog8.ast.statements.Label
|
||||
import prog8.compiler.target.Cx16Target
|
||||
import prog8tests.ast.helpers.*
|
||||
import prog8tests.helpers.*
|
||||
import kotlin.io.path.name
|
||||
import kotlin.test.assertEquals
|
||||
|
@ -13,6 +13,7 @@ import prog8.compilerinterface.size
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.compiler.target.Cx16Target
|
||||
import prog8.compilerinterface.toConstantIntegerRange
|
||||
import prog8tests.ast.helpers.mapCombinations
|
||||
import prog8tests.helpers.*
|
||||
import kotlin.test.assertContains
|
||||
import kotlin.test.assertEquals
|
||||
|
@ -6,6 +6,10 @@ import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import prog8.compiler.compileProgram
|
||||
import prog8.compiler.target.Cx16Target
|
||||
import prog8tests.ast.helpers.assumeReadableFile
|
||||
import prog8tests.ast.helpers.fixturesDir
|
||||
import prog8tests.ast.helpers.outputDir
|
||||
import prog8tests.ast.helpers.workingDir
|
||||
import prog8tests.helpers.*
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.absolute
|
||||
|
@ -3,14 +3,14 @@ package prog8tests
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import prog8.ast.internedStringsModuleName
|
||||
import prog8.compiler.ErrorReporter
|
||||
import prog8.compilerinterface.ZeropageType
|
||||
import prog8.compiler.determineCompilationOptions
|
||||
import prog8.compiler.parseImports
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.compilerinterface.ErrorReporter
|
||||
import prog8tests.ast.helpers.outputDir
|
||||
import prog8tests.helpers.assertSuccess
|
||||
import prog8tests.helpers.compileText
|
||||
import prog8tests.helpers.outputDir
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
@ -15,8 +15,8 @@ import prog8.ast.statements.*
|
||||
import prog8.compilerinterface.isInRegularRAMof
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.parser.SourceCode
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.ast.helpers.DummyFunctions
|
||||
import prog8tests.ast.helpers.DummyMemsizer
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
@ -3,7 +3,6 @@ package prog8tests
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.compiler.*
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.compiler.target.Cx16Target
|
||||
import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage
|
||||
|
@ -1,8 +1,11 @@
|
||||
package prog8tests.helpers
|
||||
|
||||
import prog8.compiler.*
|
||||
import prog8.compilerinterface.ErrorReporter
|
||||
import prog8.compilerinterface.ICompilationTarget
|
||||
import prog8.compilerinterface.IErrorReporter
|
||||
import prog8tests.ast.helpers.assumeReadableFile
|
||||
import prog8tests.ast.helpers.outputDir
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.name
|
||||
import kotlin.test.assertFalse
|
||||
@ -28,7 +31,7 @@ internal fun compileFile(
|
||||
optimize: Boolean,
|
||||
fileDir: Path,
|
||||
fileName: String,
|
||||
outputDir: Path = prog8tests.helpers.outputDir,
|
||||
outputDir: Path = prog8tests.ast.helpers.outputDir,
|
||||
errors: IErrorReporter? = null,
|
||||
writeAssembly: Boolean = true
|
||||
) : CompilationResult {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package prog8tests
|
||||
package prog8tests.ast
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
@ -9,8 +9,8 @@ import prog8.ast.internedStringsModuleName
|
||||
import prog8.parser.ParseError
|
||||
import prog8.parser.Prog8Parser.parseModule
|
||||
import prog8.parser.SourceCode
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.ast.helpers.DummyFunctions
|
||||
import prog8tests.ast.helpers.DummyMemsizer
|
||||
import kotlin.test.assertContains
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package prog8tests
|
||||
package prog8tests.ast
|
||||
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
@ -16,9 +16,9 @@ import prog8.ast.statements.*
|
||||
import prog8.parser.ParseError
|
||||
import prog8.parser.Prog8Parser.parseModule
|
||||
import prog8.parser.SourceCode
|
||||
import prog8tests.helpers.assumeNotExists
|
||||
import prog8tests.helpers.assumeReadableFile
|
||||
import prog8tests.helpers.fixturesDir
|
||||
import prog8tests.ast.helpers.assumeNotExists
|
||||
import prog8tests.ast.helpers.assumeReadableFile
|
||||
import prog8tests.ast.helpers.fixturesDir
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.isRegularFile
|
||||
import kotlin.io.path.name
|
||||
|
@ -1,4 +1,4 @@
|
||||
package prog8tests
|
||||
package prog8tests.ast
|
||||
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.hamcrest.core.StringStartsWith
|
||||
@ -6,10 +6,10 @@ import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import prog8.parser.SourceCode
|
||||
import prog8.parser.SourceCode.Companion.libraryFilePrefix
|
||||
import prog8tests.helpers.assumeNotExists
|
||||
import prog8tests.helpers.assumeReadableFile
|
||||
import prog8tests.helpers.fixturesDir
|
||||
import prog8tests.helpers.resourcesDir
|
||||
import prog8tests.ast.helpers.assumeNotExists
|
||||
import prog8tests.ast.helpers.assumeReadableFile
|
||||
import prog8tests.ast.helpers.fixturesDir
|
||||
import prog8tests.ast.helpers.resourcesDir
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.test.*
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package prog8tests
|
||||
package prog8tests.ast
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
@ -1,4 +1,4 @@
|
||||
package prog8tests.ast
|
||||
package prog8tests.ast.ast
|
||||
|
||||
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
@ -12,8 +12,8 @@ import prog8.ast.Program
|
||||
import prog8.ast.base.Position
|
||||
import prog8.ast.internedStringsModuleName
|
||||
import prog8.parser.SourceCode
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.ast.helpers.DummyFunctions
|
||||
import prog8tests.ast.helpers.DummyMemsizer
|
||||
import kotlin.test.assertContains
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertSame
|
||||
|
@ -1,4 +1,4 @@
|
||||
package prog8tests.helpers
|
||||
package prog8tests.ast.helpers
|
||||
|
||||
import prog8.ast.IBuiltinFunctions
|
||||
import prog8.ast.base.Position
|
||||
|
@ -1,4 +1,4 @@
|
||||
package prog8tests.helpers
|
||||
package prog8tests.ast.helpers
|
||||
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.compiler.IMemSizer
|
||||
|
@ -1,4 +1,4 @@
|
||||
package prog8tests.helpers
|
||||
package prog8tests.ast.helpers
|
||||
|
||||
fun <A, B, R> mapCombinations(dim1: Iterable<A>, dim2: Iterable<B>, combine2: (A, B) -> R) =
|
||||
sequence {
|
||||
@ -22,4 +22,4 @@ fun <A, B, C, D, R> mapCombinations(dim1: Iterable<A>, dim2: Iterable<B>, dim3:
|
||||
for (c in dim3)
|
||||
for (d in dim4)
|
||||
yield(combine4(a, b, c, d))
|
||||
}.toList()
|
||||
}.toList()
|
||||
|
@ -1,4 +1,4 @@
|
||||
package prog8tests.helpers
|
||||
package prog8tests.ast.helpers
|
||||
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.*
|
||||
|
@ -1,11 +1,11 @@
|
||||
package prog8tests
|
||||
package prog8tests.ast
|
||||
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.hamcrest.Matchers.`is`
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import prog8tests.helpers.*
|
||||
import prog8tests.ast.helpers.*
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.div
|
||||
import kotlin.test.assertFailsWith
|
||||
|
@ -1,14 +1,12 @@
|
||||
package prog8.compiler.functions
|
||||
package prog8.compilerinterface
|
||||
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.compilerinterface.CompilerException
|
||||
import prog8.compiler.IMemSizer
|
||||
import kotlin.math.*
|
||||
|
||||
|
||||
class FParam(val name: String, val possibleDatatypes: Array<DataType>)
|
||||
|
||||
|
||||
@ -27,11 +25,11 @@ class CallConvention(val params: List<ParamConvention>, val returns: ReturnConve
|
||||
}
|
||||
}
|
||||
val returnConv =
|
||||
when {
|
||||
returns.reg!=null -> returns.reg.toString()
|
||||
returns.floatFac1 -> "floatFAC1"
|
||||
else -> "<no returnvalue>"
|
||||
}
|
||||
when {
|
||||
returns.reg!=null -> returns.reg.toString()
|
||||
returns.floatFac1 -> "floatFAC1"
|
||||
else -> "<no returnvalue>"
|
||||
}
|
||||
return "CallConvention[" + paramConvs.joinToString() + " ; returns: $returnConv]"
|
||||
}
|
||||
}
|
||||
@ -52,7 +50,7 @@ class FSignature(val name: String,
|
||||
else -> {
|
||||
val paramType = actualParamTypes.first()
|
||||
if(pure)
|
||||
// return type depends on arg type
|
||||
// return type depends on arg type
|
||||
when(paramType) {
|
||||
DataType.UBYTE, DataType.BYTE -> ReturnConvention(paramType, RegisterOrPair.A, false)
|
||||
DataType.UWORD, DataType.WORD -> ReturnConvention(paramType, RegisterOrPair.AY, false)
|
||||
@ -87,9 +85,12 @@ class FSignature(val name: String,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Suppress("UNUSED_ANONYMOUS_PARAMETER")
|
||||
private val functionSignatures: List<FSignature> = listOf(
|
||||
// this set of function have no return value and operate in-place:
|
||||
// this set of function have no return value and operate in-place:
|
||||
FSignature("rol" , false, listOf(FParam("item", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||
FSignature("ror" , false, listOf(FParam("item", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||
FSignature("rol2" , false, listOf(FParam("item", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||
@ -97,14 +98,14 @@ private val functionSignatures: List<FSignature> = listOf(
|
||||
FSignature("sort" , false, listOf(FParam("array", ArrayDatatypes)), null),
|
||||
FSignature("reverse" , false, listOf(FParam("array", ArrayDatatypes)), null),
|
||||
FSignature("cmp" , false, listOf(FParam("value1", IntegerDatatypes), FParam("value2", NumericDatatypes)), null),
|
||||
// these few have a return value depending on the argument(s):
|
||||
// these few have a return value depending on the argument(s):
|
||||
FSignature("max" , true, listOf(FParam("values", ArrayDatatypes)), null) { a, p, prg, ct -> collectionArg(a, p, prg, ::builtinMax) }, // type depends on args
|
||||
FSignature("min" , true, listOf(FParam("values", ArrayDatatypes)), null) { a, p, prg, ct -> collectionArg(a, p, prg, ::builtinMin) }, // type depends on args
|
||||
FSignature("sum" , true, listOf(FParam("values", ArrayDatatypes)), null) { a, p, prg, ct -> collectionArg(a, p, prg, ::builtinSum) }, // type depends on args
|
||||
FSignature("abs" , true, listOf(FParam("value", NumericDatatypes)), null, ::builtinAbs), // type depends on argument
|
||||
FSignature("len" , true, listOf(FParam("values", IterableDatatypes)), null, ::builtinLen), // type is UBYTE or UWORD depending on actual length
|
||||
FSignature("sizeof" , true, listOf(FParam("object", DataType.values())), DataType.UBYTE, ::builtinSizeof),
|
||||
// normal functions follow:
|
||||
// normal functions follow:
|
||||
FSignature("sgn" , true, listOf(FParam("value", NumericDatatypes)), DataType.BYTE, ::builtinSgn ),
|
||||
FSignature("sin" , true, listOf(FParam("rads", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg, ct -> oneDoubleArg(a, p, prg, Math::sin) },
|
||||
FSignature("sin8" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.BYTE, ::builtinSin8 ),
|
||||
@ -144,7 +145,7 @@ private val functionSignatures: List<FSignature> = listOf(
|
||||
FSignature("callfar" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null),
|
||||
FSignature("callrom" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null),
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
val BuiltinFunctions = functionSignatures.associateBy { it.name }
|
||||
|
||||
@ -297,7 +298,7 @@ private fun builtinSizeof(args: List<Expression>, position: Position, program: P
|
||||
val dt = args[0].inferType(program)
|
||||
if(dt.isKnown) {
|
||||
val target = (args[0] as IdentifierReference).targetStatement(program)
|
||||
?: throw CannotEvaluateException("sizeof", "no target")
|
||||
?: throw CannotEvaluateException("sizeof", "no target")
|
||||
|
||||
return when {
|
||||
dt.isArray -> {
|
||||
@ -328,7 +329,7 @@ private fun builtinLen(args: List<Expression>, position: Position, program: Prog
|
||||
if(args[0] !is IdentifierReference)
|
||||
throw SyntaxError("len argument should be an identifier", position)
|
||||
val target = (args[0] as IdentifierReference).targetVarDecl(program)
|
||||
?: throw CannotEvaluateException("len", "no target vardecl")
|
||||
?: throw CannotEvaluateException("len", "no target vardecl")
|
||||
|
||||
return when(target.datatype) {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F -> {
|
||||
@ -440,10 +441,10 @@ private fun builtinSgn(args: List<Expression>, position: Position, program: Prog
|
||||
private fun numericLiteral(value: Number, position: Position): NumericLiteralValue {
|
||||
val floatNum=value.toDouble()
|
||||
val tweakedValue: Number =
|
||||
if(floatNum== floor(floatNum) && (floatNum>=-32768 && floatNum<=65535))
|
||||
floatNum.toInt() // we have an integer disguised as a float.
|
||||
else
|
||||
floatNum
|
||||
if(floatNum== floor(floatNum) && (floatNum>=-32768 && floatNum<=65535))
|
||||
floatNum.toInt() // we have an integer disguised as a float.
|
||||
else
|
||||
floatNum
|
||||
|
||||
return when(tweakedValue) {
|
||||
is Int -> NumericLiteralValue.optimalInteger(value.toInt(), position)
|
@ -1,4 +1,4 @@
|
||||
package prog8.optimizer
|
||||
package prog8.compilerinterface
|
||||
|
||||
import prog8.ast.Module
|
||||
import prog8.ast.Node
|
||||
@ -10,7 +10,6 @@ import prog8.ast.expressions.FunctionCall
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.IAstVisitor
|
||||
import prog8.compilerinterface.IErrorReporter
|
||||
|
||||
|
||||
class CallGraph(private val program: Program) : IAstVisitor {
|
@ -14,3 +14,47 @@ interface IErrorReporter {
|
||||
throw ParsingFailedError("There are $numErrors errors and $numWarnings warnings.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ErrorReporter: IErrorReporter {
|
||||
private enum class MessageSeverity {
|
||||
WARNING,
|
||||
ERROR
|
||||
}
|
||||
private class CompilerMessage(val severity: MessageSeverity, val message: String, val position: Position)
|
||||
|
||||
private val messages = mutableListOf<CompilerMessage>()
|
||||
private val alreadyReportedMessages = mutableSetOf<String>()
|
||||
|
||||
override fun err(msg: String, position: Position) {
|
||||
messages.add(CompilerMessage(MessageSeverity.ERROR, msg, position))
|
||||
}
|
||||
override fun warn(msg: String, position: Position) {
|
||||
messages.add(CompilerMessage(MessageSeverity.WARNING, msg, position))
|
||||
}
|
||||
|
||||
override fun report() {
|
||||
var numErrors = 0
|
||||
var numWarnings = 0
|
||||
messages.forEach {
|
||||
when(it.severity) {
|
||||
MessageSeverity.ERROR -> System.err.print("\u001b[91m") // bright red
|
||||
MessageSeverity.WARNING -> System.err.print("\u001b[93m") // bright yellow
|
||||
}
|
||||
val msg = "${it.position.toClickableStr()} ${it.severity} ${it.message}".trim()
|
||||
if(msg !in alreadyReportedMessages) {
|
||||
System.err.println(msg)
|
||||
alreadyReportedMessages.add(msg)
|
||||
when(it.severity) {
|
||||
MessageSeverity.WARNING -> numWarnings++
|
||||
MessageSeverity.ERROR -> numErrors++
|
||||
}
|
||||
}
|
||||
System.err.print("\u001b[0m") // reset color
|
||||
}
|
||||
messages.clear()
|
||||
finalizeNumErrors(numErrors, numWarnings)
|
||||
}
|
||||
|
||||
override fun noErrors() = messages.none { it.severity==MessageSeverity.ERROR }
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package prog8tests
|
||||
package prog8tests.interfaces
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
@ -1,4 +1,4 @@
|
||||
package prog8tests
|
||||
package prog8tests.interfaces
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
@ -26,7 +26,6 @@ Future
|
||||
- add a flood fill routine to gfx2?
|
||||
- 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
|
||||
- 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?
|
||||
|
@ -2,6 +2,7 @@ include ':parser'
|
||||
include ':compilerInterfaces'
|
||||
include ':compilerAst'
|
||||
include ':codeOptimizers'
|
||||
include ':codeGeneration'
|
||||
include ':compiler'
|
||||
include ':dbusCompilerService'
|
||||
include ':httpCompilerService'
|
||||
|
Loading…
Reference in New Issue
Block a user