mirror of
https://github.com/irmen/prog8.git
synced 2024-05-29 01:41:32 +00:00
doc and tweak subexpression extraction a tiny bit
This commit is contained in:
parent
cfe3fcc9e7
commit
35f3e8708b
|
@ -32,11 +32,15 @@ private var tempVarCounter = 0
|
||||||
private fun optimizeCommonSubExpressions(program: PtProgram, errors: IErrorReporter): Int {
|
private fun optimizeCommonSubExpressions(program: PtProgram, errors: IErrorReporter): Int {
|
||||||
|
|
||||||
fun extractableSubExpr(expr: PtExpression): Boolean {
|
fun extractableSubExpr(expr: PtExpression): Boolean {
|
||||||
|
if(expr is PtArrayIndexer && expr.index.isSimple())
|
||||||
|
return false
|
||||||
|
if (expr is PtMemoryByte && expr.address.isSimple())
|
||||||
|
return false
|
||||||
|
|
||||||
val result = if(expr is PtBinaryExpression)
|
val result = if(expr is PtBinaryExpression)
|
||||||
expr.type !in ByteDatatypes ||
|
expr.type !in ByteDatatypes ||
|
||||||
!expr.left.isSimple() ||
|
!(expr.left.isSimple() && expr.right.isSimple()) ||
|
||||||
!expr.right.isSimple() ||
|
(expr.operator !in LogicalOperators && expr.operator !in BitwiseOperators)
|
||||||
(expr.operator !in LogicalOperators && expr.operator !in BitwiseOperators)
|
|
||||||
else if (expr is PtArrayIndexer && expr.type !in ByteDatatypes)
|
else if (expr is PtArrayIndexer && expr.type !in ByteDatatypes)
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
|
|
|
@ -672,9 +672,9 @@ Multiple return values
|
||||||
Normal subroutines can only return zero or one return values.
|
Normal subroutines can only return zero or one return values.
|
||||||
However, the special ``asmsub`` routines (implemented in assembly code) or ``romsub`` routines
|
However, the special ``asmsub`` routines (implemented in assembly code) or ``romsub`` routines
|
||||||
(referencing an external routine in ROM or elsewhere in memory) can return more than one return value.
|
(referencing an external routine in ROM or elsewhere in memory) can return more than one return value.
|
||||||
For example a status in the carry bit and a number in A, or a 16-bit value in A/Y registers.
|
For example a status in the carry bit and a number in A, or a 16-bit value in A/Y registers and some more values in R0 and R1.
|
||||||
In these cases, it is possible to do a "multi assign" where the multiple return values of the subroutine call,
|
In all of these cases, you have to "multi assign" all return values of the subroutine call to something.
|
||||||
are all assigned to individual assignment targets. You simply write them as a comma separated list,
|
You simply write the assignment targets as a comma separated list,
|
||||||
where the element's order corresponds to the order of the return values declared in the subroutine's signature.
|
where the element's order corresponds to the order of the return values declared in the subroutine's signature.
|
||||||
So for instance::
|
So for instance::
|
||||||
|
|
||||||
|
@ -686,6 +686,14 @@ So for instance::
|
||||||
|
|
||||||
asmsub multisub() -> uword @AY, bool @Pc, ubyte @X { ... }
|
asmsub multisub() -> uword @AY, bool @Pc, ubyte @X { ... }
|
||||||
|
|
||||||
|
.. sidebar:: Using just one of the values
|
||||||
|
|
||||||
|
Sometimes it is easier to just have a single return value in the subroutine's signagure (even though it
|
||||||
|
actually may return multiple values): this avoids having to put ``void`` for all other values.
|
||||||
|
It also allows it to be called in expressions such as if-statements again.
|
||||||
|
Examples of these second 'convenience' definition are library routines such as ``cbm.STOP2`` and ``cbm.GETIN2``,
|
||||||
|
that only return a single value where the "official" versions ``STOP`` and ``GETIN`` always return multiple values.
|
||||||
|
|
||||||
**Skipping values:** you are allowed to omit assignments of one or more values by putting ``void`` as the assignment target.
|
**Skipping values:** you are allowed to omit assignments of one or more values by putting ``void`` as the assignment target.
|
||||||
One of the cases where this is useful is with boolean values returned in status flags such as the carry flag.
|
One of the cases where this is useful is with boolean values returned in status flags such as the carry flag.
|
||||||
Storing that flag as a boolean in a variable first, and then possibly adding an ``if flag...`` statement afterwards, is a lot less
|
Storing that flag as a boolean in a variable first, and then possibly adding an ``if flag...`` statement afterwards, is a lot less
|
||||||
|
@ -693,6 +701,12 @@ efficient than just keeping the flag as-is and using a conditional branch such a
|
||||||
So in the case above that could be::
|
So in the case above that could be::
|
||||||
|
|
||||||
wordvar, void, bytevar = multisub()
|
wordvar, void, bytevar = multisub()
|
||||||
|
if_cs
|
||||||
|
something()
|
||||||
|
|
||||||
|
Notice that a call to a subroutine that returns multiple values cannot be used inside an expression,
|
||||||
|
because expression terms always need to be a single value. You'll have to use a separate multi-assignment
|
||||||
|
first and then use the result of that in the expression. However, also read the sidebar about a possible alternative.
|
||||||
|
|
||||||
|
|
||||||
Subroutine definitions
|
Subroutine definitions
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
check docs on assign about status register in assignment (can no longer be ignored, use void to not assign it)
|
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user