← Dolaima← Docs indexBASIC原文中文

BASIC

The old-fashioned style: imperative, one line after another.

How to run it on your phone

vml run examples/basic/test/sysinfo.bas

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/blackjack.basBlackjack (polling message loop plus vibration)
app/gorilla.basGorillas throwing bananas (a complete game plus sound)
app/gorilla_pro.basThe same, with gradients, paths and tiles added
app/hammurabi.basHammurabi (turn-based management)
app/hurkle.basAn old-style typewriter text program (with _tty.bas inlined)
app/lander.basLunar lander
app/nibbles.basSnake
app/tetris.basTetris (grid plus gamepad)
app/whack.basWhack-a-mole (random numbers plus timers plus vibration)
bgi/demo_bgi.basA demonstration of the graphics statements, one by one
bgi/gfx_demo.basThe same as above
bgi/gfx_modes.basResolution of each SCREEN mode
test/sysinfo.basDevice information
tty/demo_tty.basText mode (ANSI color)
ui/demo_ui.basThe smallest skeleton: open a window, draw, message loop

Also in this folder: CREDITS.md, app/calendar.bas, app/donkey.bas, app/notepad.bas, app/stock.bas, app/weather.bas, demo/demo_std.bas, test/libs.bas, thirdparty/LICENSES.txt, thirdparty/bouncing_ball.bas, thirdparty/dosbism.bas, thirdparty/dosbismkey.bas, thirdparty/doscolortst.bas, thirdparty/dosgrbism.bas, thirdparty/dosgrdemo.bas, thirdparty/dosmathtbl.bas, thirdparty/dosrandom.bas, thirdparty/ex_calc.bas, thirdparty/ex_message.bas, thirdparty/ex_numgame.bas, thirdparty/ex_print.bas, thirdparty/ex_rnddots.bas, thirdparty/futureblocks_tetris.bas, thirdparty/gwiezdna_bitwa.bas, thirdparty/maze.bas, thirdparty/qbjc_guess.bas, thirdparty/qbjs_paint.bas, thirdparty/qtrek.bas, thirdparty/solitaire.bas, thirdparty/turtle.bas, thirdparty/w84d_app_template.bas, thirdparty/w84d_desert_rally.bas, thirdparty/w84d_mouse_cursor.bas, thirdparty/w84d_radar.bas, thirdparty/w84d_spaceship.bas

Pitfalls we hit on real devices


The rest of this page is taken straight from the VML source (third_party/vml/VMLPrepares/BasicCompiler/): 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

BASIC language compiler specification

Version: v2.1 | Date: 2026-08-01 | Revised by: Shenzhen Tanso Intelligent Technology Co., Ltd. Updates: v1.66.33 — all dialects ≥90% + CLASS/OOP + GPIO + 140 keywords (measured, v0.96.506)

Specification standard

FieldValue
Target standardQBasic (default) + 9 dialects (10 BasicDialect members in total, see VMLPlugins/CompilerOptions.cs), all at ≥90% completeness
CLI option--basictype qbasic|turbobasic|freebasic|truebasic|purebasic|chipbasic|minibasic
Completeness92% (QBasic), 90% (every dialect)
Tests63 passing (Lang_BASIC) + 22 dialect tests
Total tokens140 keywords (measured, v0.96.506), 171 TokenTypes (measured, v0.96.506)

Multi-dialect keyword sets

The BASIC compiler supports 10 dialects through the --basictype option. Each dialect's keyword differences are listed below.

1. QBasic (default) — __QBASIC__

Compatible with Microsoft QBasic/QuickBASIC. Every later dialect builds on this one.

Unique keywords (14): PSET, CIRCLE, PAINT, DRAW, VIEW, WINDOW, PALETTE, SCREEN, LPRINT, PRINT USING, FREEFILE, ON ERROR, RESUME, DEF FN

Typical use: QBasic programs from the DOS era, QuickBASIC games (GORILLAS/NIBBLES)


2. TurboBasic — __TURBOBASIC__

Compatible with Borland Turbo Basic.

Added on top of QBasic (6): EXIT, DO, LOOP, UNTIL, CASE ELSE, FUNCTION

Removed (difference from QBasic) (8): PSET, CIRCLE, PAINT, DRAW, VIEW, WINDOW, PALETTE, SCREEN

Typical use: scientific computing, structured BASIC programs


3. FreeBasic — __FREEBASIC__

Compatible with the open-source cross-platform BASIC compiler.

Added on top of QBasic (12): PTR, CAST, CPTR, ANY, EXTENDS, OPERATOR, PROPERTY, ENUM, NAMESPACE, USING, DESTRUCTOR, CONSTRUCTOR

Removed (difference from QBasic) (6): LPRINT, PRINT USING, PSET, CIRCLE, DRAW, PALETTE

Typical use: modern open-source BASIC projects, cross-platform development


4. TrueBasic — __TRUEBASIC__

ANSI/ISO standard BASIC.

Added on top of QBasic (4): MAT, ZER, CON, SOUND

Removed (difference from QBasic) (12): SELECT, CASE, IS, ELSEIF, DO, LOOP, EXIT, GOSUB, PEEK, POKE, LPRINT, ON ERROR

Typical use: education, standards-compliant programs


5. PureBasic — __PUREBASIC__

Compatible with PureBasic.

Added on top of QBasic (8): PROCEDURE, ENDPROCEDURE, PROTECTED, GLOBAL, THREADED, INTERFACE, ENDINTERFACE, NEW

Removed (difference from QBasic) (10): GOSUB, RETURN, LPRINT, PSET, CIRCLE, DRAW, VIEW, WINDOW, PALETTE, DEF FN

Typical use: game development, GUI applications


6. ChipBasic — __CHIPBASIC__

An MCU-optimised dialect.

Added on top of QBasic (3): PINMODE, DIGITALWRITE, DIGITALREAD

Removed (difference from QBasic) (15): SCREEN, PSET, LINE, CIRCLE, PAINT, DRAW, VIEW, WINDOW, PALETTE, LPRINT, PRINT USING, FREEFILE, ON ERROR, RESUME, CHIPASM

Typical use: embedded MCUs (Arduino/STM32), IoT devices


7. MiniBasic — __MINIBASIC__

The smallest subset — for teaching and resource-constrained environments.

Added on top of QBasic (0): None.

Removed (difference from QBasic) (20): TYPE, DIM, REDIM, ERASE, SWAP, SHARED, COMMON, SELECT, CASE, DO, LOOP, EXIT, GOSUB, GOTO, CALL, LPRINT, PRINT USING, PSET, CIRCLE, DRAW

Retained keywords (15 only): PRINT, INPUT, IF, THEN, ELSE, FOR, NEXT, WHILE, WEND, LET, REM, DIM (simplified), END, GOTO (simplified), GOSUB (simplified)

Typical use: teaching, microcontroller bootstrapping


Dialect keyword comparison
CategoryQBasicTurboBasicFreeBasicTrueBasicPureBasicChipBasicMiniBasic
Total keywords~70~68~76~62~68~57~15
Completeness92%90%90%90%90%90%90%
Graphics✅❌❌❌❌❌❌
OOP❌❌✅❌✅❌❌
MCU GPIO❌❌❌❌❌✅❌
Line numbers✅✅✅✅❌✅optional
GOSUB✅✅✅❌❌✅simplified

Full QBasic keyword list (by category)

Control flow (14)

IF, THEN, ELSE, ELSEIF, END, END IF, SELECT, CASE, IS, TO, FOR, STEP, NEXT, WHILE, WEND, DO, LOOP, UNTIL, EXIT, GOTO, GOSUB, RETURN

Subroutines/functions (7)

SUB, FUNCTION, CALL, BYVAL, BYREF, DECLARE, DEF FN

Variables/data (12)

LET, DIM, SWAP, ERASE, REDIM, PRESERVE, LOCAL, STATIC, SHARED, COMMON, CONST, TYPE

I/O (8)

PRINT, INPUT, LPRINT, PRINT USING, OPEN, CLOSE, AS, FREEFILE

Graphics (17)

SCREEN, PSET, LINE, CIRCLE, PAINT, DRAW, COLOR, LOCATE, CLS, VIEW, WINDOW, PALETTE, GET, PUT, WIDTH, BEEP

Functions (20+)

ABS, SGN, SQR, INT, FIX, SIN, COS, TAN, EXP, LOG, ATN, RND, RANDOMIZE, TIMER, DATE$, TIME$, PEEK, POKE, INKEY$, KBGETCH, KBHIT, MOUSEGETX, MOUSEGETY, MOUSELEFT, MOUSERIGHT, LEN, CHR$, ASC, STR$, VAL, LEFT$, RIGHT$, MID$, exit

Other (9)

REM, DATA, READ, RESTORE, SLEEP, SYSTEM, ON ERROR, RESUME, CHIPASM, ASM

Full operator list (highest precedence first)

PrecedenceOperatorTokenDescription
1^EXPONENTexponentiation
2- (unary)MINUSnegation
3* /MULTIPLY, DIVIDEmultiply, divide
4+ -PLUS, MINUSadd, subtract
5= < > <= >= <>EQUALS, LESS, GREATER, LESS_EQUAL, GREATER_EQUAL, NOT_EQUALrelational
6NOTNOTlogical NOT
7ANDANDlogical AND
8ORORlogical OR

Separators

SymbolTokenPurpose
,COMMAseparates arguments / columns
;SEMICOLONPRINT without a newline
:COLONseparates multiple statements
.DOTmember access
"QUOTEstring delimiter
( )LPAREN, RPARENfunction/array parentheses
#HASHfile number prefix

3. Statement reference

3.1 Basic I/O
' PRINT — write to the console
PRINT "Hello"       ' a string
PRINT 42            ' a number
PRINT A; B;         ' a semicolon suppresses the newline
PRINT A, B          ' a comma moves to the next column
PRINT               ' a blank line

' INPUT — keyboard input
INPUT "prompt: ", X
INPUT A, B, C
INPUT A$

' LPRINT — printer output
LPRINT "Hello"

PRINT output target rules

Where PRINT writes is decided by the SCREEN mode:

ModeConsole outputMemory outputDescription
Default (no SCREEN)✅❌console terminal only
SCREEN 0 (text mode)✅✅ 0xB8000console + VGA text video memory at the same time
SCREEN N>0 (graphics mode)❌✅ VGA frame bufferrenders to the VGA graphics frame buffer only; nothing goes to the console

The details:

3.2 Variable operations
' LET (may be omitted)
LET A = 42
B = A + 10

' SWAP — exchange two variables
SWAP A, B

' ERASE — clear an array
ERASE ArrayName

' DIM — array declaration
DIM A(10)           ' one dimension
DIM B(5, 5)         ' two dimensions
DIM C(3, 3, 3)      ' three dimensions
DIM S$(10)          ' an array of strings
3.3 Control flow
' IF
IF condition THEN
    ...
ELSEIF condition THEN
    ...
ELSE
    ...
END IF

' single-line IF
IF X > 10 THEN PRINT "Big" ELSE PRINT "Small"

' FOR
FOR I = 1 TO 10 STEP 2
    PRINT I
NEXT I

' WHILE
WHILE A > 0
    A = A - 1
WEND

' DO
DO
    EXIT DO
LOOP WHILE A > 0

DO WHILE A > 0
    EXIT DO
LOOP

DO
LOOP UNTIL A > 0

' SELECT CASE
SELECT CASE X
    CASE 1
        PRINT "One"
    CASE 2 TO 5
        PRINT "Two to Five"
    CASE IS > 10
        PRINT "Big"
    CASE ELSE
        PRINT "Other"
END SELECT

' GOTO / GOSUB
GOTO label
GOSUB subroutine
RETURN

' EXIT
EXIT FOR
EXIT DO
EXIT WHILE
EXIT SUB
EXIT FUNCTION
3.4 Subroutines and functions
SUB MySub(param1, BYREF param2)
    LOCALVAR = param1
    param2 = 99
END SUB

FUNCTION Add(a, b)
    Add = a + b
END FUNCTION

CALL MySub(x, y)
result = Add(5, 3)
3.5 Graphics (standard QBASIC syntax)
SCREEN 9              ' set the graphics mode
WIDTH 80, 25          ' set the text size
COLOR 7, 0            ' foreground colour, background colour
CLS                   ' clear the screen
LOCATE 10, 20         ' position the cursor

PSET (100, 150), 4    ' draw a point (x, y), colour index
LINE (0,0)-(100,100), 2                    ' draw a line
LINE (0,0)-(100,100), 2, B                 ' a rectangle outline
LINE (0,0)-(100,100), 2, BF                ' a filled rectangle
CIRCLE (160,120), 50, 3                    ' draw a circle
PAINT (160,120), 4, 3                      ' fill

' graphics string macro (DRAW)
DRAW "U10 R20 D10 L20"                     ' a draw string

How SCREEN mode affects PRINT The SCREEN statement switches the display mode, and PRINT writes to the console.

3.6 VML graphics extensions
VGAPUTPIXEL x, y, r, g, b      ' draw a point in 24-bit colour
VGADRAWLINE x1,y1,x2,y2,r,g,b   ' draw a coloured line
VGADRAWCIRCLE x,y,radius,r,g,b  ' draw a coloured circle
VGAFILLCIRCLE x,y,radius,r,g,b  ' draw a filled coloured circle
VGADRAWRECT x,y,w,h,r,g,b       ' draw a coloured rectangle outline
' strings
LEN(s$), CHR$(n), ASC(s$), STR$(n), VAL(s$)
LEFT$(s$, n), RIGHT$(s$, n), MID$(s$, start, len)

' random
RND(n)
RANDOMIZE [TIMER]

' memory
PEEK(addr)
POKE addr, value

' time
TIMER, DATE$, TIME$

' detection
KBGETCH(), KBHIT()
MOUSEGETX(), MOUSEGETY(), MOUSELEFT(), MOUSERIGHT()
VGAGETPIXEL(x,y), VGAGETWIDTH(), VGAGETHEIGHT()
3.7 File operations
OPEN "file.txt" FOR INPUT AS #1
OPEN "file.txt" FOR OUTPUT AS #2
INPUT #1, X
PRINT #2, "Hello"
CLOSE #1
3.9 Audio
' PLAY — play a music string
PLAY "C D E F G A B"
PLAY "O3 L4 CDEFGAB"

' SOUND — frequency / duration
SOUND 440, 18         ' frequency (Hz), duration (1/18 s)

' BEEP — the system beep
BEEP
3.10 Error handling
' ON ERROR GOTO — runtime error handling
ON ERROR GOTO ErrorHandler
    ... normal code ...
    EXIT SUB

ErrorHandler:
    PRINT "错误: "; ERR
    RESUME NEXT
3.11 Data types and structures
' CONST — constant definitions
CONST PI = 3.14159
CONST MAX_ROWS = 25

' TYPE / END TYPE — user-defined types
TYPE Point
    X AS INTEGER
    Y AS INTEGER
END TYPE

' using a user-defined type
DIM P AS Point
P.X = 10
P.Y = 20

' DATA/READ/RESTORE — embedded data
DATA 1, 2, 3, 4, 5
FOR I = 1 TO 5
    READ X
    PRINT X
NEXT
RESTORE

' DEF FN — a single-line user-defined function
DEF FNAdd(a, b) = a + b
PRINT FNAdd(3, 5)

' COMMON — variables shared across modules
COMMON SHARED Score, Lives

' REDIM/PRESERVE — resize a dynamic array
DIM A(10)
REDIM A(20)
REDIM PRESERVE A(30)    ' keep the existing data
3.12 Other
SLEEP [seconds]     ' pause
SWAP A, B           ' exchange two variables
ERASE ArrayName     ' clear an array
SYSTEM              ' exit the program
exit(code)          ' exit and return code to the system (SYSCALL 3)
END                 ' end the program
DEFINT A-C          ' type declaration (compatibility)
DEFSNG D-F
DEFSTR S

' OPTION BASE — the starting array index
OPTION BASE 0       ' arrays start at 0 (default)
OPTION BASE 1       ' arrays start at 1

' INKEY$ — non-blocking key check
K$ = INKEY$
IF K$ <> "" THEN PRINT "Key: "; K$

' DECLARE — forward declaration of a subroutine
DECLARE SUB MySub(x)
DECLARE FUNCTION MyFunc(x, y)

' LOCAL / STATIC / SHARED / COMMON
SUB MyProc()
    LOCAL temp        ' a local variable
    STATIC count      ' a static variable (persists)
    SHARED globalVar  ' a shared variable
END SUB
COMMON SHARED Score, Lives  ' shared across modules
3.13 Calling conventions and inline assembly
' the __stdcall calling convention — all arguments go on the stack, the callee cleans up
SUB MyFunc STDCALL(a, b)
    MyFunc = a + b
END SUB

' ASM — inline VML assembly
ASM "MOVE R0, #42"
ASM "SYSCALL #4"

' CHIPASM — inline assembly for the target architecture (6502/Z80/8051 and so on)
CHIPASM "LDA #$42"
CHIPASM "STA $0400"
3.14 Advanced graphics (GET/PUT/PALETTE/VIEW/WINDOW)
' PALETTE — set a palette entry (SCREEN 13 mode)
PALETTE 0, 0, 0, 0         ' index 0 = black
PALETTE 1, 63, 0, 0        ' index 1 = red
PALETTE 2, 0, 63, 0        ' index 2 = green

' GET — save a screen region into an array
DIM buffer(200)
CIRCLE (50,50), 10, 2
GET (40,40)-(60,60), buffer

' PUT — restore a screen region from an array
PUT (100,100), buffer       ' overwrite directly
PUT (100,100), buffer, 1    ' XOR mode

' VIEW — set the graphics viewport
VIEW (10,10)-(200,100)       ' the viewport region
VIEW (10,10)-(200,100), 2, 4 ' with a coloured border

' WINDOW — set the logical coordinate system
WINDOW (0,0)-(1,1)           ' logical coordinates 0-1
CIRCLE (0.5,0.5), 0.3       ' draw in logical coordinates
3.15 PRINT USING — formatted output
PRINT USING "###.##"; 12.345     ' prints: 12.35
PRINT USING "####"; 42            ' prints:   42
PRINT USING "$$###.##"; 12.3     ' prints: $ 12.30

4. Differences from standard QBASIC

Unsupported features
Extensions

Floating point and 64-bit compile modes

The VML toolchain controls its strategy for floating point and 64-bit integers through three compile options:

OptionAllowed valuesDefaultDescription
--float32hard / soft / nonehardhow 32-bit floating point (SINGLE/!) is handled
--float64hard / soft / nonesofthow 64-bit floating point (DOUBLE/#) is handled
--int64hard / soft / nonesofthow 64-bit integers are handled
32-bit floating point (float32)

The 32-bit single-precision types SINGLE / ! in this language compile in the following modes:

64-bit floating point (double)

The 64-bit double-precision types DOUBLE / # in this language compile in the following modes:

64-bit integers (int64)

64-bit integer types are supported in this language by the VML compilation layer. The BASIC standard does not define a matching explicit type, but the compiler leaves open the possibility of supporting one through the --int64 extension.

Software emulation libraries

All of the software emulation libraries above live in Lib/shared/, are written in C and are compiled to VML by the C compiler, so every language shares them:

Library filePurposeCore functions
softfloat.cQ15.16 fixed-point emulation of 32-bit floating point__vml_float_add/sub/mul/div/neg/abs/cmp, __vml_int2float/float2int
softdouble.cIEEE 754 software emulation of 64-bit double precision__vml_double_add/sub/mul/div/neg/abs/cmp, __vml_int2double/double2int, __vml_float2double/double2float
softint64.cdouble-register emulation of 64-bit integers__vml_i64_add/sub/neg/and/or/xor/not/shl/shr

5. Hardware interface

Memory-mapped I/O
AddressPurpose
0x60keyboard data port
0x64keyboard status port
0x300-0x304mouse X/Y/buttons
System calls
NumberFunction
1output a string
4output a character
5input a character
7input an integer
100-104device management
110-114file operations
Device management (syscall 100-104)
100: open a device     R0=device name address -> R0=handle
101: close a device    R0=handle
102: read a device     R0=handle, R1=buffer, R2=length
103: write a device    R0=handle, R1=data, R2=length
104: control a device  R0=handle, R1=command, R2=data, R3=length

6. Compiling

# compile
dotnet run --project VMLPrepares/BasicCompiler input.bas -o output.vml

# run (character mode)
dotnet run --project VMLEmulators/ConsoleEmulator -- --run output.vml

# run (VGA mode)

# run (GUI graphics mode)
dotnet run --project VMLEmulators/FullDevicesEmulator

🆕 String encoding (v1.65.19)

This language compiler uses the VML string system indirectly through the shared libraries (Lib/shared/).

DirectiveWidthEncodingC type
.string8-bitUTF-8char*
.wstring16-bitUTF-16LEwchar_t*
.ustring32-bitUTF-32LEchar32_t*

MCU mode (default): strings are emitted as UTF-8 (.string) OS mode: the encoding can be tested with the VML_WSTRING macro


v1.66.33 improvements (2026-08-01)

Every dialect at 90%+ completeness
CLASS/OOP support
Lexer
Preprocessor
Test coverage
Known limitations

The shared libraries already provide wide-string conversion functions (wchar.h/uchar.h), which each language compiler can use as needed.

Compiler README

BASIC compiler

Path: VMLPrepares/BasicCompiler/ | Version: v1.66.33 Completeness: 10 dialects, ≥90% each | 🟢 production ready (graphics/sound/files already work on phones) ⚠ The test numbers (78 / Lang_BASIC, VMLTests/, test/basic_examples/) belong to the upstream repository — this repository (the mobile copy after the fork) does not have the VMLTests/ or test/ directories, so those paths and numbers cannot be reproduced here. The check for this repository is scripts/vml-basic-probe/ (54 cases + 5 fileio.sh cases). Standard library: Lib/basic/

Multiple dialect support

The --basictype option selects one of 10 BASIC dialects:

DialectCLI valueFamilyCompleteness
QBasic (default)qbasicMicrosoft92%
GW-BASICgwbasicMicrosoft90%
VisualBasic 6visualbasicMicrosoft90%
TurboBasicturbobasicBorland90%
PowerBASICpowerbasicBorland90%
FreeBasicfreebasicopen source90%
PureBasicpurebasiccommercial90%
TrueBasictruebasicANSI/ISO90%
ChipBasicchipbasicMCU90%
MiniBasicminibasiceducational90%
vmltool -x basic --basictype freebasic test.bas -o test.vml
vmltool -x basic --basictype gwbasic test.bas -o test.vml

Keyword implementation

⚠ These numbers did not match the code for a long time (this README said 81/99, the same file further down said 116+, and the SPEC said 116/141). Recalculated from measurements in v0.96.506: 140 keywords in the lexer table, 171 TokenTypes; the 99-item table in ALL_KEYWORDS.md measures 89 implemented / 10 unimplemented. ALL_KEYWORDS.md is the authority — it marks the measured status of every entry.

Fully implemented
Partially implemented
Not implemented (needs a type system)

Dialect-specific features

FeatureDialectsDescription
CLASS/OOPFreeBasicclass/constructor/destructor/method/enum
GPIOChipBasicPINMODE/DIGITALWRITE/DIGITALREAD
GLOBALPureBasicmaps to SHARED
PROCEDUREPureBasicmaps to SUB
ENUM value assignmentFreeBasiccompile-time constants (RED+GREEN=30)
NEWPureBasicmaps to EmitAlloc heap allocation
Private/PublicVisualBasicmodifier recognition

File structure

BasicCompiler/
├── ASTNode.cs                 # AST nodes (measured: 171 TokenTypes)
├── Lexer.cs                   # lexing (measured: 140 keywords)
├── Parser.cs / Parser.*.cs    # parsing (10 dialects supported)
├── CodeGenerator.cs / *.cs    # code generation (TypedCodeGen<BasicType>)
├── BasicCompilerPlugin.cs     # plugin entry point + compilation pipeline
├── TokenType.cs               # the Token type enum
├── BASIC_LANGUAGE_SPEC.md     # language specification v2.1
├── ALL_KEYWORDS.md            # 99 keywords x 10 dialects
├── UNIMPLEMENTED_FEATURES.md  # list of unimplemented features
└── README.md                  # this file

Usage

# QBasic (default)
vmltool input.bas -o output.vml

# pick a dialect
vmltool -x basic --basictype freebasic input.bas -o output.vml
vmltool -x basic --basictype visualbasic input.bas -o output.vml

# compile + run
vmltool input.bas -o output.vml && vmltool -r output.vml

Tests

# run all BASIC tests
dotnet test VMLTests/VMLTests.csproj --filter "ClassName~Lang_BASIC"

# run the modern-feature tests
dotnet test VMLTests/VMLTests.csproj --filter "ClassName~Lang_ModernFeatures"