Files
notes/docs/lectures/compilers/08_variables.md
T

150 lines
4.3 KiB
Markdown

# Compiling Variables
A variable is identified by a alphanumeric string. We can store this as a list of pairs, with the variables identifier and its value.
Variable Environment or VarEnv - `[(Identifier, Stack Address)]`
A stack address is an integer value that specifies where in the stack that variable is contained. The bottom of the stack is reserved for variable values.
The bottom of the stack is indexed `0`.
Lets say our environment consists of 3 variables named x,y,z. It would look like:
`[("z",2), ("y",1), ("x",0)]`
| Variables | Stack (Values) | Index |
| :-------: | :------------: | :---: |
| x | 7 | 0 |
| y | 2 | 1 |
| z | 9 | 2 |
To get the value of a variable from the stackk, TAM uses the instruction `LOADL a` where `a` is a stack address. `LOADL` will get the value and copy the value to the top of the stack.
`LOAD a` - copy address a to top of stack
`STORE a` - pop top of stack to address a
For example if `LOADL 2` is called, it will effect the stack in the following way:
| Variables | Stack (Values) | Index |
| :-------: | :------------: | :---: |
| x | 7 | 0 |
| y | 2 | 1 |
| z | 9 | 2 |
| | … | |
| | 9 | |
```haskell
expCode :: VarEnv -> Expr -> [TAMInst]
```
Before we just called the abstract syntax tree `AST` however with the extended grammar now we will have multiple ASTs, one for programs, one for commands, expressions. The AST for expressions we call `Expr`.
Remember in our compiler, the stack is represented and stored as a list, with the top of the stack being the head of the list.
## Declaration of Variables
```js
let var x; //no value given means initialised to 0
var y := 5 //note no semicolon
var z;
in ...
```
For the code above, we need to generate a VarEnv. The compiler needs to generate a variable environment and TAM code.
VarEnv: `[("z",2), ("y",1), ("x",0)]`
TAM code stack: `[0,5,0]`
However we also need to account for expressions such as:
```js
let var x := 3;
var y := 5;
var z := x*y
```
```haskell
declarationCompiler :: [Declaration] -> (VarEnv, [TAMInstr])
VarEnv :: [(Identifier, Address)]
```
NOTE: this can be defined with functions given in the `FunParser` library. Or using a `state monad`
### State Monad
$s_0 \rightarrow s_1 \rightarrow s_2 \rightarrow s_n$ for each change in state, there's a corresponding result generated.
$$
a_0 \quad\space\space\space a_1 \quad\space\space\space a_n
$$
- For each of these states, we need a variable environment and address
- For each of the results, we need to generate TAM instructions.
Example: $s_n$ could be your bank balance and $a_n$ could be the purchase history.
- In our case:
- States are VarEnv & next free address space for next variable
- Outputs are TAM instructions
We to define a type that models a state transform, while at the same time producing a result. This is where a state monad comes in.
```haskell
newtype ST st a = S (\st -> (a, st))
-- ST - state transformer
-- st - type of states
-- a - type of output/results
-- S - constructor
-- \st a function that takes a state and returns a value along with a new state
-- this is a general type definition with state type st and result type a
-- this is still just a type constructor, has to be applied to a type
instance Functor (ST st)
instance Applicative (ST st)
instance Monad (ST st)
--as we inherit the monad class, we can use do notation
```
```haskell
newtype ST st a = S (\st -> (a, st))
--type definition
ST Int
--type constructor
ST Int String
--type
```
```haskell
app :: ST st a -> st -> (a, st)
app (S f) x = f x
--applies the constructor to state x
```
```haskell
instance Functor (ST st) where
--fmap :: (a->b) -> ST st a -> ST st b
fmap g sta = S (\s -> let (x,s') = app sta s
in (g x, s'))
```
```haskell
instance Applicative (ST st) where
--pure :: a -> ST st a
pure x = S (\s -> (x,s))
--(<*>) :: (ST st (a -> b)) -> ST st a -> ST st b
stf <*> sta = S (\s -> let (f,s') = app stf s
(x,s'') = app sta s')
in (f x, s''))
```
```haskell
instance Monad (ST st) where
return = pure
-- (>>=) :: (ST st a) -> (a -> ST st b) -> ST st b
sta >>= f = S (\s -> let (x,s') = app sta s
(y,s'') = app (f x) s'
in (y,s''))
```