plcc/src/dsl.rs

77 lines
1.6 KiB
Rust
Raw Normal View History

2025-12-26 14:07:16 +03:00
use crate::support::{run_parallel, Arc};
2025-12-26 06:45:35 +03:00
// Обобщённое выражение: I -> Out
pub trait Expr<I> {
type Out;
fn eval(&self, x: I) -> Self::Out;
}
2025-12-26 14:07:16 +03:00
// Позволяет использовать Arc<T> там, где требуется Expr.
impl<I, T> Expr<I> for Arc<T>
where
T: Expr<I> + ?Sized,
{
type Out = T::Out;
fn eval(&self, x: I) -> Self::Out {
(**self).eval(x)
}
}
2025-12-26 06:45:35 +03:00
// атомарная функция
pub struct Function<I, O> {
pub f: fn(I) -> O,
}
impl<I, O> Expr<I> for Function<I, O> {
type Out = O;
fn eval(&self, x: I) -> O {
(self.f)(x)
}
}
// композиция g∘f
pub struct Composition<F1, F2> {
pub first: F1,
pub second: F2,
}
impl<I, F1, F2> Expr<I> for Composition<F1, F2>
where
F1: Expr<I>,
F2: Expr<F1::Out>,
{
type Out = F2::Out;
fn eval(&self, x: I) -> Self::Out {
let mid = self.first.eval(x);
self.second.eval(mid)
}
}
// junction — две ветки параллельно
2025-12-26 14:07:16 +03:00
pub struct Junction<F1: ?Sized, F2: ?Sized> {
2025-12-26 06:45:35 +03:00
pub left: Arc<F1>,
pub right: Arc<F2>,
}
impl<I, F1, F2> Expr<I> for Junction<F1, F2>
where
I: Copy + Send + 'static,
2025-12-26 14:07:16 +03:00
F1: Expr<I> + Send + Sync + 'static + ?Sized,
F2: Expr<I> + Send + Sync + 'static + ?Sized,
2025-12-26 06:45:35 +03:00
F1::Out: Send + 'static,
F2::Out: Send + 'static,
{
type Out = (F1::Out, F2::Out);
fn eval(&self, x: I) -> (F1::Out, F2::Out) {
let l = Arc::clone(&self.left);
let r = Arc::clone(&self.right);
let x1 = x;
let x2 = x;
2025-12-26 14:07:16 +03:00
run_parallel(move || l.eval(x1), move || r.eval(x2))
2025-12-26 06:45:35 +03:00
}
}