
拆解Savage项目架构savage、savage_core与savage_macros三大crate协作全解【免费下载链接】savageA primitive computer algebra system项目地址: https://gitcode.com/gh_mirrors/sa/savageSavage 是一个用纯 Rust 从零编写的计算机代数系统Computer Algebra System支持任意精度算术、符号表达式求值、向量矩阵运算和素数等数论函数最终编译为仅 2.5 MB 的单一可执行文件。它的整个代码库由 Cargo workspace 组织成三个职责清晰的 cratesavageREPL 交互界面、savage_core核心符号计算引擎、savage_macros函数注册过程宏。本文将带你完整拆解这三者的分工与协作机制。一、Cargo Workspace一个仓库三个 crate项目根目录的 Cargo.toml 定义了 workspace 成员列表[workspace] members [ savage_macros, savage_core, savage, ]依赖关系呈一条清晰的单向链条savage_macros ──────┐ │ 提供过程宏 │ ▼ ▼ savage_core ◄─── savageREPL 可执行程序 数学核心库 终端交互层savage_macros纯工具层被savage_core依赖编译期生成代码savage_core核心库层包含全部符号计算能力可独立作为 Rust 库使用savage应用层是可执行的 REPLRead-Eval-Print Loop依赖savage_core这种分层让同一套数学引擎既能驱动终端 REPL也能被其他 Rust 程序以库的形式复用。二、savage_core符号计算引擎核心savage_core是项目的心脏所有真正的数学都在这里发生。其入口 savage_core/src/lib.rs 暴露了 7 个模块模块路径职责expressionsavage_core/src/expression.rs定义Expression枚举——符号表达式的抽象语法树ASTparsesavage_core/src/parse.rs基于 chumsky 的组合式解析器把字符串变成表达式树evaluatesavage_core/src/evaluate.rs表达式求值引擎处理四则运算、函数调用等simplifysavage_core/src/simplify.rs代数化简规则如双重负号抵消、逻辑恒真/矛盾判定printsavage_core/src/print.rs把表达式树渲染为人类可读的文本functionssavage_core/src/functions/内置数学函数库按领域拆分为 4 个子模块helperssavage_core/src/helpers.rs运算符实现Add、Mul等与便捷构造函数2.1 Expression万物皆表达式savage_core/src/expression.rs 中的Expression枚举是整个系统的中心数据结构。它用一个枚举统一表示变量、函数、函数调用、整数、有理数、复数、向量、矩阵等所有数学对象并基于numcrate 的BigInt实现任意精度pub enum Expression { Variable(String), Function(String, RcFunction), FunctionValue(BoxSelf, VecSelf), Integer(Integer), // num::bigint::BigInt Rational(Rational, RationalRepresentation), Complex(Complex, RationalRepresentation), Vector(Vector), // nalgebra 向量 Matrix(Matrix), // nalgebra 矩阵 // 以及 Negation、Not、Add、Mul 等运算符节点…… }值得注意的设计有理数携带RationalRepresentation标记记录输入时用户写的是分数还是小数——这就是 REPL 中6/5 * 3输出18/5而1.2 * 3输出3.6的原因。2.2 内置函数库按数学领域组织savage_core/src/functions/mod.rs 将内置函数按领域拆分为四个文件逻辑函数savage_core/src/functions/logic.rsand等组合数学savage_core/src/functions/combinatorics.rsfactorial线性代数savage_core/src/functions/linear_algebra.rsdet行列式利用 permutohedron 做符号展开数论函数savage_core/src/functions/number_theory.rsis_prime、nth_prime、prime_pi由高速筛法库 primal 驱动三、savage_macros让函数注册零样板代码新增一个数学函数需要三件事实现逻辑、声明元数据名称/描述/参数类型/示例、注册到函数表。savage_macros用过程宏把后两件事自动化源码仅一个文件savage_macros/src/lib.rs。3.1#[function]属性宏自动生成元数据与代理函数给一个普通 Rust 函数打上属性宏编译期就会自动生成配套的元数据常量和类型转换代理#[function( name is_prime, description whether the given non-negative integer is a prime number, examples r#[(is_prime(2^31 - 1), true)]#, categories r#[number theory, prime numbers]# )] fn is_prime(n: NonNegativeInteger) - Expression { ... }宏会读取函数的签名参数类型Expression、Integer、SquareMatrix、bool等生成 savage_core/src/functions/mod.rs 中Metadata结构和带参数类型检查的_proxy包装函数。也就是说参数类型校验规则直接从 Rust 函数签名推导写一份代码元数据和类型检查免费获得。3.2functions!函数宏一键汇总函数表savage_core/src/functions/mod.rs 末尾的注册入口只有一张清单pub fn functions() - VecFunction { functions!( logic::and, combinatorics::factorial, linear_algebra::determinant, number_theory::is_prime, number_theory::nth_prime, number_theory::prime_pi, ) }savage_macros中的functions!过程宏在编译期为每个路径生成元数据 实现包装的Function结构体并装入向量。新增函数时除了在对应领域文件中写实现只需在清单里加一行——这就是 README 中宏驱动的函数定义系统的由来。四、savageREPL 交互终端savagecrate 是用户直接面对的程序源码集中在 4 个文件全部围绕终端体验文件职责savage/src/main.rs主循环读行 → 解析命令 → 求值 → 高亮输出并维护变量环境contextsavage/src/command.rs用 chumsky 解析 4 类 REPL 命令表达式求值、x …定义变量、f(x) …定义函数、?查看帮助savage/src/input.rs基于 rustyline 的输入助手语法高亮、括号配对、自动多行补全savage/src/help.rs帮助系统从savage_core的函数元数据自动生成帮助文本用 termimad 以 Markdown 渲染两个体现架构协作的细节out变量链main.rs把每次求值结果压入outputs向量并写回环境的out变量因此用户可以在 REPL 中引用out[0]复用历史结果。错误显示解析错误由savage_core返回结构化ParseErrormain.rs中的format_parse_error再借 ariadne 渲染成带彩色标注、行内定位的友好报告还能专门指出未闭合的括号。五、三大 crate 协作全解一条表达式的一生在 REPL 输入det([[a, 2], [3, a]])并回车数据流依次穿过三个 cratesavagerustyline 捕获输入command.rs解析出EvaluateExpression命令savage_core/ parseparser()把字符串解析为Expression语法树FunctionValue节点 矩阵参数savage_core/ evaluate沿表达式树递归求值途中由simplify应用化简规则遇到函数节点时从functions()注册表查找实现——该注册表正是savage_macros在编译期生成的savage结果经to_string()渲染input.rs的高亮器着色后打印为a ^ 2 - 6。反过来看编译期savage_macros在savage_core编译时就把所有函数的元数据和代理函数烘焙进了库运行期 REPL 的帮助系统、参数类型检查、函数分发全部复用这份编译期产物。一次编写三处受益。六、总结给新手的三点架构启示关注点分离界面savage、引擎savage_core、代码生成savage_macros各占一个 crate依赖方向单一替换 REPL 或复用引擎都互不干扰编译期做重复劳动用过程宏把元数据声明、类型检查、函数注册压成签名上一份代码的副产品杜绝手工维护的漂移AST 是通用货币所有数学对象统一为Expression枚举解析、求值、化简、打印共享同一结构这是小型 CAS 保持原始但正确的关键。想动手探索从 savage_core/src/expression.rs 读起理解数据模型再看 savage_core/src/evaluate.rs 理解求值机制最后打开 savage_macros/src/lib.rs 看代码生成的魔法——三个文件就是 Savage 的全部精华所在。【免费下载链接】savageA primitive computer algebra system项目地址: https://gitcode.com/gh_mirrors/sa/savage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考