mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
fixed return values problem and wrong optimization into jump
This commit is contained in:
parent
756930a54f
commit
d6cf8bcce0
@ -48,8 +48,7 @@
|
||||
; c64.CHROUT('\n')
|
||||
|
||||
if guess==secretnumber {
|
||||
ending(true)
|
||||
return ; @todo make return ending(true) actually work as well
|
||||
return ending(true)
|
||||
} else {
|
||||
c64scr.print_string("\n\nThat is too ")
|
||||
if guess<secretnumber
|
||||
@ -59,12 +58,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
; return 99 ;@todo error message (no return values)
|
||||
; return 99,44 ;@todo error message (no return values)
|
||||
; return ending(false) ; @todo fix this, actuall needs to CALL ending even though no value is returned
|
||||
|
||||
ending(false)
|
||||
return ; @todo make return ending(false) actually work as well
|
||||
return ending(false)
|
||||
|
||||
|
||||
sub ending(success: ubyte) {
|
||||
@ -78,10 +72,6 @@
|
||||
c64scr.print_string("Thanks for playing, ")
|
||||
c64scr.print_string(name)
|
||||
c64scr.print_string(".\n")
|
||||
|
||||
; return 99 ; @todo error message (no return values)
|
||||
; return 99,44 ; @todo error message (no return values)
|
||||
; return 99,44 ; @todo should check number of return values!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,8 @@
|
||||
vm_write_str("\nYou have ")
|
||||
vm_write_num(attempts_left)
|
||||
vm_write_str(" guess")
|
||||
if attempts_left>1 vm_write_str("es")
|
||||
if attempts_left>1
|
||||
vm_write_str("es")
|
||||
vm_write_str(" left. What is your next guess? ")
|
||||
vm_input_str(guess)
|
||||
ubyte guessednumber = str2ubyte(guess)
|
||||
|
@ -1,26 +1,15 @@
|
||||
%output raw
|
||||
%launcher none
|
||||
%import c64utils
|
||||
|
||||
~ main {
|
||||
|
||||
sub start() {
|
||||
ending(true)
|
||||
return ; @todo make return ending(true) actually work as well
|
||||
|
||||
return 99 ;@todo error message (no return values)
|
||||
return 99,44 ;@todo error message (no return values)
|
||||
return ending(false) ; @todo fix this, actuall needs to CALL ending even though no value is returned
|
||||
return ending(true) ;; @todo fix argument passing!
|
||||
|
||||
sub ending(success: ubyte) {
|
||||
return 99 ; @todo error message (no return values)
|
||||
return 99,44 ; @todo error message (no return values)
|
||||
return 99,44 ; @todo should check number of return values!!
|
||||
}
|
||||
|
||||
sub ending2() -> ubyte {
|
||||
return
|
||||
return 1
|
||||
return 2, 2 ; @todo error message number of return values
|
||||
c64scr.print_byte_decimal(success)
|
||||
c64scr.print_byte_decimal(success)
|
||||
c64scr.print_byte_decimal(success)
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import kotlin.system.exitProcess
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println("\nProg8 StackVM by Irmen de Jong (irmen@razorvine.net)")
|
||||
// @todo software license string
|
||||
// @todo decide on software license
|
||||
// println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
|
||||
println("**** This is a prerelease version. Please do not distribute! ****\n")
|
||||
|
||||
|
@ -96,9 +96,9 @@ class AstChecker(private val namespace: INameScope,
|
||||
if(returnStmt.values.size==1 && returnStmt.values[0] is FunctionCall) {
|
||||
val dt = (returnStmt.values[0] as FunctionCall).resultingDatatype(namespace, heap)
|
||||
if(dt!=null && expectedReturnValues.isEmpty())
|
||||
checkResult.add(SyntaxError("number of return values doesn't match subroutine return spec", returnStmt.position))
|
||||
checkResult.add(SyntaxError("invalid number of return values", returnStmt.position))
|
||||
} else
|
||||
checkResult.add(SyntaxError("number of return values doesn't match subroutine return spec", returnStmt.position))
|
||||
checkResult.add(SyntaxError("invalid number of return values", returnStmt.position))
|
||||
}
|
||||
|
||||
for (rv in expectedReturnValues.withIndex().zip(returnStmt.values)) {
|
||||
|
@ -177,6 +177,8 @@ class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
|
||||
if(returnStmt.values.isNotEmpty()) {
|
||||
// possibly adjust any literal values returned, into the desired returning data type
|
||||
val subroutine = returnStmt.definingSubroutine()!!
|
||||
if(subroutine.returntypes.size!=returnStmt.values.size)
|
||||
return returnStmt // mismatch in number of return values, error will be printed later.
|
||||
val newValues = mutableListOf<IExpression>()
|
||||
for(returnvalue in returnStmt.values.zip(subroutine.returntypes)) {
|
||||
val lval = returnvalue.first as? LiteralValue
|
||||
|
@ -41,13 +41,53 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
optimizeDataConversionAndUselessDiscards()
|
||||
optimizeVariableCopying()
|
||||
optimizeMultipleSequentialLineInstrs()
|
||||
optimizeCallReturnIntoJump()
|
||||
optimizeRestoreXSaveXIntoRestoreX()
|
||||
// todo: optimize stackvm code more
|
||||
// todo: stackvm replace rrestorex+rsavex combo by only rrestorex (note: can have label/comment inbetween)
|
||||
// todo: stackvm replace call X + return (without values) combo by a jump X
|
||||
|
||||
optimizeRemoveNops() // must be done as the last step
|
||||
optimizeMultipleSequentialLineInstrs() // once more
|
||||
optimizeRemoveNops() // once more
|
||||
}
|
||||
|
||||
private fun optimizeRemoveNops() {
|
||||
// remove nops (that are not a label)
|
||||
for (blk in blocks) {
|
||||
for (blk in blocks)
|
||||
blk.instructions.removeIf { it.opcode== Opcode.NOP && it !is LabelInstr }
|
||||
}
|
||||
|
||||
private fun optimizeRestoreXSaveXIntoRestoreX() {
|
||||
// replace rrestorex+rsavex combo by only rrestorex
|
||||
for(blk in blocks) {
|
||||
val instructionsToReplace = mutableMapOf<Int, Instruction>()
|
||||
|
||||
blk.instructions.asSequence().withIndex().filter {it.value.opcode!=Opcode.LINE}.windowed(2).toList().forEach {
|
||||
if(it[0].value.opcode==Opcode.RRESTOREX && it[1].value.opcode==Opcode.RSAVEX) {
|
||||
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
|
||||
}
|
||||
}
|
||||
|
||||
for (rins in instructionsToReplace) {
|
||||
blk.instructions[rins.key] = rins.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun optimizeCallReturnIntoJump() {
|
||||
// replaces call X followed by return, by jump X
|
||||
for(blk in blocks) {
|
||||
val instructionsToReplace = mutableMapOf<Int, Instruction>()
|
||||
|
||||
blk.instructions.asSequence().withIndex().filter {it.value.opcode!=Opcode.LINE}.windowed(2).toList().forEach {
|
||||
if(it[0].value.opcode==Opcode.CALL && it[1].value.opcode==Opcode.RETURN) {
|
||||
instructionsToReplace[it[1].index] = Instruction(Opcode.JUMP, callLabel = it[0].value.callLabel)
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
|
||||
}
|
||||
}
|
||||
|
||||
for (rins in instructionsToReplace) {
|
||||
blk.instructions[rins.key] = rins.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,18 +67,6 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
|
||||
return super.process(functionCall)
|
||||
}
|
||||
|
||||
override fun process(returnStmt: Return): IStatement {
|
||||
// if the return value is a subroutine call, replace this with a jump to the subroutine
|
||||
if(returnStmt.values.size==1 && returnStmt.values[0] is FunctionCall) {
|
||||
val call = returnStmt.values[0] as FunctionCall
|
||||
if(call.target.targetStatement(namespace) is Subroutine) {
|
||||
optimizationsDone++
|
||||
return Jump(null, call.target, null, call.position)
|
||||
}
|
||||
}
|
||||
return super.process(returnStmt)
|
||||
}
|
||||
|
||||
override fun process(ifStatement: IfStatement): IStatement {
|
||||
super.process(ifStatement)
|
||||
val constvalue = ifStatement.condition.constValue(namespace, heap)
|
||||
|
Loading…
x
Reference in New Issue
Block a user