完整示例(保存为 main.mbt.macro,运行 moonmacro.sh . && moon run src/main.mbt):
macro_rules! greet {
($name:expr) => {
fn greet_$name() -> String { "Hello, $name!" }
}
}
greet!(World)
#[macro_derive(Constructor, Getters)]
struct Point { x: Int; y: Int }
fn main {
let p = Point::new(1, 2)
println("\{p.x()}, \{p.y()}")
println(greet_World())
}
预处理后展开为:
fn greet_World() -> String { "Hello, World!" }
struct Point { x: Int; y: Int }
pub fn Point::new(x: Int, y: Int) -> Point { { x, y } }
pub fn Point::x(self: Point) -> Int { self.x }
pub fn Point::y(self: Point) -> Int { self.y }
fn main {
let p = Point::new(1, 2)
println("\{p.x()}, \{p.y()}")
println(greet_World())
}
3. 内置宏
无需导入即可使用。在用户定义宏匹配失败后自动尝试内置宏。
3.1 assert!
生成带错误消息的断言:
assert!(x > 0)
// -> if !(x > 0) { println("assertion failed: x > 0"); abort("") }
assert!(x > 0 && y < 10)
// -> if !(x > 0 && y < 10) { println("assertion failed: x > 0 && y < 10"); abort("") }
3.2 stringify!
将参数文本原样字面量化为字符串:
let s = stringify!(hello world) // -> let s = "hello world"
let op = stringify!(x + y) // -> let op = "x + y"
3.3 matches!
模式匹配表达式,返回 Bool;表达式与模式类型必须兼容(同 MoonBit match 规则):
let b = matches!(result, Ok(val))
// -> let b = match result { Ok(val) => true; _ => false }
参数用逗号分隔:第一个是表达式,第二个是模式。
3.4 todo!
占位宏,标记未完成的代码:
fn unimplemented() -> Int {
todo!() // -> println("not implemented"); abort("")
}
todo!("fix this later") // -> println("fix this later"); abort("")
3.5 dbg!
调试宏:输出 [dbg] 表达式 = 值,并返回该值。
fn main {
let x = 42
let y = dbg!(x + 1)
}
// 展开为:
// fn main {
// let x = 42
// let y = {
// let __dbg_val = x + 1
// println("[dbg] " + "x + 1" + " = " + __dbg_val.to_string())
// __dbg_val
// }
// }
// 运行时输出: [dbg] x + 1 = 42
3.6 let_array!
将数组元素展开为多个 let 绑定,避免重复手写 let a = arr[0]; let b = arr[1] 等代码。支持 mut 前缀和起始位置偏移。
let_array!(a, b, c = arr)
// -> let a = arr[0]; let b = arr[1]; let c = arr[2]
let_array!(mut a, mut b = state)
// -> let mut a = state[0]; let mut b = state[1]
let_array!(mut a, b, mut c = data)
// -> let mut a = data[0]; let b = data[1]; let mut c = data[2]
let_array!(a, b, c = items, start: 5)
// -> let a = items[5]; let b = items[6]; let c = items[7]
MoonMacro 使用手册
MoonMacro 是一个面向 MoonBit 语言的构建时宏系统(编译期预处理器), 提供声明式
macro_rules!宏定义、模式匹配展开、#[macro_derive]自动派生以及 13 个内置实用宏。版本: 0.2.0 / 许可证: MIT / 模块路径:
faaaaaa3/moonmacroGitHub · Mooncakes
1. 安装与使用
1.1 安装
前置要求: 需安装 MoonBit 工具链。
安装后
~/.local/bin/中有两个文件:mmprocessmoonmacro.sh确保
~/.local/bin/在PATH中即可全局使用。1.2 mmprocess(核心二进制)
1.3 moonmacro.sh(批量预处理)
自动查找目录中所有
.mbt.macro文件(递归处理所有子目录)并展开为.mbt:1.4 构建系统集成
在 Makefile 中添加预处理步骤:
1.5 作为库依赖
在
moon.mod.json中添加:2. 工作流程
项目中用
.mbt.macro文件编写含宏的代码,预处理后展开为纯.mbt:完整示例(保存为
main.mbt.macro,运行moonmacro.sh . && moon run src/main.mbt):预处理后展开为:
3. 内置宏
无需导入即可使用。在用户定义宏匹配失败后自动尝试内置宏。
3.1 assert!
生成带错误消息的断言:
3.2 stringify!
将参数文本原样字面量化为字符串:
3.3 matches!
模式匹配表达式,返回
Bool;表达式与模式类型必须兼容(同 MoonBitmatch规则):参数用逗号分隔:第一个是表达式,第二个是模式。
3.4 todo!
占位宏,标记未完成的代码:
3.5 dbg!
调试宏:输出
[dbg] 表达式 = 值,并返回该值。3.6 let_array!
将数组元素展开为多个
let绑定,避免重复手写let a = arr[0]; let b = arr[1]等代码。支持mut前缀和起始位置偏移。3.7 repeat!
重复生成某个表达式多次,用指定分隔符连接,避免手动重复书写相同代码。
参数:
,)3.8 call_each!
批量调用同一个方法,避免重复手写
m.add("a"); m.add("b"); m.add("bc")等代码。支持单参数和多参数两种模式。单参数模式:每个逗号分隔项作为一个参数。
多参数模式:用圆括号
()包裹多个参数,括号内的逗号不会被误解为参数分隔。3.9 inspect!
inspect!(expr, "expected")是@debug.debug_inspect(expr, content="expected")的简写,用于测试断言。参数:
content命名参数传入3.10 echo!
echo!(varname, ...)展开为println("varname1 = \{varname1}, varname2 = \{varname2}, ..."),用于调试时快速打印多个变量名和值。参数: 一个或多个变量名,逗号分隔
3.11 logger!
logger!(fn funcName(...) -> ReturnType { body })在函数体开头插入defer和日志打印:defer保证离开日志在函数退出时执行,不影响返回值。3.12 timeit!
timeit!(fn funcName(...) -> ReturnType { body })测量函数执行耗时:3.13 tryn!
tryn!(expr, n)尝试执行表达式expr最多n次,返回第一个Some(val);若全部失败则返回None:4. 用户宏(macro_rules!)
4.1 基本语法
模式支持
$变量名:类型捕获和$($inner),*重复。4.2 简单示例
4.3 重复匹配
4.4 嵌套展开
宏展开支持嵌套:一轮展开产生新的宏调用,下一轮继续展开,最多 10 轮。
5. 自动派生 #[macro_derive]
#[macro_derive(Trait1, Trait2)]为 struct 或 enum 自动生成 trait 实现代码。 多个 trait 可以放在同一个#[macro_derive(...)]中,也可以用连续多行堆叠。5.1 Constructor
为 struct 生成
new()构造函数。仅支持 struct,至少需要一个字段。5.2 Getters
为 struct 生成与字段同名的 getter 方法。仅支持 struct,至少需要一个字段。
5.3 EnumFromStr
为 enum 生成
from_string解析函数。仅支持 enum,至少需要一个单元变体。 数据变体(带字段)被自动跳过。支持泛型 enum:
5.4 自定义 derive(macro_derive!)
用
macro_derive! Name { template }自定义派生宏,用#[macro_derive(Name)]使用。模板变量:
$T/$type— 类型名$body— 类型体原文$kind—"struct"或"enum"$generics— 泛型声明(如"[T]")$Name— 首字母大写$fields— 逗号分隔的字段名列表(仅 struct)$field_types— 逗号分隔的字段类型列表(struct 和 enum 均可)$variants— 逗号分隔的变体名列表(仅 enum)更多示例(全部模板变量都用到了):
优先级:built-in > custom > unknown。
6. 架构
6.1 文件结构
reader.mbtbuiltins.mbtderive.mbtexpander.mbtpattern.mbtmmprocess/mmprocess.mbtmmprocess/demo.mbttest/test.mbtverify/verify.mbtmoonmacro.sh6.3 设计原则