Profile Import Rules

Profiles

Every module has a profile declared with @profile:

tape
@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)

PlannedProfile-based import restrictions are designed but not enforced by the compiler. Currently any module can import any other module regardless of profile.

The intended rules:

ImporterCan import
t2t2, t1, t0
t1t1, t0
t0t0 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)

Plannedt0 isolation is not enforced. The compiler does not reject t0 modules importing t1/t2.

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:

tape
// inside io.tape
import rt from "tapert100";

One implementation exists per target platform:

TargetRuntime fileMechanism
Windowsrt/win64/tapert100.tape@link("kernel32.dll") — HeapAlloc, WriteFile, etc.
Linuxrt/linux/tapert100.tape@link("libc.so.6") — malloc, write, etc.
Uusirt/uusi/tapert100.tapeRaw syscalls (brk, write)
macOSrt/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: