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

VML is the lightweight virtual machine and compiler toolchain built into Dolaima. It compiles 27 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: 27 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 27 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
27 language front endsCompile source in 27 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 27 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 27 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)

The kinds of programs you can write

From “print one line” to a “3D scene”, one virtual machine covers five tiers, each with its own library: new programs use the new tier, old programs run through a compatibility layer without changing a line. Example names link straight to readable source (all examples are sorted by language and category; every one of the 22 languages has its own set).

What you writeWith whatNotesExamples
① stdio program each language’s own printf / puts / scanf The most basic tier: write text to standard output, read from standard input. The terminal / command-line page shows its output directly. demo_std.c
② colour TTY program tty_* (new text)
conio / crt (old programs)
Character interface: coloured text, cursor positioning, clearing the screen; old conio.h / curses programs run on this path too. demo_tty.c · ansi_colors.c · conio_screen.c
③ classic BGI program graphics (BGI compatibility layer) The DOS-era initgraph / line / circle set compiles and runs as-is — it forwards to ui_* and does not simulate video memory. demo_bgi.c · old_gfx_bgi.c
④ cross-platform UI program ui_* (new graphics) Windows, primitives, touch and key messages, timers, sound, saved data — one source file draws a UI on the phone and a window on the desktop. demo_ui.c · draw_prims.c
⑤ cross-platform 3D program ui_3d_* (numbers 600–632) Viewport, meshes, camera, lighting, and meshes loaded from an external .obj file — equally cross-platform. solar3d.c (a solar system) · g3_all.c · objload.c · air3d.c

The rule is simple: a newly written program should only use the new libraries of tiers ①②④⑤ — conio / crt / graphics are compatibility layers that fill in the environment for old programs, not new APIs. Every game and sample running on mobile goes through ui_* and ui_3d_*.

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 27 languages and the optimiser.