Files
notes/docs/lectures/compilers/10_if_then_else.md
T
2026-10-04 15:24:17 +01:00

105 lines
2.5 KiB
Markdown

# Compiling Branches
**Mini Triangle Programs** -$parse$-> **AST** -$Code\space Generation$-> **TAM Programs** -$execute$ -> **Output**
Before, we could generate a list of instructions to be executed in sequence; now we need to implement code that's conditionally executed or executed multiple times.
```haskell
--Code for dealing with functions and commands
commCode :: VarEnv -> Command -> TAMProg
```
We will assume an if statement looks like this
IF $e$ THEN $c_1$ ELSE $c_2$
```python
if e then c1 else c2
IfThenElse e c1 c2
```
```haskell
expCode ve e
commCode ve c1
commCode ve c2
-- We dont want to execute both
```
- We can use `JUMPIFZ R1`, a branching function supplied by the TAM language.
- This means `commCode ve c1` & `commCode ve c2` need labels and a `JUMPA` after
```
MINI TRIANGLE PROGRAM
let var := 5
in
begin
if 1
then n := 6
else n := 7;
if 0
then n := 8
else n := 9;
end
```
```assembly
COMPILED VERSION
LOADL 5
LOAD 1 --if 1
JUMPIFZ "label1" --jump to else
LOAD 6 --load the number
STORE 0 --store 0 (stack[0] is 6 from line above) in the place of variable n, for other variables you would have to check the variable enviroment to get the stack address
JUMP "label2"
Label "label1"
LOAD 7
STORE 0
Label "label2"
LOAD 0
JUMPIFZ "label3"
```
![img](img/i.png)
### Generating Labels
Labels must **always** be **unique**.
This would require a global variable in our compiler to count the number of labels; Haskell does not allow global variables.
We can use the `stateMonad` instead.
```haskell
type LabelName = String
fresh :: ST Int LabelName
-- Whenever we call fresh, it generates a new label name
-- We can use do (because fresh is element of ST Monad)
fresh = do
n <- stGet --checks current state (which is num of labels)
stUpdate(n+1) --update number of labels
return ("#" : (show n)) -- # symbol to denote labels
-- show converts integer to string (fresh returns string)
commCode :: VarEnv -> Command -> ST Int [TAMInsrt]
-- TAMPrgm is interchangable with [TAMInstr]
commCode ve (IFTHENELSE e c1 c2) =
do l1 <- fresh
l2 <- fresh --generate the two labels needed for an if
let te = expCode ve e --the condition expression
tc1 <- commCode ve c1 --compile success branch
tc2 <- commCode ve c2 --compile else branch
return (te ++ [JUMPIFZ l1] ++ tc1 ++ [JUMP l2]
++ [Label l1] ++ tc2 ++ [Label l2])
--then return the tam instructions
```
**REMINDER**: `expCode` is a function that takes a variable environment `ve` and an expression `e` and generates a list of TAM instructions.