- C 98.7%
- Makefile 1.3%
| assets | Initial commit fr | |
| examples | ADD [v0.3.0]: Refactor memory management and enhance error handling + changing file extension to <file>.vlsp -> <file>.vl | |
| src | ADD [v0.3.2]: New performance updates with bytecode + VM for vlisp | |
| .gitignore | ADD [v0.3.2]: New performance updates with bytecode + VM for vlisp | |
| LICENSE | Initial commit | |
| Makefile | ADD [v0.3.2]: New performance updates with bytecode + VM for vlisp | |
| README.md | FIX [v0.3.1]: Fixing README.md release flag | |
| vlisp.h | ADD [v0.3.2]: New performance updates with bytecode + VM for vlisp | |
The Vanguard Lisp — a lightweight, embeddable functional language written in C.
vLisp is a minimal Lisp dialect designed to be embedded in C projects. It features a clean functional core, optional static type annotations, first-class functions, and a tiny footprint — making it ideal as a scripting or configuration layer for C applications.
Features
- Functional core — lambdas, closures, currying, and partial application
- Optional type annotations — gradual typing with compile-time-like checking at runtime
- Higher-order functions —
map,filter,foldl,apply,compose,flip,const - Tail-call optimization —
if,cond,let,letrec, andbeginall support TCO - Lexically scoped environments — closures capture their defining environment
- REPL and file execution — run scripts or explore interactively
- Simple runtime allocation — runtime objects use standard heap allocation for predictable desktop performance
- Easy to embed — the entire interpreter fits in a handful of
.cfiles with a single header
Building
vLisp requires a C11-compatible compiler, the standard C library, libm for math builtins, and readline for the interactive REPL.
The default release build is balanced for speed and size (-Os, LTO, dead-section elimination, and stripping):
make release
For a speed-focused build:
make fast
For debug builds:
make debug
Manual build equivalent:
cc -std=c11 -Wall -O2 -flto -ffunction-sections -fdata-sections \
src/value.c src/env.c src/parser.c src/eval.c src/builtins.c src/main.c \
-Wl,--gc-sections -lm -lreadline -o vlisp
Installing
Build vLisp before installing:
make release
To use the freshly built binary from the project directory without installing it system-wide:
./vlisp
./vlisp examples/ex.vl
To install the vlisp executable into /usr/local/bin:
sudo make install
After that, vlisp should be available from your shell:
vlisp
vlisp examples/ex.vl
If /usr/local/bin is not in your PATH, add it in your shell configuration or install to a prefix that already is:
make install PREFIX="$HOME/.local"
For package builds or staged installs, use DESTDIR:
make install DESTDIR="$PWD/pkg" PREFIX=/usr
To remove an installed binary from the selected prefix:
sudo make uninstall
Use the same PREFIX when uninstalling if you installed somewhere other than /usr/local:
make uninstall PREFIX="$HOME/.local"
Usage
Interactive REPL
./vlisp
vLisp v0.3.0 - The Vanguard Lisp
Type (quit) or Ctrl+D to exit.
vlisp> (+ 1 2)
3
vlisp> (define (square n) (* n n))
<lambda>
vlisp> (square 7)
49
Run a script file
./vlisp examples/ex.vl
Language Reference
Primitive Types
| Type | Example | Description |
|---|---|---|
Int |
42, -7 |
64-bit signed integer |
Float |
3.14, -0.5 |
IEEE 754 double |
Bool |
#t, #f |
Boolean |
String |
"hello" |
Immutable string |
Nil |
nil |
Empty / unit value |
List |
(list 1 2 3) |
Singly-linked cons list |
Special Forms
define — bind a name or define a function
(define x 10)
(define (square n)
(* n n))
Common Lisp-style definitions are also accepted:
(defvar x 10)
(defparameter y 20)
(defun square (n) (* n n))
lambda — anonymous function
(lambda (x y) (+ x y))
; with parameter type annotation
(lambda ((n Int)) (* n n))
if — conditional (tail-call optimized)
(if (> x 0) "positive" "non-positive")
cond — multi-branch conditional
(cond
((< n 0) "negative")
((= n 0) "zero")
(else "positive"))
let — local bindings
(let ((x 3)
(y 4))
(+ x y))
letrec — mutually recursive local bindings
(letrec ((fact (lambda (n)
(if (<= n 1)
1
(* n (fact (- n 1)))))))
(fact 6))
begin — sequential evaluation
(begin
(define x 1)
(define y 2)
(+ x y))
progn is available as a Common Lisp-compatible alias.
quote / ' — suppress evaluation
'(1 2 3)
(quote hello)
set! — mutate an existing binding
(set! x 99)
setq is available as a Common Lisp-compatible alias.
function — refer to a function value
(apply (function +) (list 1 2 3))
Type Annotations
vLisp supports optional, gradual type annotations via the : form. Type errors are caught at runtime before evaluation proceeds.
(: answer Int)
(define answer 42)
(: inc (-> Int Int))
(define (inc n) (+ n 1))
(: xs (List Int))
(define xs (list 1 2 3))
Type syntax:
| Annotation | Meaning |
|---|---|
Int |
Integer |
Float |
Floating-point |
Bool |
Boolean |
String |
String |
Nil |
Nil / empty |
Number |
Int or Float |
Any |
Unconstrained |
(List T) |
List of T |
(-> T1 T2 Ret) |
Function from T1, T2 → Ret |
Arithmetic
(+ 1 2 3) ; => 6
(- 10 3) ; => 7
(* 4 5) ; => 20
(/ 10 2) ; => 5 (integer division when both are Int)
(/ 10 3.0) ; => 3.333...
(mod 10 3) ; => 1
(abs -7) ; => 7
(sqrt 2.0) ; => 1.4142...
Comparison & Logic
(= 1 1) ; => #t
(< 2 5) ; => #t
(>= 3 3) ; => #t
(not #f) ; => #t
(and #t #t) ; => #t
(or #f #t) ; => #t
List Operations
(cons 1 (list 2 3)) ; => (1 2 3)
(car (list 1 2 3)) ; => 1
(cdr (list 1 2 3)) ; => (2 3)
(head (list 1 2 3)) ; => 1 (alias for car)
(tail (list 1 2 3)) ; => (2 3) (alias for cdr)
(first (list 1 2 3)) ; => 1
(rest (list 1 2 3)) ; => (2 3)
(second (list 1 2 3)) ; => 2
(third (list 1 2 3)) ; => 3
(nth 1 (list 1 2 3)) ; => 2
(last (list 1 2 3)) ; => 3
(list 1 2 3) ; => (1 2 3)
(length (list 1 2 3)) ; => 3
(null? nil) ; => #t
(null nil) ; => #t
(empty? nil) ; => #t
(append (list 1 2) (list 3 4)) ; => (1 2 3 4)
(reverse (list 1 2 3)) ; => (3 2 1)
(member 2 (list 1 2 3)) ; => (2 3)
(assoc 'b (list (cons 'a 1) (cons 'b 2))) ; => (b . 2)
(range 5) ; => (0 1 2 3 4)
(range 1 6) ; => (1 2 3 4 5)
(range 0 10 2) ; => (0 2 4 6 8)
Higher-Order Functions
(map (lambda (n) (* n n)) (list 1 2 3 4))
; => (1 4 9 16)
(filter (lambda (n) (> n 2)) (list 1 2 3 4))
; => (3 4)
(foldl + 0 (list 1 2 3 4 5))
; => 15
(apply + (list 1 2 3 4 5))
; => 15
(apply + 1 2 (list 3 4))
; => 10
Functional Combinators
Currying & Partial Application
Functions in vLisp support partial application automatically — calling a function with fewer arguments than it expects returns a new function.
(define add (lambda (x y) (+ x y)))
(define add5 (add 5))
(add5 10) ; => 15
compose — function composition (right to left)
(define f (compose
(lambda (x) (* x 2))
(lambda (x) (+ x 3))))
(f 10) ; => 26 — (10+3)*2
flip — swap first two arguments
((flip -) 3 10) ; => 7 — (10 - 3)
const — constant function
((const "always this") 99) ; => "always this"
id — identity function
(id 42) ; => 42
Type Predicates
(int? 1) ; => #t
(integerp 1) ; => #t
(float? 1.0) ; => #t
(floatp 1.0) ; => #t
(numberp 1.0) ; => #t
(bool? #t) ; => #t
(booleanp #t) ; => #t
(string? "hi") ; => #t
(stringp "hi") ; => #t
(symbolp 'hi) ; => #t
(list? (list)) ; => #t
(listp nil) ; => #t
(consp (cons 1 nil)) ; => #t
(atom 'x) ; => #t
(null? nil) ; => #t
(empty? nil) ; => #t
(zerop 0) ; => #t
(plusp 10) ; => #t
(minusp -1) ; => #t
(evenp 4) ; => #t
(oddp 5) ; => #t
Type Conversions
(int->float 3) ; => 3.0
(float->int 3.9) ; => 3
(to-string 42) ; => "42"
Strings
(str-len "hello") ; => 5
(str-concat "foo" "bar") ; => "foobar"
(to-string 3.14) ; => "3.14"
I/O
(print "hello") ; prints without newline
(println "hello") ; prints with newline
(println 1 2 3) ; => 1 2 3
Constants
| Name | Value |
|---|---|
#t |
Boolean true |
#f |
Boolean false |
nil |
Empty / nil |
NIL |
Empty / nil |
t / T |
Boolean true |
pi |
3.14159265358979... |
Embedding in C
vLisp is designed to be embedded. The full public API is declared in vlisp.h, and the default allocator uses the standard C heap for runtime objects.
#include "vlisp.h"
int main(void) {
Env *env = env_new(NULL);
register_builtins(env);
// Evaluate a string
Value *exprs = parse_all("(define (square n) (* n n)) (square 9)");
Value *cur = exprs;
Value *result = NULL;
while (cur && cur->type == TYPE_CONS) {
result = eval(cur->cons.head, env);
cur = cur->cons.tail;
}
println_value(result); // => 81
return 0;
}
Adding custom builtins
static Value *my_hello(Value *args, Env *env) {
(void)args; (void)env;
printf("Hello from C!\n");
return make_nil();
}
// Register it
env_set(env, "hello!", make_builtin(my_hello));
Example Script
; examples/ex.vl
(: answer Int)
(define answer 42)
(println answer)
(: inc (-> Int Int))
(define (inc n) (+ n 1))
(println (inc 9))
(define square (lambda ((n Int)) (* n n)))
(println (square 7))
; Partial application
(define add (lambda (x y) (+ x y)))
(define inc2 (add 2))
(println (inc2 40))
; Local recursion with letrec
(letrec ((fact
(lambda ((n Int))
(if (<= n 1)
1
(* n (fact (- n 1)))))))
(println (fact 6)))
; Functional pipeline
(define nums (range 1 8))
(println (map square nums))
(println (filter (lambda ((n Int)) (>= n 4)) nums))
(println (foldl + 0 nums))
; Combinators
(define twice (compose (lambda (x) (* x 2))
(lambda (x) (+ x 3))))
(println (twice 10))
(println ((flip -) 3 10))
(println ((const "always this") 99))
(println (apply + (list 1 2 3 4 5)))
Project Structure
vlisp/
├── vlisp.h — Public API and type definitions
├── src/
│ ├── value.c — Value constructors, type system, printing
│ ├── env.c — Lexical environment (symbol tables)
│ ├── parser.c — Lexer and S-expression parser
│ ├── eval.c — Evaluator with TCO and type checking
│ ├── builtins.c — Standard library of built-in functions
│ └── main.c — REPL and file execution entry point
└── examples/
├── ex.vl — Example script
├── compat.vl — Common Lisp compatibility smoke test
└── sqrt.vl — Integer square-root example
Limitations
- No garbage collection — runtime objects are heap allocated and are not reclaimed individually
- Environment capacity is fixed at 128 bindings per scope (
ENV_CAPACITY) - List/array operations use fixed-size internal buffers (512 elements for
map,filter,append, etc.) - No tail-call optimization for
foldlormap(these are iterative internally) - No macro system
License
MIT License — Copyright (c) 2026 grassleaff. All Rights Reserved.