1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! This library is used to define types that implement the trait  `FiniteElement`
//!  
//! The types are defined by procedural macros. To create a new type, one must first define an
//! unit-like Structure and implement the trait `AutoImplementable` for it. Once the trait
//! `AutoImplementable` has been implemented it is possible to define a proc macro that will
//! generate the deffinition of a new type and an implementation of the trait `FiniteElement` for
//! it.
//!
//! # Creation of a new macro
//!
//! To create a new macro, one must first define a Zero-Sized `struct`, and implement the trait
//! `AutoImplementable` for it. For example if we want to create an element representing a spring,
//! we first create a zero-sized `struct`: `pub struct _Spring{}` and the implement the trait
//! `Autotimplementable` for it.
//!
//! The types that implement the trait `AutoImplementable` can be passed as type argument to the
//! function `macro_def<F: Float, T: AutoImplementable<F>>() -> TokenStream`. This function
//! can be used to define a procedural macro that will generate the code defining the
//! corresponding structure and its implementation of the trait `FiniteElement`. 
//! Complete example
//! (copied-pasted from `spring.rs`)
//! ```
//!
//!use crate::formal::{Formal, FormalVector, FormalPoint, Float};
//!use crate::autoimplementable::AutoImplementable;
//!
//!use std::collections::HashMap;
//!
//!// A `Spring` likes it when `a` and `b` are at distance `l`, and
//!// exerts a force of `k.(|ab| - l)` to achieve this.
//!pub struct _Spring{}
//!
//!impl<F: Float> AutoImplementable<F> for _Spring {
//!    fn struct_name() -> String {
//!        String::from("Spring")
//!    }
//!
//!    fn elt_list() -> Vec<String> {
//!        vec![String::from("a"), String::from("b")]
//!    }
//!
//!    fn cst_list() -> Vec<String> {
//!        vec![String::from("l"), String::from("k")]
//!    }
//!
//!    fn formal_map() -> HashMap<String, FormalVector<F>> {
//!    //Create a `Formal` for each element coordiate and each constants
//!        let point_a = FormalPoint {
//!            x: Formal::new_var(0),
//!            y: Formal::new_var(1),
//!            z: Formal::new_var(2)
//!        };
//!
//!        let point_b = FormalPoint {
//!            x: Formal::new_var(3),
//!            y: Formal::new_var(4),
//!            z: Formal::new_var(5)
//!        };
//!
//!        let cst_l = Formal::new_var(6);
//!        let cst_k = Formal::new_var(7);
//!
//!        // The force applied on point a is k(|ab| - l) * ab/|ab|
//!        let ab = point_b - point_a;
//!        let force_a: FormalVector<F> = (ab.clone().norm() - cst_l.clone()) * ab.clone()/ab.clone().norm() * cst_k.clone();
//!
//!        // The force applied on point b is k(|ba| - l) * ba/|ba|
//!        let force_b = (ab.clone().norm() - cst_l.clone()) * ab.clone()/ab.clone().norm() * cst_k.clone() * Formal::new_cst(F::one().neg());
//!        let mut ret = HashMap::new();
//!        ret.insert(String::from("a"), force_a);
//!        ret.insert(String::from("b"), force_b);
//!        ret
//!    }
//!
//!}
//!
//!// Once the trait is implemented, we can write a procedural macro
//!#[proc_macro]
//!pub fn auto_impl_spring(_item: TokenStream) -> TokenStream {
//!    macro_def::<f32, _Spring>()
//!}
//! ```
//!
//!
//!

extern crate proc_macro;



/// Defines the trait `AutoImplementable`
mod autoimplementable;
/// Defines a type to represent mathematical formulas whose derivatives can be computed
/// automatically
mod formal;
#[doc(hidden)]
mod spring;
#[doc(hidden)]
mod stack;

pub (crate) use autoimplementable::*;
use proc_macro::TokenStream;
use spring::_Spring;
use stack::_Stack;

/// A `Spring` likes it when `a` and `b` are at distance `l`, and
/// exerts a force of `k.(|ab| - l)` to achieve this.
#[proc_macro]
pub fn auto_impl_spring(_item: TokenStream) -> TokenStream {
    macro_def::<f32, _Spring>()
}

/// A `Stack` likes it when the angle between `ab` and `cd` is equal to `theta0`, and
/// exerts a torque of `k.(theta - theta0)` to achieve this.
#[proc_macro]
pub fn auto_impl_stack(_item: TokenStream) -> TokenStream {
    macro_def::<f32, _Stack<f32>>()
}