Features

This page is a catalog of Lambda C's capabilities and APIs. For internal design — the 4-byte instruction format, FFI linking mechanism, three-stack model, hot-reload, and design rationale — see Architecture.

Language Features

Supported

Supported (Preprocessor)

Not Supported

FFI System

Function Registration

// Basic registration (returns negative ID starting from -1000)
int lcvm_register_function(const char *name, lcvm_ffi_func_t func, int arg_count);

// Registration with type signature (type checking in DEBUG builds)
int lcvm_register_function_ex(const char *name, lcvm_ffi_func_t func,
                               int arg_count, const char *signature);

// Find function by name (for manual linking)
int lcvm_ffi_find_by_name(const char *name, int *arg_count);

// Automatic linking (called after bytecode load)
int lcvm_link_program(compact_program_t *prog);

Type Signatures

Signature characters for lcvm_register_function_ex():

CharacterType
iint
ddouble
ffloat
ppointer
sstring
// Example: function taking int and double
lcvm_register_function_ex("add", ffi_add, 2, "id");

// Example: function taking two pointers
lcvm_register_function_ex("memcpy", ffi_memcpy, 2, "pp");

Type mismatch log output example:

FFI add: arg 0 type mismatch (expected i, got pointer)

FFI Function Signature

typedef void (*lcvm_ffi_func_t)(LcvmState *vm);

// Push return value to stack
void lcvm_push_int(LcvmState *vm, int32_t value);
void lcvm_push_double(LcvmState *vm, double value);

// Pop arguments from stack (in reverse order)
int32_t lcvm_pop_int(LcvmState *vm);
double lcvm_pop_double(LcvmState *vm);

Example: Multi-argument FFI

// Script: result = add(10, 20.5);
static void ffi_add(LcvmState *vm) {
    double b = lcvm_pop_double(vm);  // 20.5
    int32_t a = lcvm_pop_int(vm);    // 10
    lcvm_push_double(vm, a + b);     // 30.5
}

lcvm_register_function_ex("add", ffi_add, 2, "id");

Memory Management

Memory Layout

Flash/ROM (Read-only)

RAM (Writable)

Heap Watermark API

Ideal for temporary bulk memory allocation and batch release patterns:

// Record current heap position
size_t mark = lcvm_heap_mark();

// Allocate temporary memory
char *buf = lcvm_malloc(64 * 1024);
// ... processing ...

// Batch release to mark position (O(1), no fragmentation)
lcvm_heap_release(mark);

Also available from scripts:

int mark = heap_mark();
// ... temporary processing ...
heap_release(mark);

Cortex-M0+ (32KB RAM)

#define VM_STACK_SIZE   (8 * 1024)   /* 8KB */
#define VM_GAREA_SIZE   (8 * 1024)   /* 8KB */
#define VM_HEAP_SIZE    (12 * 1024)  /* 12KB */

Cortex-M4 with FPU (64KB RAM)

#define VM_STACK_SIZE   (16 * 1024)  /* 16KB */
#define VM_GAREA_SIZE   (16 * 1024)  /* 16KB */
#define VM_HEAP_SIZE    (24 * 1024)  /* 24KB */

Hardware FPU (FPv4-SP) support enables fast floating-point operations.

RISC-V RV32 (RV32IMC)

#define VM_STACK_SIZE   (8 * 1024)   /* 8KB */
#define VM_GAREA_SIZE   (8 * 1024)   /* 8KB */
#define VM_HEAP_SIZE    (12 * 1024)  /* 12KB */

Open ISA. Supports Integer, Multiply, and Compressed instruction sets.

ESP32 (320KB RAM)

#define VM_STACK_SIZE   (32 * 1024)  /* 32KB */
#define VM_GAREA_SIZE   (32 * 1024)  /* 32KB */
#define VM_HEAP_SIZE    (128 * 1024) /* 128KB */

Static Type Mode

Compile with -Os to omit stack-side type tracking. Achieves ~2x speedup for integer-heavy programs.

lcvmc -Os -oc output.lcbc source.c

Limitations:

For benchmarks and the technical background, see Architecture.

Debug Support Features

Watchpoint Feature

Automatic detection of global variable modifications:

Watch range is specified by an offset and size into garea (size must be 1, 2, 4, or 8).

// Enable: build with LCVM_WATCH_ENABLED=1

// Add watch targets (up to 8)
lcvm_watch_add(&vm, hp_offset,    sizeof(int), "player_hp");
lcvm_watch_add(&vm, state_offset, sizeof(int), "game_state");

// Clear watches
lcvm_watch_clear(&vm);

Writes that overlap a watched range are automatically logged.

GDB Pretty Printer

Load tools/gdb_lcvm.py to display VM state in human-readable format within GDB:

(gdb) source tools/gdb_lcvm.py
(gdb) p vm
$1 = LcvmState { pc=42, sp=8, error=NONE, ... }

Shows call stack, registers, and opcode details on error.

Postmortem Tool

Ideal for crash analysis in embedded environments:

Writes the dump into a buffer and returns the byte count (minimum 24 bytes). The caller forwards the buffer to storage or transport.

// Output binary dump on host side
unsigned char buf[256];
int len = lcvm_dump_diagnostic_binary(&vm, buf, sizeof(buf));
// e.g. forward buf to Flash / serial / file
# Analyze on PC
python tools/lcvm_postmortem.py crash.bin

Simulator SDK

Framework for rapidly building domain-specific simulators.

Minimal Configuration

Implement a simulator with just 2 callback functions:

void on_init(LcvmState *vm, void *user) {
    // Register FFI functions (with type signature)
    lcvm_register_function_ex("set_motor",  ffi_set_motor,  2, "ii");
    lcvm_register_function_ex("get_sensor", ffi_get_sensor, 1, "i");
}

void on_frame(LcvmState *vm, float dt, void *user) {
    // Physics simulation
    update_physics(dt);
    // Rendering
    render_scene();
}

Implementation Example

demos/raylib_drone/ — RayLib-integrated drone delivery simulator. See Drone Demo for the full walkthrough.

Safety Features

Watchdog Timer

Sandbox Mode

Error Handling