Questa guida mostra come usare i tipi generati per un pacchetto Lake nel pacchetto generato per un altro pacchetto che lo richiede, così che i valori passino dall’uno all’altro senza conversioni.
Supponi che il pacchetto Lake drawing richieda il pacchetto geometry. Generati
separatamente, ciascuno ha il proprio tipo per la structure Lean Geometry.Point, e un Point
dell’uno non può essere passato a una funzione dell’altro. Indicare alla generazione di
drawing quale tipo fornisce Geometry.Point (un tipo extern) le fa usare quello di
geometry.
In Rust
Compila ogni pacchetto in build.rs, e indica alla build di drawing quale tipo Rust fornisce
ciascun tipo Lean di geometry che usa:
fn main() -> lungo_build::Result<()> {
lungo_build::compile_lean("lean/geometry")?;
lungo_build::configure()
.extern_type("Geometry.Point", "crate::geometry::Point")
.extern_type("Geometry.Shape", "crate::geometry::Shape")
.compile_lean("lean/drawing")
}
I percorsi Rust sono visti dalla radice del crate; ogni modulo prende il nome dal suo pacchetto Lake:
pub mod geometry {
lungo::include_lean!("geometry");
}
pub mod drawing {
lungo::include_lean!("drawing");
}
Ora le funzioni di drawing accettano e restituiscono i tipi di geometry:
use my_crate::{drawing, geometry::Point};
use lungo::Int;
let a = Point { x: Int::from(-4), y: Int::from(2) };
let b = Point { x: Int::from(8), y: Int::from(6) };
let mid: Point = drawing::midpoint(a, b);
Un tipo i cui valori può costruire solo il codice Lean (uno con una dimostrazione tra i suoi
campi) è opaco: il modulo di geometry vi si riferisce come
lungo::LeanValue<crate::geometry::__opaque::<Name>>, ed è quello il percorso da indicare.
Negli altri linguaggi
La tabella di ciascun linguaggio in lungo.toml indica il tipo dell’altro pacchetto per un
tipo Lean (vedi tipi extern):
# lungo.toml di drawing
project = "lean/drawing"
[go]
out = "drawing"
[go.extern-types."Geometry.Point"]
package = "example.com/app/geometry" # il pacchetto Go generato per geometry
name = "Point"
package è ciò che il linguaggio importa (un percorso di import Go, un modulo Python, un
modulo Swift, uno specificatore di modulo JavaScript, un header C) e name il tipo come lo ha
chiamato il generatore di geometry. I valori creati da un programma passano all’altro così
come sono: tramite handle per i tipi opachi, poiché entrambi girano sull’unico runtime del
processo. In TypeScript ogni programma gira in una propria istanza WebAssembly, quindi lì si
possono condividere solo i tipi i cui valori sono dati semplici; un tipo opaco viene rifiutato.
Che cosa lo rende sicuro
Il codice compilato di drawing legge i valori di geometry secondo il layout per cui è stato
compilato. Entrambi devono provenire dalla stessa definizione del tipo, e di ogni tipo
raggiunto dai suoi campi. Ogni tipo generato porta un’impronta del layout, e drawing controlla
quella di geometry prima che qualcosa venga eseguito: in Rust non compila con un’altra (il
tipo fornito implementa lungo::LeanLayout, cosa che un tipo generato da lungo fa già), e
negli altri linguaggi il pacchetto si rifiuta di caricarsi, indicando il tipo e il pacchetto
che lo fornisce. La soluzione è rigenerarli entrambi dalla stessa definizione Lean.
I tipi di drawing che contengono un tipo extern Rust derivano solo Clone e Debug, poiché
lungo non sa quali altri trait implementi il tipo extern; aggiungi altre derivazioni con
type_attribute. Una mappatura per un tipo Lean che nessuna dichiarazione esportata usa
fallisce con LNG0107.
In lungo-rs, compiler-tests/shaping
compila due moduli Rust di questo tipo, e
compiler-tests/extern
condivide tipi tra due programmi in ogni linguaggio.