- 编程语言
- 编译器
- 云原生
- 语言运行时
【免费下载链接】wing
A programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡
本文以 Hangar 工具链生成的编译快照 atan2.test.w_compile_tf-aws.md 为切入点,深入讲解 Wing 标准库
math中atan2函数的完整使用链路:从测试源码的断言设计、SDK 层实现原理,到tf-aws平台下编译产物的形态与快照生成机制。读完本文,你将掌握math.atan2的象限语义、preflight/inflight 双阶段测试写法,以及 Wing 编译快照的解读方法,能够在自己的 Wing 项目中正确使用该函数并验证其输出。
一、快照文件概览:一份「编译产物」的权威记录
这份位于tools/hangar/__snapshots__/test_corpus/sdk_tests/math/目录下的 Markdown 快照,是 Wing 工具链测试套件(Hangar)对源文件 tests/sdk_tests/math/atan2.test.w 执行wing compile -t tf-aws后生成的规范化产物记录。整个文件只有两部分内容,结构如下:
# [atan2.test.w](https://link.gitcode.com/i/3169b48d3cb9d116caf1cd647cfd4f1a) | compile | tf-aws ## main.tf.json其中标题行由三个要素组成,用|分隔:
| 要素 | 值 | 含义 |
|---|---|---|
| 源文件 | atan2.test.w | 被测的 Wing 源文件,位于tests/sdk_tests/math/目录 |
| 测试类型 | compile | 本次快照记录的是编译阶段的产物(另一种类型是test,记录运行结果) |
| 目标平台 | tf-aws | 使用-t tf-aws平台编译,输出为 Terraform/terraform CDK 格式 |
快照正文中的main.tf.json即编译生成的 Terraform JSON 配置文件(Hangar 工具链中常量TERRAFORM_JSON_FILENAME = "main.tf.json"定义于 tools/hangar/src/generated_test_targets.ts):
{ "//": { "metadata": { "backend": "local", "stackName": "root" }, "outputs": {} }, "provider": { "aws": [ {} ] } }逐段解读这份 JSON:
//.metadata.backend为"local",表示 Terraform 状态后端采用本地存储(localbackend);//.metadata.stackName为"root",即根 Stack 的名称;//.outputs为空对象{},说明该应用没有声明任何 Terraform output;provider.aws是长度为 1 的数组,元素为空对象{},表示仅为 AWS provider 声明了默认配置,未指定 region 等附加参数。
值得注意的是:整份快照没有出现任何resource字段——这是理解后续内容的关键线索,我们会在第四节展开分析。
二、源测试文件 atan2.test.w:preflight 与 inflight 双阶段验证
快照记录的对象是测试源文件 tests/sdk_tests/math/atan2.test.w,其完整内容如下:
bring math; assert(math.atan2(90, 15) == 1.4056476493802699); assert(math.atan2(15, 90) == 0.16514867741462683); assert(math.atan2(-1, -1) == -1 * math.PI * 3 / 4); assert(math.atan2(-0, -1) == -1 * math.PI); assert(math.atan2(0, -1) == math.PI); assert(math.atan2(1, -1) == math.PI * 3 / 4); assert(math.atan2(0, 0) == 0); test "inflight arc tangent 2" { assert(math.atan2(90, 15) == 1.4056476493802699); assert(math.atan2(15, 90) == 0.16514867741462683); assert(math.atan2(-1, -1) == -1 * math.PI * 3 / 4); assert(math.atan2(-0, -1) == -1 * math.PI); assert(math.atan2(0, -1) == math.PI); assert(math.atan2(1, -1) == math.PI * 3 / 4); assert(math.atan2(0, 0) == 0); }该文件展示了 Wing 测试体系的两个典型特征:
bring math;显式导入:atan2属于 Wing 标准库math模块,必须先bring后才能调用。标准库 API 参考见 docs/api/04-standard-library/math/api-reference.md,其中atan2的签名定义为math.atan2(y: num, x: num),两个参数均为必填的num类型。preflight 断言 + inflight 测试双覆盖:文件顶层(preflight 阶段)的 7 条
assert在编译/部署前验证函数行为;随后test "inflight arc tangent 2" { ... }将同样的 7 条断言放入运行时(inflight)测试块中执行,确保函数在云运行时环境中行为一致。这正是 Wing「同一语言同时描述基础设施与运行时代码」理念在测试侧的体现。
2.1 断言背后的象限语义
atan2(y, x)返回平面内从正 x 轴到点(x, y)的射线之间的夹角(弧度制),因此能区分atan无法区分的象限信息。SDK 实现中的注释对此给出了精确定义:
Returns the angle in the plane (in radians) between the positive x-axis and the ray from (0, 0) to the point (x, y), for Math.atan2(y, x).
下面把 7 条断言逐一映射到坐标象限,验证其数学正确性(弧度值与 π 的换算关系可自行用计算器复核):
断言参数(y, x) | 落点象限 | 结果值 | 等价表达 |
|---|---|---|---|
(90, 15) | 第一象限(x>0, y>0) | 1.4056476493802699 | atan(90/15) = atan(6) |
(15, 90) | 第一象限(x>0, y>0) | 0.16514867741462683 | atan(15/90) = atan(1/6) |
(-1, -1) | 第三象限(x<0, y<0) | -1 * math.PI * 3 / 4 | -3π/4 |
(-0, -1) | 负 x 轴边界 | -1 * math.PI | -π(负零方向) |
(0, -1) | 负 x 轴边界 | math.PI | π(正零方向) |
(1, -1) | 第二象限(x<0, y>0) | math.PI * 3 / 4 | 3π/4 |
(0, 0) | 原点 | 0 | 结果与参数顺序相关,按规范返回0 |
这里最有信息量的边界用例是(-0, -1)与(0, -1)的组合:在 IEEE 754 浮点语义下,负零与正零是不同的输入,atan2(-0, -1)返回-π而atan2(0, -1)返回π。测试文件特意同时断言了这两条,说明 Wing 的atan2完整继承了 IEEE 754 对带符号零的处理,这一细节在需要精确方向判断(如导航、姿态计算)的场景中至关重要。
三、SDK 层实现:Util.atan2如何工作
math.atan2在 SDK 中的真实实现位于 packages/@winglang/sdk/src/math/math.ts:
/** * Returns the angle in the plane (in radians) between the positive x-axis and the ray from * (0, 0) to the point (x, y), for Math.atan2(y, x). * @param y The y coordinate of the point. * @param x The x coordinate of the point. */ public static atan2(y: number, x: number): number { return Math.atan2(y, x); }从实现可以得出三个结论:
- 直接委托原生
Math.atan2:Util.atan2是 TypeScript 运行时中Math.atan2的一层薄封装,因此其返回值精度、NaN 与无穷大行为、带符号零处理等都与 JavaScript/Node.js 运行时完全一致,测试文件中的浮点字面量1.4056476493802699正是这一行为的直接产物。 - 参数顺序为
(y, x)而非(x, y):第一参数是纵坐标 y,第二参数是横坐标 x,与常见编程语言(C、Java、JavaScript)的atan2(y, x)约定一致。使用时若颠倒顺序会得到错误角度,例如atan2(15, 90)与atan2(90, 15)的结果完全不同,测试文件也通过这两条断言进行了显式区分。 - 与常量
math.PI协同:Util.PI = Math.PI定义在同一文件的 math.ts,测试中用math.PI * 3 / 4、-1 * math.PI等表达式表达弧度结果,既避免了魔法数字,又精确刻画了边界角度。
值得补充的是,math模块通过 packages/@winglang/sdk/src/math/index.ts 统一导出,Util是模块内唯一的数学工具类,atan2与其姊妹函数atan、asin、acos、sec、csc、cot等共同组成完整的三角/反三角函数能力集。
四、编译快照为什么“几乎为空”:纯函数不产生云资源
这是解读这份快照最核心的一点:atan2是一个纯数学计算函数,不涉及任何云资源。因此,尽管测试文件位于tests/sdk_tests/math/(SDK 测试目录),以tf-aws平台编译后,生成的main.tf.json中:
- 没有
resource字段:不创建任何 AWS 资源(没有 S3 桶、Lambda 函数、API 网关等); - 没有
outputs:应用未声明对外输出; - 仅有 provider 声明:
provider.aws空配置仅表示「编译产物面向 AWS 平台」。
这与同目录下其他涉及云资源的测试快照形成鲜明对比——凡是bring cloud;并创建 Bucket、Queue 等资源的测试,其main.tf.json中都会出现对应的resource区块。从 Hangar 的 tools/hangar/src/utils.ts 中定义的tfResourcesOf/tfResourcesOfCount辅助函数(用于从快照模板中提取并按序列出资源、统计资源数量)可以看出,快照体系本身就预设了「资源枚举」这一常用分析手段。
这一现象反过来印证了 Wing 的设计:数学工具函数是与平台无关的纯计算逻辑,它们在 preflight 阶段以普通函数形式内联执行,不会映射为任何基础设施单元,因此编译产物在资源维度上保持「干净」。
五、快照是如何生成的:Hangar 工具链全链路
atan2.test.w_compile_tf-aws.md并非手工编写,而是 Hangar 测试套件自动生成的产物。完整链路如下:
第 1 步:扫描测试源文件并生成 vitest 用例。tools/hangar/src/generate_tests.ts 递归扫描tests/sdk_tests目录(sdkTestsDir)下所有*.w文件,为每个文件生成一对测试:
test("wing compile -t tf-aws", async () => { await compileTest(sourceDir, filename, ...); }); test("wing test -t sim", async () => { await testTest(sourceDir, filename, ...); });注意 SDK 测试(sdkTestsDir)在生成时设置了includeJavaScriptInSnapshots: false,意味着生成的快照不会包含.js产物,从而保持快照精简——这也解释了为什么本快照只记录了main.tf.json。
第 2 步:执行编译并收集产物。tools/hangar/src/generated_test_targets.ts 中的compileTest函数完成核心工作:
- 固定使用
platforms = ["tf-aws"],调用wing compile <file> -t tf-aws(命令参数由 tools/hangar/src/utils.ts 的runWingCommand拼装,并附加--no-update-check --no-analytics以隔离环境干扰); - 编译产物输出到
tests/sdk_tests/math/target/atan2.test.tfaws/目录; - 读取其中的
main.tf.json,调用sanitize_json_paths做规范化处理。
第 3 步:规范化 JSON 并写入快照。tools/hangar/src/utils.ts 的sanitize_json_paths对 JSON 做了几项关键清洗:
- 将
asset.xxx、assets/xxx等资产路径替换为<ASSET_KEY>/<ASSET_SOURCE>占位符; - 将
source/source_hash中的绝对路径替换为<SOURCE>占位符; - 删除
terraform字段(去除 cdktf 运行时信息); - 删除
//.metadata.version(去除 cdktf 版本号)。
这些清洗保证了快照在不同机器、不同构建版本下保持一致,避免绝对路径或版本号造成无意义的 diff。随后createMarkdownSnapshot(tools/hangar/src/utils.ts)按固定模板把文件内容写入tools/hangar/__snapshots__/test_corpus/<相对路径>/<文件名>_<类型>_<平台>.md,并用 vitest 的toMatchFileSnapshot与既有快照比对。
第 4 步:目录结构映射。快照目录与测试目录一一对应:tests/sdk_tests/math/→tools/hangar/__snapshots__/test_corpus/sdk_tests/math/,映射关系定义在 tools/hangar/src/paths.ts(sdkTestsDir = tests/sdk_tests,snapshotDir = tools/hangar/__snapshots__)。因此快照标题行中的../../../../../../tests/sdk_tests/math/atan2.test.w正是从快照目录回指向源测试文件的相对路径。
六、sim 平台对照:运行测试快照
与编译快照配套的还有一份运行结果快照 atan2.test.w_test_sim.md,记录wing test -t sim在模拟器平台上的输出:
pass ─ atan2.test.wsim » root/Default/test:inflight arc tangent 2 Tests 1 passed (1) Snapshots 1 skipped Test Files 1 passed (1) Duration <DURATION>解读要点:
pass ─ atan2.test.wsim » root/Default/test:inflight arc tangent 2:sim 平台将测试编译为atan2.test.wsim应用,测试名inflight arc tangent 2即源文件中test "inflight arc tangent 2"块,挂载在root/Default构造树下;Snapshots 1 skipped:说明测试块内部未使用 Wing 的 snapshot 断言;Duration <DURATION>:时间戳/时长被sanitizeOutput(tools/hangar/src/utils.ts)替换为占位符,保证快照跨机器稳定——同一函数也负责抹平端口号、IP、绝对路径、时间戳等一切环境敏感信息。
对比两份快照可以看到 Hangar 的完整验证闭环:编译快照(compile/tf-aws)验证「能否在目标平台正确编译」,运行快照(test/sim)验证「运行时行为是否符合断言」。对atan2而言,7 条断言在 sim 运行时全部通过,证明Util.atan2的 JavaScript 原生实现与测试预期一致。
七、在自己的环境中复现与验证
仓库为只读镜像,你可以按以下方式在本地验证同样结果(需要先依据 CONTRIBUTING.md 构建 wing CLI):
# 1. 编译到 tf-aws 平台,产出 target/atan2.test.tfaws/main.tf.json wing compile tests/sdk_tests/math/atan2.test.w -t tf-aws # 2. 在模拟器平台运行测试,应看到 "inflight arc tangent 2" 通过 wing test tests/sdk_tests/math/atan2.test.w -t sim # 3. 若修改了 SDK 或测试,可运行 Hangar 套件刷新快照 # 快照位于 tools/hangar/__snapshots__/test_corpus/ 目录复现时注意:生成快照前应确保本地没有环境相关差异(例如绝对路径、时间戳),否则sanitize_json_paths已做了大部分归一化,但仍建议在干净的 CI 或本地环境中执行,避免快照 diff 噪音。
相关文件索引
| 文件 | 作用 |
|---|---|
| tests/sdk_tests/math/atan2.test.w | atan2的测试源文件(preflight 断言 + inflight 测试) |
| tools/hangar/snapshots/test_corpus/sdk_tests/math/atan2.test.w_compile_tf-aws.md | 本文解读的 tf-aws 编译快照 |
| tools/hangar/snapshots/test_corpus/sdk_tests/math/atan2.test.w_test_sim.md | sim 平台运行结果快照 |
| packages/@winglang/sdk/src/math/math.ts | Util.atan2的 SDK 实现 |
| docs/api/04-standard-library/math/api-reference.md | math.atan2的标准库 API 文档 |
| tools/hangar/src/generate_tests.ts | 扫描*.w并生成 vitest 用例 |
| tools/hangar/src/generated_test_targets.ts | compileTest/testTest执行与产物收集 |
| tools/hangar/src/utils.ts | JSON 规范化、输出清洗与 Markdown 快照生成 |
| tools/hangar/src/paths.ts | 测试目录与快照目录的路径映射 |
总而言之,atan2.test.w_compile_tf-aws.md这份看似简短的快照,串联起了 Wing 从「标准库实现 → 测试设计 → 平台编译 → 快照回归」的完整工程链路:它既是一份可读的产物记录,也是理解 Wing 数学库行为约定(尤其是参数顺序与带符号零语义)的权威样例。
- 编程语言
- 编译器
- 云原生
- 语言运行时
【免费下载链接】wing
A programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡
相关推荐
Wing 云编程语言 `math.atan2` 深度解析:四象限角度判定、负零语义与 Hangar 快照测试实践
Wing 云编程语言 math.atan2 深度解析:四象限角度判定、负零语义与 Hangar 快照测试实践 本指南以 Wing 仓库中 atan2.test.
编程语言编译器云原生语言运行时Wing 语言 cloud.Bucket.tryDelete 深度解析:tf-aws 编译快照与 S3 对象删除语义
Wing 语言 cloud.Bucket.tryDelete 深度解析:tf aws 编译快照与 S3 对象删除语义 本文以 Wing 开源仓库中的 try_d
编程语言编译器云原生语言运行时Wing 语言 math.atan 测试全解析:从 tf-aws 编译快照到 SDK 实现
Wing 语言 math.atan 测试全解析:从 tf aws 编译快照到 SDK 实现 本篇围绕 Wing 仓库中 atan.test.w 的 Hangar
编程语言编译器云原生语言运行时
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考