Crepe adalah perpustakaan yang memungkinkan Anda untuk menulis program logika deklaratif di Rust, dengan sintaksis seperti datalog. Ini menyediakan makro prosedural yang menghasilkan kode yang efisien dan aman dan interoperasi dengan mulus dengan program karat.
@input Program di bawah ini menghitung penutupan transitif grafik terarah. Perhatikan penggunaan crepe! makro.
use crepe :: crepe ;
crepe ! {
@input
struct Edge ( i32 , i32 ) ;
@output
struct Reachable ( i32 , i32 ) ;
Reachable ( x , y ) <- Edge ( x , y ) ;
Reachable ( x , z ) <- Edge ( x , y ) , Reachable ( y , z ) ;
}
fn main ( ) {
let mut runtime = Crepe :: new ( ) ;
runtime . extend ( [ Edge ( 1 , 2 ) , Edge ( 2 , 3 ) , Edge ( 3 , 4 ) , Edge ( 2 , 5 ) ] ) ;
let ( reachable , ) = runtime . run ( ) ;
for Reachable ( x , y ) in reachable {
println ! ( "node {} can reach node {}" , x , y ) ;
}
}Keluaran:
node 1 can reach node 2
node 1 can reach node 3
node 1 can reach node 4
node 1 can reach node 5
node 2 can reach node 3
node 2 can reach node 4
node 2 can reach node 5
node 3 can reach node 4
Anda dapat melakukan lebih banyak lagi dengan crepe. Contoh berikutnya menunjukkan bagaimana Anda dapat menggunakan negasi bertingkat, sintaks ekspresi karat, dan evaluasi semi-naif untuk menemukan semua jalur dalam grafik tertimbang dengan panjang paling banyak MAX_PATH_LEN .
use crepe :: crepe ;
const MAX_PATH_LEN : u32 = 20 ;
crepe ! {
@input
struct Edge ( i32 , i32 , u32 ) ;
@output
struct Walk ( i32 , i32 , u32 ) ;
@output
struct NoWalk ( i32 , i32 ) ;
struct Node ( i32 ) ;
Node ( x ) <- Edge ( x , _ , _ ) ;
Node ( x ) <- Edge ( _ , x , _ ) ;
Walk ( x , x , 0 ) <- Node ( x ) ;
Walk ( x , z , len1 + len2 ) <-
Edge ( x , y , len1 ) ,
Walk ( y , z , len2 ) ,
( len1 + len2 <= MAX_PATH_LEN ) ;
NoWalk ( x , y ) <- Node ( x ) , Node ( y ) , ! Walk ( x , y , _ ) ;
}
fn main ( ) {
let n = 256 ;
let mut edges = Vec :: new ( ) ;
for i in 0 ..n {
for j in 0 ..n {
if rand :: random :: < f32 > ( ) < 0.02 {
edges . push ( Edge ( i , j , 5 ) ) ;
}
}
}
let mut runtime = Crepe :: new ( ) ;
runtime . extend ( edges ) ;
let ( walk , nowalk ) = runtime . run ( ) ;
println ! ( "Walk: {}" , walk . len ( ) ) ;
println ! ( "NoWalk: {}" , nowalk . len ( ) ) ;
}Keluaran:
Walk: 89203
NoWalk: 8207
Dari pengujian awal, kode yang dihasilkan sangat cepat. Varian penutupan transitif untuk grafik besar (~ 10 6 relasi) berjalan pada kecepatan yang sebanding untuk menyusun souffle, dan menggunakan sebagian kecil dari waktu kompilasi.
Untuk tolok ukur, lihat benches/ direktori. Tolok ukur dapat dijalankan menggunakan cargo bench .
Makro ini menghasilkan struce Crepe dalam modul saat ini, serta struct untuk semua hubungan yang dinyatakan. Ini berarti bahwa untuk mengintegrasikan crepe di dalam program yang lebih besar, Anda harus memasukkannya ke dalam modulnya sendiri dengan kode terkait. Lihat dokumentasi untuk informasi lebih lanjut.
Proyek ini sangat terinspirasi oleh Souffle dan Formulog, yang keduanya menggunakan model yang serupa dari kompilasi Datalog untuk analisis statis.