mirror of
https://github.com/irmen/prog8.git
synced 2024-08-21 12:29:02 +00:00
better return types
This commit is contained in:
parent
f891fc698c
commit
4f7465ba44
@ -100,15 +100,16 @@ fun compileProgram(filepath: Path,
|
|||||||
// printAst(programAst)
|
// printAst(programAst)
|
||||||
|
|
||||||
if(writeAssembly) {
|
if(writeAssembly) {
|
||||||
val (success, message) = writeAssembly(programAst, errors, outputDir, compilationOptions)
|
val result = writeAssembly(programAst, errors, outputDir, compilationOptions)
|
||||||
if(success)
|
when(result) {
|
||||||
programName = message
|
is WriteAssemblyResult.Ok -> programName = result.filename
|
||||||
else {
|
is WriteAssemblyResult.Fail -> {
|
||||||
System.err.println(message)
|
System.err.println(result.error)
|
||||||
return CompilationResult(false, programAst, programName, compTarget, importedFiles)
|
return CompilationResult(false, programAst, programName, compTarget, importedFiles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
System.out.flush()
|
System.out.flush()
|
||||||
System.err.flush()
|
System.err.flush()
|
||||||
println("\nTotal compilation+assemble time: ${totalTime / 1000.0} sec.")
|
println("\nTotal compilation+assemble time: ${totalTime / 1000.0} sec.")
|
||||||
@ -319,10 +320,15 @@ private fun postprocessAst(programAst: Program, errors: IErrorReporter, compiler
|
|||||||
programAst.moveMainAndStartToFirst()
|
programAst.moveMainAndStartToFirst()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed class WriteAssemblyResult {
|
||||||
|
class Ok(val filename: String): WriteAssemblyResult()
|
||||||
|
class Fail(val error: String): WriteAssemblyResult()
|
||||||
|
}
|
||||||
|
|
||||||
private fun writeAssembly(programAst: Program,
|
private fun writeAssembly(programAst: Program,
|
||||||
errors: IErrorReporter,
|
errors: IErrorReporter,
|
||||||
outputDir: Path,
|
outputDir: Path,
|
||||||
compilerOptions: CompilationOptions): Pair<Boolean, String> {
|
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()
|
||||||
@ -340,14 +346,14 @@ private fun writeAssembly(programAst: Program,
|
|||||||
return if(assembly.valid && errors.noErrors()) {
|
return if(assembly.valid && errors.noErrors()) {
|
||||||
val assemblerReturnStatus = assembly.assemble(compilerOptions)
|
val assemblerReturnStatus = assembly.assemble(compilerOptions)
|
||||||
if(assemblerReturnStatus!=0)
|
if(assemblerReturnStatus!=0)
|
||||||
Pair(false, "assembler step failed with return code $assemblerReturnStatus")
|
WriteAssemblyResult.Fail("assembler step failed with return code $assemblerReturnStatus")
|
||||||
else {
|
else {
|
||||||
errors.report()
|
errors.report()
|
||||||
Pair(true, assembly.name)
|
WriteAssemblyResult.Ok(assembly.name)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errors.report()
|
errors.report()
|
||||||
Pair(false, "compiler failed with errors")
|
WriteAssemblyResult.Fail("compiler failed with errors")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,9 +30,8 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
val sub = stmt.target.targetSubroutine(program) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
|
val sub = stmt.target.targetSubroutine(program) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
|
||||||
if(sub.shouldSaveX()) {
|
if(sub.shouldSaveX()) {
|
||||||
val regSaveOnStack = sub.asmAddress==null // rom-routines don't require registers to be saved on stack, normal subroutines do because they can contain nested calls
|
val regSaveOnStack = sub.asmAddress==null // rom-routines don't require registers to be saved on stack, normal subroutines do because they can contain nested calls
|
||||||
val (keepAonEntry: Boolean, keepAonReturn: Boolean) = sub.shouldKeepA()
|
|
||||||
if(regSaveOnStack)
|
if(regSaveOnStack)
|
||||||
asmgen.saveRegisterStack(CpuRegister.X, keepAonEntry)
|
asmgen.saveRegisterStack(CpuRegister.X, sub.shouldKeepA().saveOnEntry)
|
||||||
else
|
else
|
||||||
asmgen.saveRegisterLocal(CpuRegister.X, (stmt as Node).definingSubroutine!!)
|
asmgen.saveRegisterLocal(CpuRegister.X, (stmt as Node).definingSubroutine!!)
|
||||||
}
|
}
|
||||||
@ -42,10 +41,8 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
val sub = stmt.target.targetSubroutine(program) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
|
val sub = stmt.target.targetSubroutine(program) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
|
||||||
if(sub.shouldSaveX()) {
|
if(sub.shouldSaveX()) {
|
||||||
val regSaveOnStack = sub.asmAddress==null // rom-routines don't require registers to be saved on stack, normal subroutines do because they can contain nested calls
|
val regSaveOnStack = sub.asmAddress==null // rom-routines don't require registers to be saved on stack, normal subroutines do because they can contain nested calls
|
||||||
val (keepAonEntry: Boolean, keepAonReturn: Boolean) = sub.shouldKeepA()
|
|
||||||
|
|
||||||
if(regSaveOnStack)
|
if(regSaveOnStack)
|
||||||
asmgen.restoreRegisterStack(CpuRegister.X, keepAonReturn)
|
asmgen.restoreRegisterStack(CpuRegister.X, sub.shouldKeepA().saveOnReturn)
|
||||||
else
|
else
|
||||||
asmgen.restoreRegisterLocal(CpuRegister.X)
|
asmgen.restoreRegisterLocal(CpuRegister.X)
|
||||||
}
|
}
|
||||||
|
15
compilerAst/src/prog8/Either.kt
Normal file
15
compilerAst/src/prog8/Either.kt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package prog8
|
||||||
|
|
||||||
|
sealed class Either<out L, out R> {
|
||||||
|
|
||||||
|
data class Left<out L>(val value: L) : Either<L, Nothing>()
|
||||||
|
|
||||||
|
data class Right<out R>(val value: R) : Either<Nothing, R>()
|
||||||
|
|
||||||
|
fun isRight() = this is Right<R>
|
||||||
|
|
||||||
|
fun isLeft() = this is Left<L>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <L> left(a: L) = Either.Left(a)
|
||||||
|
fun <R> right(b: R) = Either.Right(b)
|
@ -651,15 +651,18 @@ class Subroutine(override val name: String,
|
|||||||
fun regXasResult() = asmReturnvaluesRegisters.any { it.registerOrPair in setOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY) }
|
fun regXasResult() = asmReturnvaluesRegisters.any { it.registerOrPair in setOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY) }
|
||||||
fun regXasParam() = asmParameterRegisters.any { it.registerOrPair in setOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY) }
|
fun regXasParam() = asmParameterRegisters.any { it.registerOrPair in setOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY) }
|
||||||
fun shouldSaveX() = CpuRegister.X in asmClobbers || regXasResult() || regXasParam()
|
fun shouldSaveX() = CpuRegister.X in asmClobbers || regXasResult() || regXasParam()
|
||||||
fun shouldKeepA(): Pair<Boolean, Boolean> {
|
|
||||||
|
class KeepAresult(val saveOnEntry: Boolean, val saveOnReturn: Boolean)
|
||||||
|
|
||||||
|
fun shouldKeepA(): KeepAresult {
|
||||||
// determine if A's value should be kept when preparing for calling the subroutine, and when returning from it
|
// determine if A's value should be kept when preparing for calling the subroutine, and when returning from it
|
||||||
if(!isAsmSubroutine)
|
if(!isAsmSubroutine)
|
||||||
return Pair(false, false)
|
return KeepAresult(saveOnEntry = false, saveOnReturn = false)
|
||||||
|
|
||||||
// it seems that we never have to save A when calling? will be loaded correctly after setup.
|
// 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.
|
// but on return it depends on wether the routine returns something in A.
|
||||||
val saveAonReturn = asmReturnvaluesRegisters.any { it.registerOrPair==RegisterOrPair.A || it.registerOrPair==RegisterOrPair.AY || it.registerOrPair==RegisterOrPair.AX }
|
val saveAonReturn = asmReturnvaluesRegisters.any { it.registerOrPair==RegisterOrPair.A || it.registerOrPair==RegisterOrPair.AY || it.registerOrPair==RegisterOrPair.AX }
|
||||||
return Pair(false, saveAonReturn)
|
return KeepAresult(false, saveAonReturn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun amountOfRtsInAsm(): Int = statements
|
fun amountOfRtsInAsm(): Int = statements
|
||||||
|
Loading…
Reference in New Issue
Block a user