Skip to content

Advanced zh

Enoch-199811 edited this page Aug 9, 2026 · 2 revisions

高手——智能引用、库、内存与真实项目

English | 中文 | Русский | Español | Português | 繁體中文 | Deutsch

进阶课程:类型化智能引用、调用原生 C 库、内存管理、性能、把注解当作设计工具,以及一个完整的动手项目。

类型化智能引用

智能引用(smart reference)是一个指向左值(lvalue)的类型化值。它由 权限 × 跟随层 × 基本类型 声明:

&<permission> <follow> <base type> <name> = &<lvalue>;
  • 权限(Permissions)(7 种):r 读、w 写、m 移动(指针)、rwrmwmrwm
  • 跟随层(Follows)(4 种):u 程序层(Unistream)、f 方法层、a 作用域/区域层、t 线程层。
  • 基本类型int / double / float / string / char / 数组 / 类——泛型。

也就是 7 × 4 = 28 种引用类型

读取、写入、移动

int counter = 0;
&w u int wr = &counter;          // writable program-level ref
Ref::write(wr, 10);

&r u int rr = &counter;          // read-only ref
CIO::println(get Ref::read(rr)); // 10

&rw u int rw = &counter;         // read-write
CIO::println(get rw);            // 10
rw = 5;
CIO::println(counter);           // 5

指针移动(m 权限)

有了 m,引用就是一个移动指针(类似 C 语言中的 a++):

ALL a = new int[3];
a[0] = 10; a[1] = 20; a[2] = 30;
&m u int mp = &a[1];
CIO::println(get mp);            // 20
mp++;
CIO::println(get mp);            // 30
mp = 99;                         // writes through the pointer
CIO::println(a[2]);              // 99
CIO::println(cause Ref::move(mp));  // refused: pointer moved out of bounds

把拒绝当作设计工具

引用会拒绝其权限所禁止的操作——而拒绝原因本身也是一个值:

CIO::println(cause Ref::write(rr, 99));
// Ref refused: reference is read-only, cannot write

注解:@read@write@onlyread@unfork

注解在流和方法上声明契约:

// A stream that must never be forked again:
Stream Sealed {
    void ping();
} @unfork
Sealed BadFork {}       // startup: refused: stream Sealed is @unfork, cannot fork

// A read-only stream: users may not call write methods:
Stream ReadOnly {
    int count;
    void bump();
    int get();
}
ReadOnly RO {
    void bump() { this::count = count + 1; } @write
    int get() { res count; } @read
} @onlyread
  • 方法上的 @write / @read 显式声明其读写性质——它们优先于 AST 启发式推断(一个看起来只读的方法体可以被声明为写方法,反之亦然)。
  • @onlyread 拒绝在流上调用任何写方法。
  • @unfork 拒绝所有派生路径,包括对 @unfork 类执行 new

调用原生 C 库

流可以绑定一个共享库:

Stream m & "libm.so.6";          // bind libm

Main {
    void exec() {
        CIO::println(get m::sin(0));    // 0
        CIO::println(get m::pow(2, 10)); // 1024
    }
}

二进制函数以 double(*)(double, ...)(最多 6 个参数)的形式调用;导出的符号成为流方法。bio_dlsym / 平台 shim 处理 dlopen/LoadLibrary 的差异,因此在 Windows 上同样可用。

内存管理

  • 解释器使用基于块(block-based)的竞技场(arena)——分配的内存永远不会移动。
  • 默认限制:解释模式下 256 MiB0 表示不限制。
  • 限制参数:bio -e 256M script.bio(或 -e 1G-e 0)。
  • 编译产物:无限制,除非在环境中设置了 BIO_MEM_LIMITbio shell build 会把该行为嵌入生成的 main 中。
  • 达到限制时,程序会以清晰的提示停止:memory limit exceeded (limit N bytes)

性能

  • 缓存:热路径上的流和方法会被缓存(stream_cache / method_cache)——对同名对象的重复查找是 O(1) 的。
  • 增量编译bio build 对每个模块的源码做哈希;只有变更的模块会重新编译(N module(s) cached, M recompiled)。
  • 编译模式bio shell build 把解释器运行时链接进一个独立可执行文件——启动瞬时完成,产物在任意机器上无需 bio 即可运行。

跨平台构建

make bin(通过 tools/make-dist.sh)使用 zig 为所有平台交叉编译发布树——不需要外部 SDK:

make bin
# bin/linux-x86_64/bin/bio + lib/libbio.so
# bin/win64/bin/bio.exe + lib/bio.dll + bio.bat
# bin/macos-arm64/bin/bio + lib/libbio.dylib
# ...

支持的平台:linux-x86_64linux-arm64win32win64win-arm64macos-x86_64macos-arm64。需要 PATH 中有 zig >= 0.14

内部实现:启动器与 lib/ 中的共享运行时动态链接(rpath $ORIGIN/../lib);Windows 使用 bio.bat 设置 PATH。POSIX 上线程使用 ucontext,Windows 上使用 Win32 fibers;二进制库通过平台 shim 使用 dlopenLoadLibrary

动手实践:一个真实项目

我们来构建一个词频统计器:读取文件、统计单词数、打印排序报告。

1. 骨架

bio init wordcount

2. src/main.bio

program main;

need function countWords;          // provided by utils/counter.bio

Main {
    void exec() {
        if (CIO::getln() == "") { }   // (placeholder for arg reading)
        FIO::open("input.txt");
        string text = FIO::readFile("input.txt");
        ALL report = countWords(text);
        CIO::println(get report);
    }
}

3. utils/counter.bio

program utils;

function countWords(text string) {
    // SIO lets us scan word by word through a string buffer.
    int words = 0;
    for (int i = 0; i < text::length(); i = i + 1;) {
        char c = text[i];
        if (c == ' ' || c == '\n' || c == '\t') {
            words = words + 1;
        }
    }
    res words + 1;    // last word has no trailing space
}

4. 构建并运行

bio build . -s                 # standalone executable
bio build . -m                 # packaged .img with the platform runtime
bio run .                      # interpret directly

5. 打包发布

bio build . -m wordcount.zip   # one distributable file

这就是完整的循环:源码 → 验证过的包 → 独立二进制 → 跨平台包。

调试

  • bio --tokens file.bio——转储词法分析器的 token 流。
  • 拒绝消息是一等公民:cause expr 精确显示请求失败的原因。
  • make PROFILE=sanitize 编译,获得 ASan + UBSan 构建。

延伸阅读

  • 入门——基础与控制流。
  • 进阶——流、类、项目、线程。
  • Packaging——格式与发布树。
  • 示例——15 个覆盖全部特性的带注释程序(尤其是 11-smart-refs.bio14-binary-lib.bio15-annotations.bio)。

Clone this wiki locally