VML: the virtual machine and 22 languages that ship in the box

VML is the lightweight virtual machine and compiler toolchain built into Dolaima. It compiles 22 languages into its own bytecode and runs them on phone and desktop offline. It downloads no executable code and does not depend on any compiler already installed on your system — the compilers are inside the package.

What it is

In one sentence: a virtual machine plus a complete set of compilers, shipped with the installer to your machine.

  • A virtual machine: loads and executes VML bytecode (full CPU simulation, MMIO, system calls).
  • A set of compilers: 22 languages → VML assembly → VML bytecode. All compilation happens locally.
  • Offline: it works the moment it is installed. The sample programs and games come with the package. No network, no SDK, no compiler needed.

It is not the same thing as "putting a language's official toolchain on a phone": VML has its own instruction set, its own standard library and its own ABI. The 22 languages are just different ways of writing code — they all compile to the same back end and share the same runtime and the same UI interfaces.

The same stack on phone and desktop

The same source file, the same front-end compiler, the same virtual machine. A program you verified on your computer runs directly on the phone.

Called in-process, not bolted on as an exe

On mobile, VML's source is vendored into the app and called in-process — the compiler is not built into an executable and handed to a shell.

Why it has to be that way: the iOS sandbox physically refuses fork/exec (starting your own child process is never going to work there), and Android 10+ W^X makes files in an app's private directory non-executable. Link the managed code straight into the app and all three limits disappear.

What it is made of

PartWhat it does
Virtual machineLoads and executes bytecode: full CPU simulation + MMIO + system calls
AssemblerVML assembly text ↔ VML bytecode, both directions
22 language front endsCompile source in 22 languages into VML assembly
18 back-end translatorsTranslate VML into real hardware architectures and VM targets
Shared libraryOne cross-language standard library, shared by all 22 languages
Drawing and UI interfacesText mode tty_*, graphics mode ui_*, plus compatibility layers for old programs
Samples and gamesUnder examples/, one directory per language — compile and run them right away

The 22 language front ends

Each language has its own front-end compiler, and all of them are marked production-ready:

C (C99)

.c

C++

.cpp

Python

.py

Go

.go

Rust

.rs

Java

.java

C#

.cs

JavaScript

.js

Swift

.swift

Kotlin

.kt

Dart

.dart

Ruby

.rb

Lua

.lua

Scheme

.scm

Forth

.fth / .fs

Fortran

.f90

Pascal

.pas

BASIC

.bas

Objective-C

.m

D

.d

R

.r

Ladder

.ld (ladder logic)

Two of them also come with dialects: 10 BASIC dialects (QBasic / TurboBasic / FreeBasic / TrueBasic / PureBasic / ChipBasic / MiniBasic / GW-BASIC / PowerBASIC / VisualBasic) and 6 Pascal dialects (Turbo Pascal / Delphi / FreePascal / ISO / UCSD / Oberon).

The standard library is shared too: three layers of strings (string / wstring / ustring), formatted output and input (printf / scanf plus their wide-character variants), expression evaluation (parserexp / parserexpf), maths and floating point (math / float / softdouble / softfloat / softint64), and os / file / network / memory / device / convert. A library written in one language can be called from the others.

The 18 back-end translators

VML does not only run by itself — it can also be translated into the assembly of real hardware:

Word sizeTargets
8-bit6502 (Apple II / C64 / NES), Z80 (CP/M / ZX Spectrum), 8051, AVR (Arduino / ATmega), PIC
16-bitMSP430, PIC24
32-bitARM Cortex-M (STM32), x86, MIPS, RISC-V, 68000, PowerPC, SPARC
Virtual machinesJVM, .NET (CLR), Wasm (browsers)

How the drawing interfaces are layered: tty_* and ui_*

Libraries are split into four layers and do not cross into each other. New programs should only use the first two:

PurposeLibraryNotes
New · text modetty_*Characters only, no graphics at all; coordinates start at 1, 16 indexed colours
New · graphics modeui_*Windows, primitives, touch and key messages, timers, sound, saved data
Old programs · textconio / crtCompatibility layer
Old programs · graphicsgraphics (BGI)Compatibility layer; it forwards to ui_* and does not simulate video memory

The rule is simple: a newly written program should not use conio / crt / graphics directly — those are compatibility layers that fill in the environment for old programs, not new APIs. Every game and sample running on mobile goes through ui_*.

Why it is useful

📱

Real programming on a phone

The mobile app ships an editor and can compile and run. The samples and games under examples/ work out of the box — vml run examples/c/tetris.c and it plays.

🖥️

Verify on desktop, run on mobile

The desktop uses the same compile chain, with second-long iteration — get the syntax and the logic right on your computer, then do the last step on the phone.

🕰️

Old programs still run

Most text programs from the DOS and Unix era compile and run without a single line changed: the classic terminal clock tty-clock (689 lines) compiles and runs unmodified, the animated train sl (295 lines) animates end to end, and cmatrix (894 lines) draws its matrix.

Old-program compatibility is not a binary "yes / no" but four tiers:

TierKindFeasibility
APure character interfaces (curses / conio / ANSI escapes)High — the bulk of them, and already working
BTerminal control using termios / ioctlMedium
Cx86-specific (DOS memory model, bios.h, int86, video memory 0xB8000)Low, and should not be done — out of scope, not "not yet done"
DGraphics (BGI graphics.h / Allegro)BGI has a shim (it forwards to ui_*); Allegro / SDL are not done

The boundaries it deliberately does not cross

The following are not "not yet done" but deliberately not done (these are settled decisions, written down in the project's own documentation):

ShapeExamples
Manipulating assembly directlyasm / __asm__ blocks, __emit__, register pseudo-variables _AX / _BX / _CX / _DX
Manipulating memory directlyWriting video memory directly (text 0xB8000 / graphics 0xA0000), bios.h, int86, peek / poke
Bare hardwareinterrupt / _interrupt handlers, ports inp / outp, BASIC's DEF SEG

The reason is that the semantics do not translate: those programs mean "write to a block of memory at a fixed address and let the host blit it to the screen", whereas this platform's model is "the program calls host interfaces to draw". Those are two parallel drawing surfaces — and fixed addresses (video memory, ports, interrupt vectors) simply have no counterpart on a phone.

Such things cannot be treated as "transparent blanks" and quietly skipped — dropping them compiles silently wrong, and a program that looks like it runs but gives the wrong result is far harder to diagnose than one that fails to compile. What has to change is the program itself (write to ui_* instead of video memory, rewrite the asm block in a high-level language), not the grammar.

Also deliberately not done:

  • windows.h (Win32 GUI) — it maps to nothing on a phone;
  • the whole gfx_* / video-memory family — see above;
  • system() — this platform has no shell. Rather than pretend (system("copy a b") would report success while nothing happened), it is better for the symbol to be missing at compile time;
  • Allegro / SDL — they carry their own audio, input and timer runtime; that is no longer "filling in an environment" but "porting a platform";
  • mouse interrupts (INT 33h) and BGI's driver-loading model (registerbgidriver / font files / setviewport).

The rule is consistent throughout: if it is missing, the symbol is missing at compile time — there is no pretending. "It compiles but shows nothing" is far harder to diagnose than "it does not compile".

Where to start

🧭 Start from zero

Where to run it, your first program, why registers are written with @, how to open a window and draw, and how to set up a game skeleton — every step can be followed, and the code can be pasted and run as-is.

Read the VML tutorial

📥 Install it first

On mobile, open the Files page and examples/ is already there. On desktop, download, unzip and run.

Go to downloads

One more thing: the editor and the ability to compile and run C and VML assembly are free. The "Full Edition" is a one-time in-app purchase (not a subscription) that unlocks the compilers for all 22 languages and the optimiser.