commit 00e2260bb3b9b87ccf6749a0a457ae615ec3f9ab Author: Gregory Bednov Date: Fri Dec 26 06:45:35 2025 +0300 wow it works diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0e0be5d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "plcc" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a39bedb --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "plcc" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..9b5db5e --- /dev/null +++ b/shell.nix @@ -0,0 +1,9 @@ +{ pkgs ? import {} }: + +pkgs.mkShell { + buildInputs = [ + pkgs.rustc + pkgs.cargo + ]; +} + diff --git a/src/ast.rs b/src/ast.rs new file mode 100644 index 0000000..b2e0692 --- /dev/null +++ b/src/ast.rs @@ -0,0 +1,28 @@ +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum Prim { + Sin, + Cos, + Triple, // 3 * x + AddPair, // (a,b) -> a + b + Input, // переменная x +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ExprAst { + Atom(Prim), + Composition(Box, Box), // g ∘ f + Junction(Box, Box), // (f, g) +} + +pub fn ast_input() -> ExprAst { + ExprAst::Atom(Prim::Input) +} + +pub fn hash_ast(e: &ExprAst) -> u64 { + let mut h = DefaultHasher::new(); + e.hash(&mut h); + h.finish() +} diff --git a/src/dsl.rs b/src/dsl.rs new file mode 100644 index 0000000..accd2d8 --- /dev/null +++ b/src/dsl.rs @@ -0,0 +1,69 @@ +use std::sync::Arc; +use std::thread; + +// Обобщённое выражение: I -> Out +pub trait Expr { + type Out; + fn eval(&self, x: I) -> Self::Out; +} + +// атомарная функция +pub struct Function { + pub f: fn(I) -> O, +} + +impl Expr for Function { + type Out = O; + fn eval(&self, x: I) -> O { + (self.f)(x) + } +} + +// композиция g∘f +pub struct Composition { + pub first: F1, + pub second: F2, +} + +impl Expr for Composition +where + F1: Expr, + F2: Expr, +{ + type Out = F2::Out; + + fn eval(&self, x: I) -> Self::Out { + let mid = self.first.eval(x); + self.second.eval(mid) + } +} + +// junction — две ветки параллельно +pub struct Junction { + pub left: Arc, + pub right: Arc, +} + +impl Expr for Junction +where + I: Copy + Send + 'static, + F1: Expr + Send + Sync + 'static, + F2: Expr + Send + Sync + 'static, + 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; + + let h1 = thread::spawn(move || l.eval(x1)); + let h2 = thread::spawn(move || r.eval(x2)); + + (h1.join().unwrap(), h2.join().unwrap()) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..c3ee6e2 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,117 @@ +// src/main.rs +mod ast; +mod dsl; + +use std::sync::Arc; + +use ast::{ + ExprAst, ExprAst::Atom, ExprAst::Composition as C, ExprAst::Junction as J, Prim::AddPair, + Prim::Cos, Prim::Input, Prim::Sin, Prim::Triple, ast_input, hash_ast, +}; +use dsl::{Composition, Expr, Function, Junction}; + +// ========= тестовые функции ========= + +fn sin_f(x: f64) -> f64 { + x.sin() +} +fn cos_f(x: f64) -> f64 { + x.cos() +} +fn triple(x: f64) -> f64 { + 3.0 * x +} + +// (a,b) -> a + b +fn add_pair(p: (f64, f64)) -> f64 { + p.0 + p.1 +} + +// ========= демонстрация ========= + +// AST для sin(cos(x) + 3*x) +fn pupa() -> ExprAst { + // cos(x) + let cos_x = C(Box::new(ast_input()), Box::new(Atom(Cos))); + + // 3 * x + let triple_x = C(Box::new(ast_input()), Box::new(Atom(Triple))); + + // (cos(x), 3*x) + let j = J(Box::new(cos_x), Box::new(triple_x)); + + // AddPair ∘ Junction => cos(x) + 3*x + let add = C(Box::new(j), Box::new(Atom(AddPair))); + + // Sin ∘ (AddPair ∘ Junction) + C(Box::new(add), Box::new(Atom(Sin))) +} + +fn lupa() -> ExprAst { + use ast::*; + // cos(x) + let cos_x = C(Box::new(ast::ast_input()), Box::new(Atom(Cos))); + + // 3 * x + let triple_x = C(Box::new(ast_input()), Box::new(Atom(Triple))); + + // (cos(x), 3*x) + let j = J(Box::new(triple_x), Box::new(cos_x)); + + // AddPair ∘ Junction => cos(x) + 3*x + let add = C(Box::new(j), Box::new(Atom(AddPair))); + + // Sin ∘ (AddPair ∘ Junction) + C(Box::new(add), Box::new(Atom(Sin))) +} + +fn main() { + // --- исполняемый граф для sin(cos(x) + 3*x) --- + + let cos_expr = Function { f: cos_f }; // f64 -> f64 + let mul3_expr = Function { f: triple }; // f64 -> f64 + + // (cos(x), 3*x) параллельно + let j = Junction { + left: Arc::new(cos_expr), + right: Arc::new(mul3_expr), + }; // f64 -> (f64,f64) + + // (a,b) -> a+b + let add_expr = Function { f: add_pair }; // (f64,f64) -> f64 + let sin_expr = Function { f: sin_f }; // f64 -> f64 + + // (f64,f64) -> f64 -> f64 === sin(a+b) + let sum_then_sin = Composition { + first: add_expr, + second: sin_expr, + }; + + // полный конвейер: x -> (cos(x),3x) -> cos(x)+3x -> sin(...) + let full = Composition { + first: j, + second: sum_then_sin, + }; + + let x = 2.0; + let y = full.eval(x); // y = sin(cos(x) + 3*x) + + println!("sin(cos({}) + 3*{}) = {}", x, x, y); + + // --- AST + hash для того же выражения --- + + let ast = pupa(); + let h = hash_ast(&ast); + + println!("AST: {ast:#?}"); + println!("AST hash: {h:016x}\n"); + + println!("comparison:"); + + let ast1 = pupa(); + let ast2 = lupa(); + + println!("equal? {}", ast1 == ast2); + println!("hash1 = {:016x}", hash_ast(&ast1)); + println!("hash2 = {:016x}", hash_ast(&ast2)); +}