using System.Linq.Expressions; namespace Iceshrimp.Backend.Core.Extensions; public static class ExpressionExtensions { public static Expression> True() => f => true; public static Expression> False() => f => false; public static Expression> Or( this Expression> expr1, Expression> expr2 ) { var invokedExpr = Expression.Invoke(expr2, expr1.Parameters); return Expression.Lambda>(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters); } public static Expression> And( this Expression> expr1, Expression> expr2 ) { var invokedExpr = Expression.Invoke(expr2, expr1.Parameters); return Expression.Lambda>(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters); } public static Expression> Compose( this Expression> first, Expression> second ) { var param = Expression.Parameter(typeof(TFirstParam), "param"); var newFirst = first.Body.Replace(first.Parameters[0], param); var newSecond = second.Body.Replace(second.Parameters[0], newFirst); return Expression.Lambda>(newSecond, param); } private static Expression Replace(this Expression expression, Expression searchEx, Expression replaceEx) { return new ReplaceVisitor(searchEx, replaceEx).Visit(expression) ?? throw new NullReferenceException(); } private class ReplaceVisitor(Expression from, Expression to) : ExpressionVisitor { public override Expression? Visit(Expression? node) { return node == from ? to : base.Visit(node); } } }