BASIC
老式写法,命令式一行一行往下走。
在手机上怎么跑
vml run examples/basic/test/sysinfo.bas
编译要等一会儿(C 那种要一两分钟,脚本类语言几秒)。程序跑起来后屏幕底部就是手柄,方向键 + 四个动作键都在;点右上角返回可以回到命令行。
写法要点
- 用到的每个
ui_*都要NATIVE FUNCTION/NATIVE SUB声明 - 无返回值的过程裸调(不写括号也可以)
- 一屏的
NATIVE声明不用自己抄 —— 写一行'$INCLUDE: 'vml_ui.bas'就把整张ui_*表拉进来了(见Lib/basic/vml_ui.bas) SCREEN/CLS/PSET/LINE/CIRCLE/PAINT/COLOR/PALETTE/LOCATE/DRAW/GET/PUT/POINT(x,y)/WIDTH手机上直接可用(编译器默认翻译成 宿主的ui_*图元);SCREEN n只决定开多大窗口PRINT在图形模式下落到窗口里(不是控制台),中文与框线正常- 浮点可用:
PRINT 3.14打3.14、PRINT 7 / 2打3.5(\才是整除)、整数不打多余的.0(PRINT 2.0打2) - 文件
OPEN/CLOSE/PRINT #/INPUT #/LINE INPUT #/FREEFILE都能用,路径落在你自己的工作区里(越界会被拒)
示例
| 文件 | 演示什么 |
|---|---|
app/blackjack.bas | 21 点(轮询式消息循环 + 振动) |
app/gorilla.bas | 猴子扔香蕉(完整游戏 + 音效) |
app/gorilla_pro.bas | 同上,加了渐变 / 路径 / 图块 |
app/hammurabi.bas | 汉谟拉比(回合制经营) |
app/hurkle.bas | 老式打字机式文本程序(内联了 _tty.bas) |
app/lander.bas | 登月舱 |
app/nibbles.bas | 贪吃蛇 |
app/tetris.bas | 俄罗斯方块(网格 + 手柄) |
app/whack.bas | 打地鼠(随机数 + 定时器 + 振动) |
bgi/demo_bgi.bas | 图形语句逐条演示 |
bgi/gfx_demo.bas | 同上 |
bgi/gfx_modes.bas | 各 SCREEN 模式的分辨率 |
test/sysinfo.bas | 设备信息 |
tty/demo_tty.bas | 文本模式(ANSI 彩色) |
ui/demo_ui.bas | 开窗 / 画图 / 消息循环的最小骨架 |
同目录还有: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
实测踩过的坑
- 形参名不能叫
on(关键字)。 FOR INPUT里的INPUT是关键字,不是普通标识符 —— 别的模式名(OUTPUT/APPEND)随便写就行。- 字符串拼接是好的,但一行里同时活着的串有上限(轮转缓冲 8 块),超过会互相覆盖。
FUNCTION的返回值槽是整数 —— 想返回浮点得绕(用SUB+ 输出参数)。- ⚠⚠
visualbasic方言只有一小半能用(2026-10-11 实测):Private/Public/Friend/With … End With/ByVal/As Integer|String|Object|Variant都好了(在默认 QBasic 方言下就生效,不必写--basictype)。但文档里那句「Visual Basic 6」说的另外几样没实现,而且症状很坑: · ✅Property Get/Let支持了(2026-10-11 新做):写在CLASS … END CLASS里,b.Value = 7走Let、PRINT b.Value走Get(属性访问没有括号)。 ⚠Property Set(对象赋值)还没做;写在类外会报「要写在 CLASS 里面」。 ⚠ v0.96.868 及以前它是静默的:编得过、跑得完、一个字都不打,而且它后面的代码整段消失(End Property被当成了「结束程序的 END」); ⚠ v0.96.868 及以前它是静默的:编得过、跑得完、一个字都不打,而且它后面的代码整段消失(End Property被当成了「结束程序的 END」); · 类的方法调用(语句位)能用(2026-10-11 新做):CLASS Counter/SUB Bump()/DIM a AS Counter/a.Bump⇒ 两个实例各加各的、互不串味。 ✅ 表达式位也能用(2026-10-11 新做):x = c.GetN()—— 类里的FUNCTION会被合成为真正的函数(AS 类型认得出来),表达式里直接当值用。 ·Sub Main会被自动调用(2026-10-11 新做):VB 的正规形态是「模块里只有声明与过程」,顶层一条可执行语句都没有 ⇒ 这时自动CALL Main(必须无参)。 ⚠ 顶层有代码就不自动调 ⇒ 老 QBasic 程序一条都不受影响。 · 对象构造能用(2026-10-11 新做):DIM c AS NEW Counter与SET c = NEW Counter都行 —— 两条写法降级成同一条路径(声明带NEW就发出那次CALL Counter_constructor(&c))。 ⚠ 只有写了NEW才构造(VB6 的Dim c As Counter不构造);类里没写CONSTRUCTOR时什么也不发。 ·MsgBox支持(VBA/VB6 的对话框,2026-10-11 新做)—— 落到宿主的ui_dlg_msg。 ⚠ 按钮是宿主画的,本平台只有「是/否」与「确定」两种观感(vbOKCancel的「取消」按不出来);返回值由前端按 VB 语义给足(是/否 →vbYes/vbNo= 6/7,其余 →vbOK= 1)。vb*那批常量只在--basictype visualbasic下登记(QBasic 里没有它们)。 ·Set x = New C—— 报一句专指的话(New不能写在表达式里:VB 的Set 对象 = New 类型对象构造还没实现;单独成句的NEW 类型是 PureBasic 的堆分配); ·Optional/ParamArray—— 现在会打一条 warning(修饰符被忽略、该形参按必填处理)。 ⚠ 此前是静默吃掉,而且会把它当成一个形参名 ⇒ 多一个形参、后面那个真形参错位。 · 窗体/控件/事件(Form_Load、Me.)现阶段不做 —— 用户 2026-10-11:「VB6 的窗体程序,以后再去评估能否实现,现阶段不考虑;界面无关的部分可以实现的就实现」(同日另一句:「界面库太大了,支持不了」)⇒ 老 VB6 窗体程序现阶段别指望;但界面无关的语言层(对象构造、Property、类方法调用…)能做就做 —— 这几样都已经做了(类方法调用 /MsgBox/Set … = New/ 表达式位调用 /Property)。
下面的内容是从 VML 源码里直接带的(third_party/vml/VMLPrepares/BasicCompiler/): README 讲这个前端支持什么、怎么编;语言规范 讲语法本身。上游一改,这里重新生成就是最新的。
语言规范
BASIC 语言编译器规范说明
版本:v2.1 | 日期:2026-08-01 | 修订者:深圳市探索智能科技有限公司 更新: v1.66.33 — 全方言 ≥90% + CLASS/OOP + GPIO + 140 条关键字(实测,v0.96.506)
规范标准
| 字段 | 值 |
|---|---|
| 目标标准 | QBasic (默认) + 9 种方言(共 10 个 BasicDialect 成员,见 VMLPlugins/CompilerOptions.cs), 全部 ≥90% 完成度 |
| CLI 选项 | --basictype qbasic|turbobasic|freebasic|truebasic|purebasic|chipbasic|minibasic |
| 完成度 | 92% (QBasic), 90% (全部方言) |
| 测试 | 63 通过 (Lang_BASIC) + 22 方言测试 |
| Token 总数 | 140 条关键字(实测,v0.96.506), 171 个 TokenType(实测,v0.96.506) |
多方言关键字集合
BASIC 编译器通过 --basictype 选项支持 10 种方言。下方列出每种方言的关键字差异。
1. QBasic (默认) — __QBASIC__
Microsoft QBasic/QuickBASIC 兼容。所有后续方言以此为基础。
独有关键字 (14): PSET, CIRCLE, PAINT, DRAW, VIEW, WINDOW, PALETTE, SCREEN, LPRINT, PRINT USING, FREEFILE, ON ERROR, RESUME, DEF FN
适用场景: DOS 时代 QBasic 程序、QuickBASIC 游戏 (GORILLAS/NIBBLES)
2. TurboBasic — __TURBOBASIC__
Borland Turbo Basic 兼容。
QBasic 基础上新增 (6): EXIT, DO, LOOP, UNTIL, CASE ELSE, FUNCTION
移除 (与 QBasic 差异) (8): PSET, CIRCLE, PAINT, DRAW, VIEW, WINDOW, PALETTE, SCREEN
适用场景: 科学计算、结构化 BASIC 程序
3. FreeBasic — __FREEBASIC__
开源跨平台 BASIC 编译器兼容。
QBasic 基础上新增 (12): PTR, CAST, CPTR, ANY, EXTENDS, OPERATOR, PROPERTY, ENUM, NAMESPACE, USING, DESTRUCTOR, CONSTRUCTOR
移除 (与 QBasic 差异) (6): LPRINT, PRINT USING, PSET, CIRCLE, DRAW, PALETTE
适用场景: 现代开源 BASIC 项目、跨平台开发
4. TrueBasic — __TRUEBASIC__
ANSI/ISO 标准 BASIC。
QBasic 基础上新增 (4): MAT, ZER, CON, SOUND
移除 (与 QBasic 差异) (12): SELECT, CASE, IS, ELSEIF, DO, LOOP, EXIT, GOSUB, PEEK, POKE, LPRINT, ON ERROR
适用场景: 教育、标准兼容程序
5. PureBasic — __PUREBASIC__
PureBasic 兼容。
QBasic 基础上新增 (8): PROCEDURE, ENDPROCEDURE, PROTECTED, GLOBAL, THREADED, INTERFACE, ENDINTERFACE, NEW
移除 (与 QBasic 差异) (10): GOSUB, RETURN, LPRINT, PSET, CIRCLE, DRAW, VIEW, WINDOW, PALETTE, DEF FN
适用场景: 游戏开发、GUI 应用
6. ChipBasic — __CHIPBASIC__
MCU 优化方言。
QBasic 基础上新增 (3): PINMODE, DIGITALWRITE, DIGITALREAD
移除 (与 QBasic 差异) (15): SCREEN, PSET, LINE, CIRCLE, PAINT, DRAW, VIEW, WINDOW, PALETTE, LPRINT, PRINT USING, FREEFILE, ON ERROR, RESUME, CHIPASM
适用场景: 嵌入式 MCU (Arduino/STM32)、IoT 设备
7. MiniBasic — __MINIBASIC__
最小子集 — 教学/资源受限环境。
QBasic 基础上新增 (0): 无新增。
移除 (与 QBasic 差异) (20): TYPE, DIM, REDIM, ERASE, SWAP, SHARED, COMMON, SELECT, CASE, DO, LOOP, EXIT, GOSUB, GOTO, CALL, LPRINT, PRINT USING, PSET, CIRCLE, DRAW
保留关键字 (仅 15): PRINT, INPUT, IF, THEN, ELSE, FOR, NEXT, WHILE, WEND, LET, REM, DIM(简化), END, GOTO(简化), GOSUB(简化)
适用场景: 教学、微控制器引导程序
方言关键字对比总表
| 类别 | QBasic | TurboBasic | FreeBasic | TrueBasic | PureBasic | ChipBasic | MiniBasic |
|---|---|---|---|---|---|---|---|
| 关键字总数 | ~70 | ~68 | ~76 | ~62 | ~68 | ~57 | ~15 |
| 完成度 | 92% | 90% | 90% | 90% | 90% | 90% | 90% |
| 图形 | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| OOP | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ |
| MCU GPIO | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| 行号 | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | 可选 |
| GOSUB | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | 简化 |
QBasic 关键字完整列表 (按类别)
控制流 (14)
IF, THEN, ELSE, ELSEIF, END, END IF, SELECT, CASE, IS, TO, FOR, STEP, NEXT, WHILE, WEND, DO, LOOP, UNTIL, EXIT, GOTO, GOSUB, RETURN
子程序/函数 (7)
SUB, FUNCTION, CALL, BYVAL, BYREF, DECLARE, DEF FN
变量/数据 (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
图形 (17)
SCREEN, PSET, LINE, CIRCLE, PAINT, DRAW, COLOR, LOCATE, CLS, VIEW, WINDOW, PALETTE, GET, PUT, WIDTH, BEEP
函数 (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
其它 (9)
REM, DATA, READ, RESTORE, SLEEP, SYSTEM, ON ERROR, RESUME, CHIPASM, ASM
运算符完整列表 (优先级从高到低)
| 优先级 | 运算符 | Token | 说明 |
|---|---|---|---|
| 1 | ^ | EXPONENT | 指数 |
| 2 | - (一元) | MINUS | 负号 |
| 3 | * / | MULTIPLY, DIVIDE | 乘除 |
| 4 | + - | PLUS, MINUS | 加减 |
| 5 | = < > <= >= <> | EQUALS, LESS, GREATER, LESS_EQUAL, GREATER_EQUAL, NOT_EQUAL | 关系 |
| 6 | NOT | NOT | 逻辑非 |
| 7 | AND | AND | 逻辑与 |
| 8 | OR | OR | 逻辑或 |
分隔符
| 符号 | Token | 用途 |
|---|---|---|
, | COMMA | 参数/分栏分隔 |
; | SEMICOLON | PRINT 不换行 |
: | COLON | 多语句分隔 |
. | DOT | 成员访问 |
" | QUOTE | 字符串定界 |
( ) | LPAREN, RPAREN | 函数/数组括号 |
# | HASH | 文件号前缀 |
3. 语句参考
3.1 基本 I/O
' PRINT — 输出到控制台
PRINT "Hello" ' 字符串
PRINT 42 ' 数字
PRINT A; B; ' 分号不换行
PRINT A, B ' 逗号分栏
PRINT ' 空行
' INPUT — 键盘输入
INPUT "prompt: ", X
INPUT A, B, C
INPUT A$
' LPRINT — 打印机输出
LPRINT "Hello"
PRINT 输出目标规则
PRINT 的输出目标由 SCREEN 模式决定:
| 模式 | 控制台输出 | 内存输出 | 说明 |
|---|---|---|---|
| 默认(无 SCREEN) | ✅ | ❌ | 仅输出到控制台终端 |
| SCREEN 0(文本模式) | ✅ | ✅ 0xB8000 | 控制台 + VGA 文本显存同时输出 |
| SCREEN N>0(图形模式) | ❌ | ✅ VGA 帧缓冲 | 仅渲染到 VGA 图形帧缓冲,控制台不输出 |
具体机制:
- SYSCALL #4:纯控制台输出,不涉及 VGA。处理 BEL 蜂鸣和 UTF-8 解码
- 文本模式 VGA:由扩展库
vga_text_putchar(Lib/shared/vga_text.vml) 处理,写入0xB8000文本显存并管理光标。BASIC 编译器默认链接此库,在每次 SYSCALL #4 前调用 - 图形模式 VGA:编译器为每个 PRINT 字符生成
EmitGfxPrintChar()调用,从 8×8 位图字库渲染像素到 VGA 图形帧缓冲 - 两者各自检查 SCREEN 模式(0x6FF0),仅在各自模式激活时执行,互补工作
- LOCATE 设置的光标位置在文本模式和图形模式下均有效(通过
0x6FF4/0x6FF8共享)
3.2 变量操作
' LET (可省略)
LET A = 42
B = A + 10
' SWAP — 变量交换
SWAP A, B
' ERASE — 清除数组
ERASE ArrayName
' DIM — 数组声明
DIM A(10) ' 一维
DIM B(5, 5) ' 二维
DIM C(3, 3, 3) ' 三维
DIM S$(10) ' 字符串数组
3.3 控制流
' IF
IF condition THEN
...
ELSEIF condition THEN
...
ELSE
...
END IF
' 单行 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 子程序与函数
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 图形 (标准 QBASIC 语法)
SCREEN 9 ' 设置图形模式
WIDTH 80, 25 ' 设置文本尺寸
COLOR 7, 0 ' 前景色, 背景色
CLS ' 清屏
LOCATE 10, 20 ' 光标定位
PSET (100, 150), 4 ' 画点 (x, y), 颜色索引
LINE (0,0)-(100,100), 2 ' 画线
LINE (0,0)-(100,100), 2, B ' 矩形边框
LINE (0,0)-(100,100), 2, BF ' 填充矩形
CIRCLE (160,120), 50, 3 ' 画圆
PAINT (160,120), 4, 3 ' 填充
' 图形字符串宏 (DRAW)
DRAW "U10 R20 D10 L20" ' 绘图字符串
SCREEN 模式对 PRINT 的影响 SCREEN 语句切换显示模式,PRINT 输出到控制台。
3.6 VML 扩展图形
VGAPUTPIXEL x, y, r, g, b ' 24位彩色画点
VGADRAWLINE x1,y1,x2,y2,r,g,b ' 彩色画线
VGADRAWCIRCLE x,y,radius,r,g,b ' 彩色画圆
VGAFILLCIRCLE x,y,radius,r,g,b ' 彩色填充圆
VGADRAWRECT x,y,w,h,r,g,b ' 彩色矩形边框
' 字符串
LEN(s$), CHR$(n), ASC(s$), STR$(n), VAL(s$)
LEFT$(s$, n), RIGHT$(s$, n), MID$(s$, start, len)
' 随机
RND(n)
RANDOMIZE [TIMER]
' 内存
PEEK(addr)
POKE addr, value
' 时间
TIMER, DATE$, TIME$
' 检测
KBGETCH(), KBHIT()
MOUSEGETX(), MOUSEGETY(), MOUSELEFT(), MOUSERIGHT()
VGAGETPIXEL(x,y), VGAGETWIDTH(), VGAGETHEIGHT()
3.7 文件操作
OPEN "file.txt" FOR INPUT AS #1
OPEN "file.txt" FOR OUTPUT AS #2
INPUT #1, X
PRINT #2, "Hello"
CLOSE #1
3.9 音频
' PLAY — 音乐字符串播放
PLAY "C D E F G A B"
PLAY "O3 L4 CDEFGAB"
' SOUND — 频率/持续时间
SOUND 440, 18 ' 频率(Hz), 持续时间(1/18秒)
' BEEP — 系统蜂鸣
BEEP
3.10 错误处理
' ON ERROR GOTO — 运行时错误处理
ON ERROR GOTO ErrorHandler
... 正常代码 ...
EXIT SUB
ErrorHandler:
PRINT "错误: "; ERR
RESUME NEXT
3.11 数据类型与结构
' CONST — 常量定义
CONST PI = 3.14159
CONST MAX_ROWS = 25
' TYPE / END TYPE — 自定义类型
TYPE Point
X AS INTEGER
Y AS INTEGER
END TYPE
' 自定义类型使用
DIM P AS Point
P.X = 10
P.Y = 20
' DATA/READ/RESTORE — 内嵌数据
DATA 1, 2, 3, 4, 5
FOR I = 1 TO 5
READ X
PRINT X
NEXT
RESTORE
' DEF FN — 单行自定义函数
DEF FNAdd(a, b) = a + b
PRINT FNAdd(3, 5)
' COMMON — 模块共享变量
COMMON SHARED Score, Lives
' REDIM/PRESERVE — 动态数组重定义
DIM A(10)
REDIM A(20)
REDIM PRESERVE A(30) ' 保留原有数据
3.12 其他
SLEEP [seconds] ' 暂停
SWAP A, B ' 变量交换
ERASE ArrayName ' 清除数组
SYSTEM ' 退出程序
exit(code) ' 退出并返回code给系统 (SYSCALL 3)
END ' 程序结束
DEFINT A-C ' 类型声明 (兼容)
DEFSNG D-F
DEFSTR S
' OPTION BASE — 数组下标起始
OPTION BASE 0 ' 数组从0开始 (默认)
OPTION BASE 1 ' 数组从1开始
' INKEY$ — 无阻塞按键检测
K$ = INKEY$
IF K$ <> "" THEN PRINT "Key: "; K$
' DECLARE — 前置声明子程序
DECLARE SUB MySub(x)
DECLARE FUNCTION MyFunc(x, y)
' LOCAL / STATIC / SHARED / COMMON
SUB MyProc()
LOCAL temp ' 局部变量
STATIC count ' 静态变量 (持久)
SHARED globalVar ' 共享变量
END SUB
COMMON SHARED Score, Lives ' 模块共享
3.13 调用约定与内联汇编
' __stdcall 调用约定 — 参数全部栈传递,被调用者清理
SUB MyFunc STDCALL(a, b)
MyFunc = a + b
END SUB
' ASM — 内联 VML 汇编
ASM "MOVE R0, #42"
ASM "SYSCALL #4"
' CHIPASM — 内联目标架构汇编 (6502/Z80/8051 等)
CHIPASM "LDA #$42"
CHIPASM "STA $0400"
3.14 高级图形 (GET/PUT/PALETTE/VIEW/WINDOW)
' PALETTE — 设置调色板颜色 (SCREEN 13 模式)
PALETTE 0, 0, 0, 0 ' 索引0=黑色
PALETTE 1, 63, 0, 0 ' 索引1=红色
PALETTE 2, 0, 63, 0 ' 索引2=绿色
' GET — 保存屏幕区域到数组
DIM buffer(200)
CIRCLE (50,50), 10, 2
GET (40,40)-(60,60), buffer
' PUT — 从数组恢复屏幕区域
PUT (100,100), buffer ' 直接覆盖
PUT (100,100), buffer, 1 ' XOR 模式
' VIEW — 设置图形视口
VIEW (10,10)-(200,100) ' 视口区域
VIEW (10,10)-(200,100), 2, 4 ' 带颜色边框
' WINDOW — 设置逻辑坐标系统
WINDOW (0,0)-(1,1) ' 逻辑坐标 0-1
CIRCLE (0.5,0.5), 0.3 ' 在逻辑坐标中绘制
3.15 PRINT USING — 格式化输出
PRINT USING "###.##"; 12.345 ' 输出: 12.35
PRINT USING "####"; 42 ' 输出: 42
PRINT USING "$$###.##"; 12.3 ' 输出: $ 12.30
4. 与标准 QBASIC 的差异
不支持的特性
SHELL/CHAIN/RUN— 外部程序调用(裸机环境不支持)LINE INPUT— 行输入(可替代为 INPUT)FIELD/LSET/RSET— 随机文件字段操作
扩展特性
- 完整的中文标识符和字符串
- VGA 24位彩色图形扩展 (VGAPUTPIXEL 等)
- 设备描述文件支持 (devices/*.json)
- 多平台模拟 (PC, Apple II, C64 等)
POKE/PEEK内存映射 I/O__stdcall调用约定,支持跨语言函数互操作- PRINT 输出目标根据 SCREEN 模式自动切换:图形模式下仅渲染到 VGA 帧缓冲,控制台无输出(与 QBASIC 的物理 VGA 显卡行为一致)
浮点与64位编译模式
VML 工具链通过三个编译参数控制浮点和 64 位整数的处理策略:
| 参数 | 可选值 | 默认值 | 说明 |
|---|---|---|---|
--float32 | hard / soft / none | hard | 32位浮点 (SINGLE/!) 处理模式 |
--float64 | hard / soft / none | soft | 64位浮点 (DOUBLE/#) 处理模式 |
--int64 | hard / soft / none | soft | 64位整数处理模式 |
32位浮点 (float32)
本语言中的 32 位单精度浮点类型 SINGLE / ! 按以下模式编译:
hard模式(默认): 使用 VML 原生浮点指令MOVEF/ADDF/SUBF/MULF/DIVF/CMPF/NEGF,通过 F0-F15 十六个浮点寄存器直接运算。性能最佳,适合支持浮点硬件的目标平台。soft模式: 使用 Q15.16 定点数软件模拟库softfloat.c,通过__vml_float_add/sub/mul/div/neg/abs/cmp等函数模拟浮点运算。适合无浮点硬件的 MCU 平台。none模式: 禁用所有 32 位浮点类型,遇到浮点声明时报告编译错误。
64位浮点 (double)
本语言中的 64 位双精度浮点类型 DOUBLE / # 按以下模式编译:
soft模式(默认): 使用 IEEE 754 双精度软件模拟库softdouble.c,通过__vml_double_add/sub/mul/div/neg/abs/cmp、__vml_int2double/double2int、__vml_float2double/double2float等函数模拟。兼容所有平台(含 MCU)。hard模式: 使用 VML 双精度指令MOVED/ADDD/SUBD/MULD/DIVD/CMPD/NEGD,通过 D0-D7 八个双精度寄存器运算。需要目标平台支持 64 位运算。none模式: 禁用所有 64 位浮点类型,遇到浮点声明时报告编译错误。
64位整数 (int64)
64 位整数类型在本语言中由 VML 编译层支持,BASIC 标准中未定义对应的显式类型,但编译器预留了通过 --int64 扩展支持的可能性。
soft模式(默认): 使用双寄存器软件模拟库softint64.c,通过__vml_i64_add/sub/neg/and/or/xor/not/shl/shr等函数模拟 64 位整数运算。hard模式: 预留,未来 VML 版本将支持原生 64 位整数指令。none模式: 禁用 64 位整数扩展。
软件模拟库
以上软件模拟库均位于 Lib/shared/ 目录,使用 C 语言编写并由 C 编译器编译为 VML,所有语言共享:
| 库文件 | 用途 | 核心函数 |
|---|---|---|
softfloat.c | Q15.16 定点数 32 位浮点模拟 | __vml_float_add/sub/mul/div/neg/abs/cmp、__vml_int2float/float2int |
softdouble.c | IEEE 754 双精度 64 位浮点模拟 | __vml_double_add/sub/mul/div/neg/abs/cmp、__vml_int2double/double2int、__vml_float2double/double2float |
softint64.c | 64 位整数双寄存器模拟 | __vml_i64_add/sub/neg/and/or/xor/not/shl/shr |
5. 硬件接口
内存映射 I/O
| 地址 | 用途 |
|---|---|
| 0x60 | 键盘数据端口 |
| 0x64 | 键盘状态端口 |
| 0x300-0x304 | 鼠标 X/Y/按钮 |
系统调用
| 编号 | 功能 |
|---|---|
| 1 | 输出字符串 |
| 4 | 输出字符 |
| 5 | 输入字符 |
| 7 | 输入整数 |
| 100-104 | 设备管理 |
| 110-114 | 文件操作 |
设备管理 (syscall 100-104)
100: 打开设备 R0=设备名地址 → R0=句柄
101: 关闭设备 R0=句柄
102: 读设备 R0=句柄, R1=缓冲区, R2=长度
103: 写设备 R0=句柄, R1=数据, R2=长度
104: 控制设备 R0=句柄, R1=命令, R2=数据, R3=长度
6. 编译
# 编译
dotnet run --project VMLPrepares/BasicCompiler input.bas -o output.vml
# 运行 (字符模式)
dotnet run --project VMLEmulators/ConsoleEmulator -- --run output.vml
# 运行 (VGA 模式)
# 运行 (GUI 图形模式)
dotnet run --project VMLEmulators/FullDevicesEmulator
🆕 字符串编码 (v1.65.19)
该语言编译器通过共享库 (Lib/shared/) 间接使用 VML 字符串体系。
| 伪指令 | 宽度 | 编码 | C 类型 |
|---|---|---|---|
.string | 8-bit | UTF-8 | char* |
.wstring | 16-bit | UTF-16LE | wchar_t* |
.ustring | 32-bit | UTF-32LE | char32_t* |
MCU 模式 (默认): 字符串输出为 UTF-8 (.string) OS 模式: 可通过 VML_WSTRING 宏判断编码
v1.66.33 改进 (2026-08-01)
全方言 90%+ 完成度
- PureBasic: GLOBAL → SHARED, PROCEDURE → SUB (Lexer 映射)
- ChipBasic: PINMODE/DIGITALWRITE/DIGITALREAD → GpioStatement
- FreeBasic: ENUM 编译通过, PTR/CAST/EXTENDS/OPERATOR 识别
- TrueBasic: MAT/ZER/CON 识别
CLASS/OOP 支持
- CLASS 关键字 → 映射到 TYPE_KW 统一解析
- 类声明: CLASS name ... END CLASS (字段 + 方法)
- 构造函数: CONSTRUCTOR 块
- 方法: METHOD name(params) ... END METHOD
- 属性: PROPERTY (token 已注册)
- 析构函数: DESTRUCTOR (token 已注册)
词法分析器
- 140 条关键字、171 个
TokenType(实测,v0.96.506 —— 此前这里写的是 116 / 141) - 支持 10 种方言的特有关键字
- 关键字大小写不敏感 (LexerBase.ReadIdentifier)
预处理器
- 支持
#param lib("name")/#param path("dir")指令 - 支持
#include,#define,#undef,#if/#else/#endif - 每个方言自动定义宏:
__QBASIC__,__FREEBASIC__等
测试覆盖
- 63 个单元测试 (Lang_BASIC.cs)
- 22 个多方言测试 (7 方言 × 特有关键字)
- 5 个 TYPE/CLASS 结构体测试
- FreeBasic 示例程序 (14 个测试文件)
已知限制
- CLASS 方法体尚未链接到调用点 (Phase 3)
- EXTENDS/INTERFACE 语义待实现
- GPIO 语句编译通过但未生成实际调用
- PTR/CAST 指针语义待实现
共享库已提供宽字符串转换函数 (wchar.h/uchar.h),各语言编译器可按需使用。
编译器 README
BASIC 编译器
路径: VMLPrepares/BasicCompiler/ | 版本: v1.66.33 完成度: 10方言 ≥90% | 🟢 生产可用(图形/声音/文件已通手机端) ⚠ 测试数字(78 / Lang_BASIC、VMLTests/、test/basic_examples/)是上游仓库的 —— 本仓(分家后的移动端副本)没有 VMLTests/ 与 test/ 这两个目录,那些路径与数字在这里复现不了。本仓的判据是 scripts/vml-basic-probe/(54 例 + fileio.sh 5 例)。 标准库: Lib/basic/
多方言支持
通过 --basictype 选项支持 10 种 BASIC 方言:
| 方言 | CLI 值 | 派系 | 完成度 |
|---|---|---|---|
| QBasic (默认) | qbasic | Microsoft | 92% |
| GW-BASIC | gwbasic | Microsoft | 90% |
| VisualBasic 6 | visualbasic | Microsoft | 90% |
| TurboBasic | turbobasic | Borland | 90% |
| PowerBASIC | powerbasic | Borland | 90% |
| FreeBasic | freebasic | 开源 | 90% |
| PureBasic | purebasic | 商业 | 90% |
| TrueBasic | truebasic | ANSI/ISO | 90% |
| ChipBasic | chipbasic | MCU | 90% |
| MiniBasic | minibasic | 教学 | 90% |
vmltool -x basic --basictype freebasic test.bas -o test.vml
vmltool -x basic --basictype gwbasic test.bas -o test.vml
关键字实现
⚠ 这里的数字此前对不上代码(README 写 81/99、同文件下面又写 116+,SPEC 又写 116/141)。按 v0.96.506 实测重算:词法表 140 条关键字、TokenType 171 个; ALL_KEYWORDS.md 那张 99 项的表按实测是 89 实现 / 10 未实现。 以 ALL_KEYWORDS.md 为准,它逐条标了实测状态。
完全实现
- ✅ 控制流: IF/THEN/ELSE/ELSEIF/SELECT CASE/FOR/NEXT/WHILE/WEND/DO/LOOP/GOTO/GOSUB
- ✅ 子程序: SUB/END SUB/FUNCTION/CALL/DECLARE/BYVAL/BYREF/PROCEDURE
- ✅ 变量: DIM/LET/CONST/SWAP/ERASE/REDIM/SHARED/COMMON/STATIC/LOCAL/GLOBAL
- ✅ I/O: PRINT/INPUT/OPEN/CLOSE/WRITE/LPRINT/PRINT USING/FREEFILE/LINE INPUT # (⚠ 文件那一族是 v0.96.503/504 才真做通的:此前 OPEN 的句柄根本没存、
PRINT #/INPUT #走的是设备号而不是文件号、FREEFILE只有词法条目。现在全部改走吃沙箱的#110-113,判据见scripts/vml-basic-probe/fileio.sh) - ⚠️ OOP (FreeBasic): CLASS/METHOD/ENUM ✅;CONSTRUCTOR 只到"解析"、DESTRUCTOR 无代码
- ✅ 数学: ABS/SGN/SQR/SIN/COS/TAN/INT/FIX/RND/RANDOMIZE
- ✅ 字符串: LEN/CHR$/ASC/STR$/VAL/LEFT$/RIGHT$/MID$
- ⚠️ MCU: CHIPASM/ASM/BLOAD/BSAVE ——
ASM已从词法表移除(注释写着"仅限 C/ObjC/C++");BLOAD/BSAVE会生成 GPIO 调用但缺运行时库,且手机上没有 GPIO ⇒ 实际不可用 - ✅ 其他: REM/DATA/READ/RESTORE/ON ERROR/RESUME/SLEEP/SYSTEM/BEEP/SOUND
部分实现
- ⚠️ PROPERTY, CONSTRUCTOR (框架就绪, 待完善)
未实现 (需类型系统)
- ❌ PTR, CAST, EXTENDS, OPERATOR, INTERFACE
方言特有功能
| 功能 | 适用方言 | 说明 |
|---|---|---|
| CLASS/OOP | FreeBasic | 类/构造/析构/方法/枚举 |
| GPIO | ChipBasic | PINMODE/DIGITALWRITE/DIGITALREAD |
| GLOBAL | PureBasic | → SHARED 映射 |
| PROCEDURE | PureBasic | → SUB 映射 |
| ENUM 值代入 | FreeBasic | 编译时常量 (RED+GREEN=30) |
| NEW | PureBasic | → EmitAlloc 堆分配 |
| Private/Public | VisualBasic | 修饰符识别 |
文件结构
BasicCompiler/
├── ASTNode.cs # AST 节点 (实测 171 个 TokenType)
├── Lexer.cs # 词法分析 (实测 140 条关键字)
├── Parser.cs / Parser.*.cs # 语法分析 (10方言支持)
├── CodeGenerator.cs / *.cs # 代码生成 (TypedCodeGen<BasicType>)
├── BasicCompilerPlugin.cs # 插件入口 + 编译流水线
├── TokenType.cs # Token 类型枚举
├── BASIC_LANGUAGE_SPEC.md # 语言规范 v2.1
├── ALL_KEYWORDS.md # 99关键字×10方言清单
├── UNIMPLEMENTED_FEATURES.md # 未实现特性清单
└── README.md # 本文件
使用
# QBasic (默认)
vmltool input.bas -o output.vml
# 指定方言
vmltool -x basic --basictype freebasic input.bas -o output.vml
vmltool -x basic --basictype visualbasic input.bas -o output.vml
# 编译 + 运行
vmltool input.bas -o output.vml && vmltool -r output.vml
测试
- 78 单元测试 (
VMLTests/Lang_BASIC.cs): 方言关键字 + TYPE/CLASS + ENUM - 22 方言测试: 7方言特有关键字 + 跨方言兼容性
- 14 FreeBasic 示例 (
test/basic_examples/freebasic/): class/constructor/method/pointers等 - QBasic 游戏: gorillas.bas, nibbles.bas
# 运行所有 BASIC 测试
dotnet test VMLTests/VMLTests.csproj --filter "ClassName~Lang_BASIC"
# 运行现代特性测试
dotnet test VMLTests/VMLTests.csproj --filter "ClassName~Lang_ModernFeatures"