← Dolaima← Docs indexPython原文中文

Python

The fastest one to write. The syntax is almost desktop Python, and changing a line and running again is a pleasure.

How to run it on your phone

vml run examples/python/test/sysinfo.py

Compiling takes a while (one to two minutes for C, a few seconds for scripting languages). Once the program is running, the gamepad is at the bottom of the screen - the D-pad and the four action buttons are all there. Tap the back arrow in the top-right corner to return to the Shell.

What to know before you write

Examples

FileWhat it shows
app/tetris.pyTetris
test/sysinfo.pyDevice information

Also in this folder: app/breakout.py, app/calendar.py, app/notepad.py, app/stock.py, app/weather.py, app/wordle.py, demo/demo_std.py, test/libs.py, tty/demo_tty.py, ui/demo_ui.py

Pitfalls we hit on real devices


The rest of this page is taken straight from the VML source (third_party/vml/VMLPrepares/PythonCompiler/): the README covers what this front end supports and how to compile it, and the language reference covers the syntax itself. When upstream changes, regenerating this page brings it up to date.

Language reference

Python language compiler specification

Version: v1.0 | Date: 2026-07-06 | Revised by: Shenzhen Tanso Intelligent Technology Co., Ltd.

Specification standard

FieldValue
Target standardPython 3.0 (2008)
Release year2008
Completeness~90%
Updates2026-05-18: list/dict/tuple/set are all implemented with heap allocation
Tests6 passing

Version 1.0 | 2026-04-19 | Compiler path: VMLPrepares/PythonCompiler/


1. Goals and scope

Compile a subset of Python into VML assembly that runs on the VML virtual machine. VML is a hybrid register-plus-stack architecture with 16 general-purpose registers (R0–R15), supporting integer and floating-point arithmetic.

Not implemented: class, async/await, decorators, type annotations, list comprehensions, the generator runtime


2. Reserved words

Reserved wordSemanticsParserCodeGen
False/True/Noneliterals✅✅→0/1/0
and/or/notlogical operators✅ short-circuit✅ jump chain
if/elif/elseconditionals✅✅ conditional jumps
while/forloops✅ with else✅ loop + else
break/continueloop control✅✅ JMP
deffunction definition✅✅ stack frame convention
returnreturn✅✅ epilogue
passempty statement✅✅ NOP
lambdaanonymous function✅⚠️ stub
assertassertion✅⚠️ stub
deldelete✅⚠️ stub
global/nonlocalscope✅⚠️ stub
import/frommodule import✅⚠️ stub
raiseraise an exception✅⚠️ stub
try/except/finallyexceptions✅⚠️ stub
withcontext manager✅⚠️ stub
yieldgenerators✅⚠️ stub
match/casepattern matching✅ constant patterns⚠️ stub (jumps already generated)
in/ismembership/identity✅ comparison⚠️ stub (→0)
asalias✅—
//division✅✅ //
_wildcard✅⚠️ →0

3. Data types

3.1 Literals
TypeSyntaxLexer TokenCodeGen
Decimal integer42, 1_000INTEGERLOAD RR0 #42
Hexadecimal0xFFINTEGERLOAD RR0 #255
Octal0o77INTEGERLOAD RR0 #63
Binary0b1010INTEGERLOAD RR0 #10
Float3.14, 1e10FLOATLOADF RR0 #3.14
String"hello", 'world'STRINGdataSection + LOAD RR0 [addr]
Triple-quoted"""multi"""STRINGdataSection
BooleanTrue/FalseTRUE/FALSELOAD RR0 #1/#0
NoneNoneNONELOAD RR0 #0
List[1, 2, 3]LBRACKET✅ heap allocated [length + elements]
Dictionary{k:v}LBRACE✅ heap allocated [pair count + key/value pairs]
Tuple(1, 2)LPAREN✅ heap allocated [length + elements]
Set{1, 2, 3}LBRACE✅ heap allocated [length + elements]

Dictionary vs set ambiguity: {expr} is a set, {expr:expr} is a dictionary, {} is an empty dictionary.

3.2 Type compatibility

VML has no dynamic typing; at runtime every value is an integer (int) or a float (float). bool→int, None→0. A string is a special data-segment reference (an address), and runtime string operations are not supported yet.


4. Operator precedence (lowest to highest)

Level 1  lambda x: expr                    # loosest, right associative
Level 2  x if cond else y                 # ternary
Level 3  or                                # short-circuit
Level 4  and                               # short-circuit
Level 5  not x                             # unary
Level 6  in | is | < <= > >= != ==         # comparison (chained: a<b<c → (a<b)&(b<c))
Level 7  |                                 # bitwise or
Level 8  ^                                 # bitwise xor
Level 9  &                                 # bitwise and
Level 10 << >>                             # shifts
Level 11 + -                               # add/subtract
Level 12 * / // %                          # multiply/divide/floor-divide/modulo
Level 13 -x +x ~x                          # unary
Level 14 **                                # power (right associative)
Level 15 await x                           # unary (runtime not implemented yet)
Level 16 x[i] x.attr f(args)              # subscript/attribute/call (highest)
VML mapping of the operators
OperatorVML instructionNotes
+ADD RR0 RR0 RR1
-SUB RR0 RR0 RR1
*MUL RR0 RR0 RR1
/DIV RR0 RR0 RR1float
//DIV RR0 RR0 RR1 + truncationfloor division
%MOD RR0 RR0 RR1
**loop MULsimplified for now
&AND RR0 RR0 RR1
|OR RR0 RR0 RR1
^XOR RR0 RR0 RR1
~NOT RR0 RR0
<<SHL RR0 RR0 RR1
>>SHR RR0 RR0 RR1
-x (neg)SUB RR0 #0 RR0
==CMP + JE/JNE
!=CMP + JNE/JE
<CMP + JL
<=CMP + JLE
>CMP + JG
>=CMP + JGE
andshort-circuit jump chainif A is 0, skip B
orshort-circuit jump chainif A is non-zero, skip B
notCMP RR0 #0 + invert

5. Statement and VML semantics mapping

5.1 Function definition
def foo(a, b, c):
    return a + b + c

VML stack frame convention:

caller: PUSH c, PUSH b, PUSH a  (right to left)
       CALL foo                  (pushes the return address)
callee prologue: PUSH R15, PUSH R12, MOVE R12 R13
callee epilogue: MOVE R13 R12, POP R12, POP R15, RET
stack layout (R12 = frame pointer):
  arg0  ← R12+12
  arg1  ← R12+8
  arg2  ← R12+4
  ret   ← R12+0  (implicit)
  saved R15 ← R12-4
  saved R12 ← R12-8
  local0 ← R12-12
  local1 ← R12-16
5.2 if/elif/else
if a > 0:
    x = 1
elif a == 0:
    x = 0
else:
    x = -1

VML:

    LOAD RR0 [R12-a]
    CMP RR0 #0
    JLE elif_0
    LOAD RR0 #1
    STORE [R12-x] RR0
    JMP endif_0
elif_0:
    LOAD RR0 [R12-a]
    CMP RR0 #0
    JNE else_0
    LOAD RR0 #0
    STORE [R12-x] RR0
    JMP endif_0
else_0:
    LOAD RR0 #-1
    STORE [R12-x] RR0
endif_0:
5.3 while loops
while i < n:
    i = i + 1
else:
    result = -1

VML:

while_0:
    LOAD RR0 [R12-i]
    CMP RR0 [R12-n]
    JGE endwhile_0
    # body: i = i + 1
    LOAD RR0 [R12-i]
    PUSH RR0
    LOAD RR0 #1
    MOVE RR1 RR0
    POP RR0
    ADD RR0 RR0 RR1
    STORE [R12-i] RR0
    JMP while_0
endwhile_0:
    # else branch (runs when the while condition is False and no break left the loop)
    LOAD RR0 #-1
    STORE [R12-result] RR0

while-else semantics: the else runs when the loop ends normally (the condition is false); it does not run when a break leaves the loop. Implementation: break jumps to just after endwhile.

5.4 for loops
for i in range(n):
    x = i * 2

VML:

    LOAD RR0 #0           # i = 0
    STORE [R12-i] RR0
for_0:
    LOAD RR0 [R12-i]
    CMP RR0 [R12-n]
    JGE endfor_0
    # body: x = i * 2
    LOAD RR0 [R12-i]
    PUSH RR0
    LOAD RR0 #2
    MOVE RR1 RR0
    POP RR0
    MUL RR0 RR0 RR1
    STORE [R12-x] RR0
    # increment
    LOAD RR0 [R12-i]
    PUSH RR0
    LOAD RR0 #1
    MOVE RR1 RR0
    POP RR0
    ADD RR0 RR0 RR1
    STORE [R12-i] RR0
    JMP for_0
endfor_0:
5.5 match/case
match n:
    case 1:
        print(100)
    case 2:
        print(200)
    case _:
        print(999)

VML:

    LOAD RR0 [R12-n]
    PUSH RR0
    LOAD RR0 #1
    CMP RR0 RR1
    JE case_0_end
    LOAD RR0 #100
    PUSH RR0
    SYSCALL #4
    ADD RR13 RR13 #4
    JMP match_end
case_0_end:
    LOAD RR0 #2
    CMP RR0 RR1
    JE case_1_end
    LOAD RR0 #200
    PUSH RR0
    SYSCALL #4
    ADD RR13 RR13 #4
    JMP match_end
case_1_end:
    # _ wildcard: always matches
    LOAD RR0 #999
    PUSH RR0
    SYSCALL #4
    ADD RR13 RR13 #4
    JMP match_end
match_end:
    POP RR0

Semantics: push the matched value, then compare it in each case; the _ wildcard matches unconditionally. After a case body runs successfully, JMP match_end.

5.6 lambda
f = lambda x, y: x + y

VML:

lambda_f_0:
    PUSH R15, PUSH R12, MOVE R12 R13
    # x = R12+12, y = R12+8
    LOAD RR0 [R12+12]
    PUSH RR0
    LOAD RR0 [R12+8]
    MOVE RR1 RR0
    POP RR0
    ADD RR0 RR0 RR1
    MOVE RR13 R12, POP R12, POP R15, RET
# f points at the address of lambda_f_0
5.7 assert
assert x > 0, "x must be positive"

VML:

    # evaluate x > 0 → bool in RR0
    CMP RR0 #0
    JNE assert_ok_0
    # failure: print message, halt
    LOAD RR0 #-1
    SYSCALL #99          # abnormal exit
assert_ok_0:
5.8 Assignment and augmented assignment
x = 10
x += 5

VML:

    LOAD RR0 #10
    STORE [R12-x] RR0
    LOAD RR0 [R12-x]
    PUSH RR0
    LOAD RR0 #5
    MOVE RR1 RR0
    POP RR0
    ADD RR0 RR0 RR1
    STORE [R12-x] RR0
5.9 Ternary expression
result = 1 if a > 10 else 0

VML:

    LOAD RR0 [R12-a]
    CMP RR0 #10
    JG cmp_true_0
    LOAD RR0 #0
    JMP cmp_end_1
cmp_true_0:
    LOAD RR0 #1
cmp_end_1:
    STORE [R12-result] RR0

6. Built-in functions

FunctionVMLArgumentsReturn value
print(x)SYSCALL #41 int on the stacknone
input()SYSCALL #7noneRR0 = integer
len(x)stub—RR0 = 0
range(n)for loop unrolling—special-cased
abs(x)inlinedRR0RR0
int(x)inlinedRR0RR0
str(x)stub—RR0 = 0

7. Indentation rules (Lexer)


Floating-point and 64-bit compilation modes

The VML toolchain controls how floating point and 64-bit integers are handled through three compilation flags:

FlagPossible valuesDefaultDescription
--float32hard / soft / nonehard32-bit float handling mode
--float64hard / soft / nonesoft64-bit float (float) handling mode
--int64hard / soft / nonesoft64-bit integer (int) handling mode
32-bit float (float32)

Python's float type is mapped to a 64-bit double-precision float when VML compiles it. 32-bit float arithmetic is used for internal intermediate results:

64-bit float (double)

Python's float type is natively an IEEE 754 double-precision 64-bit float and compiles as follows:

64-bit integer (int64)

Python 3's int type is an arbitrary-precision integer. When VML compiles it, integers within the 64-bit range are handled as follows:

Software emulation libraries

The software emulation libraries above all live in the Lib/shared/ directory, are written in C, are compiled to VML by the C compiler, and are shared by every language:

Library filePurposeCore functions
softfloat.cQ15.16 fixed-point 32-bit float emulation__vml_float_add/sub/mul/div/neg/abs/cmp, __vml_int2float/float2int
softdouble.cIEEE 754 double-precision 64-bit float emulation__vml_double_add/sub/mul/div/neg/abs/cmp, __vml_int2double/double2int, __vml_float2double/double2float
softint64.c64-bit integer dual-register emulation__vml_i64_add/sub/neg/and/or/xor/not/shl/shr

8. Unsupported Python features

FeatureReason
class / __init__ / inheritancethe class system is too complex
async / awaitneeds an event loop
decorators @low-priority syntactic sugar
type annotations x: intcompile-time checking is not needed yet
f-stringstring interpolation is complex
list comprehensions [x*2 for x in ...]needs iterators
the yield generator runtimeneeds a state machine
with __enter__/__exit__simplified to an empty implementation
full match patterns (destructuring/guards)constants + wildcards only
*args/**kwargsvariadic parameters
multiple assignment a, b = 1, 2unpacking
the walrus operator :=not implemented yet

9. Change log

DateVersionChange
2026-04-190.1initial version
2026-04-191.0added the VML semantics mapping, the stack frame convention, the indentation rules, and while/for-else semantics

🆕 String type (v1.65.19)

This language compiler uses .wstring (UTF-16LE) by default as its internal string storage.

ModeDefault encodingVML directiveSYSCALL output
MCU (default).string (UTF-8).string#1
OS.wstring (UTF-16LE).wstring#391

Predefined macro: VML_WSTRING — defined automatically in OS mode, undefined in MCU mode Output function: OS mode automatically uses shared_print_wstr (automatic UTF-16LE→UTF-8 conversion)

// user code can determine the encoding through the macro
#ifdef VML_WSTRING
  // the default string is a wstring (UTF-16LE)
#else
  // the default string is UTF-8
#endif

Compiler README

Python 3 compiler

Path: VMLPrepares/PythonCompiler/ Completeness: ~90% | 🟢 production ready Standard library: Lib/python/

Features

Compilation modes

MCU mode (default --mode mcu)

MCU mode is tuned for microcontrollers and bare-metal environments (Arduino/STM32/8051 and so on), and automatically skips features that are incompatible with an operating system.

Skipped (no code is generated for this syntax):

Kept (implemented underneath by the BIOS):

OS mode (--mode os, reserved)

OS mode targets environments that have an operating system (such as embedded Linux or an RTOS), and will support every language feature (file system, threads, asynchronous I/O, exceptions, reflection and so on).

RAM levels
MCU-safe coding tips

Usage

dotnet run --project VMLPrepares/PythonCompiler input.Py -o output.vml

Tests

Test/Py/ — 0 test files (the test directory is yet to be created)