diff --git a/cm b/cm
deleted file mode 100755
index c1f44fd..0000000
Binary files a/cm and /dev/null differ
diff --git a/test/.DS_Store b/test/.DS_Store
deleted file mode 100644
index 23b06df..0000000
Binary files a/test/.DS_Store and /dev/null differ
diff --git a/test/website/.DS_Store b/test/website/.DS_Store
deleted file mode 100644
index e9f3143..0000000
Binary files a/test/website/.DS_Store and /dev/null differ
diff --git a/test/website/HTML/.DS_Store b/test/website/HTML/.DS_Store
deleted file mode 100644
index 609049f..0000000
Binary files a/test/website/HTML/.DS_Store and /dev/null differ
diff --git a/test/website/HTML/A5Week1.html b/test/website/HTML/A5Week1.html
deleted file mode 100644
index 17559e5..0000000
--- a/test/website/HTML/A5Week1.html
+++ /dev/null
@@ -1,279 +0,0 @@
-
CSCU9A5 Week 1
-
Read Chapters 1 and 2 of Clean Code
-
-
You get the drift. Indeed, the ratio of time spent reading vs. writing is well over 10:1. We are constantly reading old code as part of the effort to write new code. Because this ratio is so high, we want the reading of code to be easy, even if it makes the writing harder. Of course there’s no way to write code without reading it, so making it easy to read actually makes it easier to write.
-
-
Class names
-
-
Classes and objects should have noun or noun phrase names like Customer, WikiPage, Account, and AddressParser. Avoid words like Manager, Processor, Data, or Info in the name of a class. A class name should not be a verb.
-
-
Method names
-
-
Methods should have verb or verb phrase names like postPayment, deletePage, or save. Accessors, mutators, and predicates should be named for their value and prefixed with get, set, and is according to the javabean standard.
-
-
string name = employee.getName();
-customer.setName("mike");
-if (paycheck.isPosted())...
-
-
-
When constructors are overloaded, use static factory methods with names that describe the arguments. For example,
Consider enforcing their use by making the corresponding constructors private.
-
-
Note: Listings 2-1 and his solution in 2-2 make me cringe
-
Its too long! Random methods with very long names makes it hard to read on screens like IDE's. You also end up jumping around the code, back and forth and trying to figure out what method returns what and where the next bit of code goes. There is also the issue of creating entire methods for one case of something happening. You could easily split the decision making within the one method with better coding. You can check if there is more and 0 counts and then handle what happens there. We already have access to all the variables we need passed as parameters, why split this off into many methods. I hate it.
-
Extended BNF (EBNF)
-
-
We can use * to make things appear 0-to-many times by wrapping then in brackets
-
-
N ::== a | (b | c)*
-
-
This can be read as "N may consist of a or alternatively a series of characters comprising zero to many b or c". A valid syntax matching this rule would include:
-
-
"a"
-
an empty string (the * helps with this as its 0 to many)
-
"b"
-
"c"
-
"bc"
-
"cb"
-
"cbcbcbc"
-
or "ccccccb"
-
-
Example
-
We have a simple programming language that allows the user to write arithmetic sums for some existing variables a, b, c, d, or e. We can use +, -, /, * and () on the variables too.
-
Expression ::== primary-Expression (Operator primary-Expression)*
-primary-Expression ::== Identifier
- | (Expression)
-Idenifier ::== a | b | c | d | e
-Operator ::== + | - | / | *
-
-
For example:
-
a + (b * c)
-
-
Here you can view the Java specifications as well as Pythons! Go has a very good break down of its grammar, with lots of documentation!
-
Triangle
-
Features of Triangle
-
-
-
Three primitive types of variables:
-
-
Boolean (i.e. true or false)
-
Char (a single character; same as the Java char type)
-
Integer (values between -32767 and 32767)
-
-
-
-
Two types of composite variable:
-
-
Records (a bit like dictionaries in python)
-
Arrays
-
-
-
-
There are no strings or floating point types built-in
-
-
-
Let blocks are used to declare local constants, variables, procedures and functions (see repl.tri and factorials.ri below)
-
-
-
The only conditional command is if and the only loop command is while
-
-
-
if commands look like this:
-
-
if x < y then dostuff else dootherstuff
-
the “else” is needed, but can just be followed by ; (do nothing)
-
-
-
-
while commands look like this:
-
-
while x < y do dostuff
-
-
-
-
begin and end signify a block of commands; the same as {} in Java or indentation in Python
-
-
-
Assignment of a value to a variable is done using the := operator like this
-
-
a := 10
-
-
-
-
-
We can also bind values within declarations by using ~
-
-
-
put() and get(), and similarly named functions, are used to write and read from the console
#while.tri
-let
- var a : Integer
-in
-begin
- a := 0;
- while a < 5 do
- begin
- put('a');
- a := a + 1;
- end
-end
-
-
Output: aaaaa
-
#str.tri
-let
- type Str ~ array 10 of Char;
-
- func replicate (c: Char): Str ~
- [c,c,c,c,c,c,c,c,c,c];
-
- var s: Str
-in
-
-begin
- s := replicate('*');
- put (s[0]); put(s[9]); puteol()
-end
-
-
Output: **
-
AST Examples
-
See OneNote folder (Year\ 3/AST/) for the answers
-
Syntactic Analysis
-
Let's have a look at Java's syntax
-
int myNumber = 55;
-
-
Kindis the category (Identifier, Integer etc)
-Spelling is the actual text used in the code
-
Let's break it down into tokens:
-
-
int - of kind Identifier(name of type) (spelling "int")
-
myNumber - of kind Identifier(name of variable) (spelling "myNumber")
-
= - of kind Becomes (spelling "=")
-
55 of kind Integer Literal (spelling "55")
-
; of kind Semicolon (spelling ";")
-
-
Below is the same example in Triangle:
-
let
- var myNumber : Integer
-in
- myNumber := 55
-
-
Let's break it down into tokens again:
-
-
let, :, var, in of kind let, :, var, in (spelling "let, :, var, in ")
-
:= of kind Becomes (spelling "Becomes")
-
myNumber of kind Identifier (spelling "myNumber")
-
Integer of kind Identifier (spelling "Integer")
-
55 of kind Integer Literal (spelling "55")
-
-
Scanning a string into tokens
-
The basic ideas is that we have a loop implemented using recursion that gobbles up characters from the text until they match a known template for a token.
-
myNumber := 55+ 10
-^
-
-
Our starting point is char 'm', so we assume that we are working along a Identifier. We continue working our way through to the end of the word (until we hit a space). At this stage, it is impossible to know if we are working with either method names, string literals or anything of that nature.
-
myNumber := 55+ 10
-~~~~~~~~^
-
-
We now check that string with a list of reserved words (such as if, end, while). If it was, say for example, if, the kind of this token will be set to If. We don't match any known reserved words so this token is labelled as an Identifier with the spelling "myNumber".
-
myNumber := 55+ 10
-~~~~~~~~~^
-
-
We now keep moving along the spaces until we hit something other than a space. We've hit a colon. There are two types of colon in Triangle, one for separating a variable type from its name or a colon-equals (Becomes token). Let's take the next character as we will know what to do with it after this.
-
myNumber := 55+ 10
-~~~~~~~~~~^
-
-
It is an colon equals sign. That tells us that the token is Becomes with the spelling ":="
-
myNumber := 55+ 10
-~~~~~~~~~~~~^
-
-
We hit a 5. Triangle can only support Integer types (handy!) so we know that we can carry along this number until we hit something that isn't a number (to get the full context of the Integer). In this case, we move along until we hit a space!
-
myNumber := 55+ 10
-~~~~~~~~~~~~~~^
-
-
We've hit something that isn't a digit! This means that this token is of kind Integer Literal and has the spelling "55".
-
myNumber := 55+ 10
-~~~~~~~~~~~~~~^
-
-
The next character is a plus. Operators can start with this character so we keep taking characters until reaching something that's not an operator. The next character is a space
-
myNumber := 55+ 10
-~~~~~~~~~~~~~~~~~~^
-
-
We hit another Integer (10!) and reach the EOL (end of line). Most methods use recursion to keep reading until we reach the end of a line of a end of file.
-
Syntactic Analysis: Parsing into an AST
-
Let's create a theoretical language, Micro-English. Here is the EBNF:
-
Sentence ::== Subject Verb Object .
-Subject ::== I | a Noun | the Noun
-Object ::== Me | a Noun | the Noun
-Noun ::== cat | mat | rat
-Verb ::== like | is | see | sees
-(terminals are english lowercase words, e.g. like, the, etc)
-
-
Bottom Up
-
Noun
- |
-the cat sees a rat.
-
-
Subject
- ____
- | Noun
- | |
-the cat sees a rat.
-
-
S
- ____
- | N Verb
- | | |
-the cat sees a rat.
-
-
S
- ____
- | N V N
- | | | |
-the cat sees a rat.
-
-
S Obj
- ____ ____
- | N V | N
- | | | | |
-the cat sees a rat.
-
-
Sentence
-___________________
- | | | |
- S | Obj |
- ____ | ____ |
- | N V | N |
- | | | | | |
-the cat sees a rat.
-
-
-
Key definitions for compilers
-
-
-
Syntactic analysis: scanning and parsing, which takes the text of the source code and transforms it into an abstract syntax tree
-
-
-
Contextual analysis: checks things like variable types and scope, and creates the connections within the AST so we can later look up declarations for named identifiers like variables, constants and function.
-
-
-
Code generation: generates the output code, which might be machine code, another high-level language, or an intermediate language (as it the case with Java bytecode). Might also include optimisations of the code.
public class Example{
- private int count;
-
- public int doStuff(int[] values){
- int count = 0;
- ...
- }
-}
-
-
Here there is two variables with the name count. How does the compiler know which is which?
-
Identification Tables
-
We could walk back up the abstract syntax tree to figure out what needs to go where in memory (size, type etc.). That would work but, it's slow. (Think back to Tree Walks).
-
The ID table might contain a list of these attributes or just a pointer to the place as to where the identifier was declared.
-
Declarations are functions, class in Java or even int etc.
-
A block is any part of the program that limits the scope of the declaration in Java.
-
Each declaration has a scope.
-
Monolithic Block Structure
-
A programming language exhibits a monolithic block structure if there is only one block:
-
-
All declarations are global in scope
-
No identifier may be declared more than once
-
For every reference to an identifier, i, there must be a corresponding declaration of i.
-
-
program
- D
-begin
- C
-end
-
-
One block for the whole program. The ID table may look like this:
-
| Identity | Attribute |
-|----------|-----------|
-| b | (1) |
-| n | (2) |
-| c | (3) |
-
program
-(1) integer b = 10
-(2) integer n
-(3) char c
-begin
-...
-n = n * b
-...
-write c
-...
-end
-
-
Flat Block Structure
-
Several overlapping blocks, local and global scopes.
-
Nested Block Structure
-
Most programming languages fall into this structure (Java, C and Python).
-
Many scope levels, declarations can be global (scope level 1, outer most scope) in scope or local in scope.
-
Example:
-
let
- (1) var a : Integer
- (2) var b : Boolean
-in
- begin
- ....
- let
- (3) var b : Integer
- (4) var c : Boolean
- in
- begin
- ....
- let
- (5) var d : Integer
- in
- ....
- end
- let
- (6) var d : Boolean
- (7) var e : Integer
- in
- ....
-end
-
-
| Level | Identity | Attribute |
-|-------|----------|-----------|
-| 1 | a | (1) |
-| 1 | b | (2) |
-| 2 | b | (3) |
-| 2 | c | (4) |
-| 3 | d | (5) |
-| 2 | d | (6) |
-| 2 | e | (7) |
-
What do we need to store instead of the identifiers?
-
Type Checking
-
This is a key feature in a statically typed language like Triangle or Java. This helps programmers not make mistakes (assigning a string to an int). This type checking happens at compile time.
-
The picture is much more complex for dynamically typed languages such as JavaScript or Go!
-
Runtime Organisation: Data Representation
-
-
Principles to follow with data representation:
-
-
-
(1) nonconfusion: different values of a given type should have different representations
-
-
-
(2) uniqueness: each value should always have the same representation.
-
-
All values of a given type should occupy the same amount of space, this being that an int will have a storage size of 8 bytes, a boolean value having only 1 byte and a char only having 1 byte too.
-
The compiler then can efficiently work out where to map the values in memory as it knows all the space needed.
-
Should values be represented directly or indirectly?
-
If a variable is directly represented, it simply maps to a binary representation of the variables value somewhere in heap memory.
If a value is indirectly, the variable maps to a handle, a pointer to a storage area where the binary representation of that variable exists (most likely in a heap memory area).
-
| Address | Value |
-|---------|-------|
-| 0 | ? | Object x = new Object()
-| 1 | ? | | (indirect binary repr.)
-| 2 | 160 |<---| (160 is an addr. in memory)
-| 4 | ? |
-| ... | ... |
-| 160 |Object |
-| 161 | data |
-| 162 | here |
-| 163 |etc... |
-
-
Indirect representation is necessary for variable whose values vary in size by a large amount e.g. dynamic arrays or objects. (Think malloc() in C).
-
Primate Types
-
Primate types are stored directly, as this is more efficient than managing a pointer and the allocation of space in heap memory.
-
Integer, Boolean and Char types are supported directly by the target machine with corresponding operations like add, multiply etc.
-
Composite Types
-
Composite types are types which can be simplified into collections of primitive types.
-
Record
-
Record: A collection of variables of fields, each of which has an identifier.
-
-
Records in Triangle
-
Structs in C, Go etc.
-
Java Class with only public variables (closest anyway...)
-
-
Simplest way to store this in memory is to store the variables consecutively in memory (like in a row).
-
type Date = record
- y : Integer
- m : Integer
- d : Integer
- end;
-
-type Details = record
- manager : Boolean
- joined : Date
- dep : Char
- end;
-
Array: consists of several elements which are all of the same type. Each element is referenced by an index (often an integer), there is a one-to-one relationship between indexes and array elements. Arrays start at 0 (some terrible languages don't)
-
We are talking about static arrays (defined at compile time to a fixed size) but some languages support dynamic arrays whereby the length can vary at runtime.
-
For dynamic arrays, we need a handle for the array where it points to the beginning and the end addresses somewhere else in the memory.
Accessing the elements of this array requires an extra computation at runtime compared to accessing a single variable or a record field.
-
Expression Evaluation
-
To summarise, broadly there are two approaches to storing temporary values: registers and stack. Registers are fixed locations that can be referenced directly, but this means a tricky process of choosing which registers to hold which values. Stacks grow and shrink to accommodate new values, but lead to simpler evaluation of expressions.
-
-
Summary of Key Concepts
-
-
-
Identification Table: associates identifiers with a list of attributes, or the original declaration
-
-
-
Declaration: something like a function declaration in python, class declaration in Java, or a variable declaration like “int a;” in Java
-
-
-
Scope: each declaration has a scope, which is the portion of the program that the declaration takes effect.
-
-
-
Block: any part of the program that limits the scope of a declaration (e.g. curly brackets in Java, indentation in Python) In Triangle, scope is determined by the let...in... Command.
-
-
-
Block structure: there are three types of block structure: monolithic, flat, and nested
-
-
-
Non-confusion: different values of a given type should have different representations
-
-
-
Uniqueness: each value should always have the same representation.
-
-
-
Two issues to remember in practice:
-
-
-
All values of a given type should occupy the same amount of space
-
-
-
Should values be represented directly or indirectly? If all values of a given type occupy the same space (that is, the same number of bits or bytes), it is possible for the compiler to plan the allocation of space efficiently simply by knowing the type of each variable.
By the end of this week you should have the ability to:
-
-
Explain the differences between static, stack, and heap storage allocation
-
Describe the purpose of frames in a stack
-
Explain why garbage collection is needed and describe an approach to carrying it out
-
Describe what a template is in the context of code generation, and give simple examples
-
Implement simple additions to the visitor pattern within a compiler
-
Reflect on the value of where and when good commenting is needed
-
-
Runtime Organisation: Static Storage Allocation
-
Memory is basically like a very long list with each element having an address and a value.
-
If we have a variable that might change in size, and indirect representation is used - a pointer. This mean that the variable can occupy a fixed size space in memory because it just points to the address of where the data is really stored (usually in the heap).
-
Stack storage allocation
-
-
Stacks are last-in-first-out data structures: think of a stack of paper where you can only add or remove from the top. Stacks are an effective way to store local variables throughout the lifetime of a program.
-
-
Stack Storage Allocation:
-
-
Variables are stored in frames; each frame contains the local variables for a routine
-
Global variables are stored at the base of the stack
-
Link data at the start of each frame contains:
-
-
Static link (reference to the start of the frame of the routine containing the current one)
-
Dynamic link (reference to the start of the frame for the previously active routine)
-
Return address (reference to the code instruction to jump back to when the routine is finished)
-
-
-
When a routine is called, a new frame is pushed onto the stack; when it returns, the frame is removed
-
Arguments are placed on the stack immediately before a routine is called
-
When a routine returns, its arguments and frame are replaced by a return value on the stack
-
-
Example of Routines and returns
-
let
- var g: Integer;
- func F(m: Integer, n: Integer): Integer ~
- m * n
-
-in
- begin
- getint(var g)
- putint(F(g, g+1))
- end
-
Heap storage allocation is another way to organise memory, and is good for indirect storage of variables.
-
-
A heap variable is allocated by a special command called an allocator in Java. This is whenever you use the keyword new and in C it is malloc(). These return a pointer to the variable in the heap. They exist in memory until it is unallocated (via free() in C or automatically in Java).
-
Heap is placed in opposite to the stack:
-
[ Stack ] <-SB
-[ a ]
-[ b ]
-[ ...... ] <-ST
-[ ]
-[ 8 ] <-HT
-[ H ]
-[ ]
-[ Heap ] <-HB
-
-
Heap Storage Allocation:
-
-
Heaps can indirectly store more complex data structures
-
Heap variables are added to the heap when they are created
-
They are either removed by explicit deallocation, or automatically by a garbage collector
-
Gaps appear in the heap over time; these can be managed by:
-
-
Trying to match new variables to the closest size of available gap
-
Merging gaps when variables are deallocated
-
Compacting the heap periodically
-
-
-
Garbage is when a variable is inaccessible, because no pointers to it remain in the program
-
Explicit deallocation can lead to garbage or dangling pointers
Instances variables for objects have a pointer to a class object that defines what methods are applicable to them
-
-
Code Generation: Code Selection
-
Code Selection is the process of choosing the specific machine code instructions that are needed to represent a high high-level code structure. Code Templates are used for this purpose, though it is complicated by dealing with special cases.
-
Storage Allocation is the process of deciding the addresses for each variable in the program. This is why we have spent some time discussing stack and heap memory.
-
We have parsed the program to an AST and applied contextual analysis to that AST to ensure that all the types are valid! We are now ready to generate the target code for our program.
-
n := n + 1
-
-
LOAD n
-LOAD 1
-ADD
-STORE n
-
-
Adding one to a variable is very common thing to do. We can instead use this instruction
-
LOAD n
-SUCC
-STORE n
-
-
SUCC, means successor instruction to increase the value on the top of the stack by one. This uses 3 instructions instead of 4, meaning it is around 25% faster.
-
The Triangle Abstract Machine
-
The Triangle Abstract Machine (TAM) is a virtual machine designed as the target for our case study compiler. It is also implemented in Java, and you have a copy of it by virtue of cloning the Triangle-Tools project. TAM has the following features:
-
-
-
Its memory is organised to have a stack at the low-address end and a heap at the high address end. Low level operations are provided for adding and removing data in these
-
-
-
Call and return instructions for routines handle frames automatically; return automatically replaces the arguments in the stack with a result from the functions return.
-
-
-
The only registers are dedicated to specific purposes as we’ve described. SB, ST, HB and HT to locate the stack and heap; LB points to the topmost frame on the stack, and so on. These are updated automatically by the instructions that add or remove things from memory
-
-
-
Several routines such as ADD, MULT, and NOT are provided for basic arithmetic and logic operations. There are also routines for reading and writing text on the console.
-
-
-
A full description of TAM is given in the extracts from Programming Language Processors in Java given in the Canvas Reading List. You don’t need to become familiar with this but the text is there to serve as reference material and you will likely want to refer to it when reading and extending the compiler.
-
From Programming Language Processors in Java: Compilers and Interpreters by Watt, D.A
Variable declarations: Martin suggests that declarations should be as close to the usage of the variables as possible. Others feel they should all be at the top, or at least together somewhere. What's your opinion?
-
-
When it comes to variables within a program - it's important to remember 'scope'. We need to make it clear what scope the variables are in.
-
If we are declaring variables at the top of the program (not in a main but the very top) - this is what I would consider global variables. These will be used throughout the entire program and therefore be rather important e.g. A Window object. This variable will be altered through the program.
-
We've talked about global variables - let's talk about local ones.
-
I would say there are two types of local variables. One's within a methods usages and ones within loops.
-
Method usage local are the ones you would declare at the start of a function. These could be used to calculate a sum and then be returned. There is no need to put the variable else where. Now I believe you should use the variable right after declaring it in this situation.
-
Sometimes it's helpful to declare all the variables at the start - this helps give context to what the function will be doing and possibly what it is returning without the need of comments. I find this helpful for functions that handle complex maths equations.
-
The variables used within loops should come before the loops start; this gives me as a programmer better control on the scope and also context. An example could be line number, character position and file name before a for loop. I know that these three variables will be used in this for loop for keeping track of where we are in the loop.
-
-
Do you have any of your own formatting rules you follow (even if only sometimes?)
-
-
I try and reduce the amount of nesting I do - this falls under refactoring. I also like to still use {} around one line if functions too.
-
Code Generation: Algorithm
-
The Visitor Pattern is used to generate the necessary low level instructions.
-
The algorithm we are using follows the visitor pattern. We can already see this in the visualisation of the AST.
-
We specifically write visitNode methods to view the tree.
-
The Visitor pattern walks the AST calling emit() methods to generate machine code instructions as it goes. Lookups into the AST are used to decide things like the value of literals or specific operators to use.
-
Backpatching is used when we need to make forward jumps when we need them (look at visitIf command).
-
Code Generation: Resource Allocation
-
let
- const b ~ 10;
- var i : Integer
-in
- i := i * b
-
-
b is bound to 10 and i is bound to an address large enough to hold an integer.
-
When b is called in the program - it should be translated to a 10 by the compiler. Each time i is used, it should be translated to a memory address.
-
In this example, the address for i is 4. The machine code could look like this:
-
LOAD 4[SB]
-LOADL 10
-CALL mult
-STORE 4[SB]
-
-
In any declaration, identifiers can be bound to values or addresses, and these might be known or unknown at compile time. So at any declaration, there is one of four possible known values:
-
-
-
Known Value: This is a constant declaration, e.g. b in the above program. It was bound to a literal value of 10.
-
-
-
Unknown Value: This is a constant expression where the right-side needs to be evaluated at runtime e.g. const b ~ a + 5 or a parameter received by a routine.
-
-
-
Known Address: This is a known address that is allocated and bound to a variable declaration e.g. i in the example above.
-
-
-
Unknown Address: This is an address bound to a variable parameter in a routine.
-
-
-
The specific machine codes to read and write variables and constants are wrapped up in objects that are attached to the relevant declaration nodes in the AST
-
-
-
These codes include either the literal value (in the case of constants bound to literals) or the necessary steps to work out the right address
-
-
-
Each time we have a declaration, we need to generate the instructions to increase the size of the current frame; when that declaration drops out of scope, the frame is decreased in size again by “popping” elements off the stack
A Known value (KnownValue.java) is simple. Size is the amount of memory taken up by this value and Value is the value itself. encodeFetch loads the literal value onto the stack (0).
An Unknown Value is made up of two parts - level and displacement. Level is how nested the routine that contained this declaration. Displacement is where the entity is located relative to the base of the frame (i.e. how many words is from the start if the frame it is).
-
We can use the frame as the displacement; that's the top of the stack.
-
Code Generation: Procedures and Functions
-
How do we handle procedures and functions? These both translate to low level routines. A routine is a series of instructions and the template might look something like this:
-
elaborate [proc I () ~ C] =
- JUMP g
-e: execute c
- RETURN (0) 0
-h:
-
-
-
Routines are also treated as entities, and entities to track their addresses and generate necessary low level code to run them are stored in the AST much the same as for variables
-
-
Compiler Optimisations
-
Compiler optimisation can happen in a few places:
-
-
-
Having a step before the code generation whereby the AST is manipulated or manipulating intermediate code if that is being generated.
-
-
-
At the point where code is being generated - we can use processor specific instructions can be used/exploited.
-
-
-
Common Sub-expression Elimination: attempts to reduce calculations that are repeated. (This only works when the code is simple).
-
-
-
Constant Propagation: At some point in a program - a variable might always have the same value. An algorithm to trace the flow of constant variables through the programme can be run to determine where this is guaranteed to be the case. The reference to the variable can be replaced by a literal value - reducing the need for fetches from memory.
-
-
-
Hoisting: If part of a computation in a loop is independent of the values that change inside the loop, it can be moved outside the loop - meaning that it is only calculated once e.g:
-
-
-
while(j < k) {
- a[j] := b + c;
- j++;
-}
-
-
In this example: b and c can be moved outside the loop so they are only computed once. We could turn the above code into this:
-
if (j < k){
- tmp = b + c;
- while (j < k){
- a[j] := tmp;
- j++;
- }
-}
-
-
-
Loop unrolling: Reducing the amount of checks a program's loop (such as a for loop) will need. We can use some methods to half the checks or even completely remove the checks - this will result in a larger compiled program with less overhead.
-
Function Inlining: Lifts the body of the code and places it directly to where the function was called.
-
-
Optional reading: More examples are mentioned in the book Introduction to Compiler Design (Mogensen) cited in the module home page; also here https://compileroptimizations.com
-
Interpreters and Native Code, JIT
-
Python is an interpreted language, meaning that the instructions called are done in real time - this creates more slow-down when running the program compared to a compiled language like C.
-
Java is in the middle. Javac generates bytecode which is targeted at a virtual machine. This is then interpreted, so there is still some overhead involved when running with Java.
-
Our toy language compiles into a Tam file. This is that intermediate language similar to bytecode in Java.
-
-
Interpreters for high level languages still scan and parse to generate an AST, and then visit that tree’s nodes to execute the program
-
Interpreters for low level or intermediate languages iterate over the instructions one-by-one, matching the fetch-execute cycle
-
In order of performance (approximately!): compiled native code is fastest, then intermediate code, the interpreted high level code
-
-
Just-in-time compilation, HotSpot, and GI
-
JIT (Just-in-Time) compilation was introduced to help speed up Java's slow interpreted bytecode. Java's compiler doesn't do much optimisation itself, the idea of JIT is to offload certain expensive CPU executions into native machine code. Only parts of the program are complied in this way rather than the whole thing (most of it wont be ran often enough to make it worthwhile.).
-
The process of targeting this extra compilation step is where the HotSpot (Oracles implementation of Java gets it name) - the targeted code is where the program runs hot.
-
Simply put, there's a count of the number of times each method, loop and numerous other structures are executed. If that number would reach a particular threshold, that relevant block of code is compiled natively on the machine!
-
JIT will also monitor branches of code and do the heavy work of lifting the never executed blocks of code from the compilation process off.
We must not prematurely optimise! We should write straight forward clean code. We don't want to write hard-to-read code; slows down development, introduce bugs that are hard to track and make maintenance so much harder.
This simple line has to be compiled and the method calls have to be computed i.e moving values on and off the stack and tracing ourselves around the program calls. If there is an error, log only reports levels higher than FINE so all that computation is wasted! We can rewrite this to:
Turns out, if we use XOR in a variable three times - it swaps!
-
-
Unfortunately, it turns out that in practise, at best this will perform the same as using a temporary variable. On many modern CPU's, copies between registers are extremely fast. Some provide low-level instructions to swap variables anyway.
-
In summary:
-
-
Write clear, logical code
-
Make good design choices by selecting the right data types, the appropriate data structures and algorithms for the task at hand
-
“clever” tricks can get in the way of the compiler doing its job, and make the code harder to read and debug
-
Save the fancy optimisations until you’ve profiled the code and identified bottlenecks
diff --git a/test/website/HTML/css/style.css b/test/website/HTML/css/style.css
deleted file mode 100755
index a5b10e7..0000000
--- a/test/website/HTML/css/style.css
+++ /dev/null
@@ -1,52 +0,0 @@
-@import url('https://fonts.googleapis.com/css?family=Roboto+Mono');
-@import url('https://fonts.googleapis.com/css?family=Roboto');
-@import url('https://fonts.googleapis.com/css?family=Anton');
-
-body {
- padding: 20px;
- background-color: #1e1e2e;
- color: #cdd6f4;
- font-family: "Roboto Mono";
- font-size: 14px;
- line-height: 22px;
- margin: 0 auto;
- max-width: 960px;
-}
-
-pre {
- color: #f9e2af;
-}
-
-blockquote {
- color: #f9e2af;
-}
-
-a {
- color: #f5e0dc;
- text-decoration: none;
-}
-
-a:hover {
- color: #a6e3a1;
-}
-
-h1 {
- font-size: 20px;
- color: #eba0ac;
- margin-bottom: 0px;
-}
-
-h2, h3, h4, h5, h6 {
- font-size: 16px;
- color: #51afef;
- margin-bottom: 0px;
-}
-
-li {
- color: #a6e3a1;
-}
-
-p {
- padding: 0px;
- margin: 0px;
-}
diff --git a/test/website/HTML/inner/inner_test.md b/test/website/HTML/inner/inner_test.md
deleted file mode 100644
index 89ecf4e..0000000
--- a/test/website/HTML/inner/inner_test.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# This should be in a dir
-
-if not, something has gone wrong
diff --git a/test/website/MARKDOWN/.DS_Store b/test/website/MARKDOWN/.DS_Store
deleted file mode 100644
index 6030e32..0000000
Binary files a/test/website/MARKDOWN/.DS_Store and /dev/null differ
diff --git a/test/website/MARKDOWN/A5Week1.md b/test/website/MARKDOWN/A5Week1.md
deleted file mode 100644
index 1cb5f47..0000000
--- a/test/website/MARKDOWN/A5Week1.md
+++ /dev/null
@@ -1,332 +0,0 @@
-# CSCU9A5 Week 1
-
-## Read Chapters 1 and 2 of Clean Code
->
-> You get the drift. Indeed, the ratio of time spent reading vs. writing is well over 10:1. We are constantly reading old code as part of the effort to write new code. Because this ratio is so high, we want the reading of code to be easy, even if it makes the writing harder. Of course there’s no way to write code without reading it, so making it easy to read actually makes it easier to write.
-
-### Class names
->
-> Classes and objects should have noun or noun phrase names like Customer, WikiPage, Account, and AddressParser. Avoid words like Manager, Processor, Data, or Info in the name of a class. A class name should not be a verb.
-
-### Method names
->
-> Methods should have verb or verb phrase names like postPayment, deletePage, or save. Accessors, mutators, and predicates should be named for their value and prefixed with get, set, and is according to the javabean standard.
-
-```java
-string name = employee.getName();
-customer.setName("mike");
-if (paycheck.isPosted())...
-```
-
-> When constructors are overloaded, use static factory methods with names that describe the arguments. For example,
-
-```java
-Complex fulcrumPoint = Complex.FromRealNumber(23.0);
-```
-
-> is generally better than
-
-```java
-Complex fulcrumPoint = new Complex(23.0);
-```
-
-> Consider enforcing their use by making the corresponding constructors private.
-
-### Note: Listings 2-1 and his solution in 2-2 make me cringe
-
-Its too long! Random methods with very long names makes it hard to read on screens like IDE's. You also end up jumping around the code, back and forth and trying to figure out what method returns what and where the next bit of code goes. There is also the issue of creating entire methods for one case of something happening. You could easily split the decision making within the one method with better coding. You can check if there is more and 0 counts and then handle what happens there. We already have access to all the variables we need passed as parameters, why split this off into many methods. I hate it.
-
-## Extended BNF (EBNF)
-
-* We can use * to make things **appear 0-to-many times** by wrapping then in brackets
-
-```text
-N ::== a | (b | c)*
-```
-
-This can be read as **"N may consist of a or alternatively a series of characters comprising zero to many b or c"**. A valid syntax matching this rule would include:
-
-* "a"
-* an empty string (the * helps with this as its 0 to many)
-* "b"
-* "c"
-* "bc"
-* "cb"
-* "cbcbcbc"
-* or "ccccccb"
-
-## Example
-
-We have a simple programming language that allows the user to write arithmetic sums for some existing variables **a, b, c, d, or e**. We can use +, -, /, * and () on the variables too.
-
-```text
-Expression ::== primary-Expression (Operator primary-Expression)*
-primary-Expression ::== Identifier
- | (Expression)
-Idenifier ::== a | b | c | d | e
-Operator ::== + | - | / | *
-```
-
-For example:
-
-```text
-a + (b * c)
-```
-
-Here you can view the [Java](https://docs.oracle.com/javase/specs/jls/se18/html/jls-19.html) specifications as well as [Pythons](https://docs.python.org/3/reference/grammar.html)! [Go](https://go.dev/ref/spec) has a very good break down of its grammar, with lots of documentation!
-
-## Triangle
-
-## Features of Triangle
-
-* Three primitive types of variables:
- * Boolean (i.e. true or false)
- * Char (a single character; same as the Java char type)
- * Integer (values between -32767 and 32767)
-
-* Two types of composite variable:
- * Records (a bit like dictionaries in python)
- * Arrays
-
-* There are no strings or floating point types built-in
-
-* Let blocks are used to declare local constants, variables, procedures and functions (see repl.tri and factorials.ri below)
-
-* The only conditional command is **if** and the only loop command is **while**
-
-* **if** commands look like this:
- * if x < y then *dostuff* else *dootherstuff*
- * the “else” is needed, but can just be followed by ; (do nothing)
-
-* **while** commands look like this:
- * while x < y do *dostuff*
-
-* **begin** and **end** signify a block of commands; the same as {} in Java or indentation in Python
-
-* Assignment of a value to a variable is done using the := operator like this
- * a := 10
- *
-* We can also bind values within declarations by using **~**
-
-* **put()** and **get()**, and similarly named functions, are used to write and read from the console
-
-### Examples of Triangle (.tri)
-
-```
-#hi.tri
-begin
- put('H'); put('i'); put('!')
-end
-```
-
-Output: **Hi!**
-
-```
-#while.tri
-let
- var a : Integer
-in
-begin
- a := 0;
- while a < 5 do
- begin
- put('a');
- a := a + 1;
- end
-end
-```
-
-Output: **aaaaa**
-
-```
-#str.tri
-let
- type Str ~ array 10 of Char;
-
- func replicate (c: Char): Str ~
- [c,c,c,c,c,c,c,c,c,c];
-
- var s: Str
-in
-
-begin
- s := replicate('*');
- put (s[0]); put(s[9]); puteol()
-end
-```
-
-Output: **
-
-## AST Examples
-
-***See OneNote folder (Year\ 3/AST/) for the answers***
-
-## Syntactic Analysis
-
-Let's have a look at Java's syntax
-
-```java
-int myNumber = 55;
-```
-
-**Kind***is the category (Identifier, Integer etc)
-**Spelling*** is the actual text used in the code
-
-Let's break it down into tokens:
-
-* **int** - of kind Identifier(name of type) (spelling "int")
-* **myNumber** - of kind Identifier(name of variable) (spelling "myNumber")
-* **=** - of kind Becomes (spelling "=")
-* **55** of kind Integer Literal (spelling "55")
-* **;** of kind Semicolon (spelling ";")
-
-Below is the same example in Triangle:
-
-```
-let
- var myNumber : Integer
-in
- myNumber := 55
-```
-
-Let's break it down into tokens again:
-
-* **let, :, var, in** of kind let, :, var, in (spelling "let, :, var, in ")
-* **:=** of kind Becomes (spelling "Becomes")
-* **myNumber** of kind Identifier (spelling "myNumber")
-* **Integer** of kind Identifier (spelling "Integer")
-* **55** of kind Integer Literal (spelling "55")
-
-## Scanning a string into tokens
-
-The basic ideas is that we have a loop implemented using recursion that gobbles up characters from the text until they match a known template for a token.
-
-```
-myNumber := 55+ 10
-^
-```
-
-Our starting point is char 'm', so we assume that we are working along a Identifier. We continue working our way through to the end of the word (until we hit a space). At this stage, it is impossible to know if we are working with either method names, string literals or anything of that nature.
-
-```
-myNumber := 55+ 10
-~~~~~~~~^
-```
-
-We now check that string with a list of reserved words (such as *if*, *end*, *while*). If it was, say for example, **if**, the kind of this token will be set to If. We don't match any known reserved words so this token is labelled as an Identifier with the spelling "myNumber".
-
-```
-myNumber := 55+ 10
-~~~~~~~~~^
-```
-
-We now keep moving along the spaces until we hit something other than a space. We've hit a colon. There are two types of colon in Triangle, one for separating a variable type from its name or a colon-equals (Becomes token). Let's take the next character as we will know what to do with it after this.
-
-```
-myNumber := 55+ 10
-~~~~~~~~~~^
-```
-
-It is an colon equals sign. That tells us that the token is **Becomes** with the spelling ":="
-
-```
-myNumber := 55+ 10
-~~~~~~~~~~~~^
-```
-
-We hit a 5. Triangle can only support Integer types (handy!) so we know that we can carry along this number until we hit something that isn't a number (to get the full context of the Integer). In this case, we move along until we hit a space!
-
-```
-myNumber := 55+ 10
-~~~~~~~~~~~~~~^
-```
-
-We've hit something that isn't a digit! This means that this token is of kind Integer Literal and has the spelling "55".
-
-```
-myNumber := 55+ 10
-~~~~~~~~~~~~~~^
-```
-
-The next character is a plus. Operators can start with this character so we keep taking characters until reaching something that's not an operator. The next character is a space
-
-```
-myNumber := 55+ 10
-~~~~~~~~~~~~~~~~~~^
-```
-
-We hit another Integer (10!) and reach the EOL (end of line). Most methods use recursion to keep reading until we reach the end of a line of a end of file.
-
-## Syntactic Analysis: Parsing into an AST
-
-Let's create a theoretical language, Micro-English. Here is the EBNF:
-
-```
-Sentence ::== Subject Verb Object .
-Subject ::== I | a Noun | the Noun
-Object ::== Me | a Noun | the Noun
-Noun ::== cat | mat | rat
-Verb ::== like | is | see | sees
-(terminals are english lowercase words, e.g. like, the, etc)
-```
-
-### Bottom Up
-
-```
- Noun
- |
-the cat sees a rat.
-```
-
-```
-Subject
- ____
- | Noun
- | |
-the cat sees a rat.
-```
-
-```
- S
- ____
- | N Verb
- | | |
-the cat sees a rat.
-```
-
-```
- S
- ____
- | N V N
- | | | |
-the cat sees a rat.
-```
-
-```
- S Obj
- ____ ____
- | N V | N
- | | | | |
-the cat sees a rat.
-```
-
-```
- Sentence
-___________________
- | | | |
- S | Obj |
- ____ | ____ |
- | N V | N |
- | | | | | |
-the cat sees a rat.
-```
-
----
-
-### Key definitions for compilers
-
-* **Syntactic analysis**: scanning and parsing, which takes the text of the source code and transforms it into an abstract syntax tree
-
-* **Contextual analysis**: checks things like variable types and scope, and creates the connections within the AST so we can later look up declarations for named identifiers like variables, constants and function.
-
-* **Code generation**: generates the output code, which might be machine code, another high-level language, or an intermediate language (as it the case with Java bytecode). Might also include optimisations of the code.
diff --git a/test/website/MARKDOWN/A5Week2.md b/test/website/MARKDOWN/A5Week2.md
deleted file mode 100644
index 3f940c8..0000000
--- a/test/website/MARKDOWN/A5Week2.md
+++ /dev/null
@@ -1,277 +0,0 @@
-# CSCU9A5 Week 2
-
-TODO
-> Read Chapter 3 of Clean Code
-
-## Contextual Analysis
-
-```java
-public class Example{
- private int count;
-
- public int doStuff(int[] values){
- int count = 0;
- ...
- }
-}
-```
-
-Here there is two variables with the name **count**. How does the compiler know which is which?
-
-### Identification Tables
-
-We could walk back up the abstract syntax tree to figure out what needs to go where in memory (size, type etc.). That would work but, it's slow. (Think back to Tree Walks).
-
-The ID table might contain a list of these *attributes* or just a *pointer* to the place as to where the identifier was declared.
-
-Declarations are functions, class in Java or even int etc.
-
-A *block* is any part of the program that limits the scope of the declaration in Java.
-
-Each declaration has a **scope**.
-
-### Monolithic Block Structure
-
-A programming language exhibits a monolithic block structure if there is only one block:
-
-* All declarations are **global in scope**
-* No identifier may be declared more than once
-* For every reference to an identifier, *i*, there must be a corresponding declaration of *i*.
-
-```code
-program
- D
-begin
- C
-end
-```
-
-One block for the **whole** program. The ID table may look like this:
-
-| Identity | Attribute |
-|----------|-----------|
-| b | (1) |
-| n | (2) |
-| c | (3) |
-
-```code
-program
-(1) integer b = 10
-(2) integer n
-(3) char c
-begin
-...
-n = n * b
-...
-write c
-...
-end
-```
-
-### Flat Block Structure
-
-Several overlapping blocks, local and global scopes.
-
-### Nested Block Structure
-
-Most programming languages fall into this structure (Java, C and Python).
-
-Many scope levels, declarations can be global (scope level 1, outer most scope) in scope or local in scope.
-
-Example:
-
-```code
-let
- (1) var a : Integer
- (2) var b : Boolean
-in
- begin
- ....
- let
- (3) var b : Integer
- (4) var c : Boolean
- in
- begin
- ....
- let
- (5) var d : Integer
- in
- ....
- end
- let
- (6) var d : Boolean
- (7) var e : Integer
- in
- ....
-end
-```
-
-| Level | Identity | Attribute |
-|-------|----------|-----------|
-| 1 | a | (1) |
-| 1 | b | (2) |
-| 2 | b | (3) |
-| 2 | c | (4) |
-| 3 | d | (5) |
-| 2 | d | (6) |
-| 2 | e | (7) |
-
-What do we need to store instead of the identifiers?
-
-## Type Checking
-
-This is a key feature in a **statically** typed language like Triangle or Java. This helps programmers not make mistakes (assigning a string to an int). This type checking happens at compile time.
-
-The picture is much more complex for **dynamically** typed languages such as JavaScript or Go!
-
-## Runtime Organisation: Data Representation
-
-> Principles to follow with data representation:
-
-> (1) nonconfusion: different values of a given type should have different representations
-
-> (2) uniqueness: each value should always have the same representation.
-
-All values of a given type should occupy the same amount of space, this being that an int will have a storage size of 8 bytes, a boolean value having only 1 byte and a char only having 1 byte too.
-
-The compiler then can efficiently work out where to map the values in memory as it knows all the space needed.
-
-Should values be represented directly or indirectly?
-
-If a variable is directly represented, it simply maps to a binary representation of the variables value somewhere in heap memory.
-
-```text
-| Address | Value |
-|---------|-------|
-| 0 | ? | int x = 130
-| 1 | ? | | (direct binary repr.)
-| 2 | 130 |<---|
-| 4 | ? |
-| ... | ... |
-```
-
-If a value is indirectly, the variable maps to a **handle**, a pointer to a storage area where the binary representation of that variable exists (most likely in a heap memory area).
-
-```text
-| Address | Value |
-|---------|-------|
-| 0 | ? | Object x = new Object()
-| 1 | ? | | (indirect binary repr.)
-| 2 | 160 |<---| (160 is an addr. in memory)
-| 4 | ? |
-| ... | ... |
-| 160 |Object |
-| 161 | data |
-| 162 | here |
-| 163 |etc... |
-```
-
-**Indirect representation** is necessary for variable whose values vary in size by a large amount e.g. dynamic arrays or objects. (Think malloc() in C).
-
-## Primate Types
-
-Primate types are stored directly, as this is more efficient than managing a pointer and the allocation of space in heap memory.
-
-Integer, Boolean and Char types are supported directly by the target machine with corresponding operations like *add*, *multiply* etc.
-
-## Composite Types
-
-Composite types are types which can be simplified into collections of primitive types.
-
-### Record
-
-**Record**: A collection of variables of fields, each of which has an identifier.
-
-* Records in Triangle
-* Structs in C, Go etc.
-* Java Class with only public variables (closest anyway...)
-
-Simplest way to store this in memory is to store the variables consecutively in memory (like in a row).
-
-```code
-type Date = record
- y : Integer
- m : Integer
- d : Integer
- end;
-
-type Details = record
- manager : Boolean
- joined : Date
- dep : Char
- end;
-```
-
-This could be stored in memory like so:
-
-```text
-var person : Details
-
-| Address | Value |
-|---------|-------|
-| 1 | ?? |
-| 2 | true | <-- person.manager
-| 2 | 1992 | <--- person.joined.y ]
-| 4 | 3 | <--- person.joined.m ]> person.joined
-| 5 | 1 | <--- person.joined.d ]
-| 6 | 'c' | <-- person.dep
-| 7 | ?? |
-
-```
-
-### Array
-
-**Array**: consists of several elements which are all of the same type. Each element is referenced by an index (often an integer), there is a one-to-one relationship between indexes and array elements. Arrays start at 0 (some terrible languages don't)
-
-We are talking about static arrays (defined at compile time to a fixed size) but some languages support dynamic arrays whereby the length can vary at runtime.
-
-For dynamic arrays, we need a handle for the array where it points to the beginning and the end addresses somewhere else in the memory.
-
-Static arrays could look like this:
-
-```text
-| Address | Value |
-|---------|-------|
-| 1 | ?? |
-| 2 | ?? |
-| 3 | ?? |
-| 4 | 'h' | a[0]
-| 5 | 'e' | a[1]
-| 6 | 'l' | a[2]
-| 7 | 'l' | a[3]
-| 8 | 'o' | a[4]
-| 9 | '!' | a[5]
-| 10 | ?? |
-| 11 | ?? |
-| ... | ... |
-```
-
-Accessing the elements of this array requires an extra computation at runtime compared to accessing a single variable or a record field.
-
-## Expression Evaluation
-
-To summarise, broadly there are two approaches to storing temporary values: registers and stack. Registers are fixed locations that can be referenced directly, but this means a tricky process of choosing which registers to hold which values. Stacks grow and shrink to accommodate new values, but lead to simpler evaluation of expressions.
-
----
-
-## Summary of Key Concepts
-
-* Identification Table: associates identifiers with a list of attributes, or the original declaration
-
-* Declaration: something like a function declaration in python, class declaration in Java, or a variable declaration like “int a;” in Java
-
-* Scope: each declaration has a scope, which is the portion of the program that the declaration takes effect.
-
-* Block: any part of the program that limits the scope of a declaration (e.g. curly brackets in Java, indentation in Python) In Triangle, scope is determined by the let...in... Command.
-
-* Block structure: there are three types of block structure: monolithic, flat, and nested
-
-* Non-confusion: different values of a given type should have different representations
-
-* Uniqueness: each value should always have the same representation.
-
-Two issues to remember in practice:
-
-* All values of a given type should occupy the same amount of space
-
-* Should values be represented directly or indirectly? If all values of a given type occupy the same space (that is, the same number of bits or bytes), it is possible for the compiler to plan the allocation of space efficiently simply by knowing the type of each variable.
diff --git a/test/website/MARKDOWN/A5Week3.md b/test/website/MARKDOWN/A5Week3.md
deleted file mode 100644
index 95b4af4..0000000
--- a/test/website/MARKDOWN/A5Week3.md
+++ /dev/null
@@ -1,177 +0,0 @@
-# CSCU9A5 Week 3
-
-By the end of this week you should have the ability to:
-
-* **Explain** the differences between static, stack, and heap storage allocation
-* **Describe** the purpose of frames in a stack
-* **Explain** why garbage collection is needed and describe an approach to carrying it out
-* **Describe** what a template is in the context of code generation, and give simple examples
-* **Implement** simple additions to the visitor pattern within a compiler
-* **Reflect** on the value of where and when good commenting is needed
-
-## Runtime Organisation: Static Storage Allocation
-
-Memory is basically like a very long list with each element having an address and a value.
-
-If we have a variable that might change in size, and indirect representation is used - a pointer. This mean that the variable can occupy a fixed size space in memory because it just *points* to the address of where the data is really stored (usually in the **heap**).
-
-### Stack storage allocation
-
-> Stacks are last-in-first-out data structures: think of a stack of paper where you can only add or remove from the top. Stacks are an effective way to store local variables throughout the lifetime of a program.
-
-***Stack Storage Allocation:***
-
-* Variables are stored in frames; each frame contains the local variables for a routine
-* Global variables are stored at the base of the stack
-* Link data at the start of each frame contains:
- * Static link (reference to the start of the frame of the routine containing the current one)
- * Dynamic link (reference to the start of the frame for the previously active routine)
- * Return address (reference to the code instruction to jump back to when the routine is finished)
-* When a routine is called, a new frame is pushed onto the stack; when it returns, the frame is removed
-* Arguments are placed on the stack immediately before a routine is called
-* When a routine returns, its arguments and frame are replaced by a return value on the stack
-
-Example of Routines and returns
-
-```text
-let
- var g: Integer;
- func F(m: Integer, n: Integer): Integer ~
- m * n
-
-in
- begin
- getint(var g)
- putint(F(g, g+1))
- end
-```
-
-```asm
-PUSH 1
-LOADA 0[SB]
-CALL getint
-LOAD 0[SB]
-LOAD 0[SB]
-PUSH 1
-CALL add
-CALL(SB) F
-CALL putint
-POP
-HALT
-
-F:
- LOAD -2[LB]
- LOAD -1[LB]
- CALL mult
- RETURN(1) 2
-```
-
-### Heap Storage Allocation and Garbage Collection
-
-> Heap storage allocation is another way to organise memory, and is good for indirect storage of variables.
-
-A heap variable is allocated by a special command called an allocator in Java. This is whenever you use the keyword *new* and in C it is *malloc()*. These return a pointer to the variable in the heap. They exist in memory until it is unallocated (via *free()* in C or automatically in Java).
-
-Heap is placed in opposite to the stack:
-
-```text
-[ Stack ] <-SB
-[ a ]
-[ b ]
-[ ...... ] <-ST
-[ ]
-[ 8 ] <-HT
-[ H ]
-[ ]
-[ Heap ] <-HB
-```
-
-***Heap Storage Allocation:***
-
-* Heaps can indirectly store more complex data structures
-* Heap variables are added to the heap when they are created
-* They are either removed by explicit deallocation, or automatically by a garbage collector
-* Gaps appear in the heap over time; these can be managed by:
- * Trying to match new variables to the closest size of available gap
- * Merging gaps when variables are deallocated
- * Compacting the heap periodically
-* Garbage is when a variable is inaccessible, because no pointers to it remain in the program
-* Explicit deallocation can lead to garbage or dangling pointers
-* Automatic deallocation runs periodically, deallocating inaccessible variables
-* Instances variables for objects have a pointer to a class object that defines what methods are applicable to them
-
-## Code Generation: Code Selection
-
-**Code Selection** is the process of choosing the specific machine code instructions that are needed to represent a high high-level code structure. Code Templates are used for this purpose, though it is complicated by dealing with special cases.
-
-**Storage Allocation** is the process of deciding the addresses for each variable in the program. This is why we have spent some time discussing stack and heap memory.
-
-We have parsed the program to an AST and applied contextual analysis to that AST to ensure that all the types are valid! We are now ready to generate the target code for our program.
-
-```go
-n := n + 1
-```
-
-```asm
-LOAD n
-LOAD 1
-ADD
-STORE n
-```
-
-Adding one to a variable is very common thing to do. We can instead use this instruction
-
-```asm
-LOAD n
-SUCC
-STORE n
-```
-
-SUCC, means successor instruction to increase the value on the top of the stack by one. This uses 3 instructions instead of 4, meaning it is around 25% faster.
-
-## The Triangle Abstract Machine
-
-The Triangle Abstract Machine (TAM) is a virtual machine designed as the target for our case study compiler. It is also implemented in Java, and you have a copy of it by virtue of cloning the Triangle-Tools project. TAM has the following features:
-
-* Its memory is organised to have a stack at the low-address end and a heap at the high address end. Low level operations are provided for adding and removing data in these
-
-* Call and return instructions for routines handle frames automatically; **return** automatically replaces the arguments in the stack with a result from the functions return.
-
-* The only registers are dedicated to specific purposes as we’ve described. SB, ST, HB and HT to locate the stack and heap; LB points to the topmost frame on the stack, and so on. These are updated automatically by the instructions that add or remove things from memory
-
-* Several routines such as ADD, MULT, and NOT are provided for basic arithmetic and logic operations. There are also routines for reading and writing text on the console.
-
-A full description of TAM is given in the extracts from Programming Language Processors in Java given in the Canvas Reading List. You don’t need to become familiar with this but the text is there to serve as reference material and you will likely want to refer to it when reading and extending the compiler.
-
-### From Programming Language Processors in Java: Compilers and Interpreters by Watt, D.A
-
-Yarr link be here!
-
-
-* Both stack and heap can expand and contrast. Storage exhaustion arises when ST and HT attempt to cross over.
-
-#### Layout of a TAM frame
-
-* A *static link* points to an underlying frame associated with teh routine that textually encloses R in the source program
-* The *dynamic link* points to the frame immediately underlying this one in the stack.
-* The *return address* is the address of the instruction immediately following the call instruction that activated R.
-
-
-
-#### TAM instruction format
-
-All TAM instructions have a common format.
-
-* *op*: the operation code [4bits]
-* *r*: a register number [4bits]
-* *n*: the size of the operand. [8bits]
-* *d*: address displacement (possibly negative) [16bit *signed*]
-
-```text
-[ op ][ r ][ n ][ d ]
- 4 bits 4 bits 8 bits 16 bits
-```
-
-#### TAM instructions
-
-
diff --git a/test/website/MARKDOWN/A5Week4.md b/test/website/MARKDOWN/A5Week4.md
deleted file mode 100644
index 966b332..0000000
--- a/test/website/MARKDOWN/A5Week4.md
+++ /dev/null
@@ -1,229 +0,0 @@
-# CSCU9A5 Week 4
-
-## Read: Chapter 5 of Clean Code
-
-> Variable declarations: Martin suggests that declarations should be as close to the usage of the variables as possible. Others feel they should all be at the top, or at least together somewhere. What's your opinion?
-
-When it comes to variables within a program - it's important to remember 'scope'. We need to make it clear what scope the variables are in.
-
-If we are declaring variables at the top of the program (not in a *main* but the *very* top) - this is what I would consider **global** variables. These will be used throughout the entire program and therefore be rather important e.g. A Window object. This variable will be altered through the program.
-
-We've talked about **global** variables - let's talk about **local** ones.
-
-I would say there are two types of **local** variables. One's within a methods usages and ones within loops.
-
-Method usage **local** are the ones you would declare at the start of a function. These could be used to calculate a sum and then be returned. There is no need to put the variable else where. Now I believe you should use the variable right after declaring it in this situation.
-
-Sometimes it's helpful to declare all the variables at the start - this helps give context to what the function will be doing and possibly what it is returning without the need of comments. I find this helpful for functions that handle complex maths equations.
-
-The variables used within loops should come before the loops start; this gives me as a programmer better control on the scope and also context. An example could be line number, character position and file name before a for loop. I know that these three variables will be used in this for loop for keeping track of where we are in the loop.
-
-> Do you have any of your own formatting rules you follow (even if only sometimes?)
-
-***I try and reduce the amount of nesting I do - this falls under refactoring. I also like to still use {} around one line if functions too.***
-
-## Code Generation: Algorithm
-
-The **Visitor Pattern** is used to generate the necessary low level instructions.
-
-The algorithm we are using follows the **visitor pattern**. We can already see this in the visualisation of the AST.
-
-We specifically write *visitNode* methods to view the tree.
-
-The Visitor pattern walks the AST calling **emit()** methods to generate machine code instructions as it goes. Lookups into the AST are used to decide things like the value of literals or specific operators to use.
-
-Backpatching is used when we need to make forward jumps when we need them (look at visitIf command).
-
-## Code Generation: Resource Allocation
-
-```code
-let
- const b ~ 10;
- var i : Integer
-in
- i := i * b
-```
-
-**b** is bound to 10 and **i** is bound to an address large enough to hold an integer.
-
-When **b** is called in the program - it should be translated to a 10 by the compiler. Each time **i** is used, it should be translated to a memory address.
-
-In this example, the address for **i** is **4**. The machine code could look like this:
-
-```code
-LOAD 4[SB]
-LOADL 10
-CALL mult
-STORE 4[SB]
-```
-
-In any declaration, identifiers can be bound to values or addresses, and these might be known or unknown at compile time. So at any declaration, there is one of four possible known values:
-
-* **Known Value**: This is a constant declaration, e.g. **b** in the above program. It was bound to a literal value of 10.
-* **Unknown Value**: This is a constant expression where the right-side needs to be evaluated at runtime e.g. *const b ~ a + 5* or a parameter received by a routine.
-* **Known Address**: This is a known address that is allocated and bound to a variable declaration e.g. **i** in the example above.
-* **Unknown Address**: This is an address bound to a variable parameter in a routine.
-
-* The specific machine codes to read and write variables and constants are wrapped up in objects that are attached to the relevant declaration nodes in the AST
-* These codes include either the literal value (in the case of constants bound to literals) or the necessary steps to work out the right address
-* Each time we have a declaration, we need to generate the instructions to increase the size of the current frame; when that declaration drops out of scope, the frame is decreased in size again by “popping” elements off the stack
-
-### Within the Triangle Compiler
-
-#### Known Value
-
-```java
-...
-public KnownValue(int size, int value){ ... }
-...
-public void encodeFetch(Emitter ...){
- emitter.emit(OpCode.LOADL, 0, value)
-}
-...
-```
-
-A **Known value** (*KnownValue.java*) is simple. *Size* is the amount of memory taken up by this value and *Value* is the value itself. *encodeFetch* loads the literal value onto the stack *(0)*.
-
-#### Unknown Value
-
-```java
-...
-public UnknownValue(int size, int level, int displacement){ ... }
-...
-public void encodeFetch(Emitter ...){
- if (vname.indexed){
- emitter.emit(OpCode.LOADA ...
- emitter.emit(OpCode.CALL ...
- emitter.emit(OpCode.LOADI ...
- } else {
- emitter.emit(OpCode.LOAD ...
- }
-}
-...
-```
-
-An **Unknown Value** is made up of two parts - level and displacement. Level is how nested the routine that contained this declaration. Displacement is where the entity is located relative to the base of the frame (i.e. how many words is from the start if the frame it is).
-
-We can use the *frame* as the displacement; that's the top of the stack.
-
-## Code Generation: Procedures and Functions
-
-How do we handle procedures and functions? These both translate to low level routines. A routine is a series of instructions and the template might look something like this:
-
-```code
-elaborate [proc I () ~ C] =
- JUMP g
-e: execute c
- RETURN (0) 0
-h:
-```
-
-* Routines are also treated as entities, and entities to track their addresses and generate necessary low level code to run them are stored in the AST much the same as for variables
-
-## Compiler Optimisations
-
-Compiler optimisation can happen in a few places:
-
-* Having a step before the code generation whereby the AST is manipulated or manipulating intermediate code if that is being generated.
-* At the point where code is being generated - we can use processor specific instructions can be used/exploited.
-
-* **Common Sub-expression Elimination**: attempts to reduce calculations that are repeated. (This only works when the code is simple).
-* **Constant Propagation**: At some point in a program - a variable might always have the same value. An algorithm to trace the flow of constant variables through the programme can be run to determine where this is guaranteed to be the case. The reference to the variable can be replaced by a literal value - reducing the need for fetches from memory.
-* **Hoisting**: If part of a computation in a loop is independent of the values that change inside the loop, it can be moved *outside* the loop - meaning that it is only calculated **once** e.g:
-
-```code
-while(j < k) {
- a[j] := b + c;
- j++;
-}
-```
-
-In this example: **b** and **c** can be moved outside the loop so they are only computed once. We could turn the above code into this:
-
-```code
-if (j < k){
- tmp = b + c;
- while (j < k){
- a[j] := tmp;
- j++;
- }
-}
-```
-
-* **Loop unrolling**: Reducing the amount of checks a program's loop (such as a *for* loop) will need. We can use some methods to half the checks or even completely remove the checks - this will result in a larger compiled program with less overhead.
-* **Function Inlining**: Lifts the body of the code and places it directly to where the function was called.
-
-**Optional reading: More examples are mentioned in the book Introduction to Compiler Design (Mogensen) cited in the module home page; also here **
-
-## Interpreters and Native Code, JIT
-
-Python is an interpreted language, meaning that the instructions called are done in real time - this creates more slow-down when running the program compared to a compiled language like C.
-
-Java is in the middle. Javac generates *bytecode* which is targeted at a *virtual machine*. This is then interpreted, so there is still some overhead involved when running with Java.
-
-Our toy language compiles into a Tam file. This is that intermediate language similar to *bytecode* in Java.
-
-* Interpreters for high level languages still scan and parse to generate an AST, and then visit that tree’s nodes to execute the program
-* Interpreters for low level or intermediate languages iterate over the instructions one-by-one, matching the fetch-execute cycle
-* In order of performance (approximately!): compiled native code is fastest, then intermediate code, the interpreted high level code
-
-## Just-in-time compilation, HotSpot, and GI
-
-JIT (Just-in-Time) compilation was introduced to help speed up Java's slow interpreted bytecode. Java's compiler doesn't do much optimisation itself, the idea of JIT is to offload certain expensive CPU executions into native machine code. Only parts of the program are complied in this way rather than the whole thing (most of it wont be ran often enough to make it worthwhile.).
-
-The process of targeting this extra compilation step is where the HotSpot (Oracles implementation of Java gets it name) - the targeted code is where the program runs hot.
-
-Simply put, there's a count of the number of times each method, loop and numerous other structures are executed. If that number would reach a particular threshold, that relevant block of code is compiled natively on the machine!
-
-JIT will also monitor branches of code and do the heavy work of lifting the *never executed* blocks of code from the compilation process off.
-
-* Search-based software engineering and genetic improvement of software is an active area of research that targets improvements to code that trades off possibly reduced functionality in return for greatly improved performance. Read more about it in this review paper: to an external site. or in these slides:
-
-## When and Where to Optimise Your Code
-
-We must not prematurely optimise! We should write straight forward clean code. We don't want to write hard-to-read code; slows down development, introduce bugs that are hard to track and make maintenance so much harder.
-
-```java
-log.log(Level.FINE, "..." + calcX() ... + calcY() ... );
-```
-
-This simple line has to be compiled and the method calls have to be computed i.e moving values on and off the stack and tracing ourselves around the program calls. If there is an error, *log* only reports levels higher than *FINE* so all that computation is wasted! We can rewrite this to:
-
-```java
-if(log.isLoaggable(Level.FINE)){_
- log.log(Level.FINE, "..." + calcX() ... + calcY() ... );
-}
-```
-
-This is much more efficient.
-
-Sometimes we want to swap values around. We could do it like this:
-
-```java
-temp = a
-a = b
-b = temp
-```
-
-This can be done better though. Maybe we can remove the *temp* variable. Let's have a look at the XOR binary function.
-
-XOR works like this:
-
-| ----- | - |
-| 0 + 0 | 0 |
-| 0 + 1 | 1 |
-| 1 + 0 | 1 |
-| 1 + 0 | 0 |
-
-Turns out, if we use XOR in a variable three times - it swaps!
-
-
-
-Unfortunately, it turns out that in practise, at best this will perform the same as using a temporary variable. On many modern CPU's, copies between registers are extremely fast. Some provide low-level instructions to swap variables anyway.
-
-In summary:
-
-* Write clear, logical code
-* Make good design choices by selecting the right data types, the appropriate data structures and algorithms for the task at hand
-* “clever” tricks can get in the way of the compiler doing its job, and make the code harder to read and debug
-* Save the fancy optimisations until you’ve profiled the code and identified bottlenecks
diff --git a/test/website/MARKDOWN/A5Week5.md b/test/website/MARKDOWN/A5Week5.md
deleted file mode 100644
index b9f05e7..0000000
--- a/test/website/MARKDOWN/A5Week5.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# CSCU9A5 Week 5
-
-## Debugging Code
-
-Hello there
-
-This is sync test!
diff --git a/test/website/MARKDOWN/A5Week8.md b/test/website/MARKDOWN/A5Week8.md
deleted file mode 100644
index 71eaa07..0000000
--- a/test/website/MARKDOWN/A5Week8.md
+++ /dev/null
@@ -1 +0,0 @@
-# CSCU9A5 Week 8
diff --git a/test/website/MARKDOWN/css/style.css b/test/website/MARKDOWN/css/style.css
deleted file mode 100755
index cfcb1bc..0000000
--- a/test/website/MARKDOWN/css/style.css
+++ /dev/null
@@ -1,52 +0,0 @@
-@import url('https://fonts.googleapis.com/css?family=Roboto+Mono');
-@import url('https://fonts.googleapis.com/css?family=Roboto');
-@import url('https://fonts.googleapis.com/css?family=Anton');
-
-body {
- padding: 20px;
- background-color: #1e1e2e;
- color: #cdd6f4;
- font-family: "Roboto Mono";
- font-size: 14px;
- line-height: 22px;
- margin: 0 auto;
- max-width: 960px;
-}
-
-pre {
- color: #f9e2af;
-}
-
-blockquote {
- color: #f9e2af;
-}
-
-a {
- color: #f5e0dc;
- text-decoration: none;
-}
-
-a:hover {
- color: #a6e3a1;
-}
-
-h1 {
- font-size: 20px;
- color: #eba0ac;
- margin-bottom: 0px;
-}
-
-h2, h3, h4, h5, h6 {
- font-size: 16px;
- color: #51afef;
- margin-bottom: 0px;
-}
-
-li {
- color: #a6e3a1;
-}
-
-p {
- padding: 0px;
- margin: 0px;
-}
diff --git a/test/website/css/style.css b/test/website/css/style.css
deleted file mode 100755
index cfcb1bc..0000000
--- a/test/website/css/style.css
+++ /dev/null
@@ -1,52 +0,0 @@
-@import url('https://fonts.googleapis.com/css?family=Roboto+Mono');
-@import url('https://fonts.googleapis.com/css?family=Roboto');
-@import url('https://fonts.googleapis.com/css?family=Anton');
-
-body {
- padding: 20px;
- background-color: #1e1e2e;
- color: #cdd6f4;
- font-family: "Roboto Mono";
- font-size: 14px;
- line-height: 22px;
- margin: 0 auto;
- max-width: 960px;
-}
-
-pre {
- color: #f9e2af;
-}
-
-blockquote {
- color: #f9e2af;
-}
-
-a {
- color: #f5e0dc;
- text-decoration: none;
-}
-
-a:hover {
- color: #a6e3a1;
-}
-
-h1 {
- font-size: 20px;
- color: #eba0ac;
- margin-bottom: 0px;
-}
-
-h2, h3, h4, h5, h6 {
- font-size: 16px;
- color: #51afef;
- margin-bottom: 0px;
-}
-
-li {
- color: #a6e3a1;
-}
-
-p {
- padding: 0px;
- margin: 0px;
-}