跳到正文
Hacker News· oldrev·· 7 天前AI 评分22

Show HN:CAPL Playground 在浏览器中编译并运行 Vector CAPL

Show HN: CAPL Playground – compile and run Vector CAPL in the browser

AI 导读

CAPL Playground 是一个在浏览器中编译并运行 Vector CAPL(CANoe/CANalyzer 节点语言)的在线工具,编译器完全在页面内运行,不上传服务器。

正文 · AI 翻译

Deploy to GitHub Pages Rust tests Coverage License: MIT OR Apache-2.0

一个用于 Vector CAPL(CANoe/CANalyzer 节点语言)的在线演练场。 在浏览器中编写 CAPL,观察它经过真实的编译器流水线,以 JSON 形式检查 AST,阅读生成的 C,阅读生成的 WebAssembly——然后 运行该 WebAssembly,在一个带有虚拟时间、定时器、CAN 总线和按键事件的微型模拟测量环境中。

不会向服务器发送任何内容:编译器在页面内运行。

CAPL Playground interface

Play Now

source.can ─▶ lexer ─▶ parser ─▶ AST ─▶ sema ─┬─▶ wasm backend ─▶ .wasm ─▶ simulator
                                              ├─▶ C backend    ─▶ .c
                                              └─▶ AST backend  ─▶ .json

仓库布局

src/                      the playground UI (React + Vite + Tailwind v4)
  core/                   Rust WASM bridge and editor-only syntax lexer
    driver.ts             frontend contract for capl-wasm
  runtime/sim.ts          the simulated CANoe measurement (host imports)
  components/             editor, panels, architecture tab
rust/                     the compiler core as reusable crates
  crates/capl-diag        spans + diagnostic bag
  crates/capl-parse       recursive-descent parser and lexer
  crates/capl-ast         AST, type lattice, visitor, serde JSON export
  crates/capl-sema        scopes, symbols, types
  crates/capl-codegen-wasm  wasm module writer (LEB128 + sections, no deps)
  crates/capl-codegen-c     C99 writer
  crates/capl-driver      stage orchestration, Backend trait, `capl` CLI
  crates/capl-wasm        wasm-bindgen facade for this page

Rust 编译器,TypeScript UI

页面在 React 启动前加载 capl-wasm。它在 globalThis.__CAPL_CORE__ 上注册唯一的编译器 实现;TypeScript 只负责编辑器、 模拟宿主和展示层。

./rust/build-wasm.sh          # wasm-pack build → public/capl/capl_wasm.js
cargo run -p capl-driver -- node.can --emit=wat
cargo run -p capl-driver -- node.can --emit=wasm -o node.wasm
cargo test --workspace

原生驱动程序相对于源文件解析 includes { "file.can" }。可以通过 CAPL_INCLUDE_PATH 环境变量提供额外的搜索目录(使用平台路径分隔符)。 浏览器构建没有文件系统访问权限,因此目前 include 仅限于原生驱动程序使用。

Rust 测试覆盖率和 CAPL 测试夹具

编译器在 rust/crates/capl-driver/tests/ 下有驱动程序级集成测试。它们通过 Rust 词法分析器、解析器、语义处理、C 后端和 WebAssembly 后端编译真实的 CAPL 程序。测试夹具 涵盖定时器和处理程序、周期性 CAN 消息、数组和函数、 64 位和浮点表达式,以及无效输入诊断。

安装一次 cargo-llvm-cov,然后 运行:

cd rust
cargo llvm-cov --workspace --all-features --lcov --output-path coverage/lcov.info
cargo llvm-cov --workspace --all-features --html --open

在 Windows 上,./rust/coverage.ps1 运行 LCOV 命令并打印摘要。 CI 安装相同的工具,并在 Rust 测试任务期间生成 rust/coverage/lcov.info,然后将其作为 rust-coverage 工件上传。原生 覆盖率命令有意测量可复用的编译器 crate; capl-wasm 门面由浏览器构建和运行时冒烟测试来检验。

生成的模块

wasm 后端手工写出二进制——LEB128、各个节、一个代码构建器, 同步生成字节和 WAT 清单。

0x0000  null guard
0x0040  vararg marshalling area (32 slots × 16 B) used by write()
0x0400  string pool, globals, message objects, function statics

导入(模块 "capl",由宿主提供——此处是浏览器模拟器, 其他地方可能是 CANoe 垫片或测试台):

write(fmt, argc, args)   setTimer(id, ms)   setTimerCyclic(id, ms)
cancelTimer(id)          output(msgPtr)     timeNow() -> i32
random(n) -> i32         strlen(ptr) -> i32 pow/sin/cos
canOnline()              canOffline()       stopMeasurement()

导出:memory、不可变全局变量 __msgbuf(事件 消息对象的地址)、__init、__set_this、__set_fuel、每个用户函数以及 每个事件处理程序一个函数(on_start、on_timer_tick、 on_message_0x100、on_key_103、……)。

每个循环回边都会递减一个燃料计数器,并在其归零时陷入,因此 意外的 while (1) {} 不会冻结标签页——模拟器会将其报告为 运行时陷入。

支持的语言子集

variables{} 块(也可以定义类型)· 全局变量 · const · 具名 struct 声明,带字段和字段数组 · 原生驱动程序 includes{} 支持相对路径和 CAPL_INCLUDE_PATH · 数组 和花括号初始化器 · byte word dword qword int long int64 float double char · 标量类型和 数组,包括花括号初始化器和多维 索引 · 消息对象,带 .id .dlc .can .byte(n) .word(n) .dword(n) 和 this · timer/msTimer · 事件 preStart start stopMeasurement preStop timer message key sysvar envVar errorFrame busOff(对 on message CAN2.0x100 进行通道感知匹配)· if else while do for switch(带贯穿)break continue return · 完整的 C 表达式语法,包括 ?:、短路 &&/|| 和复合 赋值 · 用户函数,支持递归、数组参数和 基于地址的聚合参数/返回值 · 内置函数 write(printf 风格)、output、elCount、timeNow、random、abs、min、 max、sqrt、pow、sin、cos、floor、ceil、strlen、canOnline、 canOffline、stopMeasurement。

局部聚合变量在声明时由生成的 __zero 辅助函数清零, 这使示例保持可复现。诸如 const int N = 3 之类的编译期常量会被折叠为立即数,且从不占用线性内存。

当前的聚合 ABI 在 WASM 中将数组和结构体作为线性内存地址传递。C 后端在函数边界使用数组指针和结构体指针,返回结构体的函数返回指向所返回对象的指针。这使两个后端能够与相同的源码级模型互操作;调用方应将聚合值视为基于存储的对象,而非标量寄存器值。

TODO:CAPL 语言覆盖范围

编译器有意实现了一个聚焦的 CAPL 子集。以下语法和语言特性保留给未来工作,不应仅因为词法分析器能识别其关键字就视为已支持:

  • includes 在浏览器构建中,那里没有文件系统包含解析器;原生驱动程序支持相对文件和 CAPL_INCLUDE_PATH。
  • 匿名结构体、递归布局、打包/位域,以及超出当前命名字段子集的完整 CAPL 布局兼容性。
  • 基于数据库的对象和信号访问,例如 $Signal,包括消息限定的信号和信号赋值。
  • CAPL 测试模块:testcase、testfunction、测试设置/拆卸,以及测试判定/报告 API。
  • 超出当前地址 ABI 的聚合转换,包括针对每个数组和结构体上下文的精确 CAPL 复制/别名规则。
  • 除当前定时器、消息、按键、系统变量、环境变量和总线/错误事件之外的额外 CAPL 事件形式和运行时对象。
  • CANoe/CANalyzer 项目使用的 CAPL 特定属性、限定符、命名空间和配置语法。
  • 用于诊断、传输协议、面板、文件、套接字和测量配置的更广泛内置 API 表面。

每个条目在应被宣传为受支持之前,都需要解析器、语义分析、后端和运行时覆盖。新语法还应获得驱动程序集成测试夹具,并在适用时获得聚焦的优先级/诊断测试。

UI

  • 浅色 / 深色 / 系统主题,记忆于 localStorage
  • 英语 / 简体中文,从 navigator.language 自动检测
  • 具有精确范围的诊断,可点击,在编辑器边栏中镜像显示
  • 状态栏中的各阶段计时、令牌/节点计数和模块大小
  • 模拟栏:虚拟时钟、+100 ms / +1 s、帧注入、按键事件、待处理定时器检查器

键盘:Ctrl/⌘ + Enter 构建并运行。

免责声明

CAPL Playground 是一个独立的、实验性的兼容性与教学项目。它未获得 Vector Informatik GmbH、CANoe、CANalyzer 或任何其他 Vector 产品的赞助、认可、关联或衍生。“Vector”、“CAPL”、“CANoe”和“CANalyzer”是各自所有者的名称和商标,此处仅用于标识本项目旨在互操作的语言或行为。本项目不包含 Vector 软件、专有数据库、文档或测试资产,也不声称实现官方 CAPL 工具链。

使用本项目风险自负。您有责任检查适用于您使用中涉及的任何源代码、规范、示例、商标、逆向工程活动和部署环境的许可证和条款。本声明仅供参考,不构成法律建议。

许可证

版权所有 (c) 2026 Wei Li

本项目根据以下任一许可证双许可,由您选择:

除非您明确声明,否则任何有意提交以纳入本项目的贡献均应按上述方式双重许可,不附加任何额外条款或条件。

编译器架构参考

编译器架构参考了 DMD 前端的设计。

来源:Hacker News · github.com