Skip to content

Instantly share code, notes, and snippets.

@palladin
Created March 18, 2019 17:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save palladin/7f623217965c6c37759187cd32f9f202 to your computer and use it in GitHub Desktop.
Save palladin/7f623217965c6c37759187cd32f9f202 to your computer and use it in GitHub Desktop.
Expression splicing
public class Subs : ExpressionVisitor
{
private Dictionary<ParameterExpression, Expression> env;
public Subs(Dictionary<ParameterExpression, Expression> env)
{
this.env = env;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (env.ContainsKey(node))
return env[node];
return base.VisitParameter(node);
}
}
class Splicer : ExpressionVisitor
{
protected override Expression VisitMethodCall(MethodCallExpression node)
{
var (name, method, args) = node;
if (name == "Invoke" && method is LambdaExpression lambda)
{
var env = lambda.Parameters.Zip(args, (param, arg) => (param, arg))
.ToDictionary(t => t.param, t => t.arg);
return new Subs(env).Visit(lambda.Body);
}
return base.VisitMethodCall(node);
}
}
public static class SplicerExtensions
{
public static void Deconstruct(this MethodCallExpression m, out string name, out Expression func, out Expression[] args)
{
name = m.Method.Name;
if (name == "Invoke")
{
var thunk = Expression.Lambda<Func<object>>(m.Arguments[0], new ParameterExpression[0]);
func = thunk.Compile().DynamicInvoke() as Expression;
}
else
func = m.Arguments[0];
args = Enumerable.Range(1, m.Arguments.Count - 1).Select(i => m.Arguments[i]).ToArray();
}
public static TResult Invoke<TSource, TResult>(this Expression<Func<TSource, TResult>> f, TSource src)
{
throw new Exception("Stump call");
}
}
class Program
{
static void Main(string[] args)
{
Expression<Func<int, int>> f = x => x + 1;
Expression<Func<int, int>> g = x => f.Invoke(x + 2);
var test = new Splicer().Visit(g);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment