Kylix 连续观察 · 第二十五篇
项目地址:https://github.com/astra-zhao/kylix
版本聚焦:v3.0.0-alpha
关键词:LLVM 原生后端、WASI、包注册中心、stdlib Phase 4、jsonutil/regex/datetime 纯 Kylix 实现、external 函数声明、HTTP 客户端
开篇:第二十五篇,Kylix 跨过了一条真正的分水岭
上一篇第二十四篇,我们分析的是 Kylix v2.5.0。当时的判断是:v2.5.0 是一次"工具链深化",把 LSP 重构、文档示例提取、bench 内存报告、iter 模块和类外方法定义补齐,让工具链从"能用"走向"顺手"。
第二十四篇结尾写的是:
下一步,如果 ROADMAP 按原计划推进,v2.6.0 将进入性能与优化阶段。
而 v2.6.0 确实如期而至------并行编译、死代码消除(DCE)、LSP 大文件性能基准三项任务落地,给 v2.x 系列画上了一个漂亮的句号。
但真正的大新闻,不是 v2.6.0。
是在 v2.6.0 发布仅仅一天之后,39cef28 号提交标记了一个所有人都在等的版本:
v3.0.0-alpha --- Architecture breakthrough
一次提交,93 个文件变更,9850 行新增,370 行删除。
这不是增量迭代。这是架构跃迁。
如果说 v1.2.0 的自举(Kylix 编译 Kylix)回答了"这门语言能不能编译自己",v2.0.0 回答了"它能不能成为一个完整工具链",v2.1~v2.6 回答了"它能不能被开发者舒服地使用",那么 v3.0.0-alpha 回答的是一个更根本的问题:
Kylix 能不能不依赖 Go 运行时,直接生成原生代码?
答案是:能。
而且不止于此。本次 v3.0.0-alpha 同时落地了四大架构级特性:
-
- LLVM 原生后端(Milestone 1) ------
kylix build --backend=llvm,Kylix → LLVM IR → 原生 ARM64/x86_64 二进制,Hello World 只有 33KB ,对比 Go 后端约 2MB,体积缩小约 60 倍
- LLVM 原生后端(Milestone 1) ------
-
- WASI 支持 ------
kylix build --wasi,编译到 WebAssembly System Interface,可以跑在 Wasmtime、Node.js、Cloudflare Workers 上
- WASI 支持 ------
-
- 包注册中心服务端 ------
registry/子模块,完整的包发布/搜索/下载 REST API + htmx Web 前端,配套kylix publishCLI 命令
- 包注册中心服务端 ------
-
- stdlib Phase 4 ------纯 Kylix 重写
jsonutil(390 行,支持嵌套 JSON)、regex(387 行,覆盖常见验证场景)、datetime(260 行,日期运算与格式化),标准库纯 Kylix 函数达到 90+ ,Kylix 级测试达到 117 个
- stdlib Phase 4 ------纯 Kylix 重写
此外,还顺手修复了 external 函数声明解析这个长期 Bug,新增了 HTTP 客户端标准库,补了 23 个完整教程示例,以及中英文 Getting Started 文档。
一句话概括 v3.0.0-alpha:
Kylix 正式从"编译到 Go 的 Pascal"进化为"多后端架构的现代语言",自举叙事从编译器扩展到整个生态。
这篇文章,我们就来把这次架构突破掰开揉碎了讲。
一、版本总览:从 v2.6.0 到 v3.0.0-alpha,9850 行新增了什么
从第二十四篇(v2.5.0)完成到现在,远端主线推进了两个版本:
-
• v2.6.0 (
0077caf):并行编译、死代码消除、LSP 性能基准------8 个测试,性能与优化主题 -
• v3.0.0-alpha (
39cef28→fbf3141):LLVM + WASI + Registry + stdlib Phase 4------9850 行,架构突破
让我们先从统计数据感受一下这次变更的规模:
| 指标 | v2.6.0 | v3.0.0-alpha | 变化 |
|---|---|---|---|
| Go 测试包 | 13 | 15 | +2(llvmgen、wasi) |
| Go 级测试 | ~258 | ~310+ | +52 |
| Kylix 级 stdlib 测试 | 48 | 117 | +69 |
| 纯 Kylix stdlib 模块 | 7 | 10 | +3(datetime、jsonutil、regex + wasi、httpclient) |
| 纯 Kylix stdlib 函数 | 54 | 90+ | +36+ |
| CLI 命令 | 17 | 19 | +2(publish、--backend=llvm、--wasi) |
| 构建后端 | 1(Go) | 3 (Go、LLVM、WASI) | +2 |
| 代码生成 | Go AST → .go | 新增 LLVM IR → .ll → .o → binary | 全新路径 |
| 二进制大小(Hello World) | ~2MB | 33KB | ~60× 缩小 |
v3.0.0-alpha 的 CHANGELOG 结构也变了。之前版本按"Task 1/2/3"分任务,这次直接按四大架构里程碑展开:
| 模块 | 内容 | 核心文件 |
|---|---|---|
| LLVM 原生后端 | SSA 寄存器分配、标量/控制流/函数/类 codegen、llc+clang 链路 | pkg/llvmgen/ (5 个 .go 文件,~1430 行) |
| WASI 支持 | --wasi 编译、系统调用层、纯 Kylix 高层包装 |
pkg/wasi/ (4 文件)、stdlib/src/wasi.klx |
| 包注册中心 | SQLite 后端、Bearer 认证、REST API、htmx 前端、publish CLI | registry/ (独立 Go module,~1300 行) |
| stdlib Phase 4 | jsonutil、regex、datetime 纯 Kylix 实现 | stdlib/src/{jsonutil,regex,datetime}.klx (1037 行) |
| 编译器修复 | function Foo(); external; 正确解析 |
ast/ast.go 、parser/parser_decl.go、generator/generator_types.go |
| HTTP 客户端 | THttpClient、Get/Post/JSON、状态码判断 | stdlib/http_client.go 、stdlib/src/httpclient.klx |
| 文档与教程 | 中英文 Getting Started、23 个完整教程示例 | docs/GETTING_STARTED{,_CN}.md 、examples/complete-tutorial/ |
这是自 v1.2.0 自举以来,单次版本变更最大的一次。
二、LLVM 原生后端:33KB 原生二进制是怎么来的
这是 v3.0.0-alpha 最重要的特性,也是为什么版本号直接跳到了 3.0。
2.1 设计思路:文本 IR + SSA + libc 调用链
Kylix 的 LLVM 后端选择了一个非常务实的实现路径:
-
- 输出文本格式 LLVM IR (
.ll文件),不依赖 LLVM C++ API 或 Go 的 LLVM 绑定,避免了庞大的 CGO 依赖
- 输出文本格式 LLVM IR (
-
- 使用 alloca/load/store 模型简化 SSA(Static Single Assignment)------每个局部变量分配一个 stack slot,读写通过 load/store 指令,而不是追求更激进的 SSA 寄存器优化
-
- 运行时最小化 :不引入垃圾回收器或复杂 runtime,直接调用 libc 的
printf/puts/malloc/strlen/snprintf
- 运行时最小化 :不引入垃圾回收器或复杂 runtime,直接调用 libc 的
-
- 后端工具链 :调用系统安装的
llc(LLVM Static Compiler)将.ll编译为.o目标文件,再调用clang链接为可执行文件
- 后端工具链 :调用系统安装的
整个管道是:
Kylix AST → LLVM IR Text (.ll) → llc → Native Object (.o) → clang → Native Binary
2.2 已实现的能力(Milestone 1)
根据源码和测试验证,Milestone 1 已支持:
| 特性 | 实现状态 | 测试验证 |
|---|---|---|
| 模块头与目标三元组 | ✅ | TestIR_ModuleHeader |
| 整数/布尔/字符串常量 | ✅ | TestIR_IntegerLiteral 、TestIR_BooleanLiteral、TestIR_StringConstant |
| 算术/比较/逻辑运算 | ✅ | TestIR_IntegerArithmetic 、TestIR_IntegerComparison、TestIR_BooleanNot |
| WriteLn 整数/字符串/布尔 | ✅ | TestIR_WriteLnInteger 、端到端 Hello World 验证 |
| IntToStr 整数转字符串 | ✅ | TestIR_IntToStr 、端到端求和验证 |
| if/if-else 控制流 | ✅ | TestIR_IfStatement 、TestIR_IfElseStatement |
| while/for 循环 | ✅ | TestIR_WhileLoop 、TestIR_ForLoop |
| repeat-until 循环 | ✅ | stmt.go 中已实现 |
| 函数定义与调用 | ✅ | TestIR_FunctionDecl |
| external 函数声明跳过 | ✅ | TestIR_ExternalFunctionSkipped |
| 类 Struct 类型 | ✅ | TestIR_ClassStructType |
| 类 vtable 与方法 | ✅ | TestIR_ClassWithMethod 、TestIR_ClassVtable |
| 类多字段 GEP 访问 | ✅ | TestIR_ClassMultipleFields |
端到端实测结果(本机 macOS ARM64):
program LLVMComplete;
function Sum(n: Integer): Integer;
var
i: Integer;
total: Integer;
begin
total := 0;
i := 1;
while i <= n do
begin
total := total + i;
i := i + 1;
end;
result := total;
end;
var
i: Integer;
begin
WriteLn('=== Kylix v3.0.0 LLVM Backend Demo ===');
i := 1;
while i <= 5 do
begin
WriteLn(IntToStr(Sum(i)));
i := i + 1;
end;
WriteLn('Sum(100) =');
WriteLn(IntToStr(Sum(100)));
WriteLn('Compiled to native ARM64 via LLVM!');
end.
编译运行:
$ kylix build --backend=llvm llvm_complete.klx
✓ Built llvm_complete.klx → llvm_complete [llvm]
IR: llvm_complete.ll
Obj: llvm_complete.o
$ ./llvm_complete
=== Kylix v3.0.0 LLVM Backend Demo ===
1
3
6
10
15
Sum(100) =
5050
Compiled to native ARM64 via LLVM!
$ ls -lh llvm_complete
-rwx------ 33K llvm_complete
33KB 原生 ARM64 二进制。作为对比,用 Go 后端编译同样功能的程序大约是 2MB------差距约 60 倍。这是因为 Go 后端携带了整个 Go runtime(GC、调度器、net/http 等),而 LLVM 后端只链接需要的 libc 函数。
2.3 已知限制(Milestone 1)
ROADMAP 非常诚实地列出了当前的限制:
-
• 不支持接口(vtable fat pointer)------ Milestone 2
-
• 不支持泛型单态化------ Milestone 2
-
• 不支持 LLVM 优化 Pass(当前是 -O0)------ Milestone 2
-
• 不支持异常(try/except)------ Milestone 3
-
• 不支持数组、record 类型------ Milestone 2
-
• WriteLn 当前只支持单参数,多参数串联输出需要使用 IntToStr 转换后逐行输出
-
• 类的 GEP 字段访问对复杂 lvalue(如
box.Value := 42)支持尚在完善中
这些限制说明 Milestone 1 的定位非常准确:先跑通端到端管道,再逐步补全语言特性。这是正确的工程策略------先让最小子集工作,再迭代扩展。
2.4 架构意义:为什么 LLVM 后端是 v3.0 而不是 v2.7
很多项目会把新后端作为次要版本发布,但 Kylix 把它作为 3.0 的核心特性,这是有道理的:
Go 后端是编译器的拐杖,LLVM 后端是编译器的成年礼。
在 Go 后端时代,Kylix 本质上是一个"Pascal → Go 转译器"。它巧妙地借助 Go 的成熟生态(GC、调度器、标准库、交叉编译)快速完成了语言自举和工具链建设。但代价是:
-
- 二进制携带 Go runtime,体积不可能小
-
- 无法摆脱 Go 的语言语义限制(如 goroutine 调度模型)
-
- 无法做细粒度的编译优化(逃逸分析、内联、向量化)
-
- 无法直接生成不依赖 Go 运行时的裸机/嵌入式代码
LLVM 后端的出现,意味着 Kylix 开始拥有自己独立的代码生成能力。未来它可以:
-
• 生成独立的小体积二进制(CLI 工具、系统工具)
-
• 支持裸机/嵌入式/WASM 等多目标
-
• 做独立于 Go 的编译优化
-
• 甚至可能自举 Kylix 编译器到 LLVM,彻底脱离 Go
这不是一个功能,这是一条新的生命线。
三、WASI 支持:Kylix 跑进服务端 WebAssembly
v2.3.0 已经有了 --wasm 支持(Go 的 GOOS=js GOARCH=wasm),但那个目标依赖 JavaScript 宿主环境(浏览器),无法做系统调用。
v3.0.0-alpha 新增的 WASI(WebAssembly System Interface)是另一个东西:它是 WebAssembly 的系统调用标准,可以在非浏览器环境中访问文件、环境变量、时钟、命令行参数等。
3.1 实现方式
kylix build --wasi main.klx
底层使用 Go 1.21+ 内置的 GOOS=wasip1 GOARCH=wasm 交叉编译目标。同时支持 --tinygo 选项以 TinyGo 编译更小的二进制。
代码层面,pkg/wasi/ 采用了 Go build tag 分离:
-
•
wasi_wasip1.go------WASI 原生实现,调用 wasi-libc 系统调用 -
•
wasi_stub.go------非 WASI 环境的 stub 实现(所有函数返回"not available"),确保本地测试可编译
这是一个很干净的设计:WASI 相关代码不会污染正常构建,通过 build tag 实现零开销条件编译。
3.2 WASI 模块提供的能力
Kylix 的 WASI 标准库模块(stdlib/src/wasi.klx)封装了高层 API:
| 类别 | 函数 |
|---|---|
| 标准 I/O | WriteLn 、ReadLine、Stdout、Stderr、Stdin |
| 环境变量 | Getenv 、HasEnv、Environ |
| 命令行参数 | Args 、ArgCount、Arg |
| 时钟 | ClockMonotonic 、ClockWalltime、ElapsedMs |
| 文件 I/O | ReadFile 、WriteFile |
| 退出 | WasiExit |
示例 examples/wasi-hello/main.klx:
program WasiHello;
uses wasi;
begin
WriteLn('Hello from WASI!');
WriteLn('Kylix on WebAssembly System Interface');
end.
编译后生成 .wasm 文件,可以用 Wasmtime 或支持 WASI 的 Node.js 运行。同时还提供了 examples/cloudflare-worker/worker.klx------一个 Cloudflare Workers HTTP handler 示例,说明 Kylix 的 WASI 目标可以直接部署到边缘计算平台。
3.3 为什么 WASI 重要
WASI 让 Kylix 代码可以跑在:
-
• 边缘计算:Cloudflare Workers、Fastly Compute、Vercel Edge Functions
-
• 容器化微服务:Wasm 微服务比 Docker 容器启动更快、体积更小、隔离性更强
-
• 插件系统:作为宿主应用的脚本扩展
-
• 跨平台 CLI:一个 .wasm 文件到处运行
结合 LLVM 后端的原生代码生成,Kylix 在 v3.0.0 后拥有了三种部署模式:
-
- Go 后端(默认):快速编译、完整标准库、依赖 Go runtime
-
- LLVM 后端:小体积原生二进制、最佳性能、不依赖 Go
-
- WASI 后端:WebAssembly 沙箱、跨平台、边缘计算
四、包注册中心:生态闭环的最后一块拼图
一门语言要真正形成生态,只有编译器和标准库是不够的。它还需要一个包分发机制。
v2.4.0 已经有了本地包管理器(kylix add/remove、嵌套依赖、kylix.lock),v3.0.0-alpha 把它升级成了完整的客户端-服务端架构。
4.1 服务端:registry/ 模块
registry/ 是一个独立的 Go module(有自己的 go.mod),包含:
-
• SQLite 数据库层 (
internal/db/sqlite.go,318 行)------ Store 接口设计,可切换 PostgreSQL -
•
-
REST API
-
(
-
internal/api/handler.go -
,281 行)------ 四个核心端点:
-
•
GET /api/v1/packages------搜索包(支持?q=关键词查询) -
•
POST /api/v1/packages------发布包(需要 Bearer token 认证) -
•
GET /api/v1/packages/:name/versions------查询版本列表 -
•
GET /api/v1/packages/:name/:ver/dl------下载 tarball(重定向)
-
-
• 认证中间件 (
internal/auth/auth.go,66 行)------ Bearer token 验证 -
• Web 前端------ htmx + Tailwind CSS,首页实时搜索 + 包详情页
-
• 数据模型 (
internal/models/models.go,48 行)------ Package、Version 等结构
4.2 客户端:kylix publish
CLI 新增 kylix publish 命令:
kylix publish --version=1.0.0 --registry=https://kylix.top/packages --token=xxx
支持通过 KYLIX_TOKEN 环境变量传递认证 token,避免在命令行中明文输入。pkg/pkgmgr/http.go(44 行)处理 HTTP 上传。
4.3 意义
包注册中心的落地,意味着 Kylix 的生态系统叙事完整了:
开发者写代码 → kylix build/run 编译 → kylix test 测试 → kylix doc 生成文档
→ kylix publish 发布到注册中心 → 其他开发者 kylix add 安装使用
这是一个从源码到分发的完整闭环。在此之前,Kylix 的包管理器只能安装 Git URL,缺乏中心化索引和搜索能力。注册中心补上了这个缺口。
当前注册中心还没有部署到公网(ROADMAP 标记为 v3.1 的待办项),但代码已经全部就绪,包括 7 个端到端集成测试(publish → list → search → download)。
五、stdlib Phase 4:jsonutil、regex、datetime 的纯 Kylix 实现
这是 v3.0.0-alpha 最让我兴奋的部分。
因为标准库的 Kylix 化,不是简单的"用自己的语言重写"------它意味着Kylix 已经足够强大,可以实现有实际复杂度的库。
5.1 统计回顾
从 v2.1.0 的 stdlib Phase 1 开始,Kylix 就在持续用 Kylix 写自己的标准库:
| 模块 | 版本 | 行数 | 函数数 | 测试数 |
|---|---|---|---|---|
strutil |
v2.1.0 | - | 8 | 8 |
mathutil |
v2.1.0 | - | 12 | 10 |
arrayutil |
v2.2.0 | - | 8 | 8 |
collections |
v2.2.0 | - | 6 | 5 |
stringbuilder |
v2.4.0 | - | 5 | 4 |
resulttype |
v2.4.0 | - | 6 | 4 |
iter |
v2.5.0 | - | 9 | 9 |
jsonutil |
v3.0.0-alpha | 390 | - | 29 |
regex |
v3.0.0-alpha | 387 | - | 19 |
datetime |
v3.0.0-alpha | 260 | - | 21 |
wasi |
v3.0.0-alpha | 119 | - | - |
httpclient |
v3.0.0-alpha | 58 | - | - |
Phase 4 三个模块合计 1037 行纯 Kylix 代码,69 个测试。
纯 Kylix 标准库函数累计达到 90+ ,测试 117 个。
5.2 jsonutil:390 行手写递归下降 JSON 解析器
ROADMAP 的已知问题中一直写着:
jsonutil仅支持扁平 JSON ------ v3.0
v3.0.0-alpha 解决了这个问题。
stdlib/src/jsonutil.klx 实现了一个完整的 JSON 解析器:
-
•
TJsonLexer------词法分析器,支持字符串、数字、布尔、null、对象、数组的 tokenization -
•
TJsonParser------递归下降解析器,支持任意深度嵌套的对象和数组 -
• 修复了此前仅支持单层扁平 JSON 的限制
这意味着 JSON 解析这个在多数语言里由运行时库提供的基础能力,Kylix 已经用自己写出来了。
特别值得注意的是:JsonEncode/JsonEncodePretty 保留为 external(Go 实现),因为编码需要 Go 的 reflect 支持来处理任意类型。这种"性能关键/需要外部能力的部分用 external 声明保留 Go 实现,解析逻辑用纯 Kylix 实现"的策略非常务实。
5.3 regex:387 行字符级验证函数库
这里的 regex 模块不是一个正则表达式引擎(NFA/DFA),而是一组常见格式验证函数:
-
• 字符分类:
IsDigit、IsLower、IsUpper、IsLetter、IsAlphanumeric -
• 格式验证:
IsNumeric、IsAlpha、IsEmail、IsURL、IsIPv4、IsPhone、IsDate
没有 NFA 开销,全部是纯字符遍历的精确判断。
这是一个聪明的定位:Kylix 目前不需要完整的正则引擎(那是个大工程),但开发者最常用正则做的事情就是验证邮箱、URL、IP、手机号------这些直接写专用函数更快更准确。
5.4 datetime:260 行日期时间运算
ROADMAP 的另一个已知问题:
TDateTime运算符 (+, -) 未实现 ------ v2.5
v3.0.0-alpha 解决了这个问题,提供了:
-
•
FormatPattern------yyyy/MM/dd/HH/mm/ss 格式化模式 -
•
DateAdd/DateSub------日期加减运算 -
•
IsLeapYear、DaysInMonth、IsWeekend、IsWeekday、WeekNumber------日历计算 -
•
MonthName、DayName------月份和星期名称
这三个模块加起来,标志着 Kylix 的标准库自举从"简单工具函数"阶段进入了"实现有实质复杂度的库"阶段。写一个 JSON 解析器和写一个字符串反转函数完全不是一个量级的事情。
六、其他改进:external 函数、HTTP 客户端、文档体系
6.1 external 函数声明修复
Kylix 一直支持 function Foo(); external; 语法来声明在 Go 端实现的外部函数(如标准库函数),但此前解析器对文件末尾或某些位置的 external 声明处理有误。
v3.0.0-alpha 修复了这个问题:
-
•
ast/ast.go新增FunctionDecl.IsExternal字段 -
•
parser/parser_decl.go正确识别EXTERNAL修饰词 -
•
generator/generator_types.go对IsExternal=true的函数跳过函数体生成 -
• 新增 8 个测试(3 个 parser + 5 个 generator)
这个修复对于 standard library 作者非常重要,因为它确保了 external 声明可以放在文件任意位置,不再受位置限制。
6.2 HTTP 客户端标准库
新增 stdlib/http_client.go------THttpClient 类,支持:
-
•
Get(url)、Post(url, body)、StatusCode()、SetHeader(key, value) -
• 便捷函数:
NewHttpClient()、HttpGet(url)、HttpPost(url, body)、HttpGetJSON(url)
配套 stdlib/src/httpclient.klx------纯 Kylix 包装层:
-
•
BuildQueryString(params)------构建 URL 查询字符串 -
•
IsOK(code)、IsRedirect(code)、IsClientError(code)、IsServerError(code)------状态码判断
加上已有的 web 模块(HTTP 服务端),Kylix 在 HTTP 层面同时具备了服务端和客户端能力。
6.3 文档体系大升级
v3.0.0-alpha 在文档方面做了两项重要补充:
-
- 中英文 Getting Started 指南 (
docs/GETTING_STARTED.md、docs/GETTING_STARTED_CN.md,各 278 行)------面向新手的完整入门教程
- 中英文 Getting Started 指南 (
-
-
23 个完整教程示例
-
(
-
examples/complete-tutorial/ -
)------按类别组织:
-
•
01_basics/:Hello World、变量、常量、类型推断、运算符、注释(6 个) -
•
02_control_flow/:if/else、while、for、repeat、case(5 个) -
•
03_functions/:函数与过程、递归、多返回值(3 个) -
•
05_generics/:泛型类(1 个) -
•
06_advanced_types/:record、数组、Map(3 个) -
•
07_stdlib_core/:基础函数(1 个) -
•
10_exceptions/:try/except、try/finally(2 个) -
•
11_modules/:unit 定义与 uses(2 个)
-
其中 20 个完全可运行(87%),3 个有运行时问题(泛型类和模块引用)已在 INDEX.md 中标注。附带 test_all.sh 自动化测试脚本。
对于一个编程语言项目来说,文档质量直接决定了新用户的第一道门槛。23 个经过测试的示例 + 中英文 Getting Started,说明 Kylix 开始认真对待"如何让新用户 5 分钟上手"这件事。
七、与 v2.x 系列的对比:从工具链打磨到架构革命
让我们把 v2.1 到 v3.0.0-alpha 的演进放在一张表里看:
| 版本 | 主题 | 核心价值 | 本质 |
|---|---|---|---|
| v2.1.0 | 增强类型系统 + stdlib Phase 1 | 多参数泛型约束、接口签名验证、strutil/mathutil | 语言内核增强 |
| v2.2.0 | 工程质量 + stdlib Phase 2 | CI/CD、跨文件类型检查、增量编译、arrayutil/collections | 生产可用性 |
| v2.3.0 | 开发者体验 | LSP 增量同步、REPL 增强、Delve 调试、WASM | 现代化 DX |
| v2.4.0 | 完善与生态 | i18n 全接入、真实类型推导、SetLength、包管理器 lockfile | 生态闭环 |
| v2.5.0 | 工具链深化 | LSP rename/codeAction、doc 示例、bench --mem、iter 模块 | 开发手感 |
| v2.6.0 | 性能与优化 | 并行编译、死代码消除、LSP 性能基准 | 编译性能 |
| v3.0.0-alpha | 架构突破 | LLVM 原生后端、WASI、包注册中心、stdlib Phase 4 | 多后端架构 |
这条路线有一个非常清晰的递进逻辑:
-
• v2.1-v2.2:把语言做对(类型系统、工程质量)
-
• v2.3-v2.5:把工具做好(IDE、REPL、调试、文档、benchmark)
-
• v2.6:把性能做快(并行编译、DCE)
-
• v3.0:把架构做大(多后端、生态、标准库自主化)
v2.x 回答的是"Kylix 能不能做好";v3.0 回答的是"Kylix 能走多远"。
八、开发示例:v3.0.0 新特性亲手体验
以下所有示例均已在 Kylix v3.0.0-alpha 上实际编译运行通过。
示例 1:LLVM 原生后端编译------从 Pascal 到 33KB 原生二进制
program LLVMDemo;
function Sum(n: Integer): Integer;
var
i: Integer;
total: Integer;
begin
total := 0;
i := 1;
while i <= n do
begin
total := total + i;
i := i + 1;
end;
result := total;
end;
var
i: Integer;
begin
WriteLn('=== Kylix LLVM Backend (v3.0.0) ===');
i := 1;
while i <= 6 do
begin
WriteLn(IntToStr(Sum(i)));
i := i + 1;
end;
WriteLn('Sum(100) =');
WriteLn(IntToStr(Sum(100)));
end.
编译运行:
$ kylix build --backend=llvm llvm_demo.klx
✓ Built llvm_demo.klx → llvm_demo [llvm]
IR: llvm_demo.ll
Obj: llvm_demo.o
$ ./llvm_demo
=== Kylix LLVM Backend (v3.0.0) ===
1
3
6
10
15
21
Sum(100) =
5050
$ ls -lh llvm_demo
-rwx------ 33K llvm_demo
对比 Go 后端同样功能程序约 2MB 的体积,LLVM 后端的优势一目了然。
注意 :使用 LLVM 后端需要系统安装 LLVM 工具链(
llc和clang)。macOS 上通过brew install llvm安装,Linux 上通过apt install llvm clang。
示例 2:WASI 编译------Pascal 跑在 WebAssembly 上
program WasiDemo;
begin
WriteLn('Hello from WASI!');
WriteLn('Kylix compiles to WebAssembly System Interface');
WriteLn('Run with: wasmtime wasi_demo.wasm');
end.
$ kylix build --wasi wasi_demo.klx
✓ Built wasi_demo.klx → wasi_demo.wasm [wasi via Go]
$ ls -lh wasi_demo.wasm
-rwx------ 2.5M wasi_demo.wasm
生成的 .wasm 文件可以在任何支持 WASI 的运行时中执行:
# 使用 Wasmtime
wasmtime wasi_demo.wasm
# 或使用 Node.js(需要 --experimental-wasi-unstable-preview1)
node --experimental-wasi-unstable-preview1 -e "
const { WASI } = require('wasi');
const wasi = new WASI({ version: 'preview1' });
const fs = require('fs');
const wasm = WebAssembly.compile(fs.readFileSync('wasi_demo.wasm'));
wasi.start(wasm.instance);
"
示例 3:v3.0.0 综合特性展示------Go 后端(最稳定,功能最全)
program V3Showcase;
function Factorial(n: Integer): Integer;
begin
if n <= 1 then
result := 1
else
result := n * Factorial(n - 1);
end;
function IsPrime(n: Integer): Boolean;
var
i: Integer;
begin
if n < 2 then
begin
result := false;
Exit;
end;
i := 2;
while i * i <= n do
begin
if n mod i = 0 then
begin
result := false;
Exit;
end;
i := i + 1;
end;
result := true;
end;
var
i: Integer;
count: Integer;
begin
WriteLn('========================================');
WriteLn(' Kylix v3.0.0-alpha Feature Showcase');
WriteLn('========================================');
WriteLn('');
// 类型推断
var version := '3.0.0-alpha';
var codename := 'Architecture Breakthrough';
WriteLn('Version: ', version);
WriteLn('Codename: ', codename);
WriteLn('');
// 递归 + Exit 提前返回
WriteLn('--- Factorials 1-10 ---');
for i := 1 to 10 do
begin
WriteLn(i, '! = ', Factorial(i));
end;
// 循环 + 判断
WriteLn('');
WriteLn('--- Primes under 30 ---');
count := 0;
for i := 2 to 29 do
begin
if IsPrime(i) then
begin
Write(i, ' ');
count := count + 1;
end;
end;
WriteLn('');
WriteLn('Found ', count, ' primes');
// 字符串插值
var msg := 'Running on Kylix ${version}!';
WriteLn('');
WriteLn(msg);
WriteLn('');
WriteLn('--- New Features ---');
WriteLn('[x] LLVM native backend (--backend=llvm)');
WriteLn('[x] WASI support (--wasi)');
WriteLn('[x] Package registry (kylix publish)');
WriteLn('[x] stdlib Phase 4 (jsonutil/regex/datetime)');
WriteLn('[x] External function declarations');
WriteLn('[x] HTTP client (stdlib/http_client)');
WriteLn('[x] 23 complete-tutorial examples');
end.
运行结果:
$ kylix run v3_showcase.klx
========================================
Kylix v3.0.0-alpha Feature Showcase
========================================
Version: 3.0.0-alpha
Codename: Architecture Breakthrough
--- Factorials 1-10 ---
1 ! = 1
2 ! = 2
3 ! = 6
4 ! = 24
5 ! = 120
6 ! = 720
7 ! = 5040
8 ! = 40320
9 ! = 362880
10 ! = 3628800
--- Primes under 30 ---
2 3 5 7 11 13 17 19 23 29
Found 10 primes
Running on Kylix 3.0.0-alpha!
--- New Features ---
[x] LLVM native backend (--backend=llvm)
[x] WASI support (--wasi)
[x] Package registry (kylix publish)
[x] stdlib Phase 4 (jsonutil/regex/datetime)
[x] External function declarations
[x] HTTP client (stdlib/http_client)
[x] 23 complete-tutorial examples
示例 4:Dead Code Elimination(v2.6.0 特性,v3.0 测试仍通过)
program DCEDemo;
function Foo(): Integer;
begin
result := 42;
end;
function SafeDivide(a: Integer; b: Integer): Integer;
begin
if b = 0 then
begin
raise Exception.Create('Division by zero');
end;
result := a div b;
end;
var
i: Integer;
begin
WriteLn('=== v2.6.0 DCE + v3.0.0 ===');
for i := 0 to 10 do
WriteLn('Fib(', i, ')'); // Exit/return/raise 后的代码会被消除
try
SafeDivide(10, 0);
except
on E: Exception do
WriteLn('Caught: ', E.Message);
end;
end.
九、也要指出的问题
9.1 DCE(死代码消除)已实现但未接入主编译管线
pkg/compiler/optimize.go 中的 OptimizeProgram 函数已经实现,5 个单元测试全部通过(包括 TestOptimize_DeadCodeAfterReturn、TestOptimize_DeadCodeAfterRaise、TestOptimize_DeadCodeAfterExit、TestOptimize_DeadCodeAfterBreak、TestOptimize_NoDeadCode)。但当前 CompileFile 和 CompileProject 尚未调用它。
这意味着 DCE 在测试层面已验证正确,但默认编译还不会触发。这是一个典型的"功能已就绪、只差最后接线"的状态,预计很快会在后续 alpha 或 beta 补丁中接入。
9.2 LLVM 后端 Milestone 1 的已知限制
如前文详细分析,LLVM 后端目前不支持接口、泛型、数组、record、异常、优化 Pass、多参数 WriteLn 等特性。这是 alpha 阶段的正常状态,但在撰写本文时必须明确指出:LLVM 后端目前适合编译计算密集型、逻辑简单的程序,不适合作为生产环境的主力后端。 Go 后端仍然是默认和推荐的编译目标。
9.3 examples 目录中部分示例与当前编译器不对齐
仓库中的 examples/modern.klx、examples/classes.klx 等旧示例仍有编译错误(lambda 多语句处理、类字段可见性等)。v3.0.0-alpha 新增的 examples/complete-tutorial/ 目录中的 20 个示例经过验证可以正常工作,但旧 examples 目录中的部分文件需要更新。
9.4 examples/ 包测试失败
go test ./... 时 kylix/examples 包因 modern.klx 的语法错误而 build failed。这不影响核心编译器功能,但会导致全量测试不绿。建议在正式发布前清理或修复这些旧示例。
十、ROADMAP 前瞻:v3.1 要做什么
根据 ROADMAP.md,v3.1 的方向已经清晰:
LLVM 后端 Milestone 2
-
• 接口 codegen(vtable / fat pointer)
-
• 泛型单态化
-
• LLVM 优化 Pass(-O2 / LTO)
-
• 交叉编译支持(linux/windows/arm64)
包注册中心部署
-
• 部署到 kylix.top/packages
-
• 域名 + TLS + PostgreSQL 生产配置
-
• 搜索索引优化
stdlib Phase 6
-
•
net模块(TCP/UDP/DNS) -
•
crypto模块(hash/HMAC/AES) -
•
encoding模块(base64/hex/CSV)
可以看到,v3.1 的核心任务是把 v3.0.0-alpha 已经跑通的架构管道做深做厚:
-
• LLVM 后端从"Hello World 能跑"进化到"完整语言特性支持 + 优化"
-
• 注册中心从"代码写完"进化到"公网部署可用"
-
• 标准库从"纯 Kylix 基础模块"扩展到"网络/加密/编码"
这条路线非常清晰,而且完全建立在 v3.0.0-alpha 已交付的基础设施之上。
十一、总结:v3.0.0-alpha 是 Kylix 的"成人礼"
回望整个 Kylix 系列文章,我们见证了一门语言从 0 到 1 的全过程:
-
• v0.x:从无到有的 Lexer → Parser → Go 代码生成器
-
• v1.0:核心语言特性稳定,异常处理、多返回值、泛型落地
-
• v1.2:自举------Kylix 编译 Kylix,15/15 示例通过
-
• v2.0:工具链成型------test/bench/doc/LSP/fmt/repl 全到位
-
• v2.1-v2.5:体验打磨------类型系统、i18n、增量编译、LSP 重构、stdlib 自举
-
• v2.6:性能优化------并行编译、DCE、LSP 基准
-
• v3.0.0-alpha :架构突破------LLVM 原生后端、WASI、包注册中心、stdlib Phase 4
v3.0.0-alpha 不是一个完美的版本。它是一个 alpha。LLVM 后端有明显的 Milestone 限制,DCE 还没接线,旧示例还有编译错误。
但它是一个正确方向上的里程碑。
它告诉我们:
-
- Kylix 不满足于做一个"Pascal → Go 转译器"。它要拥有自己独立的代码生成能力。33KB 原生二进制的对比数据,是这条路线最有力的证明。
-
- 自举叙事正在从编译器扩展到整个生态。编译器自举(v1.2)只是第一步。标准库自举(v2.1-v3.0 的 10 个纯 Kylix 模块、90+ 函数、117 个测试)才是更深层的自举------用自己的语言构建自己的基础设施。
-
- 架构设计是务实的。LLVM 后端选择文本 IR 而非 CGO 绑定,WASI 用 build tag 分离,jsonutil 解析纯 Kylix 实现而编码保留 external,包注册中心独立 module......这些都是在"做对的事"和"用可控的成本做"之间的理性权衡。
-
- 工程节奏依然稳健。从 v2.1 到 v3.0.0-alpha,每个版本都有明确的主题,每项功能都有测试,已知问题都诚实记录。没有"画大饼",没有"跳票"。
第二十四篇我们说:
v2.5.0 是 Kylix 对开发者日常体验的一次打磨。它不只是让语言"能用",而是让工具链开始变得"顺手"。
第二十五篇,可以这样接上:
v3.0.0-alpha 是 Kylix 对自己未来的一次下注。它不再只是"编译到 Go 的 Pascal",而是开始成为一个拥有多后端架构、独立代码生成能力、完整生态闭环的现代语言。
这是从"好用"到"强大"的跃迁。
Kylix 用 v2.x 系列证明了自己是一门认真的语言。
v3.0.0-alpha 则告诉我们:它的野心远不止于此。
从 Pascal 的清晰优雅出发,借 Go 的生态快速起步,用 LLVM 打开原生性能的大门,以 WASI 拥抱 WebAssembly 的未来,用注册中心编织生态之网。
Kylix 正在成为一门有自己灵魂的语言。而 v3.0.0-alpha,就是这条路上最关键的一步。
结尾:下一篇该看什么?
v3.0.0-alpha 已经架好了四大架构支柱,但每一根都还需要打磨。下一篇最值得关注的将是:
-
• LLVM 后端 Milestone 2 什么时候到来------接口、泛型、优化 Pass、交叉编译
-
• DCE 什么时候接入主编译管线(代码已就绪,只差接线)
-
• 包注册中心什么时候部署到公网 kylix.top/packages
-
• stdlib Phase 6(net/crypto/encoding)是否开始推进
-
• LLVM 后端的类支持什么时候完整(vtable + 虚函数分发端到端可用)
-
• 旧 examples 目录是否更新对齐当前编译器
第二十四篇结尾写的是:
现在它来到更难、更细、更长期的阶段:证明我能让开发者每天写得舒服。
今天,v3.0.0-alpha 给出了一个新的答案:
它不仅要让开发者写得舒服,还要给他们选择后端的自由、部署到任何平台的能力、以及一个真正生长的生态。
从自举到多后端,从工具链到生态,从 Go 运行时到 LLVM 原生代码------
Kylix 的 3.0 时代,才刚刚开始。