Profile Import Rules
Profiles
Every module has a profile declared with @profile:
@profile(t0); // freestanding: no implicit heap, no GC
@profile(t1); // application: explicit types, scope-based cleanup
@profile(t2); // scripting: optional types (default profile)If omitted, the default is t2. The profile is stored on the module AST but currently has no semantic effect beyond documentation.
Import restrictions (design)
The intended rules:
| Importer | Can import |
|---|---|
| t2 | t2, t1, t0 |
| t1 | t1, t0 |
| t0 | t0 only |
The rationale: t0 code must have no hidden dependencies on heap allocation or GC, so it cannot call into t1/t2 modules. t1 code uses explicit memory management and cannot depend on t2’s dynamic typing.
t0 isolation (design)
t0 modules are intended for kernel, drivers, and firmware — fully freestanding with no implicit heap. A kernel can launch higher-profile programs but should not call their functions directly.
Runtime module (tapert100)
Every t1/t2 program that uses stdlib transitively links against tapert100 — the platform bridge that provides:
- Memory allocator (
rt_alloc,rt_free) - I/O primitives (
rt_write,rt_read,rt_puts) - Process control (
rt_exit) - Initialization (
io_init)
Stdlib modules (io, mem, str, os) explicitly import tapert100:
// inside io.tape
import rt from "tapert100";One implementation exists per target platform:
| Target | Runtime file | Mechanism |
|---|---|---|
| Windows | rt/win64/tapert100.tape | @link("kernel32.dll") — HeapAlloc, WriteFile, etc. |
| Linux | rt/linux/tapert100.tape | @link("libc.so.6") — malloc, write, etc. |
| Uusi | rt/uusi/tapert100.tape | Raw syscalls (brk, write) |
| macOS | rt/macos/tapert100.tape | @link("libSystem.B.dylib") |
The compiler selects the correct tapert100 based on the build target. The DLL output uses the export name tapert100.dll.
Stdlib modules import tapert100 explicitly. User code never imports it directly — it is accessed indirectly through stdlib.
Last modified: