/Juicemacs

An absolutely-not-solid Emacs implementation (WIP)

Primary LanguageJavaGNU General Public License v3.0GPL-3.0

Juicemacs - An absolutely-not-solid Emacs implementation

https://img.shields.io/badge/justforfunnoreally-dev-9ff.svg https://img.shields.io/badge/Java-23-orange.svg?logo=openjdk&ext=.svg https://img.shields.io/github/actions/workflow/status/gudzpoz/Juicemacs/test.yml?ext=.svg

Juicemacs is a work-in-progress Emacs implementation just for the fun of it that over-ambitiously aims to explore the following:

  • Speculative JIT compilation
  • Transparent(-ish) concurrentization of ELisp code
  • Polyglot programming with Python, JavaScript, etc.
  • GNU Emacs 30 compatibility

Java helps to make all these possible, for it runs on JVM, which happens to be a platform with several nice things:

  • A decent GC: HotSpot has a number of state-of-the-art GCs.
  • Green threads & OS threads: One without the hassle of function coloring.
  • An incredible JIT framework: Truffle lets you build an interpreter and a JIT compiler all at once.

Of course using Java brings in its own problems, which this project will need to live with:

  • Sloooow startup (and with Truffle, it actually needs two warm-ups)
  • It bloats (and we can only hope Project Valhalla somehow tackles that)

Running

Currently, Juicemacs has two functional interpreters (one for AST, one for bytecode) and enough built-in routines implemented to handle pdump. It usually stops when top-level tries to use unimplemented UI subroutines.

To run it:

  1. Make sure to have JDK 23 installed (preferably graalvm-ce).
  2. Clone the repository, go to elisp/emacs/ and build a GNU Emacs to have all the generated data/elisp files ready.
  3. Run sh -c "cd app && $(./gradlew -q :app:jvmCmd)" (in the project root) for a REPL.

If you’re on Windows or just can’t run the command above, it basically just does the following:

  1. Run the :app:jvmCmd Gradle task, which will produce a command with the correct JVM flags to make the JIT magic from Truffle work.
  2. Run the produced command under the app/ directory, because we currently hard-code the Emacs directory path to help with our tests. You can also use the -L/--directory option to specify a Lisp source directory.

By the way, you may also try:

  • sh -c "cd app && $(./gradlew -q :app:jvmCmd) --help"
  • sh -c "cd app && $(./gradlew -q :app:jvmCmd) --inspect=4242" (for a Chrome DevTools protocol server)

And specially, if you want to try out the experimental slowish pdump:

  • sh -c "cd app && $(./gradlew -q :app:jvmCmd) --dump=pdump"
  • sh -c "cd app && $(./gradlew -q :app:jvmCmd) --dump-file ./emacs.pdmp"

We also support Java native images:

  • ./gradlew :app:nativeCompile (pdump is much faster with native images)

ERT Testing

Emacs comes with a unit-testing toolkit, Emacs Lisp Regression Testing (ERT), and has a bunch of ELisp tests in its source repository (./test/src/). Juicemacs currently can run some of these tests with a bit of workaround:

;; TODO: pp requires a bunch of sexp parsing functions
(require 'pp)
(defalias 'pp 'princ)
;; ert asserts about newlines produced by pp
(defun cl--assertion-failed (&rest _) t)

(require 'ert)
(load "../test/src/data-tests")
(ert-run-tests-batch)
(null (ert-run-tests-batch)) ; don't print the huge info object

You’re welcome to try the tests and report any failing cases! (I think many of them might simply throw an UnsupportedOperationException since they are yet to be implemented.)

Contributing

Check out CONTRIBUTING.org for a walkthrough. Check out docs/TODO.org or search for UnsupportedOperationException or TODO in code for things that need more work.

Documentation

Blog posts

Similar projects

Disclaimers

By calling this project Juicemacs, I do mean that: