Hacker News new | ask | show | jobs
by JonChesterfield 724 days ago
Fantastic news! This is a really interesting place in the design space and has come so close to being lost to history.

I believe the idea is essentially to write C semantics in scheme notation. Variables get marked with 'u32' or similar instead of being implicit sum types of anything the language can represent, memory allocation is explicit instead of garbage collected. In itself that essentially means writing C syntax trees in prefix notation, which is probably an acquired taste.

However scheme also comes with the compile time macro layer and that lot runs just fine in pre-scheme, garbage collected and all, because it's burned off before runtime anyway. Specifically, it's wholly macro-expanded before compilation to C (or similar), which is the obvious lowering to use for execution.

Also scheme has tooling, so if you're careful, the type annotated Cish syntax trees execute correctly as scheme, so you can debug the thing there, unit test it from scheme and so forth.

I really like it as a path to writing lisp runtimes in something that isn't C since an alarming fraction of them turn out to have a C runtime library at the bottom of the stack. Also for writing other things that I tend to write in C, where it's really the semantics I want and the syntax getting in the way.

3 comments

Smalltalk can use a similar bootstrapping method, which blew my mind the first time I read and understood (see https://ftp.squeak.org/docs/OOPSLA.Squeak.html, "Smalltalk to C Translation"). In that world, images can easily obscure some of the lineage. Scheme has the advantage of having a standard to hold dialects to. I am watching this project with interest.
This is (potentially) so much better than complex C preprocessor or C++ template complexity.
This is similar to how https://www.oilshell.org/ is written

There are two complete implementations

1. one that runs under a stock Python interpreter (which doesn't use static types)

2. one that's pure C++, translated from statically typed Python code, and from data structures generated in Python

In the second case, everything before main() is "burned off" at build time -- e.g. there is metaprogramming on lexers, flag parsers, dicts, etc. that gets run and then turned into static C data -- i.e. data that incurs zero startup cost

Comparison to Pre-Scheme: https://lobste.rs/s/tjiwrd/revival_pre_scheme_systems_progra... (types, compiler output, and GC)

Brief Descriptions of a Python to C++ Translator - https://www.oilshell.org/blog/2022/05/mycpp.html

...

And related to your other point, I remember looking at Racket's implementation around the time it started the Chez Scheme conversion. For some reason, I was surprised that it was over 100K lines of hand-written C in the runtime -- it looked similar to CPython in many ways (which is at least 250K lines of C in the core).