Skip to content

Instantly share code, notes, and snippets.

@earthengine
Created July 30, 2015 02:25
Show Gist options
  • Save earthengine/797bb9c23c4fde293b95 to your computer and use it in GitHub Desktop.
Save earthengine/797bb9c23c4fde293b95 to your computer and use it in GitHub Desktop.
Transforming c# expression tree in CPS
class CPSExpressionVisitor : ExpressionVisitor
{
delegate R SFunc<T, R>(T v);
delegate SFunc<T2, R> SFunc<T1, T2, R>(T1 v);
delegate SFunc<T2, T3, R> SFunc<T1, T2, T3, R>(T1 v);
delegate SFunc<T2, T3, T4, R> SFunc<T1, T2, T3, T4, R>(T1 v);
delegate dynamic FDynamic(FDynamic s);
private static FDynamic ConstFDynamic<T>(T v)
{
return new FDynamic(_ => v);
}
private static dynamic SelfRunDynamic(FDynamic f)
{
return f(f);
}
private static FDynamic InvokeDynamic(FDynamic f, FDynamic v)
{
return new FDynamic(u => f(InvokeDynamic(v, u)));
}
protected Expression Visit(Expression exp)
{
switch (exp.NodeType)
{
case ExpressionType.Call:
case ExpressionType.Lambda:
case ExpressionType.Parameter:
return base.Visit(exp);
default:
throw new NotImplementedException(exp.Type.ToString());
}
}
private Func<Expression, Expression> context;
private ParameterExpression standardContinuation;
override protected Expression VisitParameter(ParameterExpression exp){
if (exp.Type != typeof(FDynamic))
throw new NotImplementedException(exp.Type.ToString());
return context(exp);
}
protected override Expression VisitLambda<T>(Expression<T> node)
{
var c = context;
var x = Expression.Parameter(node.Parameters[0].Type, "x");
standardContinuation = Expression.Parameter(typeof(FDynamic), "k");
context = x1 => Expression.Call(this.GetType(), "InvokeDynamic", new Type[0], standardContinuation, x);
return c(Expression.Lambda(Expression.Lambda(Visit(node.Body), standardContinuation), x));
}
protected override Expression VisitMethodCall(MethodCallExpression exp)
{
var c = context;
var k = standardContinuation;
context = m =>
{
context = n =>
{
var v = Expression.Call(this.GetType(), "InvokeDynamic", new Type[0], m, n);
if (k != null)
return Expression.Call(this.GetType(), "InvokeDynamic", new Type[0], v, k);
else
{
var v1 = Expression.Parameter(typeof(FDynamic), "v");
return Expression.Call(this.GetType(), "InvokeDynamic", new Type[0], v, Expression.Lambda(c(v1), v1));
}
};
standardContinuation = null;
return Visit(exp.Arguments[1]);
};
standardContinuation = null;
return Visit(exp.Arguments[0]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment