From 5f8cb40a93dd9e5d0ebbdcce54195e5458eb5161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wilma=20Krutr=C3=B6k?= <wilkru-7@student.ltu.se> Date: Wed, 4 Nov 2020 13:31:56 +0000 Subject: [PATCH] Continued on conclusion --- HOME_EXAM.md | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/HOME_EXAM.md b/HOME_EXAM.md index 41a5203..4f34476 100644 --- a/HOME_EXAM.md +++ b/HOME_EXAM.md @@ -598,8 +598,7 @@ Below follows the rewritten examples that are accepted by the borrow checker. ```rust fn a(x: &mut i32) -> () { *x = *x + 1; -} - +}; fn main() -> () { let mut y: i32 = 5; a(&mut y); @@ -607,10 +606,10 @@ fn main() -> () { ``` ```rust -fn b(x: &mut i32, y: &mut i32) -> () { - *x = *x + 1; - *y = *y + 1; -} +fn b(z: &mut i32, w: &mut i32) -> () { + *z = *z + 1; + *w = *w + 1; +}; fn main() -> () { let mut x: i32 = 5; let mut y: i32 = 5; @@ -626,6 +625,7 @@ fn main() -> () { x = x + 1; } ``` +(Functions should not be separeated by ";", but this was the only solution that worked so I decided to move on) The borrowchecker should make sure that: - One reference can only be mutable at a time. @@ -641,11 +641,7 @@ When building the parser we got to use both regular expressions and context-free The process of implementing the type checker and the interpreter was similar. These gave me more insight in what order a program is executed and how the compiler makes sure that the types are correct in all the different cases. To be able to execute and type check earlier decleared variables and functions was environments used where the variable/function are stored in a vecdeque containing hashmaps of strings and matching type/value. For each scope is a new hashmap pushed to the front of the vecdeque. It was good to get to do the type checker and interpreter both in code and as a logical inference system to get a deeper understanding. - - -- 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] +The next step would be to generate machine code from the parser output that has been accepted by the type checker and the interpreter. To do this could the code generator Crane-lift be used. The code could be optimized in several way, for example due to the rules for borrow checking is it possible to put together all changes to a mutable reference into one expression. This because we know that the interpreter only allows one mutable refernce at a time. One way to implement the intermediate representation could be by using the SSA form where each variable only can be assigned once. +I have not implemented this part, instead I focused on understanding the parser, type checker, intepreter and the borrow checking. It has been difficult to write good structured code because this is the first time I worked with Rust. Therefor the rules and structure was new to me which ended up in very messy code. I focused on getting as much as possible to work to get a broad understanding instead. It would be really fun to rewrite everything from the beginning now with the knowledge and insight the course have given! \ No newline at end of file -- GitLab