add a suggestion to use when statement if it seems appropriate

This commit is contained in:
Irmen de Jong
2021-12-28 15:39:46 +01:00
parent 0feeb88024
commit b2876b0a03
6 changed files with 32 additions and 16 deletions

View File

@@ -786,8 +786,8 @@ class AsmGen(private val program: Program,
is When -> translate(stmt) is When -> translate(stmt)
is AnonymousScope -> translate(stmt) is AnonymousScope -> translate(stmt)
is BuiltinFunctionPlaceholder -> throw AssemblyError("builtin function should not have placeholder anymore") is BuiltinFunctionPlaceholder -> throw AssemblyError("builtin function should not have placeholder anymore")
is UntilLoop -> throw AssemblyError("do..until should have been desugared to jumps") is UntilLoop -> throw AssemblyError("do..until should have been converted to jumps")
is WhileLoop -> throw AssemblyError("while should have been desugared to jumps") is WhileLoop -> throw AssemblyError("while should have been converted to jumps")
is Block -> throw AssemblyError("block should have been handled elsewhere") is Block -> throw AssemblyError("block should have been handled elsewhere")
is Break -> throw AssemblyError("break should have been replaced by goto") is Break -> throw AssemblyError("break should have been replaced by goto")
else -> throw AssemblyError("missing asm translation for $stmt") else -> throw AssemblyError("missing asm translation for $stmt")

View File

@@ -36,11 +36,11 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
} }
override fun before(whileLoop: WhileLoop, parent: Node): Iterable<IAstModification> { override fun before(whileLoop: WhileLoop, parent: Node): Iterable<IAstModification> {
throw FatalAstException("while should have been desugared to jumps") throw FatalAstException("while should have been converted to jumps")
} }
override fun before(untilLoop: UntilLoop, parent: Node): Iterable<IAstModification> { override fun before(untilLoop: UntilLoop, parent: Node): Iterable<IAstModification> {
throw FatalAstException("do..until should have been desugared to jumps") throw FatalAstException("do..until should have been converted to jumps")
} }
override fun before(block: Block, parent: Node): Iterable<IAstModification> { override fun before(block: Block, parent: Node): Iterable<IAstModification> {

View File

@@ -91,6 +91,19 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter)
return noModifications return noModifications
} }
override fun before(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
if(expr.operator == "or") {
val leftBinExpr = expr.left as? BinaryExpression
val rightBinExpr = expr.right as? BinaryExpression
if(leftBinExpr!=null && leftBinExpr.operator=="==" && rightBinExpr!=null && rightBinExpr.operator=="==") {
if(leftBinExpr.right is NumericLiteralValue && rightBinExpr.right is NumericLiteralValue) {
errors.warn("consider using when statement to test for multiple values", expr.position)
}
}
}
return noModifications
}
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> { override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
if(expr.operator in ComparisonOperators) { if(expr.operator in ComparisonOperators) {
val leftConstVal = expr.left.constValue(program) val leftConstVal = expr.left.constValue(program)

View File

@@ -11,9 +11,6 @@ import prog8.ast.statements.FunctionCallStatement
import prog8.ast.statements.Label import prog8.ast.statements.Label
import prog8.codegen.target.Cx16Target import prog8.codegen.target.Cx16Target
import prog8tests.helpers.* import prog8tests.helpers.*
import prog8tests.helpers.assertFailure
import prog8tests.helpers.assertSuccess
import prog8tests.helpers.compileFile
import kotlin.io.path.name import kotlin.io.path.name

View File

@@ -3,7 +3,10 @@ TODO
For next compiler release (7.6) For next compiler release (7.6)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
... add "if X in [1,2,3] {...}" syntax , as an alternative to when X { 1,2,3-> {...} }
if the array is not a literal, do a normal containment test instead in an array or string or range
change "consider using when statement..." to "consider using if X in [..] or when statement..."
Blocked by an official Commander-x16 v39 release Blocked by an official Commander-x16 v39 release
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,12 +16,14 @@ Blocked by an official Commander-x16 v39 release
Future Future
^^^^^^ ^^^^^^
- rethink the whole "isAugmentable" business. Because the way this is determined, should always also be exactly mirrorred in the AugmentableAssignmentAsmGen or you'll get a crash at code gen time. - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``v_``
- simplifyConditionalExpression() should not split expression if it still results in stack-based evaluation then we can get rid of the instruction lists in the machinedefinitions as well?
- fix the asm-labels problem (github issue #62) - fix the asm-labels problem (github issue #62)
- simplifyConditionalExpression() should not split expression if it still results in stack-based evaluation
- get rid of all TODO's in the code - get rid of all TODO's in the code
- improve testability further, add more tests - improve testability further, add more tests
- use more of Result<> and Either<> to handle errors/ nulls better - use more of Result<> and Either<> to handle errors/ nulls better
- rethink the whole "isAugmentable" business. Because the way this is determined, should always also be exactly mirrorred in the AugmentableAssignmentAsmGen or you'll get a crash at code gen time.
- can we get rid of pieces of asmgen.AssignmentAsmGen by just reusing the AugmentableAssignment ? generated code should not suffer - can we get rid of pieces of asmgen.AssignmentAsmGen by just reusing the AugmentableAssignment ? generated code should not suffer
- add a switch to not create the globals-initialization logic, but instead create a smaller program (that can only run once though) - add a switch to not create the globals-initialization logic, but instead create a smaller program (that can only run once though)
- c64: make the graphics.BITMAP_ADDRESS configurable (VIC banking) - c64: make the graphics.BITMAP_ADDRESS configurable (VIC banking)
@@ -27,7 +32,7 @@ Future
- add a flood fill routine to gfx2? - add a flood fill routine to gfx2?
- add a diskio.f_seek() routine for the Cx16 that uses its seek dos api? - 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)? - make it possible for diskio to read and write from more than one file at the same time (= use multiple io channels)?
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``v_`` - fix problems in c128 target
- [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 ... - [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? Perhaps replace all uses of .proc/.pend by .block/.bend will fix that?
(but we lose the optimizing aspect of the assembler where it strips out unused code. (but we lose the optimizing aspect of the assembler where it strips out unused code.
@@ -36,13 +41,9 @@ Future
More code optimization ideas More code optimization ideas
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- automatically convert if statements that test for multiple values (if X==1 or X==2..) to if X in [1,2,..] statements
- byte typed expressions should be evaluated in the accumulator where possible, without (temp)var - byte typed expressions should be evaluated in the accumulator where possible, without (temp)var
for instance value = otherbyte >> 1 --> lda otherbite ; lsr a; sta value for instance value = otherbyte >> 1 --> lda otherbite ; lsr a; sta value
- rewrite multiple choice if into when:
if X==1 or X==2 or X==3 { truepart } else { falsepart }
-> when X { 1,2,3->truepart else->falsepart }
same with assignment if the lhs is simple var or memaddr
- rewrite expression tree evaluation such that it doesn't use an eval stack but flatten the tree into linear code that uses a fixed number of predetermined value 'variables' - rewrite expression tree evaluation such that it doesn't use an eval stack but flatten the tree into linear code that uses a fixed number of predetermined value 'variables'
- this removes the need for the BinExprSplitter? (which is problematic and very limited now) - this removes the need for the BinExprSplitter? (which is problematic and very limited now)
- introduce byte-index operator to avoid index multiplications in loops over arrays? see github issue #4 - introduce byte-index operator to avoid index multiplications in loops over arrays? see github issue #4

View File

@@ -9,6 +9,11 @@ main {
if xx<100 { if xx<100 {
foobar() foobar()
} }
if xx==9 or xx==10 or xx==11 or xx==12 or xx==13 {
txt.print("9 10 11\n")
}
txt.print("\nthe end\n") txt.print("\nthe end\n")
} }