Riferimento
Ridgun — Specifica del livello di astrazione della piattaforma (PAL) e delle librerie di sistema (posix.rglib, io.rglib)
Questa specifica definisce il contratto tra il compilatore di Ridgun (ridgunc) e le librerie di sistema di Ridgun (posix.rglib, io.rglib, unix-tools) su tutti i sistemi operativi di destinazione supportati e previsti (Linux, MacOS, Windows) e su tutte le architetture di CPU (X86_64, Arm64).
1. Panoramica dell'architettura: PAL a 2 livelli + ADT somma di destinazione
Ridgun evita di esporre nelle librerie portabili numeri di syscall esclusivi di Linux o maschere di bit specifiche di un sistema operativo. Per farlo divide l'interazione con il sistema in due livelli del compilatore, più alcuni ADT di destinazione fortemente tipizzati:
- ADT somma della piattaforma di destinazione predichiarati (
sys os => SysOs,sys arch => SysArch):
- Invece di restituire valori
Stringnon tipizzati (soggetti a refusi e che il type checker non può verificare),ridguncpredichiara due ADT somma estensibili:
type SysOs = Linux | MacOS | Windows
type SysArch = X86_64 | Arm64
sys os => SysOsesys arch => SysArchvengono risolti dal backend in fase di compilazione in costantiNLoadAdt0a costo zero (Linux/X86_64sux86_64-linux,Linux/Arm64suarm64-linux).- Le librerie possono fare dispatch in modo pulito con il pattern matching tabellare su
SysOs/SysArch, confrontare con==((sys os) == Linux) oppure estenderli per destinazioni BSD o bare-metal personalizzate conexpand type SysOs = FreeBSD | BareMetal(FR-COMP-005).
- Livello 1 — Primitive PAL multipiattaforma (
sys open mode,sys open,sys close,sys read fd,sys write fd,sys poll,sys terminate,sys kill,sys call):
- Tutte le maschere di flag e di eventi di polling passate alle primitive del livello 1 usano le costanti normalizzate della PAL di Ridgun.
- Ogni backend (
x86_64.rgELF64,arm64.rgELF64 e i futuri backendMach-Oper macOS ePE64per Windows) traduce queste costanti normalizzate nell'ABI nativa del kernel del sistema operativo (openat/poll/killsu Linux,open/poll/killsu macOS,CreateFileW/WaitForSingleObject/WSAPoll/TerminateProcesssu Windows). - La sintassi naturale separata da spazi (
sys open mode path "r") e quella separata da underscore (sys open mode path "r") sono accettate allo stesso modo.
- Livello 2 — Quote di esecuzione dichiarative (
with timeout <duration> do):
- I letterali interi accettano suffissi di durata:
_ms(* 1),_s(* 1000) e_min(* 60000). with timeout 500_ms do <body>(e la forma combinatawith region 64_KB, timeout 500_ms do <body>) inserisce una scadenza lessicale (sys time ms + duration_ms) nello stack delle scadenze PAL locale al thread, la limita a un'eventuale scadenza esterna più stringente (min(outer, new)) e ripristina la scadenza esterna all'uscita.- All'interno di un blocco
with timeout,sys deadline ms => Intrestituisce la scadenza attiva in tempo epoch (0se illimitata),sys remaining ms => Intrestituisce i millisecondi rimanenti (-1se illimitata,0se scaduta) esys poll fd events -1limita automaticamente il proprio tempo di attesa asys remaining ms.
2. Riferimento della PAL integrata nel compilatore (FR-COMP-007)
2.1 Introspezione della piattaforma di destinazione
| Primitiva | Firma | Descrizione |
|---|---|---|
sys os | => SysOs | Sistema operativo di destinazione in fase di compilazione (Linux | MacOS | Windows). |
sys arch | => SysArch | Architettura di CPU di destinazione in fase di compilazione (X86_64 | Arm64). |
Esempio di dispatch idiomatico tra più sistemi operativi in una libreria .rglib, senza catene di if/else:
fn :: path separator SysOs => String
path separator Linux = "/"
path separator MacOS = "/"
path separator Windows = "\\"
fn :: null device => String
null device = null device for (sys os)
fn :: null device for SysOs => String
null device for Windows = "NUL"
null device for _ = "/dev/null"
2.2 I/O tramite descrittore o handle e polling di disponibilità
| Primitiva | Firma | Contratto PAL normalizzato |
|---|---|---|
sys open mode | String String => Int | Apre path con la stringa di modalità portabile "r", "w", "a", "rw", "w+" o "a+" (permesso predefinito 0644 / 420 in creazione). Restituisce un descrittore o handle >= 0 oppure un codice di errore negativo (-errno). |
sys open | String Int Int => Int | Apre path con i flags normalizzati della PAL di Ridgun (0 = sola lettura, 1 = sola scrittura, 2 = lettura e scrittura, 64 = crea, 512 = tronca, 1024 = accoda, 2048 = non bloccante) e il permesso mode (ad esempio 420 per 0644). |
sys close | Int => Int | Chiude fd o l'handle. Restituisce 0 in caso di successo oppure il valore negativo -errno. |
sys read fd | Int Int => String | Legge fino a max_bytes da fd o dall'handle (0 = stdin, 1 = stdout, 2 = stderr, oppure un file, una pipe o una FIFO aperti). Restituisce "" a EOF (0 byte) o in caso di errore. |
sys write fd | Int String => Int | Scrive data su fd o sull'handle. Restituisce i byte scritti (>= 0) oppure il valore negativo -errno. |
sys poll | Int Int Int => Int | Interroga fd in attesa degli events normalizzati (1 = POLLIN leggibile, 4 = POLLOUT scrivibile, 8 = POLLERR, 16 = POLLHUP) con timeout_ms (-1 = infinito, oppure limitato a sys remaining ms all'interno di with timeout; 0 = polling non bloccante; > 0 = attesa massima in ms). Restituisce > 0 con la maschera di bit degli eventi pronti, 0 allo scadere del timeout oppure < 0 con -errno. |
2.3 Orologi, scadenze, segnali e via di fuga di basso livello
| Primitiva | Firma | Contratto PAL normalizzato |
|---|---|---|
sys time ms | => Int | Orologio monotono in millisecondi (CLOCK_MONOTONIC). |
sys sleep ms | Int => () | Sospende l'esecuzione per ms millisecondi (nanosleep / Sleep). |
sys deadline ms | => Int | Scadenza lessicale attiva in ms monotoni (0 fuori da with timeout). |
sys remaining ms | => Int | Millisecondi che mancano alla scadenza lessicale attiva (-1 fuori da with timeout, 0 se scaduta). |
sys getpid | => Int | ID del processo corrente (> 0). |
sys terminate | Int Bool => Int | Terminazione dei processi multipiattaforma: force = False invia una richiesta di terminazione ordinata (SIGTERM su POSIX), force = True forza la terminazione immediata (SIGKILL su POSIX, TerminateProcess su Windows). Restituisce 0 oppure -errno. |
sys kill | Int Int => Int | Invia un segnale normalizzato (0 = verifica di esistenza, 2 = SIGINT, 9 = SIGKILL, 15 = SIGTERM) a pid (o al gruppo di processi se pid < 0). Restituisce 0 oppure -errno. |
sys pipe | => Int Int | Crea una pipe del sistema operativo (__NR_pipe = 22) e restituisce (read_fd, write_fd) (oppure (-1, -1) in caso di errore). |
sys waitpid | Int Int => Int Int | Attende il processo figlio pid con options (0 = bloccante, 1 = WNOHANG) tramite __NR_wait4 = 61 e restituisce (ret_pid, exit_status), decodificato con WIFEXITED/WEXITSTATUS (0..255) e WIFSIGNALED (128 + WTERMSIG). |
sys call | Int Int... => Int | Syscall grezza di basso livello secondo l'ABI di destinazione (nr più 0..6 argomenti a1..a6) per driver specifici di un sistema operativo. Se la usi, proteggila con sys os / sys arch. |
3. Superficie consigliata delle librerie .rglib (io.rglib e posix.rglib)
3.1 io.rglib — Wrapper di I/O di alto livello che rispettano i timeout
type IoResult = IoOk String | IoTimeout | IoEof | IoError Int
fn :: io read with timeout String Int => IoResult
io read with timeout path wait_ms =
with timeout wait_ms do
-- Open non-blocking (0 + 2048 = O_RDONLY | O_NONBLOCK) so FIFO/device open never hangs
fd = sys open path 2048 0
io read poll step fd
fn :: io read poll step Int => IoResult
io read poll step fd
| fd < 0 = IoError fd
| otherwise =
-- timeout_ms = -1 automatically uses `sys remaining ms` from the active `with timeout` block
ev = sys poll fd 1 (0 - 1)
io read after poll fd ev
fn :: io read after poll Int Int => IoResult
io read after poll fd ev
| ev == 0 =
sys close fd -> ()
IoTimeout
| ev < 0 =
sys close fd -> ()
IoError ev
| otherwise =
chunk = sys read fd fd 65536
sys close fd -> ()
io wrap chunk chunk
fn :: io wrap chunk String => IoResult
io wrap chunk "" = IoEof
io wrap chunk s = IoOk s
3.2 posix.rglib — Costanti simboliche e funzioni di supporto per i processi
-- Normalized PAL Open Flags
fn :: o rdonly => Int
o rdonly = 0
fn :: o wronly => Int
o wronly = 1
fn :: o rdwr => Int
o rdwr = 2
fn :: o creat => Int
o creat = 64
fn :: o trunc => Int
o trunc = 512
fn :: o append => Int
o append = 1024
fn :: o nonblock => Int
o nonblock = 2048
-- Normalized PAL Poll Events
fn :: poll in => Int
poll in = 1
fn :: poll out => Int
poll out = 4
fn :: poll err => Int
poll err = 8
fn :: poll hup => Int
poll hup = 16
-- Normalized Signals
fn :: sig int => Int
sig int = 2
fn :: sig kill => Int
sig kill = 9
fn :: sig term => Int
sig term = 15
fn :: process exists Int => Bool
process exists pid = (sys kill pid 0) == 0
4. Compilare e distribuire librerie .rglib e .so
Compila qualsiasi modulo di libreria senza bisogno di main:
# Emit portable Ridgun library bundle (.rglib)
./bin/ridgunc build --lib src/main/ridgun/lib/io.rg -o target/io.rglib
# Emit native ELF64 shared object (.so)
./bin/ridgunc build --so src/main/ridgun/lib/io.rg -o target/libio.so
# Or via stable in a library project (`stable new --lib io`):
./bin/stable built lib