-
Notifications
You must be signed in to change notification settings - Fork 0
Advanced
English | 中文 | Русский | Español | Português | 繁體中文 | Deutsch
Masterclass: typed smart references, calling native C libraries, memory management, performance, annotations as design tools, and a full hands-on project.
A smart reference is a typed value pointing at an lvalue. It is declared with permission × follow × base type:
&<permission> <follow> <base type> <name> = &<lvalue>;
-
Permissions (7 stacks):
rread,wwrite,mmove (pointer),rw,rm,wm,rwm. -
Follows (4):
uprogram level (Unistream),fmethod level,ascope/area level,tthread level. -
Base type:
int/double/float/string/char/ arrays / classes — generic.
That is 7 × 4 = 28 reference types.
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
With m, the reference is a moving pointer (like a++ in C):
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
References refuse what their permission forbids — and the refusal reason is just a value:
CIO::println(cause Ref::write(rr, 99));
// Ref refused: reference is read-only, cannot write
Annotations declare contracts on streams and methods:
// 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/@readon a method declare its read/write nature explicitly — they take priority over AST heuristics (a body that looks read-only can be declared a write method, and vice versa). -
@onlyreadrefuses any write-method call on the stream. -
@unforkrefuses every fork path, includingnewon a@unforkclass.
A stream can bind to a shared library:
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
}
}
Binary functions are called as double(*)(double, ...) (up to 6 arguments);
exported symbols become stream methods. bio_dlsym / the platform shim
handles dlopen/LoadLibrary differences, so this works on Windows too.
- The interpreter uses a block-based arena — allocations never move.
- Default limit: 256 MiB in interpreted mode;
0= unlimited. - Limit flags:
bio -e 256M script.bio(or-e 1G,-e 0). - Compiled products: no limit unless
BIO_MEM_LIMITis set in the environment;bio shell buildembeds this behavior in the generated main. - When the limit is hit, the program stops with a clear message:
memory limit exceeded (limit N bytes).
-
Caching: streams and methods are cached on the hot path
(
stream_cache/method_cache) — repeated lookups by the same name are O(1). -
Incremental compilation:
bio buildhashes each module's source; only changed modules recompile (N module(s) cached, M recompiled). -
Compile mode:
bio shell buildlinks the interpreter runtime into a standalone executable — startup is instant and the product runs anywhere withoutbio.
make bin (via tools/make-dist.sh) cross-compiles release trees for all
platforms with zig — no foreign SDKs:
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
# ...Platforms: linux-x86_64, linux-arm64, win32, win64, win-arm64,
macos-x86_64, macos-arm64. Requires zig >= 0.14 on PATH.
Internals: the launcher is dynamically linked against the shared runtime in
lib/ (rpath $ORIGIN/../lib); Windows uses bio.bat to set PATH.
Threads use ucontext on POSIX and Win32 fibers on Windows; binary
libraries use dlopen or LoadLibrary through the platform shim.
Let's build a word-frequency counter that reads a file, counts words, and prints a sorted report.
bio init wordcountprogram 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);
}
}
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
}
bio build . -s # standalone executable
bio build . -m # packaged .img with the platform runtime
bio run . # interpret directlybio build . -m wordcount.zip # one distributable fileThat's the full loop: source → validated bundle → standalone binary → cross-platform package.
-
bio --tokens file.bio— dump the lexer token stream. - Refusal messages are first-class:
cause exprshows exactly why a request failed. - Compile with
make PROFILE=sanitizefor ASan + UBSan builds.
- Beginner — basics and control flow.
- Intermediate — streams, classes, projects, threads.
- Packaging — formats and release trees.
-
Examples —
15 commented programs covering every feature (especially
11-smart-refs.bio,14-binary-lib.bio,15-annotations.bio).
- Home
- Beginner — first steps
- Intermediate — real usage
- Advanced — masterclass
- Build & Run
- Packaging
- Language-Reference
- BR-Model
- BTM-Model