Tending to a small lisp ◯
Find a file
Børge Lundsaunet 3f8d1ed47a taiji: remove join
turns out we already had it lol
2026-01-25 00:44:34 +01:00
editor load binary and library locally for development 2026-01-15 16:49:44 +01:00
examples update documentation 2026-01-15 16:50:01 +01:00
src wuji: add 64 bit int types for ffi 2026-01-21 20:04:37 +01:00
taiji taiji: remove join 2026-01-25 00:44:34 +01:00
.dir-locals.el use local wuji-mode for development 2026-01-15 16:50:20 +01:00
.envrc load binary and library locally for development 2026-01-15 16:49:44 +01:00
.gitignore ignore db files 2025-12-12 02:42:46 +01:00
flake.lock delete old jit code 2025-12-01 19:56:06 +01:00
flake.nix flake: cleanup 2026-01-15 18:09:05 +01:00
Makefile taiji: start working on raylib bindings 2026-01-20 15:40:28 +01:00
README.org there are no secrets 2025-12-14 23:48:21 +00:00

Wuji ◯

Tàijí is born from wújí. It is the mother of yīn and yáng.

Tàijí Classic (ii), Wang TsungYueh

About

Wuji is a lisp implemented in C. It is heavily inspired by Clojure and its excellent design decision. A goal for Wuji is to have a small interpreter, with as much functionality as possible implemented as library code. Wuji features C ffi via libffi. This is used for implementing bindings for sqlite and microhttpd in userland.

Examples

Here are a couple of examples of Wuji code:

Working with strings:

  ;; Splitting and joining
  (join " " (split "1-2-3" "-"))
  ; => "1 2 3"

  ;; Generic formatting function
  (format "Map: {}, Array: {}, String: {}" {:a 1 :b} [1 2 3] "Hello!")
  ; => "Map: {:a 1 b 2}, Array: [1 2 3], String: Hello!"

  ;; f-string macro
  (def name "Børge")
  (f "My name is {name}")
  ; => "My name is Børge"

Sqlite queries:

  (def db (sqlite/open ":memory:"))

  ;; Create a table
  (sqlite/exec db "CREATE TABLE languages(id INTEGER PRIMARY KEY, name TEXT);")
  ; => {:sqlitedb <c-ptr:0x2f1a1d88> :name ":memory:" :rc 0}

  ;; Insert some data
  (sqlite/exec db "INSERT INTO languages (name) VALUES ('C'), ('Clojure'), ('Wuji');")
  ; => {:sqlitedb <c-ptr:0x2f1a1d88> :name ":memory:" :rc 0}

  ;; Read data out as an array of maps
  (sqlite/query db "SELECT * FROM languages")
  ; => [{:id "1" :name "C"} {:id "2" :name "Clojure"} {:id "2" :name "Wuji"}]

  ;; Close the db
  (sqlite/close db)

Running a web server:

  ;; Define a handler function
  (defn handler [cls conn url method version upload-data upload-data-size con-cls]
    (cond
      (= url "/")
        (http/html conn "Hello world!")
      :else
        (http/not-found conn)))

  ;; Start the server
  (def port 8080)
  (def server (http/start port handler))

  ;; The handler can be redefined live in the repl!
  (defn handler [cls conn url method version upload-data upload-data-size con-cls]
     (http/html conn "Hello brand new world!"))

Building

Wuji and its standard library is tested and works on Mac and Linux.

In order to build Wuji, you need Nix with Nix Flakes enabled. Read the Nix wiki for more info.

To make sure everything works, you can run the following

  # Build the application
  nix build
  # Run the tests
  make test

If that works, you can try out the web server!

  ./result/bin/wuji examples/web-server.wu

You can now go to localhost:8080 and you should see a web page!

Language features