Branching rules
Last time I talked about synthesis and IL generation. Currently, half of the statements already write valid byte code. I have now completed the branching infrastructure that I mentioned in my previous blog post, and most conditional structures and loops are now prepared – including the If
, While
, and Until
structures. The For-Next
loop and the Select-Case
structure are next. But before going there I decided to wrap up a quick summary about branching rules and what they mean in terms of code compilation.
First of all, there’s a mechanic in place that eliminates unreachable code. For example, if you had an If condition that has a constant expression that always evaluates to false, the compiler knows this during compile time and will not write the byte code for that block. Similarly, if you had a While
loop that is known to be always true the compiler doesn’t write the byte code for the expression at all. Code elimination also applies to nested code blocks, meaning that everything inside an unreachable code block is ignored when the byte code output is written. Next, let’s look at the specs:
The If structure
- The
If
andElseIf
statements must know the nextElseIf
/Else
statement in order to branch when the expression is false - The
If
,ElseIf
andElse
statements must know theEndIf
statement that is associated with the condition chain; TheIf
statement needs it in order to branch when the expression is false, and theElseIf
andElse
statements need it in order to issue an unconditional jump to indicate the end of the previous block - The
ElseIf
andElse
statements must add an unconditional jump to the correspondingEndIf
statement before any other byte code unless the statement in question is andElseIf
with a constant value expression of false - If the
If
/ElseIf
expression is a constant value, don’t write expression byte code - If any of the
If
orElseIf
blocks evaluated to a constant expression of true, don’t write byte code for any of the subsequent blocks in the same chain - If an
If
block or anElseIf
block has a constant expression of false, don’t write its byte code. This includes nested code blocks
In addition to the rules listed above there are some minor tweaks that accomplish cleaner byte code output; I’ve eliminated some branching instructions that are not needed, for example.
The Repeat-Until structure
- The
Until
andForever
statements must know the correspondingRepeat
statement in order to branch to the correct location - If the
Until
statement’s expression is a constant value of true, do nothing - If the
Until
statement’s expression is a constant value of false, add an unconditional jump - The
Forever
statement just adds an unconditional jump
The While-EndWhile structure
- The
While
statement needs to know the correspondingEndWhile
statement in order to branch when the expression is false - The
EndWhile
statement needs to know the correspondingWhile
statement in order to issue an unconditional jump - If the
While
statement’s expression is a constant value of false, don’t write byte code for the expression or code block - If the
While
statement’s expression is a constant value of true, don’t write the expression’s byte code - The
EndWhile
statement only adds an unconditional jump to theWhile
statement
Controlling loops
The old “Exit
” statement is now renamed as “Break
”. It exits the Repeat
, While
, For
, and Foreach
loops, and continues execution from after the loop.
Similarly, a new loop control statement has been added. The “Continue
” statement continues the encapsulating loop from its next iteration pass, but doesn’t exit the loop unless the associated condition dictates so.
The implementation of these is quite straight-forward; The Break
statement needs to know the loop’s ending statement, and the Continue
statement needs to know the loop’s starting statement. Both issue an unconditional jump.
I haven’t yet implemented these, and will retain doing so until I get the For-Next
structure done. I might write a similar blog post about the For-Next
structure and Select-Case
structure next time…