[00:00.000 --> 00:07.760] Right, so welcome. [00:07.760 --> 00:14.440] My name is Ramco and I'm here to talk about two very undeclarative but very minimal and [00:14.440 --> 00:17.320] hopefully useful languages. [00:17.320 --> 00:18.960] So the first one is FORTH. [00:18.960 --> 00:25.040] FORTH is a very minimal programming language that's been around since the 70s. [00:25.040 --> 00:31.080] It's had mostly applications in low-level contexts such as embedded systems, spacecraft [00:31.080 --> 00:35.040] controllers and so on, but it's had some other applications as well. [00:35.040 --> 00:40.560] Now if you look at FORTH, the most obvious thing to notice is that it's stack-based. [00:40.560 --> 00:45.840] So it uses a reverse-polish notation where you first put something on the stack and then [00:45.840 --> 00:46.840] you call a function. [00:46.840 --> 00:53.160] But other than that, it looks like a regular high-level language with syntax for constant [00:53.160 --> 00:58.800] variables for comments, syntax for function definitions, loops and conditions and so on. [00:58.800 --> 01:01.320] But actually, that's an illusion. [01:01.320 --> 01:03.640] FORTH has almost no syntax. [01:03.640 --> 01:07.000] So FORTH executes through a very simple interpreter loop. [01:07.000 --> 01:13.520] So what it does is it reads something up until the next space and then decides, is it a number? [01:13.520 --> 01:15.740] I'm going to put it on the stack. [01:15.740 --> 01:17.160] Is it something else? [01:17.160 --> 01:21.120] Then I assume it's a function which is called a word in FORTH and it's going to execute [01:21.120 --> 01:22.440] it. [01:22.440 --> 01:29.120] So symbols is just like any normal word, so it's just a function of FORTH. [01:29.120 --> 01:30.360] Same goes for the colon. [01:30.360 --> 01:33.920] Colon starts a new definition of a word. [01:33.920 --> 01:40.000] Colon, when it executes, it puts the interpreter into a special mode called compilation mode. [01:40.000 --> 01:45.560] In this compilation mode, the interpreter still advances token by token, but when it [01:45.560 --> 01:49.480] encounters a number, instead of putting it on the stack, what it does is it generates [01:49.480 --> 01:54.960] some code that will put that number on the stack later when this word is executed. [01:54.960 --> 01:57.000] Same for another symbol. [01:57.000 --> 02:00.280] Instead of calling this function, what it's going to do is it's going to compile some [02:00.280 --> 02:06.320] code that will call this function when this word is executed. [02:06.320 --> 02:19.760] Now the same goes actually another, sorry, so it's going to compile. [02:19.760 --> 02:25.560] The exception for this is that there is a thing called immediate words. [02:25.560 --> 02:30.120] Immediate words are always executed even if your interpreter is in compiler mode. [02:30.120 --> 02:35.880] An example of such an immediate word is the opening parenthesis which starts a comment. [02:35.880 --> 02:47.560] When it executes, what it will do is it will actually consume all the input. [02:47.560 --> 02:49.760] Another immediate word is the semicolon. [02:49.760 --> 02:53.000] So the semicolon is what you see when you end the definition. [02:53.000 --> 02:59.280] What this will do is it will put your interpreter back out of compilation mode into interpretation [02:59.280 --> 03:00.600] mode. [03:00.600 --> 03:04.840] Other of these immediate words are the loops and the ifs and then else, and you can actually [03:04.840 --> 03:10.160] create your own immediate words and as such, extend the compiler because these are executed [03:10.160 --> 03:11.160] at compile time. [03:11.160 --> 03:15.640] So you extend the compiler and you create your own language. [03:15.640 --> 03:21.000] So in summary, fourth is actually nothing but a very simple interpreter loop with an [03:21.000 --> 03:23.840] integrated compiler. [03:23.840 --> 03:26.320] There is no syntax almost to fourth. [03:26.320 --> 03:28.120] Just paste the limited tokens. [03:28.120 --> 03:33.400] All the behavior of the language is in the execution of these definitions and you can [03:33.400 --> 03:37.160] actually extend the compiler yourself. [03:37.160 --> 03:44.240] This combination of super simplicity and power has actually made fourth a very attractive [03:44.240 --> 03:49.840] language to implement on a new piece of hardware and a restricted piece of hardware. [03:49.840 --> 03:55.000] Typically, these fourth implementations are targeted at hardware assembly, but you can [03:55.000 --> 04:00.520] actually do this in any low-level language, which brings me to the second language of [04:00.520 --> 04:02.040] my talk, WebAssembly. [04:02.040 --> 04:04.800] So I think everybody here knows WebAssembly. [04:04.800 --> 04:08.600] It's an open standard for portable binary code. [04:08.600 --> 04:11.800] Most browsers can execute WebAssembly. [04:11.800 --> 04:16.120] Many languages can compile to WebAssembly, so the result is that you can run all these [04:16.120 --> 04:19.280] languages in a browser. [04:19.280 --> 04:24.320] Although WebAssembly was designed for the web, there's actually nothing web-specific [04:24.320 --> 04:25.320] about WebAssembly. [04:25.320 --> 04:30.080] It's just an open standard of portable code. [04:30.080 --> 04:35.440] So most of the information you find online about WebAssembly is about how you compile [04:35.440 --> 04:40.440] your favorite language to WebAssembly or how you run WebAssembly in your browser. [04:40.440 --> 04:45.760] So a few years ago, I wanted to figure out what was actually under the hood of WebAssembly. [04:45.760 --> 04:48.800] And at the same time, I came across fourth. [04:48.800 --> 04:54.400] So what I did was I combined both, hoping that I would learn something about both. [04:54.400 --> 04:57.240] So that's why I created WA fourth. [04:57.240 --> 05:00.880] WA fourth is a small fourth system. [05:00.880 --> 05:05.420] It's completely handwritten in WebAssembly, and it compiles to WebAssembly. [05:05.420 --> 05:11.360] So goals are, WebAssembly tries to, WA fourth tries to do as much as possible in WebAssembly. [05:11.360 --> 05:16.960] Now the problem is WebAssembly is a portable standard, so you cannot do everything in WebAssembly. [05:16.960 --> 05:21.640] For example, it needs to do very few things outside of WebAssembly. [05:21.640 --> 05:27.480] For example, reading or writing a character to the output or reading from the input. [05:27.480 --> 05:30.360] WA fourth tries to be simple. [05:30.360 --> 05:33.120] So it's just one big WebAssembly file handwritten. [05:33.120 --> 05:36.920] There are no dependencies, no complex tools. [05:36.920 --> 05:39.920] The compiler is very simply written. [05:39.920 --> 05:43.800] It still tries to be complete enough to be useful. [05:43.800 --> 05:48.280] There's an ANS standard that defines what the fourth interpreter needs to implement, [05:48.280 --> 05:50.200] the minimal set of words. [05:50.200 --> 05:57.200] WA fourth implements these and implements a bunch of other words as well. [05:57.200 --> 05:58.680] What isn't the goal is speed. [05:58.680 --> 06:03.520] So of course, because WA fourth is implemented in WebAssembly, you're going to get some speed [06:03.520 --> 06:04.800] for free. [06:04.800 --> 06:09.920] But still the compiler is very naive, so I don't expect it to be very fast. [06:09.920 --> 06:12.760] Same goes for binary size of the system. [06:12.760 --> 06:15.920] It's written in WebAssembly, so it's going to be naturally very small. [06:15.920 --> 06:20.920] In fact, it's about 14 kilobytes of WebAssembly, compiled binary WebAssembly. [06:20.920 --> 06:26.400] However, I'm not doing any code golfing or something like that to keep the system small [06:26.400 --> 06:28.880] because I want to keep it simple. [06:28.880 --> 06:35.200] And as most fourths are not really known to be very user friendly and WA fourth is not [06:35.200 --> 06:41.160] different, although it does emit some debugging information to make debugging easier, as you [06:41.160 --> 06:43.800] will see. [06:43.800 --> 06:45.440] So what can you do with WA fourth? [06:45.440 --> 06:50.560] Well, you can embed it in any JavaScript application, which means you can run fourth [06:50.560 --> 06:57.600] code inside your JavaScript and you get bi-directional bindings to the system and back to JavaScript. [06:57.600 --> 07:01.680] To illustrate this, I have a few example applications. [07:01.680 --> 07:08.560] So the first one is the standard fourth console that always exists where you can interactively [07:08.560 --> 07:14.720] execute fourth code and you can even interactively compile code and then run this compiled code. [07:14.720 --> 07:19.040] So it's a wrapper, actually. [07:19.040 --> 07:25.040] I also have a small graphical programming environment where you can create some graphics [07:25.040 --> 07:30.120] using a logo-like turtle graphics language, but it uses fourth. [07:30.120 --> 07:32.720] It looks a lot like logo, but it's actually fourth. [07:32.720 --> 07:39.360] And I took this a bit further and then I created a notebook extension, VS Code extension to [07:39.360 --> 07:40.720] create VS Code notebooks. [07:40.720 --> 07:47.720] So these are actually formatted markdown files interleaved with runnable code, so you can [07:47.720 --> 07:48.720] run this code. [07:48.720 --> 07:52.720] This is ideal for tutorials because you can have the code directly there, you can execute [07:52.720 --> 07:58.440] it, you can change some parameters and then see what the effect is by rerunning the program. [07:58.440 --> 08:03.960] Now because this is just WebAssembly and it's just a very small system, there's also a script [08:03.960 --> 08:10.200] that converts these notebooks into a standalone, small standalone HTML file with all the functionality, [08:10.200 --> 08:13.880] but you don't actually need VS Code anymore to run it. [08:13.880 --> 08:19.280] Now let's have a look under the hood. [08:19.280 --> 08:25.960] Like most assembly formats, WebAssembly has a text-based format, which is much easier [08:25.960 --> 08:28.840] to read than the binary format for humans. [08:28.840 --> 08:35.640] So this text-based format is based on S expression, so it looks a lot like Lisp. [08:35.640 --> 08:42.240] So this right part here is the entire fourth interpreter that I described earlier, but [08:42.240 --> 08:46.960] comes straight out of WA fourth, and it's actually quite easy to understand. [08:46.960 --> 08:52.560] So first it starts by parsing something, parsing the token and then it's going to either execute [08:52.560 --> 08:57.160] it if it's a function or it's going to compile it if you're in compiler mode, or if it's [08:57.160 --> 09:01.080] a number then it's going to put it on the stack or it's going to compile it. [09:01.080 --> 09:10.720] So this tree-like code structure is then transformed to binary WebAssembly using a tool from WebIt. [09:10.720 --> 09:14.560] WebIt is a WebAssembly binary toolkit. [09:14.560 --> 09:19.160] This is actually a toolkit with a lot of tools to work with WebAssembly files. [09:19.160 --> 09:23.840] It's a very interesting project to look at. [09:23.840 --> 09:25.960] So this is the entire interpreter. [09:25.960 --> 09:27.720] The interpreter is actually quite simple. [09:27.720 --> 09:31.200] The interesting part is the part where you have to compile something. [09:31.200 --> 09:33.920] So you have to compile a call when you're in compiler mode. [09:33.920 --> 09:36.360] So how does this work? [09:36.360 --> 09:42.800] Well somewhere in memory there is a hard-coded binary header of a WebAssembly module with [09:42.800 --> 09:44.540] one function in it. [09:44.540 --> 09:50.200] So when a new word definition starts, what happens is some values in this header are reset [09:50.200 --> 09:54.480] and the pointer is initialized to start at the end of the header. [09:54.480 --> 09:59.240] So each time the interpreter, this is the piece of the interpreter, needs to compile [09:59.240 --> 10:08.240] a call to a function, what it does is it generates some raw binary WebAssembly hexcodes and puts [10:08.240 --> 10:09.360] it at the end of the header. [10:09.360 --> 10:15.280] So for example if it needs to do a call, what it does is it generates a hexcode for a constant [10:15.280 --> 10:21.280] instruction with the index of the function to call and then an indirect call instruction. [10:21.280 --> 10:26.320] And so the compiler keeps on adding binary code to the end of this module. [10:26.320 --> 10:30.920] Now once you reach the end of the definition, this code, this binary piece of code, needs [10:30.920 --> 10:33.200] to be loaded into the system. [10:33.200 --> 10:36.240] So WebAssembly doesn't support anything for this yet. [10:36.240 --> 10:41.040] So there's no support for just in time compilation, although there are some discussions about [10:41.040 --> 10:43.040] it. [10:43.040 --> 10:47.920] So what WA4 does is it takes a pointer to this piece in memory of binary code and it [10:47.920 --> 10:49.520] passes it to the host system. [10:49.520 --> 10:51.760] So in this case it's JavaScript. [10:51.760 --> 10:55.880] And JavaScript has a small piece of code here running, what it does is it takes this binary, [10:55.880 --> 11:02.880] it uses the WebAssembly API to create a new WebAssembly module and it instantiates it. [11:02.880 --> 11:05.000] That's all JavaScript has to do. [11:05.000 --> 11:10.400] The rest is tracked by WA4, it keeps track of which module corresponds to which function [11:10.400 --> 11:14.800] that it needs to call or compile later on. [11:14.800 --> 11:17.560] So here you can see the system in action. [11:17.560 --> 11:23.480] So what's happening here is now it's you start the definition, you start by compiling something [11:23.480 --> 11:29.160] so you're still in compilation mode. [11:29.160 --> 11:33.160] And so it's only when you reach the end of the definition that suddenly you're going [11:33.160 --> 11:38.600] to see a new entry in your WebAssembly debugger with a function that has been loaded. [11:38.600 --> 11:47.880] So, and this is the generated WebAssembly code that's been generated by the compiler. [11:47.880 --> 11:54.200] You can get even more control over this compilation process by writing your own WebAssembly inside [11:54.200 --> 11:56.200] 4th. [11:56.200 --> 12:01.920] So this is actually, this is again no new syntax, this is just standard 4th with some [12:01.920 --> 12:03.760] user defined words. [12:03.760 --> 12:08.520] And there's one direct one-to-one mapping from this to this, if you can read it, but [12:08.520 --> 12:12.400] probably can't from there. [12:12.400 --> 12:17.000] Last thing I want to note about implementation detail is that most 4ths have very efficient [12:17.000 --> 12:19.960] execution by using a system they call ThreadedCode. [12:19.960 --> 12:24.960] So ThreadedCode is actually called doing jump instructions all over the place using values [12:24.960 --> 12:27.960] that come from memory or from registers. [12:27.960 --> 12:30.600] Now this is something you can do in WebAssembly. [12:30.600 --> 12:33.480] WebAssembly only allows structured jumps. [12:33.480 --> 12:37.920] So WebAssembly is actually structured programming language. [12:37.920 --> 12:40.520] What WebAssembly does have is function tables. [12:40.520 --> 12:45.600] So these are dynamic tables where you can put functions in, function references in, [12:45.600 --> 12:50.280] and then it comes with a special instruction where you can say jump to the function at [12:50.280 --> 12:51.800] this index. [12:51.800 --> 12:57.960] This is a system that WA4th uses for calling the words. [12:57.960 --> 13:05.960] Now the downside is that this is a very inefficient system compared to direct calls or jumps. [13:05.960 --> 13:12.760] So I said that speed wasn't really a goal for WA4th, but it's still interesting to get [13:12.760 --> 13:17.800] some ID of ballpark numbers of speed and size involved. [13:17.800 --> 13:23.120] So I did some very unscientific thing, and I took an algorithm, in this case the sieve [13:23.120 --> 13:25.080] algorithm to compute prime numbers. [13:25.080 --> 13:29.880] I took a fourth implementation, ported it to JavaScript CE WebAssembly, and then ran [13:29.880 --> 13:33.400] it a few times and see what the result was. [13:33.400 --> 13:38.840] Again this is not a very representative benchmark, but it's just here to get a feel for some [13:38.840 --> 13:39.880] numbers. [13:39.880 --> 13:45.160] So if you look at the execution times, WA4th is about 10 times faster than a JavaScript [13:45.160 --> 13:46.520] 4th version. [13:46.520 --> 13:48.120] This is to be expected. [13:48.120 --> 13:53.160] JavaScript 4th versions do pure interpretation, WA4th uses compilation, so there's no surprise [13:53.160 --> 13:54.160] there. [13:54.160 --> 14:00.320] But what is a bit surprising is that G4th, which is a native 4th, is not much faster [14:00.320 --> 14:01.320] than WA4th. [14:01.320 --> 14:05.880] I have no idea why this is, I'm suspicious about this result, maybe it's because I'm [14:05.880 --> 14:10.840] using an architecture that G4th isn't optimized for. [14:10.840 --> 14:15.240] JavaScript is 10 times faster than WA4th, which is also normal because WA4th needs to [14:15.240 --> 14:18.920] do these constant indirect jumps, and JavaScript doesn't have this problem. [14:18.920 --> 14:23.040] It doesn't need to do any function calling at all. [14:23.040 --> 14:28.440] And then finally, if you have the C version, and you compile it to WebAssembly using M-scripten, [14:28.440 --> 14:33.360] it's about as fast as running the raw WebAssembly, and the native version of the algorithm is [14:33.360 --> 14:34.360] slightly faster. [14:34.360 --> 14:39.280] Although you have to say the WebAssembly engine is pretty good at running this code compared [14:39.280 --> 14:41.800] to native code. [14:41.800 --> 14:47.080] So if we look at the size of the runtime and the code that is executed, the main takeaway [14:47.080 --> 14:55.280] here is that WA4th is actually a very small system, it's like about 15K, but you need [14:55.280 --> 15:01.840] a complete browser to run it, so that's of course huge to run. [15:01.840 --> 15:06.840] So the question is, can we improve this situation? [15:06.840 --> 15:14.200] So actually there are several standalone implementations of WebAssembly in different languages. [15:14.200 --> 15:19.960] For example, WebIt has a reference implementation in C++, there's WasmTime, which is security [15:19.960 --> 15:25.800] focused and speed focused in Rust, but there are several others. [15:25.800 --> 15:31.400] But these only do the WebAssembly part, so there's still this small piece of code, these [15:31.400 --> 15:36.080] small pieces that are outside of the system that you need to call out to. [15:36.080 --> 15:40.120] If you wanted to use all these engines and try this out and create a standalone version, [15:40.120 --> 15:44.200] you would need to write this little piece of code in all these languages against all [15:44.200 --> 15:45.200] these APIs. [15:45.200 --> 15:50.120] Now luckily there's something called the WebAssembly C API, and this is a standardized [15:50.120 --> 15:55.960] Blackbox API that most of these systems implement. [15:55.960 --> 16:00.880] So actually the only thing you have to do is write these, I had to do was write these [16:00.880 --> 16:06.360] 200 lines of implementation in Dependency, and then I could drop in any engine I wanted [16:06.360 --> 16:11.920] and then have a standalone version of my system. [16:11.920 --> 16:17.160] Now if we look at some, the same benchmark again, we can see that speed-wise, WebIt is [16:17.160 --> 16:21.400] about 100 times slower than the browser version, which is normal. [16:21.400 --> 16:27.080] I mean, this version in WebIt, that's a reference implementation, it's very naive, it just does [16:27.080 --> 16:30.040] what it needs to do to be functional. [16:30.040 --> 16:34.520] What is a bit weird is that WasmTime, which is supposed to be fast, is still about 10 [16:34.520 --> 16:38.320] times faster than the browser version, and there is no good reason for this. [16:38.320 --> 16:42.440] So I don't know why this is, I haven't tried other engines yet. [16:42.440 --> 16:49.680] Now if you look at size, you see that if you use a relatively optimizing system, you still [16:49.680 --> 16:55.080] have 90 megabytes, which is a lot smaller than a browser, but still if you have a system [16:55.080 --> 17:00.040] of about 15K, this is still big. [17:00.040 --> 17:03.160] Can we do something about this? [17:03.160 --> 17:08.920] Well, you need the WebAssembly runtime to be able to run your fourth code and to compile [17:08.920 --> 17:13.520] your code and load it, but typically most programs, once you did the first pass and [17:13.520 --> 17:18.080] you did all the compilation necessary, you no longer need a compiler if you want to run [17:18.080 --> 17:19.960] the program again. [17:19.960 --> 17:24.680] So you can do some out-of-time compiling, and this is where WA4C comes in. [17:24.680 --> 17:31.320] So what it does is it takes your fourth program, it uses WA4C to run your program once, and [17:31.320 --> 17:35.820] at the end of the cycle, it's going to look at all the modules that you created, it's [17:35.820 --> 17:41.400] going to combine them all, combine the final state, and then create one big WebAssembly module [17:41.400 --> 17:42.400] out of this. [17:42.400 --> 17:47.920] Now it's going to take this big module and then use another tool from Rabbit, Rabbit is [17:47.920 --> 17:54.000] really a cool toolset, it's going to use another tool from Rabbit called Wasm2C to transform [17:54.000 --> 17:58.720] this big module into C, and then it's going to use your host compiler to create a native [17:58.720 --> 18:00.440] executable. [18:00.440 --> 18:06.320] So the end result is that you have a fourth code to native compiler and your native binary [18:06.320 --> 18:11.680] is your fourth code with the rest of the fourth system still in there, but the compiler left [18:11.680 --> 18:12.680] out. [18:12.680 --> 18:20.000] And the cool thing is that because this is all platform-independent stuff up until the [18:20.000 --> 18:24.800] native compiler, you can actually do cross-compiling easily, so you can just do cross-compiling [18:24.800 --> 18:27.240] from fourth to any architecture you want. [18:27.240 --> 18:32.560] And all this code is about 500 lines and uses a lot of stuff from Rabbit actually, and Rabbit [18:32.560 --> 18:37.560] is the only dependency here. [18:37.560 --> 18:42.600] So if you look at our final table of benchmarks, we see that the speed is slightly better than [18:42.600 --> 18:47.120] Wasm, than it was before in the browser version, and the binary is becoming a lot smaller, [18:47.120 --> 18:53.280] so the entire system is only about 116K in the end of native code. [18:53.280 --> 18:56.000] Now there's still room for improvement here. [18:56.000 --> 19:02.560] So what WA4C does is it just throws together all these modules and then generates the big [19:02.560 --> 19:04.480] module. [19:04.480 --> 19:09.280] Now this big module, there are no cross-module calls anymore, so what you could do is actually [19:09.280 --> 19:10.680] do some post-processing. [19:10.680 --> 19:16.040] You could change all these indirect calls into direct calls, which could speed up a lot [19:16.040 --> 19:19.120] because the calls are really the bottleneck here. [19:19.120 --> 19:22.760] Another thing you could do is throw away code that you don't need. [19:22.760 --> 19:28.440] So in conclusions, this was a very fast talk. [19:28.440 --> 19:31.080] I could only touch upon things very briefly. [19:31.080 --> 19:37.000] What I did was I used fourth to explore low-level language implementation in WebAssembly. [19:37.000 --> 19:42.200] Because fourth is so minimal, I was able to keep things very simple, try out a lot of things, [19:42.200 --> 19:43.200] and go a lot of places. [19:43.200 --> 19:49.800] But I think a lot of the things that I've shown here are actually applicable to other [19:49.800 --> 19:50.800] languages. [19:50.800 --> 19:53.800] You could use declarative languages if you want to compare to WebAssembly. [19:53.800 --> 19:59.800] Although I have to say, if you don't know fourth yet, I can really recommend having a [19:59.800 --> 20:04.400] look at it because I find that there's some interesting philosophies and concepts behind [20:04.400 --> 20:05.400] it. [20:05.400 --> 20:06.400] Thank you. [20:06.400 --> 20:26.480] Questions? [20:26.480 --> 20:28.200] It was fast, wasn't it? [20:28.200 --> 20:29.200] Sorry about that. [20:29.200 --> 20:31.200] Sir, I have a question. [20:31.200 --> 20:34.400] We seem to be dealing in rather old languages today. [20:34.400 --> 20:35.400] Yeah, yeah, yeah. [20:35.400 --> 20:36.400] I always have been. [20:36.400 --> 20:39.400] It's at least the 60s, I think, or 50s even. [20:39.400 --> 20:40.400] Yeah, yeah. [20:40.400 --> 20:41.400] And fourth is early 70s. [20:41.400 --> 20:42.400] Yeah, yeah, yeah. [20:42.400 --> 20:43.400] WebAssembly is nowhere. [20:43.400 --> 20:44.400] Yes. [20:44.400 --> 20:45.400] WebAssembly is slightly newer. [20:45.400 --> 20:46.400] So yes, I... [20:46.400 --> 20:47.400] We'll have more from the 90s later. [20:47.400 --> 20:48.400] Okay. [20:48.400 --> 20:49.400] One question? [20:49.400 --> 20:50.400] Yeah, one thing is that there was a... [20:50.400 --> 20:51.400] Potentially, you could... [20:51.400 --> 20:52.400] I'm not sure. [20:52.400 --> 20:53.400] One potential direction. [20:53.400 --> 21:10.400] You could also consider doing the code generation in JavaScript, as in you can just create function [21:10.400 --> 21:11.400] out of binary... [21:11.400 --> 21:14.400] Out of text in JavaScript. [21:14.400 --> 21:15.400] And the same thing... [21:15.400 --> 21:19.400] I'm not sure the infrastructure how much can be shared, but the same thing could happen [21:19.400 --> 21:26.400] also in JavaScript side, as in the thing of compiling the code, the JavaScript side, [21:26.400 --> 21:27.400] and then it's... [21:27.400 --> 21:30.400] So it could get to JavaScript. [21:30.400 --> 21:35.400] So the level of performance of JavaScript. [21:35.400 --> 21:37.400] I'm not sure if it's interesting. [21:37.400 --> 21:44.400] So the question is, can I reach the same performance if you do it in JavaScript? [21:44.400 --> 21:50.400] Potentially, there is this thing passing through WebAssembly and this JS port you mentioned, [21:50.400 --> 21:55.400] but potentially it's also possible to do code generation in JavaScript. [21:55.400 --> 21:58.400] So the question is, can you do also this code generation in JavaScript? [21:58.400 --> 21:59.400] Yes, of course you can. [21:59.400 --> 22:00.400] Potentially. [22:00.400 --> 22:01.400] Potentially you can. [22:01.400 --> 22:06.400] So typically what you will see is the handy part, because I'm working in WebAssembly, is [22:06.400 --> 22:10.400] that I have all the WebAssembly low levels at my disposal. [22:10.400 --> 22:14.400] The hard part, if you go to the other languages, is that you're going to be... [22:14.400 --> 22:17.400] You need to have something to manipulate these... [22:17.400 --> 22:20.400] For example, this function table is very critical. [22:20.400 --> 22:23.400] So you need to be able to talk to that and hook into that. [22:23.400 --> 22:26.400] That's going to be the tricky part, but it's definitely possible. [22:26.400 --> 22:30.400] But it's easier if you do it directly in WebAssembly. [22:30.400 --> 22:36.400] Of course, you would never write a complex language directly in WebAssembly. [22:36.400 --> 22:37.400] That's madness. [22:37.400 --> 22:41.400] So you can do it with force, but I would not recommend it with anything. [22:41.400 --> 22:43.400] Thank you. [22:43.400 --> 22:45.400] One more question. [22:45.400 --> 22:51.400] Yes, I'm interested because you also used WebAssembly to see compiler. [22:51.400 --> 22:53.400] Yes, I used it. [22:53.400 --> 23:02.400] You had poor performance compared to C. Have you checked the regions? [23:02.400 --> 23:03.400] I didn't know. [23:03.400 --> 23:05.400] I used the WebAssembly to see compiler. [23:05.400 --> 23:08.400] The performance was quite on par with... [23:08.400 --> 23:12.400] So if I took the C algorithm, it was about... [23:12.400 --> 23:17.400] It's a bad benchmark, but the performance was about 10% slower. [23:17.400 --> 23:22.400] So it was not much slower than native binary. [23:22.400 --> 23:27.400] So it's C-compiled to native and C-compiled to WebAssembly was only a little bit slower. [23:27.400 --> 23:30.400] Of course, you are running... [23:30.400 --> 23:36.400] Okay, but you are running in WebAssembly, you are still running in virtual machine, right? [23:36.400 --> 23:40.400] So the fact that the performance is going to be maybe a little bit slower, [23:40.400 --> 23:45.400] but I thought it was still okay, given that you're still in a VM. [23:45.400 --> 24:01.400] We need to solve. That's amazing.