A.S.T.R.A.L (Advanced System & Theoretical Research Architecture Language) est un langage de programmation systÚme conçu pour combiner :
A.S.T.R.A.L est conçu pour :
| Feature | A.S.T.R.A.L | C | Rust | Python |
|---|---|---|---|---|
| Performance | âââââ | âââââ | âââââ | ââ |
| Memory Safety | ââââ | â | âââââ | âââ |
| UnitĂ©s Physiques | âââââ | â | ââ | âââ |
| System Programming | âââââ | âââââ | âââââ | â |
| FacilitĂ© d'apprentissage | âââ | ââ | ââ | âââââ |
Pour utiliser A.S.T.R.A.L, vous devriez avoir :
Ătape 1 :
echo "deb [trusted=yes] https://apt.ravnssonlabs.space stable main" | \
sudo tee /etc/apt/sources.list.d/astralc.list > /dev/null
Ătape 2 :
sudo apt update
Ătape 3 :
sudo apt install astralc
# Vérifier la version
astralc --version
# Devrait afficher: astral 1.0.0
Créer un fichier .vscode/settings.json :
{
"files.associations": {
"*.astral": "rust"
},
"editor.tabSize": 4,
"editor.insertSpaces": true
}
Ajouter Ă .vimrc :
au BufRead,BufNewFile *.astral set filetype=rust
Créer hello.astral :
fn main() -> i32 {
return 0;
}
Compiler et exécuter :
astralc hello.astral -o hello
./hello
echo $? # Devrait afficher: 0
Un programme A.S.T.R.A.L typique a cette structure :
// 1. Attributs de programme (optionnel)
#![no_std]
// 2. Déclarations use (imports)
use math::sqrt;
use io::println;
// 3. Constantes globales
const MAX_SIZE: usize = 1024;
// 4. Structures et types
struct Point {
x: f64,
y: f64,
}
// 5. Fonctions
fn distance(p1: Point, p2: Point) -> f64 {
let dx: f64 = p2.x - p1.x;
let dy: f64 = p2.y - p1.y;
return sqrt(dx * dx + dy * dy);
}
// 6. Point d'entrée
fn main() -> i32 {
let p1: Point = Point { x: 0.0, y: 0.0 };
let p2: Point = Point { x: 3.0, y: 4.0 };
let dist: f64 = distance(p1, p2);
return 0;
}
// Commentaire sur une ligne
// Commentaires
// multi-lignes
// avec plusieurs //
/* Commentaires blocs ne sont pas encore supportés */
// Note: I/O pas encore complÚtement implémenté
fn main() -> i32 {
// Programme qui retourne 42
return 42;
}
Compilation :
astralc hello.astral -o hello
./hello
echo $? # Affiche: 42
// Fonctions : snake_case
fn calculate_distance() -> f64 { }
// Variables : snake_case
let my_variable: i32 = 42;
// Constantes : SCREAMING_SNAKE_CASE
const MAX_BUFFER_SIZE: usize = 4096;
// Types (structures) : PascalCase
struct Vector3D { }
// Génériques : Single uppercase letter
fn generic_function<T>() { }
// Variable immutable (défaut)
let x: i32 = 42;
// Variable mutable
mut y: i32 = 10;
y = 20; // OK
// Inférence de type (pas encore implémenté)
// let z = 42; // Sera i32 automatiquement
fn example() -> i32 {
let x: i32 = 10;
{
let y: i32 = 20;
// x et y sont visibles ici
}
// y n'est plus visible ici
// x est toujours visible
return x;
}
fn shadow_example() -> i32 {
let x: i32 = 5;
let x: i32 = x + 1; // Shadow la variable précédente
{
let x: i32 = x * 2; // Nouveau shadow dans ce scope
// x = 12 ici
}
// x = 6 ici
return x;
}
// Déclaration
let x: i32 = 42;
// Assignation
mut y: i32 = 10;
y = 20;
// Appel de fonction
calculate_sum(5, 10);
// Return
return 42;
Tout en A.S.T.R.A.L est une expression qui retourne une valeur :
// Expression arithmétique
let result: i32 = 2 + 3 * 4;
// Expression conditionnelle
let max: i32 = if a > b { a } else { b };
// Expression de bloc
let value: i32 = {
let temp: i32 = calculate();
temp * 2
};
let a: i32 = 10;
let b: i32 = 3;
let sum: i32 = a + b; // 13
let diff: i32 = a - b; // 7
let prod: i32 = a * b; // 30
let quot: i32 = a / b; // 3
let rem: i32 = a % b; // 1
// Négation
let neg: i32 = -a; // -10
let a: i32 = 10;
let b: i32 = 20;
let eq: bool = a == b; // false
let ne: bool = a != b; // true
let lt: bool = a < b; // true
let le: bool = a <= b; // true
let gt: bool = a > b; // false
let ge: bool = a >= b; // false
let t: bool = true;
let f: bool = false;
let and_result: bool = t && f; // false
let or_result: bool = t || f; // true
let not_result: bool = !t; // false
mut x: i32 = 10;
x = 20; // Assignation simple
x += 5; // x = x + 5 (25)
x -= 3; // x = x - 3 (22)
x *= 2; // x = x * 2 (44)
x /= 4; // x = x / 4 (11)
De la plus haute Ă la plus basse :
f(), x.y, a[i]-x, !x, *x, &x*, /, %+, -==, !=, <, >, <=, >=&&, ||=, +=, -=, etc.// Exemples de précédence
let result1: i32 = 2 + 3 * 4; // 14, pas 20
let result2: i32 = (2 + 3) * 4; // 20
let result3: bool = 5 > 3 && 10 < 20; // true
let a: i8 = 127; // -128 Ă 127
let b: i16 = 32767; // -32768 Ă 32767
let c: i32 = 2147483647; // -2^31 Ă 2^31-1
let d: i64 = 9223372036854775807; // -2^63 Ă 2^63-1
let e: i128 = 170141183460469231731687303715884105727; // TrĂšs grand
// Type dépendant de l'architecture (32 ou 64 bits)
let f: isize = 1000;
let a: u8 = 255; // 0 Ă 255
let b: u16 = 65535; // 0 Ă 65535
let c: u32 = 4294967295; // 0 Ă 2^32-1
let d: u64 = 18446744073709551615; // 0 Ă 2^64-1
let e: u128 = 340282366920938463463374607431768211455; // Ănorme
let f: usize = 1000; // Taille de pointeur
let pi: f32 = 3.14159265; // 32-bit IEEE 754
let e: f64 = 2.718281828459045; // 64-bit IEEE 754
// Notation scientifique
let avogadro: f64 = 6.02214076e23;
let planck: f64 = 6.62607015e-34;
let is_true: bool = true;
let is_false: bool = false;
// Utilisation dans conditions
if is_true {
// Code exécuté
}
let name: str = "A.S.T.R.A.L";
let message: str = "Hello, World!";
// CaractÚres d'échappement
let escaped: str = "Line 1\nLine 2\tTabbed";
let quote: str = "She said \"Hello\"";
// Fonction sans retour
fn print_message() -> void {
// Pas de return nécessaire
}
// Ăquivalent Ă () en Rust
// Déclaration avec initialisation
let numbers: [i32; 5] = [1, 2, 3, 4, 5];
// Tous les éléments identiques
let zeros: [i32; 10] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
// AccÚs aux éléments
let first: i32 = numbers[0]; // 1
let third: i32 = numbers[2]; // 3
mut arr: [i32; 3] = [1, 2, 3];
arr[0] = 10;
arr[1] = 20;
// arr est maintenant [10, 20, 3]
// Matrice 3x3
let matrix: [[i32; 3]; 3] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
let element: i32 = matrix[1][1]; // 5
// Référence à une portion d'un tableau
let numbers: [i32; 5] = [1, 2, 3, 4, 5];
let slice: &[i32] = &numbers[1..3]; // [2, 3]
// Grouper plusieurs valeurs de types différents
let point: (f64, f64) = (3.0, 4.0);
let person: (str, i32) = ("Alice", 30);
// AccĂšs par index
let x: f64 = point.0; // 3.0
let y: f64 = point.1; // 4.0
let x: i32 = 42;
let y: f64 = x as f64; // Conversion i32 â f64
let a: f64 = 3.14;
let b: i32 = a as i32; // 3 (truncation)
let large: i64 = 1000;
let small: i32 = large as i32;
// Ăviter les pertes de donnĂ©es
fn safe_convert(value: i64) -> i32 {
if value > 2147483647 {
return 2147483647; // MAX_I32
}
if value < -2147483648 {
return -2147483648; // MIN_I32
}
return value as i32;
}
fn function_name(param1: Type1, param2: Type2) -> ReturnType {
// Corps de la fonction
return result;
}
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
fn greet(name: str) -> void {
// Affichage (conceptuel)
}
fn get_answer() -> i32 {
return 42;
}
fn do_something() -> void {
// Code sans return
}
fn increment(x: i32) -> i32 {
return x + 1;
}
// Utilisation
let result: i32 = increment(5); // 6
// Référence immutable
fn print_value(x: &i32) -> void {
// x est en lecture seule
}
// Référence mutable
fn increment_in_place(x: &mut i32) -> void {
*x = *x + 1;
}
// Utilisation
mut value: i32 = 10;
increment_in_place(&mut value);
// value est maintenant 11
fn calculate(a: i32, b: i32, c: i32, d: i32) -> i32 {
return a * b + c * d;
}
fn double(x: i32) -> i32 {
return x * 2;
}
fn divide(a: i32, b: i32) -> i32 {
if b == 0 {
return 0; // Ăviter division par zĂ©ro
}
return a / b;
}
struct Point {
x: f64,
y: f64,
}
fn create_origin() -> Point {
return Point { x: 0.0, y: 0.0 };
}
fn factorial(n: i32) -> i32 {
if n <= 1 {
return 1;
}
return n * factorial(n - 1);
}
fn fibonacci(n: i32) -> i32 {
if n <= 1 {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
fn factorial_tail(n: i32, acc: i32) -> i32 {
if n <= 1 {
return acc;
}
return factorial_tail(n - 1, n * acc);
}
fn factorial(n: i32) -> i32 {
return factorial_tail(n, 1);
}
// Pointeur de fonction
type BinaryOp = fn(i32, i32) -> i32;
fn apply_op(a: i32, b: i32, op: BinaryOp) -> i32 {
return op(a, b);
}
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
// Utilisation
let result: i32 = apply_op(5, 3, add); // 8
@inline
fn fast_add(a: i32, b: i32) -> i32 {
return a + b;
}
// Le compilateur va substituer directement le code
// au lieu de faire un appel de fonction
@pure
fn square(x: f64) -> f64 {
return x * x;
}
// Une fonction pure :
// - Ne modifie aucun état global
// - Retourne toujours le mĂȘme rĂ©sultat pour les mĂȘmes entrĂ©es
// - Peut ĂȘtre optimisĂ©e agressivement par le compilateur
fn max(a: i32, b: i32) -> i32 {
if a > b {
return a;
} else {
return b;
}
}
fn check_positive(x: i32) -> void {
if x > 0 {
// Code exécuté si positif
}
}
fn categorize(score: i32) -> str {
if score >= 90 {
return "A";
} else if score >= 80 {
return "B";
} else if score >= 70 {
return "C";
} else if score >= 60 {
return "D";
} else {
return "F";
}
}
fn is_valid_range(x: i32, min: i32, max: i32) -> bool {
if x >= min && x <= max {
return true;
}
return false;
}
// Itération sur un range
fn sum_range(start: i32, end: i32) -> i32 {
mut sum: i32 = 0;
for i in start..end {
sum = sum + i;
}
return sum;
}
// Exemple : sum_range(1, 11) = 1+2+3+...+10 = 55
fn sum_array(arr: [i32; 5]) -> i32 {
mut sum: i32 = 0;
for i in 0..5 {
sum = sum + arr[i];
}
return sum;
}
fn infinite_loop() -> void {
loop {
// Code répété indéfiniment
// Nécessite une condition de sortie externe
}
}
fn find_value(target: i32) -> i32 {
mut i: i32 = 0;
loop {
if i == target {
return i; // Sortie de la boucle
}
i = i + 1;
}
}
// Syntaxe prévue (pas encore fonctionnelle)
match value {
0 => handle_zero(),
1 => handle_one(),
_ => handle_other(),
}
// Pattern avec Result
match result {
Ok(value) => process(value),
Err(error) => handle_error(error),
}
struct Point {
x: f64,
y: f64,
}
struct Person {
name: str,
age: i32,
}
struct Rectangle {
width: f64,
height: f64,
}
fn create_point() -> Point {
let p: Point = Point {
x: 10.0,
y: 20.0,
};
return p;
}
fn create_person() -> Person {
let person: Person = Person {
name: "Alice",
age: 30,
};
return person;
}
fn distance_from_origin(p: Point) -> f64 {
let x_squared: f64 = p.x * p.x;
let y_squared: f64 = p.y * p.y;
return x_squared + y_squared; // Simplifié, pas de sqrt
}
fn move_point(p: &mut Point, dx: f64, dy: f64) -> void {
p.x = p.x + dx;
p.y = p.y + dy;
}
// Utilisation
mut point: Point = Point { x: 0.0, y: 0.0 };
move_point(&mut point, 5.0, 3.0);
// point.x = 5.0, point.y = 3.0
struct Line {
start: Point,
end: Point,
}
fn create_line() -> Line {
let line: Line = Line {
start: Point { x: 0.0, y: 0.0 },
end: Point { x: 10.0, y: 10.0 },
};
return line;
}
fn line_length(line: Line) -> f64 {
let dx: f64 = line.end.x - line.start.x;
let dy: f64 = line.end.y - line.start.y;
return dx * dx + dy * dy;
}
// Syntaxe prévue (implémentation partielle)
struct Vector3 {
x: f64,
y: f64,
z: f64,
}
impl Vector3 {
fn length(&self) -> f64 {
return self.x * self.x + self.y * self.y + self.z * self.z;
}
fn normalize(&mut self) -> void {
let len: f64 = self.length();
self.x = self.x / len;
self.y = self.y / len;
self.z = self.z / len;
}
}
// Syntaxe prévue
enum Color {
Red,
Green,
Blue,
RGB(u8, u8, u8),
}
enum Option<T> {
Some(T),
None,
}
A.S.T.R.A.L suit le modÚle d'ownership inspiré de Rust :
fn ownership_example() -> void {
let s1: String = create_string(); // s1 possĂšde la string
let s2: String = s1; // s1 move vers s2
// s1 n'est plus utilisable ici
}
fn calculate_length(s: &str) -> usize {
// Lecture seule de s
return 0; // Simplifié
}
fn example() -> void {
let text: str = "Hello";
let len: usize = calculate_length(&text);
// text est toujours valide
}
fn append_exclamation(s: &mut String) -> void {
// Modification de s
}
fn example() -> void {
mut text: String = create_string();
append_exclamation(&mut text);
}
fn valid_borrowing() -> void {
let x: i32 = 5;
let r1: &i32 = &x; // OK
let r2: &i32 = &x; // OK, plusieurs refs immutables
// let r3: &mut i32 = &mut x; // ERREUR avec r1 et r2 existants
}
unsafe {
let x: i32 = 42;
let ptr: *i32 = &x as *i32;
let value: i32 = *ptr; // Déréférencement
}
unsafe {
mut x: i32 = 42;
let ptr: *mut i32 = &mut x as *mut i32;
*ptr = 100; // x est maintenant 100
}
@volatile
mut hardware_register: u32 @ 0x40000000;
unsafe {
*hardware_register = 0x01;
}
// Allocation dynamique (simplifié)
unsafe {
let ptr: *mut i32 = heap::allocate(size_of::<i32>(), align_of::<i32>());
*ptr = 42;
heap::deallocate(ptr, size_of::<i32>(), align_of::<i32>());
}
Force l'inlining de la fonction :
@inline
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
// Le compilateur remplacera les appels par le code directement
let result: i32 = 5 + 3; // Au lieu d'un call
Indique une fonction pure (pas d'effets de bord) :
@pure
fn square(x: f64) -> f64 {
return x * x;
}
// Permet des optimisations agressives
// Peut ĂȘtre Ă©liminĂ© si le rĂ©sultat n'est pas utilisĂ©
Préserve le nom de la fonction pour FFI :
@no_mangle
fn public_api_function() -> i32 {
return 42;
}
// Le nom reste "public_api_function" dans le binaire
// Utile pour l'interopérabilité avec C
Marque une fonction comme handler kernel :
@kernel
fn interrupt_handler() -> void {
// Code d'interruption
}
Fonction sans prologue/épilogue :
@naked
fn raw_function() -> void {
unsafe {
asm!(
"mov rax, 0",
"ret"
);
}
}
Spécifie l'alignement mémoire :
@aligned(16)
let buffer: [u8; 4096];
// buffer sera aligné sur une frontiÚre de 16 bytes
AccĂšs volatil (pour hardware) :
@volatile
mut register: u32 @ 0x40000000;
unsafe {
*register = 0xFF; // Lecture/écriture toujours effectuée
}
Programme sans bibliothĂšque standard :
#![no_std]
// Pas d'accĂšs Ă io, collections, etc.
// Utile pour kernels et embedded
Programme sans fonction main() standard :
#![no_std]
#![no_main]
@entry_point
fn _start() -> ! {
loop {}
}
Programme en mode kernel :
#![kernel]
#![no_std]
#![no_main]
@entry_point
fn kernel_main() -> ! {
// Code kernel
loop {}
}
Structure mappée en mémoire :
@memory_mapped
struct UART {
@offset(0x00) data: u32,
@offset(0x04) status: u32,
@offset(0x08) control: u32,
}
unsafe {
let uart: &mut UART = &mut *(0x10000000 as *mut UART);
uart.data = 0x41; // Ăcrire 'A'
}
@volatile
mut GPIO_DATA: u32 @ 0x3F200000;
@volatile
mut GPIO_DIR: u32 @ 0x3F200004;
fn configure_pin(pin: u32, output: bool) -> void {
unsafe {
if output {
*GPIO_DIR = *GPIO_DIR | (1 << pin);
} else {
*GPIO_DIR = *GPIO_DIR & !(1 << pin);
}
}
}
@aligned(64)
let dma_buffer: [u8; 4096];
fn setup_dma() -> void {
unsafe {
let buffer_addr: u64 = &dma_buffer as *u8 as u64;
// Configurer le DMA avec buffer_addr
}
}
unsafe {
asm!(
"mov rax, 0",
"mov rbx, 1",
"add rax, rbx"
);
}
fn read_cpu_id() -> u32 {
mut result: u32 = 0;
unsafe {
asm!(
"cpuid",
"mov {}, eax",
out(reg) result
);
}
return result;
}
unsafe {
asm!(
"mov rax, {}",
"add rax, 1",
in(reg) 42,
clobber_abi("C")
);
}
@interrupt_handler(IRQ_TIMER)
fn timer_interrupt() -> void {
unsafe {
// Acquitter l'interruption
*PIC_EOI = 0x20;
}
}
struct IDTEntry {
offset_low: u16,
selector: u16,
ist: u8,
flags: u8,
offset_mid: u16,
offset_high: u32,
reserved: u32,
}
const IDT_SIZE: usize = 256;
mut IDT: [IDTEntry; IDT_SIZE];
fn setup_idt() -> void {
// Configurer les entrées IDT
}
struct PageTableEntry {
present: bool,
writable: bool,
user_accessible: bool,
write_through: bool,
cache_disabled: bool,
accessed: bool,
dirty: bool,
page_size: bool,
global: bool,
available: u8,
physical_address: u64,
}
fn map_page(virtual_addr: u64, physical_addr: u64) -> void {
unsafe {
// Créer mapping dans page table
}
}
@section(".boot")
@naked
fn _start() -> ! {
unsafe {
asm!(
"mov sp, #0x8000",
"bl kernel_main"
);
}
loop {}
}
// Syntaxe prévue
let distance: meter = 100.0;
let time: second = 10.0;
let speed: meter/second = distance / time;
let mass: kilogram = 70.0;
let force: newton = mass * 9.81;
let energy: joule = force * distance;
let power: watt = energy / time;
let density: kg/meterÂł = 1000.0;
let acceleration: meter/secondÂČ = 9.81;
let pressure: pascal = 101325.0;
const C: meter/second = physics::SPEED_OF_LIGHT; // 299792458.0
const G: meterÂł/kilogram/secondÂČ = physics::GRAVITATIONAL_CONSTANT;
const PLANCK: joule*second = physics::PLANCK_CONSTANT;
// Syntaxe prévue
fn max<T>(a: T, b: T) -> T {
if a > b {
return a;
}
return b;
}
// Utilisation
let max_int: i32 = max::<i32>(10, 20);
let max_float: f64 = max::<f64>(3.14, 2.71);
struct Pair<T> {
first: T,
second: T,
}
let int_pair: Pair<i32> = Pair {
first: 10,
second: 20,
};
trait Drawable {
fn draw(&self) -> void;
fn clear(&self) -> void;
}
struct Circle {
radius: f64,
}
impl Drawable for Circle {
fn draw(&self) -> void {
// Code de dessin
}
fn clear(&self) -> void {
// Code d'effacement
}
}
@parallel
parallel for i in 0..1000 {
process(i);
}
@simd
fn vector_add(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
mut result: [f32; 4];
for i in 0..4 {
result[i] = a[i] + b[i];
}
return result;
}
@gpu
@workgroup(256)
fn gpu_compute(id: u32, data: &mut [f32]) -> void {
data[id] = sqrt(data[id]) * 2.0;
}
use collections::Vec;
fn example() -> void {
mut v: Vec<i32> = Vec::new();
v.push(1);
v.push(2);
v.push(3);
let first: i32 = v.get(0); // 1
let len: usize = v.len(); // 3
}
use collections::HashMap;
fn example() -> void {
mut map: HashMap<str, i32> = HashMap::new();
map.insert("one", 1);
map.insert("two", 2);
let value: i32 = map.get("one"); // 1
}
use io::println;
fn example() -> void {
println("Hello, World!");
println("The answer is 42");
}
use fs::File;
fn read_file(path: str) -> String {
let file: File = File::open(path);
let contents: String = file.read_all();
return contents;
}
use math::*;
fn example() -> void {
let sq: f64 = sqrt(16.0); // 4.0
let sine: f64 = sin(PI / 2.0); // 1.0
let power: f64 = pow(2.0, 8.0); // 256.0
let log: f64 = ln(E); // 1.0
}
use physics::*;
fn example() -> void {
const C: f64 = SPEED_OF_LIGHT; // 299792458 m/s
const G: f64 = GRAVITATIONAL_CONSTANT;
const h: f64 = PLANCK_CONSTANT;
const Na: f64 = AVOGADRO_NUMBER;
}
# Pas d'optimisation (debug)
astralc program.astral -O0
# Optimisation légÚre
astralc program.astral -O1
# Optimisation standard (recommandé)
astralc program.astral -O2
# Optimisation agressive
astralc program.astral -O3
# Optimisation pour la taille
astralc program.astral -Os
// Force inline
@inline
fn small_function() -> i32 {
return 42;
}
// SuggĂšre de ne pas inline
@inline(never)
fn large_function() -> i32 {
// Code volumineux
return 0;
}
@inline
fn sum_array_4(arr: [i32; 4]) -> i32 {
// Le compilateur peut unroll cette boucle
mut sum: i32 = 0;
for i in 0..4 {
sum = sum + arr[i];
}
return sum;
}
// â
Sur la stack (rapide)
fn good_performance() -> void {
let arr: [i32; 100];
// ...
}
// â Sur le heap (plus lent, si implĂ©mentĂ©)
fn slower_performance() -> void {
let vec: Vec<i32> = Vec::with_capacity(100);
// ...
}
fn process_multiple() -> void {
mut buffer: [u8; 4096];
for i in 0..10 {
// RĂ©utilise le mĂȘme buffer
fill_buffer(&mut buffer);
process_buffer(&buffer);
}
}
# Avec symboles de debug
astralc program.astral -g -o program
# Profiler avec perf (Linux)
perf record ./program
perf report
# Mode debug avec symboles
astralc program.astral -g -O0 -o program_debug
# Utiliser gdb
gdb program_debug
fn example() -> void {
let x: i32 = 42;
assert!(x == 42);
assert_eq!(x, 42);
assert_ne!(x, 0);
}
#[test]
fn test_addition() -> void {
assert_eq!(add(2, 3), 5);
}
#[test]
fn test_fibonacci() -> void {
assert_eq!(fibonacci(0), 0);
assert_eq!(fibonacci(1), 1);
assert_eq!(fibonacci(10), 55);
}
// fibonacci.astral
fn fibonacci(n: i32) -> i32 {
if n <= 1 {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
fn fibonacci_iterative(n: i32) -> i32 {
if n <= 1 {
return n;
}
mut a: i32 = 0;
mut b: i32 = 1;
mut i: i32 = 2;
for i in 2..n {
let temp: i32 = a + b;
a = b;
b = temp;
}
return b;
}
fn main() -> i32 {
let result: i32 = fibonacci_iterative(10);
return result; // 55
}
Compilation :
astralc fibonacci.astral -O2 -o fib
./fib
echo $? # Affiche: 55
// distance.astral
struct Point {
x: f64,
y: f64,
}
fn distance_squared(p1: Point, p2: Point) -> f64 {
let dx: f64 = p2.x - p1.x;
let dy: f64 = p2.y - p1.y;
return dx * dx + dy * dy;
}
fn create_point(x: f64, y: f64) -> Point {
return Point { x: x, y: y };
}
fn main() -> i32 {
let origin: Point = create_point(0.0, 0.0);
let point: Point = create_point(3.0, 4.0);
let dist_sq: f64 = distance_squared(origin, point);
// dist_sq = 25.0 (distance réelle = 5.0)
return 0;
}
// bubble_sort.astral
fn bubble_sort(arr: &mut [i32; 10]) -> void {
let n: usize = 10;
for i in 0..n {
for j in 0..(n - i - 1) {
if arr[j] > arr[j + 1] {
// Swap
let temp: i32 = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
fn main() -> i32 {
mut numbers: [i32; 10] = [64, 34, 25, 12, 22, 11, 90, 88, 45, 50];
bubble_sort(&mut numbers);
// numbers est maintenant trié
return 0;
}
// factorial.astral
fn factorial_helper(n: i32, acc: i32) -> i32 {
if n <= 1 {
return acc;
}
return factorial_helper(n - 1, n * acc);
}
fn factorial(n: i32) -> i32 {
return factorial_helper(n, 1);
}
fn main() -> i32 {
let result: i32 = factorial(5); // 120
return result;
}
// binary_search.astral
fn binary_search(arr: [i32; 10], target: i32) -> i32 {
mut left: i32 = 0;
mut right: i32 = 9;
for _ in 0..10 { // Max 10 itérations
if left > right {
return -1; // Non trouvé
}
let mid: i32 = left + (right - left) / 2;
if arr[mid] == target {
return mid;
}
if arr[mid] < target {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
fn main() -> i32 {
let sorted: [i32; 10] = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
let index: i32 = binary_search(sorted, 11); // 5
return index;
}
// kernel.astral
#![no_std]
#![no_main]
@section(".boot")
@naked
fn _start() -> ! {
unsafe {
asm!(
"mov sp, #0x8000",
"bl kernel_main"
);
}
loop {}
}
@entry_point
fn kernel_main() -> ! {
// Initialisation du kernel
init_hardware();
// Boucle principale
loop {
handle_interrupts();
}
}
fn init_hardware() -> void {
// Configuration matérielle
}
fn handle_interrupts() -> void {
// Gestion des interruptions
}
@panic_handler
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
fn |
Définit une fonction |
let |
Déclare une variable immutable |
mut |
Déclare une variable mutable |
const |
Déclare une constante |
struct |
Définit une structure |
trait |
Définit un trait |
impl |
Implémente un trait |
for |
Boucle for |
if |
Condition |
else |
Branche else |
match |
Pattern matching |
loop |
Boucle infinie |
while |
Boucle while |
in |
Itération dans un range |
parallel |
Boucle parallĂšle |
return |
Retourne d'une fonction |
use |
Importe un module |
unsafe |
Bloc non-sûr |
asm |
Assembleur inline |
as |
Cast de type |
void |
Type vide |
// Entiers signés
i8, i16, i32, i64, i128, isize
// Entiers non-signés
u8, u16, u32, u64, u128, usize
// Flottants
f32, f64
// Autres
bool Booléen (true/false)
str ChaĂźne de caractĂšres
// Arithmétiques
+ - * / %
// Comparaison
== != < > <= >=
// Logiques
&& || !
// Assignation
= += -= *= /=
// AccĂšs
. AccĂšs aux champs
[] Indexation de tableau
& Référence
* Déréférencement
:: Path separator
@inline |
Force inline |
@pure |
Fonction pure |
@no_mangle |
Préserve le nom |
@kernel |
Handler kernel |
@naked |
Pas de prologue/épilogue |
@aligned(N) |
Alignement N bytes |
@volatile |
AccĂšs volatil |
@simd |
Vectorisation SIMD |
@parallel |
Parallélisation |
@gpu |
Exécution GPU |
@workgroup(N) |
Taille workgroup GPU |
#![no_std] |
Sans stdlib |
#![no_main] |
Sans main() |
#![kernel] |
Mode kernel |
-o <file> Fichier de sortie
-O0/-O1/-O2/-O3 Niveau d'optimisation
--emit-llvm Générer LLVM IR
--emit-asm Générer assembleur
--no-std Sans stdlib
--target Target triple
-g Symboles de debug
// Fonctions et variables : snake_case
fn calculate_sum() -> i32 { }
let my_variable: i32 = 42;
// Types : PascalCase
struct MyStruct { }
// Constantes : SCREAMING_SNAKE_CASE
const MAX_SIZE: usize = 1024;
// Génériques : Single letter uppercase
fn generic<T>() { }
A.S.T.R.A.L est un langage de programmation systÚme ambitieux qui combine performance, sûreté mémoire et support scientifique. Bien qu'actuellement en version prototype, il démontre déjà des capacités solides pour la programmation systÚme de base.
â Fonctionnel
ⳠEn Développement
Pour continuer votre apprentissage :