← board

Platform Abstraction Layer (PAL): per-platform RTL port at one seam

Problem

The RTL (lib/rtl/*) is flat with no platform branching, and historically the compiler predefined only a CPU axis (CPU32/64, CPUXTENSA, …) plus PXX_ESP_BARE and host LINUX. Networking, file IO, time, and threading depend on the platform (posix-hosted vs ESP-IDF/FreeRTOS-hosted), not the CPU — aarch64 can be Linux or bare; xtensa/riscv32 ESP code normally rides IDF. Without an explicit axis and a single porting seam, platform {$ifdef}s would scatter through every IO library.

Two axes (untwine them)

  1. CPU — codegen target (exists): x86_64 / i386 / aarch64 / arm32 / xtensa / riscv32.
  2. Platformposix (hosted: syscalls, fd IO, sockets, dlopen) vs esp (ESP-IDF/FreeRTOS-hosted: vendor VFS/lwIP/tasks/timers), extensible to other RTOS later. Bare ESP remains a separate constrained profile, not the default PAL assumption.

Do not derive platform from CPU. Add --platform=posix|esp (default derived from target: esp targets/--esp-profile=bare → esp, else posix) and predefine:

Layering — abstract at the syscall/transport seam, not per feature

3. protocols / high libs   HTTP, JSON, hashing, Synapse-reuse   ← pure, portable, written ONCE
2. OS-services RTL         file-IO, sockets-as-streams, time    ← written ONCE against PAL iface
1. PAL (platform port)     byte-handle IO, transport(connect/   ← ONLY place with per-platform code
                           send/recv/poll), clock, yield/thread
0. builtins / codegen      heap, raw syscall, MMIO              ← exists

Hard rule: no platform {$ifdef} above layer 1. Every leak above the PAL defeats the design.

Backend selection

Preferred: each backend in lib/rtl/platform/<plat>/, the platform dir on the Pascal unit search path, so uses platio binds to the right implementation with zero ifdefs in callers. This needs the Pascal-uses search-path slice of feature-dynamic-include-paths-config (only C #include -I landed so far).

Interim (until that lands): a single lib/rtl/platform.pas with one top-level {$ifdef PXX_PLATFORM_ESP} include switch — one branch point only.

Compile-time selection (not a runtime vtable/interface) — right for embedded.

Scope

In scope:

Out of scope (separate tickets):

Acceptance

Log