MiniD
Jarrett Billingsley's 2006 scripting language for embedding in D programs - a Lua-like, dynamically typed language with C-style syntax, Squirrel-style classes, a D-style module system, coroutines and a Pyd-like binding library, written entirely in D 1 on Tango, released as 1.0 in 2007 and 2.0 in 2009, and renamed Croc in 2011
Created by Jarrett Billingsley
MiniD is a small, dynamically typed scripting language created by Jarrett Billingsley in 2006 for embedding in programs written in the D programming language. In the words of its author’s 2011 README it is “a small, dynamically-typed language most closely related to Lua, with C-style syntax” whose “semantics are borrowed mainly from Lua, D, Squirrel, and Io”: a language in the family of Lua and Squirrel, with C-style (and specifically D-style) syntax, single-inheritance classes, a D-like module system, coroutines, first-class functions and closures, garbage collection, and a native API designed so that D code and script code could call each other with as little ceremony as possible. It was written entirely in D 1 on the Tango library, released as version 1.0 on 1 August 2007 and as a reimplemented version 2.0 in June 2009, and in June 2011 was renamed Croc, under which name it was eventually ported to C++ and then abandoned.
The encyclopedia lists MiniD as dormant, which is exactly right. There has been no MiniD release since 2009 and no code under the name since 2011; the Croc continuation received its last code commit on 21 November 2015; and the author’s own README now says “It’s not developed anymore. No one ever used it. But I still love it.” What makes it worth a page is that it was one of the very few complete embeddable scripting languages built for and in D during the D 1 era, and that its entire history - every Subversion commit from 21 June 2006 onward - survives in the open, which is more than can be said for most hobby languages of its generation.
History and origins
A smaller D (2006)
Billingsley announced MiniD to the D community on 25 June 2006, four days after setting up a Subversion repository on dsource.org, the community’s project host. The announcement described “a statically-typed, object-oriented scripting language based on D and designed with D in mind as the host language”, borrowing “static closures, generators, and coroutines” from other scripting languages, with “an almost seamless integration of scripting into the host program” as its central idea: native code should be able to call script code and vice versa without friction. He called it “a sort of for-fun project” that had become a learning project in compiler and virtual-machine design, and hoped that static typing would make “the VM … somewhat faster. Maybe. I hope :)”. He was undecided about the licence - public domain, zlib or MIT - and asked for opinions; zlib/libpng won.
The name was literal: MiniD was to be a stripped-down D. The oldest grammar in the project’s attic still has keywords such as int, float, char, bool, void, cast and def. But, as the later Wikipedia article on the language put it, “after work began on the compiler, the creator … realized just how large a project this language was becoming, and decided to recast the language into something simpler to implement. The result was a Lua-like language with a C-style syntax.” The commit log shows the syntactic phase finished on 16 July 2006 and the original minid.d renamed to compiler.d in mid-August; over the following months the dynamically typed design acquired Squirrel-like classes, a D-like module system and Lua-like cooperative multithreading.
The road to 1.0 (2007)
By 29 June 2007 - “a belated birthday present”, as Billingsley put it - the feature set was frozen as the 1.0 specification. The standard library had been moved from Phobos to Tango, native coroutines had been implemented on Tango’s Fiber class, and a “Pyd-like binding library” was under way that would let a D module be exposed to scripts with a single template instantiation: WrapModule!("foo", WrapFunc!(one), WrapFunc!(two), WrapFunc!(three)). The requirements were a current DMD 1.x and “the latest snapshot of Tango”, on Windows or Linux; there was no Mac build because “GDC is too old to compile it”.
MiniD 1.0 was released on 1 August 2007 (the announcement is timestamped 31 July in the digitalmars archive), “after more than a year of brainstorming, writing, re-writing, taking ideas from other languages and generally having a good time”. The announcement is the best summary of what the language was:
- dynamic typing over booleans, integers, doubles, UTF-32 characters, strings, tables, arrays, functions and classes;
- class-based object orientation with single inheritance and the ability to modify classes at run time;
- C-style syntax with D influences;
- modules and packages, so that larger programs could be organised;
- coroutines, used both for cooperative multithreading and as the basis of iterators;
- sandboxing: multiple contexts, each with its own restricted set of loaded libraries, so that untrusted scripts could be run;
- a templated binding library for exposing native D code;
- an
eval()function.
It shipped with a compiler (minidc), an interactive interpreter (MDCL), a small standard library (base, array, char, I/O, math, OS, regexp, string and table libraries), sample programs and a port of the shootout benchmarks. Derek Parnell’s reaction on the newsgroup - “a gem of a D project” - was typical; Robert Fraser, on “a cursory look”, missed eval() (it was there) and regretted the lack of first-class regular expressions, but called it “an awesome language for scripting within the context of another application, which I guess is the point”.
Version 1.1 followed on 18 November 2007. It was a version bump forced by a bug: fixing super-calls required a breaking change to the code generated for class declarations. The same announcement described the binding library rewritten around chained method calls on a “module/object under construction”, because the Pyd-style variadic templates it had used before “caused it to fail miserably” with the OMF object format of DMD on Windows once a module or class had “more than ten or so members”; it also announced that MiniD 2 had begun, with 1.x to receive “bugfixes and maybe stdlib additions, but no changes to the language itself” - an explicit echo of the D 1 / D 2 split then under way in D itself.
MiniD 2 (2008-2009)
MiniD 2 was a reimplementation, not a revision, and it was reimplemented twice. The commit log for 28 June 2008 reads “Last old MD2 implementation commit!” and then “It’s the new implementation! Yaay!”; a new lexer and parser were working by 18 July, a separate semantic-analysis phase by 22 July, code generation by 24 July, and decorators - Python-style annotations that replaced the earlier attribute tables - by 19 August. During this period Billingsley experimented with a prototype-based object system in place of classes; he defended the idea in the newsgroup discussion of his Tango Conference 2008 talk (“They’re simpler to implement as there is now only one type and one set of lookup rules”; with fully dynamic classes “you’d more or less end up with a prototype-based object system with an arbitrary bifurcation between classes and their instances”), but by 9 November 2008 the log says “We have class-based OO, once again”, and 2.0 shipped with classes.
The big architectural change was memory management. MiniD 1 had simply used the D garbage collector. MiniD 2 got its own allocator and collector (minid.alloc, minid.gc), with weak references, finalizers and per-VM memory accounting, so that a game or other real-time host could control when and how much the script heap was collected - the Wikipedia article summarised version 2 as “a major reimplementation of most of the library in order to support its own garbage collector rather than relying on the underlying D garbage collector, for better behavior in realtime applications such as games”. Around it grew a much larger library: streams, serialization of whole object graphs (including open upvalues and script classes), a StringBuffer, a Vector type, a time library, a debug library with hooks, PCRE regular expressions and an early networking add-on, plus the Arc game-library binding used by the Missile Command and antimatroids samples. In June 2009 the author noted in a commit message that “a few simple changes to the interpreter core resulted in as much as a 25% speedup in execution speed” on his own benchmark programs; no methodology was published, so the figure should be read only as an indication that performance work was happening.
MiniD 2.0 was declared “gold” on 15 June 2009, in a newsgroup thread titled “MiniD 2 - Might as well be done” (“After nearly two years in development, I think I’m ready to call MiniD 2 ‘gold’”); the repository’s “We’re not beta anymoooore” commit is dated 16 June UTC, and the former Wikipedia article gave 15 June in its text and 16 June in its infobox. The release came with Windows binaries and, for the first time, a 32-bit Linux binary of MDCL.
Croc (2011 onward)
Work continued at a lower rate through 2010 and early 2011 on D 1 and Tango, both of which were by then clearly on their way out. On 17 June 2011 Billingsley created a GitHub repository containing the whole Subversion history, and on 18 June added a README for “The Newt Programming Language”: “It used to be called MiniD.” Within hours (“LET’S RENAME AGAIN SINCE SOMEONE ELSE TOOK NEWT”) the name changed again, and the commit of 19 June is “Let’s rename everything to Croc.” The MiniD 1 and 2 trees were parked in a Croc-attic repository “for nostalgic purposes”.
Croc was the same language with the same code, but it left D: from mid-2012 Tango-dependent features were removed because they “won’t be available by default when porting to C++”, and between February and September 2014 the interpreter, compiler and standard library were rewritten in C++11, with GLFW, OpenAL, DevIL and PCRE add-ons. The last code commit was on 21 November 2015; the README edits of 2016 and 2017 closed the book.
Design philosophy
MiniD’s design goals were stated most crisply in the 2011 README that renamed it: a language “most closely related to Lua, with C-style syntax”, whose “semantics are borrowed mainly from Lua, D, Squirrel, and Io”, which “aims to be somewhat unique among dynamically-typed languages by making it as difficult as possible for you, the programmer, to make mistakes”, which “tries to be fast and to make memory allocation the exception rather than the norm”, and which “is meant to be a language that is perfectly capable on its own, but which can be seamlessly integrated into and/or extended by a host language”.
Several concrete choices follow from that:
- Lua semantics, D syntax. Tables, first-class functions, closures, multiple return values, coroutines, a register-based bytecode VM and a stack-based native API are all recognisably Lua’s. The surface, though, is D: braces,
//and nested/+ +/comments,foreach(x; xs),~for concatenation,<=>for three-way comparison,opCmp/toString/opApplymetamethods named as in D, andwriteflnwith Tango’s{}format strings. A D programmer could read MiniD immediately. - No implicit declarations. Every variable is declared with
localorglobal; assigning to an undeclared name is an error rather than the creation of a global, which the Wikipedia article singled out as one of the ways the language guarded against mistakes. - Classes, not prototypes. After the 2008 experiment, MiniD kept Squirrel-style classes with single inheritance, constructors (
this),supercalls and metamethod operator overloading, while still allowing classes and instances to be modified at run time. - Modules as namespaces. Each file is a
module a.b.c, imports create namespaces, andimportis ultimately sugar for calling the module loader - so the same mechanism serves script modules, native modules and sandboxes. - Coroutines everywhere. Generators, iterators and cooperative threads are all
coroutine function()objects withyield; MiniD 2 even supported (optionally) coroutines that could yield across native calls, on top of Tango fibers. - The host is a peer. The native API was written to be as convenient from D as the script side, with the binding library generating wrappers from D types at compile time - in the November 2007 discussion Billingsley argued that being “designed from the ground up to be truly integrated with D”, not any single language feature, was MiniD’s advantage over DMDScript.
The language
MiniD 1 syntax
MiniD 1 required semicolons and looked very much like D. This is the opening of the simple.md sample shipped with 1.0: a class with a constructor, a toString and an opCmp metamethod, and arrays compared element by element.
| |
Functions could return several values and finally blocks ran on every exit path, even nested ones; the same sample checks both:
| |
And factorial.md shows that functions were first-class enough to write a Y combinator:
| |
MiniD 2 syntax
MiniD 2 made semicolons optional, added the function name(args) = expression shorthand, \args -> expression lambdas, array comprehensions, a # length operator, numeric for(i: lo .. hi) loops, ? and ?= null-coalescing operators, decorators, @"verbatim" strings, and optional type constraints on parameters. The markov.md sample (first committed in February 2008 and shipped with 2.0) - a Markov-chain text generator in the style of the one in Programming in Lua - shows most of the everyday syntax, including a coroutine used as a generator:
| |
The beer.md sample compresses the whole of “99 Bottles” into one array comprehension and a lambda:
| |
Parameter type constraints, written name: type, were checked when a function was called, and class itself was a type: the Missile Command sample defines function FreeList(T: class) and methods with this: class so that a mistaken call failed immediately with a clear message rather than somewhere inside the function.
Types
| Type | Notes |
|---|---|
bool, int, float | 64-bit integers and doubles; integer and float arithmetic distinct, as in D |
char | a single UTF-32 code point |
string | immutable, interned, UTF-8 internally in MiniD 2, indexable by character |
table | hash map with any non-null key; {} literal |
array | 0-based, growable, sliceable with ..; [] literal and comprehensions |
function | closures over locals (upvalues); variadic via vararg |
class, instance | single inheritance; metamethods opAdd, opCmp, opIndex, opApply, toString… |
namespace | the object behind modules and globals |
thread | a coroutine, created with coroutine function() {...} |
nativeobj, weakref, funcdef | host objects, weak references and compiled function prototypes (MiniD 2) |
Embedding
From D, a program created a VM, loaded whichever standard libraries it chose to allow (the basis of sandboxing), and either ran files or pushed values onto a Lua-style stack to call script functions. The binding library did the reverse: given D functions, classes or structs, it generated MiniD-visible wrappers at compile time using D’s templates, with polymorphic method dispatch and D properties appearing as MiniD properties. Because the whole thing was D, error messages, exceptions and stack traces crossed the boundary in both directions, which was the point.
Evolution
| MiniD 1.0 (Aug 2007) | MiniD 2.0 (Jun 2009) | Croc (2011-2015) | |
|---|---|---|---|
| Implementation | D 1 + Tango; D garbage collector | D 1 + Tango; own allocator and GC | D 1 until 2014, then C++11 |
| Statement terminators | semicolons required | optional | optional |
| Objects | classes with single inheritance | classes (after a prototype experiment) | classes; later a redesigned object model |
| Notable additions | modules, coroutines, binding library, sandboxing, eval | decorators, serialization, streams, PCRE, netlib, type constraints, comprehensions, lambdas | memblocks, doc comments, GLFW/OpenAL/DevIL add-ons |
| Tooling | minidc, MDCL | minidc, MDCL with embeddable console | single croc executable |
Community and current relevance
MiniD’s community was the D 1 community of 2006-2011, and it was small: a dsource forum, an IRC channel (#d.minid on freenode), a handful of contributors named in the commit log (Tom S of team0xf patched the binding library in 2009; Ligustah, elite01, Brix, HeiHon and csauls reported or fixed bugs), and a 2008 conference talk. Several people said they intended to use it in projects, but no shipped product that embedded MiniD has been identified in the sources consulted for this page, and the author’s own verdict - “No one ever used it” - should be taken at face value.
There is no packaged way to run MiniD today. The language needs a D 1 compiler and a Tango snapshot of the right vintage, both of which are museum pieces; dsource.org, where the documentation and downloads lived, is still online in 2026 but behind an anti-bot challenge, and the English Wikipedia article on MiniD was renamed and then deleted in November 2020, surviving in mirrors such as HandWiki. The realistic route for the curious is the Croc repository on GitHub, which preserves every MiniD commit (the d1impl branch, last touched in February 2014, appears to be the final D-based code) and whose C++ version builds with CMake, and the Croc-attic repository, which holds the MiniD 1 and 2 source trees as they were in 2011.
Why it matters
MiniD matters for three reasons, none of them adoption.
First, it is a well-documented example of a one-person language done properly: a public specification frozen before 1.0, a versioning policy, a test suite, benchmark ports, a bug tracker whose ticket numbers appear in the commit log, and a design that was revised in the open when it did not work. The prototype-object experiment of 2008, tried and reverted within five months, is the kind of decision most languages hide.
Second, it is part of the history of D. Between 2006 and 2011 the question “what do I embed in my D program?” had MiniD as its most complete answer, and the language’s evolution - from Phobos to Tango, from the D garbage collector to its own, and finally out of D altogether when D 1 and Tango faded - tracks the turbulence of the D 1 era more faithfully than most accounts of it.
Third, it shows what happens when a language is both an extension language and “perfectly capable on its own”. MiniD’s answer, borrowed from Lua and refined over three implementations, was a small core with a rich host API and a growing standard library, and its successor’s failure to find users is a reminder that the answer is rarely enough on its own. The code, at least, is still there.
Timeline
Notable Uses & Legacy
MDCL and minidc (2007-2011)
The project's own toolchain: minidc, a compiler that produced MiniD bytecode modules, and MDCL, an interactive command-line interpreter (with GNU readline support on POSIX) that doubled as the test bed for the language. From MiniD 2 the interactive loop was factored into a minid.commandline module so that host applications could embed a MiniD console of their own; Windows binaries and, from June 2009, a 32-bit Linux binary were shipped in the repository
Arc game library binding and the Missile Command sample (2008-2009)
arc_wrap, a MiniD 2 binding to the Arc 2D game library for D, was the showcase for the templated binding library: wrapped D classes, structs and properties appeared as native MiniD classes with polymorphic method calls. The samples written against it - missilecommand.md, a complete Missile Command clone using class type constraints and a free-list allocator, and antimatroids.md - were the closest thing MiniD had to a shipped game, and are the kind of use the language was designed for
Tango Conference 2008 talk
Billingsley presented MiniD at the D community's Tango Conference in 2008, one of a set of talks (with DWT, DReactor, DDL, 'Teaching D' and a game-development session by Tomasz Stachowiak and Piotr Modzelewski of team0xf) whose videos were announced on the D newsgroup in October-November 2008. The talk is the main surviving public explanation of the MiniD 2 design, and the discussion it provoked on the D newsgroup - over multiple return values versus Python tuples, and over class-based versus prototype-based objects - documents the choices that went into 2.0
Computer Language Benchmarks Game ports
The repository carried MiniD versions of the shootout programs - binarytrees, fannkuch, fasta, mandelbrot, nsieve, partialsums, pidigits and others - which the author used to profile the interpreter (with xfProf) while developing MiniD 2. In the June 2009 release thread he said informally that MiniD 2 ran faster than Python and comparably to Lua on such programs, but no figures, hardware or methodology were published, so no assessable comparative performance data exist; the suite is nevertheless a useful corpus of idiomatic MiniD code
Croc (2011-2015)
MiniD's direct continuation: the same repository, renamed in June 2011 and ported from D to C++11 in 2014 so that it could be embedded in programs that were not written in D. Croc kept MiniD's syntax and semantics while adding a documentation system, memblocks, and graphics and audio add-ons; it is where anyone who wants to run MiniD-style code today should start