← Dolaima← Docs indexWhat VML is原文中文

What VML is

VML = a virtual machine that runs inside your phone, with its own standard library, its own assembler and its own bytecode format.

A program you write (C / Python / BASIC / ... 27 languages in all) is compiled by a front end compiler into the instructions this virtual machine understands, and then that is what runs it. So:

Why not just call the system compiler

You cannot install, or even run, a full gcc / CPython on a phone. VML moves that work to compile time - compilation happens in the front end, and at run time all that is needed is a very small virtual machine.

Three levels of artifact

your source (.c)  ──front end──▶  .vml (text assembly)  ──assemble──▶  .vmb (binary bytecode)
                                                                    │
                                                              load and run
ArtifactWhat it isWhen to use it
SourceWhat you wroteYou edit this day to day
.vmlText assembly, readable and greppableWhen you want to see what the compiler made of your code
.vmbBinary bytecodeLoad this one to run - it is the fastest

vml run understands all three and tells them apart on its own.

It can draw UI, make sound, and vibrate

A VML program is not limited to printing text - it has a complete set of phone UI interfaces:

Tetris, Gomoku, Pac-Man, Snake, a plane shooter and a piano have already been written against these interfaces. They are all in examples/, and they all run as they are.

See "UI development" for the details.

27 languages, pick any one

The same set of VML interfaces is available from all 27 front ends. Write in whichever one you know, and what you compile runs on the same virtual machine. Each language has its own detailed page (its language spec plus what this front end supports) under "About -> Help -> VML compilers -> 27 languages".

27 languages, one example each

LanguageExamplesHow to run
Cexamples/c/app/tetris.c gomoku.c pacman.c mario.c starfall.c **piano.c** **audio_test.c**vml run examples/c/app/gomoku.c
C++examples/cpp/app/snake.cppvml run examples/cpp/app/snake.cpp
C#examples/csharp/app/snake.cs racer.csvml run examples/csharp/app/snake.cs
Objective-Cexamples/objc/app/snake.mvml run examples/objc/app/snake.m
Javaexamples/java/test/catch.javavml run examples/java/test/catch.java
Kotlinexamples/kotlin/test/catch.ktvml run examples/kotlin/test/catch.kt
Swiftexamples/swift/app/plane.swift snake.swiftvml run examples/swift/app/snake.swift
Goexamples/go/app/snake.govml run examples/go/app/snake.go
Rustexamples/rust/app/breakout.rsvml run examples/rust/app/breakout.rs
Dexamples/d/test/catch.dvml run examples/d/test/catch.d
Dartexamples/dart/test/catch.dartvml run examples/dart/test/catch.dart
Pythonexamples/python/app/tetris.pyvml run examples/python/app/tetris.py
JavaScriptexamples/javascript/test/catch.jsvml run examples/javascript/test/catch.js
Luaexamples/lua/app/life.luavml run examples/lua/app/life.lua
Rubyexamples/ruby/test/catch.rbvml run examples/ruby/test/catch.rb
Rexamples/r/test/catch.rvml run examples/r/test/catch.r
Pascalexamples/pascal/test/catch.pasvml run examples/pascal/test/catch.pas
Fortranexamples/fortran/app/sokoban.f90vml run examples/fortran/app/sokoban.f90
BASICexamples/basic/app/whack.bas tetris.basvml run examples/basic/app/whack.bas
Forthexamples/forth/test/parserexp_demo.fsvml run examples/forth/test/parserexp_demo.fs
Schemeexamples/scheme/test/catch.scmvml run examples/scheme/test/catch.scm
Ladderexamples/ladder/test/file_io.ldCompile only, see below

Every language directory also has a sysinfo.<ext> that calls ui_call_json("sysinfo", "") and prints the device information - if you want to know whether this language works, run that first.

How to write in each language

C / C++ / Objective-C - the most complete path

#include <vml_ui.h>

int main(void) {
    int w = ui_scr_get_w(), h = ui_scr_get_h();
    ui_win_open("Demo", w, h);
    ui_2d_clear(0xFF101020);
    ui_2d_text(20, 40, "Hello", 0xFFFFFFFF, 20, 0);
    ui_2d_present();
    while (ui_win_is_closed() == 0) { int m[4]; ui_msg_wait(m, 0); }
    return 0;
}

C# / Java / Kotlin / Dart - you have to declare them

These front ends require external functions to be declared first:

// C#
class P { static void Main() { ui_win_open("Demo", ui_scr_get_w(), ui_scr_get_h()); } }
// Java
static native int ui_win_open(String t, int w, int h);
// Dart
external int ui_win_open(String t, int w, int h);

Python / Lua / JavaScript / Ruby / R - call them directly

ui_win_open("Demo", ui_scr_get_w(), ui_scr_get_h())
ui_2d_clear(0xFF101020)
ui_2d_present()

Warning: Python lists cannot be written to (b[i] = v still reads back as 0). For a mutable grid such as a game board, use the integer grid the shared library provides:

ui_grid_clear()
ui_grid_set(3, 1)      # cell 3
v = ui_grid_get(3)

BASIC

NATIVE FUNCTION ui_win_open(t AS STRING, w AS INTEGER, h AS INTEGER) AS INTEGER
ui_win_open "Whack-a-mole", w, h

Warning: a parameter must not be named on (it is a keyword).

Pascal

{ comments are { }, not // }
program p;
begin
  ui_win_open('Demo', ui_scr_get_w(), ui_scr_get_h());
  ui_2d_present();
end.

Warning: comments may only contain ASCII - Chinese punctuation (dashes, commas) is reported as an unknown character. And if you use // for a comment, the whole line is treated as code.

Forth

S" Demo" ui_scr_get_w ui_scr_get_h ui_win_open

Scheme

(ui_win_open "Demo" (ui_scr_get_w) (ui_scr_get_h))

Warning: a user function cannot see top-level variables (the two frame pointers collide). Write games as a flat top-level program, and pull out only pure functions that take every parameter explicitly and never touch globals.

Fortran

call ui_win_open('Demo', ui_scr_get_w(), ui_scr_get_h())

Ladder - special case

It is a PLC ladder-logic style front end, and it has no syntax for "a function call with string arguments", so the whole UI set is out of reach (ladder/file_io.ld in the repository is itself an empty test). It compiles and it runs, but it cannot build a phone UI program.

Pitfalls common to all languages

  1. Ask first, then open: ui_scr_get_w/h -> ui_win_open
  2. **Call ui_2d_present() every frame**
  3. **Call ui_msg_clear() before starting a new round**
  4. Timers must be killed
  5. Do not run an array out of bounds - nine times out of ten, "memory error" means exactly that