Show HN: The C3 programming language (C alternative language)
Show HN:C3 编程语言(C 语言的替代方案)
用于 C3 语言的编译器
许可协议
发现 LGPL-3.0, MIT 许可
发现的许可
LGPL-3.0 LICENSE MIT LICENSE_STDLIB
3.8k stars 253 forks Branches Tags Activity
C3 Language
C3 是一种编程语言,它建立在 C 语言的语法和语义之上,目标是在发展它的同时,仍然保留 C 程序员的熟悉感。它是一种进化,而不是一场革命:对于喜欢 C 语言的程序员来说,它就像 C 语言。
以下操作系统提供了预编译的二进制文件:
- Windows x64 download, 安装说明。
- Debian x64 download, 安装说明。
- Ubuntu x86 download, 安装说明。
- MacOS Arm64 download, 安装说明。
C3 的手册可以在 www.c3-lang.org 上找到。
由于与 C 语言的完全 ABI 兼容性,可以在同一个项目中混合使用 C 和 C3,而无需任何努力。作为一个演示,vkQuake 编译时将一小部分代码转换为 C3,并使用 c3c 编译器进行编译。(该 fork 可以在 https://github.com/c3lang/vkQuake 找到)
设计原则
- 过程式 “把事情做好” 类型的语言。
- 尽量保持与 C 接近 - 只改变真正必要的。
- C ABI 兼容性和出色的 C 语言集成。
- C 程序员应该很容易学习 C3。
- 数据是惰性的。
- 避免 “大想法” 和 “越多越好” 的谬论。
- 在价值巨大的地方引入一些更高级别的便利。
C3 的灵感来自 C2 language:在 C 的基础上迭代,而不是试图成为一种全新的语言。
示例代码
以下代码展示了 generic modules (更多例子可以在 https://c3-lang.org/references/docs/examples/ 找到)。
module stack {Type};
// Above: the parameterized type is applied to the entire module.
struct Stack
{
usz capacity;
usz size;
Type* elems;
}
// The type methods offers dot syntax calls,
// so this function can either be called
// Stack.push(&my_stack, ...) or
// my_stack.push(...)
fn void Stack.push(Stack* this, Type element)
{
if (this.capacity == this.size)
{
this.capacity *= 2;
if (this.capacity < 16) this.capacity = 16;
this.elems = realloc(this.elems, Type.sizeof * this.capacity);
}
this.elems[this.size++] = element;
}
fn Type Stack.pop(Stack* this)
{
assert(this.size > 0);
return this.elems[--this.size];
}
fn bool Stack.empty(Stack* this)
{
return !this.size;
}
测试:
import stack;
// Define our new types, the first will implicitly create
// a complete copy of the entire Stack module with "Type" set to "int"
alias IntStack = Stack {int};
// The second creates another copy with "Type" set to "double"
alias DoubleStack = Stack {double};
// If we had added "alias IntStack2 = Stack {int}"
// no additional copy would have been made (since we already
// have an parameterization of Stack {int} so it would
// be same as declaring IntStack2 an alias of IntStack
// Importing an external C function is straightforward
// here is an example of importing libc's printf:
extern fn int printf(char* format, ...);
fn void main()
{
IntStack stack;
// Note that C3 uses zero initialization by default
// so the above is equivalent to IntStack stack = {};
stack.push(1);
// The above can also be written IntStack.push(&stack, 1);
stack.push(2);
// Prints pop: 2
printf("pop: %d\n", stack.pop());
// Prints pop: 1
printf("pop: %d\n", stack.pop());
DoubleStack dstack;
dstack.push(2.3);
dstack.push(3.141);
dstack.push(1.1235);
// Prints pop: 1.123500
printf("pop: %f\n", dstack.pop());
}
C3 与 C 有哪些不同?
- 没有强制性的头文件
- 新的语义宏系统
- 基于模块的命名空间
- 切片
- 编译时反射
- 增强的编译时执行
- 基于泛型模块的泛型
- 基于 "Result" 的零开销错误处理
- Defer
- 值方法
- 关联的枚举数据
- 没有预处理器
- 减少了未定义的行为,并在 “安全” 模式下添加了运行时检查
- 有限的运算符重载以支持用户态动态数组
- 可选的前置和后置条件
当前状态
当前编译器的稳定版本是 version 0.7.0。
即将发布的 0.7.x 版本将侧重于扩展标准库、修复错误和改进编译时分析。请关注 这里 的问题。
如果您对如何改进该语言有任何建议,请 提交 issue 或在其专用 Discord 上讨论 C3:https://discord.gg/qN76R87。
目前已验证编译器可以在 Linux、Windows 和 MacOS 上编译。
支持矩阵
| 平台 | 是否提供原生 C3 编译器? | 支持的目标 | 堆栈跟踪 | 线程 | 套接字 | 内联汇编 | | ------------------------- | ---------------------- | -------- | -------- | ---- | ---- | ------ | | Win32 x64 | 是 | 是 + 交叉编译 | 是 | 是 | 是 | 是* | | Win32 Aarch64 | 未测试 | 未测试 | 未测试 | 未测试 | 未测试 | 是* | | MacOS x64 | 是 | 是 + 交叉编译 | 是 | 是 | 是 | 是* | | MacOS Aarch64 | 是 | 是 + 交叉编译 | 是 | 是 | 是 | 是* | | iOS Aarch64 | 否 | 未测试 | 未测试 | 是 | 是 | 是* | | Linux x86 | 是 | 是 | 是 | 是 | 是 | 是* | | Linux x64 | 是 | 是 | 是 | 是 | 是 | 是* | | Linux Aarch64 | 是 | 是 | 是 | 是 | 是 | 是* | | Linux Riscv32 | 是 | 是 | 是 | 是 | 是 | 未测试 | | Linux Riscv64 | 是 | 是 | 是 | 是 | 是 | 未测试 | | ELF freestanding x86 | 否 | 未测试 | 否 | 否 | 否 | 是* | | ELF freestanding x64 | 否 | 未测试 | 否 | 否 | 否 | 是* | | ELF freestanding Aarch64 | 否 | 未测试 | 否 | 否 | 否 | 是* | | ELF freestanding Riscv64 | 否 | 未测试 | 否 | 否 | 否 | 未测试 | | ELF freestanding Riscv32 | 否 | 未测试 | 否 | 否 | 否 | 未测试 | | FreeBSD x86 | 未测试 | 未测试 | 否 | 是 | 未测试 | 是* | | FreeBSD x64 | 未测试 | 未测试 | 否 | 是 | 未测试 | 是* | | NetBSD x86 | 未测试 | 未测试 | 否 | 是 | 未测试 | 是* | | NetBSD x64 | 未测试 | 未测试 | 否 | 是 | 未测试 | 是* | | OpenBSD x86 | 未测试 | 未测试 | 否 | 是 | 未测试 | 是* | | OpenBSD x64 | 未测试 | 未测试 | 否 | 是 | 未测试 | 是* | | MCU x86 | 否 | 未测试 | 否 | 否 | 否 | 是* | | Wasm32 | 否 | 是 | 否 | 否 | 否 | 否 | | Wasm64 | 否 | 未测试 | 否 | 否 | 否 | 否 |
* 内联汇编仍在开发中
未来将支持更多平台。
你能提供什么帮助?
- 如果您希望贡献想法,请提交 issue 或在 Discord 上讨论。
- 有兴趣为 stdlib 做出贡献吗?请在 Discord 上联系。
- 感谢提供其他 Linux 和 Unix 变体的编译说明。
- 您想为某些库贡献绑定吗?如果能支持 SDL、Raylib 等就太好了。
- 使用 C3 构建一些东西,展示出来并提供反馈。该语言仍然可以进行重大调整。
- 开始开发 C -> C3 转换器,该转换器获取 C 代码并尽最大努力将其转换为 C3。第一个版本只需要在 C 头文件上工作。
- 您是否在某些特定领域拥有深入的知识,可以帮助 C3 在该领域做得更好?提交或评论 issue。
安装
使用预编译的二进制文件在 Windows 上安装
- 下载 zip 文件: https://github.com/c3lang/c3c/releases/download/latest/c3-windows.zip (debug 版本 here)
- 解压 exe 和标准库。
- 如果您没有安装 Visual Studio 17,您可以安装它,或者运行
msvc_build_libraries.py
Python 脚本,该脚本将下载必要的文件以在 Windows 上编译。 - 运行
c3c.exe
。
使用预编译的二进制文件在 Debian 上安装
- 下载 tar 文件: https://github.com/c3lang/c3c/releases/download/latest/c3-linux.tar.gz (debug 版本 here)
- 解压可执行文件和标准库。
- 运行
./c3c
。
使用预编译的二进制文件在 Ubuntu 上安装
- 下载 tar 文件: https://github.com/c3lang/c3c/releases/download/latest/c3-ubuntu-20.tar.gz (debug 版本 here)
- 解压可执行文件和标准库。
- 运行
./c3c
。
使用预编译的二进制文件在 MacOS 上安装
- 确保您已安装带有命令行工具的 XCode。
- 下载 zip 文件: https://github.com/c3lang/c3c/releases/download/latest/c3-macos.zip (debug 版本 here)
- 解压可执行文件和标准库。
- 运行
./c3c
。
(*请注意,MacOS 13 上的调试符号生成存在已知问题,请参阅 issue #1086)
在 Arch Linux 上安装
Arch 在官方 'extra' 存储库中包含 c3c。可以像往常一样轻松安装:
sudo pacman -S c3c
# or paru -S c3c
# or yay -S c3c
# or aura -A c3c
还有一个用于 c3c 编译器的 AUR 包:c3c-git。您可以使用您的 AUR 包管理器:
paru -S c3c-git
# or yay -S c3c-git
# or aura -A c3c-git
或者手动克隆它:
git clone https://aur.archlinux.org/c3c-git.git
cd c3c-git
makepkg -si
通过 Docker 构建
您可以使用 Ubuntu 容器构建 c3c
。默认情况下,该脚本将通过 Ubuntu 22.04 构建。您可以通过传递 UBUNTU_VERSION
环境变量来指定版本。
UBUNTU_VERSION=20.04 ./build-with-docker.sh
有关其他可配置环境变量的更多信息,请参阅 build-with-docker.sh
脚本。
使用 Homebrew 在 OS X 上安装
- 安装 CMake:
brew install cmake
- 安装 LLVM 17+:
brew install llvm
- 克隆 C3C github 存储库:
git clone https://github.com/c3lang/c3c.git
- 进入 C3C 目录
cd c3c
。 - 创建一个构建目录
mkdir build
- 将目录更改为构建目录
cd build
- 为调试设置 CMake 构建:
cmake ..
- 构建:
cmake --build .
使用 Scoop 在 Windows 上安装
c3c 包含在 'Main' bucket 中。
scoop install c3
从 "hello world" 开始
创建一个 main.c3
文件,内容如下:
module hello_world;
import std::io;
fn void main()
{
io::printn("Hello, world!");
}
确保您在 ../lib/std/
或 /lib/std/
中有标准库。
然后运行
c3c compile main.c3
默认情况下,生成的二进制文件将以包含 main 函数的模块命名。在我们的例子中,它是 hello_world
,所以生成的二进制文件将被调用为 hello_world
或 hello_world.exe
,具体取决于平台。
编译
在 Windows 上编译
- 确保您已安装 Visual Studio 17 2022,或者安装 "Buildtools for Visual Studio" (https://aka.ms/vs/17/release/vs_BuildTools.exe),然后选择 "Desktop development with C++"
- 安装 CMake
- 克隆 C3C github 存储库:
git clone https://github.com/c3lang/c3c.git
- 进入 C3C 目录
cd c3c
。 - 设置 CMake 构建
cmake -B build -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
- 构建:
cmake --build build --config Release
- 现在您应该有 c3c.exe
现在您应该有一个 c3c
可执行文件。
您可以通过运行一些示例代码来尝试一下:c3c.exe compile ../resources/examples/hash.c3
请注意,如果在构建时遇到链接问题,请确保您使用的是最新版本的 VS17。
在 Ubuntu 24.04 LTS 上编译
- 确保您有一个处理 C11 的 C 编译器和一个 C++ 编译器,例如 GCC 或 Clang。还需要安装 Git。
- 安装 LLVM 18
sudo apt-get install cmake git clang zlib1g zlib1g-dev libllvm18 llvm llvm-dev llvm-runtime liblld-dev liblld-18 libpolly-18-dev
- 克隆 C3C github 存储库:
git clone https://github.com/c3lang/c3c.git
- 进入 C3C 目录
cd c3c
。 - 创建一个构建目录
mkdir build
- 将目录更改为构建目录
cd build
- 设置 CMake 构建:
cmake ..
- 构建:
cmake --build .
现在您应该有一个 c3c
可执行文件。
您可以通过运行一些示例代码来尝试一下:./c3c compile ../resources/examples/hash.c3
在 Void Linux 上编译
- 作为 root 用户,确保安装了所有项目依赖项:
xbps-install git cmake llvm17 llvm17-devel lld17-devel libcurl-devel ncurses-devel zlib-devel libzstd-devel libxml2-devel
- 克隆 C3C 存储库:
git clone https://github.com/c3lang/c3c.git
- 如果您只需要最新的提交,您可能想要进行浅克隆:
git clone https://github.com/c3lang/c3c.git --depth=1
- 如果您只需要最新的提交,您可能想要进行浅克隆:
- 进入目录:
cd c3c
- 创建一个构建目录:
mkdir build
- 进入构建目录:
cd build
- 创建 CMake 构建缓存:
cmake ..
- 构建:
cmake --build .
您的 c3c 可执行文件应该已正确编译。您可能需要测试它:./c3c compile ../resources/examples/hash.c3
要进行系统范围的安装,请以 root 用户身份运行以下命令:cmake --install .
在 Fedora 上编译
- 安装所需的项目依赖项:
dnf install cmake clang git llvm llvm-devel lld lld-devel ncurses-devel
- (可选)安装其他依赖项:
dnf install libcurl-devel zlib-devel libzstd-devel libxml2-devel libffi-devel
- 克隆 C3C 存储库:
git clone https://github.com/c3lang/c3c.git
- 如果您只需要最新的提交,您可以进行浅克隆:
git clone https://github.com/c3lang/c3c.git --depth=1
- 如果您只需要最新的提交,您可以进行浅克隆:
- 进入 C3C 目录:
cd c3c
- 创建一个构建目录并进入它:
mkdir build && cd build
- 创建 CMake 构建缓存。Fedora 存储库为 lld 提供了
.so
库,因此您需要设置 C3_LINK_DYNAMIC 标志:cmake .. -DC3_LINK_DYNAMIC=1
- 构建项目:
cmake --build .
c3c 二进制文件应该在构建目录中创建。您可以通过运行一些示例代码来尝试一下:./c3c compile ../resources/examples/hash.c3
在其他 Linux / Unix 变体上编译
- 安装 CMake。
- 安装或编译 LLVM 和 LLD 库 (版本 17+ 或更高版本)
- 克隆 C3C github 存储库:
git clone https://github.com/c3lang/c3c.git
- 进入 C3C 目录
cd c3c
。 - 创建一个构建目录
mkdir build
- 将目录更改为构建目录
cd build
- 为调试设置 CMake 构建:
cmake ..
。此时,您可能需要手动提供 LLVM CMake 目录的链接路径,例如cmake -DLLVM_DIR=/usr/local/opt/llvm/lib/cmake/llvm/ ..
- 构建:
cmake --build .
关于为 Linux/Unix/MacOS 编译的说明:为了能够获取供应商库,需要 libcurl。如果可用,CMake 脚本应该会检测到它。请注意,此功能并非必不可少,并且在没有它的情况下使用编译器是完全可以的。
许可
C3 编译器在 LGPL 3.0 下获得许可,标准库本身在 MIT 许可下获得许可。
编辑器插件
编辑器插件可以在 https://github.com/c3lang/editor-plugins 找到。
贡献单元测试
- 编写测试,要么添加到
/test/unit/
中的现有测试文件中,要么添加一个新文件。(如果测试标准库,请将其放在/test/unit/stdlib/
子目录中)。 - 确保测试函数具有
@test
属性。 - 运行测试并查看它们是否通过。(建议设置:
c3c compile-test -O0 test/unit
。- 在本例中,
test/unit/
是测试目录的相对路径,因此请根据需要进行调整)
- 在本例中,
- 为新测试创建一个 pull request。
致谢
非常感谢所有贡献者和赞助者。
特别感谢赞助者 Caleb-o 和 devdad 提供了额外的帮助。