Add the rest of university notes
This commit is contained in:
366 files changed
+9844
-110
No files matched your search
@@ -0,0 +1,149 @@
|
||||
# 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''))
|
||||
```
|
||||
Reference in new issue
Block a user