Présentation
Goose est un langage de programmation système conçu pour être memory‑safe sans recourir à un allocateur de tas, à un ramasse‑miettes ou à des annotations de durée de vie. Le compilateur place chaque valeur dynamique sur une ou plusieurs piles de données gérées statiquement. La croissance d’une pile se fait par simple incrément d’un pointeur (« bump pointer »), et la libération d’une structure se résume à un seul store lorsque la portée se termine.
Modèle de mémoire et sécurité
Chaque référence possède une racine statique, c’est‑à‑dire la variable qui possède la valeur cible. Le compilateur infère ces racines et rejette toute référence qui pourrait dépasser la durée de vie de son propriétaire, sans syntaxe de lifetimes ni règles d’exclusivité. Ainsi, les références restent valides même pendant la croissance d’un tableau :
struct Item { id: i32, weight: f32 }
var items: Item[>..] = [];
let first .= items.push(Item { 1, 0.5 });
for i: i32 in 2..1000001 { items.push(Item { i, 0.0 }); }
first.weight = 99.5; // toujours valide après un million d'ajouts
Le même principe s’applique aux slices : le compilateur signale l’erreur suivante lorsqu’une référence ancrée dans une portée intérieure est assignée à une variable plus large :
fn longest(a: u8[:], b: u8[:]) -> u8[:] {
if a.len >= b.len { a } else { b }
}
var outer: u8[>..] = [];
var w = outer[..];
{
var inner: u8[>..] = [];
format(inner, "inner text");
w = longest(outer, inner); // error: storing a reference rooted at inner,
} // which does not outlive the destination
Performances et comparaison
Les benchmarks fournis par le projet montrent que Goose dépasse C++ et Rust sur plusieurs métriques. Sur seize tests, Goose atteint :
- 3,3× la vitesse d’un code C++ idiomatique,
- 1,16× la vitesse d’un C++ optimisé à la main,
- 1,12× la vitesse du meilleur Rust sûr.
En même temps, l’utilisation mémoire est réduite de 1,9×, 1,3× et 1,2× respectivement. Ces gains proviennent principalement de la représentation « inline » des structures : un enregistrement de 160 octets occupe 29 octets en C++ et aucune allocation supplémentaire en Goose. Les énumérations à mode variable consomment quatre fois moins de mémoire et sont deux fois plus rapides que les enums Rust équivalents.
Compilation et interopérabilité
Goose se compile en un unique fichier C, ce qui le rend portable sur tout environnement disposant d’un compilateur C. Le backend TinyCC intégré permet d’exécuter le code en‑processus sans étape de construction externe. Les appels externes sont déclarés via extern fn, offrant une interopérabilité directe avec du code C existant. Les structures sont stockées sous forme de liens relatifs de 1, 2 ou 4 octets, ce qui les rend position‑indépendantes et directement utilisables comme format de fichier : sauvegarder consiste en une écriture brute, charger en une lecture suivie d’une vérification de validité.