I guess I wrote a scripting language or something.
I recently found the need for a very small scripting language. I wanted something with a very small VM, short startup time, threadsafe between different contexts, and ideally no default bindings to the outside world (or at least ones that can be disabled, like how JS in SpiderMonkey can be used without any of the default functions or objects).
I want this for a 3D game I'm working on. I want to be able to spin up an arbitrary number of script threads, which will run many very small scripts. Thread-safety will be handled by the engine itself (this probably deserves its own post). Memory use and performance should be as deterministic as possible; GC should be minimal if at all, and JITs would need to be very conservative.
I browsed several scripting languages, including Io, Python, Lua, some Lisps, JS, and Ruby. I eventually decided that none of these did what I needed. Io and Lua were the closest, but still missed the mark. Io is way too much trouble to compile, and Lua is not as deterministic as I want (although it is quite fast).
So I wrote my own very small language. It's called DLCL, for DarkLight Command
Language (the game is temporarily named DarkLight). Since I know exactly how it
will be used, I was able to enforce some pretty strict constraints on the
language and implementation, and the VM is both rather quick and has constant
I decided that I would just put hard caps on all memory usage. Each VM instance
takes slightly more than 1 MB, and only ever takes that much. 128 K of token
memory, 512 K of runtime string memory, and 128 K of runtime variable memory.
Once those arenas are full, the VM will OOM. That's that. But since I know exactly what scripts will run, and scripts will be completley consistent in their memory usage, this actually isn't too big an issue. Plus, having such excellent memory locality makes almost all operations quite quick.
The VM is also fairly good about reclaiming variable and string memory on function and scope exit, although returning strings will cause leaks. This is a fairly easily fixable problem, but I haven't done anything about it yet.
The language features a few niceties, too. Functions are first class objects, the language is statically typed, has const variables, scripts can be pre-compiled to a sort of bytecode (more like a fortified lexer output). It's also almost homoiconic. Almost, but not really. The VM also satisfies my threading needs: as long as you use different parser contexts, there are no threading issues.
The best part is that all this fits in under 2000 lines of code. It's also got a fairly decent test suite, which conveniently doubles as some language and embedding examples.
You can check out the source on github: https://github.com/FlyingJester/dlcl