Lithium

A small Clojure-inspired Lisp for the bare metal



Daniel Janus
@nathell

Bare metal?

  • Compiles to x86 native code
  • No runtime dependencies
    • Not even a C library
    • Not even an OS
  • Also an x86 assembler

Inspirations

  • Abdulaziz Ghuloum, An Incremental Approach to Compiler Construction
  • Movitz, a similar thing for Common Lisp
  • Henry Massalin, Synthesis: An Efficient Implementation of Fundamental Operating System Services
Language

?

OS

Fluchtpunkt Lisp

Practical
Kernel
Exo
Pedagogical
 

Dream

I’m dreaming of a clean system,
Small, stable, fast, and trouble-free;
Each component matches,
No bits or patches,
Unlike 7.5.3.
— From an old filk song

Sample code

(do (init-graph)
    (loop [x 0 y 0]
      (put-pixel x y (let [z (mod (+ x y) 32)]
                       (+ 16 (if (> z 15)
                               (- 31 z)
                               z)))))
      (if (= y 200)
        nil
        (if (= x 319)
          (recur 0 (inc y))
          (recur (inc x) y)))))

(compile-program *1)

[cli] [mov :bp :sp] [mov :si :heap-start] [add :si 7] [and :si 65528] [jmp :g__1327] :g__1327 [mov :ax 19] [int 16] [mov :ax 40960] [mov :es :ax] [mov :ax 0] [mov [:bp -2] :ax] [mov :ax 0] [mov [:bp -4] :ax] :g__1328 [mov :cx :di][mov :ax [:bp -4]] [sal :ax 4] [mov :di :ax] [sal :ax 2] [add :di :ax] [mov :ax [:bp -2]] [sar :ax 2] [add :di :ax] [mov :ax 128] [sar :ax 2] [mov [:bp -6] :ax] [mov :ax [:bp -4]] [mov [:bp -8] :ax] [mov :ax [:bp -2]] [add :ax [:bp -8]] [mov :dx 0] [sar :ax 2][div [:bp -6]] [mov :ax :dx] [sal :ax 2] [mov [:bp -6] :ax] [mov :ax 64] [mov [:bp -8] :ax] [mov :ax [:bp -6]] [xor :bx :bx] [cmp :ax [:bp -8]] [setb :bl] [mov :ax :bx] [sal :ax 7] [or :ax 31] [cmp :ax 31] [je :g__1337] [cmp :ax 47] [je :g__1337] ;; etc.

(asm *1)

[250 137 229 190 60 2 129 198 7 0 129 230 248 255 233 0 0 184 19 0 205
16 184 0 160 142 192 184 0 0 137 70 254 184 0 0 137 70 252 137 249 139
70 252 193 224 4 137 199 193 224 2 1 199 139 70 254 193 248 2 1 199
184 128 0 193 248 2 137 70 250 139 70 252 137 70 248 139 70 254 3 70
248 186 0 0 193 248 2 247 118 250 137 208 193 224 2 137 70 250 184 64
0 137 70 248 139 70 250 49 219 59 70 248 15 146 211 137 216 193 224 7
129 200 31 0 61 31 0 116 20 61 47 0 116 15 139 70 250 137 70 248 184
64 0 3 70 248 233 21 0 139 70 250 137 70 248 184 124 0 43 70 248 137
70 248 184 64 0 3 70 248 193 248 2 170 137 207 184 32 3 137 70 250 139
70 252 59 70 250 117 6 184 159 0 233 3 0 184 31 0 61 31 0 116 11 61 47
0 116 6 184 47 0 233 96 0 184 252 4 137 70 250 139 70 254 59 70 250
117 6 184 159 0 233 3 0 184 31 0 61 31 0 116 38 61 47 0 116 33 184 0 0
137 70 250 139 70 252 5 4 0 137 70 248 139 94 250 137 94 254 139 94
248 137 94 252 233 15 255 233 30 0 139 70 254 5 4 0 137 70 250 139 70
252 137 70 248 139 94 250 137 94 254 139 94 248 137 94 252 233 238 254
233 253 255]

(run! *1)

if

(defn compile-if
  [test-expr then-expr else-expr si env rp]
  (let [l0 (genkey) l1 (genkey)]
    (codeseq
     (compile-expr test-expr si env rp)
     ['cmp :ax (immediate-rep false)]
     ['je l0]
     ['cmp :ax (immediate-rep nil)]
     ['je l0]
     (compile-expr then-expr si env rp)
     ['jmp l1]
     l0
     (compile-expr else-expr si env rp)
     l1)))

What Lithium has

  • Basic compiler/assembler infrastructure
  • Some primitives: if, =, < etc
  • Closures (fn)
  • let, loop/recur

What Lithium doesn't (yet) have

  • Everything else
  • No I/O of any kind
  • No global environment (so no def, defn etc)
  • No datatypes other than integer and boolean
  • No GC
  • No macros
  • No concurrency
  • No ponies

Is Lithium a Clojure?

NO

On the other hand...

  • Lithium is written in Clojure
  • And it will compile itself one day

Come to think of it,
what is  Clojure?

Is...

  • ClojureCLR
  • ClojureScript
  • clojure-py
  • CinC


...Clojure?

Key takeaways

  • It's not as hard as it may seem
  • Start small, grow organically
  • loop/recur rocks

Questions?

(doseq [you (audience)]
  (thank! you))

Daniel Janus
@nathell
http://github.com/nathell/lithium