Wren 0.4.0 版本全解析:语言新特性、核心库扩充与 C API 嵌入实践 编程语言语言运行时编译器【免费下载链接】wrenThe Wren Programming Language. Wren is a small, fast, class-based concurrent scripting language.项目地址https://gitcode.com/gh_mirrors/wr/wren点击查看免费下载Wren 是一个小巧、快速、基于类并发的脚本语言本篇文章以 CHANGELOG.md 中 0.4.0 版本为主线系统梳理该版本带来的语言层新特性、核心库List/Num/String能力扩充、内存与 GC 修复以及面向宿主嵌入方的 C API 破坏性变更与新增接口。读者读完将能完整掌握 0.4.0 的变更全貌并能在自己的嵌入项目中正确使用wrenSetListElement、Map 系列 API 与WrenLoadModuleResult等新设施。0.4.0 版本概览一次面向语言与嵌入的里程碑升级0.4.0 是 Wren 仓库中最新标注的正式版本当前仓库main分支的 CHANGELOG 即以此版本开头。与 0.3.0 偏重构建流程、跨平台修复不同0.4.0 的重心明显转向两处语言层补齐了continue关键字、import ... for Name as OtherName重命名导入、Fiber.try(value)、科学计数法正号支持以及允许.换行的流式 API 写法嵌入层C API对wrenReallocateFn和模块加载机制做了破坏性变更同时新增了一批 Map/List 操作接口让宿主程序控制数据结构的能力大幅增强。此外还修复了多个与栈损坏stack corruption、GC 收集模块期间崩溃相关的严重问题。下文将按「语言特性 → 核心库 → 修复 → C API → 构建与 VM 杂项」的顺序逐项展开。语言层新特性continue、as 导入与 Fiber.trycontinue关键字0.4.0 为for与while循环新增continue关键字用于跳过当前迭代、直接进入下一次循环判断。仓库中对应的语言测试位于 test/language/continue/覆盖了for循环、while循环、嵌套循环中的行为例如continue之后不再执行循环体剩余语句、但会继续推进循环变量与条件判断。import ... for Name as OtherName导入重命名0.4.0 引入as语法使模块导入可以重命名import math for Sin as Sine即从math模块导入名为Sin的类/变量并在当前作用域中绑定为Sine。这对避免命名冲突、简化长标识符非常实用。与之配套的「更智能的 import」设计思路可参考 doc/rfc/0001-smarter-imports.md 与 doc/notes/import syntax.md两者讨论了相对导入与逻辑导入的区分背景。科学计数法支持正号此前形如1e5这类带显式正号的科学计数法字面量可能无法解析0.4.0 修复了该问题现在1e5、2.5E3均可正常识别为数值字面量。Fiber.try(value)与Fiber.call互补的调用形式Fiber.try(value)用于以「尝试」语义启动/恢复一个纤程若被调纤程内部抛错错误会作为普通返回值返回给调用方而非中断整个调用链。它与Fiber.call(value)的差异在于错误传播方式这在 test/core/fiber/ 的try.wren、try_done.wren、try_error.wren、try_value.wren、try_through_call.wren、try_without_error.wren等测试中均有覆盖。典型场景是var f Fiber.new { Fiber.abort(something went wrong) } var result f.try() // 捕获错误而非崩溃允许.换行流式/构建器 API0.4.0 允许方法调用点号.与接收者分处不同行便于书写链式流式 APIvar query db .select(name) .where(age 18) .orderBy(name)相关测试位于 test/language/ 下的语法类用例如chained_newline.wren覆盖了链式换行解析。这一改动降低了长链式调用的排版负担属于纯解析层面的放宽。核心库增强List 排序/交换/查找、Num 新常量与方法Listsort、swap、indexOflist.sort()与list.sort {|a, b| ... }0.4.0 为 List 加入原地快速排序。无参形式按默认升序low high带比较器函数形式由调用方自定义顺序。排序逻辑并非 C 原生实现而是以 Wren 写就的快速排序核心实现位于 src/vm/wren_core.wren包含sort()、sort(comparer)、quicksort_(low, high, comparer)与partition_四段方法。其中sort()直接委托sort {|low, high| low high }而sort(comparer)会先校验comparer is Fn否则Fiber.abort(Comparer must be a function.)。注意sort是原地排序并返回列表自身方便链式调用。 测试用例 test/core/list/sort.wren 验证了默认升序、自定义升/降序以及传入非函数比较器时的运行时错误。list.swap(index0, index1)交换列表中两个位置的元素实现为 src/vm/wren_core.c 中的list_swap原生方法先对两个下标做validateIndex校验越界会报错再交换底层elements.data中的两个Value返回null。list.indexOf(value)返回指定值在列表中首次出现的位置找不到时返回-1实现见 src/vm/wren_core.c内部调用wrenListIndexOf。三者对应的原生方法注册位于 src/vm/wren_core.c。Num新常量与数学函数0.4.0 为 Num 补充了三个常量与四个函数Num.tau6.28318530717958647692528676655900577即 2πNum.nanWREN_DOUBLE_NANIEEE 754 非数Num.infinityINFINITY正无穷min(other)/max(other)取两数较小/较大者实现在 src/vm/wren_core.c接收方与参数均要求为 Numclamp(min, max)将数值钳制到[min, max]区间实现在 src/vm/wren_core.cvalue min ? min : (value max ? max : value)expe^xlog2以 2 为底的对数。常量定义见 src/vm/wren_core.c 的DEF_NUM_CONSTANT宏函数则通过DEF_NUM_FN宏直接映射到 C 标准库exp、log2见 src/vm/wren_core.c。方法注册表位于 src/vm/wren_core.c。Num.tau // ≈ 6.28318 Num.infinity // Infinity Num.nan.isNan // true (3).clamp(0, 2) // 2 (2).max(7) // 7 (8).log2 // 3 (1).exp // ≈ 2.71828Randomsample 优化Random.sample系列得到性能优化相关测试见 test/random/sample_one.wren、sample_count_one.wren、sample_count_multiple.wren、sample_count_too_many.wren等。关键修复栈损坏、GC 与类型系统0.4.0 修复了若干影响稳定性的深层问题Fn调用相关栈损坏涉及闭包/函数调用时栈帧被破坏的问题CODE_IMPORT_VARIABLE字节偏移 bug导入变量字节码中的偏移量计算错误可能导致解析到错误变量多次wrenInterpret调用导致的栈损坏同一 VM 上反复解释执行脚本时出现的栈不一致导入期间 GC 收集模块导致崩溃模块加载过程中发生垃圾回收时模块对象可能被误回收Bool、Num、Null允许被继承此前这三个内建类可以被is继承0.4.0 明确禁止保证类型系统语义正确。C API破坏性变更与新接口0.4.0 对嵌入 API 做了两处破坏性变更与一批新增接口全部声明于 src/include/wren.h实现于 src/vm/wren_vm.c 等文件。破坏性变更 1userData加入wrenReallocateFnWrenReallocateFn现在多带一个void* userData参数宿主在自定义内存分配/释放回调时需要同步更新签名。该参数由WrenConfiguration.userData传入见 src/include/wren.h 中WrenConfiguration的userData字段让分配器能访问宿主上下文。破坏性变更 2WrenLoadModuleResult与onComplete回调loadModuleFn的返回类型由const char*改为结构体WrenLoadModuleResultsrc/include/wren.htypedef struct WrenLoadModuleResult { const char* source; // 模块源码找不到时为 NULL WrenLoadModuleCompleteFn onComplete; // 可选回调 void* userData; // 宿主自定义数据 } WrenLoadModuleResult; typedef void (*WrenLoadModuleCompleteFn)(WrenVM* vm, const char* name, struct WrenLoadModuleResult result);onComplete在 Wren 用完模块源码后被调用并回传原始WrenLoadModuleResult宿主可在此释放源码内存。这意味着模块源码的内存所有权明确归宿主所有宿主可动态生成、读取后再释放不必再依赖静态字符串。resolveModuleFn与loadModuleFn的配合流程相对导入支持在 src/include/wren.h 的注释中有完整说明resolveModuleFn负责把导入串解析为唯一规范名loadModuleFn只负责加载源码且每个模块名只回调一次VM 内部缓存结果。新增查询接口wrenHasModule与wrenHasVariablewrenHasModule(WrenVM* vm, const char* module)查询某模块是否已加载wrenHasVariable(WrenVM* vm, const char* module, const char* name)查询某已加载模块中是否存在指定变量。两者用于配合wrenGetVariable使用wren.h中注明「use wrenHasModule to ensure that before calling」避免在模块未加载/变量不存在时调用wrenGetVariable导致错误。声明见 src/include/wren.h。列表与 Map 操作接口wrenSetListElement(WrenVM* vm, int listSlot, int index, int elementSlot)设置列表中指定下标的元素与已有wrenGetListElement互补两者的 index 现在都支持负数从尾部计数。声明见 src/include/wren.h。Map 系列 APIsrc/include/wren.hwrenSetSlotNewMap(WrenVM* vm, int slot); // 在槽位创建空 Map wrenGetMapCount(WrenVM* vm, int slot); // 取键值对数量 wrenGetMapContainsKey(WrenVM* vm, int mapSlot, int keySlot); // 是否含某键 wrenGetMapValue(WrenVM* vm, int mapSlot, int keySlot, int valueSlot); // 取值到 valueSlot wrenSetMapValue(WrenVM* vm, int mapSlot, int keySlot, int valueSlot); // 写值 wrenRemoveMapValue(WrenVM* vm, int mapSlot, int keySlot, ...); // 删除键这套接口让 C 宿主无需先调用 Wren 代码即可直接构造、读取、修改和删除 Map 数据。Map 在 VM 底层的键校验与存储逻辑可参考 src/vm/wren_core.cmap_subscript、map_subscriptSetter、map_containsKey、map_remove等原生方法。一个结合上述 API 的典型嵌入片段示意wrenEnsureSlots(vm, 4); wrenSetSlotNewMap(vm, 0); // map wrenSetSlotString(vm, 1, key); // key wrenSetSlotString(vm, 2, value); // value wrenSetMapValue(vm, 0, 1, 2); // map[key] value wrenGetMapCount(vm, 0); // 1 wrenGetMapValue(vm, 0, 1, 3); // value - slot 3构建与 VM 杂项util/generate_docs.py新增用于重新生成项目文件的脚本见 util/generate_docs.pyclang 下 Windows 的 computed gotoVM 主循环允许在使用 clang 编译 Windows 目标时启用计算跳转提升解释器性能WREN_MAX_TEMP_ROOTS 默认值由 5 提升到 8临时 GC 根数量上限增大降低深表达式/长调用链下临时值被误回收的风险GC 调试时间单位改为毫秒此前以秒输出改动后更便于观测。版本脉络0.3.0 / 0.2.0 / 0.1.0 一览CHANGELOG 还记录了更早版本的关键变化理解它们有助于把握 0.4.0 的上下文0.3.0聚焦跨平台构建修复所有主要平台「开箱即用」CLI 迁出到独立仓库wren-lang/wren-cliVM 与 CLI 的边界被明确全部 Python 脚本升级为 Python 3 并统一可在各平台运行文档新增在线 Try 页。0.2.0约 290 个提交。语言/VM 侧包括「更智能的 import」区分相对导入与逻辑导入、Fiber首次call/transfer可携带值、String.trim/split/replace/fromByte/indexOf(needle, startIndex)、Sequence.take/skip、List.filled(count, value)、Num.pow/log/round/largest/smallest、Map迭代MapEntryC API 新增wren.hppC 绑定、WrenVM的userData、无模块加载器时仍可加载可选模块、wrenAbortFiber。0.1.0首个正式版本「一切都是新的」。其中 0.2.0 引入的List.filled与Num.largest/smallest等能力在 0.4.0 中继续沿用相关原生实现可在 src/vm/wren_core.c 与 src/vm/wren_core.c 中直接查阅。升级与嵌入建议若你是宿主嵌入方升级到 0.4.0 时必须同步修改两处回调签名——wrenReallocateFn新增userData参数与loadModuleFn返回WrenLoadModuleResult并在onComplete中释放源码。利用新增的wrenHasModule/wrenHasVariable可让wrenGetVariable的调用更安全。若你使用 Wren 语言侧continue、导入重命名、Fiber.try、链式换行语法属于纯增量特性不破坏既有代码但需注意Bool/Num/Null不再允许被继承若旧代码依赖这一点需要调整。若你关注性能与 GCWREN_MAX_TEMP_ROOTS默认值提升、clang 下的 computed goto、Random.sample优化都值得在升级后重新跑一遍基准。仓库基准脚本位于 test/benchmark/fib.wren、binary_trees.wren等可用 util/benchmark.py 复测对比。总而言之0.4.0 既补齐了日常编码所需的语言糖continue、as导入、链式换行又通过 List/Num 的方法扩充让标准库更顺手更以两处 C API 破坏性变更为代价换来了更安全、更灵活的模块加载与数据结构操作能力——是 Wren 从「可用」走向「更易嵌入、更健壮」的关键一版。赞分享编程语言语言运行时编译器【免费下载链接】wrenThe Wren Programming Language. Wren is a small, fast, class-based concurrent scripting language.项目地址https://gitcode.com/gh_mirrors/wr/wren点击查看免费下载相关推荐Wren 0.4.0 版本解析continue 与 as 关键字、原始字符串、属性系统与嵌入 API 升级Wren 0.4.0 版本解析continue 与 as 关键字、原始字符串、属性系统与嵌入 API 升级 导读 本文基于 Wren 语言官方博客的 0.4.编程语言语言运行时编译器CPython 3.14.0a4 新特性全解析分支监控、unittest 断言扩充与 C API 增强CPython 3.14.0a4 新特性全解析分支监控、unittest 断言扩充与 C API 增强 本文以 CPython 官方仓库的 3.14.0a4编程语言语言运行时解释器标准库Wren 嵌入指南从 C 语言调用 Wren 方法wrenCall 实战Wren 嵌入指南从 C 语言调用 Wren 方法wrenCall 实战 本文面向需要把 Wren 作为嵌入式脚本语言集成进 C/C 主程序的开发者编程语言语言运行时编译器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考