1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
|
[[!meta title="One year progress update Schemacs (formerly Gypsum)"]]
[[!meta copyright="Copyright © 2025 Ramin Honary"]]
[[!inline pages="internal(2025/info/schemacs-nav)" raw="yes"]]
<!-- Initially generated with emacsconf-publish-talk-page and then left alone for manual editing -->
<!-- You can manually edit this file to update the abstract, add links, etc. --->
# One year progress update Schemacs (formerly Gypsum)
Ramin Honary (he/him) - Pronunciation: "Rah-mean" (hard-H) "Ho-na-ree", Mastodon (preferred): ; blog: <https://tilde.town/~ramin_hal9001>; Codeberg: <https://codeberg.org/ramin_hal9001/schemacs> - SourceHut: <https://sr.ht/~ramin_hal9001>
[[!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"]]
|