Add the rest of university notes
This commit is contained in:
366 files changed
+9844
-110
No files matched your search
@@ -0,0 +1,164 @@
|
||||
# Variable Environments
|
||||
|
||||
```haskell
|
||||
type VarEnv = [(Identifier, StkAddress)]
|
||||
-- String Int
|
||||
|
||||
address :: VarEnv -> Identifer -> StkAddress
|
||||
address ve v = case lookup v ve of
|
||||
Nothing -> error "variable not in enviroment"
|
||||
Just a -> a
|
||||
--Expr is AST of expressions
|
||||
expCode :: VarEnv -> Expr -> [TAMInstr]
|
||||
expCode ve (LitInteger x) = [LOADL x]
|
||||
-- we must put variable value on top of the stack
|
||||
expCode ve (Var v) = [LOAD (address ve v)]
|
||||
```
|
||||
|
||||
How do we build a variable environment?
|
||||
|
||||
Every program begins with a sequence of variable declarations
|
||||
|
||||
```js
|
||||
var x := 7;
|
||||
var y := 3;
|
||||
var z;
|
||||
var w := x * y - 2
|
||||
```
|
||||
|
||||
The parser will turn this into a list of AST for declarations
|
||||
|
||||
Then we have to use this to build a variable environment, and generate TAM code to write the values of the variables onto the stack.
|
||||
|
||||
We do this using the state monad
|
||||
|
||||
- We use as an underlying state the variable environment itself, as we build it sequentially
|
||||
- We also keep the stack address as a state, where it keeps the next free address
|
||||
|
||||
```haskell
|
||||
declsCode :: [Declarations] -> (VarEnv, [TAMInstr])
|
||||
declsCode ds = let (tam,(ve,0a)) app (declsTAM ds) ([],0) --initial state
|
||||
in (ve,tam)
|
||||
|
||||
declsTAM :: [Declarations] -> ST (VarEnv, StkAddress) [TAMInstr]
|
||||
declsTAM [] = return []
|
||||
declsTAM (d:ds) = do
|
||||
td <- declTAM d
|
||||
tds <- declsTAM ds
|
||||
return (td++tds)
|
||||
|
||||
declTAM :: Declarations -> ST (VarEnv, StkAddress) [TAMInstr]
|
||||
declTAM (VarDecl v) = do
|
||||
(ve,a) <- stState
|
||||
stUpdate ((v,a) : ve, a+1)
|
||||
return [LOADL 0]
|
||||
declTAM (VarInit v e) = do
|
||||
(ve,a) <- stState
|
||||
stUpdate ((v,a) : ve, a+1)
|
||||
return (expCode ve e)
|
||||
|
||||
```
|
||||
|
||||
```shell
|
||||
λ> parseAll declarations "var x:=7;var y:=3;var z;var w:=x*y-2"
|
||||
[VarInit "x" (LitInteger 7), VarInit "y" (LitInteger 3), VarDecl "z", VarInit "w" (BinOp Subtraction (BinOp Multiplication (Var "x") (Var "y")) (LitInteger 2))]
|
||||
|
||||
λ> ds = parseAll declarations "var x:=7;var y:=3;var z;var w:=x*y-2"
|
||||
|
||||
λ> (ve,tam) = declsCode ds
|
||||
λ> ve
|
||||
[("w",3),("z",2),("y",1),("x",0)]
|
||||
λ> tam
|
||||
[LOADL 7, LOADL 3m LOADL 0, LOAD 0, LOAD 1, MUL, LOADL 2, SUB]
|
||||
λ> execTAM [] tam
|
||||
[19, 0, 3, 7]
|
||||
```
|
||||
|
||||
## Designing ASTs for any grammar
|
||||
|
||||
- We turn every non-terminal of the grammar into a type of AST
|
||||
|
||||
- We turn every production of the non-terminal into a constructor of the type
|
||||
|
||||
Defining the grammar of TAM
|
||||
|
||||
```
|
||||
command ::= identifier := expr
|
||||
| if expr then command else command
|
||||
| while expr do command
|
||||
| getint ( identifier )
|
||||
| printint ( expr )
|
||||
| begin commands end
|
||||
```
|
||||
|
||||
Here: `:=`, `if`, `then`, `else`, `while`, `do`, `getint`, `printint`, `begin`, `end`, `(`, `)` are terminal
|
||||
|
||||
```haskell
|
||||
data Command =
|
||||
|
||||
datatypes Identifier = String, Expr, Commands -- [Command]
|
||||
```
|
||||
|
||||
Assign to every production one constructor for the data type.
|
||||
|
||||
This means we will have 6 constructors called `Assignment`, `IfThenElse`, `WhileDo`, `GetInt`, `PrintInt`, `BeginEnd`
|
||||
|
||||
```haskell
|
||||
data Command = Assignment Identifier Expr
|
||||
| IfThenElse Expr Command Command
|
||||
| WhileDo Expr Command
|
||||
| GetInt Identifer
|
||||
| PrintInt Expr
|
||||
| BeginEnd [Command]
|
||||
|
||||
type Commands = [Command]
|
||||
--or
|
||||
data Commands = SingleC Command
|
||||
| MultipleC Command Commands
|
||||
```
|
||||
|
||||
## Organising a Haskell Project
|
||||
|
||||
There are 6 Haskell modules, `Main.hs` is the entry point.
|
||||
|
||||
###### Defining a Module
|
||||
|
||||
```haskell
|
||||
module <filename> where
|
||||
import ...
|
||||
--definitions
|
||||
newtype ...
|
||||
--functions
|
||||
func :: a -> b
|
||||
```
|
||||
|
||||
Note file name must start with a capital
|
||||
|
||||
When you import a module, can can use functions defined in the module
|
||||
|
||||
```haskell
|
||||
data FileType = EXP | TAM
|
||||
data Option = Trace | Run | Evaluate
|
||||
|
||||
main :: IO () --input output monad
|
||||
```
|
||||
|
||||
this is the entry point, to compile
|
||||
|
||||
```shell
|
||||
$ ghc Main.hs -o aec
|
||||
$ ./aec arith_example.exp --evaluate
|
||||
Evaluating Expression: 45
|
||||
```
|
||||
|
||||
```haskell
|
||||
stUpdate :: st -> ST st ()
|
||||
stUpdate s = S (\_ -> ((), s))
|
||||
|
||||
stGet :: ST st st
|
||||
stGet = S (\s -> (s,s))
|
||||
|
||||
stRevise :: (st -> st) -> ST st ()
|
||||
stRevise f = stGet >>= stUpdate . f
|
||||
```
|
||||
|
||||
Reference in new issue
Block a user