Skip to content
Snippets Groups Projects
Commit bbeccd22 authored by Aron Strandberg's avatar Aron Strandberg
Browse files

added borrow checker and overal course goals, learning etc

parent b0b7e346
No related branches found
No related tags found
No related merge requests found
- [Your repo](#your-repo) - [Your repo](#your-repo)
- [Your syntax](#your-syntax) - [Your syntax](#your-syntax)
- [Your semantics](#your-semantics) - [Your semantics](#your-semantics)
- [Function sequence](#function-sequence)
- [Command sequence](#command-sequence)
- [Operands for arithmetic expressions](#operands-for-arithmetic-expressions)
- [Operands for boolean expressions](#operands-for-boolean-expressions)
- [If true](#if-true)
- [If false](#if-false)
- [While false](#while-false)
- [While true](#while-true)
- [Let assignment](#let-assignment)
- [Assignment](#assignment)
- [Return](#return)
- [Your type checker](#your-type-checker) - [Your type checker](#your-type-checker)
- [Command sequence](#command-sequence-1)
- [Operands for i32 types](#operands-for-i32-types)
- [Operands for boolean types](#operands-for-boolean-types)
- [If true/false](#if-truefalse)
- [While true/false](#while-truefalse)
- [Let assignment i32](#let-assignment-i32)
- [Let assignment bool](#let-assignment-bool)
- [Assignment i32](#assignment-i32)
- [Assignment bool](#assignment-bool)
- [Return i32](#return-i32)
- [Return bool](#return-bool)
- [Void (none)](#void-none)
- [Your borrrow checker](#your-borrrow-checker) - [Your borrrow checker](#your-borrrow-checker)
- [Your LLVM backend](#your-llvm-backend) - [Your LLVM backend](#your-llvm-backend)
- [Overal course goals and learning outcomes.](#overal-course-goals-and-learning-outcomes) - [Overal course goals and learning outcomes.](#overal-course-goals-and-learning-outcomes)
...@@ -193,12 +216,12 @@ Symbols: ...@@ -193,12 +216,12 @@ Symbols:
- x, variable - x, variable
- e, expression - e, expression
An expression can be either a Expression can be either a
- b, boolean - b, boolean
- n, number - n, number
- f, function - f, function
Function sequence ### Function sequence
```math ```math
<f, σ>⇓σ' <f, σ>⇓σ'
``` ```
...@@ -210,7 +233,7 @@ fn main() { ...@@ -210,7 +233,7 @@ fn main() {
``` ```
The function call moves the current state, $σ$ to the new derived state $σ'$ in the function, test()'s context. A function can evaluate void (none), i32 and bool. The function call moves the current state, $σ$ to the new derived state $σ'$ in the function, test()'s context. A function can evaluate void (none), i32 and bool.
Command sequence ### Command sequence
```math ```math
\frac{<c1,σ> ⇓ σ' <c2,σ'> ⇓ σ''}{<c1;c2,σ> ⇓ σ''} \frac{<c1,σ> ⇓ σ' <c2,σ'> ⇓ σ''}{<c1;c2,σ> ⇓ σ''}
``` ```
...@@ -221,7 +244,7 @@ test(); ...@@ -221,7 +244,7 @@ test();
``` ```
A sequence is a composition of commands where the first command is first executed then the second command. Otherwise the intermediate step, $σ'$ would be lost. A sequence is a composition of commands where the first command is first executed then the second command. Otherwise the intermediate step, $σ'$ would be lost.
Operands for lhs, rhs arithmetic expressions ### Operands for arithmetic expressions
```math ```math
\frac{<e1,σ> ⇓ n1 <e2, σ> ⇓ n2}{<e1 + e2, σ> ⇓ n1 \text{ } plus \text{ } n2} \frac{<e1,σ> ⇓ n1 <e2, σ> ⇓ n2}{<e1 + e2, σ> ⇓ n1 \text{ } plus \text{ } n2}
``` ```
...@@ -240,7 +263,7 @@ plus is addition as implemented in the computer. Other arithmetic operands imlem ...@@ -240,7 +263,7 @@ plus is addition as implemented in the computer. Other arithmetic operands imlem
1 < 2; // Is valid! 1 < 2; // Is valid!
``` ```
Operands for lhs, rhs boolean expressions ### Operands for boolean expressions
```math ```math
\frac{<e1,σ> ⇓ b1 <e2, σ> ⇓ b2}{<e1 == e2, σ> ⇓ b1 \text{ } equal \text{ } b2} \frac{<e1,σ> ⇓ b1 <e2, σ> ⇓ b2}{<e1 == e2, σ> ⇓ b1 \text{ } equal \text{ } b2}
``` ```
...@@ -257,26 +280,26 @@ how equal is evaluated is up to the computer. Other boolean operands implemented ...@@ -257,26 +280,26 @@ how equal is evaluated is up to the computer. Other boolean operands implemented
``` ```
If true ### If true
```math ```math
\frac{<b, σ> ⇓ true <c1, σ> ⇓ σ'}{<if \text{ } b \text{ } then \text{ } c1> ⇓ σ} \frac{<b, σ> ⇓ true <c1, σ> ⇓ σ'}{<if \text{ } b \text{ } then \text{ } c1> ⇓ σ}
``` ```
then the state, $σ$ will change immediately to $σ'$. then the state, $σ$ will change immediately to $σ'$.
If false ### If false
```math ```math
\frac{<b, σ> ⇓ false <c1, σ> ⇓ σ''}{<if \text{ } b \text{ } then \text{ } c1> ⇓ σ} \frac{<b, σ> ⇓ false <c1, σ> ⇓ σ''}{<if \text{ } b \text{ } then \text{ } c1> ⇓ σ}
``` ```
the state, $σ'$ will be changed at the second command to $σ''$. the state, $σ'$ will be changed at the second command to $σ''$.
While false ### While false
```math ```math
\frac{<b,σ> ⇓ false}{<while \text{ } b \text{ } do \text{ } c,σ> ⇓ σ} \frac{<b,σ> ⇓ false}{<while \text{ } b \text{ } do \text{ } c,σ> ⇓ σ}
``` ```
While true ### While true
```math ```math
\frac{<b, σ> ⇓ true <c,σ> ⇓ σ' <while \text{ } b \text{ } do \text{ } c, σ'> ⇓ σ''}{<while \text{ } b \text{ } do \text{ } c,σ> ⇓ σ''} \frac{<b, σ> ⇓ true <c,σ> ⇓ σ' <while \text{ } b \text{ } do \text{ } c, σ'> ⇓ σ''}{<while \text{ } b \text{ } do \text{ } c,σ> ⇓ σ''}
``` ```
...@@ -290,7 +313,7 @@ while a < 5 { ...@@ -290,7 +313,7 @@ while a < 5 {
then $σ'$ is the result of the current state, $σ$ and the last state $σ''$ is the result of $σ'$. then $σ'$ is the result of the current state, $σ$ and the last state $σ''$ is the result of $σ'$.
Let assignment expression ### Let assignment
```math ```math
\frac{<x, σ>⇓<let \text{ } x:=e, σ>⇓σ'}{<let \text{ } x := e, σ> ⇓ σ[x := e]} \frac{<x, σ>⇓<let \text{ } x:=e, σ>⇓σ'}{<let \text{ } x := e, σ> ⇓ σ[x := e]}
``` ```
...@@ -301,7 +324,7 @@ let c : i32 = test(); // c will be assigned whaterver test() returns ...@@ -301,7 +324,7 @@ let c : i32 = test(); // c will be assigned whaterver test() returns
``` ```
For let commands, if the variable is already declared the state $σ$ will be changed to the one of the second command, state $σ'$, the variable will be lost. Otherwise the variable will be assigned to the state, $σ$. For let commands, if the variable is already declared the state $σ$ will be changed to the one of the second command, state $σ'$, the variable will be lost. Otherwise the variable will be assigned to the state, $σ$.
Assignment expression ### Assignment
```math ```math
\frac{}{<x := e, σ> ⇓ σ[x := e]} \frac{}{<x := e, σ> ⇓ σ[x := e]}
``` ```
...@@ -317,7 +340,7 @@ For assignment, when the variable is assigned to a number, boolean or function t ...@@ -317,7 +340,7 @@ For assignment, when the variable is assigned to a number, boolean or function t
Return ### Return
```math ```math
\frac{<f, σ>⇓σ}{<return : e, σ> ⇓ σ[return : e]} \frac{<f, σ>⇓σ}{<return : e, σ> ⇓ σ[return : e]}
``` ```
...@@ -362,7 +385,7 @@ Types are now defined as ...@@ -362,7 +385,7 @@ Types are now defined as
- none - none
Command sequence ### Command sequence
```math ```math
\frac{<c1,σ> ⇓ σ' <c2,σ'> ⇓ σ''}{<c1;c2,σ> ⇓ σ''} \frac{<c1,σ> ⇓ σ' <c2,σ'> ⇓ σ''}{<c1;c2,σ> ⇓ σ''}
``` ```
...@@ -370,7 +393,7 @@ Command sequence ...@@ -370,7 +393,7 @@ Command sequence
as described in the SOS rules of the interpreter. as described in the SOS rules of the interpreter.
Operands for i32 types ### Operands for i32 types
```math ```math
\frac{<e1,σ> ⇓ i32 <e2, σ> ⇓ i32}{<e1 + e2, σ> ⇓ i32} \frac{<e1,σ> ⇓ i32 <e2, σ> ⇓ i32}{<e1 + e2, σ> ⇓ i32}
``` ```
...@@ -389,7 +412,7 @@ To operate these operands the expression need to evaluate to i32. Other arithmet ...@@ -389,7 +412,7 @@ To operate these operands the expression need to evaluate to i32. Other arithmet
1 + true; //TypeError 1 + true; //TypeError
``` ```
Operands for boolean types ### Operands for boolean types
```math ```math
\frac{<e1,σ> ⇓ bool <e2, σ> ⇓ bool}{<e1 == e2, σ> ⇓ bool} \frac{<e1,σ> ⇓ bool <e2, σ> ⇓ bool}{<e1 == e2, σ> ⇓ bool}
``` ```
...@@ -406,7 +429,7 @@ true || false; ...@@ -406,7 +429,7 @@ true || false;
1 || true; //TypeError 1 || true; //TypeError
``` ```
If true/false ### If true/false
```math ```math
\frac{<e, σ> ⇓ bool <c1, σ> ⇓ σ'}{<if \text{ } bool \text{ } then \text{ } c1> ⇓ σ} \frac{<e, σ> ⇓ bool <c1, σ> ⇓ σ'}{<if \text{ } bool \text{ } then \text{ } c1> ⇓ σ}
``` ```
...@@ -417,7 +440,7 @@ if false { ...@@ -417,7 +440,7 @@ if false {
} }
``` ```
While true/false ### While true/false
```math ```math
\frac{<e, σ> ⇓ bool <c,σ> ⇓ σ' <while \text{ } bool \text{ } do \text{ } c, σ'> ⇓ σ''}{<while \text{ } bool \text{ } do \text{ } c,σ> ⇓ σ''} \frac{<e, σ> ⇓ bool <c,σ> ⇓ σ' <while \text{ } bool \text{ } do \text{ } c, σ'> ⇓ σ''}{<while \text{ } bool \text{ } do \text{ } c,σ> ⇓ σ''}
``` ```
...@@ -425,7 +448,7 @@ While true/false ...@@ -425,7 +448,7 @@ While true/false
For both if and while commands their block/scope are evluated as long as their condition is evaluted to the type boolean. This differ from the interpreter which only executes the block/scope if the condition is true. For both if and while commands their block/scope are evluated as long as their condition is evaluted to the type boolean. This differ from the interpreter which only executes the block/scope if the condition is true.
Let assignment i32 expression ### Let assignment i32
```math ```math
\frac{<x, σ>⇓i32<let \text{ } x:=i32, σ>⇓σ'}{<let \text{ } x := i32, σ> ⇓ σ[x := i32]} \frac{<x, σ>⇓i32<let \text{ } x:=i32, σ>⇓σ'}{<let \text{ } x := i32, σ> ⇓ σ[x := i32]}
``` ```
...@@ -433,7 +456,7 @@ Let assignment i32 expression ...@@ -433,7 +456,7 @@ Let assignment i32 expression
let a : i32 = 1; let a : i32 = 1;
let b : i32 = test(); // test() must return type i32 otherwise Error let b : i32 = test(); // test() must return type i32 otherwise Error
``` ```
Let assignment bool expression ### Let assignment bool
```math ```math
\frac{<x, σ>⇓bool<let \text{ } x:=bool, σ>⇓σ'}{<let \text{ } x := bool, σ> ⇓ σ[x := bool]} \frac{<x, σ>⇓bool<let \text{ } x:=bool, σ>⇓σ'}{<let \text{ } x := bool, σ> ⇓ σ[x := bool]}
``` ```
...@@ -443,7 +466,7 @@ let b : bool = test(); // test() must return type bool otherwise Error ...@@ -443,7 +466,7 @@ let b : bool = test(); // test() must return type bool otherwise Error
``` ```
As previously mentioned, let assignment are unique declerations. Thus, the same variable can not be declared twice in the same scope. Here, the given return type of the variable is checked with rhs evluated type. As previously mentioned, let assignment are unique declerations. Thus, the same variable can not be declared twice in the same scope. Here, the given return type of the variable is checked with rhs evluated type.
Assignment i32 expression ### Assignment i32
```math ```math
\frac{<x, σ> ⇓ i32<e, σ> i32}{<x := i32, σ> ⇓ σ[x := i32]} \frac{<x, σ> ⇓ i32<e, σ> i32}{<x := i32, σ> ⇓ σ[x := i32]}
``` ```
...@@ -451,7 +474,7 @@ Assignment i32 expression ...@@ -451,7 +474,7 @@ Assignment i32 expression
```rust ```rust
x = 1; x = 1;
``` ```
Assignment bool expression ### Assignment bool
```math ```math
\frac{<x, σ> ⇓ bool<e, σ> bool}{<x := bool, σ> ⇓ σ[x := bool]} \frac{<x, σ> ⇓ bool<e, σ> bool}{<x := bool, σ> ⇓ σ[x := bool]}
``` ```
...@@ -463,7 +486,7 @@ For any assigment, the variable typed stored with the rhs evaluated type is chec ...@@ -463,7 +486,7 @@ For any assigment, the variable typed stored with the rhs evaluated type is chec
Return i32 ### Return i32
```math ```math
\frac{<f, σ>⇓σ}{<return : i32, σ> ⇓ σ[return : i32]} \frac{<f, σ>⇓σ}{<return : i32, σ> ⇓ σ[return : i32]}
``` ```
...@@ -476,7 +499,7 @@ fn main() -> i32 { ...@@ -476,7 +499,7 @@ fn main() -> i32 {
The function is declared to return a type i32. The function is declared to return a type i32.
Return bool ### Return bool
```math ```math
\frac{<f, σ>⇓σ}{<return : bool, σ> ⇓ σ[return : bool]} \frac{<f, σ>⇓σ}{<return : bool, σ> ⇓ σ[return : bool]}
``` ```
...@@ -488,7 +511,7 @@ fn main() -> bool { ...@@ -488,7 +511,7 @@ fn main() -> bool {
``` ```
The function is declared to return a type boolean. The function is declared to return a type boolean.
Void (none) ### Void (none)
```math ```math
\frac{<f, σ>⇓σ}{<none, σ> ⇓ σ[none]} \frac{<f, σ>⇓σ}{<none, σ> ⇓ σ[none]}
``` ```
...@@ -535,15 +558,15 @@ In the future the type checking can be expanded to handle mutability and memory ...@@ -535,15 +558,15 @@ In the future the type checking can be expanded to handle mutability and memory
## Your borrrow checker ## Your borrrow checker
- Any borrow may only last for the lifetime of the owners scope.
- One mutably borrow at a time. E.g. function parameter references may not reference to the same value.
- One or more immutably borrows at a time. E.g. to reference an immutable value is possible at any time.
- You cannot borrow a mutably and immutably at the same time.
For the dev, do not try to do multiple simultaneous mutable borrows. Store your future changes in a separate location and then apply them.
- Give a specification for well versus ill formed borrows. (What are the rules the borrow checker should check). The end goal of the borrow checker is to prevent data-racing. Data-racing is when two or more pointers are pointing to the same memory location where one ore more pointers are writing to the location. The operations are not syncronizhed.
- Demonstrate the cases of ill formed borrows that your borrow checker is able to detect and reject.
- Compare your solution to the requirements (as stated in the README.md). What are your contributions to the implementation.
## Your LLVM backend ## Your LLVM backend
- Let your backend produces LLVM-IR for your example program. - Let your backend produces LLVM-IR for your example program.
...@@ -556,16 +579,26 @@ In the future the type checking can be expanded to handle mutability and memory ...@@ -556,16 +579,26 @@ In the future the type checking can be expanded to handle mutability and memory
## Overal course goals and learning outcomes. ## Overal course goals and learning outcomes.
Comment on the alignment of the concrete course goals (taken from the course description) to the theory presented, work You have done and knowledge You have gained. (I have put some comments in [...]).
- Lexical analysis, syntax analysis, and translation into abstract syntax. - Lexical analysis, syntax analysis, and translation into abstract syntax.
- As I took the decesion to use a parser generator, lalrpop the lexical analysis and syntax analysis has been simplified. Lalrpop made it easy to understand lexical tokenizing and it was a strong tool for syntax analysis e.g. precedence or paranthesis handling. Then it all boils down to the building block of my compiler, the AST which I have found it hard to get 'perfect' but has been fun to work with and given me a better understanding after each iteration.
- Regular expressions and grammars, context-free languages and grammars, lexer and parser generators. [Nom is lexer/parser library (and replaces the need for a generator, while lalr-pop is a classical parser generator)] - Regular expressions and grammars, context-free languages and grammars, lexer and parser generators. [Nom is lexer/parser library (and replaces the need for a generator, while lalr-pop is a classical parser generator)]
- As mentioned above, first tokenizing the input to produce terminals and then recognizing the terminals and executing the code. Thus, lalrpop is a canonical LR parser or LR(1) parser which handles my context-free language e.g. arethmetic expressions. By using lalrpop the EBNF is basically given.
- Identifier handling and symbol table organization. Type-checking, logical inference systems. [SOS is a logical inference system] - Identifier handling and symbol table organization. Type-checking, logical inference systems. [SOS is a logical inference system]
- Type checking gave me a realisation that my interpreter may have fault in how it executes. Other than that has type checking given me some more insight in the ownership model of rust and implemented my own interpretation, described in the SOS.
- SOS describes my compiler language in a more formal way, how my compiler works! But is has been a bit tricky to define the SOS and I expect some scemantics may be wrong. Identifier handling and symbol table is trivial to defining the SOS.
- At this point I excpect the interpreter not to fail.
- Intermediate representations and transformations for different languages. [LLVM is a cross language compiler infrastructure] - LLVM
- This is the last step of my compiler, now we are generating actual machine code. It has linked this course with microcomputing which I feel has been rewarding. To think more of e.g. how boolean are represented in machine code. To grasp LLVM you could have a seperate course but it wraps up the comiler you have written and produce something useful.
- Code optimization and register allocation. Machine code generation for common architectures. [LLVM is a cross target compiler infrastructure, doing the "dirty work" of optimazation/register allocation leveraging the SSA form of the LLVM-IR]
Comment on additional things that you have experienced and learned throughout the course. Comment on additional things that you have experienced and learned throughout the course.
To get the AST "perfect" is hard and needs a lot of interations. Therefor a complete or class complete parser could have been given. Focus on
- Interpretation, to understand how will your compiler execute, how does RUST execute?
- Type checking, what type rules do RUST enforce?
- Borrow checking, it slaps you in the face but you gradually get a more understanding of it and why it exists in the first place.
- LLVM, a wrapper for the course that could have gotten more love to show it's twits and bits.
In all I have gotten a understanding of how a compiler works and the formality to describe a language. A more in-depth understanding of RUST than I previously knew. It has given me the a good stepping stone to be able to build and define my own language of a compiler.
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment