mirror of
https://github.com/irmen/prog8.git
synced 2024-06-10 20:29:33 +00:00
code cleanups
This commit is contained in:
parent
9167ba499d
commit
c223702ea0
|
@ -213,8 +213,7 @@ class StStaticVariable(name: String,
|
||||||
|
|
||||||
|
|
||||||
class StConstant(name: String, val dt: DataType, val value: Double, astNode: PtNode) :
|
class StConstant(name: String, val dt: DataType, val value: Double, astNode: PtNode) :
|
||||||
StNode(name, StNodeType.CONSTANT, astNode) {
|
StNode(name, StNodeType.CONSTANT, astNode)
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class StMemVar(name: String,
|
class StMemVar(name: String,
|
||||||
|
@ -236,12 +235,11 @@ class StMemorySlab(
|
||||||
val align: UInt,
|
val align: UInt,
|
||||||
astNode: PtNode
|
astNode: PtNode
|
||||||
):
|
):
|
||||||
StNode(name, StNodeType.MEMORYSLAB, astNode) {
|
StNode(name, StNodeType.MEMORYSLAB, astNode)
|
||||||
}
|
|
||||||
|
|
||||||
class StSub(name: String, val parameters: List<StSubroutineParameter>, val returnType: DataType?, astNode: PtNode) :
|
class StSub(name: String, val parameters: List<StSubroutineParameter>, val returnType: DataType?, astNode: PtNode) :
|
||||||
StNode(name, StNodeType.SUBROUTINE, astNode) {
|
StNode(name, StNodeType.SUBROUTINE, astNode)
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class StRomSub(name: String,
|
class StRomSub(name: String,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package prog8.code.core
|
package prog8.code.core
|
||||||
|
|
||||||
import prog8.code.core.SourceCode.Companion.libraryFilePrefix
|
import prog8.code.core.SourceCode.Companion.LIBRARYFILEPREFIX
|
||||||
import java.nio.file.InvalidPathException
|
import java.nio.file.InvalidPathException
|
||||||
import kotlin.io.path.Path
|
import kotlin.io.path.Path
|
||||||
import kotlin.io.path.absolute
|
import kotlin.io.path.absolute
|
||||||
|
@ -10,7 +10,7 @@ data class Position(val file: String, val line: Int, val startCol: Int, val endC
|
||||||
fun toClickableStr(): String {
|
fun toClickableStr(): String {
|
||||||
if(this===DUMMY)
|
if(this===DUMMY)
|
||||||
return ""
|
return ""
|
||||||
if(file.startsWith(libraryFilePrefix))
|
if(file.startsWith(LIBRARYFILEPREFIX))
|
||||||
return "$file:$line:$startCol:"
|
return "$file:$line:$startCol:"
|
||||||
return try {
|
return try {
|
||||||
val path = Path(file).absolute().normalize().toString()
|
val path = Path(file).absolute().normalize().toString()
|
||||||
|
|
|
@ -54,12 +54,12 @@ sealed class SourceCode {
|
||||||
/**
|
/**
|
||||||
* filename prefix to designate library files that will be retreived from internal resources rather than disk
|
* filename prefix to designate library files that will be retreived from internal resources rather than disk
|
||||||
*/
|
*/
|
||||||
const val libraryFilePrefix = "library:"
|
const val LIBRARYFILEPREFIX = "library:"
|
||||||
const val stringSourcePrefix = "string:"
|
const val STRINGSOURCEPREFIX = "string:"
|
||||||
val curdir: Path = Path(".").toAbsolutePath()
|
val curdir: Path = Path(".").toAbsolutePath()
|
||||||
fun relative(path: Path): Path = curdir.relativize(path.toAbsolutePath())
|
fun relative(path: Path): Path = curdir.relativize(path.toAbsolutePath())
|
||||||
fun isRegularFilesystemPath(pathString: String) =
|
fun isRegularFilesystemPath(pathString: String) =
|
||||||
!(pathString.startsWith(libraryFilePrefix) || pathString.startsWith(stringSourcePrefix))
|
!(pathString.startsWith(LIBRARYFILEPREFIX) || pathString.startsWith(STRINGSOURCEPREFIX))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,7 +69,7 @@ sealed class SourceCode {
|
||||||
class Text(override val text: String): SourceCode() {
|
class Text(override val text: String): SourceCode() {
|
||||||
override val isFromResources = false
|
override val isFromResources = false
|
||||||
override val isFromFilesystem = false
|
override val isFromFilesystem = false
|
||||||
override val origin = "$stringSourcePrefix${System.identityHashCode(text).toString(16)}"
|
override val origin = "$STRINGSOURCEPREFIX${System.identityHashCode(text).toString(16)}"
|
||||||
override val name = "<unnamed-text>"
|
override val name = "<unnamed-text>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ sealed class SourceCode {
|
||||||
|
|
||||||
override val isFromResources = true
|
override val isFromResources = true
|
||||||
override val isFromFilesystem = false
|
override val isFromFilesystem = false
|
||||||
override val origin = "$libraryFilePrefix$normalized"
|
override val origin = "$LIBRARYFILEPREFIX$normalized"
|
||||||
override val text: String
|
override val text: String
|
||||||
override val name: String
|
override val name: String
|
||||||
|
|
||||||
|
|
|
@ -203,7 +203,7 @@ class AsmGen6502Internal (
|
||||||
private val allocator = VariableAllocator(symbolTable, options, errors)
|
private val allocator = VariableAllocator(symbolTable, options, errors)
|
||||||
private val assemblyLines = mutableListOf<String>()
|
private val assemblyLines = mutableListOf<String>()
|
||||||
private val breakpointLabels = mutableListOf<String>()
|
private val breakpointLabels = mutableListOf<String>()
|
||||||
private val forloopsAsmGen = ForLoopsAsmGen(program, this, zeropage)
|
private val forloopsAsmGen = ForLoopsAsmGen(this, zeropage)
|
||||||
private val postincrdecrAsmGen = PostIncrDecrAsmGen(program, this)
|
private val postincrdecrAsmGen = PostIncrDecrAsmGen(program, this)
|
||||||
private val functioncallAsmGen = FunctionCallAsmGen(program, this)
|
private val functioncallAsmGen = FunctionCallAsmGen(program, this)
|
||||||
private val programGen = ProgramAndVarsGen(program, options, errors, symbolTable, functioncallAsmGen, this, allocator, zeropage)
|
private val programGen = ProgramAndVarsGen(program, options, errors, symbolTable, functioncallAsmGen, this, allocator, zeropage)
|
||||||
|
@ -852,7 +852,7 @@ $repeatLabel""")
|
||||||
DataType.UBYTE, DataType.UWORD -> {
|
DataType.UBYTE, DataType.UWORD -> {
|
||||||
val result = zeropage.allocate(counterVar, dt, null, stmt.position, errors)
|
val result = zeropage.allocate(counterVar, dt, null, stmt.position, errors)
|
||||||
result.fold(
|
result.fold(
|
||||||
success = { (address, _) -> asmInfo.extraVars.add(Triple(dt, counterVar, address)) },
|
success = { (address, _, _) -> asmInfo.extraVars.add(Triple(dt, counterVar, address)) },
|
||||||
failure = { asmInfo.extraVars.add(Triple(dt, counterVar, null)) } // allocate normally
|
failure = { asmInfo.extraVars.add(Triple(dt, counterVar, null)) } // allocate normally
|
||||||
)
|
)
|
||||||
return counterVar
|
return counterVar
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
package prog8.codegen.cpu6502
|
package prog8.codegen.cpu6502
|
||||||
|
|
||||||
import com.github.michaelbull.result.Ok
|
|
||||||
import com.github.michaelbull.result.Result
|
|
||||||
import com.github.michaelbull.result.mapError
|
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import prog8.code.target.C64Target
|
import prog8.code.target.C64Target
|
||||||
import java.io.File
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.io.path.Path
|
|
||||||
import kotlin.io.path.isRegularFile
|
|
||||||
|
|
||||||
|
|
||||||
internal class AssemblyProgram(
|
internal class AssemblyProgram(
|
||||||
|
@ -130,18 +124,3 @@ internal class AssemblyProgram(
|
||||||
viceMonListFile.toFile().appendText(breakpoints.joinToString("\n") + "\n")
|
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)}").text
|
|
||||||
}.mapError { NoSuchFileException(File(filename)) }
|
|
||||||
} else {
|
|
||||||
val sib = Path(source.origin).resolveSibling(filename)
|
|
||||||
if (sib.isRegularFile())
|
|
||||||
Ok(SourceCode.File(sib).text)
|
|
||||||
else
|
|
||||||
Ok(SourceCode.File(Path(filename)).text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,17 +6,6 @@ import prog8.code.ast.PtSub
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
|
|
||||||
|
|
||||||
internal class KeepAresult(val saveOnEntry: Boolean, val saveOnReturn: Boolean)
|
|
||||||
|
|
||||||
internal fun PtAsmSub.shouldKeepA(): KeepAresult {
|
|
||||||
// determine if A's value should be kept when preparing for calling the subroutine, and when returning from it
|
|
||||||
|
|
||||||
// it seems that we never have to save A when calling? will be loaded correctly after setup.
|
|
||||||
// but on return it depends on wether the routine returns something in A.
|
|
||||||
val saveAonReturn = returns.any { it.first.registerOrPair==RegisterOrPair.A || it.first.registerOrPair==RegisterOrPair.AY || it.first.registerOrPair==RegisterOrPair.AX }
|
|
||||||
return KeepAresult(false, saveAonReturn)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun IPtSubroutine.returnsWhatWhere(): List<Pair<RegisterOrStatusflag, DataType>> {
|
internal fun IPtSubroutine.returnsWhatWhere(): List<Pair<RegisterOrStatusflag, DataType>> {
|
||||||
when(this) {
|
when(this) {
|
||||||
is PtAsmSub -> {
|
is PtAsmSub -> {
|
||||||
|
|
|
@ -5,9 +5,10 @@ import prog8.code.ast.*
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
internal class ForLoopsAsmGen(private val program: PtProgram,
|
internal class ForLoopsAsmGen(
|
||||||
private val asmgen: AsmGen6502Internal,
|
private val asmgen: AsmGen6502Internal,
|
||||||
private val zeropage: Zeropage) {
|
private val zeropage: Zeropage
|
||||||
|
) {
|
||||||
|
|
||||||
internal fun translate(stmt: PtForLoop) {
|
internal fun translate(stmt: PtForLoop) {
|
||||||
val iterableDt = stmt.iterable.type
|
val iterableDt = stmt.iterable.type
|
||||||
|
@ -382,7 +383,7 @@ $loopLabel sty $indexVar
|
||||||
// allocate index var on ZP if possible
|
// allocate index var on ZP if possible
|
||||||
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
|
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
|
||||||
result.fold(
|
result.fold(
|
||||||
success = { (address,_)-> asmgen.out("""$indexVar = $address ; auto zp UBYTE""") },
|
success = { (address, _, _)-> asmgen.out("""$indexVar = $address ; auto zp UBYTE""") },
|
||||||
failure = { asmgen.out("$indexVar .byte 0") }
|
failure = { asmgen.out("$indexVar .byte 0") }
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2497,7 +2497,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||||
CpuRegister.X -> asmgen.out(" txa")
|
CpuRegister.X -> asmgen.out(" txa")
|
||||||
CpuRegister.Y -> asmgen.out(" tya")
|
CpuRegister.Y -> asmgen.out(" tya")
|
||||||
}
|
}
|
||||||
if(asmgen.isZpVar(target.origAstTarget!!.array!!.variable)) {
|
if(asmgen.isZpVar(target.origAstTarget.array!!.variable)) {
|
||||||
asmgen.out(" ldy #${target.constArrayIndexValue} | sta (${target.asmVarname}),y")
|
asmgen.out(" ldy #${target.constArrayIndexValue} | sta (${target.asmVarname}),y")
|
||||||
} else {
|
} else {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
|
@ -2515,8 +2515,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||||
CpuRegister.X -> asmgen.out(" txa")
|
CpuRegister.X -> asmgen.out(" txa")
|
||||||
CpuRegister.Y -> asmgen.out(" tya")
|
CpuRegister.Y -> asmgen.out(" tya")
|
||||||
}
|
}
|
||||||
val indexVar = target.array!!.index as PtIdentifier
|
val indexVar = target.array.index as PtIdentifier
|
||||||
if(asmgen.isZpVar(target.origAstTarget!!.array!!.variable)) {
|
if(asmgen.isZpVar(target.origAstTarget.array!!.variable)) {
|
||||||
asmgen.out(" ldy ${asmgen.asmVariableName(indexVar)} | sta (${target.asmVarname}),y")
|
asmgen.out(" ldy ${asmgen.asmVariableName(indexVar)} | sta (${target.asmVarname}),y")
|
||||||
} else {
|
} else {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
|
@ -2545,7 +2545,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||||
CpuRegister.X -> asmgen.out(" txa")
|
CpuRegister.X -> asmgen.out(" txa")
|
||||||
CpuRegister.Y -> asmgen.out(" tya")
|
CpuRegister.Y -> asmgen.out(" tya")
|
||||||
}
|
}
|
||||||
val indexVar = target.array!!.index as PtIdentifier
|
val indexVar = target.array.index as PtIdentifier
|
||||||
asmgen.out(" ldy ${asmgen.asmVariableName(indexVar)} | sta ${target.asmVarname},y")
|
asmgen.out(" ldy ${asmgen.asmVariableName(indexVar)} | sta ${target.asmVarname},y")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ class ExperiCodeGen: ICodeGeneratorBackend {
|
||||||
symbolTable: SymbolTable,
|
symbolTable: SymbolTable,
|
||||||
options: CompilationOptions,
|
options: CompilationOptions,
|
||||||
errors: IErrorReporter
|
errors: IErrorReporter
|
||||||
): IAssemblyProgram? {
|
): IAssemblyProgram {
|
||||||
|
|
||||||
// you could write a code generator directly on the PtProgram AST,
|
// you could write a code generator directly on the PtProgram AST,
|
||||||
// but you can also use the Intermediate Representation to build a codegen on:
|
// but you can also use the Intermediate Representation to build a codegen on:
|
||||||
|
|
|
@ -1652,24 +1652,6 @@ class IRCodeGen(
|
||||||
|
|
||||||
internal fun isOne(expression: PtExpression): Boolean = expression is PtNumber && expression.number==1.0
|
internal fun isOne(expression: PtExpression): Boolean = expression is PtNumber && expression.number==1.0
|
||||||
|
|
||||||
fun getReusableTempvar(scope: PtNamedNode, type: DataType): PtIdentifier {
|
|
||||||
val uniqueId = Pair(scope, type).hashCode().toUInt()
|
|
||||||
val tempvarname = "${scope.scopedName}.tempvar_${uniqueId}"
|
|
||||||
val tempvar = PtIdentifier(tempvarname, type, Position.DUMMY)
|
|
||||||
val staticVar = StStaticVariable(
|
|
||||||
tempvarname,
|
|
||||||
type,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
ZeropageWish.DONTCARE,
|
|
||||||
tempvar
|
|
||||||
)
|
|
||||||
irSymbolTable.add(staticVar)
|
|
||||||
return tempvar
|
|
||||||
}
|
|
||||||
|
|
||||||
fun makeSyscall(syscall: IMSyscall, params: List<Pair<IRDataType, Int>>, returns: Pair<IRDataType, Int>?, label: String?=null): IRCodeChunk {
|
fun makeSyscall(syscall: IMSyscall, params: List<Pair<IRDataType, Int>>, returns: Pair<IRDataType, Int>?, label: String?=null): IRCodeChunk {
|
||||||
return IRCodeChunk(label, null).also {
|
return IRCodeChunk(label, null).also {
|
||||||
val args = params.map { (dt, reg)->
|
val args = params.map { (dt, reg)->
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package prog8.codegen.intermediate
|
package prog8.codegen.intermediate
|
||||||
|
|
||||||
import prog8.code.core.IErrorReporter
|
import prog8.code.core.IErrorReporter
|
||||||
import prog8.code.core.SourceCode.Companion.libraryFilePrefix
|
import prog8.code.core.SourceCode.Companion.LIBRARYFILEPREFIX
|
||||||
import prog8.intermediate.*
|
import prog8.intermediate.*
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ class IRUnusedCodeRemover(
|
||||||
irprog.blocks.forEach { block ->
|
irprog.blocks.forEach { block ->
|
||||||
block.children.filterIsInstance<IRSubroutine>().reversed().forEach { sub ->
|
block.children.filterIsInstance<IRSubroutine>().reversed().forEach { sub ->
|
||||||
if(sub.isEmpty()) {
|
if(sub.isEmpty()) {
|
||||||
if(!sub.position.file.startsWith(libraryFilePrefix)) {
|
if(!sub.position.file.startsWith(LIBRARYFILEPREFIX)) {
|
||||||
errors.warn("unused subroutine ${sub.label}", sub.position)
|
errors.warn("unused subroutine ${sub.label}", sub.position)
|
||||||
}
|
}
|
||||||
block.children.remove(sub)
|
block.children.remove(sub)
|
||||||
|
@ -71,7 +71,7 @@ class IRUnusedCodeRemover(
|
||||||
irprog.blocks.forEach { block ->
|
irprog.blocks.forEach { block ->
|
||||||
block.children.filterIsInstance<IRAsmSubroutine>().reversed().forEach { sub ->
|
block.children.filterIsInstance<IRAsmSubroutine>().reversed().forEach { sub ->
|
||||||
if(sub.isEmpty()) {
|
if(sub.isEmpty()) {
|
||||||
if(!sub.position.file.startsWith(libraryFilePrefix)) {
|
if(!sub.position.file.startsWith(LIBRARYFILEPREFIX)) {
|
||||||
errors.warn("unused asmsubroutine ${sub.label}", sub.position)
|
errors.warn("unused asmsubroutine ${sub.label}", sub.position)
|
||||||
}
|
}
|
||||||
block.children.remove(sub)
|
block.children.remove(sub)
|
||||||
|
|
|
@ -16,7 +16,7 @@ class VmCodeGen: ICodeGeneratorBackend {
|
||||||
symbolTable: SymbolTable,
|
symbolTable: SymbolTable,
|
||||||
options: CompilationOptions,
|
options: CompilationOptions,
|
||||||
errors: IErrorReporter
|
errors: IErrorReporter
|
||||||
): IAssemblyProgram? {
|
): IAssemblyProgram {
|
||||||
val irCodeGen = IRCodeGen(program, symbolTable, options, errors)
|
val irCodeGen = IRCodeGen(program, symbolTable, options, errors)
|
||||||
val irProgram = irCodeGen.generate()
|
val irProgram = irCodeGen.generate()
|
||||||
return VmAssemblyProgram(irProgram.name, irProgram)
|
return VmAssemblyProgram(irProgram.name, irProgram)
|
||||||
|
|
|
@ -5,11 +5,11 @@ package prog8.buildversion
|
||||||
*/
|
*/
|
||||||
const val MAVEN_GROUP = "prog8"
|
const val MAVEN_GROUP = "prog8"
|
||||||
const val MAVEN_NAME = "compiler"
|
const val MAVEN_NAME = "compiler"
|
||||||
const val VERSION = "9.2-SNAPSHOT"
|
const val VERSION = "9.3-SNAPSHOT"
|
||||||
const val GIT_REVISION = 3980
|
const val GIT_REVISION = 4012
|
||||||
const val GIT_SHA = "9f247901d484ca36d047cdcf77f5b905ba772f82"
|
const val GIT_SHA = "9167ba499de99696aa7c6887d4867eae70eb5caf"
|
||||||
const val GIT_DATE = "2023-07-16T21:45:04Z"
|
const val GIT_DATE = "2023-07-30T15:49:35Z"
|
||||||
const val GIT_BRANCH = "remove_evalstack"
|
const val GIT_BRANCH = "master"
|
||||||
const val BUILD_DATE = "2023-07-17T23:11:43Z"
|
const val BUILD_DATE = "2023-07-30T16:41:27Z"
|
||||||
const val BUILD_UNIX_TIME = 1689635503506L
|
const val BUILD_UNIX_TIME = 1690735287514L
|
||||||
const val DIRTY = 1
|
const val DIRTY = 1
|
||||||
|
|
|
@ -104,7 +104,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
||||||
program.processAstBeforeAsmGeneration(compilationOptions, args.errors)
|
program.processAstBeforeAsmGeneration(compilationOptions, args.errors)
|
||||||
args.errors.report()
|
args.errors.report()
|
||||||
|
|
||||||
val intermediateAst = IntermediateAstMaker(program, compilationOptions).transform()
|
val intermediateAst = IntermediateAstMaker(program).transform()
|
||||||
// println("*********** COMPILER AST RIGHT BEFORE ASM GENERATION *************")
|
// println("*********** COMPILER AST RIGHT BEFORE ASM GENERATION *************")
|
||||||
// printProgram(program)
|
// printProgram(program)
|
||||||
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
||||||
|
@ -334,7 +334,7 @@ private fun processAst(program: Program, errors: IErrorReporter, compilerOptions
|
||||||
errors.report()
|
errors.report()
|
||||||
program.desugaring(errors)
|
program.desugaring(errors)
|
||||||
errors.report()
|
errors.report()
|
||||||
program.reorderStatements(errors, compilerOptions)
|
program.reorderStatements(errors)
|
||||||
errors.report()
|
errors.report()
|
||||||
program.changeNotExpressionAndIfComparisonExpr(errors, compilerOptions.compTarget)
|
program.changeNotExpressionAndIfComparisonExpr(errors, compilerOptions.compTarget)
|
||||||
errors.report()
|
errors.report()
|
||||||
|
|
|
@ -117,7 +117,7 @@ class ModuleImporter(private val program: Program,
|
||||||
importedModule.statements.remove(block)
|
importedModule.statements.remove(block)
|
||||||
} else {
|
} else {
|
||||||
val merges = block.statements.filter { it is Directive && it.directive=="%option" && it.args.any { a->a.name=="merge" } }
|
val merges = block.statements.filter { it is Directive && it.directive=="%option" && it.args.any { a->a.name=="merge" } }
|
||||||
block.statements.removeAll(merges)
|
block.statements.removeAll(merges.toSet())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ class ModuleImporter(private val program: Program,
|
||||||
// Most global directives don't apply for imported modules, so remove them
|
// Most global directives don't apply for imported modules, so remove them
|
||||||
val moduleLevelDirectives = listOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address")
|
val moduleLevelDirectives = listOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address")
|
||||||
var directives = importedModule.statements.filterIsInstance<Directive>()
|
var directives = importedModule.statements.filterIsInstance<Directive>()
|
||||||
importedModule.statements.removeAll(directives)
|
importedModule.statements.removeAll(directives.toSet())
|
||||||
directives = directives.filter{ it.directive !in moduleLevelDirectives }
|
directives = directives.filter{ it.directive !in moduleLevelDirectives }
|
||||||
importedModule.statements.addAll(0, directives)
|
importedModule.statements.addAll(0, directives)
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ internal class AstChecker(private val program: Program,
|
||||||
errors.err("type $valueDt of return value doesn't match subroutine's return type ${expectedReturnValues[0]}",returnStmt.value!!.position)
|
errors.err("type $valueDt of return value doesn't match subroutine's return type ${expectedReturnValues[0]}",returnStmt.value!!.position)
|
||||||
}
|
}
|
||||||
} else if(valueDt.isIterable && expectedReturnValues[0]==DataType.UWORD) {
|
} else if(valueDt.isIterable && expectedReturnValues[0]==DataType.UWORD) {
|
||||||
// you can return a string or array when a uword (pointer) is returned
|
// you can return a string or array when an uword (pointer) is returned
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
errors.err("type $valueDt of return value doesn't match subroutine's return type ${expectedReturnValues[0]}",returnStmt.value!!.position)
|
errors.err("type $valueDt of return value doesn't match subroutine's return type ${expectedReturnValues[0]}",returnStmt.value!!.position)
|
||||||
|
|
|
@ -39,8 +39,8 @@ internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Program.reorderStatements(errors: IErrorReporter, options: CompilationOptions) {
|
internal fun Program.reorderStatements(errors: IErrorReporter) {
|
||||||
val reorder = StatementReorderer(this, errors, options)
|
val reorder = StatementReorderer(this, errors)
|
||||||
reorder.visit(this)
|
reorder.visit(this)
|
||||||
if(errors.noErrors()) {
|
if(errors.noErrors()) {
|
||||||
reorder.applyModifications()
|
reorder.applyModifications()
|
||||||
|
|
|
@ -19,7 +19,7 @@ import kotlin.io.path.isRegularFile
|
||||||
/**
|
/**
|
||||||
* Convert 'old' compiler-AST into the 'new' simplified AST with baked types.
|
* Convert 'old' compiler-AST into the 'new' simplified AST with baked types.
|
||||||
*/
|
*/
|
||||||
class IntermediateAstMaker(private val program: Program, private val options: CompilationOptions) {
|
class IntermediateAstMaker(private val program: Program) {
|
||||||
fun transform(): PtProgram {
|
fun transform(): PtProgram {
|
||||||
val ptProgram = PtProgram(
|
val ptProgram = PtProgram(
|
||||||
program.name,
|
program.name,
|
||||||
|
@ -529,9 +529,9 @@ class IntermediateAstMaker(private val program: Program, private val options: Co
|
||||||
|
|
||||||
|
|
||||||
private fun loadAsmIncludeFile(filename: String, source: SourceCode): Result<String, NoSuchFileException> {
|
private fun loadAsmIncludeFile(filename: String, source: SourceCode): Result<String, NoSuchFileException> {
|
||||||
return if (filename.startsWith(SourceCode.libraryFilePrefix)) {
|
return if (filename.startsWith(SourceCode.LIBRARYFILEPREFIX)) {
|
||||||
return com.github.michaelbull.result.runCatching {
|
return com.github.michaelbull.result.runCatching {
|
||||||
SourceCode.Resource("/prog8lib/${filename.substring(SourceCode.libraryFilePrefix.length)}").text
|
SourceCode.Resource("/prog8lib/${filename.substring(SourceCode.LIBRARYFILEPREFIX.length)}").text
|
||||||
}.mapError { NoSuchFileException(File(filename)) }
|
}.mapError { NoSuchFileException(File(filename)) }
|
||||||
} else {
|
} else {
|
||||||
val sib = Path(source.origin).resolveSibling(filename)
|
val sib = Path(source.origin).resolveSibling(filename)
|
||||||
|
|
|
@ -7,9 +7,9 @@ import prog8.ast.walk.AstWalker
|
||||||
import prog8.ast.walk.IAstModification
|
import prog8.ast.walk.IAstModification
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
|
|
||||||
internal class StatementReorderer(val program: Program,
|
internal class StatementReorderer(
|
||||||
val errors: IErrorReporter,
|
val program: Program,
|
||||||
private val options: CompilationOptions
|
val errors: IErrorReporter
|
||||||
) : AstWalker() {
|
) : AstWalker() {
|
||||||
// Reorders the statements in a way the compiler needs.
|
// Reorders the statements in a way the compiler needs.
|
||||||
// - 'main' block must be the very first statement UNLESS it has an address set.
|
// - 'main' block must be the very first statement UNLESS it has an address set.
|
||||||
|
@ -109,7 +109,7 @@ internal class StatementReorderer(val program: Program,
|
||||||
|
|
||||||
private fun directivesToTheTop(statements: MutableList<Statement>) {
|
private fun directivesToTheTop(statements: MutableList<Statement>) {
|
||||||
val directives = statements.filterIsInstance<Directive>().filter {it.directive in directivesToMove}
|
val directives = statements.filterIsInstance<Directive>().filter {it.directive in directivesToMove}
|
||||||
statements.removeAll(directives)
|
statements.removeAll(directives.toSet())
|
||||||
statements.addAll(0, directives)
|
statements.addAll(0, directives)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ class TestIntermediateAst: FunSpec({
|
||||||
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS
|
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS
|
||||||
)
|
)
|
||||||
val result = compileText(target, false, text, writeAssembly = false)!!
|
val result = compileText(target, false, text, writeAssembly = false)!!
|
||||||
val ast = IntermediateAstMaker(result.compilerAst, options).transform()
|
val ast = IntermediateAstMaker(result.compilerAst).transform()
|
||||||
ast.name shouldBe result.compilerAst.name
|
ast.name shouldBe result.compilerAst.name
|
||||||
ast.allBlocks().any() shouldBe true
|
ast.allBlocks().any() shouldBe true
|
||||||
val entry = ast.entrypoint() ?: fail("no main.start() found")
|
val entry = ast.entrypoint() ?: fail("no main.start() found")
|
||||||
|
|
|
@ -378,7 +378,7 @@ class TestProg8Parser: FunSpec( {
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val module = parseModule(SourceCode.Text(srcText))
|
val module = parseModule(SourceCode.Text(srcText))
|
||||||
assertSomethingForAllNodes(module) {
|
assertSomethingForAllNodes(module) {
|
||||||
it.position.file shouldStartWith SourceCode.stringSourcePrefix
|
it.position.file shouldStartWith SourceCode.STRINGSOURCEPREFIX
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +387,7 @@ class TestProg8Parser: FunSpec( {
|
||||||
val resource = SourceCode.Resource("prog8lib/math.p8")
|
val resource = SourceCode.Resource("prog8lib/math.p8")
|
||||||
val module = parseModule(resource)
|
val module = parseModule(resource)
|
||||||
assertSomethingForAllNodes(module) {
|
assertSomethingForAllNodes(module) {
|
||||||
it.position.file shouldStartWith SourceCode.libraryFilePrefix
|
it.position.file shouldStartWith SourceCode.LIBRARYFILEPREFIX
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import io.kotest.core.spec.style.AnnotationSpec
|
||||||
import io.kotest.matchers.shouldBe
|
import io.kotest.matchers.shouldBe
|
||||||
import io.kotest.matchers.string.shouldContain
|
import io.kotest.matchers.string.shouldContain
|
||||||
import prog8.code.core.SourceCode
|
import prog8.code.core.SourceCode
|
||||||
import prog8.code.core.SourceCode.Companion.libraryFilePrefix
|
import prog8.code.core.SourceCode.Companion.LIBRARYFILEPREFIX
|
||||||
import prog8tests.helpers.assumeNotExists
|
import prog8tests.helpers.assumeNotExists
|
||||||
import prog8tests.helpers.assumeReadableFile
|
import prog8tests.helpers.assumeReadableFile
|
||||||
import prog8tests.helpers.fixturesDir
|
import prog8tests.helpers.fixturesDir
|
||||||
|
@ -77,7 +77,7 @@ class TestSourceCode: AnnotationSpec() {
|
||||||
val srcFile = assumeReadableFile(resourcesDir, pathString).toFile()
|
val srcFile = assumeReadableFile(resourcesDir, pathString).toFile()
|
||||||
val src = SourceCode.Resource(pathString)
|
val src = SourceCode.Resource(pathString)
|
||||||
|
|
||||||
src.origin shouldBe "$libraryFilePrefix/$pathString"
|
src.origin shouldBe "$LIBRARYFILEPREFIX/$pathString"
|
||||||
src.text shouldBe srcFile.readText()
|
src.text shouldBe srcFile.readText()
|
||||||
src.isFromResources shouldBe true
|
src.isFromResources shouldBe true
|
||||||
src.isFromFilesystem shouldBe false
|
src.isFromFilesystem shouldBe false
|
||||||
|
@ -89,7 +89,7 @@ class TestSourceCode: AnnotationSpec() {
|
||||||
val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile()
|
val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile()
|
||||||
val src = SourceCode.Resource(pathString)
|
val src = SourceCode.Resource(pathString)
|
||||||
|
|
||||||
src.origin shouldBe "$libraryFilePrefix$pathString"
|
src.origin shouldBe "$LIBRARYFILEPREFIX$pathString"
|
||||||
src.text shouldBe srcFile.readText()
|
src.text shouldBe srcFile.readText()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class TestSourceCode: AnnotationSpec() {
|
||||||
val srcFile = assumeReadableFile(resourcesDir, pathString).toFile()
|
val srcFile = assumeReadableFile(resourcesDir, pathString).toFile()
|
||||||
val src = SourceCode.Resource(pathString)
|
val src = SourceCode.Resource(pathString)
|
||||||
|
|
||||||
src.origin shouldBe "$libraryFilePrefix/$pathString"
|
src.origin shouldBe "$LIBRARYFILEPREFIX/$pathString"
|
||||||
src.text shouldBe srcFile.readText()
|
src.text shouldBe srcFile.readText()
|
||||||
src.isFromResources shouldBe true
|
src.isFromResources shouldBe true
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ class TestSourceCode: AnnotationSpec() {
|
||||||
val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile()
|
val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile()
|
||||||
val src = SourceCode.Resource(pathString)
|
val src = SourceCode.Resource(pathString)
|
||||||
|
|
||||||
src.origin shouldBe "$libraryFilePrefix$pathString"
|
src.origin shouldBe "$LIBRARYFILEPREFIX$pathString"
|
||||||
src.text shouldBe srcFile.readText()
|
src.text shouldBe srcFile.readText()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ class TestSourceCode: AnnotationSpec() {
|
||||||
val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile()
|
val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile()
|
||||||
val src = SourceCode.Resource(pathString)
|
val src = SourceCode.Resource(pathString)
|
||||||
|
|
||||||
src.origin shouldBe "$libraryFilePrefix/prog8lib/math.p8"
|
src.origin shouldBe "$LIBRARYFILEPREFIX/prog8lib/math.p8"
|
||||||
src.text shouldBe srcFile.readText()
|
src.text shouldBe srcFile.readText()
|
||||||
src.isFromResources shouldBe true
|
src.isFromResources shouldBe true
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ class TestAsmGenSymbols: StringSpec({
|
||||||
fun createTestAsmGen6502(program: Program): AsmGen6502Internal {
|
fun createTestAsmGen6502(program: Program): AsmGen6502Internal {
|
||||||
val errors = ErrorReporterForTests()
|
val errors = ErrorReporterForTests()
|
||||||
val options = CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, true, C64Target(), 999u)
|
val options = CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, true, C64Target(), 999u)
|
||||||
val ptProgram = IntermediateAstMaker(program, options).transform()
|
val ptProgram = IntermediateAstMaker(program).transform()
|
||||||
val st = SymbolTableMaker(ptProgram, options).make()
|
val st = SymbolTableMaker(ptProgram, options).make()
|
||||||
return AsmGen6502Internal(ptProgram, st, options, errors)
|
return AsmGen6502Internal(ptProgram, st, options, errors)
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ class Program(val name: String,
|
||||||
// replace it with a variable declaration that points to the entry in the pool.
|
// replace it with a variable declaration that points to the entry in the pool.
|
||||||
|
|
||||||
if(string.parent is VarDecl) {
|
if(string.parent is VarDecl) {
|
||||||
// deduplication can only be performed safely for known-const strings (=string literals OUTSIDE OF A VARDECL)!
|
// deduplication can only be performed safely for known-const strings (=string literals OUTSIDE A VARDECL)!
|
||||||
throw FatalAstException("cannot intern a string literal that's part of a vardecl")
|
throw FatalAstException("cannot intern a string literal that's part of a vardecl")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -985,8 +985,6 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
|
||||||
val scope=decl.definingModule
|
val scope=decl.definingModule
|
||||||
return scope.name==internedStringsModuleName
|
return scope.name==internedStringsModuleName
|
||||||
}
|
}
|
||||||
|
|
||||||
fun renamed(newName: List<String>): IdentifierReference = IdentifierReference(newName, position)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FunctionCallExpression(override var target: IdentifierReference,
|
class FunctionCallExpression(override var target: IdentifierReference,
|
||||||
|
|
|
@ -136,7 +136,6 @@ data class Label(override val name: String, override val position: Position) : S
|
||||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||||
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
||||||
override fun toString()= "Label(name=$name, pos=$position)"
|
override fun toString()= "Label(name=$name, pos=$position)"
|
||||||
fun renamed(newName: String): Label = Label(newName, position)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Return(var value: Expression?, override val position: Position) : Statement() {
|
class Return(var value: Expression?, override val position: Position) : Statement() {
|
||||||
|
@ -291,13 +290,6 @@ class VarDecl(val type: VarDeclType,
|
||||||
return copy
|
return copy
|
||||||
}
|
}
|
||||||
|
|
||||||
fun renamed(newName: String): VarDecl {
|
|
||||||
val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize, newName, value,
|
|
||||||
isArray, sharedWithAsm, splitArray, position)
|
|
||||||
copy.allowInitializeWithZero = this.allowInitializeWithZero
|
|
||||||
return copy
|
|
||||||
}
|
|
||||||
|
|
||||||
fun findInitializer(program: Program): Assignment? =
|
fun findInitializer(program: Program): Assignment? =
|
||||||
(parent as IStatementContainer).statements
|
(parent as IStatementContainer).statements
|
||||||
.asSequence()
|
.asSequence()
|
||||||
|
@ -883,25 +875,6 @@ class ForLoop(var loopVar: IdentifierReference,
|
||||||
|
|
||||||
fun loopVarDt(program: Program) = loopVar.inferType(program)
|
fun loopVarDt(program: Program) = loopVar.inferType(program)
|
||||||
|
|
||||||
fun constIterationCount(program: Program): Int? {
|
|
||||||
return when (val iter = iterable) {
|
|
||||||
is IdentifierReference -> {
|
|
||||||
val target = iter.targetVarDecl(program)!!
|
|
||||||
if (target.isArray)
|
|
||||||
target.arraysize!!.constIndex()
|
|
||||||
else if (target.value is StringLiteral)
|
|
||||||
(target.value as StringLiteral).value.length
|
|
||||||
else if (target.value is ArrayLiteral)
|
|
||||||
(target.value as ArrayLiteral).value.size
|
|
||||||
else null
|
|
||||||
}
|
|
||||||
is ArrayLiteral -> iter.value.size
|
|
||||||
is RangeExpression -> iter.size()
|
|
||||||
is StringLiteral -> iter.value.length
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class WhileLoop(var condition: Expression,
|
class WhileLoop(var condition: Expression,
|
||||||
|
|
|
@ -5,4 +5,4 @@ org.gradle.daemon=true
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
javaVersion=11
|
javaVersion=11
|
||||||
kotlinVersion=1.9.0
|
kotlinVersion=1.9.0
|
||||||
version=9.2.1
|
version=9.3-SNAPSHOT
|
||||||
|
|
|
@ -76,7 +76,7 @@ class GraphicsWindow(val pixelWidth: Int, val pixelHeight: Int, val pixelScaling
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class BitmapScreenPanel(private val drawImage: BufferedImage, val pixelScaling: Int) : JPanel() {
|
internal class BitmapScreenPanel(private val drawImage: BufferedImage, pixelScaling: Int) : JPanel() {
|
||||||
init {
|
init {
|
||||||
val size = Dimension(drawImage.width * pixelScaling, drawImage.height * pixelScaling)
|
val size = Dimension(drawImage.width * pixelScaling, drawImage.height * pixelScaling)
|
||||||
minimumSize = size
|
minimumSize = size
|
||||||
|
|
|
@ -3,7 +3,7 @@ package prog8.vm
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import prog8.intermediate.IRSymbolTable
|
import prog8.intermediate.IRSymbolTable
|
||||||
|
|
||||||
internal class VmVariableAllocator(val st: IRSymbolTable, val encoding: IStringEncoding, memsizer: IMemSizer) {
|
internal class VmVariableAllocator(st: IRSymbolTable, val encoding: IStringEncoding, memsizer: IMemSizer) {
|
||||||
|
|
||||||
internal val allocations = mutableMapOf<String, Int>()
|
internal val allocations = mutableMapOf<String, Int>()
|
||||||
private var freeMemoryStart: Int
|
private var freeMemoryStart: Int
|
||||||
|
|
Loading…
Reference in New Issue
Block a user