use reflect_nat::{N3, N5, S, Z};
use reify_reflect_core::{reify, Reflect, RuntimeValue};
fn part1_reflect() {
println!("=== Part 1: Type-Level → Value (Reflect) ===\n");
type Three = S<S<S<Z>>>;
type Five = N5;
println!(" Three::reflect() = {:?}", Three::reflect());
println!(" Five::reflect() = {:?}", Five::reflect());
#[derive(reflect_derive::Reflect)]
#[allow(dead_code)]
struct Config {
width: N3,
height: N5,
}
let config = Config::reflect();
println!(" Config::reflect() = {:?}", config);
println!();
}
fn part2_reify_branded() {
println!("=== Part 2: Value → Scoped Context (branded reify) ===\n");
let val = 42i32;
let result = reify(&val, |token| {
let v: &i32 = token.reflect();
println!(" Inside reify: token.reflect() = {}", v);
v * 2
});
println!(" Result from reify: {}", result);
let sum = reify(&10i32, |a| {
reify(&20i32, |b| {
let result = a.reflect() + b.reflect();
println!(
" Nested reify: {} + {} = {}",
a.reflect(),
b.reflect(),
result
);
result
})
});
println!(" Nested result: {}", sum);
let reflected = N5::reflect(); reify(&reflected, |token| {
println!(" Reified a reflected value: {:?}", token.reflect());
});
println!();
}
#[const_reify_derive::reifiable(range = 0..=255)]
trait ModularArith {
fn pow_mod<const N: u64>(&self, base: u64, exp: u64) -> u64;
fn is_qr<const N: u64>(&self, a: u64) -> bool;
}
struct ModArithImpl;
impl ModularArith for ModArithImpl {
fn pow_mod<const N: u64>(&self, base: u64, exp: u64) -> u64 {
if N == 0 {
return 0;
}
let mut result = 1u64;
let mut b = base % N;
let mut e = exp;
while e > 0 {
if e % 2 == 1 {
result = result * b % N;
}
b = b * b % N;
e /= 2;
}
result
}
fn is_qr<const N: u64>(&self, a: u64) -> bool {
if N <= 1 {
return true;
}
self.pow_mod::<N>(a, (N - 1) / 2) == 1
}
}
fn part3_reify_const_generic() {
println!("=== Part 3: Value → Const Generic (#[reifiable]) ===\n");
let impl_ = ModArithImpl;
let modulus = 7u64;
let result = reify_pow_mod(modulus, &impl_, 3, 5);
println!(" 3^5 mod 7 = {} (expected {})", result, 243u64 % 7);
let fermat = reify_pow_mod(modulus, &impl_, 3, 6);
println!(" 3^6 mod 7 = {} (Fermat's little theorem)", fermat);
println!(" Quadratic residues mod 7:");
for a in 1..7u64 {
let is_qr = reify_is_qr(modulus, &impl_, a);
println!(" {} is QR mod 7: {}", a, is_qr);
}
let modulus = 13u64;
let result = reify_pow_mod(modulus, &impl_, 2, 12);
println!(" 2^12 mod 13 = {} (Fermat)", result);
println!();
}
fn part4_full_roundtrip() {
println!("=== Part 4: Full Roundtrip ===\n");
type Base = S<S<S<Z>>>; type Exponent = N5;
let base_val = match Base::reflect() {
RuntimeValue::Nat(n) => n,
_ => unreachable!(),
};
let exp_val = match Exponent::reflect() {
RuntimeValue::Nat(n) => n,
_ => unreachable!(),
};
println!(" Type-level: Base=3, Exponent=5");
println!(" Reflected: base={}, exp={}", base_val, exp_val);
let modulus = 7u64;
println!(" Runtime modulus: {}", modulus);
let result = reify_pow_mod(modulus, &ModArithImpl, base_val, exp_val);
println!(
" Reified computation: {}^{} mod {} = {}",
base_val, exp_val, modulus, result
);
use const_reify::nat_reify::{reify_nat, NatCallback};
struct FermatTest {
base: u64,
}
impl NatCallback<bool> for FermatTest {
fn call<const P: u64>(&self) -> bool {
if P <= 1 {
return false;
}
let mut result = 1u64;
let mut b = self.base % P;
let mut e = P - 1;
while e > 0 {
if e % 2 == 1 {
result = result * b % P;
}
b = b * b % P;
e /= 2;
}
result == 1
}
}
println!("\n Fermat test with type-level base:");
for &p in &[7u64, 11, 13, 17, 23] {
let passes = reify_nat(p, &FermatTest { base: base_val });
println!(" {}^({}-1) ≡ 1 (mod {})? {}", base_val, p, p, passes);
}
let final_result = reify(&result, |token| {
let v = token.reflect();
println!("\n Branded reify of result: {}", v);
format!("{}^{} mod {} = {}", base_val, exp_val, modulus, v)
});
println!(" Final: {}", final_result);
println!();
}
fn part5_macro_ergonomics() {
println!("=== Part 5: Macro Ergonomics ===\n");
use const_reify::nat_reify::{reify_nat, reify_nat2_fn, reify_nat_fn};
let squared = reify_nat_fn(12, |n| n * n);
println!(" reify_nat_fn(12, |n| n * n) = {}", squared);
let sum = reify_nat2_fn(100, 55, |a, b| a + b);
println!(" reify_nat2_fn(100, 55, |a, b| a + b) = {}", sum);
const_reify::def_nat_callback!(Factorial -> u64 {
let mut result = 1u64;
let mut i = 1u64;
while i <= N {
result *= i;
i += 1;
}
result
});
let fact5 = reify_nat(5, &Factorial);
let fact10 = reify_nat(10, &Factorial);
println!(" 5! = {}", fact5);
println!(" 10! = {}", fact10);
println!();
}
fn main() {
part1_reflect();
part2_reify_branded();
part3_reify_const_generic();
part4_full_roundtrip();
part5_macro_ergonomics();
println!("=== Summary ===");
println!(" Reflect: type-level → runtime value");
println!(" reify (branded): runtime value → scoped token (borrow-checker enforced)");
println!(" reify_nat: runtime u64 → const generic N (true type-level dispatch)");
println!(" #[reifiable]: auto-generate dispatch for any trait with const-generic methods");
println!(" Full roundtrip: S<S<S<Z>>> → 3 → reify_nat(modulus, ...) → compute → result");
}