Transcript

[[!template new="1" text="""Rune""" start="00:00:00.000" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Hello, EmacsConf. My name is Troy Hinckley, and this is my""" start="00:00:00.000" video="mainVideo-rust" id="subtitle"]] [[!template text="""talk on Rune, a Rust implementation in Emacs. We strive to be""" start="00:00:05.120" video="mainVideo-rust" id="subtitle"]] [[!template text="""bug compatible with Emacs, so you can use the same Elisp.""" start="00:00:08.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""It's still a fairly early stage experimental project, and""" start="00:00:11.840" video="mainVideo-rust" id="subtitle"]] [[!template text="""we have some basic things implemented.""" start="00:00:14.880" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""The Emacs core""" start="00:00:17.082" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Before I get started, I want to talk a bit more""" start="00:00:17.082" video="mainVideo-rust" id="subtitle"]] [[!template text="""about what the core is.""" start="00:00:19.947" video="mainVideo-rust" id="subtitle"]] [[!template text="""So the Emacs core, it includes the runtime, the interpreter,""" start="00:00:21.848" video="mainVideo-rust" id="subtitle"]] [[!template text="""garbage collector, everything used to run the code.""" start="00:00:24.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""It includes the GUI. It includes all the data structures.""" start="00:00:26.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""If you look underneath all the Elisp data structures,""" start="00:00:29.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""there's C code underneath there,""" start="00:00:31.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""as well as the auxiliary functions""" start="00:00:33.600" video="mainVideo-rust" id="subtitle"]] [[!template text="""of which there's about 1500. In making this talk, I don't""" start="00:00:35.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""want to give the impression that I'm saying the core is""" start="00:00:39.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""outdated or that needs to be replaced or that it can't be""" start="00:00:40.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""evolved on its own, because clearly it has continued to""" start="00:00:42.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""evolve. If we look in just the last few years, we can see that""" start="00:00:45.520" video="mainVideo-rust" id="subtitle"]] [[!template text="""we've added native compilation, we've added tree-sitter""" start="00:00:48.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""support, we've added color emoji, and there's work right""" start="00:00:50.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""now to add a new garbage collector to Emacs as well.""" start="00:00:52.760" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Why create this?""" start="00:00:57.168" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Why create this project? Emacs has a long history.""" start="00:00:57.168" video="mainVideo-rust" id="subtitle"]] [[!template text="""It has a lot of users. It needs to support a big community.""" start="00:01:01.072" video="mainVideo-rust" id="subtitle"]] [[!template text="""Because of that, it has to be very conservative""" start="00:01:04.536" video="mainVideo-rust" id="subtitle"]] [[!template text="""about what things it can allow into the project.""" start="00:01:06.838" video="mainVideo-rust" id="subtitle"]] [[!template text="""Forks like this create an""" start="00:01:10.322" video="mainVideo-rust" id="subtitle"]] [[!template text="""opportunity to experiment and try new approaches.""" start="00:01:11.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""This is particularly a good use case for Rust because the C core,""" start="00:01:15.587" video="mainVideo-rust" id="subtitle"]] [[!template text="""it's pretty well tested. It's been around for a long time.""" start="00:01:18.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""A lot of the bugs have been ironed out, but when you're doing a""" start="00:01:20.850" video="mainVideo-rust" id="subtitle"]] [[!template text="""new greenfield project, it's very easy to introduce new""" start="00:01:22.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""undefined behavior and memory unsafety""" start="00:01:26.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""and stuff like that. Rust protects us from most of that,""" start="00:01:28.775" video="mainVideo-rust" id="subtitle"]] [[!template text="""but it also gives us the ability to be fast""" start="00:01:32.377" video="mainVideo-rust" id="subtitle"]] [[!template text="""and has a strong ecosystem behind it.""" start="00:01:34.938" video="mainVideo-rust" id="subtitle"]] [[!template text="""Rust is also really good at multi-threading.""" start="00:01:37.884" video="mainVideo-rust" id="subtitle"]] [[!template text="""Their phrase in the community is fearless concurrency.""" start="00:01:40.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""They should be able to write concurrent programs without""" start="00:01:43.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""having to worry about data races. It's also really high""" start="00:01:45.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""performance. It has a really good regex engine. It's known""" start="00:01:49.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""for its non-copy I/O as well.""" start="00:01:51.840" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""How does this compare to other projects?""" start="00:01:55.865" video="mainVideo-rust" id="subtitle"]]
[[!template text="""How does this compare to other""" start="00:01:55.865" video="mainVideo-rust" id="subtitle"]] [[!template text="""Rust and Emacs projects, whether there's been a couple? The""" start="00:01:57.480" video="mainVideo-rust" id="subtitle"]] [[!template text="""first is Remacs. This project was the first. It took an""" start="00:01:59.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""outside-in approach. Basically you could take a C""" start="00:02:02.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""function and replace it with a Rust function and build it""" start="00:02:05.520" video="mainVideo-rust" id="subtitle"]] [[!template text="""together as one executable. This is pretty easy to do""" start="00:02:09.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""because they could both talk over the C ABI. You could""" start="00:02:11.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""swap out functions once at a time. They made really good""" start="00:02:14.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""progress at first, but eventually they ran into the problem""" start="00:02:16.480" video="mainVideo-rust" id="subtitle"]] [[!template text="""that as you get down to the really core parts of it, you can't""" start="00:02:20.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""just replace one function at a time anymore, because some of""" start="00:02:23.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""that functionality is connected to other things. Like for""" start="00:02:25.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""example, you can't replace the garbage collector without""" start="00:02:28.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""replacing the entire garbage collection system. So the""" start="00:02:30.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""progress really kind of slowed down. Another issue with it""" start="00:02:32.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""was, is that they were doing a one-to-one rewrite, so they""" start="00:02:36.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""weren't adding any new features or functionality, just""" start="00:02:38.840" video="mainVideo-rust" id="subtitle"]] [[!template text="""taking the same code and replacing it in Rust, which doesn't""" start="00:02:41.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""add any advantages in and of itself.""" start="00:02:43.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""This spawned Emacs-NG, which was kind of the spiritual successor to""" start="00:02:46.802" video="mainVideo-rust" id="subtitle"]] [[!template text="""Remacs, where they decided to add new functionality,""" start="00:02:50.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""the biggest one being a JavaScript runtime,""" start="00:02:52.747" video="mainVideo-rust" id="subtitle"]] [[!template text="""as well as some new renderers to Emacs.""" start="00:02:55.809" video="mainVideo-rust" id="subtitle"]] [[!template text="""This is no longer actively developed though.""" start="00:02:58.231" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Multi-threading""" start="00:03:01.315" video="mainVideo-rust" id="subtitle"]]
[[!template text="""In this project, one of the big focuses we have is""" start="00:03:01.315" video="mainVideo-rust" id="subtitle"]] [[!template text="""on multi-threading. The C core itself is, everything is""" start="00:03:04.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""designed around being single-threaded, all the data""" start="00:03:07.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""structures and everything like that. Rust has a great""" start="00:03:09.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""concurrency story. In Rust, everything is intended to be""" start="00:03:13.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""multi-threaded. That doesn't mean that everything has to""" start="00:03:15.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""run on multiple threads, but you can't write something that""" start="00:03:18.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""is limited to only running in a single-threaded""" start="00:03:20.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""environment. So this makes it really easy to use all the""" start="00:03:22.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""existing packages and build something that is""" start="00:03:25.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""concurrency safe. which is what we've done here,""" start="00:03:28.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""and that was relatively easy to do.""" start="00:03:30.481" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Multi-threading elisp""" start="00:03:32.441" video="mainVideo-rust" id="subtitle"]]
[[!template text="""But adding it to Elisp is the hard part,""" start="00:03:32.441" video="mainVideo-rust" id="subtitle"]] [[!template text="""because we've got to come up with a good model""" start="00:03:34.782" video="mainVideo-rust" id="subtitle"]] [[!template text="""for Lisp, and Elisp is just a giant ball""" start="00:03:36.503" video="mainVideo-rust" id="subtitle"]] [[!template text="""of mutable state. We need to find some""" start="00:03:39.625" video="mainVideo-rust" id="subtitle"]] [[!template text="""way to tame that so we can make workable concurrency""" start="00:03:41.480" video="mainVideo-rust" id="subtitle"]] [[!template text="""out of it. There's really two ways you can do this.""" start="00:03:44.567" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""No-GIL method""" start="00:03:47.648" video="mainVideo-rust" id="subtitle"]]
[[!template text="""One is what I call the no-GIL method.""" start="00:03:47.648" video="mainVideo-rust" id="subtitle"]] [[!template text="""This is what Python is doing, where""" start="00:03:49.269" video="mainVideo-rust" id="subtitle"]] [[!template text="""you take all of your data structures, you make them""" start="00:03:51.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""concurrency safe, and then you just leave it up to the""" start="00:03:53.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""programmer to decide what they're going to do with it.""" start="00:03:56.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""They've got to build safe abstractions on top of that.""" start="00:03:58.120" video="mainVideo-rust" id="subtitle"]] [[!template text="""One of the big downsides with this is that""" start="00:04:00.468" video="mainVideo-rust" id="subtitle"]] [[!template text="""it comes with a pretty high cost.""" start="00:04:03.087" video="mainVideo-rust" id="subtitle"]] [[!template text="""The last benchmarks I've seen is that by making""" start="00:04:05.248" video="mainVideo-rust" id="subtitle"]] [[!template text="""everything concurrency safe in Python, single-threaded""" start="00:04:07.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""code is about 20% slower in some benchmarks.""" start="00:04:10.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""Since most code is single-threaded, this has a big""" start="00:04:15.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""performance impact for most code that isn't taking""" start="00:04:19.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""advantage of the multi-threading. The other thing is this""" start="00:04:21.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""introduces a lot of nasty concurrency bugs because you can""" start="00:04:23.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""have anything mutating any part of the data from any thread,""" start="00:04:26.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""even if you can't have memory unsafety per se.""" start="00:04:29.040" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Actors""" start="00:04:32.638" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other option is actors,""" start="00:04:32.638" video="mainVideo-rust" id="subtitle"]] [[!template text="""which are a really known way to approach this,""" start="00:04:34.739" video="mainVideo-rust" id="subtitle"]] [[!template text="""where you trade some of that flexibility that you get""" start="00:04:36.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""with fully concurrent for more control and. Code and""" start="00:04:39.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""functions are shared between all the different threads,""" start="00:04:43.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""but data has to be passed along channels between different""" start="00:04:45.840" video="mainVideo-rust" id="subtitle"]] [[!template text="""actors.""" start="00:04:50.600" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Multi-threading elisp (functions)""" start="00:04:51.252" video="mainVideo-rust" id="subtitle"]]
[[!template text="""We want the functions to be shared, and this""" start="00:04:51.252" video="mainVideo-rust" id="subtitle"]] [[!template text="""should be pretty easy because we don't mutate functions""" start="00:04:52.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""like we do data, except when we do. In Lisp, functions are""" start="00:04:55.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""just lists like anything else. So you can mutate them""" start="00:05:00.120" video="mainVideo-rust" id="subtitle"]] [[!template text="""just like lists. Even if you're not talking about""" start="00:05:03.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""interpreted code, like if you have a native compiled""" start="00:05:06.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""function, you can still mutate the constants inside the""" start="00:05:09.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""function. For example, here we have a function returns a""" start="00:05:11.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""string. We take that string out, we mutate that string, and""" start="00:05:14.840" video="mainVideo-rust" id="subtitle"]] [[!template text="""now the function returns a different string. In Rune, we""" start="00:05:17.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""enforce that all functions, their constants are""" start="00:05:23.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""immutable. You can't mutate the insides of a function. You""" start="00:05:25.000" video="mainVideo-rust" id="subtitle"]] [[!template text="""can still swap out functions and redefine them, but you""" start="00:05:27.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""can't mutate the inside of a function. This enables them""" start="00:05:29.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""to be safely shared across threads.""" start="00:05:32.240" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Caveats""" start="00:05:34.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""However, there are some caveats to this.""" start="00:05:34.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""For example, some functions actually do""" start="00:05:36.401" video="mainVideo-rust" id="subtitle"]] [[!template text="""need to mutate their own data. The example that we run into is""" start="00:05:38.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""cl-generic. It uses a method cache. So it has to be able to""" start="00:05:41.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""update that cache. In this case, we just made a special""" start="00:05:44.840" video="mainVideo-rust" id="subtitle"]] [[!template text="""case for this particular situation, but we don't know what""" start="00:05:47.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""more of these we're gonna run into the future where this is""" start="00:05:50.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""needed behavior to be able to mutate a function.""" start="00:05:53.160" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Multi-threading elisp (data)""" start="00:05:57.090" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Okay, so functions are pretty easy.""" start="00:05:57.090" video="mainVideo-rust" id="subtitle"]] [[!template text="""They just can be shared between""" start="00:05:59.811" video="mainVideo-rust" id="subtitle"]] [[!template text="""threads, but data can't be immutable, at least not into the""" start="00:06:00.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""model that Emacs currently has. We have two different""" start="00:06:05.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""ways to handle this. One is we require whenever you're""" start="00:06:08.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""calling some other code in a different thread, you have to""" start="00:06:12.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""send all the variables that it's going to need over to that""" start="00:06:14.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""thread. This is how you traditionally do inside actors.""" start="00:06:17.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""Any data that needs to go to a different actor needs to be sent""" start="00:06:19.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""over a channel. It's relatively easy implementation, but""" start="00:06:21.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""this is difficult in the Emacs case because everything is""" start="00:06:25.520" video="mainVideo-rust" id="subtitle"]] [[!template text="""going to be accessing different variables. That means""" start="00:06:28.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""when you call something, you have to know ahead of time, all""" start="00:06:30.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""the different variables that are gonna be accessed inside""" start="00:06:33.120" video="mainVideo-rust" id="subtitle"]] [[!template text="""that other thread and put those in when you call it.""" start="00:06:34.880" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Copy values to other threads on demands""" start="00:06:38.249" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other option we're using is we're copying values to the""" start="00:06:38.249" video="mainVideo-rust" id="subtitle"]] [[!template text="""other threads on demand. If you're running a thread, it""" start="00:06:40.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""tries to look up a variable. It doesn't have any value for""" start="00:06:43.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""that variable. It will go back and ask the main thread and it""" start="00:06:45.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""will copy that value into that thread and it can continue""" start="00:06:48.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""execution. This is nice because you can just launch some""" start="00:06:50.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""code and it'll take care of handling all the data transfer""" start="00:06:53.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""for you.""" start="00:06:55.640" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Multi-threading elisp (buffers)""" start="00:06:57.884" video="mainVideo-rust" id="subtitle"]]
[[!template text="""But we don't want to be copying around is buffers,""" start="00:06:57.884" video="mainVideo-rust" id="subtitle"]] [[!template text="""because they can be really large. In this case, we have a""" start="00:07:00.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""mutex. Each thread could only have one current buffer that""" start="00:07:04.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""it has an exclusive lock to. This comes with some""" start="00:07:07.600" video="mainVideo-rust" id="subtitle"]] [[!template text="""trade-offs, big one being that if the user tries to access""" start="00:07:12.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""some buffer, they want to type something, and a background""" start="00:07:16.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""thread is holding onto that buffer, what do we do in that""" start="00:07:18.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""situation? And we still need to hold an exclusive lock, even""" start="00:07:20.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""if we're only going to read a buffer. If you have multiple""" start="00:07:24.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""readers, they each still need to take turns because we can't""" start="00:07:26.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""determine if at some point a thread is going to try and mutate""" start="00:07:29.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""the buffer. It has to be an exclusive lock. The other issue""" start="00:07:31.000" video="mainVideo-rust" id="subtitle"]] [[!template text="""is buffer-locals. This is less of a implementation issue""" start="00:07:33.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""as much as it is a technical issue. Because you think about""" start="00:07:37.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""when we switch to a buffer, it has some buffer-local data and""" start="00:07:40.520" video="mainVideo-rust" id="subtitle"]] [[!template text="""we have some thread-local data. As we go through, we're""" start="00:07:42.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""mutating everything. Those can get intertwined and""" start="00:07:45.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""pointing to each other. Then we switch away from that""" start="00:07:47.600" video="mainVideo-rust" id="subtitle"]] [[!template text="""buffer. We need some quick way to be able to separate those""" start="00:07:49.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""out. The buffer-locals can go with the buffer-locals and""" start="00:07:51.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""the thread data can stay with thread data and make copies of""" start="00:07:54.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""anything that was pointing to the other side. But we don't""" start="00:07:56.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""have a good method to determine how to separate those two,""" start="00:07:58.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""like what data belongs to this and what data belongs to this,""" start="00:08:02.840" video="mainVideo-rust" id="subtitle"]] [[!template text="""so that we can do that quickly. We haven't found a good""" start="00:08:05.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""solution to that yet, but it's something we're still""" start="00:08:08.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""working on.""" start="00:08:09.600" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Would this actually be useful?""" start="00:08:11.903" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The question is, would this actually be""" start="00:08:11.903" video="mainVideo-rust" id="subtitle"]] [[!template text="""useful for doing real work inside Emacs? I would say,""" start="00:08:13.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""yes, there's a lot of things you can do with this. You could""" start="00:08:15.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""handle process output in the background. You can do syntax""" start="00:08:17.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""highlighting. You can do buffer search in parallel. You can""" start="00:08:20.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""do LSP. You can do fetching your mail in the background. You""" start="00:08:23.480" video="mainVideo-rust" id="subtitle"]] [[!template text="""can have a window manager that doesn't block your window""" start="00:08:26.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""manager when Emacs is blocked. You could do""" start="00:08:29.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""something like a file system watcher that keeps up on files""" start="00:08:32.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""without blocking Emacs. This wouldn't be so great for""" start="00:08:34.480" video="mainVideo-rust" id="subtitle"]] [[!template text="""building concurrent data structures or operating on""" start="00:08:37.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""shared data or building your own abstractions, because of the""" start="00:08:39.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""trade-offs that we've made here. Okay. That's talking""" start="00:08:42.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""about multi-threading.""" start="00:08:46.040" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Precise garbage collection""" start="00:08:46.919" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other thing we're going to talk""" start="00:08:46.919" video="mainVideo-rust" id="subtitle"]] [[!template text="""about is precise garbage collection. In Rune, we have a""" start="00:08:47.600" video="mainVideo-rust" id="subtitle"]] [[!template text="""safe, precise garbage collection because of the Rust type""" start="00:08:51.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""system. Let's look at what the problem is with garbage""" start="00:08:54.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""collection in the first place. Really, the tricky part""" start="00:08:58.120" video="mainVideo-rust" id="subtitle"]] [[!template text="""about garbage collection is rooting. How do we find out what""" start="00:09:00.480" video="mainVideo-rust" id="subtitle"]] [[!template text="""the roots are? These are all the values that are on the""" start="00:09:03.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""stack or inside the registers. In this example here, we""" start="00:09:06.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""allocate an object. We call garbage_collect, that object's""" start="00:09:08.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""collected, and then we try and return it.""" start="00:09:11.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""It's no longer valid.""" start="00:09:13.537" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""How Emacs used to deal with roots""" start="00:09:16.537" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Let's look at how Emacs used to deal with this""" start="00:09:16.537" video="mainVideo-rust" id="subtitle"]] [[!template text="""problem way back in the day. There was a system called gcpro""" start="00:09:19.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""or GC Protect, which is basically designed that every time a""" start="00:09:22.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""value needed to survive past a garbage collection point,""" start="00:09:26.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""you had to try and protect it. In order to do this, you had""" start="00:09:28.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""to declare a struct, you had to put a macro around it to root""" start="00:09:32.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""the object, and then you had to unroot it when you were done--""" start="00:09:35.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""past the garbage collection. Now the value is safe. You""" start="00:09:38.000" video="mainVideo-rust" id="subtitle"]] [[!template text="""can see down here, I pulled these eight rules out from a""" start="00:09:41.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""really old version of the Emacs manual about all the things""" start="00:09:44.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""you had to keep track of when you were trying to use this""" start="00:09:46.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""system. All right, so there was a special handling for""" start="00:09:49.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""nested GC protects. You had to make sure the memory was""" start="00:09:52.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""initialized. You had to make sure that traps couldn't occur""" start="00:09:54.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""between allocating and when GC protect would happen. It""" start="00:09:58.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""can be tricky because you don't always know when a function""" start="00:10:00.840" video="mainVideo-rust" id="subtitle"]] [[!template text="""that's getting called could potentially call garbage""" start="00:10:03.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""collection. So if you got something wrong, you also""" start="00:10:06.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""might not catch it for a long time because garbage""" start="00:10:10.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""collection may only get called one out of 99 times. The other""" start="00:10:12.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""99 times is just fine. That one time it happens and you""" start="00:10:15.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""can't reproduce the issue. When you do get this wrong and""" start="00:10:19.000" video="mainVideo-rust" id="subtitle"]] [[!template text="""some, something doesn't get rooted and it gets""" start="00:10:22.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""overwritten, it generally doesn't show up right where the""" start="00:10:24.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""problem is. It gets showed up way later when you actually try""" start="00:10:26.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""and access the value and the value is invalid. You've got""" start="00:10:28.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""to track it back to where that thing did not get properly""" start="00:10:31.480" video="mainVideo-rust" id="subtitle"]] [[!template text="""rooted. It's a huge source of bugs and very hard to""" start="00:10:33.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""maintain.""" start="00:10:37.360" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Conservative stack scanning""" start="00:10:38.713" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Emacs decided to go with a different path,""" start="00:10:38.713" video="mainVideo-rust" id="subtitle"]] [[!template text="""which we call conservative stack scanning. Basically,""" start="00:10:40.120" video="mainVideo-rust" id="subtitle"]] [[!template text="""the garbage collector just looks at the stack and all the""" start="00:10:42.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""registers and any data inside there that looks like it could""" start="00:10:45.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""be a pointer, it treats it as a pointer. This is nice because""" start="00:10:47.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""you get really easy root tracking,""" start="00:10:52.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""but it also comes with some trade-offs,""" start="00:10:54.712" video="mainVideo-rust" id="subtitle"]] [[!template text="""mostly that your objects are no longer movable.""" start="00:10:56.114" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Movable objects""" start="00:11:00.157" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Why would we want movable objects in Emacs?""" start="00:11:00.157" video="mainVideo-rust" id="subtitle"]] [[!template text="""There's a couple of different reasons. One is compaction.""" start="00:11:03.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""You can take all your heap, you can pack that on down because""" start="00:11:05.840" video="mainVideo-rust" id="subtitle"]] [[!template text="""you can coalesce all your objects together. Another is that""" start="00:11:08.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""it's easy to implement generational garbage collection.""" start="00:11:11.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""You can just copy everything out of your minor heap into your""" start="00:11:13.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""older heap. Really, Emacs is kind of uniquely ideal for""" start="00:11:16.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""generational collection, because the typical way we""" start="00:11:21.840" video="mainVideo-rust" id="subtitle"]] [[!template text="""interact with Emacs is as a series of commands. You execute""" start="00:11:24.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""some command, you'd execute the next command, you execute""" start="00:11:27.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""a command. It could be happening every key press, it could be""" start="00:11:29.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""happening with M-x. However long that command is, that is""" start="00:11:33.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""the ideal length for the minor collection generation, the""" start="00:11:36.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""first generation. Because once you're done with that""" start="00:11:40.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""generation, anything that's still existing is going to be""" start="00:11:43.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""around for a very long time. So that works out really well""" start="00:11:45.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""for Emacs. We want to make this a generational collector.""" start="00:11:49.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""The other thing is with object layout. We use a lot of lists""" start="00:11:52.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""inside Emacs Lisp. Every time you go to the cdr, you've""" start="00:11:56.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""got to be chasing a pointer around the heap and following""" start="00:12:00.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""that. That can potentially result in cache misses and""" start="00:12:03.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""all sorts of other things like that. So it can take a long""" start="00:12:05.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""time. It can be quite slow. But if you have the ability to move""" start="00:12:08.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""objects, you can just relocate an entire list and lay it out""" start="00:12:12.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""in an array right next to each other inside memory.""" start="00:12:16.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""So iterating over it is just as fast as iterating over an array.""" start="00:12:19.169" video="mainVideo-rust" id="subtitle"]] [[!template text="""But you can only do that if you have movable objects.""" start="00:12:22.480" video="mainVideo-rust" id="subtitle"]] [[!template text="""I'll point out here too, that with conservative stack scanning,""" start="00:12:25.422" video="mainVideo-rust" id="subtitle"]] [[!template text="""it's not that all objects are immovable. It's only ones that""" start="00:12:28.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""are pointed to from the stack or from the registers that have""" start="00:12:31.600" video="mainVideo-rust" id="subtitle"]] [[!template text="""to become immovable.""" start="00:12:35.520" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""How Rust makes precise GC easy""" start="00:12:38.829" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Let's look at how Rust makes precise""" start="00:12:38.829" video="mainVideo-rust" id="subtitle"]] [[!template text="""garbage collection easy. Here I have some Rust code to""" start="00:12:41.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""show kind of how the lifetime system works and what we call""" start="00:12:44.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""XOR mutability, where we can only have one mutable""" start="00:12:47.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""reference or multiple immutable references to the same""" start="00:12:49.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""thing. Here we declare a vector, we take a reference to the""" start="00:12:52.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""first element of the vector, and then we mutate the vector.""" start="00:12:56.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""Now this could potentially resize the vector and move it to a""" start="00:12:59.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""different location in memory, so that reference is no""" start="00:13:02.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""longer valid. The nice thing is, Rust catches this for""" start="00:13:04.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""us. It says, hey, this is no longer valid. This reference""" start="00:13:07.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""can't survive past when you mutated it. Okay? That's""" start="00:13:10.480" video="mainVideo-rust" id="subtitle"]] [[!template text="""exactly what we want for a garbage collector. You can see""" start="00:13:14.520" video="mainVideo-rust" id="subtitle"]] [[!template text="""here, we take this in a garbage collection context, we""" start="00:13:17.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""create a new context object, we add an object, we call""" start="00:13:19.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""garbage_collect, then we try and access that object. It's no""" start="00:13:23.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""longer accessible, and Rust will prevent us from trying to""" start="00:13:26.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""access that variable. So, how do we solve this? We have a""" start="00:13:29.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""root macro. We declared this root macro, it lets us take the""" start="00:13:34.840" video="mainVideo-rust" id="subtitle"]] [[!template text="""object and let it live past garbage collection, and""" start="00:13:39.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""everything works out. The nice thing is, this root macro""" start="00:13:41.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""will get dropped when it's out of scope, so we don't have to""" start="00:13:45.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""worry about the un-gc-protect step of this. Statically,""" start="00:13:47.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""Rust will verify and tell us any object that needs to be""" start="00:13:51.520" video="mainVideo-rust" id="subtitle"]] [[!template text="""rooted. If we try and access it, it'll tell us it's invalid.""" start="00:13:55.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""We have this root macro and then we can access it. So in""" start="00:13:58.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""that way, we have safe, precise garbage collection without""" start="00:14:01.000" video="mainVideo-rust" id="subtitle"]] [[!template text="""any chance of introducing undefined behavior, which is""" start="00:14:03.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""really, really powerful. It's really easy because the""" start="00:14:07.480" video="mainVideo-rust" id="subtitle"]] [[!template text="""type system will catch it all for us.""" start="00:14:10.000" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Other Rust niceties: proc macro""" start="00:14:13.227" video="mainVideo-rust" id="subtitle"]]
[[!template text="""There's some other Rust niceties I want to kind of""" start="00:14:13.227" video="mainVideo-rust" id="subtitle"]] [[!template text="""talk through that are useful, but""" start="00:14:15.148" video="mainVideo-rust" id="subtitle"]] [[!template text="""are not, you know, star features. One is proc macros. You""" start="00:14:16.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""can see up on the top, you can see how you declare a function""" start="00:14:21.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""inside the C core. All right. You have to use the macro. You""" start="00:14:23.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""have to put the list type, the function type,""" start="00:14:27.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""the struct type, the different types of arguments""" start="00:14:29.142" video="mainVideo-rust" id="subtitle"]] [[!template text="""or different number of arguments, the doc string,""" start="00:14:30.964" video="mainVideo-rust" id="subtitle"]] [[!template text="""and then you can put your argument listing down inside there.""" start="00:14:33.226" video="mainVideo-rust" id="subtitle"]] [[!template text="""On the Rust side, we just write this like we would""" start="00:14:36.024" video="mainVideo-rust" id="subtitle"]] [[!template text="""any other Rust function. And then we put""" start="00:14:37.985" video="mainVideo-rust" id="subtitle"]] [[!template text="""the defun proc macro on there""" start="00:14:40.045" video="mainVideo-rust" id="subtitle"]] [[!template text="""and it takes care of everything for us behind the scenes.""" start="00:14:41.286" video="mainVideo-rust" id="subtitle"]] [[!template text="""A couple of cool additional things we can do with this""" start="00:14:44.187" video="mainVideo-rust" id="subtitle"]] [[!template text="""is that we don't have to make everything just an object.""" start="00:14:46.408" video="mainVideo-rust" id="subtitle"]] [[!template text="""We can actually make things""" start="00:14:48.728" video="mainVideo-rust" id="subtitle"]] [[!template text="""more specific types. Here we have symbols. As well as""" start="00:14:49.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""you can see subfeature, it's an optional parameter, and we""" start="00:14:54.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""just make it an option inside Rust and it automatically make""" start="00:14:56.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""it an optional inside Elisp.""" start="00:15:00.920" video="mainVideo-rust" id="subtitle"]] [[!template text="""This makes them really easy to write.""" start="00:15:03.600" video="mainVideo-rust" id="subtitle"]] [[!template text="""I can't take credit for this is because this is""" start="00:15:05.182" video="mainVideo-rust" id="subtitle"]] [[!template text="""something that I saw inside Remacs and I stole from them, but""" start="00:15:06.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""it makes the functions really easy to call from each other""" start="00:15:09.120" video="mainVideo-rust" id="subtitle"]] [[!template text="""and really easy to write as well.""" start="00:15:11.440" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""sum types""" start="00:15:14.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Another thing that's really nice is sum types.""" start="00:15:14.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""In the C core, if I wanted to get a""" start="00:15:18.524" video="mainVideo-rust" id="subtitle"]] [[!template text="""string out of an object, I would first need to check that it's""" start="00:15:21.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""a string and then dereference it as a string. But if it's not a""" start="00:15:23.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""string, I may introduce undefined behavior. So in""" start="00:15:28.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""complicated code, I have to make sure that I have always""" start="00:15:30.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""checked what type it is before I try and dereference that""" start="00:15:32.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""type. We don't have to worry about any of that inside Rust""" start="00:15:34.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""because we can untag a value and we can use their some types,""" start="00:15:37.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""basically create an enum and we can match on what the""" start="00:15:41.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""different values can be. Then we only get out the types""" start="00:15:44.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""that are viable or are actually there. So we never""" start="00:15:47.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""accidentally get something out of an object that we didn't""" start="00:15:50.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""mean to, or dereference it as something that doesn't""" start="00:15:52.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""really exist. We can just match on it and we can get out the""" start="00:15:54.240" video="mainVideo-rust" id="subtitle"]] [[!template text="""values that we need, which is really, really powerful.""" start="00:15:56.880" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Regex""" start="00:16:01.041" video="mainVideo-rust" id="subtitle"]]
[[!template text="""So there's some other Rust niceties as well working with here.""" start="00:16:01.041" video="mainVideo-rust" id="subtitle"]] [[!template text="""One is the regex engine inside Rust is really fast, high""" start="00:16:03.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""performance. We are using that for the Elixir regex""" start="00:16:07.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""engine to give it high performance and worst-case""" start="00:16:10.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""guarantees.""" start="00:16:14.880" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Parsers""" start="00:16:16.052" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other is that Rust has a lot of really good""" start="00:16:16.052" video="mainVideo-rust" id="subtitle"]] [[!template text="""parsers for things like JSON that are no copy parsers that""" start="00:16:18.600" video="mainVideo-rust" id="subtitle"]] [[!template text="""are high performance. We can use those inside Rune as""" start="00:16:21.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""well.""" start="00:16:24.720" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Other changes: GUI first, terminal second""" start="00:16:27.210" video="mainVideo-rust" id="subtitle"]]
[[!template text="""There's a handful of other changes we're working on""" start="00:16:27.210" video="mainVideo-rust" id="subtitle"]] [[!template text="""that are not Rust-specific, but we'd like to see. The first is""" start="00:16:29.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""being GUI first, terminal second. This means two things.""" start="00:16:33.120" video="mainVideo-rust" id="subtitle"]] [[!template text="""First is that we have all of our key bindings. Right now""" start="00:16:36.760" video="mainVideo-rust" id="subtitle"]] [[!template text="""inside Emacs, C-i and TAB are bound to the same key""" start="00:16:40.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""binding by default, because that's how it works inside the""" start="00:16:43.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""terminal. In the GUI, you shouldn't have that limitation.""" start="00:16:45.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""The second is that the GUI should not block when Lisp is""" start="00:16:48.120" video="mainVideo-rust" id="subtitle"]] [[!template text="""blocked. It should be independent of that. Your GUI can""" start="00:16:52.560" video="mainVideo-rust" id="subtitle"]] [[!template text="""still continue to operate when Lisp is running.""" start="00:16:55.200" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Off-screen cursor""" start="00:16:58.919" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other is the ability to have an off-screen cursor""" start="00:16:58.919" video="mainVideo-rust" id="subtitle"]] [[!template text="""so that you can be typing on something,""" start="00:17:01.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""you can scroll up and down and the point""" start="00:17:02.700" video="mainVideo-rust" id="subtitle"]] [[!template text="""doesn't have to follow you where you lose your place where""" start="00:17:04.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""you were before. You don't have to intentionally set a mark.""" start="00:17:06.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""You can just scroll and then start typing and it'll go back up""" start="00:17:09.400" video="mainVideo-rust" id="subtitle"]] [[!template text="""to where it was before, like it works in most applications.""" start="00:17:11.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""And this can be optional.""" start="00:17:13.880" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Image flow""" start="00:17:16.305" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other is image flow. We want it""" start="00:17:16.305" video="mainVideo-rust" id="subtitle"]] [[!template text="""so that you can easily flow images and you can have large""" start="00:17:18.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""images and scroll past them without jumping and you can flow""" start="00:17:20.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""text around images.""" start="00:17:23.160" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Testing""" start="00:17:24.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""How are we testing this project? Because there's a lot of""" start="00:17:24.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""things that you could get wrong here. One thing we're doing""" start="00:17:29.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""is we're using ERT. Emacs ships with over 7,000 built-in""" start="00:17:33.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""tests--Elisp tests. We are using this test suite to test""" start="00:17:38.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""our project as well. We can kind of use this as a dashboard""" start="00:17:42.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""of saying how close are we to getting to parity with GNU""" start="00:17:45.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""Emacs. The other thing that we have is a tool called elprop,""" start="00:17:47.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""which is an external utility that basically tests for""" start="00:17:52.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""correctness. Because really, the correctness of Rune is""" start="00:17:55.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""whatever Emacs does, because there's no official spec on""" start="00:17:58.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""how things should behave. To do this, we can go look at""" start="00:18:01.000" video="mainVideo-rust" id="subtitle"]] [[!template text="""the Rust function signature. We know what the arguments""" start="00:18:04.080" video="mainVideo-rust" id="subtitle"]] [[!template text="""are, we know how many they are, and we know what types they""" start="00:18:07.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""should be. Given that information, we can generate a""" start="00:18:09.320" video="mainVideo-rust" id="subtitle"]] [[!template text="""whole bunch of random functions feeding those types in. And""" start="00:18:11.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""then we send a copy over to Emacs, we send a copy over to Rune.""" start="00:18:15.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""They each evaluate it and they return the result and we make""" start="00:18:18.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""sure the results are the same. Then you do that for""" start="00:18:21.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""thousands of different implementations of the function.""" start="00:18:23.520" video="mainVideo-rust" id="subtitle"]] [[!template text="""And it helps us find corner cases really easy without having""" start="00:18:26.200" video="mainVideo-rust" id="subtitle"]] [[!template text="""to handwrite a whole bunch of different cases to test things""" start="00:18:29.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""and say, where are these two functions different?""" start="00:18:31.640" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Status""" start="00:18:36.345" video="mainVideo-rust" id="subtitle"]]
[[!template text="""So the current status: we already have a multi-threaded Elixir""" start="00:18:36.345" video="mainVideo-rust" id="subtitle"]] [[!template text="""interpreter and bytecode engine inside there. There's no""" start="00:18:39.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""actual text editor in there yet, but the primitives are""" start="00:18:43.000" video="mainVideo-rust" id="subtitle"]] [[!template text="""there. Like you can insert text, move point around,""" start="00:18:45.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""delete text, do different things like that. But we don't""" start="00:18:48.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""have a GUI hooked up to different key bindings to actually""" start="00:18:52.040" video="mainVideo-rust" id="subtitle"]] [[!template text="""type on. There's just a REPL to operate in. We have about""" start="00:18:53.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""250 of the 1500 built-in functions already implemented""" start="00:18:58.160" video="mainVideo-rust" id="subtitle"]] [[!template text="""inside there. There's a lot of low-hanging fruit inside this""" start="00:19:01.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""area to still be implemented.""" start="00:19:04.120" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Next directions""" start="00:19:07.247" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The next directions we're""" start="00:19:07.247" video="mainVideo-rust" id="subtitle"]] [[!template text="""working on is we're optimizing the GC. We want to make it""" start="00:19:07.720" video="mainVideo-rust" id="subtitle"]] [[!template text="""generational. Like I said, right now, it's just a simple""" start="00:19:11.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""semi-spaced copying GC. We want to add a proper GUI. We need""" start="00:19:13.840" video="mainVideo-rust" id="subtitle"]] [[!template text="""to implement text properties, overlays, process and job""" start="00:19:17.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""control, all that goodness right there.""" start="00:19:19.600" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""How to get involved""" start="00:19:22.739" video="mainVideo-rust" id="subtitle"]]
[[!template text="""How can you get involved? This is hosted on GitHub.""" start="00:19:22.739" video="mainVideo-rust" id="subtitle"]] [[!template text="""You can come on over.""" start="00:19:25.379" video="mainVideo-rust" id="subtitle"]] [[!template text="""If you have any ideas about how to implement something or""" start="00:19:26.425" video="mainVideo-rust" id="subtitle"]] [[!template text="""something you'd like to see done, go ahead and just open an""" start="00:19:28.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""issue so we can have a discussion about it. We've had lots of""" start="00:19:30.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""interesting discussions with different people coming in""" start="00:19:32.800" video="mainVideo-rust" id="subtitle"]] [[!template text="""to the GitHub repo. If you're interested in contributing,""" start="00:19:34.600" video="mainVideo-rust" id="subtitle"]] [[!template text="""the easiest way is probably to run elprop, pick some""" start="00:19:37.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""function, run elprop on it. I promise it won't take long to""" start="00:19:40.440" video="mainVideo-rust" id="subtitle"]] [[!template text="""find some issues, some discrepancy between Emacs and Rune,""" start="00:19:43.280" video="mainVideo-rust" id="subtitle"]] [[!template text="""and that lets you dive into the Rust code and figure out, and""" start="00:19:45.640" video="mainVideo-rust" id="subtitle"]] [[!template text="""the C code, and figure out what the difference is between the""" start="00:19:48.960" video="mainVideo-rust" id="subtitle"]] [[!template text="""two. or come along and help implement your favorite""" start="00:19:50.880" video="mainVideo-rust" id="subtitle"]] [[!template text="""functionality. This has been a really interesting project""" start="00:19:53.120" video="mainVideo-rust" id="subtitle"]] [[!template text="""so far, and we've had a handful of different contributors on""" start="00:19:55.680" video="mainVideo-rust" id="subtitle"]] [[!template text="""it who just kind of want to learn Rust or get more into""" start="00:19:58.360" video="mainVideo-rust" id="subtitle"]] [[!template text="""systems-level programming. Thank you.""" start="00:20:01.800" video="mainVideo-rust" id="subtitle"]]
Captioner: sachac

Q&A transcript (unedited)

[[!template text="""Okay, so I'm going to look at some of the questions showing up""" start="00:00:00.000" video="qanda-rust" id="subtitle"]] [[!template text="""in the etherpad we got here.""" start="00:00:06.520" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Q: Have you considered using CRDTs to share buffers between threads and merge any concurrent edits automatically?""" start="00:00:08.500" video="qanda-rust" id="subtitle"]]
[[!template text="""It says, have you considered""" start="00:00:08.500" video="qanda-rust" id="subtitle"]] [[!template text="""using a CRDT to share buffers between threads and merge any""" start="00:00:09.440" video="qanda-rust" id="subtitle"]] [[!template text="""concurrent edits automatically? So I have looked at that.""" start="00:00:12.800" video="qanda-rust" id="subtitle"]] [[!template text="""And the problem with CRDTs is that even though they give you a""" start="00:00:16.040" video="qanda-rust" id="subtitle"]] [[!template text="""mathematically correct answer when you're trying to merge""" start="00:00:20.560" video="qanda-rust" id="subtitle"]] [[!template text="""two conflicts, it's not always a useful answer. Like, it's""" start="00:00:22.840" video="qanda-rust" id="subtitle"]] [[!template text="""not coherent. If you have two things trying to edit the same""" start="00:00:26.480" video="qanda-rust" id="subtitle"]] [[!template text="""thing, there's no good way to resolve that. And so they""" start="00:00:29.200" video="qanda-rust" id="subtitle"]] [[!template text="""really work well when you have two people working live, both""" start="00:00:31.360" video="qanda-rust" id="subtitle"]] [[!template text="""editing the same document, because they can fix any""" start="00:00:33.560" video="qanda-rust" id="subtitle"]] [[!template text="""particular issues like that, like you would with Google""" start="00:00:35.640" video="qanda-rust" id="subtitle"]] [[!template text="""Docs. But you have different packages that aren't aware of""" start="00:00:37.200" video="qanda-rust" id="subtitle"]] [[!template text="""each other, and you're going to run into problems. And so""" start="00:00:39.920" video="qanda-rust" id="subtitle"]] [[!template text="""this is something, if you read from the Xi editor, which was""" start="00:00:42.160" video="qanda-rust" id="subtitle"]] [[!template text="""one of the first ones to use CRDTs, in the retrospective, he""" start="00:00:45.000" video="qanda-rust" id="subtitle"]] [[!template text="""talks about how they had this problem, where the CRDTs They""" start="00:00:48.040" video="qanda-rust" id="subtitle"]] [[!template text="""give you an answer, but it's not always an answer that's""" start="00:00:52.360" video="qanda-rust" id="subtitle"]] [[!template text="""useful. And so I feel like locks at least are going to make it.""" start="00:00:54.000" video="qanda-rust" id="subtitle"]] [[!template text="""It's not going to be as efficient if you have a whole bunch of""" start="00:00:59.080" video="qanda-rust" id="subtitle"]] [[!template text="""packages, but I don't imagine there's going to be a ton of""" start="00:01:00.440" video="qanda-rust" id="subtitle"]] [[!template text="""those. It can actually, I think it'll be more useful in""" start="00:01:02.320" video="qanda-rust" id="subtitle"]] [[!template text="""practice.""" start="00:01:04.800" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Q: Why hosted on GitHub? GitHub is nonfree. Is it possible to report bugs/send patches without using GitHub?""" start="00:01:05.874" video="qanda-rust" id="subtitle"]]
[[!template text="""I host on GitHub because that's what I know.""" start="00:01:05.874" video="qanda-rust" id="subtitle"]] [[!template text="""If there's a way to host it on somewhere else, I'd be""" start="00:01:11.240" video="qanda-rust" id="subtitle"]] [[!template text="""interested in doing that. If you're interested in setting""" start="00:01:13.240" video="qanda-rust" id="subtitle"]] [[!template text="""patches without using GitHub, you could always send an""" start="00:01:15.440" video="qanda-rust" id="subtitle"]] [[!template text="""email. I'm more than happy to accept email patches.""" start="00:01:17.800" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Q: Do you think it's possible to achieve 100% compatibility with current Emacs code?""" start="00:01:22.960" video="qanda-rust" id="subtitle"]]
[[!template text="""Do you think it's possible to achieve with the current Emacs""" start="00:01:22.960" video="qanda-rust" id="subtitle"]] [[!template text="""code? I do. I think, I think you can do that. Um, like I said,""" start="00:01:24.960" video="qanda-rust" id="subtitle"]] [[!template text="""there's a couple things inside there that are intentional""" start="00:01:29.720" video="qanda-rust" id="subtitle"]] [[!template text="""breaks with existing Emacs code. And some of those being""" start="00:01:33.280" video="qanda-rust" id="subtitle"]] [[!template text="""like functions are immutable. As well as having data shared""" start="00:01:37.920" video="qanda-rust" id="subtitle"]] [[!template text="""switch between different threads, which means there's""" start="00:01:43.160" video="qanda-rust" id="subtitle"]] [[!template text="""going to be some copying going on. So there's going to be""" start="00:01:44.760" video="qanda-rust" id="subtitle"]] [[!template text="""subtle things that are going to be different. And we've""" start="00:01:46.600" video="qanda-rust" id="subtitle"]] [[!template text="""really got to think about those intentionally, but I'm""" start="00:01:48.400" video="qanda-rust" id="subtitle"]] [[!template text="""really going for bug compatibility with GNU Emacs so that""" start="00:01:50.360" video="qanda-rust" id="subtitle"]] [[!template text="""you can take an existing Elisp package and just run it and it""" start="00:01:54.520" video="qanda-rust" id="subtitle"]] [[!template text="""just works, 'cause I think that's one of the big strengths of""" start="00:01:57.160" video="qanda-rust" id="subtitle"]] [[!template text="""the Emacs ecosystem is the millions of lines of Elisp that""" start="00:01:59.880" video="qanda-rust" id="subtitle"]] [[!template text="""people have written.""" start="00:02:03.400" video="qanda-rust" id="subtitle"]] [[!template text="""Um, So I'm not, okay...""" start="00:02:07.480" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Q: so you're re-implementing elisp in rust? have you considered using a more modern lisp, such as scheme? [11:03]""" start="00:02:11.913" video="qanda-rust" id="subtitle"]]
[[!template text="""So since you're re-implementing Elisp and""" start="00:02:11.913" video="qanda-rust" id="subtitle"]] [[!template text="""Rust, have you considered using more modern Lisp such as""" start="00:02:14.280" video="qanda-rust" id="subtitle"]] [[!template text="""Scheme? So I'm not re-implementing Elisp and Rust. I'm""" start="00:02:17.040" video="qanda-rust" id="subtitle"]] [[!template text="""re-implementing the C in Rust. In fact, I would like to make""" start="00:02:20.920" video="qanda-rust" id="subtitle"]] [[!template text="""more of the core that's written in C in Elisp instead of C or""" start="00:02:25.440" video="qanda-rust" id="subtitle"]] [[!template text="""Rust, because then it's actually introspectible. There's""" start="00:02:30.480" video="qanda-rust" id="subtitle"]] [[!template text="""a talk by Tom Tromney that he gave a while ago about Emacs""" start="00:02:33.840" video="qanda-rust" id="subtitle"]] [[!template text="""should be Emacs Lisp. I kind of like that philosophy,""" start="00:02:38.720" video="qanda-rust" id="subtitle"]] [[!template text="""that as much of it as should be Elisp as possible, and we""" start="00:02:42.240" video="qanda-rust" id="subtitle"]] [[!template text="""should only have C or Rust or some systems level language for""" start="00:02:44.800" video="qanda-rust" id="subtitle"]] [[!template text="""really low-level stuff. Using a more modern LISP such as""" start="00:02:48.080" video="qanda-rust" id="subtitle"]] [[!template text="""Scheme. I know there's, I mean, there's two talks, I think,""" start="00:02:52.320" video="qanda-rust" id="subtitle"]] [[!template text="""in this conference about using Scheme inside Emacs. And I""" start="00:02:54.840" video="qanda-rust" id="subtitle"]] [[!template text="""looked at this at one point about what if you wrote it inside""" start="00:02:58.240" video="qanda-rust" id="subtitle"]] [[!template text="""Common LISP, because that's also has some really low level""" start="00:03:00.720" video="qanda-rust" id="subtitle"]] [[!template text="""details. And then you could go from Elisp down to Common""" start="00:03:03.920" video="qanda-rust" id="subtitle"]] [[!template text="""Lisp. But the problem is, is under the hood, you still need a""" start="00:03:05.880" video="qanda-rust" id="subtitle"]] [[!template text="""systems language. You can't, you still need either C or Rust""" start="00:03:09.200" video="qanda-rust" id="subtitle"]] [[!template text="""or something underneath the Common Lisp to implement the""" start="00:03:12.560" video="qanda-rust" id="subtitle"]] [[!template text="""primitives. And so it's not going to give you just two""" start="00:03:15.640" video="qanda-rust" id="subtitle"]] [[!template text="""languages, you know, you'll have three. You'll have the""" start="00:03:17.800" video="qanda-rust" id="subtitle"]] [[!template text="""elisp, common lisp, and C under the hood. And so in this case""" start="00:03:19.720" video="qanda-rust" id="subtitle"]] [[!template text="""we just have the two. We have the Elisp and the rest.""" start="00:03:24.920" video="qanda-rust" id="subtitle"]] [[!template text="""All right that's all the questions I see there. Let""" start="00:03:29.560" video="qanda-rust" id="subtitle"]] [[!template text="""me go look at... Okay,""" start="00:03:43.000" video="qanda-rust" id="subtitle"]] [[!template text="""so I see into the chat.""" start="00:03:54.080" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Q: Do you have specific features from the Rust compiler that are missing (or are nightly-only) that you would take advantage of?""" start="00:04:01.400" video="qanda-rust" id="subtitle"]]
[[!template text="""Does it features from the Rust compiler that are missing""" start="00:04:01.400" video="qanda-rust" id="subtitle"]] [[!template text="""that way you would take advantage of? Oh, that is a great""" start="00:04:03.840" video="qanda-rust" id="subtitle"]] [[!template text="""question. Um, there's a handful of them. Uh, I should've""" start="00:04:06.240" video="qanda-rust" id="subtitle"]] [[!template text="""written down a list of these. One of them is Polonius, which""" start="00:04:10.680" video="qanda-rust" id="subtitle"]] [[!template text="""is the new borrow checker because we're trying to be used""" start="00:04:13.600" video="qanda-rust" id="subtitle"]] [[!template text="""lifetime to track our objects. We often run into situations""" start="00:04:17.960" video="qanda-rust" id="subtitle"]] [[!template text="""where we've kind of got a hack around things because the""" start="00:04:21.760" video="qanda-rust" id="subtitle"]] [[!template text="""limitations with the borrow checker. And so I have a whole""" start="00:04:24.240" video="qanda-rust" id="subtitle"]] [[!template text="""bunch of like notes inside there about where. A better""" start="00:04:26.200" video="qanda-rust" id="subtitle"]] [[!template text="""Polonius would help inside there and help ease some of the""" start="00:04:29.560" video="qanda-rust" id="subtitle"]] [[!template text="""issues. Another thing is enum variances types, because""" start="00:04:34.960" video="qanda-rust" id="subtitle"]] [[!template text="""right now we have an object which is defined as a big enum that""" start="00:04:40.600" video="qanda-rust" id="subtitle"]] [[!template text="""had all the possible objects, but if we want to have a subset""" start="00:04:43.000" video="qanda-rust" id="subtitle"]] [[!template text="""of those objects or just pass in one of those objects, we've""" start="00:04:46.080" video="qanda-rust" id="subtitle"]] [[!template text="""got to define a new struct. And so we have a whole bunch of""" start="00:04:47.480" video="qanda-rust" id="subtitle"]] [[!template text="""boilerplate code to define that all out. And if we had""" start="00:04:50.080" video="qanda-rust" id="subtitle"]] [[!template text="""variances types, that would make the code a lot easier.""" start="00:04:52.840" video="qanda-rust" id="subtitle"]] [[!template text="""Another one is the allocator API. Right now we're kind of""" start="00:04:56.720" video="qanda-rust" id="subtitle"]] [[!template text="""working around it, but ultimately we're going to need our""" start="00:05:00.080" video="qanda-rust" id="subtitle"]] [[!template text="""own allocator. And the allocator API is still nightly only.""" start="00:05:02.480" video="qanda-rust" id="subtitle"]] [[!template text="""So there's a couple more. I'll look at that more, but that's a""" start="00:05:07.720" video="qanda-rust" id="subtitle"]] [[!template text="""great question.""" start="00:05:10.920" video="qanda-rust" id="subtitle"]] [[!template text="""Let's see.""" start="00:05:24.280" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Q: Can remacs be reused?""" start="00:05:26.880" video="qanda-rust" id="subtitle"]]
[[!template text="""Okay. I see a question you might not have noticed just asking""" start="00:05:26.880" video="qanda-rust" id="subtitle"]] [[!template text="""about reuse of Remacs. Oh, yes, so I have reused some of Remacs""" start="00:05:30.800" video="qanda-rust" id="subtitle"]] [[!template text="""code, and some taken, like I mentioned, taken some of their""" start="00:05:37.160" video="qanda-rust" id="subtitle"]] [[!template text="""ideas, but ultimately we're using a different model""" start="00:05:40.160" video="qanda-rust" id="subtitle"]] [[!template text="""because under the hood in Remacs, everything is just defined""" start="00:05:45.320" video="qanda-rust" id="subtitle"]] [[!template text="""as an opaque external type that's defined inside Emacs and""" start="00:05:49.440" video="qanda-rust" id="subtitle"]] [[!template text="""so it just pulls those in interacts with those and passes""" start="00:05:53.800" video="qanda-rust" id="subtitle"]] [[!template text="""them back into C. We're trying to see what we can do if we""" start="00:05:56.160" video="qanda-rust" id="subtitle"]] [[!template text="""say okay we're not going to take the same... So they're bound to""" start="00:05:58.880" video="qanda-rust" id="subtitle"]] [[!template text="""the implementation details of Emacs, and we don't want to do""" start="00:06:02.280" video="qanda-rust" id="subtitle"]] [[!template text="""that. We've re-implemented all the core types""" start="00:06:06.840" video="qanda-rust" id="subtitle"]] [[!template text="""ourselves. So that means that we can't just take the""" start="00:06:09.560" video="qanda-rust" id="subtitle"]] [[!template text="""Remacs code one for one and use it in our project, but we can""" start="00:06:12.560" video="qanda-rust" id="subtitle"]] [[!template text="""take a lot of their ideas. I've spent some time reading""" start="00:06:16.560" video="qanda-rust" id="subtitle"]] [[!template text="""through their documentation, different things about how""" start="00:06:18.800" video="qanda-rust" id="subtitle"]] [[!template text="""they approached strings and GC""" start="00:06:20.440" video="qanda-rust" id="subtitle"]] [[!template text="""and different stuff like that.""" start="00:06:23.857" video="qanda-rust" id="subtitle"]] [[!template text="""Looks like all the questions.""" start="00:06:24.760" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Q: What are you thoughts on the GUI layer. Any plans on how to reimplement it?""" start="00:07:23.600" video="qanda-rust" id="subtitle"]]
[[!template text="""Okay, so another question. What are your thoughts on the GUI""" start="00:07:23.600" video="qanda-rust" id="subtitle"]] [[!template text="""layer? Any plans on how to reimplement it? This is something""" start="00:07:26.200" video="qanda-rust" id="subtitle"]] [[!template text="""I've thought a lot about, but I still don't have a solid plan""" start="00:07:30.960" video="qanda-rust" id="subtitle"]] [[!template text="""for. I'm not really a GUI person. I mostly work with""" start="00:07:34.080" video="qanda-rust" id="subtitle"]] [[!template text="""low-level. And so my two thoughts is you can go the GTK route.""" start="00:07:37.254" video="qanda-rust" id="subtitle"]] [[!template text="""There's Rust bindings for that. That's well understood.""" start="00:07:42.720" video="qanda-rust" id="subtitle"]] [[!template text="""It's got a good support. But there's also some interesting""" start="00:07:45.520" video="qanda-rust" id="subtitle"]] [[!template text="""projects to try and do GUI in Rust, native Rust, and have it""" start="00:07:48.320" video="qanda-rust" id="subtitle"]] [[!template text="""use Rust idioms and stuff like that. And so those are things""" start="00:07:53.920" video="qanda-rust" id="subtitle"]] [[!template text="""like Druid and there's eGUI and a bunch of those that are that""" start="00:07:57.400" video="qanda-rust" id="subtitle"]] [[!template text="""way. And I've never used one of them, but I'd be interested to""" start="00:08:01.440" video="qanda-rust" id="subtitle"]] [[!template text="""try that out first and see how well does this work and how well""" start="00:08:05.360" video="qanda-rust" id="subtitle"]] [[!template text="""supported is this doing a Rust-first GUI.""" start="00:08:08.880" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Q: If money could fix the problem, how much would it cost to ship this with feature parity before 2026?""" start="00:08:21.240" video="qanda-rust" id="subtitle"]]
[[!template text="""If money could fix the problem, how much would it cost to ship""" start="00:08:21.240" video="qanda-rust" id="subtitle"]] [[!template text="""this with feature parity before 2026? Ooh, in a year. Uh,""" start="00:08:23.640" video="qanda-rust" id="subtitle"]] [[!template text="""that's a good question. Even if we had the money, it would""" start="00:08:28.400" video="qanda-rust" id="subtitle"]] [[!template text="""take more than just me, even if I was working on it full time.""" start="00:08:32.080" video="qanda-rust" id="subtitle"]] [[!template text="""Um, I don't know. That's a good question.""" start="00:08:36.640" video="qanda-rust" id="subtitle"]] [[!template text="""I would think it would take a team""" start="00:08:40.631" video="qanda-rust" id="subtitle"]] [[!template text="""of at least a handful of people to get this""" start="00:08:41.770" video="qanda-rust" id="subtitle"]] [[!template text="""shipping within one year. Because there's still a lot of""" start="00:08:45.240" video="qanda-rust" id="subtitle"]] [[!template text="""work to do. And even once you have everything implemented,""" start="00:08:48.560" video="qanda-rust" id="subtitle"]] [[!template text="""there's a lot of bug finding and smoothing it out so that it""" start="00:08:50.760" video="qanda-rust" id="subtitle"]] [[!template text="""runs as well as Emacs, which has been, you know, battle""" start="00:08:55.120" video="qanda-rust" id="subtitle"]] [[!template text="""tested for a long time.""" start="00:08:57.520" video="qanda-rust" id="subtitle"]] [[!template text="""Um, okay, so this might be a good moment for me to break in and""" start="00:08:58.360" video="qanda-rust" id="subtitle"]] [[!template text="""just say that we've got about 10 minutes left before we""" start="00:09:06.600" video="qanda-rust" id="subtitle"]] [[!template text="""resume new talks on on both tracks. Of course, we're happy to""" start="00:09:09.040" video="qanda-rust" id="subtitle"]] [[!template text="""keep this. This chat open and keep the recording going here,""" start="00:09:12.520" video="qanda-rust" id="subtitle"]] [[!template text="""which will share after the conference as long as as long as""" start="00:09:18.120" video="qanda-rust" id="subtitle"]] [[!template text="""there's discussion here. Thank you.""" start="00:09:21.600" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""GObject implementation""" start="00:09:28.350" video="qanda-rust" id="subtitle"]]
[[!template text="""GTK project has""" start="00:09:28.350" video="qanda-rust" id="subtitle"]] [[!template text="""automatic binding with a framework called GObject""" start="00:09:29.120" video="qanda-rust" id="subtitle"]] [[!template text="""introspection, which is what I'm using for gypsum project.""" start="00:09:31.080" video="qanda-rust" id="subtitle"]] [[!template text="""Probably Rust has a G object implementation, which you can""" start="00:09:33.600" video="qanda-rust" id="subtitle"]] [[!template text="""use. Yeah, I know it has some GTK bindings. Um, I'm not sure if""" start="00:09:35.960" video="qanda-rust" id="subtitle"]] [[!template text="""it's specifically GObject, but that's a good path""" start="00:09:39.120" video="qanda-rust" id="subtitle"]] [[!template text="""because I feel like the problem""" start="00:09:41.955" video="qanda-rust" id="subtitle"]] [[!template text="""with the Rust GUIs is that they're all""" start="00:09:44.336" video="qanda-rust" id="subtitle"]] [[!template text="""very new. And so, you know, everything works in a demo, but""" start="00:09:46.760" video="qanda-rust" id="subtitle"]] [[!template text="""you need something that can work across all different""" start="00:09:50.360" video="qanda-rust" id="subtitle"]] [[!template text="""devices and all different platforms and have really good""" start="00:09:52.320" video="qanda-rust" id="subtitle"]] [[!template text="""support and good accessibility and stuff like that.""" start="00:09:54.320" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Q: elisp is implemented in c, so if you're not implementing elisp in rust, are you using/keeping the c implementation of elisp?""" start="00:09:56.600" video="qanda-rust" id="subtitle"]]
[[!template text="""All right, Elisp is implemented in C. So if you're not""" start="00:09:56.600" video="qanda-rust" id="subtitle"]] [[!template text="""implementing Elisp in Rust, we're keeping the C""" start="00:10:03.400" video="qanda-rust" id="subtitle"]] [[!template text="""implementation of Elisp. So let me see if I can do a better job""" start="00:10:07.360" video="qanda-rust" id="subtitle"]] [[!template text="""of explaining this. So inside Emacs, you have about a""" start="00:10:13.640" video="qanda-rust" id="subtitle"]] [[!template text="""million lines of Elisp. And underneath that, you have the C,""" start="00:10:18.440" video="qanda-rust" id="subtitle"]] [[!template text="""which is the primitives everything's implemented yet. And""" start="00:10:21.520" video="qanda-rust" id="subtitle"]] [[!template text="""so we're keeping all of the Elisp, and we're just taking that""" start="00:10:24.080" video="qanda-rust" id="subtitle"]] [[!template text="""C layer and replacing it with Rust. And so when you call a""" start="00:10:27.080" video="qanda-rust" id="subtitle"]] [[!template text="""built-in function, it's calling into a Rust function""" start="00:10:30.560" video="qanda-rust" id="subtitle"]] [[!template text="""instead of a C function under the hood. So all the Elisp stays""" start="00:10:33.080" video="qanda-rust" id="subtitle"]] [[!template text="""Elisp, but the C becomes Rust.""" start="00:10:40.080" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Clarifying rewriting Elisp in Rust""" start="00:10:42.680" video="qanda-rust" id="subtitle"]]
[[!template text="""So looking at the IRC chat, it feels to me like maybe there's a""" start="00:10:42.680" video="qanda-rust" id="subtitle"]] [[!template text="""little bit of confusion around what do we mean when we say""" start="00:10:54.600" video="qanda-rust" id="subtitle"]] [[!template text="""rewriting Elisp in Rust, right? I think there are some""" start="00:10:59.160" video="qanda-rust" id="subtitle"]] [[!template text="""people that are like, A, we're reinventing ELISP, and""" start="00:11:04.840" video="qanda-rust" id="subtitle"]] [[!template text="""there's other people that are like, no, we're trying to be""" start="00:11:07.400" video="qanda-rust" id="subtitle"]] [[!template text="""byte-for-byte compatible with Rust.""" start="00:11:09.680" video="qanda-rust" id="subtitle"]] [[!template text="""So some people are questioning your no answer on that.""" start="00:11:12.880" video="qanda-rust" id="subtitle"]] [[!template text="""Aren't you really, maybe, is what I'm reading in there.""" start="00:11:17.501" video="qanda-rust" id="subtitle"]] [[!template text="""Do you want to respond to that?""" start="00:11:20.001" video="qanda-rust" id="subtitle"]] [[!template text="""Yeah, I'm trying to think about how I can make this""" start="00:11:21.770" video="qanda-rust" id="subtitle"]] [[!template text="""clearer. So the Elisp stays Elisp. We're not changing the""" start="00:11:26.120" video="qanda-rust" id="subtitle"]] [[!template text="""Elisp at all, or at least very minimally. We want to be able to""" start="00:11:29.560" video="qanda-rust" id="subtitle"]] [[!template text="""take, like I said, bug compatible. So whatever works inside""" start="00:11:33.240" video="qanda-rust" id="subtitle"]] [[!template text="""existing Emacs, you can take all the Lisp and you can run it in""" start="00:11:36.520" video="qanda-rust" id="subtitle"]] [[!template text="""Rune and it works the same. So the Elisp stays the same. It's""" start="00:11:40.000" video="qanda-rust" id="subtitle"]] [[!template text="""just the under the hood core that is getting replaced. And""" start="00:11:43.600" video="qanda-rust" id="subtitle"]] [[!template text="""this in turn adds some new features such as""" start="00:11:47.120" video="qanda-rust" id="subtitle"]] [[!template text="""multi-threading. So it's not exactly compatible, but""" start="00:11:49.200" video="qanda-rust" id="subtitle"]] [[!template text="""you should be able to use your existing code and the Elisp will""" start="00:11:52.800" video="qanda-rust" id="subtitle"]] [[!template text="""stay Elisp. So the idea is that anything that I've written as""" start="00:11:55.560" video="qanda-rust" id="subtitle"]] [[!template text="""an Emacs user, my config, my custom packages, whatever it""" start="00:12:00.640" video="qanda-rust" id="subtitle"]] [[!template text="""may be, that's all going to be valid code. If you take, you""" start="00:12:04.560" video="qanda-rust" id="subtitle"]] [[!template text="""know, the Elisp implementation as being the C code""" start="00:12:09.000" video="qanda-rust" id="subtitle"]] [[!template text="""and the parts of Elisp written in Elisp""" start="00:12:13.164" video="qanda-rust" id="subtitle"]] [[!template text="""that represent opportunity space""" start="00:12:15.746" video="qanda-rust" id="subtitle"]] [[!template text="""thinking about Rust as an implementation language...""" start="00:12:18.449" video="qanda-rust" id="subtitle"]] [[!template text="""Okay fine. You know, you can make a semantic argument, okay""" start="00:12:20.800" video="qanda-rust" id="subtitle"]] [[!template text="""we're re-implementing, we're creating""" start="00:12:24.480" video="qanda-rust" id="subtitle"]] [[!template text="""an alternate implementation of Elisp""" start="00:12:25.996" video="qanda-rust" id="subtitle"]] [[!template text="""but what Elisp is isn't the problem""" start="00:12:29.019" video="qanda-rust" id="subtitle"]] [[!template text="""space here. That's a fixed, a given, if you will.""" start="00:12:31.640" video="qanda-rust" id="subtitle"]] [[!template text="""Is that all right?""" start="00:12:35.040" video="qanda-rust" id="subtitle"]] [[!template text="""That's a good way of saying it. Okay. Yeah, what you""" start="00:12:36.066" video="qanda-rust" id="subtitle"]] [[!template text="""said makes sense. I was kind of responding to some comments,""" start="00:12:39.200" video="qanda-rust" id="subtitle"]] [[!template text="""like I'm not sure it connected for everybody. Makes a lot of""" start="00:12:42.560" video="qanda-rust" id="subtitle"]] [[!template text="""sense. Yeah, I wasn't sure how much I needed to expand on that""" start="00:12:44.960" video="qanda-rust" id="subtitle"]] [[!template text="""and explain that, but I appreciate you jumping in.""" start="00:12:47.400" video="qanda-rust" id="subtitle"]] [[!template text="""Um, okay. So if I were just going to, but...""" start="00:12:51.120" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Q: Will your Rust implementation also be able to run Emacs bytecode? Or are you implementing it at the Lisp level?""" start="00:12:57.908" video="qanda-rust" id="subtitle"]]
[[!template text="""Will your Rust implementation also be able to run Emacs bytecode or the""" start="00:12:57.908" video="qanda-rust" id="subtitle"]] [[!template text="""implemented at the Lisp level? So I already have a bytecode""" start="00:13:02.240" video="qanda-rust" id="subtitle"]] [[!template text="""interpreter inside there that runs the existing Elisp""" start="00:13:04.360" video="qanda-rust" id="subtitle"]] [[!template text="""bytecode. And so that was one of the first things I did was""" start="00:13:06.760" video="qanda-rust" id="subtitle"]] [[!template text="""bootstrap the interpreter and then bootstrap the bytecode""" start="00:13:09.520" video="qanda-rust" id="subtitle"]] [[!template text="""engine. And so we compile, we use the... because the bytecode""" start="00:13:11.680" video="qanda-rust" id="subtitle"]] [[!template text="""compiler is written in Emacs Lisp. So you bootstrap that""" start="00:13:15.000" video="qanda-rust" id="subtitle"]] [[!template text="""and it gives you the Emacs bytecode. I have a bytecode""" start="00:13:19.080" video="qanda-rust" id="subtitle"]] [[!template text="""engine that runs the bytecode. So that's already done. And""" start="00:13:22.920" video="qanda-rust" id="subtitle"]] [[!template text="""you can potentially, on top of that, do something like the""" start="00:13:26.040" video="qanda-rust" id="subtitle"]] [[!template text="""data compilation or a JIT. But we have both an""" start="00:13:28.240" video="qanda-rust" id="subtitle"]] [[!template text="""interpreter and a bytecode compiler.""" start="00:13:32.000" video="qanda-rust" id="subtitle"]] [[!template text="""And I'll just break in one more time to say with about five""" start="00:13:47.020" video="qanda-rust" id="subtitle"]] [[!template text="""minutes left in our live time with this Q&A session, which""" start="00:13:50.800" video="qanda-rust" id="subtitle"]] [[!template text="""we're happy to keep going as long as there are questions.""" start="00:13:56.320" video="qanda-rust" id="subtitle"]] [[!template text="""Coming up in five minutes, we'll have a talk on color on the""" start="00:13:58.440" video="qanda-rust" id="subtitle"]] [[!template text="""gen track. And then right here, we'll have the p-search""" start="00:14:03.960" video="qanda-rust" id="subtitle"]] [[!template text="""talk.""" start="00:14:09.640" video="qanda-rust" id="subtitle"]] [[!template text="""Thank you.""" start="00:14:09.960" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""Q: Is it possible to bootstrap with just the bytecode interpreter?""" start="00:14:20.100" video="qanda-rust" id="subtitle"]]
[[!template text="""Is it possible to bootstrap with just the bytecode""" start="00:14:20.100" video="qanda-rust" id="subtitle"]] [[!template text="""interpreter? So I'll have to put in a link to one of my blog""" start="00:14:22.560" video="qanda-rust" id="subtitle"]] [[!template text="""posts. So that was my original idea was to say, I don't want to""" start="00:14:25.760" video="qanda-rust" id="subtitle"]] [[!template text="""have an interpreter, a bytecode interpreter and a native""" start="00:14:28.520" video="qanda-rust" id="subtitle"]] [[!template text="""compiler. I want to just have just one.""" start="00:14:31.560" video="qanda-rust" id="subtitle"]] [[!template text="""So I'm only going to have the bytecode.""" start="00:14:33.181" video="qanda-rust" id="subtitle"]] [[!template text="""And so that's what I did initially.""" start="00:14:36.742" video="qanda-rust" id="subtitle"]] [[!template text="""The problem with that is, is that a bunch of the early bootstrap""" start="00:14:37.709" video="qanda-rust" id="subtitle"]] [[!template text="""Emacs code is written with the assumption""" start="00:14:42.080" video="qanda-rust" id="subtitle"]] [[!template text="""that it's going to be interpreted.""" start="00:14:45.118" video="qanda-rust" id="subtitle"]] [[!template text="""This is especially true with macros,""" start="00:14:47.279" video="qanda-rust" id="subtitle"]] [[!template text="""where you'll have a function defined,""" start="00:14:49.020" video="qanda-rust" id="subtitle"]] [[!template text="""you'll evaluate part of the function.""" start="00:14:50.822" video="qanda-rust" id="subtitle"]] [[!template text="""The other half of the function has macros in it""" start="00:14:52.643" video="qanda-rust" id="subtitle"]] [[!template text="""that are not defined yet, but it doesn't matter because they""" start="00:14:55.600" video="qanda-rust" id="subtitle"]] [[!template text="""don't get used. But with the bytecode interpreter, it""" start="00:14:59.720" video="qanda-rust" id="subtitle"]] [[!template text="""expands all macros when it gets the function definition.""" start="00:15:02.400" video="qanda-rust" id="subtitle"]] [[!template text="""And so those weren't macros when the function was expanded,""" start="00:15:04.640" video="qanda-rust" id="subtitle"]] [[!template text="""and therefore they got instantiated as functions, but""" start="00:15:08.800" video="qanda-rust" id="subtitle"]] [[!template text="""they're not functions, they're macros. And so I initially""" start="00:15:12.360" video="qanda-rust" id="subtitle"]] [[!template text="""spent a bunch of time trying to work around this, trying to""" start="00:15:15.760" video="qanda-rust" id="subtitle"]] [[!template text="""move code around, work stuff around, refactor the code to""" start="00:15:19.000" video="qanda-rust" id="subtitle"]] [[!template text="""try and get it to work with only bytecode interpreter. And""" start="00:15:21.600" video="qanda-rust" id="subtitle"]] [[!template text="""eventually I just gave up. I said, you know what, I'm just""" start="00:15:24.760" video="qanda-rust" id="subtitle"]] [[!template text="""going to write an actual interpreter to handle this because""" start="00:15:27.040" video="qanda-rust" id="subtitle"]] [[!template text="""trying to handle all these lazy macros is too much work. And""" start="00:15:30.040" video="qanda-rust" id="subtitle"]] [[!template text="""everything in the bootstrap is built with the assumption""" start="00:15:33.800" video="qanda-rust" id="subtitle"]] [[!template text="""that you have lazy macro expansion.""" start="00:15:35.760" video="qanda-rust" id="subtitle"]] [[!template text="""I'm guessing the Emacs bytecode interpreter isn't""" start="00:15:37.800" video="qanda-rust" id="subtitle"]] [[!template text="""complete.""" start="00:15:45.160" video="qanda-rust" id="subtitle"]] [[!template text="""So it's mostly complete. There's a handful of opcodes that""" start="00:15:45.960" video="qanda-rust" id="subtitle"]] [[!template text="""aren't implemented that are pretty easy to add that I""" start="00:15:52.280" video="qanda-rust" id="subtitle"]] [[!template text="""haven't run into. And there's some of them that are""" start="00:15:55.240" video="qanda-rust" id="subtitle"]] [[!template text="""deprecated that aren't implemented, but it's essentially""" start="00:15:57.880" video="qanda-rust" id="subtitle"]] [[!template text="""complete.""" start="00:16:00.120" video="qanda-rust" id="subtitle"]] [[!template text="""We also provide a bytecode JIT compilation via libgcc the""" start="00:16:00.480" video="qanda-rust" id="subtitle"]] [[!template text="""way Emacs currently does it. Eventually I would like to...""" start="00:16:12.000" video="qanda-rust" id="subtitle"]] [[!template text="""I'm more inclined to have a proper runtime JIT than an""" start="00:16:17.345" video="qanda-rust" id="subtitle"]] [[!template text="""ahead-of-time compiler like libgcc, like the current""" start="00:16:22.920" video="qanda-rust" id="subtitle"]] [[!template text="""Emacs native compilation, because it allows you to take""" start="00:16:27.400" video="qanda-rust" id="subtitle"]] [[!template text="""type information and actually apply that to the code, which""" start="00:16:29.920" video="qanda-rust" id="subtitle"]] [[!template text="""can let you do more aggressive optimizations to it.""" start="00:16:34.560" video="qanda-rust" id="subtitle"]]
[[!template new="1" text="""What would it take to bootstrap Guile in Rune?""" start="00:17:03.960" video="qanda-rust" id="subtitle"]]
[[!template text="""He said, we may either get a new Emacs with an ancient C core""" start="00:17:03.960" video="qanda-rust" id="subtitle"]] [[!template text="""with a modern Lisp, or an Emacs with modern core, but stuck""" start="00:17:06.320" video="qanda-rust" id="subtitle"]] [[!template text="""with ancient Elisp. So there was another project I was""" start="00:17:09.040" video="qanda-rust" id="subtitle"]] [[!template text="""talking to, one of the Guile implementations, about how we""" start="00:17:11.880" video="qanda-rust" id="subtitle"]] [[!template text="""could potentially, he was like, what would it take to""" start="00:17:16.640" video="qanda-rust" id="subtitle"]] [[!template text="""bootstrap Guile in Rune, where you have both, you could have""" start="00:17:19.120" video="qanda-rust" id="subtitle"]] [[!template text="""Elisp and Guile running inside this project. And so we've""" start="00:17:24.480" video="qanda-rust" id="subtitle"]] [[!template text="""started that discussion, which I think would be, which""" start="00:17:27.400" video="qanda-rust" id="subtitle"]] [[!template text="""would be interesting. But it's tricky too, because""" start="00:17:29.000" video="qanda-rust" id="subtitle"]] [[!template text="""fundamentally Elisp and Guile are two different""" start="00:17:34.000" video="qanda-rust" id="subtitle"]] [[!template text="""languages. They have different semantics. They have""" start="00:17:36.200" video="qanda-rust" id="subtitle"]] [[!template text="""different ways of handling things. You've really got to""" start="00:17:38.120" video="qanda-rust" id="subtitle"]] [[!template text="""consider both of those when you're trying to make them work""" start="00:17:39.880" video="qanda-rust" id="subtitle"]] [[!template text="""together.""" start="00:17:42.480" video="qanda-rust" id="subtitle"]] [[!template text="""How would you do the native module system? What would be""" start="00:17:42.800" video="qanda-rust" id="subtitle"]] [[!template text="""different? We can do the same thing. We have an FFI. So I""" start="00:17:57.320" video="qanda-rust" id="subtitle"]] [[!template text="""haven't looked into it a ton, but I feel like it could be""" start="00:17:59.800" video="qanda-rust" id="subtitle"]] [[!template text="""similar. And I'm actually interested, there's a couple""" start="00:18:03.840" video="qanda-rust" id="subtitle"]] [[!template text="""projects on GitHub right now to have an FFI written in Elisp.""" start="00:18:06.360" video="qanda-rust" id="subtitle"]] [[!template text="""So you don't even need to create a separate C or Rust module,""" start="00:18:12.760" video="qanda-rust" id="subtitle"]] [[!template text="""because you can actually write native modules in Rust or C.""" start="00:18:17.240" video="qanda-rust" id="subtitle"]] [[!template text="""And so you can just have direct bindings to a C FFI written in""" start="00:18:21.680" video="qanda-rust" id="subtitle"]] [[!template text="""Elisp. You don't need any C code inside there. And I think""" start="00:18:25.560" video="qanda-rust" id="subtitle"]] [[!template text="""that would be an interesting approach to look at as well.""" start="00:18:27.800" video="qanda-rust" id="subtitle"]] [[!template text="""Oh, Ramin. Yeah, that's right. We were talking about that,""" start="00:18:33.700" video="qanda-rust" id="subtitle"]] [[!template text="""about bootstrapping Scheme.""" start="00:18:35.840" video="qanda-rust" id="subtitle"]] [[!template text="""And at this point, we have broken away from, uh, from this""" start="00:18:41.540" video="qanda-rust" id="subtitle"]] [[!template text="""talk, but we're continuing to record and this will all be""" start="00:18:45.520" video="qanda-rust" id="subtitle"]] [[!template text="""published. I'd say, go ahead and keep going as long as you'd""" start="00:18:47.400" video="qanda-rust" id="subtitle"]] [[!template text="""like in here. And, um, thanks once again for the awesome""" start="00:18:50.440" video="qanda-rust" id="subtitle"]] [[!template text="""discussion. Thank you so much. So I'll just pay attention to""" start="00:18:54.960" video="qanda-rust" id="subtitle"]] [[!template text="""the ether pad and the chat and see.""" start="00:18:58.640" video="qanda-rust" id="subtitle"]] [[!template text="""That sounds good. I'll keep an eye on IRC. And if there are""" start="00:19:02.920" video="qanda-rust" id="subtitle"]] [[!template text="""more questions here, I'll bounce people toward the ether""" start="00:19:05.920" video="qanda-rust" id="subtitle"]] [[!template text="""pad or this, uh, chat room. All right, thank you.""" start="00:19:08.560" video="qanda-rust" id="subtitle"]]
Questions or comments? Please e-mail [troy@troyhinckley.com](mailto:troy@troyhinckley.com?subject=Comment%20for%20EmacsConf%202023%20rust%3A%20An%20experimental%20Emacs%20core%20in%20Rust)