 Hello everyone. Welcome. Nice to see that so many people are coming in for the NIM talks and not just leaving. So yeah, my presentation here is called NIM on everything. Sorry, just have to update the video stream. So yeah, NIM on everything, how to run NIM on everything from microcontrollers to servers and even in the web browser. I held the presentation here last year. I have a computer science background from University in Trumpsa which is way like above the polar circle somewhere. Mostly with C and Python, it's sort of the background that I came from. NIM has been a really great language to migrate from that starting point. But before we get into how to run NIM on everything, I think it's a bit important to say, why should we run NIM on anything? So since you all seem to come here for the presentation, how many people here have heard of NIM? Oh, wow. Okay. Almost all of you, that's great. How many here have used them, like tried it for simple project? Oh, wow. About half of you. How many of you would say that you're experienced in NIM? Actually, some people I don't know. That's fun. Okay. Yeah. So NIM has compiled statically type language. The type system is really powerful, not like C++ with just numbers and strengths and pointers to random stuff. But we have a proper type system. We have distinct types. So you could have a number, can store multiple types of information, and you can reflect that in the type system in NIM. So you could have something like this is a meter, this is a dollar, you can't add meters to dollars because that would, or maybe you can, I don't know, but for your application. But you can create distinct types, and this is actually something that helps us with another of the great features, which is metaprogramming. I'll come back to that later. It's also garbage collected, which might sound weird when I'm talking about running it on microcontrollers. But you can actually turn the garbage collector off, and you can also tune it. So you can say, for example, if you're making a game run at 60 FPS, if we have some time left over in our frame, then we do garbage collection. So it really doesn't get in the way like Java, for example, you have a game playing along and just everything suddenly freezes while it's collecting your garbage, and then you can't get back to playing. So you can avoid that. I also included a hero quote that I had last year, the speed of sea, ease of Python and flexibility of Pearl. I thought this was something that Andrea said, the creator of NIM, apparently not, and now I've seen it attributed to me in other presentations. So apparently that's a quote of my own. So yeah, one of maybe or maybe the most sort of killer feature of NIM is a metroprogramming or the strongest kind of which is macros. Dominic is going to talk a bit more on this later today. So if you want to know even more, go see his talk as well. And with metroprogramming, what we can do is that we can really optimize our code. So we can, for example, take in types and do certain things on compile time, spit out code that works better than the code we gave it. We can also create nice looking code. So we can create nice looking code that we then optimize to be ugly code, but fast running code. For example, this case, we also have a safer way or a safety element to it. So here we can write a with lock template. This is actually in the standard libraries and I would write this yourself. And with this, you can just give it a block. It will do the try finally stuff for you. Pretty much, I think everyone who's ever worked with multi-threading and locks, you know you should do this, but you probably don't. Everywhere where you use locks. But with metroprogramming, you can easily create templates to do all of that boring stuff that you know you should be doing, but you can't be bothered. So you can do all of that automatically or some way automatically. It also works on the abstract syntax tree instead of on text. So if you've used macros and for example C, they are just taking some text, do some replacements, spit out some new text. But this works on a tree structure. So it parses name code into a tree structure. Then you can play around with that tree structure and you can give it back another tree structure. And this is something that really allows us to compose these macros in a much more efficient way and we can really make them do a lot more for us or at least easier to do a lot more for us. This is just an example. Here we take in a static string. So also the type system or the type system also applies to macros. And all of the metaprogramming. So for example in C macros again, you don't really have types. You take in something and you just put it in there and then you pass it off to the type system. Here types are actually checked when you call this function or this template, this is a macros. When you call this macro, it will actually check that your type is correct before trying to do anything with it. So you won't get some weird error message from somewhere else in your system. Yeah, I can buy time, yeah. So in this case, this is a static string. That means that this is a string on compile time. If we had just a string, it's actually anything that can become a string on runtime. So if you can give it a variable that's only available on runtime. But we tell that the macro system that yes, this should be something that will be a string when we're running this code. So you can take that symbol and put it somewhere and you know that it's gonna be a string when the code is run. This is just an example from the manual. Take a string, split it up, and this will actually spit out just an array of these four elements. And you won't have to do any of the string stuff on runtime. And this is great for microcontrollers, for example. You don't want to do string splitting on a tiny microcontroller. This way you can do all that on compile time. And then on runtime, you just have your array with pre-splift and done everything. So I mentioned that name is a compile language, but it doesn't compile directly to binaries or to code that you can run or to binaries. It uses C, C++, also Objective C, and JavaScript as sort of intermediary languages. So it first compiles, so it takes away some of the abstractions. It doesn't compile your macros into like C macros. So it compiles down to C, C++, JavaScript, and then it hands that over to the compiler, which actually creates the binary for you. And because of these languages, like they've been around for so long, you can really take your name code and run it on anything that can run these languages, which is pretty much any device. We have name running on microcontrollers, as I said, servers, Android phones, iPhones, of course, servers, laptops, anything. This also means that we can very easily tie into the native libraries of that system. So you can take a C library and just say, well, call this C function or a JavaScript library and say call this JavaScript function. So you can really easily tie into the system that you're building for. It also means that, as I write here, we're standing on the shoulders of giants. Because we have the benefit of all of the work that's gone into, for example, the GCC compiler. It's been around for a long time. There's a lot of optimizations built into that thing. And we get all of that sort of for free by creating C code. So that means it's super fast and it also doesn't spit out human readable code. So it uses C more as a target. You wouldn't want to read the name C code. I know that some people do, but it's not great. And I mean, if you're working with someone on a C project and you start committing the code that namespits out, they're not going to be happy with you. And that's also, a lot of people say, well, you have the speed of C, but you're obviously doing something more than what you can do in C. So how does that work? Like, there's got to be more work here. And the answer is just, because we're spinning out stuff that no sane human would write or read or maintain, it means that our C code can be more efficient than what you would normally write as a C programmer. Another question is, why not LLVM or WebAssembly? The answer to that is pretty simple. WebAssembly didn't exist when it was created and LLVM was still sort of kind of new when no one really knew about it. And it wasn't, yeah, it wasn't proven to be what it is today. When I first discovered them, I remember I clicked into the website, I was like, oh, compiles to C and JavaScript, that can't be good. There has to be some trade-offs here. You can't do everything you can do in C and JavaScript, that doesn't work. But the way NIM solves this is that you can't run all NIM code on both JavaScript and C. Like you can't access the DOM tree when you're writing C code and you can't do pointers when you're compiling to JavaScript. So really, this is an example, two pieces of code, both in NIM. On the right-hand side, we have some JavaScript stuff. It just interfaces with regular document, create element, onload, regular JavaScript stuff. On the left side, you have some of my horrible code from a work project that interfaces with sockets and stuff on the NSE library. And it's really, it's based on, we have the same syntax, we have the same metaprogramming capabilities, we have the same type system, but it's not exactly the same language. So it really, it gives us all of the benefits of NIM, but it doesn't take away any of the benefits or sort of capabilities of the underlying language. So what we're actually here to talk about, NIM on everything. So let's start with the smallest. These are all things you can program with the Arduino ID. This one is a DigiSpark. It has four kilobytes of accessible memory, or it has six, the two of those are used for the bootloader. And NIM runs on that. You have the Arduino Boy, which is kind of fun. It's an Arduino Leonardo-based thing with just a screen and some buttons and a tiny little speaker. It has 32 kilobytes of program memory. And you can run NIM on that. I made a breakout clone for it and that's an interesting thing. With this device, when I was writing the code, I was compiling it and it comes out to the same binary sizes. Like give or take a few bytes. So really when you're compiling NIM code into C code and then on to the Arduino, if you're not doing something dumb, like of course you're turning off the garbage collector and avoiding some stuff that you know is going to take up space. But like a one-to-one rewrite from C to NIM actually turned out to be pretty much the exact same footprint on the chip. So unlike, for example, MicroPython, I've run MicroPython on some devices and I was like, why am I running out of memory? I'm reading like two sensors and this is a super capable chip. I was like, ah, yeah, I have the Python interpreter. I have a lot of string handling. Of course I'm running out of memory. And I say we're running without the garbage collector right now. Here at Faustum, we were actually able to get it to work with GCE Arc. So now you can do strings and sequences and stuff on these. You probably don't want to, but you can. And it means that all of the standard libraries should be available at some point because now there are some points that you actually can't use. And really the benefit, like as I said, when you do a one-to-one rewrite, it's pretty much the same. But if you're doing a one-to-one rewrite, why do it in NIM? Why not just write the C code? And the thing is that you can use the metaprogramming. You can use all of the extra features. So again, for the Arduboi, I wrote a macro that loads sprites on compile time. It reads in the sprites as images on compile time. It converts them to the internal image representation that the Arduboi libraries use. And I'm using the same C libraries as the regular Arduboi code. And I'm casting them to a type that on compile time knows the size of the image. So for example, this draw-bit map. It takes a logo and a logo mask. And these have to be the same size because otherwise, like, what would it do with them? But because I do them through this load sprite function, I'm saving the size of the images in my type. So on compile time, I can check that these two sprites are actually the same size. So I can never call this function with two sprites that won't do the thing I expect them to and create crashes and stuff. So it's actually both safer. And I don't have to go through, like, a web UI to convert my sprites into an age file which I download and then put them to my project folder and run it. And I don't have to do any of that. Just load sprite, draw it, done. And it's also now running in the Arduino IDE. This was hacked together very recently. But it actually works. You can open the Arduino IDE, type name, code, hit upload. It goes straight onto your microcontroller, and it just works. There was also, and NIM forums, a Chinese Bluetooth low-energy chip producer that just out of nowhere posted that, hey, we're making Bluetooth low-energy chips and we have a NIM SDK. So it's actually catching on, even with chip manufacturers, not only users. But again, since we can use C libraries, we don't have to rewrite all our SDKs ourselves. We can just use the existing C ones and use those directly. You can also, of course, run it on a server or desktop or any regular computer. Again, we can use all the libraries, like databases, MySQL, MariaDB. We can use GUI libraries. This is a GUI library that I took. It's VX widgets. So this runs on GTK and Windows and Coco on Mac. This is just done with a macro. So the code for this looks super clean. And this runs regular programs. We also, the backend for the NIM forum is running on NIM. The backend for the NIM playground. So you can go to play.nim-lang.org and just type NIM code and head to run. Compiles it on a server since you back the results. That is written in NIM. This is another example, again, taken from the NIM forums. It created a GUI for doing some unlocking stuff and setting up servers for Battlefield, I think it was. Of course, a lot of terminal tools, NIM compiler, NIMble. A lot of stuff you can write in them. You can also run it on the web. We can compile to JavaScript, as I mentioned. Again, this is not something that you would want to look at necessarily. And again, the forums, the front end for those are also written in NIM. The playground, again, it's also written in NIM. And as I mentioned, we don't have a lot of stuff like the C pointers and all of that, but what we do have is stuff like DOM. We have JS-specific modules that are only available for the JavaScript target that only does JavaScript-specific things. But also we can use JavaScript libraries. So in the same way that we can use existing C++ code when we're running on Arduino or database code when we're running on a server, we can run JavaScript libraries in our JavaScript code. So, for example, the playground uses standard input with syntax highlighting and all of that. Don't have to re-implement that myself. Just find it like you would normally do when you're writing JavaScript. Use that, works great. And of course, we don't use the JavaScript garbage collector. We didn't build a garbage collector on top of a garbage collector. So that doesn't apply to the JavaScript target. Here's one example. Real Valley was written almost, I think, 100%, 99.99. I think it's written in a blog post somewhere. Both server frontend runs on phones, runs on web embedded on Facebook, the servers as well. These are the forums that I mentioned. Looks kind of like discourse. A lot of people think it is. But it's sort of a lightweight alternative to discourse that is written entirely in them. Yeah, that was my talk. Bit faster, but we're a bit behind schedule. So I think that's fine. Actually, we can take a couple of questions because you still have seven minutes. Yeah, yeah, yeah. And probably the next pages will come and... Yeah. Ah, templates are more like macros in C. So they are simple replacement. So if you look at the example here, this template is just... You have the lock and the body and lock and body in this code is just being replaced with whatever you pass in. But otherwise, the body is the same. In a macro like this, you see we create a new tree, like a new AST tree, and then we add nodes into that tree. So the code that actually comes out is not the code that you see here, but the code that you generate through the AST. Yeah, sorry, I should have repeated the questions. But so you're asking, can macros access the file system? And the answer is yes. What? And yeah, you can run static exec so you can run any program on your computer as well. So you have to be careful when you run other people's code. But on the other hand, it means you can do anything in a macro. Yep. So the question is if there are plans to support LLVM, I don't... Yes, I'm getting yes from Andreas back here. Yep. So yes. So the question is, when you turn off the garbage collector, is there any sort of backup? Yeah. So you have options. You can use different garbage collectors. So you can find one that suits your need. One of them is reference counting. When you turn it off, it doesn't do anything. But you will get warnings when you're compiling that says this uses garbage collected memory. But on runtime it is just going to leak, like I said. Any more questions? Yep. So the question is, can you do manual memory management? And the answer is yes. You can use malloc. You can use free. Again, like for interfacing with C, you need them anyways. So the question is, is it feasible to write large project name in reference to compile times? I would say definitely yes. It compiles super fast. And I know there is work on doing incremental compilation. I have to say if you write super complex macros or if you do like me and write a parser that isn't very good, then you can quickly rack up some compile time. But compared to C++ or something like that, it's nothing. It's run super fast. So the question is, when you're compiling to C, can you get C errors? And does that happen often? Answer, yes, it can happen. And no, it doesn't happen often. If it happens, there's something wrong in the compiler and you should create an issue in GitHub. Yeah, no, no, yeah. You can do emit. So just emit a block of text into your code file. That, of course, will get you errors. You can also do some weird things with code gendacle stuff. But if you're using them like a normal person, then you shouldn't have any issues for that at all. There was a hand, yeah? So is the language specification out on the web? Yes, it is in the manual. There is maybe some idiosyncrasies between the implementation and the specification, but in general it's, yes. Yeah, who is the next speaker? Oh, Andreas, yeah, just come down. He's using my machine, so it's fine. Do we have any more? Yeah, just come down.