Skip to content

Advanced zhtw

Enoch-199811 edited this page Aug 9, 2026 · 1 revision

高手——智慧引用、函式庫、記憶體與真實專案

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

大師班:型別化智慧引用、呼叫原生 C 函式庫、記憶體管理、效能、將標註作為設計工具,以及一個完整的動手實作專案。

型別化智慧引用

智慧引用是指向左值的型別化值。它以 權限 × 跟隨層 × 基礎型別 宣告:

&<permission> <follow> <base type> <name> = &<lvalue>;
  • 權限(7 種):r 讀取、w 寫入、m 移動(指標)、rwrmwmrwm
  • 跟隨層(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 / 平台轉接層處理 dlopen/LoadLibrary 的差異,因此在 Windows 上也能運作。

記憶體管理

  • 直譯器使用區塊式記憶體池(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 纖程;二進位函式庫透過平台轉接層使用 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 — 傾印詞法分析器的記號串流。
  • 拒絕訊息是一等公民:cause expr 會精確顯示請求失敗的原因。
  • make PROFILE=sanitize 編譯,產生 ASan + UBSan 消毒版本。

延伸閱讀

  • 入門 — 基礎與控制流程。
  • 進階 — 串流、類別、專案、執行緒。
  • Packaging — 格式與發行版目錄樹。
  • 範例 — 15 個涵蓋所有功能的註解程式(尤其是 11-smart-refs.bio14-binary-lib.bio15-annotations.bio)。

Clone this wiki locally