mirror of
https://github.com/irmen/prog8.git
synced 2024-11-25 19:31:36 +00:00
allow boolean when conditions, optimize into a regular if
This commit is contained in:
parent
15ee90e99c
commit
b8284a147d
@ -391,4 +391,47 @@ class StatementOptimizer(private val program: Program,
|
|||||||
else
|
else
|
||||||
noModifications
|
noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun after(whenStmt: When, parent: Node): Iterable<IAstModification> {
|
||||||
|
|
||||||
|
fun replaceWithIf(condition: Expression, trueBlock: AnonymousScope, elseBlock: AnonymousScope?): List<IAstModification> {
|
||||||
|
val ifStmt = IfElse(condition, trueBlock, elseBlock ?: AnonymousScope(mutableListOf(), whenStmt.position), whenStmt.position)
|
||||||
|
errors.warn("for boolean condition a normal if statement is preferred", whenStmt.position)
|
||||||
|
return listOf(IAstModification.ReplaceNode(whenStmt, ifStmt, parent))
|
||||||
|
}
|
||||||
|
|
||||||
|
if(whenStmt.condition.inferType(program).isBool) {
|
||||||
|
if(whenStmt.choices.all { it.values?.size==1 }) {
|
||||||
|
if (whenStmt.choices.all { it.values!!.single().constValue(program)!!.number in arrayOf(0.0, 1.0) }) {
|
||||||
|
// it's a when statement on booleans that can just be replaced by an if or if..else.
|
||||||
|
if (whenStmt.choices.size == 1) {
|
||||||
|
return if(whenStmt.choices[0].values!![0].constValue(program)!!.number==1.0) {
|
||||||
|
replaceWithIf(whenStmt.condition, whenStmt.choices[0].statements, null)
|
||||||
|
} else {
|
||||||
|
val notCondition = BinaryExpression(whenStmt.condition, "==", NumericLiteral(DataType.UBYTE, 0.0, whenStmt.condition.position), whenStmt.condition.position)
|
||||||
|
replaceWithIf(notCondition, whenStmt.choices[0].statements, null)
|
||||||
|
}
|
||||||
|
} else if (whenStmt.choices.size == 2) {
|
||||||
|
var trueBlock: AnonymousScope? = null
|
||||||
|
var elseBlock: AnonymousScope? = null
|
||||||
|
if(whenStmt.choices[0].values!![0].constValue(program)!!.number==1.0) {
|
||||||
|
trueBlock = whenStmt.choices[0].statements
|
||||||
|
} else {
|
||||||
|
elseBlock = whenStmt.choices[0].statements
|
||||||
|
}
|
||||||
|
if(whenStmt.choices[1].values!![0].constValue(program)!!.number==1.0) {
|
||||||
|
trueBlock = whenStmt.choices[1].statements
|
||||||
|
} else {
|
||||||
|
elseBlock = whenStmt.choices[1].statements
|
||||||
|
}
|
||||||
|
if(trueBlock!=null && elseBlock!=null) {
|
||||||
|
return replaceWithIf(whenStmt.condition, trueBlock, elseBlock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return noModifications
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1341,8 +1341,14 @@ internal class AstChecker(private val program: Program,
|
|||||||
constvalue == null -> errors.err("choice value must be a constant", whenChoice.position)
|
constvalue == null -> errors.err("choice value must be a constant", whenChoice.position)
|
||||||
constvalue.type !in IntegerDatatypes -> errors.err("choice value must be a byte or word", whenChoice.position)
|
constvalue.type !in IntegerDatatypes -> errors.err("choice value must be a byte or word", whenChoice.position)
|
||||||
conditionType isnot constvalue.type -> {
|
conditionType isnot constvalue.type -> {
|
||||||
if(conditionType.isKnown)
|
if(conditionType.isKnown) {
|
||||||
errors.err("choice value datatype differs from condition value", whenChoice.position)
|
if(conditionType.istype(DataType.BOOL)) {
|
||||||
|
if(constvalue.number!=0.0 && constvalue.number!=1.0)
|
||||||
|
errors.err("choice value datatype differs from condition value", whenChoice.position)
|
||||||
|
} else {
|
||||||
|
errors.err("choice value datatype differs from condition value", whenChoice.position)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,5 +334,22 @@ main {
|
|||||||
}"""
|
}"""
|
||||||
compileText(VMTarget(), optimize=false, src, writeAssembly=false) shouldNotBe null
|
compileText(VMTarget(), optimize=false, src, writeAssembly=false) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("when on booleans") {
|
||||||
|
val src = """
|
||||||
|
main
|
||||||
|
{
|
||||||
|
sub start()
|
||||||
|
{
|
||||||
|
bool choiceVariable=true
|
||||||
|
when choiceVariable {
|
||||||
|
false -> cx16.r0++
|
||||||
|
true -> cx16.r1++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
|
||||||
|
compileText(VMTarget(), optimize=false, src, writeAssembly=false) shouldNotBe null
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,32 +1,16 @@
|
|||||||
%import textio
|
%import textio
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
; (127 instructions in 15 chunks, 47 registers)
|
main
|
||||||
; 679 steps
|
{
|
||||||
|
; 00f9
|
||||||
|
sub start()
|
||||||
main {
|
{
|
||||||
|
bool rasterIrqAfterSubs=false
|
||||||
sub start() {
|
when rasterIrqAfterSubs {
|
||||||
uword i
|
false -> txt.print("false\n")
|
||||||
uword n
|
true -> txt.print("true\n")
|
||||||
|
}
|
||||||
repeat 10 {
|
txt.print("done")
|
||||||
txt.chrout('.')
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
n=10
|
|
||||||
for i in 0 to n step 3 {
|
|
||||||
txt.print_uw(i)
|
|
||||||
txt.nl()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
n=0
|
|
||||||
for i in 10 downto n step -3 {
|
|
||||||
txt.print_uw(i)
|
|
||||||
txt.nl()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -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.1
|
version=9.2-SNAPSHOT
|
||||||
|
Loading…
Reference in New Issue
Block a user