0.1.0 |
|
---|
#22 in #visibility
68KB
1.5K SLoC
Drunk Octopus
ZZ (醉章鱼) 是一个 C 预编译器,用于处理 C 语言的一些痛点。
其主要用途是嵌入式系统,在那里我们仍然因为绝望而用 C 语言编程,因为没有其他真正有效的方法。
您还可以用它来构建跨平台库。构建和链接概念旨在导出一个带有命名空间的干净的 API。
太长了,没尝试
cd example
cargo run && ./target/exe
最小侵入性。
ZZ 是 C,并且仅在有用时才偏离 C。是的,C 语法很糟糕,但解决方案不是编造另一种糟糕的语法,你还需要无理由地学习它。
没有头文件
它将生成头文件以确保它仍然是 C 并与 C 代码一起工作,但你永远不会再次需要编写头文件。基本上,ZZ 文件在顶级使用 ZZ 语法,而在函数体中使用纯 C。编译器处理所有乏味的函数定义工作,并允许你用纯 C 编写其他内容。
模块/命名空间
许多 ZZ 是受 Rust 启发的,因此它只是从 Rust 精确复制了相同的命名空间概念。
在项目 "yo" 的 "foo.zz" 文件中名为 "bob" 的函数将被导出为 C 符号 "yo_foo_bob",但导入 "yo::foo::bob" 将将其重新引入作用域为 "bob"。
默认构建系统
C 的所有构建系统都是垃圾,因为没有约定,人们想要奇怪的功能。ZZ 没有任何功能。它从 ZZ 源文件构建目标二进制文件。如果你需要其他东西,你很可能不在嵌入式系统上工作,那么你为什么在这里?
它看起来怎么样
import errors::error;
import math::add;
fn some_helper(mutable error* err, mutable uint32_t* bob) -> uint32_t {
printf("lol\n");
if (bob) {
*bob = add(horst(), foo);
printf("bob %d\n", *bob);
}
return 32;
}
export fn horst() -> uint32_t {
return 3;
}
它受 Rust 启发,但保留了 C 的参数声明顺序,因为如果身体仍然使用 C 风格,这将是令人困惑的。
默认情况下,参数是 const,除非声明为可变。您可以声明它们为 const,但这没有任何作用。
注意 horst() 的声明晚于其使用。声明顺序不再重要。
语言参考
顶级声明:fn,struct
fn 声明一个函数。体直接传递给 C 编译器。
struct 对结构体执行相同的操作。
宏
宏定义几乎类似于 C 的 #define,但稍微稳定一些
macro CHECK(e) {
if ((e) != 0) {
printf("oh noes!\n");
}
}
宏可以是多行的,但限制在花括号 {} 内。这有意禁用了某些疯狂的使用场景。
因为宏体未进行解析,zz 不知道宏依赖于什么。您可以通过使用 using 属性指定当宏导入时导入的额外模块,如下所示
export macro using(c::stdio::printf) CHECK(e) {
if ((e) != 0) {
printf("oh noes!\n");
}
}
存储:const,static,atomic 和 thread_local
const 和 static 与 Rust 中的完全相同,但使用 C 语法。
export const uint32_t foo = 3;
static mutable float blarg = 2.0/0.3;
thread_local mutable bool bob = true;
atomic mutable int marvin = 0;
常量在每个模块中都是内联的,因此每个模块指向不同的内存。静态变量有一个全局存储位置,但对当前模块是私有的。
实际上,没有声明共享全局可写变量的方法。ZZ没有借用检查器,这个限制与防止多线程竞态无关。相反,声明是选定的,以便生成的导出二进制接口可以映射到任何其他语言。
如果您需要导出一个全局可写内存位置(这仍然是一个坏主意,因为线程),您可以定义一个函数,该函数返回指向局部静态变量的指针。
thread_local和atomic直接映射到C11关键字。ZZ可以使用更友好的关键字,因为没有顶层用户定义的名称。
可见性:私有,导出
默认情况下,所有声明对整个模块都是可见的,但在最终的二进制文件中不会被导出。
"导出"可以确保声明最终出现在最终结果中,即在二进制文件和导出头文件中。
"私有"将声明标记为当前模块/文件的本地声明。它不能在其他模块中使用,因此编译器可以优化它。在大多数情况下,这相当于C中的'static'关键字,但可以添加到任何声明中。
可变性:const,mutable
默认情况下,所有内容都是const。这与C相反。mutable关键字用于使全局变量或函数参数可变。
依赖项
~7–17MB
~212K SLoC