[[!meta title="One year progress update Schemacs (formerly Gypsum)"]] [[!meta copyright="Copyright © 2025 Ramin Honary"]] [[!inline pages="internal(2025/info/schemacs-nav)" raw="yes"]] # One year progress update Schemacs (formerly Gypsum) Ramin Honary (he/him) - Pronunciation: "Rah-mean" (hard-H) "Ho-na-ree", Mastodon (preferred): ; blog: ; Codeberg: - SourceHut: [[!inline pages="internal(2025/info/schemacs-before)" raw="yes"]] During EmacsConf 2024 last year I presented my work on a clone of GNU Emacs written in Scheme which also clones the Emacs Lisp programming language. In this talk, I will briefly present an overview of the project similar to the talk I gave last year, and then discuss the progress that I have made on this project in the past year. To quote the description from the presentation I gave last year: > Unlike other editors which only clone the Emacs > keybindings (Edwin, Jed, jEdit, Jove, Lem, MG, Yi, > Zile), I hope my Emacs clone will also fully clone the > Emacs Lisp programming language well enough that many of > the packages in ELPA, Non-GNU ELPA, and perhaps even > MELPA, can be used in [Schemacs, formerly "Gypsum"] > without any modification. I would also like to talk a > little bit about how I am implementing it (the software > architecture), and invite others to contribute. > > I think my project is of interest to many Emacs users > because, firstly, I have personally spoken with a > relatively large number of people who have expressed > interest in making Emacs programmable in Scheme. > Secondly, there is a good amount of prior art for Scheme > implementations of Emacs. There are even builds of Emacs > that link to Guile which provides a "scheme-eval" > built-in function that translates between Elisp data > types and Scheme data types. The Guile compiler itself > ships with an Emacs Lisp compiler as well, although it > does not provide enough of Emacs's built-in functions to > be of much use. The progress I have made so far: - Ported all Guile-specific parts of the Emacs Lisp interpreter to fully standards-compliant R7RS Scheme code. The interpreter now runs on a few different Scheme implementations, not just Guile. The GUI remains Guile-only for now. - Implemented a new R7RS-compliant lexer and parser which constructs an Abstract Syntax Tree (AST) data structure, making it easier to find the source of errors and produce informative back traces. - Implemented enough of the Emacs Lisp interpreter to be able to load the "subr.el" source file, this defines what you might call the "core" of the Emacs Lisp language, including macros such as "defun" and "lambda." My primary goal continues to be to make it as easy as possible for other people to contribute to this project. Pretty soon it should be possible to run the Emacs Regression Test suite (ERT) in the cloned Emacs Lisp interpreter. Once this is done, we can run the same test code used during the building and testing GNU Emacs to test Schemacs. Hopefilly then, anyone will be able to select a failing test, write code to make the test pass, and submit a patch. About the speaker: I am Ramin Honary. I have been professional software engineer for 17 years and I have always had a passion for functional programming languages, especially Haskell and the Lisp family of languages. ## Discussion / notes - Q: I think that Kiczalez et al.'s metaobject protocol has a scheme implementation, does this mean schemacs will be metaobject-changeable in practice?  - A: I was not aware of that implementation, but I will look into it. The MOP has not been necessary for building the GUI, actually (apart from the fact that Guile-GI uses GOOPS to organize the Gtk3 bindings). Pretty soon I will demonstrate the React-like programming framework I have developed for the Schemacs GUI. - A: I don't need a meta-object protocol for Schemacs, at least so far it hasn't been necessary, but may be something to look into if it can be made cross-platform (for various R7RS Schemes). - Q: How will the GUI display code be r7rs compliant afaik there is no dlopen in r7rs? - A: To handle these platform-dependent concerns, I make heavy use of the `cond-expand` macro. Basically any Scheme implementation upon which I would like to run the Schemacs GUI will have to have it's own unique back-end code that is loaded-in to the main Scheme program. `cond-expand` has mechanisms for checking which Scheme implementation it is using, so it is pretty easy to write code that can load-in different back-ends for whatever platform you are using. - Q: Will it be possible to write multithreaded code for Schemacs? - A: The GUI is inherently single-threaded, but SRFI-18 provides multi-threading. So yes, there is multi-threading, and I do have ways of evaluating Scheme code inside of the GUI thread so that you can update the GUI. This is necessary for running external processes and putting the results into buffers. But anyone should be able to use the threading mechanism through the ordinary SRFI-18 APIs. [https://srfi.schemers.org/srfi-18/srfi-18.html](https://srfi.schemers.org/srfi-18/srfi-18.html) - Q: Do you think some of schemacs could be extracted into SRFIs since you have made it portable between scheme implementations? - A: Absolutely. I have considered making a SRFI for my `(schemacs lens)` library. I would like to break up the Schemacs into libraries and publish them on the Akku package manager, or in the Guix repository. I am hopeful that some of the libraries I have written will be useful for other Scheme programmers. [https://akkuscm.org/](https://akkuscm.org/) - Q: Is there a recommended scheme implementation or does it try to be as portable as possible? - A:(He said earlier that Guile was the only version that worked so far.  He wants it to work for all R7RS though.) That's right, Guile is the reference implementation, the GUI only works on Guile, but Emacs Lisp works on Guile, Chibi, and Gauche. I would like to support as many Scheme's as possible. If you want to get started with Scheme and you want to try Schemacs, I recommend Guile. - Q: How would Schemacs deal with Emacs' (re)display architecture? Would it be having its own display architecture? If so, how can it be compatible with things like overlays, images, etc.? From what I know, Emacs is extremely idiosyncratic here. - A: That is all "to be determined." At some point we will have to emulate the Emacs Lisp display architecture in Schemacs, but for the time being Schemacs has it's own completely different display architecture. - Q: You were saying that you'd like to get "most" of the one thousand three hundred and something Emacs packages done. Is there a technical blocker to doing them all? Or just a problem of getting enough people in to help and start writing scheme? - A: just a matter of implementing enough of Emacs' built-in functions; this relates to the bug we saw in the presentation (stack dump); other people will have trouble contributing until this is resolved because it does not handle closures correctly.  once that is worked out it will be a matter of implementing Emacs' C-based functions in scheme.  Don't have a way to be sure but we probably do not need all of them implemented. - Q: What are you thoughts on Chicken Scheme? Would it be a good fit? - A: I think it will be; tried this in preping for the presentation but ran into some issues; tried using the pattern matcher from Alex Shinn; each implementation has a slightly different take on macro-expansion for pattern matching; I would definitely love help in this area. I will probably have to avoid pattern matching to make it fully portable, or else implement my own pattern matcher which I can be sure will work on all R7RS Scheme implementations. - Q: Can this emacs lisp implementation be used by Guile's emacs lisp "mode"? - A: This was touched on last year; Emacs Lisp in guile is a different implemtation which is unfortunately quite incomplete, it can't even run some of the GNU Emacs initialization code.  When I first started I was using Guile Emacs Lisp's parser, however it did not give source locations, and was not portable to other Schemes, so I had to basically write everything for Schemacs from the ground-up. If Andy Wingo is interested, we can probably replace the existing Guile Emacs Lisp implementation with Schemacs. - Q: I wonder if we could do some sort of programmatic analysis on popular Emacs packages to see what list of functions they tend to depend upon, follow function calls down to the lowest level - A:  Yes, please do this for me! :D :D - Q: Shouldn't it be enough to just implement the builtin functions? Most of the commands are written in Emacs Lisp, right? - A: Yes, correct. That is the approach I am taking. My goal is to get the Emacs Regression Test suite (ERT) system working in Schemacs Emacs Lisp, then we can just use the reports generated by the GNU Emacs regression tests to see what Emacs Lisp functions we have left to implement in Schemacs. - Q:  Do you think there is an opportunity to use Racket? - A: Yes, looking at getting Schemacs working Chez then could somehow move onto Racket; haven't tried R7RS for racket. Racket works on Chez, and I would like to make Schemacs work on Chez, but I won't be able to make use of Racket libraries. Alexis King has written a R7RS language package for Racket, and I haven't tried it yet, but it may be a good way to get Schemacs to work in Racket. - Q: Tell us more about this show-stopping bug! How to squash it? Can people help? - A: Unfortunately, this is something I will have to do on my own unless you happen to be a Scheme genius who can read and understand all of my code so far in a short amount of time. It has to do with how closures work. Closures were introduced with Emacs 27 (?) and lexical scoped variables for ELisp.  When we create and return a lambda that uses a variable declared outside of the Lambda in a "let" binding, that variable resides on the stack, so the Lambda must have a "note" that captures part of the current stack and then later restores it when the Lambda is executed. This is where the issue is: it is not capturing the variables from the stack properly.  The plan is to do static analysis of the Lambda and then store a reference to those vairbles in the Lambda data structure. - Q: How about using smaller test cases (instead of a full Emacs loadup) to pinpoint the issue? When writing Juicemacs I've gather a few closure-related test cases ([https://github.com/gudzpoz/Juicemacs/blob/ddc61c08632cfdd1a9f2bc10f63e61c5679d6592/elisp/src/test/java/party/iroiro/juicemacs/elisp/runtime/ELispBindingScopeTest.java#L12-L91](https://github.com/gudzpoz/Juicemacs/blob/ddc61c08632cfdd1a9f2bc10f63e61c5679d6592/elisp/src/test/java/party/iroiro/juicemacs/elisp/runtime/ELispBindingScopeTest.java#L12-L91) , and some more test cases in a blog post: [https://kyo.iroiro.party/en/posts/emacs-lisp-interpreter-with-graalvm-truffle/#creating-closures-in-a-loop](https://kyo.iroiro.party/en/posts/emacs-lisp-interpreter-with-graalvm-truffle/#creating-closures-in-a-loop) ). Could they be useful? (I just tried to take a peek at Schemacs' code, but I'm really not familiar with Scheme...) - By the way, Emacs comes with its own static analyzer in elisp (cconv.el) that seems to select captured variables from env cons lists in Emacs, which might be useful if you're also using a cons/linked list of lexical bindings, I guess? - Q: Are there performance concerns with implementing certain C primitives in pure scheme? - A: No :) I think it was Donald Knuth who said "Premature optimization is the root of all evil." The graphical back-end is usually written in C anyway (Gtk3), so the graphics is being done in C. Besides that, Scheme compilers like Guile, Chez, Gambit, and Chicken all have very good performance characteristics. So for the time being, I don't think performance is a major concern. - Q:  If this project is successful, are you worried about a possible split in the community between Schemacs and GNU Emacs users? - A: There seems to be a large call for a scheme based editor, so the demand for this "split" is already there. There have been attempts at rewriting Emacs in Scheme since the early 90s. And there hasn't been a good, free-software, Scheme-based programming environment like Emacs since Edwin on MIT Scheme.  So Schemacs may cause some fragmentation but "a rising tide raises all ships".  If I have time I would also like to contribute some of what I learn from Schemacs back to GNU Emacs, for example I would like to work on an interactive canvas library based on the "Cairo" SVG rendering library. Cairo is already built-in to Emacs, so I would like to maybe port my Schemacs interactive canvas (still a work in progress) to GNU Emacs when I have some time. - Q:  The dream of never even needing to change to the web browser - would schemacs bring us closer to that? - A: I hope so!  this is also a dream of mine!  I wanted to make sure I have a good workable UI framework like React so we can write proper GUIs for applications such as a Mastadon client, it could be very nice to have a better GUI for this, or for Magit, or Gnus. I would love to be able to do as much as possible in Schemacs, e.g. social networking, public Git repos. That is a goal of mine for this project. - Q: Anything specific other than minimalism that made you choose Scheme over Common Lisp? - A: Philosophical question :)  I love Haskell, and I once had a conversation with William Byrd (author of "MiniKanren," who studied under Dan Friedman at the University of Indiana) who told me about why he didn't like Haskell and suggested looking into Scheme. I like Haskell because it is a very pure implementation of the "System-F" Lambda Calculus, and I like Scheme because it's closer to the mathematical framework of the Untyped Lambda Calculus, but Scheme is friendly (without the strict type system), similar to Python. It provides a tiny framework from which all of computer science can be explored.  Excited to see what this tiny language can do. I like the idea of starting from a tiny "kernel" language and using it to build-out all other alglorithms and software. I think it is a shame that there isn't much Scheme code out there, and I would like to try to expand the Scheme software ecosystem. - [https://codeberg.org/ramin_hal9001/schemacs](https://codeberg.org/ramin_hal9001/schemacs) - [https://github.com/spk121/guile-gi](https://github.com/spk121/guile-gi)  <-- that is the GUI back-end, by the way. - [https://gi.readthedocs.io/en/latest/](https://gi.readthedocs.io/en/latest/)   <-- that is GObject Introspection, this is how the GUI bindings work. - lol it feels like rahim has been standing at the same place since last year :P - Basically, yes, I haven't moved at all! Of course I have moved away from that spot in the interim once or twice. - Awesome talk, I will surely try to contribute even though I don't know stuff yet :) - All are welcome, if you don't know anything, I'll be happy to try and teach you! - amazing progress - nice talk. - I'm so excited for this project! Amazing update 😊 - I wonder if we could do some sort of programmatic analysis on popular Emacs packages to see what list of functions they tend to depend upon, follow function calls down to the lowest level - would love to see that - That is probably a good idea (getting rid of the baggage) [[!inline pages="internal(2025/info/schemacs-after)" raw="yes"]] [[!inline pages="internal(2025/info/schemacs-nav)" raw="yes"]]