descent_macro

Macro expr

Source
expr!() { /* proc-macro */ }
Expand description

Generate a ExprFix expression.

expr!(<expr>; var1 [= <expr>], …[; iden1 [= <expr>], …])

The macro body consists of 3 semicolon separated parts:

  1. A representation of the expression that you want to produce.
  2. A comma separated list of Var names used in the expression body.
  3. An optional comma separated list of names for Par or f64 values.

The names used to represent variables must be simple identifiers. The identifiers must either be present in the environment as legitimate Var values that can be copied into the expression, or the special syntax name = expression can be used in the list of variable or parameter names (parts 2 and 3) to conveniently declare them in a local scope.

Anything that appears in the expression is captured (moved) from the environment (or local scope), similarly to a closure. There are in fact multiple closures being created behind the scenes, so anything that is captured needs to implement copy.

§Examples

#![feature(proc_macro_hygiene)] // need to turn on nightly feature
use descent::expr::{Var, Par};
use descent_macro::expr;
let x = Var(0);
let y = Var(1);
let p = Par(0);
let c = 1.0;
let e = expr!(p * x + y * y + c; x, y);

Syntax for scoped declaration of variables / parameters:

#![feature(proc_macro_hygiene)] // need to turn on nightly feature
use descent::expr::{Var, Par};
use descent_macro::expr;
let vars = [Var(0), Var(1)];
let pars = [Par(0)];
let constant = vec![1.0, 2.0];
let e = expr!(a * x + y * y + c; x = vars[0], y = vars[1]; a = pars[0], c = constant[0]);

This is a shorthand for the following, which is required to make sure the values can be copied into the internal closures (e.g., directly using constant[0] would attempt result in attempting to move the Vec constant multiple times):

let e = {
    let x = vars[0];
    let y = vars[1];
    let a = pars[0];
    let c = constant[0];
    expr!(a * x + y * y + c; x, y;)
}