# summon

A logic engine designed to magically give you what you ask for

```use summon::{Tome, circle};

#[derive(Clone)]
struct ConstantAcceleration(f64);
#[derive(Clone)]
struct InitialVelocity(f64);
#[derive(Clone)]
struct InitialPosition(f64);
#[derive(Clone)]
struct Time(f64);

#[derive(Debug)]
struct Distance(f64);

// The tome is where all the logic and conversions are written in your code.
let mut tome = Tome::new();

// You can use ether() to give types as givens.
tome.ether(ConstantAcceleration(3.0));
tome.ether(InitialVelocity(5.0));
tome.ether(InitialPosition(6.0));
tome.ether(Time(4.0));

// Inscribe is used to describe a conversion between types.
// Several macros are provided for convenience.
// This one lets you destructure and type construct freely.
tome.inscribe(
circle!(ConstantAcceleration(a), InitialVelocity(v), InitialPosition(p), Time(t) => Distance(0.5 * a * t.powi(2) + v * t + p))
);

// So long as it is possible to produce the result with the given inscriptions, it will be produced.
let summoned = tome.summon::<Distance>().unwrap().0;
assert_eq!(
0.5 * 3.0 * 4.0f64.powi(2) + 5.0 * 4.0 + 6.0,
summoned,
);```

## Macros

 circle Use this to inscribe a transmutation between a set of input types and an output type.

## Structs

 Materials Tome This is where all of the transmutation circles are inscribed.

## Traits

 Transmutation Transmutations require ingredients and produce a product. This is usually a function.