Getting Started
Building
Build-time requirements:
gccorclang- standard C library +
libm make- For first-time
libffibootstrap:autoconf,automake,libtool,libtool-bin,libltdl-dev,pkg-config,m4,texinfo(Debian/Ubuntu names; equivalent on other distros). These are not needed oncelibffi/has been built once.
Three submodules are vendored under the repo root: linenoise/ (REPL
editing), mir/ (JIT backend), and libffi/ (FFI marshalling). All
three are built statically and linked into the sel binary — no system
runtime dependencies beyond libc.
git clone --recurse-submodules https://github.com/Luca00casati/sel.git
cd sel
make
If you already cloned without --recurse-submodules:
git submodule update --init
make produces a single sel binary. The standard library
(core.sel) is a plain source file — sel loads it on demand via
(load "core.sel"), so the working directory needs access to it.
Optional extras
make raylib-bindingregeneratesgen_raylib.selfrom/usr/include/raylib.husinggenffi.py. Requirespython-clang(libclang Python bindings) and raylib’s dev headers.
Running the REPL
Launch the interactive REPL by invoking sel with no arguments:
$ ./sel
sel repl (ctrl+d to exit)
sel> (+ 1 2)
3
sel> (let x 10)
10
sel> (* x x)
100
sel>
The REPL is multi-line aware: if you open a parenthesis and press Enter
without closing it, the prompt switches to ...> and keeps accumulating input
until the expression is balanced.
sel> (let add
...> (fn (a b) (+ a b)))
#<closure>
sel> (add 3 4)
7
Load the standard library explicitly when you need it:
sel> (load "core.sel")
After that, core macros and functions (map, filter, list3, etc.) are
available.
State persists across expressions — bindings and functions defined with let
and fn remain available for the rest of the session.
Exit the REPL with Ctrl+D (EOF).
Running a File
Pass one or more .sel files as arguments:
./sel program.sel
./sel lib.sel program.sel # lib.sel is loaded first
All top-level expressions are evaluated in order across all files. The value of
the last expression is printed as Result: <value>.
; hello.sel
(println "Hello, world!")
(+ 1 1)
$ ./sel hello.sel
Hello, world!
Result: 2
Flags
| Flag | Effect |
|---|---|
--no-jit |
Disable the JIT compiler; run purely in the interpreter |
--dump-ast <file> |
Print the AST of a file and exit (no execution) |
--dump-inst <file> |
Compile a file and print its bytecode disassembly; useful for inspecting compiler output |
./sel --no-jit program.sel # interpreter only, no JIT
./sel --dump-ast program.sel # inspect parse tree
./sel --dump-inst program.sel # inspect bytecode
First Program
; sum of 1..100
(let sum
(fn sum (n acc)
(if (= n 0)
acc
(sum (- n 1) (+ acc n)))))
(println (sum 100 0))
Save as sum.sel and run:
$ ./sel sum.sel
5050
Result: 5050