diff --git a/HOME_EXAM.md b/HOME_EXAM.md index aad26f7b546aab407862663e5723378a11a8532e..0caaee84d1098e04cc22e945490de81af546c29d 100644 --- a/HOME_EXAM.md +++ b/HOME_EXAM.md @@ -455,7 +455,7 @@ Similar SOS goes for the following operands: ```math \frac{<e0,σ> → i32 <e1,σ> → i32}{<e0 > e1,σ> → bool} ``` -SOS for comparison between two i32 types returning a boolean. +SOS for greater than comparison between two i32 types returning a boolean. Simliar SOS goes for the following operands: - "<", less @@ -552,8 +552,95 @@ It would be nice do add the following in the future: ## Borrow checker +#### Invalid examples +```rust +fn a(x: &i32) -> () { + *x += 1; +} + +fn main() -> () { + let y: i32 = 5; + + a(&y); +} +``` +This example is invalid due to trying to mutate an immutable reference. + +```rust +fn b(x: &mut i32, y: &mut i32) -> () { + *x += 1; + *y += 1; +} +fn main() -> () { + let mut a: i32 = 5; + b(&mut a, &mut a); +} +``` +Not a valid program due to variable a being borrowed twice and therefor not being treated as unique. +```rust +fn main() -> () { + let mut x = 0; + let y = &mut x; + x += 1; + *y += 1; +} +``` +Borrow is used at multiple locations, therefor it is mutable from different references and that is not accepted. + +#### Valid examples +Below follows the rewritten examples that are accepted by the borrow checker. +```rust +fn a(x: &mut i32) -> () { + *x += 1; +} + +fn main() -> () { + let mut y: i32 = 5; + + a(&mut y); +} +``` + +```rust +fn b(x: &mut i32, y: &mut i32) -> () { + *x += 1; + *y += 1; +} +fn main() -> () { + let mut x: i32 = 5; + let mut y: i32 = 5; + b(&mut x, &mut y); +} +``` + +```rust +fn main() -> () { + let mut x = 0; + let y = &mut x; + *y += 1; + x += 1; +} +``` + +The borrowchecker should make sure that: +- One reference can only be mutable at a time. +- Multiple immutable references can be used. + +This ensures that a variable can not be changed at the same time that another reference tries to read it. ## Conclusion +It has been very interesting to learn how a programming language is build. From the lexical analysing where sentences are parsed into tokens to the syntax analysing where the order of the tokens are ckecked. I found it very interesting and instructive to be able to build the AST and parser with the use of lalrpop. It was tricky to understand what should be done in the beginning when both learing lalrpop and rust at the same time. This fell inte place with time and after rewriting the AST compleatly it made alot more sense. + +When building the parser we got to use both regular expressions and context-free grammar where every production rule contains of a nonterminal symbol that is equalent to either a nonterminal and/or a terminal. In this way can a language be built recursively. For example can a nonterminal <Expr> be equal to x <Operand> y which is an abstraction of all operands that can be interpreted as a expression. The parser and lexer generator Lalrpop has helped alot with simplifying this process. + +- Identifier handling and symbol table organization. Type-checking, logical inference systems. [SOS is a logical inference system] + +- Intermediate representations and transformations for different languages. [If you attended, Recall lectures relating LLVM/Crane-lift, discussions on SSA (Single Static Assignment) used in LLVM/Crane-lift, and discussions/examples on high level optimization] + +- Code optimization and register allocation. Machine code generation for common architectures. [Both LLVM/Crane-Lift does the "dirty work" of backend optimization/register allocation leveraging the SSA form of the LLVM-IR] + + +Comment on additional things that you have experienced and learned throughout the course.