105 lines
2.5 KiB
Markdown
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 thats 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"
|
|
```
|
|
|
|

|
|
|
|
### Generating Labels
|
|
|
|
Labels must **always** be **unique**.
|
|
|
|
This would require a global variable in our compiler to count the number of labels, haskell doesnt 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.
|