← 都来码← 文档索引Perl原文English

Perl

「完整运算 + 控制流 + 函数调用」那一档:数组(@a)、哈希(%h)、子程序、字符串处理、循环、递归都能写 —— 覆盖到词频统计那种规模。

print 可以一次给多个参数(照原样连着打,不加分隔);双引号串里 $var 会插值。

在手机上怎么跑

vml run examples/perl/app/wordcount.pl

编译要等一会儿(C 那种要一两分钟,脚本类语言几秒)。程序跑起来后屏幕底部就是手柄,方向键 + 四个动作键都在;点右上角返回可以回到命令行。

写法要点

示例

文件演示什么
app/wordcount.pl词频统计(split + 哈希计数 + scalar)
hello.pl最小程序(print 多参 + 双引号插值)
test/syntax.pl语言小抄:每种形态各用一遍

实测踩过的坑


下面的内容是从 VML 源码里直接带的(third_party/vml/VMLPrepares/PerlCompiler/): README 讲这个前端支持什么、怎么编;语言规范 讲语法本身。上游一改,这里重新生成就是最新的。

语言规范

Perl 子集语言规格 —— PerlCompiler 实现了什么

本文是 PerlCompiler 前端的实现口径:支持哪些语法/语义、静默坑在哪、哪些有意不支持 (且在编译期报错,不假装支持)。对应英文版见 [PERL_LANGUAGE_SPEC.en.md](PERL_LANGUAGE_SPEC.en.md)。

版本:v1.0 | 日期:2026-10-13 | 修订者:深圳市探索智能科技有限公司

规范标准

字段值
目标标准Perl 5 子集
发布年份1994
完成度子集(未逐项统计)
测试24 通过 / 0 失败

关键字

my our sub if elsif else unless while until for foreach do last next redo return and or not print say use defined undef eq ne lt gt le ge cmp qw

概述

支持 Perl 5 子集,编译为 VML 汇编代码。变量带 sigil($ 标量 / @ 数组 / % 哈希,$x、@x、%x 在词法层就是三个独立的名字),换行是语句分隔符(与 ; 等价);有意不跑 C 预处理器(Perl 用 # 作行注释,一见 # 就跑预处理会把每条注释当成指令)。前端没有运行期类型标签:按编译期能定的信息在整数 / 浮点 / 字符串三条通道之间选择(从 @_ 取出的形参、未知库函数的返回值属于类型未知,见 §8);未实现的内置在编译期报错,没有「悄悄按 0 跑过去」的兜底。

支持的语言特性

本前端接受的语言特性按下方原有章节组织,每节都写明「收什么写法、是什么语义」:

详见下方各节。

0. 总则

1. 词法

形态说明
注释# 到行尾
数字十进制整数、0x… 十六进制、小数(如 1.5)。整数是 32 位(超出按低 32 位截断)
单引号串只认 \\ 与 \' 两个转义,其余原样
双引号串认 \n \t \r \0 \\ \" \$ \@;$name / ${name} 插值;@name 不插值(见 §5)
标识符字母 / 数字 / _ / 汉字
sigil$ 标量、@ 数组、% 哈希。% 后跟标识符才算 sigil,否则是取模算子
$#a数组 a 的末位下标(= 长度 − 1)
换行是语句分隔符(与 ; 等价);但上一 token 是算子/逗号/开括号时抑制,于是跨行写法照常算一条语句

关键字:my our sub if elsif else unless while until for foreach do last next redo return and or not print say use defined undef eq ne lt gt le ge cmp qw。

2. 变量与声明

3. 表达式与运算

4. 语句与控制流

5. 字符串

6. 数组与哈希

7. 子程序与 use

sub add { my ($x, $y) = @_; return $x + $y; }   # 或 sub add($x, $y) { … }
print add(3, 4);

8. 类型的编译期推断(为什么会"看走眼")

本前端没有运行期类型标签。前端按编译期能定的信息在整数 / 浮点 / 字符串之间选通道:

9. 有意不支持(多数在编译期报错)

特性状态
sort / reverse / each / ucfirst / lcfirst / rindex编译期报错「尚未实现」
引用 \、解引用、匿名数组/哈希不支持
正则 =~、s///、tr///不支持
包 / package / 对象 / bless不支持
local / state / our 的包语义不支持(our 等同 my)
substr 作为左值、wantarray、context(标量/列表上下文)不支持
文件句柄 / open / <> / printf 到句柄不支持(要看文件走共享库 / UI 工具)
qw()支持(拆成字符串列表)
64 位整数不支持(32 位)
浮点打印格式走共享运行时的 print_double,固定 6 位小数(3.4 可能显示成 3.399999,那是共享 dtoa 的舍入口径,不是本前端算错)

10. 判据

scripts/vml-perl-probe/run.sh 跑 bugs/vml_perl_bugs/t*.pl,逐条比 stdout。判据走的是 vmlcli <用例> --lang perl 这条真实通道(注册表 → 汇编 → 链接 → 运行), 刻意不绕开注册表 —— 绕开那条路自带一份链接集,会把"真实通道缺本语言模块集"盖过去。 实测(接线 + GenLib -m -l perl 之后):通过 24 / 失败 0。

判据可红性已实测三遍:

判据可红性已实测两遍:

编译器 README

Perl 前端编译器(PerlCompiler)

把 Perl 的一个子集编译成 VML 汇编。它是 third_party/vml/VMLPrepares/ 下的第 23 门前端,与其它前端同构:Lexer / Parser / ASTNode / CodeGenerator / PerlPlugin,继承 CompilerBase,由 CompilerPluginExBase 接进宿主。

语言范围(支持什么、不支持什么、为什么)见 [PERL_LANGUAGE_SPEC.md](PERL_LANGUAGE_SPEC.md)。接线到宿主 / GenLib / 打包的逐条改动见 [INTEGRATION.md](INTEGRATION.md)。

一句话定位

「完整运算 + 控制流 + 函数调用」 那一档 —— 能写一般的脚本程序(数组 / 哈希 / 子程序 / 字符串处理 / 循环 / 递归),不是"能编过 hello world"的骨架。覆盖到 Examples/perl/app/wordcount.pl(词频统计)这种规模。

快速上手

# ① 编译前端本体(开发期它就是一个 CLI)
dotnet build third_party/vml/VMLPrepares/PerlCompiler -c Release

# ② 编一个 .pl 成**独立可运行**的 VML 汇编(标准库已链进去)
dotnet third_party/vml/VMLPrepares/PerlCompiler/bin/Release/net10.0/PerlCompiler.dll \
       examples/perl/hello.pl -o /tmp/hello.vml

# ③ 跑
dotnet scripts/vmlcli/bin/Release/net10.0/vmlcli.dll /tmp/hello.vml \
       --vml-home third_party/vml --timeout 5

接进宿主之后(见 INTEGRATION.md)就能直接 vml run examples/perl/hello.pl。

判据套件
scripts/vml-perl-probe/run.sh              # 全部
scripts/vml-perl-probe/run.sh t07 t10      # 按前缀挑

用例在 bugs/vml_perl_bugs/t*.pl,走 vmlcli <用例> --lang perl 这条真实通道 (注册表 → 汇编 → 链接 → 运行),实测 通过 24 / 失败 0。

⚠ 跑之前先接线(见 INTEGRATION.md):① 按第 1/5/7 条把 perl 接进 vmlcli 的注册表; ② 跑一次 GenLib -m -l perl 生成 Lib/perl/*.vml。缺任一条套件要么响亮退出 2 (注册表里没 perl),要么让用例去红(缺本语言模块集 → 裸名 .linked 解析到别的语言)。套件刻意不绕开注册表 —— 绕开那条路自带一份链接集,会把"真实通道缺模块"盖过去。

文件

文件作用
TokenType.cs / Token.cs词法单元
Lexer.cs词法器(# 注释、三种 sigil、单/双引号串、换行作为语句分隔)
InterpolationParser.cs双引号串的 $var 插值与转义
ASTNode.cs语法树节点
Parser.cs语法器(含无括号列表算子、后缀 if/unless、三目、++/--)
CodeGenerator.cs代码生成:核心 + 语句(变量槽 / 控制流 / 子程序 / print)
CodeGenerator.Expressions.cs表达式、类型推断、内置函数分派
PerlCompiler.cs静态入口(读文件 + use 声明 + 链接标准库)
PerlPlugin.cs插件适配器(派生 CompilerPluginExBase)
Program.cs开发期 CLI

运行期与库:

路径作用
Lib/perl/perlrt.c语言专属运行时源(动态数组 @a / 哈希 %h / 字符串辅助,前缀 pl_)
Lib/perl/perlrt.vml上面那份编出来的模块(vmlcli --rebuild-lib 产出)
Lib/perl/builtin.vml标准库清单(.linked 列表,编译器自动读)
Lib/perl/vml_ui.plUI 库的声明文件(常量 + 函数名,给 use vml_ui; 用)

设计要点(与其它前端不同的地方)

已知限制

见 PERL_LANGUAGE_SPEC.md 的「不支持 / 有意简化」一节。要点: sort / reverse / each / ucfirst / lcfirst / rindex 未实现且在编译期报错(不静默); @数组 在双引号里不插值;没有引用 / 包 / 正则 / 对象;整数是 32 位。

许可 / License

与仓库其余部分一致(VML 已与上游分家,见 third_party/vml/FORK.md)。