LumiScript is a small language and bytecode toolchain for describing keyboard backlight behavior. It includes a host-side compiler, a reusable C library, and a static-memory VM designed to stay compatible with MCU-style deployment constraints.
Scripts are compiled from .lumi source into .lbc bytecode, then executed through a three-stage runtime model:
init: runs once when the effect is loaded or resetupdate: runs once per backlight tickrender: runs once per key and produces the final color
The compiler is free to allocate memory on the host, while the VM is designed around caller-provided fixed storage so it can reject scripts that do not fit available static memory before execution starts.
Important
Please note that this is an alpha project.
The core language, bytecode format, and VM are implemented and tested, but the system is still evolving and should be treated as experimental.
meson setup build
meson compile -C build./build/lumic examples/example-static.lumi -o build/example-static.lbc./build/lumivm build/example-static.lbc
init
render 0 0 0 16 1 0 0Example output:
init steps=1
render key=0 color=0x96C8FF steps=6
Example:
type animation
global var phase = 0
key var glow = 0
update {
phase = phase + dt * speed
}
render {
if pressed {
glow = 100
} else {
glow = clamp(glow - dt * 0.3, 0, 100)
}
color hsv(phase + x * 2, 100, glow)
}
Supported concepts include:
type staticandtype animationglobal varandkey var- section-local
let - assignments
- statement and expression
if - float-based arithmetic and boolean semantics
- builtins such as
abs,sin,cos,sqrt,ceil,floor,round,clamp,dist,lerp,min,max,pow,rand,rgb, andhsv
Compiles a Lumi source file into serialized bytecode.
./build/lumic input.lumi -o output.lbcUse -O, -O0, -O1, -O2, or -O3 to choose an optimization level:
./build/lumic -O2 input.lumi -o output.lbcHigher levels enable constant folding, expression simplification, bytecode cleanup, dedicated builtin opcodes, and conservative common-subexpression elimination.
Loads bytecode into fixed-capacity host buffers, checks whether it fits, then executes commands from stdin.
./build/lumivm build/example-static.lbcSupported commands:
initresetupdate <dt> <speed>render <key> <x> <y> <dt> <speed> <pressed> <press>
Example interactive session:
init
update 50 2
render 0 3 4 50 2 0 0
render 1 30 40 50 2 1 100
You can also force capacity checks with smaller limits:
./build/lumivm --stack-cap 1 build/example-static.lbcThe repository also includes a small stdio language server with diagnostics, hover, completion, and document symbols.
It is built together with the rest of the project:
meson setup build
meson compile -C buildProject documentation lives in the repository:
- Language Guide: LANGUAGE.md
- Bytecode Format: BYTECODE.md
Practical scripts live in examples/:
examples/example-static.lumiexamples/example-animation.lumiexamples/example-conditional.lumiexamples/example-counter.lumiexamples/example-stateful.lumiexamples/example-nested.lumiexamples/example-math.lumiexamples/example-ripple.lumiexamples/example-aurora.lumiexamples/example-meteors.lumi
Run the full suite with:
meson test -C build --print-errorlogsThe current tests cover:
- successful compilation of example scripts
- compile-time failure cases
- host VM execution results
- bytecode golden checks
- static-capacity rejection paths
Requirements:
- Meson
- Ninja
- a C11 compiler
Typical build flow:
meson setup build
meson compile -C build
meson test -C build --print-errorlogsContributions are welcome.
Useful reports and patches include:
- compiler or VM bugs
- language design improvements
- documentation fixes
If you report an issue, include:
- the
.lumiscript - the command you ran
- the exact compiler or VM output
- whether the failure is in parsing, compilation, loading, or execution