use dslcompile::final_tagless::{ASTEval, ASTMathExpr};
use dslcompile::prelude::*;
fn complex_expression(math: &MathBuilder) -> TypedBuilderExpr<f64> {
let x: TypedBuilderExpr<f64> = math.var();
let y: TypedBuilderExpr<f64> = math.var();
let x_squared_plus_one: TypedBuilderExpr<f64> = x.clone() * &x + math.constant(1.0);
x.clone().sin() * y.exp() + x_squared_plus_one.ln()
}
fn main() -> Result<()> {
println!("=== DSLCompile Basic Usage Example ===\n");
println!("1. Basic Expression Building:");
let math = MathBuilder::new();
let quadratic = math.poly(&[2.0, 3.0, 1.0], &math.var());
let x_val = 2.0;
let result = math.eval(&quadratic, &[x_val]);
println!(" quadratic({x_val}) = {result}");
println!(" Expected: 2(4) + 3(2) + 1 = 15");
assert_eq!(result, 15.0);
println!(" ✓ Correct\n");
println!("2. Operator Overloading:");
let x = math.var();
let y = math.var();
let expr = &x * &x + 2.0 * &x + &y;
let result = math.eval(&expr, &[3.0, 1.0]);
println!(" x² + 2x + y at x=3, y=1 = {result}");
println!(" Expected: 9 + 6 + 1 = 16");
assert_eq!(result, 16.0);
println!(" ✓ Operator overloading works\n");
println!("3. Transcendental Functions:");
let x = math.var();
let expr = x.clone().exp();
let result = math.eval(&expr, &[0.0]);
println!(" exp(0) = {result}");
assert_eq!(result, 1.0);
let expr = x.clone().sin();
let result = math.eval(&expr, &[0.0]);
println!(" sin(0) = {result}");
assert_eq!(result, 0.0);
let expr = x.ln();
let result = math.eval(&expr, &[1.0]);
println!(" ln(1) = {result}");
assert_eq!(result, 0.0);
println!(" ✓ Transcendental functions work\n");
println!("4. Complex Expressions:");
let complex = complex_expression(&math);
let result = math.eval(&complex, &[1.0, 0.0]);
println!(" Complex expression at x=1, y=0: {result:.6}");
println!(" ✓ Complex expressions work\n");
println!("5. High-Level Mathematical Functions:");
let x = math.var();
let quad = math.poly(&[1.0, 2.0, 3.0], &x); let quad_result = math.eval(&quad, &[x_val]);
println!(" polynomial 3x² + 2x + 1 at x=2: {quad_result}");
println!(" Expected: 1 + 4 + 12 = 17");
assert_eq!(quad_result, 17.0);
let gaussian = math.gaussian(0.0, 1.0, &x); let gaussian_result = math.eval(&gaussian, &[0.0]);
println!(" Gaussian N(0,1) at x=0: {gaussian_result:.6}");
assert!((gaussian_result - 0.398942).abs() < 0.001);
let logistic = math.logistic(&x);
let logistic_result = math.eval(&logistic, &[0.0]);
println!(" Logistic at x=0: {logistic_result}");
assert_eq!(logistic_result, 0.5);
println!(" ✓ High-level functions work\n");
println!("6. Type Safety:");
let x_f64 = math.typed_var::<f64>();
let y_f32 = math.typed_var::<f32>();
let x_expr = math.expr_from(x_f64);
let y_expr = math.expr_from(y_f32);
let mixed = &x_expr + y_expr; let mixed_result = math.eval(&mixed, &[2.5, 1.5]);
println!(" f64 + f32 = {mixed_result}");
assert_eq!(mixed_result, 4.0);
println!(" ✓ Type promotion works\n");
println!("7. Optimization:");
let x = math.var();
let optimizable = &x + math.constant(0.0);
let original_result = math.eval(&optimizable, &[5.0]);
let ast_expr = ASTEval::add(ASTEval::var(0), ASTEval::constant(0.0));
let mut optimizer = SymbolicOptimizer::new()?;
let optimized = optimizer.optimize(&ast_expr)?;
let optimized_result = match optimized {
ASTRepr::Variable(0) => 5.0, _ => optimized.eval_with_vars(&[5.0]), };
println!(" Original expression result: {original_result}");
println!(" Optimized expression result: {optimized_result}");
assert_eq!(original_result, optimized_result);
println!(" ✓ Optimization preserves semantics\n");
println!("=== Key Features Demonstrated ===");
println!("✓ Natural mathematical syntax with operator overloading");
println!("✓ Index-based variable system (no string lookups)");
println!("✓ Type safety with automatic promotion");
println!("✓ Built-in mathematical functions");
println!("✓ Integration with symbolic optimization");
println!("✓ High performance evaluation");
println!("\n=== Example Complete ===");
Ok(())
}