# Is FemtoLisp just for fun now?

**URL:** <https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838>\
**Category:** Internals & Design\
**Created:** [January 15, 2024, 5:21pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838 "2024-01-15T17:21:14Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![LeePhillips](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/leephillips/32/205514_2.png) [@LeePhillips](https://discourse.julialang.org/u/LeePhillips)\
**Post date:** [January 15, 2024, 5:21pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/1 "2024-01-15T17:21:15Z")

</div>

Now in v1.10 the parser is written in Julia, but we can still enjoy the FemtoLisp REPL with the `--lisp` flag. Is FemtoLisp purely an Easter egg now? Or does it do anything?

---

<div class="post-metadata">

**Author:** ![Keno](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/keno/32/285_2.png) [@Keno](https://discourse.julialang.org/u/Keno)\
**Post date:** [January 15, 2024, 6:00pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/2 "2024-01-15T18:00:41Z")

</div>

It’s still used for lowering for the time being. The flisp parser is also still available as a fallback and for bootstrap.

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [January 15, 2024, 6:00pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/3 "2024-01-15T18:00:49Z")

</div>

It still does. It did parsing and “lowering” I think. Now only the latter, unless you opt into the older parser. That’s still possible in case there are bugs, but will likely go away, there doesn’t seem to be bugs anymore, then few.

I expect that only other use to go away, though I’m not the expert, on when or how much of a problem. And with it likely the “Easter egg”… It might become an optional JLL/package in case you miss it. Do you?

I’m not sure the command line option will survive, does anyone rely on that undocumented feature?

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [January 15, 2024, 6:06pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/4 "2024-01-15T18:06:19Z")

</div>

What do you mean with bootstrap? I’m not sure I understand it well enough, I see changes that may be related to it(?). I think I understand lowering well enough, but for the flisp part of it, and bootstrapping, would you say it’s a lot of code, as in likely easy to replace?

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 15, 2024, 8:21pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/5 "2024-01-15T20:21:27Z")

</div>

If the parser is written in Julia, how do you parse the parser without already having a Julia parser?

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [January 15, 2024, 8:25pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/6 "2024-01-15T20:25:27Z")

</div>

One answer would be to have bootstrapping be done from a (yet to be made) Julia with S-expressions. This could be automatically generated by the parser so you only need 1 implementation of the parser.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 15, 2024, 8:28pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/7 "2024-01-15T20:28:00Z")

</div>

Yeah, that would be a nice way to do it. In the meantime the flisp parser parses the Julia parser.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [January 15, 2024, 9:56pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/8 "2024-01-15T21:56:07Z")

</div>

If we have a binary of the previous parser it can be used to build the next version.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 15, 2024, 10:07pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/9 "2024-01-15T22:07:40Z")

</div>

That’s not very appealing because in order to build any version from scratch you have to generate a long chain of compiled versions and if any step of that chain stops working you no longer have a reproducible build process. Checking binaries in is ugly and then you just have these binaries that you need but can’t really trace the origin of.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 16, 2024, 1:24am UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/10 "2024-01-16T01:24:18Z")

</div>

By contrast, Oscar’s suggestion of having a simple s-expr parser written in C would work like this:

- Parser is written in Julia
- Initially the Parser is parsed with the legacy flisp parser
- The parser parses itself and emits s-exprs for the parser code
- Commit these generated s-exprs along with Julia source for parser
- Also implement a simple s-expr parser in C that can parse saved s-exprs
- Bootstrapping: the simple s-expr parser parses the saved s-exprs, which produces a working Julia parser that can be used to parse Julia code

Normally the Julia parer goes straight from Julia source =\> Julia AST, which is fine when you have a fully working parser already. This approach effectively uses s-exprs as a “virtual machine” for parsing, decoupling the complex parsing part, i.e. Julia source =\> s-exprs, from the platform-specific part, i.e. s-exprs =\> Julia AST. This is analogous to how JVM byte code is used to separate the Java language front-end, which can “just” produce VM byte code from the platform-specific part that needs to take byte code and actually run it on a specific platform. But in this case, “interpreting” s-expr byte code is just a matter of turning a file with s-exprs into Julia AST, which is really very straightforward (much more straightforward than implementing a JVM). This way you can do the Julia source =\> s-exprs part on a system where you already have a working parser, save the s-exprs (which are system-independent), move them to another system where you don’t have a working parser, and use a simple s-expr parser to convert that into in-memory Julia AST on the new system, which can then actually be evaluated.

---

<div class="post-metadata">

**Author:** ![caleb-allen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/caleb-allen/32/14054_2.png) [@caleb-allen](https://discourse.julialang.org/u/caleb-allen)\
**Post date:** [January 16, 2024, 5:34pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/11 "2024-01-16T17:34:10Z")

</div>

> [@jar1](#):
>
> If we have a binary of the previous parser it can be used to build the next version.

When using one of these binaries in a new build, one would be required to trust every binary ever used in its “ancestry”. Each would be a vector of attack not only for the parser being built, but for anything the _new_ parser ever generates (its “descendants”).

---

<div class="post-metadata">

**Author:** ![caleb-allen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/caleb-allen/32/14054_2.png) [@caleb-allen](https://discourse.julialang.org/u/caleb-allen)\
**Post date:** [January 16, 2024, 6:05pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/12 "2024-01-16T18:05:39Z")

</div>

> [@StefanKarpinski](#):
>
> But in this case, “interpreting” s-expr byte code is just a matter of turning a file with s-exprs into Julia AST, which is really very straightforward (much more straightforward than implementing a JVM). This way you can do the Julia source =\> s-exprs part on a system where you already have a working parser, save the s-exprs (which are system-independent), move them to another system where you don’t have a working parser, use the C code to convert the s-exprs into in-memory Julia AST on the new system, which can then actually be evaluated.

This reminded me of wasm, since it uses s-exprs for its text format, and the wasm binary format acts similar to bytecode for the JVM.

But that has me wondering—would such a “bootstrapped” s-expr Julia parser make for easier porting to new environments (for the parser, at least)? Or perhaps act as a “target format” for alternate front-ends?

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 16, 2024, 6:44pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/13 "2024-01-16T18:44:17Z")

</div>

> [@caleb-allen](#):
>
> But that has me wondering—would such a “bootstrapped” s-expr Julia parser make for easier porting to new environments (for the parser, at least)? Or perhaps act as a “target format” for alternate front-ends?

Yes, porting to new environments is one of the main use cases: on a new system you “just” need to compile the C s-expr parser (and have a working LLVM backend). It could also be a target for people wanting to use a different syntax front end for Julia.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [January 16, 2024, 6:59pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/14 "2024-01-16T18:59:35Z")

</div>

> [@caleb-allen](#):
>
> When using one of these binaries in a new build, one would be required to trust every binary ever used in its “ancestry”. Each would be a vector of attack not only for the parser being built, but for anything the _new_ parser ever generates (its “descendants”).

I guess I’m playing devil’s advocate, but I don’t think you’re strictly correct. There’s been academic [research](https://dwheeler.com/trusting-trust/) on this topic (countering Ken Thompson), and Linux (and other) software distributions have to deal with the same and related issues: [https://reproducible-builds.org](https://reproducible-builds.org)

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [January 17, 2024, 12:10am UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/15 "2024-01-17T00:10:29Z")

</div>

Afaik with reproducible builds you only need to trust the original inputs, intermediate builds are deterministic and verifiable.

The Rust compiler is built using its own previous minor version.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [January 17, 2024, 4:54am UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/16 "2024-01-17T04:54:23Z")

</div>

> [@jar1](#):
>
> If we have a binary of the previous parser it can be used to build the next version.

The Zig folks used WASM/WASI to self-host.  
[https://ziglang.org/news/goodbye-cpp/](https://ziglang.org/news/goodbye-cpp/)

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 17, 2024, 4:36pm UTC](https://discourse.julialang.org/t/is-femtolisp-just-for-fun-now/108838/17 "2024-01-17T16:36:35Z")

</div>

That’s a very cool approach, but I think for us the s-expr approach is much simpler. Why can we do that whereas Zig can’t? One reason is that Julia AST is already basically s-exprs, so this is really easy for us, whereas Zig would have to design a syntax serialization format that’s simple to parse yet general enough for the entire Zig syntax (which presumably wasn’t designed with s-exprs in mind). The other major difference is that Zig is trying to fully boostrap their entire compiler, so they need a way to run the whole thing on a new system, not just the parser. Julia, on the other hand, isn’t fully bootstrapped—our core runtime is written in C—so we just don’t have as hard of a boostrapping problem as they do and a simpler solution works for us.
