Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Rust ports #18

Closed
wants to merge 55 commits into from
Closed

[Feature] Rust ports #18

wants to merge 55 commits into from

Conversation

RolandMacDoland
Copy link
Contributor

@RolandMacDoland RolandMacDoland commented Jun 13, 2024

Closes #16

@RolandMacDoland
Copy link
Contributor Author

@dominikandreasseitz @kaosmicadei Here is a very naive attempt at porting lower level types for expressions. If you want to have a look (can't add multiple reviewers until it goes public).

@RolandMacDoland RolandMacDoland changed the title [Feature] Rust binders [Feature] Rust ports Jun 13, 2024
src/symbols.rs Outdated Show resolved Hide resolved
src/symbols.rs Outdated Show resolved Hide resolved
src/symbols.rs Outdated Show resolved Hide resolved
@kaosmicadei
Copy link
Contributor

kaosmicadei commented Jun 14, 2024

Suggestion.

It would be possible to consider the whole expression + symbol as a single enum to preserve the monoid properties of addition and other operations. In the sense that:

  • A symbol is an expression
  • A numerical value is an expression
  • A tuple (operator, list<expression>) is an expression

That would make Int(...) + Int(…) : Expr the same way Expr(…) + Symbol(…) : Expr

use num::Complex;

#[derive(Debug, PartialEq)]
pub enum Operator {
   Add,
   Mul,
   Pow,
   NonComm,
   Call
}

#[derive(Debug, PartialEq)]
pub enum Numerical {
    Int(i64),
    Float(f64),
    Complex(Complex<f64>),
}

#[derive(Debug, PartialEq)]
pub enum Expression {
    Symbol(&'static str),
    Value(Numerical),
    Expr { head: Operator, args: Vec<Box<Expression>> },
}

@RolandMacDoland
Copy link
Contributor Author

@kaosmicadei Makes sense. Lemme have a go at it.

src/symbols.rs Outdated Show resolved Hide resolved
src/expression.rs Outdated Show resolved Hide resolved
@RolandMacDoland
Copy link
Contributor Author

Suggestion.

It would be possible to consider the whole expression + symbol as a single enum to preserve the monoid properties of addition and other operations. In the sense that:

Naive question: would anything else than an enum break monoidal properties ?

@RolandMacDoland
Copy link
Contributor Author

Quick comment @kaosmicadei. Would it make sense to move all boxing constructors to the convenience functions ?

@kaosmicadei
Copy link
Contributor

kaosmicadei commented Jun 18, 2024

Quick comment @kaosmicadei. Would it make sense to move all boxing constructors to the convenience functions ?

Based on https://doc.rust-lang.org/std/macro.vec.html we could do something like

macro_rules! vbox {
    () => { vec![] };
    ($elem:expr; $n:expr) => { vec![Box::new($elem); $n] };
    ($($x:expr),+ $(,)?) => { vec![$(Box::new($x)),*] };
}

Actually, in our case, the second pattern could be omitted.

@kaosmicadei
Copy link
Contributor

The macro implementation.

macro_rules! vbox {
   () => { vec![] };
   ($($x:expr),+ $(,)?) => { vec![$(Box::new($x)),*] };
}

macro_rules! impl_binary_operator_for_expression {
   ($trait:ident, $method:ident, $operator:path) => {
       impl $trait for Expression {
          type Output = Self;

          fn $method(self, other: Self) -> Self {
             use Expression::*;

             match (self, other) {
                (Value(x), Value(y)) => Value(x.$method(y)),

                (Expr {head: $operator, args: args_lhs}, Expr {head: $operator, args: args_rhs}) => {
                   let args = args_lhs.into_iter().chain(args_rhs.into_iter()).collect();
                   Expr{head: $operator, args}
                },

                (Expr {head: $operator, args: mut args_lhs}, rhs) => {
                   args_lhs.push(Box::new(rhs));
                   Expr {head: $operator, args: args_lhs}
                },

                (lhs, Expr {head: $operator, args: mut args_rhs}) => {
                   args_rhs.push(Box::new(lhs));
                   Expr {head: $operator, args: args_rhs}
                },

                (lhs, rhs) => Expr{head: $operator, args: vbox![lhs, rhs]},
             }
          }
       }
   };

   ($trait:ident, $method:ident, $operator:path, $inv:expr) => {
      impl $trait for Expression {
         type Output = Self;

         fn $method(self, other: Self) -> Self {
            use Expression::*;

            match (self, other) {
               (Value(x), Value(y)) => Value(x.$method(y)),
               (lhs, rhs) => Expr {
                  head: $operator,
                  args: vbox![lhs, $inv(rhs)]
               },
            }
         }
      }
   }
}

impl_binop!(Add, add, Operator::ADD);
impl_binop!(Mul, mul, Operator::MUL);
impl_binop!(Sub, sub, Operator:: ADD, |x: Expression| { x.neg() });
impl_binop!(Div, div, Operator:: ADD, |x: Expression| { x.pow(Expression::float(-1.0)) });

It requires the implementation of the Neg trait.

@RolandMacDoland
Copy link
Contributor Author

RolandMacDoland commented Jun 19, 2024

The macro implementation.
...

It would also require the pow trait, wouldn't it ?

@kaosmicadei
Copy link
Contributor

The macro implementation.
...

It would also require the pow trait, wouldn't it ?

This one?
I think it could be optional, but maybe by completeness

src/symbols.rs Outdated Show resolved Hide resolved
@RolandMacDoland
Copy link
Contributor Author

The macro implementation.
...

It would also require the pow trait, wouldn't it ?

This one? I think it could be optional, but maybe by completeness

Yes, I was on that one too.

src/symbols.rs Outdated Show resolved Hide resolved
@RolandMacDoland RolandMacDoland deleted the rg/rust-binders branch October 16, 2024 09:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature] Port basic types to Rust
2 participants