2025-03-11 18:34:41 Displayed 17808 times

Why I stopped everything and started writing C again

I've been a good student for 5 years at a French computer school. I've been a good freelance developer for 20 years. I've used Ruby on Rails exclusively however never writing my own code always for clients.

One day I learned Common Lisp. It was supposed to be a short mission I thought I could learn Common Lisp in ten days and hack a quick server management protocol. I ended up writing throw-away Common Lisp code that generated C for a fully-fledged ASN.1 parser and query system for a custom Common Lisp to C SNMP server.

Years later I wrote more and more Common Lisp code and ended up writing cl-unix-cybernetics which has the most stars on Github of all my repos there, and cl-streams and cl-cffi, and finally cl-facts which is a triple store that can be used as a Common Lisp graph database. The results were astonishing : very fast, atomic transactions, nestable transactions, compatible with unwind-protect, only 3 macros to learn and you're all set. Cl-facts was presented as a lightning talk at ELS (European Lisp Symposium) in Belgium. Slides for my talk there is available, see the front page.

Writing all these Common Lisp packages took a long time and I was loosing all my clients. I did not care, Common Lisp was awesome and a tool for future generations for sure.

However I also had a lot of echoes around me of people failing where Theo de Raadt and others had said they were wrong. Virtual machines still suck a lot of CPU and bandwidth for nothing but emulation. Containers in Linux with cgroups are still full of RCE (remote command execution) and priviledge escalation. New ones are discovered each year. The first report I got on those listed 10 or more RCE + PE (remote root on the machine). Remote root can also escape VMs probably also. You do have backups right ? So it kept me centered on OpenBSD and avoided me the hell that most DevOps faced : Terraform, Ansible and such. So I saw people angry with VMs and containers and also people angry with their very programming language. Like Clojure : who can write a strategy game with thousands of units each having their own vision of the world, without having a garbage collector running like hell ? In fact my friend went away and tried to write the game and failed. Garbage collectors suck, and all my Common Lisp projects have very limited applications just because of the garbage collector. And we all know it's a commercial argument to the jVM : it has one of the best GCs around and it did cost a lot to write correctly. I guess it was not written in a one time scratch

So I thought OK I have a killer app but no-one will run it because it's in Common Lisp. The only rational solution for performance and portability reasons, unless another tool is developed for these specific purpose like C, is C. Linux is written in C, OpenBSD is written in C, GTK+ is object-oriented pure C, GNOME is written in C. Most of the Linux desktop apps are actually written in plain old C. So why try harder ? I know C.

So I started writing my libc3 utility library, which would become a language (C3) with an interpreter (ic3) but could also be compiled (c3c) if we did manage to get it through at some point; and data structures emerged from UTF-8 buffers and the other way around pretty fast and all was bounds-checked at memory cost but the results were awesome. Defensive programming all the way : all bugs are reduced to zero right from the start. The system has been maintained clean of wrong bugs all of the time. There are no security implications of running KC3 code. So very fast a small interpreter was born, pumping tags (an enum-tagged union of all datatypes of the language) in a REPL (read eval print loop).

3 years later I just finished a 5 layered refactor and all the tests pass again and the webserver seems to not be broken again. The language was renamed from C3 to KC3 as the original name was already taken. So what do we have ?

I had already ported the graph database (cl-facts) to C89 and though a couple of bugs remained at the time of import pretty much all the database was written during the Covid-19 lockdown in 2020. Everything was there : add a triple, remove a triple, the recursive query system, transactions, logging and persistence. Pixel perfect implementation of my original design in Common Lisp but in plain old C89 which I remembered quite well.

Besides the graph data base I also wrote parsers and generators to get formal semantics for all algorithmic types I know of and could write in such a short amount of time : Structs, Linked lists, Maps, Hash tables, Time, Complex, Rationals, Tuples, Code blocks, Quotes, Unquotes, Copy on write, Skip lists, Sets, etc. I have macros like I explain in my other article. I'll do a follow up with some examples of macros. I was very much inspired by the awesome work of José Valim and Elixir. See Fly.io's blog if you want to read José Valim !

I have a REPL (ikc3) which parses keyboard or file input and outputs all results of a KC3 evaluation to the console (standard output). It is used for most of the second phase of unit testing KC3.

I have a webserver with an MVC framework which is producing the very webpage you're reading : kc3_httpd.

I have 700 views on a Common Lisp article which is crazy I did not think Common Lisp had so many followers.

I have a documentation website all written using kc3_httpd and a vamped Markdown to HTML C implementation.

Come on Discord and join the fun.