Vertical Slice:Speech-to-Markdown Editor、LLVM UI Codegen 和 Landscape Split - 用我们自己的语言
Source: Dev.to
我们正在构建 SMS —— 一种静态类型语言,编译后通过 LLVM 生成原生 ARM 代码。运行时为 ForgeRunner(C++ / Godot),编辑器为 ForgeStudio,它本身也是用 SMS 编写的。
今天我们发布了一个垂直切片(vertical slice),它同时触及了整个技术栈的每一层。这正是垂直切片的意义所在:验证整根柱子都能工作,而不是仅仅验证某一层。
🎙️ SMS 中的连续听写
新的 SpeechRecognizer 组件在 SML(我们的声明式 UI 语言)中的写法如下:
SpeechRecognizer {
id: mic
language: "de-DE"
mode: clean
filters: "zdf,wdr,applaus,musik"
}mode: clean 会启动后处理:在文本到达业务逻辑之前,会剔除填充词、广播噪声以及鼓掌标记。
听写流程
mic.listen()开始识别。mic.result触发部分结果。- SMS 将其累加到
pendingText,并立即再次调用mic.listen()→ 实现连续听写。
- SMS 将其累加到
当听写开始时会出现一个 confirmRow:停止 / 确认 / 取消。每个操作都会在调用 mic.stop() 之前将 isDictating = false,从而避免竞争条件。
previewLabel 使用 wrap: true,因此长文本会自动换行,而不是把确认按钮推到屏幕外。细节虽小,却带来巨大的用户体验提升。
Build 28.
🖥️ 横屏自动分屏
ForgeRunner 现在监听 mainWindow.orientationChanged。当设备旋转到横屏时,编辑器会自动分为两个窗格:左侧显示原始 SMS/Markdown,右侧显示实时预览。
- 竖屏模式下,切换按钮可以在编辑和预览之间切换。
- 分屏(横屏)模式下,切换按钮会自行隐藏——因为它们已经没有必要。
工具栏保持紧凑:fontSize 在 14–18 之间。所有操作都能用拇指轻松触达。
Build 34.
⚙️ LLVM 代码生成:UI 属性赋值
这是大多数人看不到的层,但正是它让其他一切成为可能。
SMS 现在为 UI 对象的整数和布尔成员赋值生成原生 LLVM IR:
sms_native_llvm_set_ui_int_prop当你的 SMS 代码写 label.fontSize = 16 时,它不会走解释器,而是直接生成 LLVM IR,随后编译为原生 ARM 指令。UI 属性在机器层面被设置。
这就是 ForgeStudio 能在 Android 上 无需 JVM 运行的原因。
📝 实时 Markdown 预览
编辑器现在在每次 textChanged 事件时渲染实时 Markdown 预览。分屏模式下同时显示两个窗格;竖屏模式下可以在两者之间切换。
预览在 ForgeRunner 内部原生渲染——不使用 WebView、Electron 或任何浏览器引擎。
🔧 基础设施
run.sh: FORGE_ANDROID_JAVA_HOME and adb PATH fix这行代码背后是大约两小时的调试。Linux 上的 Android 工具链路径解析是一种特殊的痛苦。现在已经修复。
说明: Java 仅在构建时充当桥梁。Android SDK 需要 JDK 来打包和签名 APK,仅此而已。运行时没有 JVM、没有 Kotlin、没有 Compose。应用通过 ForgeRunner(C++/Godot)以原生 ARM 代码运行。Java 只涉及构建流程,除此之外不参与任何操作。
为什么要做垂直切片?
垂直切片是一个端到端完整的功能:从用户的语音输入、通过 SMS 逻辑、LLVM 代码生成、原生 UI 层,最终在 Android 设备上渲染。
它与单独构建各层相反,能够证明整个栈都是活跃且可用的。
我们在 Codeberg 上。去构建一些奇怪的东西吧。
属于 Forge 4D 生态系统的一部分 —— 声明式 UI、原生编译、无需云端。