 Allright, thank you. So who am I? My name is Wendel Baalman, I'm a software engineer. I like Python and open source, these kind of things. Until recently I mainly worked on a PPCI project. If you know it or not, probably check it out. I think it's a good thing. You can find me on Twitter and GitHub. In dit talk I will talk about Rust and Python implementation in Rust. So first off, you're here, so probably you already know what is Rust. It is a new programming language and it's more or less comparable C, C++. So if you have C and C++, there's not much alternatives you have until now, I think. That's with Rust, you really have something. I would actually say that they did most of the things right that went wrong in C. So, buffer overflow, memory leaks, all these kind of things. And it's developed by Mozilla. So the question maybe is what's the problem with C? Why do we need Rust, yet another programming language? There are hundreds of programming languages. C is very complex. A mistake is easily made. And also when you work with libraries, it's not ideal to put it that way. So if you have a new programmer and he says, okay, I want to learn C, C++. Then the following snippet might surprise him because he's coming from maybe JavaScript or C sharp or I don't know, some higher level language. En this is pretty low level. So what you see here is that we have a for loop and we loop. It's a classic mistake of a buffer overflow. We loop 11 times and we override the value zero with I. And then the result is 10. And then I can imagine that programmers think, okay, C is just not for me. I will just go to Python, for example. So how does Rust resolve this issue? In Rust, you have the factor type so you can create a factor. And you can then add numbers to this factor type. And you don't have this buffer overflows. And this is just one example where Rust prevents these kinds of errors where what you have in C. But there are more benefits. I think one of the greatest benefits is the developer environment. So in Rust, you have the cargo. It's a sort of the make plus pip plus pie tests you have it. So it's a sort of combination of all the things that you really need when you develop software. Also, you have the JavaScript developers. And there's a lot of them because it's JavaScript and it's huge. And in JavaScript, we think JavaScript is maybe not so nice. We might have something different. So you have WebAssembly now. And you can have all kinds of languages which you can target WebAssembly. And one of them is Rust. So probably a lot of JavaScript programmers will maybe switch to Rust. So that means there's a lot of Rust programmers maybe coming up. Or maybe not, I don't know. So this might also be a benefit of Rust. So this led me to a question, I asked this myself. Why if you have an application, when would you choose C to develop an application? So when you have a kernel or a driver, then it makes sense that you use maybe C. If you have an application like a backend, then probably your better of is C sharp, Java, Python, anything but C. But C Python itself, it's still implemented in C. It's C Python, it's the reference implementation. You also have PyPy, which is Python implemented in Python. So let's have a look at how does Python work in C Python when you look at the documentation of the C API. You see some text like, okay, we get an item. And we will have a borrowed reference, okay. And this is interesting because in Rust, there's lots of concepts dealing with ownership and borrowing, and also reference. So maybe it's a good match. So in Rust, you, for example, have an RC type, which is a reference counting object. So if you have one object, you can put it in a reference counter. And then you have reference counting. You don't have to do anything else for it. So let's maybe try this out and create a sort of prototype and re-implement Python in Rust. Why not? I mean, is it viable? So I made this project, it's located here. But then I thought maybe there's more people with this ID, because it may sound like a crazy ID, but often you're not the only crazy one. There are more people. So, enter Rust Python. I contacted Xing via internet. He already started with something. And we said, okay, maybe we can combine forces. So I mainly worked on the parser part and here on the virtual machine part. We put something together. It's now located at this new link. So I encourage you all to check it out and start contributing because this is a large task, of course. So obvious benefits of using Rust in implementing Python would be. In Rust, everything is unicode already. So in CPython, there was this immense struggle of getting, yeah, we need unicodes. It's difficult in C. How can we do it? In Rust, it's the default. Also we have the cargo package manager, which is really good. And the reference counting and result types which are in Rust. And also what maybe also, so why would you want to have a package like Rust Python? So there are multiple use cases for this. So CPython and PyPy are really, CPython is the reference implementation and the problem with Python is that there's not a standard. For example, you can save from JavaScript what you want, but they have ECMAScript. And that's good because you have a language standard and you have implementations. In Python, we don't have it. CPython is the reference and PyPy copies all the quirks that are in CPython, which may be not so nice. So maybe this is a good chance to make a new implementation and look at the quirks again en see if they really need it. For example, you see the same as MicroPython, they also started from scratch and they didn't implement all the, say, hacks, which are possible. And also what is maybe interesting is that there's a lot of pure Rust packages now coming out. And if you want to run all the Python code or all this Python code we have in this Rust world, then this could be a nice bridge, so you want. So the design of the Python interpreter, it's like this. I would say it's a rather classical compiler interpreter design. So we start with a source code, we lex it, so taking the source code itself, then we use a parser and an abstract syntax tree. Then there's a compiler which takes the syntax tree, makes bytecode, and then there's the VM, this is actually the biggest part, I think. En we have a nice loop here, because when we're in the VM, we have an import statement. And this import statement will invoke the whole circle again. So that's kind of cool. This is, I think, the way C-Python also works. So the lexer I made in Rust is a handwritten lexer, so just scanning all the text and creating tokens of it. And creating special indent and dedent tokens for the, because you have the white space syntax in Python. And for the parser, I use the parser generator. It's called LARPOP, it's a Rust parser generator. It's pretty, yeah, works rather well, I would say. The abstract syntax tree, this is a snippet from the abstract syntax tree module in Rust for Python. So you see a statement can be either a if or a break or a lot of other things. An expression can be a binary operator with two other expressions on both end A and B and an operator. Also a lot of other things. This is a snippet of the syntax for LARPOP. We're probably not going to detail in that because it takes a while to get used to, but when you look at the examples, so the code itself looks very cryptic, but it is really compact. And of course, there's a virtual machine with the bytecode. So if you don't know what bytecode is, in Python you have this module and you can create some Python codes and disassemble it. So if you do that for a simple function, you will see the bytecode that it generates. And this is what the Python virtual machine then takes and executes. This is a snippet from the compiler. So how this works is it will just, it will work over all the nodes in the syntax tree. En create a proper bytecode part of that. In this function you can see multiple things. So also if you look at the syntax of Rust, it is quite surprising that we have in Rust also a self object, which we also have in Python. Also you see here a type annotation, but actually Rust is statically typed. So, but it's at the same place. Only we don't have def here, but it's fn. That's the Rust syntax. And one part in Rust, what is really helpful, is the match operator you see here. So which match you can, match is basically a bunch of check if an object is a certain instance. So it's like an enormous tree of instance checks. I think you can think of it like that. And then for the virtual machine of Python, so how does this more or less work? So when you have functions which call this other, each function create a new stack frame. And in each stack frame you have a value stack. So it's a stack machine in that sense. And each instruction, if you remember the bytecode, it will take a value of the value stack, perform operations and put the value back on the value stack in that frame. So that is in a nutshell how this should work. So to run a single frame in Rust Python, this is the function to execute one frame. So remember you call the function, you execute the bytecode in this frame. And you just want to run each bytecode until either you hit an exception or you return a value. So that is what you see with this loop. The loop will continuously loop and execute a single instruction. And then the result of this instruction, it can be no result, meaning no exception, no return value. It can also be that there was some result and it was okay, which means there is a return value. Or it can be there was an error. And then we should unwind the try catch blocks and handle it in some way. And also one nice feature of Rust, what you can see here is that at the end, you don't see a return statement. And that is because in Rust, every statement is an expression. So if you have here a value at the end, this will be the return value. That is also pretty handy. This is the way how, when a single function is executed or a single instruction, what it will do, it will take the current frame, fetch an instruction from it and then check, okay, what is this instruction? What do I need to do with this? And that is what the virtual machine is doing. Then we have the one bytecode is the load name operation. What this will do is it will, it's a bytecode to load a name on the value stack in the frame. And you can pass it in name. It will look in the current scope and see if there's a variable that contains his name. Right, 10 minutes left. And put it on the value stack. This is maybe one of the more important parts of the virtual machine, which types are there. So as I mentioned, Rust has the reference counting type. So what we did is create a Pi object. This is a sort of, this is the real object. And then you have the Pi object reference, which meaning this is a reference to a Python object. And this Pi object reference, that is a variable and if you clone it in Rust, you get them two references. And the RC type will automatically do the reference counting. So this is more about internals, but hey, how about the performance of this code or of this interpreter. So let's take a simple benchmark. So we create two wall loops, a wall loop and a wall loop to count up to sum up some values. And when we run this with, when I run this with the C Python, it's execute in 0.05 seconds. And then I run it with Rust using Cargo Run. And I was a little bit shocked that it took 2.73 seconds. Ah, this is not, this is not well. But later I realized that I forgot to build in release mode. Sinds I'm also not super advanced to Rust user yet. I would like to be. But if you run it in release mode, then you see that this snippet takes 0.29 seconds, which is more or less 5.3 times slower than the C Python. So this is for a first prototype. So I would say this looks promising, maybe. En this is probably also due to the fact that the Rust code is compiled really to machine code language, just like C. So it's not .NET, it's not Java, it's not, yeah it's not managed or slow in other ways. So now we have all this type systems and we have Rust. So let's take a look at how the build in all function is implemented in here. So there's a function defined. It will take a vector of pi object references and it will return a result. And here you can see that Rust also supports iterators and anonymous functions and all these nice things we also have in Python. So this can be really helpful to create, yeah, for example, this all function, it's a built in function, it's a pretty short function. So now I want to show how this works. So if you check out the Rust Python repository, you will see this files here. And what you have to do is, you can hit cargo run, what cargo run will do, it will fetch all the dependencies, build all your codes and run your program. So if you compare this with C, for example, probably you would first have to install some things which up gets and maybe grab some other library from the net and compile it, put it in a special place. With Rust you can do this, so that is great. So to exit this you simply press enter because that is not yet, the empty statement is not yet in, I didn't implement that. So it will crash on that. And here you also can see if you want more details you can set the Rust backtrace, you can set it to one. And you will get the detailed information about where this Rust program crashed. We do this again, you get a large stack trace. And then you can pinpoint more what exactly went wrong. You can also run a simple demo. So this is a demo file, if you run this with C Python, you will get the correct answer. But if you run it with Rust Python, you also get the correct answer. And what Rust also has is a built-in logger which is really helpful if you want to debug your own code. So what you can see here is that by using the Rust logger, you can trace the entire flow. So you have the lexer, you have the parsing part, the syntax tree. So you see first that okay, we have the source code, it is converted into a sequence of tokens, you see them here. And then you see that this expression is now compiled. And then actually this is a part of what someone else made to create a nice... It's basically in Rust, you also have something like the wrapper function we have in Python. So to print out this bytecode object, we can do it like this, and you see the bytecodes. And next thing, for each instruction, it will first print the current frame status. So what you see here is that you have the stack and local variables. En after executing the load name of print, you'll see that there's a Rust function on the stack. Next, there will be a constant loaded. And then you see here, there's a Rust function and a constant on the stack. Then it will call a function with one argument. And it will pop all values of the stack and here print the value 42. And that's quite helpful. And when it's also helpful is when you're interactive in the wrapper from Rust Python. Because then if you enter here, for example, AS2, you will see in between your console, all the logging of the internals of the Rust Python system. So there's also a deer function. So we have AS2. We can say A minus 2, A plus, nope. Typo, it's not full proof. So I wanted to add a, as Alma suggested to add a delete statement now, but I think there's not enough time for that. We'll skip that. So what's the current status of all this? So I would say it's, so all the parts are probably there. But it is in pre-alpha state. It is more or less a prototype. So my ID was, I just had this ID en I want to see if more people are interested in this. Because I actually don't know how much work this, if you want to complete it until CPython comparable level. I have no clue how long this will take, but I'm guessing it's more than one man year, maybe five or 10, I don't know. Here are some ideas with what you can, what are the possibilities? En things I would like to try out. So Rust has a back end for web assembly. I would like to try that and run this Rust Python in a web browser with cargo web, it's called. I didn't try it out yet. And also one interesting thing is that there is no Jil, so no global interpreter log. So I don't know how this will work with multi-training. I have also no experience with that, but since there is no Jil, it might work, I don't know. En also, ja, I would just like to give this ID and see where it goes from here. And that's it, thank you. Hi, thanks for the talk. So one challenge for a variety of alternative Python interpreters like IonPython, Jython, and PyPy has been C extension support because there's a lot of valuable extension modules written particularly for C Python. Is that something that would be easier to manage in writing an interpreter in Rust because it's that same kind of low level that C works on than it would with interpreters written in high level languages? Oh, I think that's a good question. I have no clue. I heard that there's in PyPy, there's the PX layer. So I think that's probably the way to go for that. But yeah, it's definitely interesting because you can also say, okay, we drop all C extension support, but then you lose half of the Python ecosystem. So yeah, I don't know. So I want to ask, since C and Rust interoperate pretty well, did you or the people behind the other Rust Python project think about like a gradual move from C Python to Rust Python by just using C Python in Rust Python as a dependency and then just, is it possible at all? Because theoretically, there's no Python, it's a shared library, so you could use that from Rust. True, true. There is a project which wraps the Python shared library and you can use it from within Rust. So that is there. But I didn't look at that because I didn't want to go that route, actually. But yeah, it might be an idea. I also didn't think of that. I think maybe you have to jump through a lot of hoops to get this working only for a temporary solution. So maybe just go for the end goal. I don't know, but yeah. Hi, great project, by the way, very interesting. Okay. Have you tried to disassemble the demo code that was faster in Python than in your Rust Python interpreter and see what the C is doing compared to Rust? No. Try out, maybe you'll find this wrong. Goed idee. Hallo. Fascinating project. I happen to be one of those crazy people who is working on an alternative runtime. Is this that... I'm totally impressed that you've got the compiler working and the wrapper. Okay. So one of the things was... So if you're trying to do some really crazy optimizations, like Ruby has this thing called fixed knobs, which is essentially trying to encode integers within pointers. We have really fat pointers, you can put a lot of stuff in there. So if you're doing this in, say, C or C++, you can easily reinterpret, cast anything and do whatever you want. Rust seems to be a much safer language. Yeah. Don't do it. Yeah. Have you thought about any of this stuff? I mean, if you want to essentially do some... I mean, if you aim at trying to beat C Python in terms of performance, I also noticed that you have a dictionary in every object. Yeah. So that is still open. So it was a first prototype. So we have to see how that goes, because for an integer it probably does make sense to have a dict object in it. Okay. I probably have hundreds of questions for you. Okay. I'll find you later. We'll talk. Yeah, yeah. Thanks. Any more questions? I didn't use debugger yet. Okay. I don't know. I probably said GDB, I would say. Okay. There are no questions. Then thank you, Wendel. Yeah. Okay.