Show HN:C3 编程语言(C 语言的替代方案)

c3lang / **c3c ** Public

用于 C3 语言的编译器

c3-lang.org

许可协议

发现 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 语言。

以下操作系统提供了预编译的二进制文件:

C3 的手册可以在 www.c3-lang.org 上找到。

vkQuake

由于与 C 语言的完全 ABI 兼容性,可以在同一个项目中混合使用 C 和 C3,而无需任何努力。作为一个演示,vkQuake 编译时将一小部分代码转换为 C3,并使用 c3c 编译器进行编译。(该 fork 可以在 https://github.com/c3lang/vkQuake 找到)

设计原则

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 有哪些不同?

当前状态

当前编译器的稳定版本是 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 | 否 | 未测试 | 否 | 否 | 否 | 否 |

* 内联汇编仍在开发中

未来将支持更多平台。

你能提供什么帮助?

安装

使用预编译的二进制文件在 Windows 上安装

  1. 下载 zip 文件: https://github.com/c3lang/c3c/releases/download/latest/c3-windows.zip (debug 版本 here)
  2. 解压 exe 和标准库。
  3. 如果您没有安装 Visual Studio 17,您可以安装它,或者运行 msvc_build_libraries.py Python 脚本,该脚本将下载必要的文件以在 Windows 上编译。
  4. 运行 c3c.exe

使用预编译的二进制文件在 Debian 上安装

  1. 下载 tar 文件: https://github.com/c3lang/c3c/releases/download/latest/c3-linux.tar.gz (debug 版本 here)
  2. 解压可执行文件和标准库。
  3. 运行 ./c3c

使用预编译的二进制文件在 Ubuntu 上安装

  1. 下载 tar 文件: https://github.com/c3lang/c3c/releases/download/latest/c3-ubuntu-20.tar.gz (debug 版本 here)
  2. 解压可执行文件和标准库。
  3. 运行 ./c3c

使用预编译的二进制文件在 MacOS 上安装

  1. 确保您已安装带有命令行工具的 XCode。
  2. 下载 zip 文件: https://github.com/c3lang/c3c/releases/download/latest/c3-macos.zip (debug 版本 here)
  3. 解压可执行文件和标准库。
  4. 运行 ./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 上安装

  1. 安装 CMake:brew install cmake
  2. 安装 LLVM 17+:brew install llvm
  3. 克隆 C3C github 存储库:git clone https://github.com/c3lang/c3c.git
  4. 进入 C3C 目录 cd c3c
  5. 创建一个构建目录 mkdir build
  6. 将目录更改为构建目录 cd build
  7. 为调试设置 CMake 构建:cmake ..
  8. 构建: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_worldhello_world.exe,具体取决于平台。

编译

在 Windows 上编译

  1. 确保您已安装 Visual Studio 17 2022,或者安装 "Buildtools for Visual Studio" (https://aka.ms/vs/17/release/vs_BuildTools.exe),然后选择 "Desktop development with C++"
  2. 安装 CMake
  3. 克隆 C3C github 存储库:git clone https://github.com/c3lang/c3c.git
  4. 进入 C3C 目录 cd c3c
  5. 设置 CMake 构建 cmake -B build -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
  6. 构建:cmake --build build --config Release
  7. 现在您应该有 c3c.exe

现在您应该有一个 c3c 可执行文件。

您可以通过运行一些示例代码来尝试一下:c3c.exe compile ../resources/examples/hash.c3

请注意,如果在构建时遇到链接问题,请确保您使用的是最新版本的 VS17。

在 Ubuntu 24.04 LTS 上编译

  1. 确保您有一个处理 C11 的 C 编译器和一个 C++ 编译器,例如 GCC 或 Clang。还需要安装 Git。
  2. 安装 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
  3. 克隆 C3C github 存储库:git clone https://github.com/c3lang/c3c.git
  4. 进入 C3C 目录 cd c3c
  5. 创建一个构建目录 mkdir build
  6. 将目录更改为构建目录 cd build
  7. 设置 CMake 构建:cmake ..
  8. 构建:cmake --build .

现在您应该有一个 c3c 可执行文件。

您可以通过运行一些示例代码来尝试一下:./c3c compile ../resources/examples/hash.c3

在 Void Linux 上编译

  1. 作为 root 用户,确保安装了所有项目依赖项:xbps-install git cmake llvm17 llvm17-devel lld17-devel libcurl-devel ncurses-devel zlib-devel libzstd-devel libxml2-devel
  2. 克隆 C3C 存储库:git clone https://github.com/c3lang/c3c.git
    • 如果您只需要最新的提交,您可能想要进行浅克隆:git clone https://github.com/c3lang/c3c.git --depth=1
  3. 进入目录:cd c3c
  4. 创建一个构建目录:mkdir build
  5. 进入构建目录:cd build
  6. 创建 CMake 构建缓存:cmake ..
  7. 构建:cmake --build .

您的 c3c 可执行文件应该已正确编译。您可能需要测试它:./c3c compile ../resources/examples/hash.c3 要进行系统范围的安装,请以 root 用户身份运行以下命令:cmake --install .

在 Fedora 上编译

  1. 安装所需的项目依赖项:dnf install cmake clang git llvm llvm-devel lld lld-devel ncurses-devel
  2. (可选)安装其他依赖项:dnf install libcurl-devel zlib-devel libzstd-devel libxml2-devel libffi-devel
  3. 克隆 C3C 存储库:git clone https://github.com/c3lang/c3c.git
    • 如果您只需要最新的提交,您可以进行浅克隆:git clone https://github.com/c3lang/c3c.git --depth=1
  4. 进入 C3C 目录:cd c3c
  5. 创建一个构建目录并进入它:mkdir build && cd build
  6. 创建 CMake 构建缓存。Fedora 存储库为 lld 提供了 .so 库,因此您需要设置 C3_LINK_DYNAMIC 标志:cmake .. -DC3_LINK_DYNAMIC=1
  7. 构建项目:cmake --build .

c3c 二进制文件应该在构建目录中创建。您可以通过运行一些示例代码来尝试一下:./c3c compile ../resources/examples/hash.c3

在其他 Linux / Unix 变体上编译

  1. 安装 CMake。
  2. 安装或编译 LLVM 和 LLD (版本 17+ 或更高版本)
  3. 克隆 C3C github 存储库:git clone https://github.com/c3lang/c3c.git
  4. 进入 C3C 目录 cd c3c
  5. 创建一个构建目录 mkdir build
  6. 将目录更改为构建目录 cd build
  7. 为调试设置 CMake 构建:cmake ..。此时,您可能需要手动提供 LLVM CMake 目录的链接路径,例如 cmake -DLLVM_DIR=/usr/local/opt/llvm/lib/cmake/llvm/ ..
  8. 构建:cmake --build .

关于为 Linux/Unix/MacOS 编译的说明:为了能够获取供应商库,需要 libcurl。如果可用,CMake 脚本应该会检测到它。请注意,此功能并非必不可少,并且在没有它的情况下使用编译器是完全可以的。

许可

C3 编译器在 LGPL 3.0 下获得许可,标准库本身在 MIT 许可下获得许可。

编辑器插件

编辑器插件可以在 https://github.com/c3lang/editor-plugins 找到。

贡献单元测试

  1. 编写测试,要么添加到 /test/unit/ 中的现有测试文件中,要么添加一个新文件。(如果测试标准库,请将其放在 /test/unit/stdlib/ 子目录中)。
  2. 确保测试函数具有 @test 属性。
  3. 运行测试并查看它们是否通过。(建议设置:c3c compile-test -O0 test/unit
    • 在本例中,test/unit/ 是测试目录的相对路径,因此请根据需要进行调整)
  4. 为新测试创建一个 pull request。

致谢

非常感谢所有贡献者和赞助者。

特别感谢赞助者 Caleb-odevdad 提供了额外的帮助。

Star History

Star History Chart