Skip to main content
LispBM is a small Lisp dialect designed for microcontrollers. This page covers the language features most relevant to VESC scripting. For the complete upstream language specification, see the LispBM language reference.

Basic syntax

LispBM uses the standard Lisp S-expression syntax. Everything is either an atom or a list. A list whose first element is a function or special form is a call expression.
Expressions are evaluated — the result of an expression is its value. The REPL prints the result of each top-level expression.

Data types

LispBM supports integer and floating-point literals. Integers are 28-bit signed values by default. Use the f32 suffix for single-precision floats and f64 for doubles.
Symbols are identifiers. When quoted with ', a symbol is a value in itself rather than a variable reference. VESC extensions use quoted symbols as named parameters.
t is true and nil is false (also the empty list). Many predicates return nil for false and a non-nil value for true.
Lists are the fundamental compound type. cons builds a pair, car extracts the head, cdr extracts the tail, and list creates a list from arguments.
String literals are double-quoted. The string extensions (loaded automatically) provide formatting and manipulation functions.
Byte arrays are mutable fixed-size buffers. They are used for CAN payloads, UART data, and other binary operations.

Variables and binding

Use define for top-level bindings and let for local bindings.
Use setvar to mutate an existing binding:

Control flow

if

cond

cond tests multiple conditions in order and evaluates the first branch whose condition is true:

and / or

loop (loopwhile / loopfor / looprange)

The most common loop form for VESC scripts is loopwhile, which runs until its condition becomes false:
loopfor and looprange are available for counted iterations:
progn sequences multiple expressions and returns the value of the last one:

Functions and closures

Define functions with defun or lambda:
LispBM supports closures — lambdas capture their defining environment:

Recursion

LispBM supports proper tail-call optimization for tail-recursive functions:
Deep non-tail recursion will exhaust the LBM stack. Prefer loopwhile for long-running iteration in VESC scripts.

Concurrency

LispBM supports cooperative multitasking via spawn:
Spawned threads share the same heap. Use mutex from the mutex extensions to protect shared state.

LBM Image support

For applications where fast startup is critical, the firmware supports LBM Images — pre-compiled snapshots of the heap stored in flash. On boot the image is restored rather than the script being re-evaluated from source, which eliminates startup latency.
LBM Image support requires firmware 6.00 or newer on ESC hardware. The image is generated automatically when the script is uploaded via VESC Tool.

Upstream documentation

This page covers the subset of LispBM most commonly used in VESC scripts. The full language reference — including all built-in operators, the type system, and the standard libraries — is available at: